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