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