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