From: Tang Yun ping Date: Wed, 12 Apr 2017 08:24:16 +0000 (+0800) Subject: PM / devfreq: event: add support for rk3288 dfi X-Git-Tag: release-20171130_firefly~4^2~624 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=9eecb1751226c586152f2b977aa7f0fa84ca89c6;p=firefly-linux-kernel-4.4.55.git PM / devfreq: event: add support for rk3288 dfi This adds the necessary data for handling dfi on the rk3288. Access the dfi via registers provided by GRF (general register files) module. Change-Id: Ic7241af3c20a269ab362055dea04d260e01c50de Signed-off-by: Tang Yun ping --- diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt index 71be08a0f61b..b9df91686553 100644 --- a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt +++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt @@ -3,6 +3,7 @@ Required properties: - compatible: Should be one of the following. + - "rockchip,rk3288-dfi" - for RK3288 SoCs. - "rockchip,rk3368-dfi" - for RK3368 SoCs. - "rockchip,rk3399-dfi" - for RK3399 SoCs. diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c index 65074f1af257..e692c6fd522d 100644 --- a/drivers/devfreq/event/rockchip-dfi.c +++ b/drivers/devfreq/event/rockchip-dfi.c @@ -26,6 +26,15 @@ #include #include +#define RK3288_PMU_SYS_REG2 0x9c +#define RK3288_GRF_SOC_CON4 0x254 +#define RK3288_GRF_SOC_STATUS(n) (0x280 + (n) * 4) +#define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7) +#define RK3288_DFI_EN (0x30003 << 14) +#define RK3288_DFI_DIS (0x30000 << 14) +#define RK3288_LPDDR_SEL (0x10001 << 13) +#define RK3288_DDR3_SEL (0x10000 << 13) + #define RK3368_GRF_DDRC0_CON0 0x600 #define RK3368_GRF_SOC_STATUS5 0x494 #define RK3368_GRF_SOC_STATUS6 0x498 @@ -35,17 +44,17 @@ #define RK3368_DFI_EN (0x30003 << 5) #define RK3368_DFI_DIS (0x30000 << 5) -#define RK3399_DMC_NUM_CH 2 +#define RK3399_DMC_NUM_CH 2 /* DDRMON_CTRL */ -#define DDRMON_CTRL 0x04 -#define CLR_DDRMON_CTRL (0x1f0000 << 0) -#define LPDDR4_EN (0x10001 << 4) -#define HARDWARE_EN (0x10001 << 3) -#define LPDDR3_EN (0x10001 << 2) -#define SOFTWARE_EN (0x10001 << 1) -#define SOFTWARE_DIS (0x10000 << 1) -#define TIME_CNT_EN (0x10001 << 0) +#define DDRMON_CTRL 0x04 +#define CLR_DDRMON_CTRL (0x1f0000 << 0) +#define LPDDR4_EN (0x10001 << 4) +#define HARDWARE_EN (0x10001 << 3) +#define LPDDR3_EN (0x10001 << 2) +#define SOFTWARE_EN (0x10001 << 1) +#define SOFTWARE_DIS (0x10000 << 1) +#define TIME_CNT_EN (0x10001 << 0) #define DDRMON_CH0_COUNT_NUM 0x28 #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c @@ -53,9 +62,9 @@ #define DDRMON_CH1_DFI_ACCESS_NUM 0x40 /* pmu grf */ -#define PMUGRF_OS_REG2 0x308 -#define DDRTYPE_SHIFT 13 -#define DDRTYPE_MASK 7 +#define PMUGRF_OS_REG2 0x308 +#define DDRTYPE_SHIFT 13 +#define DDRTYPE_MASK 7 enum { DDR3 = 3, @@ -85,6 +94,93 @@ struct rockchip_dfi { struct clk *clk; }; +static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev) +{ + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN); +} + +static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev) +{ + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + + regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS); +} + +static int rk3288_dfi_disable(struct devfreq_event_dev *edev) +{ + rk3288_dfi_stop_hardware_counter(edev); + + return 0; +} + +static int rk3288_dfi_enable(struct devfreq_event_dev *edev) +{ + rk3288_dfi_start_hardware_counter(edev); + + return 0; +} + +static int rk3288_dfi_set_event(struct devfreq_event_dev *edev) +{ + return 0; +} + +static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev) +{ + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + u32 tmp, max = 0; + u32 i, busier_ch = 0; + u32 rd_count, wr_count, total_count; + + rk3288_dfi_stop_hardware_counter(edev); + + /* Find out which channel is busier */ + for (i = 0; i < RK3399_DMC_NUM_CH; i++) { + regmap_read(info->regmap_grf, + RK3288_GRF_SOC_STATUS(11 + i * 4), &wr_count); + regmap_read(info->regmap_grf, + RK3288_GRF_SOC_STATUS(12 + i * 4), &rd_count); + regmap_read(info->regmap_grf, + RK3288_GRF_SOC_STATUS(14 + i * 4), &total_count); + info->ch_usage[i].access = (wr_count + rd_count) * 4; + info->ch_usage[i].total = total_count; + tmp = info->ch_usage[i].access; + if (tmp > max) { + busier_ch = i; + max = tmp; + } + } + rk3288_dfi_start_hardware_counter(edev); + + return busier_ch; +} + +static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, + struct devfreq_event_data *edata) +{ + struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); + int busier_ch; + unsigned long flags; + + local_irq_save(flags); + busier_ch = rk3288_dfi_get_busier_ch(edev); + local_irq_restore(flags); + + edata->load_count = info->ch_usage[busier_ch].access; + edata->total_count = info->ch_usage[busier_ch].total; + + return 0; +} + +static const struct devfreq_event_ops rk3288_dfi_ops = { + .disable = rk3288_dfi_disable, + .enable = rk3288_dfi_enable, + .get_event = rk3288_dfi_get_event, + .set_event = rk3288_dfi_set_event, +}; + static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev) { struct rockchip_dfi *info = devfreq_event_get_drvdata(edev); @@ -264,6 +360,42 @@ static const struct devfreq_event_ops rockchip_dfi_ops = { .set_event = rockchip_dfi_set_event, }; +static __init int rk3288_dfi_init(struct platform_device *pdev, + struct rockchip_dfi *data, + struct devfreq_event_desc *desc) +{ + struct device_node *np = pdev->dev.of_node, *node; + u32 dram_type; + + node = of_parse_phandle(np, "rockchip,pmu", 0); + if (node) { + data->regmap_pmu = syscon_node_to_regmap(node); + if (IS_ERR(data->regmap_pmu)) + return PTR_ERR(data->regmap_pmu); + } + + node = of_parse_phandle(np, "rockchip,grf", 0); + if (node) { + data->regmap_grf = syscon_node_to_regmap(node); + if (IS_ERR(data->regmap_grf)) + return PTR_ERR(data->regmap_grf); + } + + regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &dram_type); + dram_type = READ_DRAMTYPE_INFO(dram_type); + + if (dram_type == DDR3) + regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, + RK3288_DDR3_SEL); + else + regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, + RK3288_LPDDR_SEL); + + desc->ops = &rk3288_dfi_ops; + + return 0; +} + static __init int rk3368_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc) @@ -315,6 +447,7 @@ static __init int rockchip_dfi_init(struct platform_device *pdev, } static const struct of_device_id rockchip_dfi_id_match[] = { + { .compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init }, { .compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init }, { .compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init }, { },