aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-12 20:57:31 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2016-09-12 20:57:31 -0400
commite41f323ab0e2fec843ab03219f1454dd9147dfcd (patch)
treea015c649e29bb8ce1038182dcc58a74c8bf3ca30
parent9395452b4aab7bc2475ef8935b4a4fb99d778d70 (diff)
parent5a893e31a636cca3798af2db5aee8d3d144b1e1e (diff)
Merge tag 'pull_whole_for_4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq into pm-devfreq
Pull devfreq material for v4.9 from MyungJoo Ham. * tag 'pull_whole_for_4.9' of https://git.kernel.org/pub/scm/linux/kernel/git/mzx/devfreq: PM / devfreq: rockchip: add devfreq driver for rk3399 dmc Documentation: bindings: add dt documentation for rk3399 dmc PM / devfreq: event: support rockchip dfi controller Documentation: bindings: add dt documentation for dfi controller PM / devfreq: event: remove duplicate devfreq_event_get_drvdata() PM / devfreq: fix Kconfig indent style PM / devfreq: Add COMPILE_TEST for build coverage PM / devfreq: exynos-ppmu: remove unneeded of_node_put()
-rw-r--r--Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt19
-rw-r--r--Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt209
-rw-r--r--drivers/devfreq/Kconfig29
-rw-r--r--drivers/devfreq/Makefile1
-rw-r--r--drivers/devfreq/event/Kconfig11
-rw-r--r--drivers/devfreq/event/Makefile1
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c2
-rw-r--r--drivers/devfreq/event/rockchip-dfi.c256
-rw-r--r--drivers/devfreq/rk3399_dmc.c480
-rw-r--r--include/linux/devfreq-event.h5
10 files changed, 995 insertions, 18 deletions
diff --git a/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
new file mode 100644
index 000000000000..f2233138eba9
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/event/rockchip-dfi.txt
@@ -0,0 +1,19 @@
1
2* Rockchip rk3399 DFI device
3
4Required properties:
5- compatible: Must be "rockchip,rk3399-dfi".
6- reg: physical base address of each DFI and length of memory mapped region
7- rockchip,pmu: phandle to the syscon managing the "pmu general register files"
8- clocks: phandles for clock specified in "clock-names" property
9- clock-names : the name of clock used by the DFI, must be "pclk_ddr_mon";
10
11Example:
12 dfi: dfi@0xff630000 {
13 compatible = "rockchip,rk3399-dfi";
14 reg = <0x00 0xff630000 0x00 0x4000>;
15 rockchip,pmu = <&pmugrf>;
16 clocks = <&cru PCLK_DDR_MON>;
17 clock-names = "pclk_ddr_mon";
18 status = "disabled";
19 };
diff --git a/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
new file mode 100644
index 000000000000..7a9e8603c150
--- /dev/null
+++ b/Documentation/devicetree/bindings/devfreq/rk3399_dmc.txt
@@ -0,0 +1,209 @@
1* Rockchip rk3399 DMC(Dynamic Memory Controller) device
2
3Required properties:
4- compatible: Must be "rockchip,rk3399-dmc".
5- devfreq-events: Node to get DDR loading, Refer to
6 Documentation/devicetree/bindings/devfreq/
7 rockchip-dfi.txt
8- interrupts: The interrupt number to the CPU. The interrupt
9 specifier format depends on the interrupt controller.
10 It should be DCF interrupts, when DDR dvfs finish,
11 it will happen.
12- clocks: Phandles for clock specified in "clock-names" property
13- clock-names : The name of clock used by the DFI, must be
14 "pclk_ddr_mon";
15- operating-points-v2: Refer to Documentation/devicetree/bindings/power/opp.txt
16 for details.
17- center-supply: DMC supply node.
18- status: Marks the node enabled/disabled.
19
20Following properties are ddr timing:
21
22- rockchip,dram_speed_bin : Value reference include/dt-bindings/clock/ddr.h,
23 it select ddr3 cl-trp-trcd type, default value
24 "DDR3_DEFAULT".it must selected according to
25 "Speed Bin" in ddr3 datasheet, DO NOT use
26 smaller "Speed Bin" than ddr3 exactly is.
27
28- rockchip,pd_idle : Config the PD_IDLE value, defined the power-down
29 idle period, memories are places into power-down
30 mode if bus is idle for PD_IDLE DFI clocks.
31
32- rockchip,sr_idle : Configure the SR_IDLE value, defined the
33 selfrefresh idle period, memories are places
34 into self-refresh mode if bus is idle for
35 SR_IDLE*1024 DFI clocks (DFI clocks freq is
36 half of dram's clocks), defaule value is "0".
37
38- rockchip,sr_mc_gate_idle : Defined the self-refresh with memory and
39 controller clock gating idle period, memories
40 are places into self-refresh mode and memory
41 controller clock arg gating if bus is idle for
42 sr_mc_gate_idle*1024 DFI clocks.
43
44- rockchip,srpd_lite_idle : Defined the self-refresh power down idle
45 period, memories are places into self-refresh
46 power down mode if bus is idle for
47 srpd_lite_idle*1024 DFI clocks. This parameter
48 is for LPDDR4 only.
49
50- rockchip,standby_idle : Defined the standby idle period, memories are
51 places into self-refresh than controller, pi,
52 phy and dram clock will gating if bus is idle
53 for standby_idle * DFI clocks.
54
55- rockchip,dram_dll_disb_freq : It's defined the DDR3 dll bypass frequency in
56 MHz, when ddr freq less than DRAM_DLL_DISB_FREQ,
57 ddr3 dll will bypssed note: if dll was bypassed,
58 the odt also stop working.
59
60- rockchip,phy_dll_disb_freq : Defined the PHY dll bypass frequency in
61 MHz (Mega Hz), when ddr freq less than
62 DRAM_DLL_DISB_FREQ, phy dll will bypssed.
63 note: phy dll and phy odt are independent.
64
65- rockchip,ddr3_odt_disb_freq : When dram type is DDR3, this parameter defined
66 the odt disable frequency in MHz (Mega Hz),
67 when ddr frequency less then ddr3_odt_disb_freq,
68 the odt on dram side and controller side are
69 both disabled.
70
71- rockchip,ddr3_drv : When dram type is DDR3, this parameter define
72 the dram side driver stength in ohm, default
73 value is DDR3_DS_40ohm.
74
75- rockchip,ddr3_odt : When dram type is DDR3, this parameter define
76 the dram side ODT stength in ohm, default value
77 is DDR3_ODT_120ohm.
78
79- rockchip,phy_ddr3_ca_drv : When dram type is DDR3, this parameter define
80 the phy side CA line(incluing command line,
81 address line and clock line) driver strength.
82 Default value is PHY_DRV_ODT_40.
83
84- rockchip,phy_ddr3_dq_drv : When dram type is DDR3, this parameter define
85 the phy side DQ line(incluing DQS/DQ/DM line)
86 driver strength. default value is PHY_DRV_ODT_40.
87
88- rockchip,phy_ddr3_odt : When dram type is DDR3, this parameter define the
89 phy side odt strength, default value is
90 PHY_DRV_ODT_240.
91
92- rockchip,lpddr3_odt_disb_freq : When dram type is LPDDR3, this parameter defined
93 then odt disable frequency in MHz (Mega Hz),
94 when ddr frequency less then ddr3_odt_disb_freq,
95 the odt on dram side and controller side are
96 both disabled.
97
98- rockchip,lpddr3_drv : When dram type is LPDDR3, this parameter define
99 the dram side driver stength in ohm, default
100 value is LP3_DS_34ohm.
101
102- rockchip,lpddr3_odt : When dram type is LPDDR3, this parameter define
103 the dram side ODT stength in ohm, default value
104 is LP3_ODT_240ohm.
105
106- rockchip,phy_lpddr3_ca_drv : When dram type is LPDDR3, this parameter define
107 the phy side CA line(incluing command line,
108 address line and clock line) driver strength.
109 default value is PHY_DRV_ODT_40.
110
111- rockchip,phy_lpddr3_dq_drv : When dram type is LPDDR3, this parameter define
112 the phy side DQ line(incluing DQS/DQ/DM line)
113 driver strength. default value is
114 PHY_DRV_ODT_40.
115
116- rockchip,phy_lpddr3_odt : When dram type is LPDDR3, this parameter define
117 the phy side odt strength, default value is
118 PHY_DRV_ODT_240.
119
120- rockchip,lpddr4_odt_disb_freq : When dram type is LPDDR4, this parameter
121 defined the odt disable frequency in
122 MHz (Mega Hz), when ddr frequency less then
123 ddr3_odt_disb_freq, the odt on dram side and
124 controller side are both disabled.
125
126- rockchip,lpddr4_drv : When dram type is LPDDR4, this parameter define
127 the dram side driver stength in ohm, default
128 value is LP4_PDDS_60ohm.
129
130- rockchip,lpddr4_dq_odt : When dram type is LPDDR4, this parameter define
131 the dram side ODT on dqs/dq line stength in ohm,
132 default value is LP4_DQ_ODT_40ohm.
133
134- rockchip,lpddr4_ca_odt : When dram type is LPDDR4, this parameter define
135 the dram side ODT on ca line stength in ohm,
136 default value is LP4_CA_ODT_40ohm.
137
138- rockchip,phy_lpddr4_ca_drv : When dram type is LPDDR4, this parameter define
139 the phy side CA line(incluing command address
140 line) driver strength. default value is
141 PHY_DRV_ODT_40.
142
143- rockchip,phy_lpddr4_ck_cs_drv : When dram type is LPDDR4, this parameter define
144 the phy side clock line and cs line driver
145 strength. default value is PHY_DRV_ODT_80.
146
147- rockchip,phy_lpddr4_dq_drv : When dram type is LPDDR4, this parameter define
148 the phy side DQ line(incluing DQS/DQ/DM line)
149 driver strength. default value is PHY_DRV_ODT_80.
150
151- rockchip,phy_lpddr4_odt : When dram type is LPDDR4, this parameter define
152 the phy side odt strength, default value is
153 PHY_DRV_ODT_60.
154
155Example:
156 dmc_opp_table: dmc_opp_table {
157 compatible = "operating-points-v2";
158
159 opp00 {
160 opp-hz = /bits/ 64 <300000000>;
161 opp-microvolt = <900000>;
162 };
163 opp01 {
164 opp-hz = /bits/ 64 <666000000>;
165 opp-microvolt = <900000>;
166 };
167 };
168
169 dmc: dmc {
170 compatible = "rockchip,rk3399-dmc";
171 devfreq-events = <&dfi>;
172 interrupts = <GIC_SPI 1 IRQ_TYPE_LEVEL_HIGH>;
173 clocks = <&cru SCLK_DDRCLK>;
174 clock-names = "dmc_clk";
175 operating-points-v2 = <&dmc_opp_table>;
176 center-supply = <&ppvar_centerlogic>;
177 upthreshold = <15>;
178 downdifferential = <10>;
179 rockchip,ddr3_speed_bin = <21>;
180 rockchip,pd_idle = <0x40>;
181 rockchip,sr_idle = <0x2>;
182 rockchip,sr_mc_gate_idle = <0x3>;
183 rockchip,srpd_lite_idle = <0x4>;
184 rockchip,standby_idle = <0x2000>;
185 rockchip,dram_dll_dis_freq = <300>;
186 rockchip,phy_dll_dis_freq = <125>;
187 rockchip,auto_pd_dis_freq = <666>;
188 rockchip,ddr3_odt_dis_freq = <333>;
189 rockchip,ddr3_drv = <DDR3_DS_40ohm>;
190 rockchip,ddr3_odt = <DDR3_ODT_120ohm>;
191 rockchip,phy_ddr3_ca_drv = <PHY_DRV_ODT_40>;
192 rockchip,phy_ddr3_dq_drv = <PHY_DRV_ODT_40>;
193 rockchip,phy_ddr3_odt = <PHY_DRV_ODT_240>;
194 rockchip,lpddr3_odt_dis_freq = <333>;
195 rockchip,lpddr3_drv = <LP3_DS_34ohm>;
196 rockchip,lpddr3_odt = <LP3_ODT_240ohm>;
197 rockchip,phy_lpddr3_ca_drv = <PHY_DRV_ODT_40>;
198 rockchip,phy_lpddr3_dq_drv = <PHY_DRV_ODT_40>;
199 rockchip,phy_lpddr3_odt = <PHY_DRV_ODT_240>;
200 rockchip,lpddr4_odt_dis_freq = <333>;
201 rockchip,lpddr4_drv = <LP4_PDDS_60ohm>;
202 rockchip,lpddr4_dq_odt = <LP4_DQ_ODT_40ohm>;
203 rockchip,lpddr4_ca_odt = <LP4_CA_ODT_40ohm>;
204 rockchip,phy_lpddr4_ca_drv = <PHY_DRV_ODT_40>;
205 rockchip,phy_lpddr4_ck_cs_drv = <PHY_DRV_ODT_80>;
206 rockchip,phy_lpddr4_dq_drv = <PHY_DRV_ODT_80>;
207 rockchip,phy_lpddr4_odt = <PHY_DRV_ODT_60>;
208 status = "disabled";
209 };
diff --git a/drivers/devfreq/Kconfig b/drivers/devfreq/Kconfig
index a5be56ec57f2..cadd56e50b2c 100644
--- a/drivers/devfreq/Kconfig
+++ b/drivers/devfreq/Kconfig
@@ -76,7 +76,7 @@ comment "DEVFREQ Drivers"
76 76
77config ARM_EXYNOS_BUS_DEVFREQ 77config ARM_EXYNOS_BUS_DEVFREQ
78 tristate "ARM EXYNOS Generic Memory Bus DEVFREQ Driver" 78 tristate "ARM EXYNOS Generic Memory Bus DEVFREQ Driver"
79 depends on ARCH_EXYNOS 79 depends on ARCH_EXYNOS || COMPILE_TEST
80 select DEVFREQ_GOV_SIMPLE_ONDEMAND 80 select DEVFREQ_GOV_SIMPLE_ONDEMAND
81 select DEVFREQ_GOV_PASSIVE 81 select DEVFREQ_GOV_PASSIVE
82 select DEVFREQ_EVENT_EXYNOS_PPMU 82 select DEVFREQ_EVENT_EXYNOS_PPMU
@@ -91,14 +91,25 @@ config ARM_EXYNOS_BUS_DEVFREQ
91 This does not yet operate with optimal voltages. 91 This does not yet operate with optimal voltages.
92 92
93config ARM_TEGRA_DEVFREQ 93config ARM_TEGRA_DEVFREQ
94 tristate "Tegra DEVFREQ Driver" 94 tristate "Tegra DEVFREQ Driver"
95 depends on ARCH_TEGRA_124_SOC 95 depends on ARCH_TEGRA_124_SOC || COMPILE_TEST
96 select DEVFREQ_GOV_SIMPLE_ONDEMAND 96 select DEVFREQ_GOV_SIMPLE_ONDEMAND
97 select PM_OPP 97 select PM_OPP
98 help 98 help
99 This adds the DEVFREQ driver for the Tegra family of SoCs. 99 This adds the DEVFREQ driver for the Tegra family of SoCs.
100 It reads ACTMON counters of memory controllers and adjusts the 100 It reads ACTMON counters of memory controllers and adjusts the
101 operating frequencies and voltages with OPP support. 101 operating frequencies and voltages with OPP support.
102
103config ARM_RK3399_DMC_DEVFREQ
104 tristate "ARM RK3399 DMC DEVFREQ Driver"
105 depends on ARCH_ROCKCHIP
106 select DEVFREQ_EVENT_ROCKCHIP_DFI
107 select DEVFREQ_GOV_SIMPLE_ONDEMAND
108 select PM_OPP
109 help
110 This adds the DEVFREQ driver for the RK3399 DMC(Dynamic Memory Controller).
111 It sets the frequency for the memory controller and reads the usage counts
112 from hardware.
102 113
103source "drivers/devfreq/event/Kconfig" 114source "drivers/devfreq/event/Kconfig"
104 115
diff --git a/drivers/devfreq/Makefile b/drivers/devfreq/Makefile
index 09f11d9d40d5..fbff40a508a4 100644
--- a/drivers/devfreq/Makefile
+++ b/drivers/devfreq/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_DEVFREQ_GOV_PASSIVE) += governor_passive.o
8 8
9# DEVFREQ Drivers 9# DEVFREQ Drivers
10obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o 10obj-$(CONFIG_ARM_EXYNOS_BUS_DEVFREQ) += exynos-bus.o
11obj-$(CONFIG_ARM_RK3399_DMC_DEVFREQ) += rk3399_dmc.o
11obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o 12obj-$(CONFIG_ARM_TEGRA_DEVFREQ) += tegra-devfreq.o
12 13
13# DEVFREQ Event Drivers 14# DEVFREQ Event Drivers
diff --git a/drivers/devfreq/event/Kconfig b/drivers/devfreq/event/Kconfig
index eb6f74a2b6b9..0fdae8608961 100644
--- a/drivers/devfreq/event/Kconfig
+++ b/drivers/devfreq/event/Kconfig
@@ -15,7 +15,7 @@ if PM_DEVFREQ_EVENT
15 15
16config DEVFREQ_EVENT_EXYNOS_NOCP 16config DEVFREQ_EVENT_EXYNOS_NOCP
17 tristate "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver" 17 tristate "EXYNOS NoC (Network On Chip) Probe DEVFREQ event Driver"
18 depends on ARCH_EXYNOS 18 depends on ARCH_EXYNOS || COMPILE_TEST
19 select PM_OPP 19 select PM_OPP
20 help 20 help
21 This add the devfreq-event driver for Exynos SoC. It provides NoC 21 This add the devfreq-event driver for Exynos SoC. It provides NoC
@@ -23,11 +23,18 @@ config DEVFREQ_EVENT_EXYNOS_NOCP
23 23
24config DEVFREQ_EVENT_EXYNOS_PPMU 24config DEVFREQ_EVENT_EXYNOS_PPMU
25 tristate "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver" 25 tristate "EXYNOS PPMU (Platform Performance Monitoring Unit) DEVFREQ event Driver"
26 depends on ARCH_EXYNOS 26 depends on ARCH_EXYNOS || COMPILE_TEST
27 select PM_OPP 27 select PM_OPP
28 help 28 help
29 This add the devfreq-event driver for Exynos SoC. It provides PPMU 29 This add the devfreq-event driver for Exynos SoC. It provides PPMU
30 (Platform Performance Monitoring Unit) counters to estimate the 30 (Platform Performance Monitoring Unit) counters to estimate the
31 utilization of each module. 31 utilization of each module.
32 32
33config DEVFREQ_EVENT_ROCKCHIP_DFI
34 tristate "ROCKCHIP DFI DEVFREQ event Driver"
35 depends on ARCH_ROCKCHIP
36 help
37 This add the devfreq-event driver for Rockchip SoC. It provides DFI
38 (DDR Monitor Module) driver to count ddr load.
39
33endif # PM_DEVFREQ_EVENT 40endif # PM_DEVFREQ_EVENT
diff --git a/drivers/devfreq/event/Makefile b/drivers/devfreq/event/Makefile
index 3d6afd352253..dda7090a47c6 100644
--- a/drivers/devfreq/event/Makefile
+++ b/drivers/devfreq/event/Makefile
@@ -2,3 +2,4 @@
2 2
3obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o 3obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_NOCP) += exynos-nocp.o
4obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o 4obj-$(CONFIG_DEVFREQ_EVENT_EXYNOS_PPMU) += exynos-ppmu.o
5obj-$(CONFIG_DEVFREQ_EVENT_ROCKCHIP_DFI) += rockchip-dfi.o
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 845bf25fb9fb..f55cf0eb2a66 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -406,8 +406,6 @@ static int of_get_devfreq_events(struct device_node *np,
406 of_property_read_string(node, "event-name", &desc[j].name); 406 of_property_read_string(node, "event-name", &desc[j].name);
407 407
408 j++; 408 j++;
409
410 of_node_put(node);
411 } 409 }
412 info->desc = desc; 410 info->desc = desc;
413 411
diff --git a/drivers/devfreq/event/rockchip-dfi.c b/drivers/devfreq/event/rockchip-dfi.c
new file mode 100644
index 000000000000..43fcc5a7f515
--- /dev/null
+++ b/drivers/devfreq/event/rockchip-dfi.c
@@ -0,0 +1,256 @@
1/*
2 * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd
3 * Author: Lin Huang <hl@rock-chips.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/clk.h>
16#include <linux/devfreq-event.h>
17#include <linux/kernel.h>
18#include <linux/err.h>
19#include <linux/init.h>
20#include <linux/io.h>
21#include <linux/mfd/syscon.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/regmap.h>
25#include <linux/slab.h>
26#include <linux/list.h>
27#include <linux/of.h>
28
29#define RK3399_DMC_NUM_CH 2
30
31/* DDRMON_CTRL */
32#define DDRMON_CTRL 0x04
33#define CLR_DDRMON_CTRL (0x1f0000 << 0)
34#define LPDDR4_EN (0x10001 << 4)
35#define HARDWARE_EN (0x10001 << 3)
36#define LPDDR3_EN (0x10001 << 2)
37#define SOFTWARE_EN (0x10001 << 1)
38#define SOFTWARE_DIS (0x10000 << 1)
39#define TIME_CNT_EN (0x10001 << 0)
40
41#define DDRMON_CH0_COUNT_NUM 0x28
42#define DDRMON_CH0_DFI_ACCESS_NUM 0x2c
43#define DDRMON_CH1_COUNT_NUM 0x3c
44#define DDRMON_CH1_DFI_ACCESS_NUM 0x40
45
46/* pmu grf */
47#define PMUGRF_OS_REG2 0x308
48#define DDRTYPE_SHIFT 13
49#define DDRTYPE_MASK 7
50
51enum {
52 DDR3 = 3,
53 LPDDR3 = 6,
54 LPDDR4 = 7,
55 UNUSED = 0xFF
56};
57
58struct dmc_usage {
59 u32 access;
60 u32 total;
61};
62
63/*
64 * The dfi controller can monitor DDR load. It has an upper and lower threshold
65 * for the operating points. Whenever the usage leaves these bounds an event is
66 * generated to indicate the DDR frequency should be changed.
67 */
68struct rockchip_dfi {
69 struct devfreq_event_dev *edev;
70 struct devfreq_event_desc *desc;
71 struct dmc_usage ch_usage[RK3399_DMC_NUM_CH];
72 struct device *dev;
73 void __iomem *regs;
74 struct regmap *regmap_pmu;
75 struct clk *clk;
76};
77
78static void rockchip_dfi_start_hardware_counter(struct devfreq_event_dev *edev)
79{
80 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
81 void __iomem *dfi_regs = info->regs;
82 u32 val;
83 u32 ddr_type;
84
85 /* get ddr type */
86 regmap_read(info->regmap_pmu, PMUGRF_OS_REG2, &val);
87 ddr_type = (val >> DDRTYPE_SHIFT) & DDRTYPE_MASK;
88
89 /* clear DDRMON_CTRL setting */
90 writel_relaxed(CLR_DDRMON_CTRL, dfi_regs + DDRMON_CTRL);
91
92 /* set ddr type to dfi */
93 if (ddr_type == LPDDR3)
94 writel_relaxed(LPDDR3_EN, dfi_regs + DDRMON_CTRL);
95 else if (ddr_type == LPDDR4)
96 writel_relaxed(LPDDR4_EN, dfi_regs + DDRMON_CTRL);
97
98 /* enable count, use software mode */
99 writel_relaxed(SOFTWARE_EN, dfi_regs + DDRMON_CTRL);
100}
101
102static void rockchip_dfi_stop_hardware_counter(struct devfreq_event_dev *edev)
103{
104 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
105 void __iomem *dfi_regs = info->regs;
106
107 writel_relaxed(SOFTWARE_DIS, dfi_regs + DDRMON_CTRL);
108}
109
110static int rockchip_dfi_get_busier_ch(struct devfreq_event_dev *edev)
111{
112 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
113 u32 tmp, max = 0;
114 u32 i, busier_ch = 0;
115 void __iomem *dfi_regs = info->regs;
116
117 rockchip_dfi_stop_hardware_counter(edev);
118
119 /* Find out which channel is busier */
120 for (i = 0; i < RK3399_DMC_NUM_CH; i++) {
121 info->ch_usage[i].access = readl_relaxed(dfi_regs +
122 DDRMON_CH0_DFI_ACCESS_NUM + i * 20) * 4;
123 info->ch_usage[i].total = readl_relaxed(dfi_regs +
124 DDRMON_CH0_COUNT_NUM + i * 20);
125 tmp = info->ch_usage[i].access;
126 if (tmp > max) {
127 busier_ch = i;
128 max = tmp;
129 }
130 }
131 rockchip_dfi_start_hardware_counter(edev);
132
133 return busier_ch;
134}
135
136static int rockchip_dfi_disable(struct devfreq_event_dev *edev)
137{
138 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
139
140 rockchip_dfi_stop_hardware_counter(edev);
141 clk_disable_unprepare(info->clk);
142
143 return 0;
144}
145
146static int rockchip_dfi_enable(struct devfreq_event_dev *edev)
147{
148 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
149 int ret;
150
151 ret = clk_prepare_enable(info->clk);
152 if (ret) {
153 dev_err(&edev->dev, "failed to enable dfi clk: %d\n", ret);
154 return ret;
155 }
156
157 rockchip_dfi_start_hardware_counter(edev);
158 return 0;
159}
160
161static int rockchip_dfi_set_event(struct devfreq_event_dev *edev)
162{
163 return 0;
164}
165
166static int rockchip_dfi_get_event(struct devfreq_event_dev *edev,
167 struct devfreq_event_data *edata)
168{
169 struct rockchip_dfi *info = devfreq_event_get_drvdata(edev);
170 int busier_ch;
171
172 busier_ch = rockchip_dfi_get_busier_ch(edev);
173
174 edata->load_count = info->ch_usage[busier_ch].access;
175 edata->total_count = info->ch_usage[busier_ch].total;
176
177 return 0;
178}
179
180static const struct devfreq_event_ops rockchip_dfi_ops = {
181 .disable = rockchip_dfi_disable,
182 .enable = rockchip_dfi_enable,
183 .get_event = rockchip_dfi_get_event,
184 .set_event = rockchip_dfi_set_event,
185};
186
187static const struct of_device_id rockchip_dfi_id_match[] = {
188 { .compatible = "rockchip,rk3399-dfi" },
189 { },
190};
191
192static int rockchip_dfi_probe(struct platform_device *pdev)
193{
194 struct device *dev = &pdev->dev;
195 struct rockchip_dfi *data;
196 struct resource *res;
197 struct devfreq_event_desc *desc;
198 struct device_node *np = pdev->dev.of_node, *node;
199
200 data = devm_kzalloc(dev, sizeof(struct rockchip_dfi), GFP_KERNEL);
201 if (!data)
202 return -ENOMEM;
203
204 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
205 data->regs = devm_ioremap_resource(&pdev->dev, res);
206 if (IS_ERR(data->regs))
207 return PTR_ERR(data->regs);
208
209 data->clk = devm_clk_get(dev, "pclk_ddr_mon");
210 if (IS_ERR(data->clk)) {
211 dev_err(dev, "Cannot get the clk dmc_clk\n");
212 return PTR_ERR(data->clk);
213 };
214
215 /* try to find the optional reference to the pmu syscon */
216 node = of_parse_phandle(np, "rockchip,pmu", 0);
217 if (node) {
218 data->regmap_pmu = syscon_node_to_regmap(node);
219 if (IS_ERR(data->regmap_pmu))
220 return PTR_ERR(data->regmap_pmu);
221 }
222 data->dev = dev;
223
224 desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
225 if (!desc)
226 return -ENOMEM;
227
228 desc->ops = &rockchip_dfi_ops;
229 desc->driver_data = data;
230 desc->name = np->name;
231 data->desc = desc;
232
233 data->edev = devm_devfreq_event_add_edev(&pdev->dev, desc);
234 if (IS_ERR(data->edev)) {
235 dev_err(&pdev->dev,
236 "failed to add devfreq-event device\n");
237 return PTR_ERR(data->edev);
238 }
239
240 platform_set_drvdata(pdev, data);
241
242 return 0;
243}
244
245static struct platform_driver rockchip_dfi_driver = {
246 .probe = rockchip_dfi_probe,
247 .driver = {
248 .name = "rockchip-dfi",
249 .of_match_table = rockchip_dfi_id_match,
250 },
251};
252module_platform_driver(rockchip_dfi_driver);
253
254MODULE_LICENSE("GPL v2");
255MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
256MODULE_DESCRIPTION("Rockchip DFI driver");
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
new file mode 100644
index 000000000000..54d65f24a9fe
--- /dev/null
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -0,0 +1,480 @@
1/*
2 * Copyright (c) 2016, Fuzhou Rockchip Electronics Co., Ltd.
3 * Author: Lin Huang <hl@rock-chips.com>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 */
14
15#include <linux/arm-smccc.h>
16#include <linux/clk.h>
17#include <linux/delay.h>
18#include <linux/devfreq.h>
19#include <linux/devfreq-event.h>
20#include <linux/interrupt.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/platform_device.h>
24#include <linux/pm_opp.h>
25#include <linux/regulator/consumer.h>
26#include <linux/rwsem.h>
27#include <linux/suspend.h>
28
29#include <soc/rockchip/rockchip_sip.h>
30
31struct dram_timing {
32 unsigned int ddr3_speed_bin;
33 unsigned int pd_idle;
34 unsigned int sr_idle;
35 unsigned int sr_mc_gate_idle;
36 unsigned int srpd_lite_idle;
37 unsigned int standby_idle;
38 unsigned int auto_pd_dis_freq;
39 unsigned int dram_dll_dis_freq;
40 unsigned int phy_dll_dis_freq;
41 unsigned int ddr3_odt_dis_freq;
42 unsigned int ddr3_drv;
43 unsigned int ddr3_odt;
44 unsigned int phy_ddr3_ca_drv;
45 unsigned int phy_ddr3_dq_drv;
46 unsigned int phy_ddr3_odt;
47 unsigned int lpddr3_odt_dis_freq;
48 unsigned int lpddr3_drv;
49 unsigned int lpddr3_odt;
50 unsigned int phy_lpddr3_ca_drv;
51 unsigned int phy_lpddr3_dq_drv;
52 unsigned int phy_lpddr3_odt;
53 unsigned int lpddr4_odt_dis_freq;
54 unsigned int lpddr4_drv;
55 unsigned int lpddr4_dq_odt;
56 unsigned int lpddr4_ca_odt;
57 unsigned int phy_lpddr4_ca_drv;
58 unsigned int phy_lpddr4_ck_cs_drv;
59 unsigned int phy_lpddr4_dq_drv;
60 unsigned int phy_lpddr4_odt;
61};
62
63struct rk3399_dmcfreq {
64 struct device *dev;
65 struct devfreq *devfreq;
66 struct devfreq_simple_ondemand_data ondemand_data;
67 struct clk *dmc_clk;
68 struct devfreq_event_dev *edev;
69 struct mutex lock;
70 struct dram_timing timing;
71
72 /*
73 * DDR Converser of Frequency (DCF) is used to implement DDR frequency
74 * conversion without the participation of CPU, we will implement and
75 * control it in arm trust firmware.
76 */
77 wait_queue_head_t wait_dcf_queue;
78 int irq;
79 int wait_dcf_flag;
80 struct regulator *vdd_center;
81 unsigned long rate, target_rate;
82 unsigned long volt, target_volt;
83 struct dev_pm_opp *curr_opp;
84};
85
86static int rk3399_dmcfreq_target(struct device *dev, unsigned long *freq,
87 u32 flags)
88{
89 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
90 struct dev_pm_opp *opp;
91 unsigned long old_clk_rate = dmcfreq->rate;
92 unsigned long target_volt, target_rate;
93 int err;
94
95 rcu_read_lock();
96 opp = devfreq_recommended_opp(dev, freq, flags);
97 if (IS_ERR(opp)) {
98 rcu_read_unlock();
99 return PTR_ERR(opp);
100 }
101
102 target_rate = dev_pm_opp_get_freq(opp);
103 target_volt = dev_pm_opp_get_voltage(opp);
104
105 dmcfreq->rate = dev_pm_opp_get_freq(dmcfreq->curr_opp);
106 dmcfreq->volt = dev_pm_opp_get_voltage(dmcfreq->curr_opp);
107
108 rcu_read_unlock();
109
110 if (dmcfreq->rate == target_rate)
111 return 0;
112
113 mutex_lock(&dmcfreq->lock);
114
115 /*
116 * If frequency scaling from low to high, adjust voltage first.
117 * If frequency scaling from high to low, adjust frequency first.
118 */
119 if (old_clk_rate < target_rate) {
120 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt,
121 target_volt);
122 if (err) {
123 dev_err(dev, "Cannot to set voltage %lu uV\n",
124 target_volt);
125 goto out;
126 }
127 }
128 dmcfreq->wait_dcf_flag = 1;
129
130 err = clk_set_rate(dmcfreq->dmc_clk, target_rate);
131 if (err) {
132 dev_err(dev, "Cannot to set frequency %lu (%d)\n",
133 target_rate, err);
134 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt,
135 dmcfreq->volt);
136 goto out;
137 }
138
139 /*
140 * Wait until bcf irq happen, it means freq scaling finish in
141 * arm trust firmware, use 100ms as timeout time.
142 */
143 if (!wait_event_timeout(dmcfreq->wait_dcf_queue,
144 !dmcfreq->wait_dcf_flag, HZ / 10))
145 dev_warn(dev, "Timeout waiting for dcf interrupt\n");
146
147 /*
148 * Check the dpll rate,
149 * There only two result we will get,
150 * 1. Ddr frequency scaling fail, we still get the old rate.
151 * 2. Ddr frequency scaling sucessful, we get the rate we set.
152 */
153 dmcfreq->rate = clk_get_rate(dmcfreq->dmc_clk);
154
155 /* If get the incorrect rate, set voltage to old value. */
156 if (dmcfreq->rate != target_rate) {
157 dev_err(dev, "Get wrong ddr frequency, Request frequency %lu,\
158 Current frequency %lu\n", target_rate, dmcfreq->rate);
159 regulator_set_voltage(dmcfreq->vdd_center, dmcfreq->volt,
160 dmcfreq->volt);
161 goto out;
162 } else if (old_clk_rate > target_rate)
163 err = regulator_set_voltage(dmcfreq->vdd_center, target_volt,
164 target_volt);
165 if (err)
166 dev_err(dev, "Cannot to set vol %lu uV\n", target_volt);
167
168 dmcfreq->curr_opp = opp;
169out:
170 mutex_unlock(&dmcfreq->lock);
171 return err;
172}
173
174static int rk3399_dmcfreq_get_dev_status(struct device *dev,
175 struct devfreq_dev_status *stat)
176{
177 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
178 struct devfreq_event_data edata;
179 int ret = 0;
180
181 ret = devfreq_event_get_event(dmcfreq->edev, &edata);
182 if (ret < 0)
183 return ret;
184
185 stat->current_frequency = dmcfreq->rate;
186 stat->busy_time = edata.load_count;
187 stat->total_time = edata.total_count;
188
189 return ret;
190}
191
192static int rk3399_dmcfreq_get_cur_freq(struct device *dev, unsigned long *freq)
193{
194 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
195
196 *freq = dmcfreq->rate;
197
198 return 0;
199}
200
201static struct devfreq_dev_profile rk3399_devfreq_dmc_profile = {
202 .polling_ms = 200,
203 .target = rk3399_dmcfreq_target,
204 .get_dev_status = rk3399_dmcfreq_get_dev_status,
205 .get_cur_freq = rk3399_dmcfreq_get_cur_freq,
206};
207
208static __maybe_unused int rk3399_dmcfreq_suspend(struct device *dev)
209{
210 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
211 int ret = 0;
212
213 ret = devfreq_event_disable_edev(dmcfreq->edev);
214 if (ret < 0) {
215 dev_err(dev, "failed to disable the devfreq-event devices\n");
216 return ret;
217 }
218
219 ret = devfreq_suspend_device(dmcfreq->devfreq);
220 if (ret < 0) {
221 dev_err(dev, "failed to suspend the devfreq devices\n");
222 return ret;
223 }
224
225 return 0;
226}
227
228static __maybe_unused int rk3399_dmcfreq_resume(struct device *dev)
229{
230 struct rk3399_dmcfreq *dmcfreq = dev_get_drvdata(dev);
231 int ret = 0;
232
233 ret = devfreq_event_enable_edev(dmcfreq->edev);
234 if (ret < 0) {
235 dev_err(dev, "failed to enable the devfreq-event devices\n");
236 return ret;
237 }
238
239 ret = devfreq_resume_device(dmcfreq->devfreq);
240 if (ret < 0) {
241 dev_err(dev, "failed to resume the devfreq devices\n");
242 return ret;
243 }
244 return ret;
245}
246
247static SIMPLE_DEV_PM_OPS(rk3399_dmcfreq_pm, rk3399_dmcfreq_suspend,
248 rk3399_dmcfreq_resume);
249
250static irqreturn_t rk3399_dmc_irq(int irq, void *dev_id)
251{
252 struct rk3399_dmcfreq *dmcfreq = dev_id;
253 struct arm_smccc_res res;
254
255 dmcfreq->wait_dcf_flag = 0;
256 wake_up(&dmcfreq->wait_dcf_queue);
257
258 /* Clear the DCF interrupt */
259 arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
260 ROCKCHIP_SIP_CONFIG_DRAM_CLR_IRQ,
261 0, 0, 0, 0, &res);
262
263 return IRQ_HANDLED;
264}
265
266static int of_get_ddr_timings(struct dram_timing *timing,
267 struct device_node *np)
268{
269 int ret = 0;
270
271 ret = of_property_read_u32(np, "rockchip,ddr3_speed_bin",
272 &timing->ddr3_speed_bin);
273 ret |= of_property_read_u32(np, "rockchip,pd_idle",
274 &timing->pd_idle);
275 ret |= of_property_read_u32(np, "rockchip,sr_idle",
276 &timing->sr_idle);
277 ret |= of_property_read_u32(np, "rockchip,sr_mc_gate_idle",
278 &timing->sr_mc_gate_idle);
279 ret |= of_property_read_u32(np, "rockchip,srpd_lite_idle",
280 &timing->srpd_lite_idle);
281 ret |= of_property_read_u32(np, "rockchip,standby_idle",
282 &timing->standby_idle);
283 ret |= of_property_read_u32(np, "rockchip,auto_pd_dis_freq",
284 &timing->auto_pd_dis_freq);
285 ret |= of_property_read_u32(np, "rockchip,dram_dll_dis_freq",
286 &timing->dram_dll_dis_freq);
287 ret |= of_property_read_u32(np, "rockchip,phy_dll_dis_freq",
288 &timing->phy_dll_dis_freq);
289 ret |= of_property_read_u32(np, "rockchip,ddr3_odt_dis_freq",
290 &timing->ddr3_odt_dis_freq);
291 ret |= of_property_read_u32(np, "rockchip,ddr3_drv",
292 &timing->ddr3_drv);
293 ret |= of_property_read_u32(np, "rockchip,ddr3_odt",
294 &timing->ddr3_odt);
295 ret |= of_property_read_u32(np, "rockchip,phy_ddr3_ca_drv",
296 &timing->phy_ddr3_ca_drv);
297 ret |= of_property_read_u32(np, "rockchip,phy_ddr3_dq_drv",
298 &timing->phy_ddr3_dq_drv);
299 ret |= of_property_read_u32(np, "rockchip,phy_ddr3_odt",
300 &timing->phy_ddr3_odt);
301 ret |= of_property_read_u32(np, "rockchip,lpddr3_odt_dis_freq",
302 &timing->lpddr3_odt_dis_freq);
303 ret |= of_property_read_u32(np, "rockchip,lpddr3_drv",
304 &timing->lpddr3_drv);
305 ret |= of_property_read_u32(np, "rockchip,lpddr3_odt",
306 &timing->lpddr3_odt);
307 ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_ca_drv",
308 &timing->phy_lpddr3_ca_drv);
309 ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_dq_drv",
310 &timing->phy_lpddr3_dq_drv);
311 ret |= of_property_read_u32(np, "rockchip,phy_lpddr3_odt",
312 &timing->phy_lpddr3_odt);
313 ret |= of_property_read_u32(np, "rockchip,lpddr4_odt_dis_freq",
314 &timing->lpddr4_odt_dis_freq);
315 ret |= of_property_read_u32(np, "rockchip,lpddr4_drv",
316 &timing->lpddr4_drv);
317 ret |= of_property_read_u32(np, "rockchip,lpddr4_dq_odt",
318 &timing->lpddr4_dq_odt);
319 ret |= of_property_read_u32(np, "rockchip,lpddr4_ca_odt",
320 &timing->lpddr4_ca_odt);
321 ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_ca_drv",
322 &timing->phy_lpddr4_ca_drv);
323 ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_ck_cs_drv",
324 &timing->phy_lpddr4_ck_cs_drv);
325 ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_dq_drv",
326 &timing->phy_lpddr4_dq_drv);
327 ret |= of_property_read_u32(np, "rockchip,phy_lpddr4_odt",
328 &timing->phy_lpddr4_odt);
329
330 return ret;
331}
332
333static int rk3399_dmcfreq_probe(struct platform_device *pdev)
334{
335 struct arm_smccc_res res;
336 struct device *dev = &pdev->dev;
337 struct device_node *np = pdev->dev.of_node;
338 struct rk3399_dmcfreq *data;
339 int ret, irq, index, size;
340 uint32_t *timing;
341 struct dev_pm_opp *opp;
342
343 irq = platform_get_irq(pdev, 0);
344 if (irq < 0) {
345 dev_err(&pdev->dev, "Cannot get the dmc interrupt resource\n");
346 return -EINVAL;
347 }
348 data = devm_kzalloc(dev, sizeof(struct rk3399_dmcfreq), GFP_KERNEL);
349 if (!data)
350 return -ENOMEM;
351
352 mutex_init(&data->lock);
353
354 data->vdd_center = devm_regulator_get(dev, "center");
355 if (IS_ERR(data->vdd_center)) {
356 dev_err(dev, "Cannot get the regulator \"center\"\n");
357 return PTR_ERR(data->vdd_center);
358 }
359
360 data->dmc_clk = devm_clk_get(dev, "dmc_clk");
361 if (IS_ERR(data->dmc_clk)) {
362 dev_err(dev, "Cannot get the clk dmc_clk\n");
363 return PTR_ERR(data->dmc_clk);
364 };
365
366 data->irq = irq;
367 ret = devm_request_irq(dev, irq, rk3399_dmc_irq, 0,
368 dev_name(dev), data);
369 if (ret) {
370 dev_err(dev, "Failed to request dmc irq: %d\n", ret);
371 return ret;
372 }
373
374 init_waitqueue_head(&data->wait_dcf_queue);
375 data->wait_dcf_flag = 0;
376
377 data->edev = devfreq_event_get_edev_by_phandle(dev, 0);
378 if (IS_ERR(data->edev))
379 return -EPROBE_DEFER;
380
381 ret = devfreq_event_enable_edev(data->edev);
382 if (ret < 0) {
383 dev_err(dev, "failed to enable devfreq-event devices\n");
384 return ret;
385 }
386
387 /*
388 * Get dram timing and pass it to arm trust firmware,
389 * the dram drvier in arm trust firmware will get these
390 * timing and to do dram initial.
391 */
392 if (!of_get_ddr_timings(&data->timing, np)) {
393 timing = &data->timing.ddr3_speed_bin;
394 size = sizeof(struct dram_timing) / 4;
395 for (index = 0; index < size; index++) {
396 arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, *timing++, index,
397 ROCKCHIP_SIP_CONFIG_DRAM_SET_PARAM,
398 0, 0, 0, 0, &res);
399 if (res.a0) {
400 dev_err(dev, "Failed to set dram param: %ld\n",
401 res.a0);
402 return -EINVAL;
403 }
404 }
405 }
406
407 arm_smccc_smc(ROCKCHIP_SIP_DRAM_FREQ, 0, 0,
408 ROCKCHIP_SIP_CONFIG_DRAM_INIT,
409 0, 0, 0, 0, &res);
410
411 /*
412 * We add a devfreq driver to our parent since it has a device tree node
413 * with operating points.
414 */
415 if (dev_pm_opp_of_add_table(dev)) {
416 dev_err(dev, "Invalid operating-points in device tree.\n");
417 rcu_read_unlock();
418 return -EINVAL;
419 }
420
421 of_property_read_u32(np, "upthreshold",
422 &data->ondemand_data.upthreshold);
423 of_property_read_u32(np, "downdifferential",
424 &data->ondemand_data.downdifferential);
425
426 data->rate = clk_get_rate(data->dmc_clk);
427
428 rcu_read_lock();
429 opp = devfreq_recommended_opp(dev, &data->rate, 0);
430 if (IS_ERR(opp)) {
431 rcu_read_unlock();
432 return PTR_ERR(opp);
433 }
434 rcu_read_unlock();
435 data->curr_opp = opp;
436
437 rk3399_devfreq_dmc_profile.initial_freq = data->rate;
438
439 data->devfreq = devfreq_add_device(dev,
440 &rk3399_devfreq_dmc_profile,
441 "simple_ondemand",
442 &data->ondemand_data);
443 if (IS_ERR(data->devfreq))
444 return PTR_ERR(data->devfreq);
445 devm_devfreq_register_opp_notifier(dev, data->devfreq);
446
447 data->dev = dev;
448 platform_set_drvdata(pdev, data);
449
450 return 0;
451}
452
453static int rk3399_dmcfreq_remove(struct platform_device *pdev)
454{
455 struct rk3399_dmcfreq *dmcfreq = platform_get_drvdata(pdev);
456
457 regulator_put(dmcfreq->vdd_center);
458
459 return 0;
460}
461
462static const struct of_device_id rk3399dmc_devfreq_of_match[] = {
463 { .compatible = "rockchip,rk3399-dmc" },
464 { },
465};
466
467static struct platform_driver rk3399_dmcfreq_driver = {
468 .probe = rk3399_dmcfreq_probe,
469 .remove = rk3399_dmcfreq_remove,
470 .driver = {
471 .name = "rk3399-dmc-freq",
472 .pm = &rk3399_dmcfreq_pm,
473 .of_match_table = rk3399dmc_devfreq_of_match,
474 },
475};
476module_platform_driver(rk3399_dmcfreq_driver);
477
478MODULE_LICENSE("GPL v2");
479MODULE_AUTHOR("Lin Huang <hl@rock-chips.com>");
480MODULE_DESCRIPTION("RK3399 dmcfreq driver with devfreq framework");
diff --git a/include/linux/devfreq-event.h b/include/linux/devfreq-event.h
index 0a83a1e648b0..4db00b02ca3f 100644
--- a/include/linux/devfreq-event.h
+++ b/include/linux/devfreq-event.h
@@ -148,11 +148,6 @@ static inline int devfreq_event_reset_event(struct devfreq_event_dev *edev)
148 return -EINVAL; 148 return -EINVAL;
149} 149}
150 150
151static inline void *devfreq_event_get_drvdata(struct devfreq_event_dev *edev)
152{
153 return ERR_PTR(-EINVAL);
154}
155
156static inline struct devfreq_event_dev *devfreq_event_get_edev_by_phandle( 151static inline struct devfreq_event_dev *devfreq_event_get_edev_by_phandle(
157 struct device *dev, int index) 152 struct device *dev, int index)
158{ 153{