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
77enum { DDR4 = 0, DDR3 = 3, LPDDR2 = 5, LPDDR3 = 6, LPDDR4 = 7, LPDDR4X = 8, UNUSED = 0xFF };
78
79struct 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 */
89struct 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
107static 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
114static 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
121static int rk3128_dfi_disable(struct devfreq_event_dev *edev)
122{
123    rk3128_dfi_stop_hardware_counter(edev);
124
125    return 0;
126}
127
128static int rk3128_dfi_enable(struct devfreq_event_dev *edev)
129{
130    rk3128_dfi_start_hardware_counter(edev);
131
132    return 0;
133}
134
135static int rk3128_dfi_set_event(struct devfreq_event_dev *edev)
136{
137    return 0;
138}
139
140static 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
164static 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
171static 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
178static 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
185static int rk3288_dfi_disable(struct devfreq_event_dev *edev)
186{
187    rk3288_dfi_stop_hardware_counter(edev);
188
189    return 0;
190}
191
192static int rk3288_dfi_enable(struct devfreq_event_dev *edev)
193{
194    rk3288_dfi_start_hardware_counter(edev);
195
196    return 0;
197}
198
199static int rk3288_dfi_set_event(struct devfreq_event_dev *edev)
200{
201    return 0;
202}
203
204static 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
234static 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
250static 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
257static 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
264static 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
271static int rk3368_dfi_disable(struct devfreq_event_dev *edev)
272{
273    rk3368_dfi_stop_hardware_counter(edev);
274
275    return 0;
276}
277
278static int rk3368_dfi_enable(struct devfreq_event_dev *edev)
279{
280    rk3368_dfi_start_hardware_counter(edev);
281
282    return 0;
283}
284
285static int rk3368_dfi_set_event(struct devfreq_event_dev *edev)
286{
287    return 0;
288}
289
290static 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
316static 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
323static 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
344static 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
352static 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
388static 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
400static 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
417static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
418{
419    return 0;
420}
421
422static 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
438static 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
445static __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
481static __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
499static __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
536static __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
555static __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
592static __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
623static 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
636static 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
685static 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};
693module_platform_driver(rockchip_dfi_driver);
694
695MODULE_LICENSE("GPL v2");
696MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
697MODULE_DESCRIPTION("Rockchip DFI driver");
698