Merge branch 'develop' of lhh@10.10.10.29:/home/rockchip/kernel into develop
[firefly-linux-kernel-4.4.55.git] / drivers / regulator / rk29-pwm-regulator.c
1 /* drivers/regulator/rk29-pwm-regulator.c\r
2  *
3  * Copyright (C) 2010 ROCKCHIP, Inc.
4  *
5  * This software is licensed under the terms of the GNU General Public
6  * License version 2, as published by the Free Software Foundation, and
7  * may be copied, distributed, and modified under those terms.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  */
15 /*******************************************************************/
16 /*        COPYRIGHT (C)  ROCK-CHIPS FUZHOU . ALL RIGHTS RESERVED.                         */
17 /*******************************************************************
18 FILE            :               rk29-pwm-regulator.c\r
19 DESC            :       rk29 pwm regulator driver\r
20 AUTHOR          :       hxy\r
21 DATE            :       2010-12-20\r
22 NOTES           :
23 $LOG: GPIO.C,V $
24 REVISION 0.01
25 ********************************************************************/
26
27
28 #include <linux/bug.h>
29 #include <linux/err.h>\r
30 #include <linux/platform_device.h>\r
31 #include <linux/kernel.h>\r
32 #include <linux/clk.h>\r
33 #include <asm/io.h>\r
34 #include <linux/delay.h>\r
35 #include <linux/regulator/driver.h>
36 #include <linux/regulator/rk29-pwm-regulator.h>\r
37 #include <mach/iomux.h>\r
38 #include <linux/gpio.h>\r
39
40
41 #if 0
42 #define DBG(x...)       printk(KERN_INFO x)
43 #else
44 #define DBG(x...)
45 #endif
46 \r
47 \r
48 #define         PWM_VCORE_120           40\r
49 #define         PWM_VCORE_125           32\r
50 #define PWM_VCORE_130           21\r
51 #define PWM_VCORE_135           10\r
52 #define PWM_VCORE_140           0\r
53 \r
54 \r
55 #define pwm_write_reg(id, addr, val)                    __raw_writel(val, addr+(RK29_PWM_BASE+id*0x10)) \r
56 #define pwm_read_reg(id, addr)                          __raw_readl(addr+(RK29_PWM_BASE+id*0x10))\r
57 \r
58 \r
59 const static int pwm_voltage_map[] = {\r
60         1200, 1250, 1300, 1350, 1400\r
61 };\r
62 \r
63 static int pwm_set_rate(struct pwm_platform_data *pdata,int nHz,u32 rate)\r
64 {\r
65     u32 divh,divTotal;\r
66     int id = pdata->pwm_id;\r
67     unsigned long clkrate;\r
68     struct clk *pwm_clk = clk_get(NULL, "pwm");\r
69 \r
70     clkrate = clk_get_rate(pwm_clk);\r
71         \r
72     if ( id >3 || id <0 )\r
73         return -1;\r
74 \r
75     if(rate == 0)\r
76         {\r
77          // iomux pwm2 to gpio2_a[3]     \r
78          rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_gpio);\r
79          // set gpio to low level        \r
80          gpio_set_value(pdata->pwm_gpio,GPIO_LOW);\r
81 \r
82          pdata->pwm_voltage = 1400;\r
83          \r
84         }\r
85     else if (rate <= 100)\r
86         {\r
87          // iomux pwm2           \r
88          rk29_mux_api_set(pdata->pwm_iomux_name, pdata->pwm_iomux_pwm);\r
89                  \r
90          pwm_write_reg(id,PWM_REG_CTRL, PWM_DIV|PWM_RESET);\r
91          divh = clkrate / nHz;\r
92          divh = divh >> (1+(PWM_DIV>>9));\r
93          pwm_write_reg(id,PWM_REG_LRC,(divh == 0)?1:divh);\r
94                  \r
95          divTotal =pwm_read_reg(id,PWM_REG_LRC);\r
96          divh = divTotal*rate/100;\r
97          pwm_write_reg(id, PWM_REG_HRC, divh?divh:1);\r
98          pwm_write_reg(id,PWM_REG_CNTR,0);\r
99          pwm_write_reg(id, PWM_REG_CTRL,pwm_read_reg(id,PWM_REG_CTRL)|PWM_DIV|PWM_ENABLE|PWM_TimeEN);\r
100 \r
101          pdata->pwm_voltage = 1400 - 476*rate/100;\r
102          \r
103         }\r
104      else\r
105         {\r
106         return -1;\r
107         }\r
108 \r
109         msleep(50);\r
110         \r
111         \r
112     return (0);\r
113 }\r
114 \r
115 static int pwm_init(struct pwm_platform_data *pdata, int nHz, int rate)\r
116 {\r
117 \r
118         struct clk *pwm_clk = clk_get(NULL, "pwm");\r
119            \r
120         // pwm2 clk enable\r
121         clk_enable(pwm_clk);\r
122 \r
123         if(pwm_set_rate(pdata,nHz,rate)!=0)\r
124                 return -1;              \r
125 \r
126 \r
127         return 0;\r
128 }\r
129 \r
130 static int pwm_regulator_list_voltage(struct regulator_dev *dev,unsigned int index)\r
131 {\r
132         int *pwm_voltage_table = pwm_voltage_map;\r
133
134        DBG("Enter %s, index =%d\n",__FUNCTION__,index);\r
135        if (index < sizeof(pwm_voltage_map)/sizeof(int))\r
136                 return pwm_voltage_table[index];\r
137         else\r
138                 return -1;\r
139 }\r
140 \r
141 static int pwm_regulator_is_enabled(struct regulator_dev *dev)\r
142 {\r
143         DBG("Enter %s\n",__FUNCTION__);\r
144         return 0;\r
145 }
146
147 static int pwm_regulator_enable(struct regulator_dev *dev)\r
148 {\r
149         DBG("Enter %s\n",__FUNCTION__);\r
150         return 0;\r
151 }
152
153 static int pwm_regulator_disable(struct regulator_dev *dev)\r
154 {\r
155         DBG("Enter %s\n",__FUNCTION__);\r
156         return 0;\r
157 }
158
159 static int pwm_regulator_get_voltage(struct regulator_dev *dev)\r
160 {\r
161        struct pwm_platform_data *pdata = rdev_get_drvdata(dev);\r
162            \r
163         DBG("Enter %s\n",__FUNCTION__);  \r
164         \r
165         return (pdata->pwm_voltage*1000);\r
166 }
167
168 static int pwm_regulator_set_voltage(struct regulator_dev *dev,\r
169                                   int min_uV, int max_uV)\r
170 {          \r
171         struct pwm_platform_data *pdata = rdev_get_drvdata(dev);\r
172         \r
173        const int *voltage_map = pwm_voltage_map;\r
174            \r
175        int min_mV = min_uV /1000, max_mA = max_uV / 1000;\r
176            \r
177         u32 size = sizeof(pwm_voltage_map)/sizeof(int), i, vol,pwm_value;\r
178 \r
179         DBG("%s:  min_uV = %d, max_uV = %d\n",__FUNCTION__, min_uV,max_uV);\r
180 \r
181         if (min_mV < voltage_map[0] ||max_mA > voltage_map[size-1])\r
182                 return -EINVAL;
183            
184         for (i = 0; i < size; i++)\r
185         {\r
186                 if (voltage_map[i] >= min_mV)\r
187                         break;
188         }\r
189
190 \r
191        vol =  voltage_map[i];\r
192 \r
193        pdata->pwm_voltage = vol;\r
194            \r
195         // VDD12 = 1.4 - 0.476*D , ÆäÖÐDΪPWMÕ¼¿Õ±È, \r
196         pwm_value = 100*(1400-vol)/476;  // pwm_value %\r
197 \r
198            \r
199         if (pwm_set_rate(pdata,1000*1000,pwm_value)!=0)\r
200                 return -1;\r
201 \r
202        return 0;\r
203 \r
204 }
205
206 static struct regulator_ops pwm_voltage_ops = {\r
207         .list_voltage   = pwm_regulator_list_voltage,\r
208         .set_voltage    =pwm_regulator_set_voltage,\r
209         .get_voltage    = pwm_regulator_get_voltage,\r
210         .enable         = pwm_regulator_enable,\r
211         .disable        = pwm_regulator_disable,\r
212         .is_enabled     = pwm_regulator_is_enabled,\r
213 };\r
214
215 static struct regulator_desc pwm_regulator= {\r
216                 .name = "pwm-regulator",\r
217                 .ops = &pwm_voltage_ops,\r
218                 .type = REGULATOR_VOLTAGE,\r
219 };\r
220
221 static int __devinit pwm_regulator_probe(struct platform_device *pdev)\r
222 {\r
223 \r
224         struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
225         struct regulator_dev *rdev;\r
226         int ret ;\r
227
228         rdev = regulator_register(&pwm_regulator, &pdev->dev,\r
229                                 pdata->init_data, pdata);\r
230         if (IS_ERR(rdev)) {\r
231                 dev_dbg(&pdev->dev, "couldn't register regulator\n");
232                 return PTR_ERR(rdev);\r
233         }\r
234         \r
235        ret = gpio_request(pdata->pwm_gpio,"pwm");\r
236 \r
237         if (ret) {\r
238                         dev_err(&pdev->dev,"failed to request pwm gpio\n");\r
239                         goto err_gpio;\r
240                 }\r
241 \r
242         //pwm_init(pdata,1000*1000,PWM_VCORE_130);\r
243         \r
244 \r
245         platform_set_drvdata(pdev, rdev);\r
246         printk(KERN_INFO "pwm_regulator: driver initialized\n");\r
247 \r
248         return 0;\r
249 \r
250         \r
251 err_gpio:\r
252         gpio_free(pdata->pwm_gpio);\r
253 \r
254 \r
255         return ret;\r
256 \r
257 }
258 static int __devexit pwm_regulator_remove(struct platform_device *pdev)\r
259 {\r
260         struct pwm_platform_data *pdata = pdev->dev.platform_data;\r
261         struct regulator_dev *rdev = platform_get_drvdata(pdev);\r
262 \r
263         regulator_unregister(rdev);\r
264         gpio_free(pdata->pwm_gpio);\r
265 \r
266         return 0;\r
267 }\r
268 \r
269 static struct platform_driver pwm_regulator_driver = {\r
270         .driver = {\r
271                 .name = "pwm-voltage-regulator",\r
272         },\r
273         .remove = __devexit_p(pwm_regulator_remove),\r
274 };\r
275
276 \r
277 static int __init pwm_regulator_module_init(void)\r
278 {
279         return platform_driver_probe(&pwm_regulator_driver, pwm_regulator_probe);\r
280 }
281
282 static void __exit pwm_regulator_module_exit(void)\r
283 {
284         platform_driver_unregister(&pwm_regulator_driver);\r
285 }
286 \r
287 \r
288 module_init(pwm_regulator_module_init);\r
289 \r
290 module_exit(pwm_regulator_module_exit);\r
291
292 MODULE_LICENSE("GPL");
293 MODULE_AUTHOR("hxy <hxy@rock-chips.com>");\r
294 MODULE_DESCRIPTION("k29 pwm change driver");\r