1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
4  * Author: Lin Huang <hl@rock-chips.com>
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/devfreq-event.h>
9 #include <linux/kernel.h>
10 #include <linux/err.h>
11 #include <linux/init.h>
12 #include <linux/io.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/regmap.h>
17 #include <linux/slab.h>
18 #include <linux/list.h>
19 #include <linux/of.h>
20 
21 #include <soc/rockchip/rk3399_grf.h>
22 
23 #define PX30_PMUGRF_OS_REG2 0x208
24 #define PX30_PMUGRF_OS_REG3 0x20c
25 
26 #define RK3128_GRF_SOC_CON0 0x140
27 #define RK3128_GRF_OS_REG1 0x1cc
28 #define RK3128_GRF_DFI_WRNUM 0x220
29 #define RK3128_GRF_DFI_RDNUM 0x224
30 #define RK3128_GRF_DFI_TIMERVAL 0x22c
31 #define RK3128_DDR_MONITOR_EN ((1 << (16 + 6)) + (1 << 6))
32 #define RK3128_DDR_MONITOR_DISB ((1 << (16 + 6)) + (0 << 6))
33 
34 #define RK3288_PMU_SYS_REG2 0x9c
35 #define RK3288_GRF_SOC_CON4 0x254
36 #define RK3288_GRF_SOC_STATUS(n) (0x280 + (n)*4)
37 #define RK3288_DFI_EN (0x30003 << 14)
38 #define RK3288_DFI_DIS (0x30000 << 14)
39 #define RK3288_LPDDR_SEL (0x10001 << 13)
40 #define RK3288_DDR3_SEL (0x10000 << 13)
41 
42 #define RK3328_GRF_OS_REG2 0x5d0
43 
44 #define RK3368_GRF_DDRC0_CON0 0x600
45 #define RK3368_GRF_SOC_STATUS5 0x494
46 #define RK3368_GRF_SOC_STATUS6 0x498
47 #define RK3368_GRF_SOC_STATUS8 0x4a0
48 #define RK3368_GRF_SOC_STATUS9 0x4a4
49 #define RK3368_GRF_SOC_STATUS10 0x4a8
50 #define RK3368_DFI_EN (0x30003 << 5)
51 #define RK3368_DFI_DIS (0x30000 << 5)
52 
53 #define MAX_DMC_NUM_CH 2
54 #define READ_DRAMTYPE_INFO(n) (((n) >> 13) & 0x7)
55 #define READ_CH_INFO(n) (((n) >> 28) & 0x3)
56 #define READ_DRAMTYPE_INFO_V3(n, m) ((((n) >> 13) & 0x7) | ((((m) >> 12) & 0x3) << 3))
57 #define READ_SYSREG_VERSION(m) (((m) >> 28) & 0xf)
58 /* DDRMON_CTRL */
59 #define DDRMON_CTRL 0x04
60 #define CLR_DDRMON_CTRL (0x3f0000 << 0)
61 #define DDR4_EN (0x10001 << 5)
62 #define LPDDR4_EN (0x10001 << 4)
63 #define HARDWARE_EN (0x10001 << 3)
64 #define LPDDR2_3_EN (0x10001 << 2)
65 #define SOFTWARE_EN (0x10001 << 1)
66 #define SOFTWARE_DIS (0x10000 << 1)
67 #define TIME_CNT_EN (0x10001 << 0)
68 
69 #define DDRMON_CH0_COUNT_NUM 0x28
70 #define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
71 #define DDRMON_CH1_COUNT_NUM 0x3c
72 #define DDRMON_CH1_DFI_ACCESS_NUM 0x40
73 
74 /* pmu grf */
75 #define PMUGRF_OS_REG2 0x308
76 
77 enum { DDR4 = 0, DDR3 = 3, LPDDR2 = 5, LPDDR3 = 6, LPDDR4 = 7, LPDDR4X = 8, UNUSED = 0xFF };
78 
79 struct dmc_usage {
80     u32 access;
81     u32 total;
82 };
83 
84 /*
85  * The dfi controller can monitor DDR load. It has an upper and lower threshold
86  * for the operating points. Whenever the usage leaves these bounds an event is
87  * generated to indicate the DDR frequency should be changed.
88  */
89 struct rockchip_dfi {
90     struct devfreq_event_dev *edev;
91     struct devfreq_event_desc *desc;
92     struct dmc_usage ch_usage[MAX_DMC_NUM_CH];
93     struct device *dev;
94     void __iomem *regs;
95     struct regmap *regmap_pmu;
96     struct regmap *regmap_grf;
97     struct regmap *regmap_pmugrf;
98     struct clk *clk;
99     u32 dram_type;
100     /*
101      * available mask, 1: available, 0: not available
102      * each bit represent a channel
103      */
104     u32 ch_msk;
105 };
106 
rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev)107 static void rk3128_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
108 {
109     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
110 
111     regmap_write(info->regmap_grf, RK3128_GRF_SOC_CON0, RK3128_DDR_MONITOR_EN);
112 }
113 
rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)114 static void rk3128_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
115 {
116     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
117 
118     regmap_write(info->regmap_grf, RK3128_GRF_SOC_CON0, RK3128_DDR_MONITOR_DISB);
119 }
120 
rk3128_dfi_disable(struct devfreq_event_dev *edev)121 static int rk3128_dfi_disable(struct devfreq_event_dev *edev)
122 {
123     rk3128_dfi_stop_hardware_counter(edev);
124 
125     return 0;
126 }
127 
rk3128_dfi_enable(struct devfreq_event_dev *edev)128 static int rk3128_dfi_enable(struct devfreq_event_dev *edev)
129 {
130     rk3128_dfi_start_hardware_counter(edev);
131 
132     return 0;
133 }
134 
rk3128_dfi_set_event(struct devfreq_event_dev *edev)135 static int rk3128_dfi_set_event(struct devfreq_event_dev *edev)
136 {
137     return 0;
138 }
139 
rk3128_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)140 static int rk3128_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)
141 {
142     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
143     unsigned long flags;
144     u32 dfi_wr, dfi_rd, dfi_timer;
145 
146     local_irq_save(flags);
147 
148     rk3128_dfi_stop_hardware_counter(edev);
149 
150     regmap_read(info->regmap_grf, RK3128_GRF_DFI_WRNUM, &dfi_wr);
151     regmap_read(info->regmap_grf, RK3128_GRF_DFI_RDNUM, &dfi_rd);
152     regmap_read(info->regmap_grf, RK3128_GRF_DFI_TIMERVAL, &dfi_timer);
153 
154     edata->load_count = (dfi_wr + dfi_rd) * 0x4;
155     edata->total_count = dfi_timer;
156 
157     rk3128_dfi_start_hardware_counter(edev);
158 
159     local_irq_restore(flags);
160 
161     return 0;
162 }
163 
164 static const struct devfreq_event_ops rk3128_dfi_ops = {
165     .disable = rk3128_dfi_disable,
166     .enable = rk3128_dfi_enable,
167     .get_event = rk3128_dfi_get_event,
168     .set_event = rk3128_dfi_set_event,
169 };
170 
rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev)171 static void rk3288_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
172 {
173     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
174 
175     regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_EN);
176 }
177 
rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)178 static void rk3288_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
179 {
180     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
181 
182     regmap_write(info->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DFI_DIS);
183 }
184 
rk3288_dfi_disable(struct devfreq_event_dev *edev)185 static int rk3288_dfi_disable(struct devfreq_event_dev *edev)
186 {
187     rk3288_dfi_stop_hardware_counter(edev);
188 
189     return 0;
190 }
191 
rk3288_dfi_enable(struct devfreq_event_dev *edev)192 static int rk3288_dfi_enable(struct devfreq_event_dev *edev)
193 {
194     rk3288_dfi_start_hardware_counter(edev);
195 
196     return 0;
197 }
198 
rk3288_dfi_set_event(struct devfreq_event_dev *edev)199 static int rk3288_dfi_set_event(struct devfreq_event_dev *edev)
200 {
201     return 0;
202 }
203 
rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev)204 static int rk3288_dfi_get_busier_ch(struct devfreq_event_dev *edev)
205 {
206     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
207     u32 tmp, max = 0;
208     u32 i, busier_ch = 0;
209     u32 rd_count, wr_count, total_count;
210 
211     rk3288_dfi_stop_hardware_counter(edev);
212 
213     /* Find out which channel is busier */
214     for (i = 0; i < MAX_DMC_NUM_CH; i++) {
215         if (!(info->ch_msk & BIT(i))) {
216             continue;
217         }
218         regmap_read(info->regmap_grf, RK3288_GRF_SOC_STATUS(0xb + i * 0x4), &wr_count);
219         regmap_read(info->regmap_grf, RK3288_GRF_SOC_STATUS(0xc + i * 0x4), &rd_count);
220         regmap_read(info->regmap_grf, RK3288_GRF_SOC_STATUS(0xe + i * 0x4), &total_count);
221         info->ch_usage[i].access = (wr_count + rd_count) * 0x4;
222         info->ch_usage[i].total = total_count;
223         tmp = info->ch_usage[i].access;
224         if (tmp > max) {
225             busier_ch = i;
226             max = tmp;
227         }
228     }
229     rk3288_dfi_start_hardware_counter(edev);
230 
231     return busier_ch;
232 }
233 
rk3288_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)234 static int rk3288_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)
235 {
236     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
237     int busier_ch;
238     unsigned long flags;
239 
240     local_irq_save(flags);
241     busier_ch = rk3288_dfi_get_busier_ch(edev);
242     local_irq_restore(flags);
243 
244     edata->load_count = info->ch_usage[busier_ch].access;
245     edata->total_count = info->ch_usage[busier_ch].total;
246 
247     return 0;
248 }
249 
250 static const struct devfreq_event_ops rk3288_dfi_ops = {
251     .disable = rk3288_dfi_disable,
252     .enable = rk3288_dfi_enable,
253     .get_event = rk3288_dfi_get_event,
254     .set_event = rk3288_dfi_set_event,
255 };
256 
rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev)257 static void rk3368_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
258 {
259     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
260 
261     regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_EN);
262 }
263 
rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)264 static void rk3368_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
265 {
266     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
267 
268     regmap_write(info->regmap_grf, RK3368_GRF_DDRC0_CON0, RK3368_DFI_DIS);
269 }
270 
rk3368_dfi_disable(struct devfreq_event_dev *edev)271 static int rk3368_dfi_disable(struct devfreq_event_dev *edev)
272 {
273     rk3368_dfi_stop_hardware_counter(edev);
274 
275     return 0;
276 }
277 
rk3368_dfi_enable(struct devfreq_event_dev *edev)278 static int rk3368_dfi_enable(struct devfreq_event_dev *edev)
279 {
280     rk3368_dfi_start_hardware_counter(edev);
281 
282     return 0;
283 }
284 
rk3368_dfi_set_event(struct devfreq_event_dev *edev)285 static int rk3368_dfi_set_event(struct devfreq_event_dev *edev)
286 {
287     return 0;
288 }
289 
rk3368_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)290 static int rk3368_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)
291 {
292     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
293     unsigned long flags;
294     u32 dfi0_wr, dfi0_rd, dfi1_wr, dfi1_rd, dfi_timer;
295 
296     local_irq_save(flags);
297 
298     rk3368_dfi_stop_hardware_counter(edev);
299 
300     regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS5, &dfi0_wr);
301     regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS6, &dfi0_rd);
302     regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS9, &dfi1_wr);
303     regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS10, &dfi1_rd);
304     regmap_read(info->regmap_grf, RK3368_GRF_SOC_STATUS8, &dfi_timer);
305 
306     edata->load_count = (dfi0_wr + dfi0_rd + dfi1_wr + dfi1_rd) * 0x2;
307     edata->total_count = dfi_timer;
308 
309     rk3368_dfi_start_hardware_counter(edev);
310 
311     local_irq_restore(flags);
312 
313     return 0;
314 }
315 
316 static const struct devfreq_event_ops rk3368_dfi_ops = {
317     .disable = rk3368_dfi_disable,
318     .enable = rk3368_dfi_enable,
319     .get_event = rk3368_dfi_get_event,
320     .set_event = rk3368_dfi_set_event,
321 };
322 
rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)323 static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
324 {
325     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
326     void __iomem *dfi_regs = info->regs;
327 
328     /* clear DDRMON_CTRL setting */
329     writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
330 
331     /* set ddr type to dfi */
332     if (info->dram_type == LPDDR3 || info->dram_type == LPDDR2) {
333         writel_relaxed(LPDDR2_3_EN, dfi_regs + DDRMON_CTRL);
334     } else if (info->dram_type == LPDDR4 || info->dram_type == LPDDR4X) {
335         writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
336     } else if (info->dram_type == DDR4) {
337         writel_relaxed(DDR4_EN, dfi_regs + DDRMON_CTRL);
338     }
339 
340     /* enable count, use software mode */
341     writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
342 }
343 
rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)344 static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
345 {
346     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
347     void __iomem *dfi_regs = info->regs;
348 
349     writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL);
350 }
351 
rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)352 static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
353 {
354     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
355     u32 tmp, max = 0;
356     u32 i, busier_ch = 0;
357     void __iomem *dfi_regs = info->regs;
358 
359     rockchip_dfi_stop_hardware_counter(edev);
360 
361     /* Find out which channel is busier */
362     for (i = 0; i < MAX_DMC_NUM_CH; i++) {
363         if (!(info->ch_msk & BIT(i))) {
364             continue;
365         }
366 
367         info->ch_usage[i].total = readl_relaxed(dfi_regs + DDRMON_CH0_COUNT_NUM + i * 0x14);
368 
369         /* LPDDR4 and LPDDR4X BL = 16,other DDR type BL = 8 */
370         tmp = readl_relaxed(dfi_regs + DDRMON_CH0_DFI_ACCESS_NUM + i * 0x14);
371         if (info->dram_type == LPDDR4 || info->dram_type == LPDDR4X) {
372             tmp *= 0x8;
373         } else {
374             tmp *= 0x4;
375         }
376         info->ch_usage[i].access = tmp;
377 
378         if (tmp > max) {
379             busier_ch = i;
380             max = tmp;
381         }
382     }
383     rockchip_dfi_start_hardware_counter(edev);
384 
385     return busier_ch;
386 }
387 
rockchip_dfi_disable(struct devfreq_event_dev *edev)388 static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
389 {
390     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
391 
392     rockchip_dfi_stop_hardware_counter(edev);
393     if (info->clk) {
394         clk_disable_unprepare(info->clk);
395     }
396 
397     return 0;
398 }
399 
rockchip_dfi_enable(struct devfreq_event_dev *edev)400 static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
401 {
402     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
403     int ret;
404 
405     if (info->clk) {
406         ret = clk_prepare_enable(info->clk);
407         if (ret) {
408             dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
409             return ret;
410         }
411     }
412 
413     rockchip_dfi_start_hardware_counter(edev);
414     return 0;
415 }
416 
rockchip_dfi_set_event(struct devfreq_event_dev *edev)417 static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
418 {
419     return 0;
420 }
421 
rockchip_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)422 static int rockchip_dfi_get_event(struct devfreq_event_dev *edev, struct devfreq_event_data *edata)
423 {
424     struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
425     int busier_ch;
426     unsigned long flags;
427 
428     local_irq_save(flags);
429     busier_ch = rockchip_dfi_get_busier_ch(edev);
430     local_irq_restore(flags);
431 
432     edata->load_count = info->ch_usage[busier_ch].access;
433     edata->total_count = info->ch_usage[busier_ch].total;
434 
435     return 0;
436 }
437 
438 static const struct devfreq_event_ops rockchip_dfi_ops = {
439     .disable = rockchip_dfi_disable,
440     .enable = rockchip_dfi_enable,
441     .get_event = rockchip_dfi_get_event,
442     .set_event = rockchip_dfi_set_event,
443 };
444 
px30_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)445 static __init int px30_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
446                                 struct devfreq_event_desc *desc)
447 {
448     struct device_node *np = pdev->dev.of_node, *node;
449     struct resource *res;
450     u32 val_2, val_3;
451 
452     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
453     data->regs = devm_ioremap_resource(&pdev->dev, res);
454     if (IS_ERR(data->regs)) {
455         return PTR_ERR(data->regs);
456     }
457 
458     node = of_parse_phandle(np, "rockchip,pmugrf", 0);
459     if (node) {
460         data->regmap_pmugrf = syscon_node_to_regmap(node);
461         if (IS_ERR(data->regmap_pmugrf)) {
462             return PTR_ERR(data->regmap_pmugrf);
463         }
464     }
465 
466     regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG2, &val_2);
467     regmap_read(data->regmap_pmugrf, PX30_PMUGRF_OS_REG3, &val_3);
468     if (READ_SYSREG_VERSION(val_3) >= 0x3) {
469         data->dram_type = READ_DRAMTYPE_INFO_V3(val_2, val_3);
470     } else {
471         data->dram_type = READ_DRAMTYPE_INFO(val_2);
472     }
473     data->ch_msk = 1;
474     data->clk = NULL;
475 
476     desc->ops = &rockchip_dfi_ops;
477 
478     return 0;
479 }
480 
rk3128_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)481 static __init int rk3128_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
482                                   struct devfreq_event_desc *desc)
483 {
484     struct device_node *np = pdev->dev.of_node, *node;
485 
486     node = of_parse_phandle(np, "rockchip,grf", 0);
487     if (node) {
488         data->regmap_grf = syscon_node_to_regmap(node);
489         if (IS_ERR(data->regmap_grf)) {
490             return PTR_ERR(data->regmap_grf);
491         }
492     }
493 
494     desc->ops = &rk3128_dfi_ops;
495 
496     return 0;
497 }
498 
rk3288_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)499 static __init int rk3288_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
500                                   struct devfreq_event_desc *desc)
501 {
502     struct device_node *np = pdev->dev.of_node, *node;
503     u32 val;
504 
505     node = of_parse_phandle(np, "rockchip,pmu", 0);
506     if (node) {
507         data->regmap_pmu = syscon_node_to_regmap(node);
508         if (IS_ERR(data->regmap_pmu)) {
509             return PTR_ERR(data->regmap_pmu);
510         }
511     }
512 
513     node = of_parse_phandle(np, "rockchip,grf", 0);
514     if (node) {
515         data->regmap_grf = syscon_node_to_regmap(node);
516         if (IS_ERR(data->regmap_grf)) {
517             return PTR_ERR(data->regmap_grf);
518         }
519     }
520 
521     regmap_read(data->regmap_pmu, RK3288_PMU_SYS_REG2, &val);
522     data->dram_type = READ_DRAMTYPE_INFO(val);
523     data->ch_msk = READ_CH_INFO(val);
524 
525     if (data->dram_type == DDR3) {
526         regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_DDR3_SEL);
527     } else {
528         regmap_write(data->regmap_grf, RK3288_GRF_SOC_CON4, RK3288_LPDDR_SEL);
529     }
530 
531     desc->ops = &rk3288_dfi_ops;
532 
533     return 0;
534 }
535 
rk3368_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)536 static __init int rk3368_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
537                                   struct devfreq_event_desc *desc)
538 {
539     struct device *dev = &pdev->dev;
540 
541     if (!dev->parent || !dev->parent->of_node) {
542         return -EINVAL;
543     }
544 
545     data->regmap_grf = syscon_node_to_regmap(dev->parent->of_node);
546     if (IS_ERR(data->regmap_grf)) {
547         return PTR_ERR(data->regmap_grf);
548     }
549 
550     desc->ops = &rk3368_dfi_ops;
551 
552     return 0;
553 }
554 
rockchip_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)555 static __init int rockchip_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
556                                     struct devfreq_event_desc *desc)
557 {
558     struct device *dev = &pdev->dev;
559     struct device_node *np = pdev->dev.of_node, *node;
560     u32 val;
561 
562     data->regs = devm_platform_ioremap_resource(pdev, 0);
563     if (IS_ERR(data->regs)) {
564         return PTR_ERR(data->regs);
565     }
566 
567     data->clk = devm_clk_get(dev, "pclk_ddr_mon");
568     if (IS_ERR(data->clk)) {
569         dev_err(dev, "Cannot get the clk dmc_clk\n");
570         return PTR_ERR(data->clk);
571     }
572 
573     /* try to find the optional reference to the pmu syscon */
574     node = of_parse_phandle(np, "rockchip,pmu", 0);
575     if (node) {
576         data->regmap_pmu = syscon_node_to_regmap(node);
577         of_node_put(node);
578         if (IS_ERR(data->regmap_pmu)) {
579             return PTR_ERR(data->regmap_pmu);
580         }
581     }
582 
583     regmap_read(data->regmap_pmu, PMUGRF_OS_REG2, &val);
584     data->dram_type = READ_DRAMTYPE_INFO(val);
585     data->ch_msk = READ_CH_INFO(val);
586 
587     desc->ops = &rockchip_dfi_ops;
588 
589     return 0;
590 }
591 
rk3328_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data, struct devfreq_event_desc *desc)592 static __init int rk3328_dfi_init(struct platform_device *pdev, struct rockchip_dfi *data,
593                                   struct devfreq_event_desc *desc)
594 {
595     struct device_node *np = pdev->dev.of_node, *node;
596     struct resource *res;
597     u32 val;
598 
599     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
600     data->regs = devm_ioremap_resource(&pdev->dev, res);
601     if (IS_ERR(data->regs)) {
602         return PTR_ERR(data->regs);
603     }
604 
605     node = of_parse_phandle(np, "rockchip,grf", 0);
606     if (node) {
607         data->regmap_grf = syscon_node_to_regmap(node);
608         if (IS_ERR(data->regmap_grf)) {
609             return PTR_ERR(data->regmap_grf);
610         }
611     }
612 
613     regmap_read(data->regmap_grf, RK3328_GRF_OS_REG2, &val);
614     data->dram_type = READ_DRAMTYPE_INFO(val);
615     data->ch_msk = 1;
616     data->clk = NULL;
617 
618     desc->ops = &rockchip_dfi_ops;
619 
620     return 0;
621 }
622 
623 static const struct of_device_id rockchip_dfi_id_match[] = {
624     {.compatible = "rockchip,px30-dfi", .data = px30_dfi_init},
625     {.compatible = "rockchip,rk1808-dfi", .data = px30_dfi_init},
626     {.compatible = "rockchip,rk3128-dfi", .data = rk3128_dfi_init},
627     {.compatible = "rockchip,rk3288-dfi", .data = rk3288_dfi_init},
628     {.compatible = "rockchip,rk3328-dfi", .data = rk3328_dfi_init},
629     {.compatible = "rockchip,rk3368-dfi", .data = rk3368_dfi_init},
630     {.compatible = "rockchip,rk3399-dfi", .data = rockchip_dfi_init},
631     {.compatible = "rockchip,rk3568-dfi", .data = px30_dfi_init},
632     {.compatible = "rockchip,rv1126-dfi", .data = px30_dfi_init},
633     {},
634 };
635 
rockchip_dfi_probe(struct platform_device *pdev)636 static int rockchip_dfi_probe(struct platform_device *pdev)
637 {
638     struct device *dev = &pdev->dev;
639     struct rockchip_dfi *data;
640     struct devfreq_event_desc *desc;
641     struct device_node *np = pdev->dev.of_node;
642     const struct of_device_id *match;
643     int (*init)(struct platform_device * pdev, struct rockchip_dfi * data, struct devfreq_event_desc * desc);
644 
645     data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
646     if (!data) {
647         return -ENOMEM;
648     }
649 
650     desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
651     if (!desc) {
652         return -ENOMEM;
653     }
654 
655     match = of_match_node(rockchip_dfi_id_match, pdev->dev.of_node);
656     if (match) {
657         init = match->data;
658         if (init) {
659             if (init(pdev, data, desc)) {
660                 return -EINVAL;
661             }
662         } else {
663             return 0;
664         }
665     } else {
666         return 0;
667     }
668 
669     desc->driver_data = data;
670     desc->name = np->name;
671 
672     data->edev = devm_devfreq_event_add_edev(dev, desc);
673     if (IS_ERR(data->edev)) {
674         dev_err(dev, "failed to add devfreq-event device\n");
675         return PTR_ERR(data->edev);
676     }
677     data->desc = desc;
678     data->dev = &pdev->dev;
679 
680     platform_set_drvdata(pdev, data);
681 
682     return 0;
683 }
684 
685 static struct platform_driver rockchip_dfi_driver = {
686     .probe = rockchip_dfi_probe,
687     .driver =
688         {
689             .name = "rockchip-dfi",
690             .of_match_table = rockchip_dfi_id_match,
691         },
692 };
693 module_platform_driver(rockchip_dfi_driver);
694 
695 MODULE_LICENSE("GPL v2");
696 MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
697 MODULE_DESCRIPTION("Rockchip DFI driver");
698