tizen 2.4 release
[profile/mobile/platform/kernel/linux-3.10-sc7730.git] / drivers / media / sprd_dcam / common / parse_hwinfo.c
1 /*
2  * Copyright (C) 2012 Spreadtrum Communications Inc.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 #include <linux/kernel.h>
14 #include <linux/slab.h>
15 #include <linux/interrupt.h>
16 #include <linux/clk.h>
17 #include <linux/err.h>
18 #include <asm/io.h>
19 #ifndef CONFIG_64BIT
20 #include <soc/sprd/hardware.h>
21 #include <soc/sprd/board.h>
22 #include <mach/irqs.h>
23 #else
24 #include <soc/sprd/irqs.h>
25 #endif
26 #include <soc/sprd/sci.h>
27 #include <soc/sprd/sci_glb_regs.h>
28
29 #include <linux/sprd_iommu.h>
30 #include <linux/delay.h>
31 #include <linux/of_gpio.h>
32 #include "dcam_drv.h"
33 #include "../../sprd_sensor/sensor_drv_sprd.h"
34
35 //#define PARSE_DEBUG
36
37 #ifdef PARSE_DEBUG
38         #define PARSE_TRACE             printk
39 #else
40         #define PARSE_TRACE             pr_debug
41 #endif
42
43 #ifdef CONFIG_SC_FPGA
44 #define  CLK_MM_I_IN_CLOCKTREE  0
45 #else
46 #define  CLK_MM_I_IN_CLOCKTREE  1
47 #endif
48
49 #ifdef CONFIG_OF
50 unsigned long dcam_regbase = 0 ;
51 unsigned long isp_regbase = 0;
52 unsigned long csi_regbase = 0;
53 #else
54 #endif
55 static atomic_t mm_enabe_cnt = ATOMIC_INIT(0);
56
57 void parse_baseaddress(struct device_node *dn)
58 {
59 #ifdef CONFIG_OF
60         struct resource r;
61
62         if (0 == of_address_to_resource(dn, 0, &r)) {
63                 PARSE_TRACE("PARSE BASE=0x%x\n", r.start);
64         } else {
65                 PARSE_TRACE("PARSE BASE ADDRESS ERROR\n");
66                 return;
67         }
68         if (dcam_regbase == 0 && strcmp(dn->name, "sprd_dcam") == 0) {
69                 dcam_regbase = ioremap_nocache(r.start, resource_size(&r));
70                 PARSE_TRACE("Dcam register base addr: 0x%lx\n", dcam_regbase);
71         } else if (isp_regbase == 0 && strcmp(dn->name, "sprd_isp") == 0) {
72                 isp_regbase = ioremap_nocache(r.start, resource_size(&r));
73                 PARSE_TRACE("Isp register base addr: 0x%lx\n", isp_regbase);
74         } else if (csi_regbase == 0 && strcmp(dn->name, "sprd_sensor") == 0) {
75                 csi_regbase = ioremap_nocache(r.start, resource_size(&r));
76                 PARSE_TRACE("Csi register base addr: 0x%lx\n", csi_regbase);
77         }
78 #endif
79 }
80
81 uint32_t parse_irq(struct device_node *dn)
82 {
83 #ifdef CONFIG_OF
84         return irq_of_parse_and_map(dn, 0);
85 #else
86         return DCAM_IRQ;
87 #endif
88 }
89
90 struct clk * parse_clk(struct device_node *dn, char *clkname)
91 {
92 #ifdef CONFIG_OF
93         PARSE_TRACE("parse_clk %s \n",clkname);
94         return of_clk_get_by_name(dn, clkname);
95 #else
96         return clk_get(NULL, clkname);
97 #endif
98 }
99
100 int32_t clk_mm_i_eb(struct device_node *dn, uint32_t enable)
101 {
102 #ifdef CONFIG_SC_FPGA_CLK
103         return 0;
104 #else
105 #if CLK_MM_I_IN_CLOCKTREE
106         int     ret = 0;
107         struct clk*     clk_mm_i = NULL;
108
109         clk_mm_i = parse_clk(dn, "clk_mm_i");
110         if (IS_ERR(clk_mm_i)) {
111                 printk("clk_mm_i_eb: get fail.\n");
112                 return -1;
113         }
114
115         if(enable){
116                 ret = clk_enable(clk_mm_i);
117                 if (ret) {
118                         printk("clk_mm_i_eb: enable fail.\n");
119                         return -1;
120                 }
121 #if defined(CONFIG_SPRD_IOMMU)
122                 {
123                         sprd_iommu_module_enable(IOMMU_MM);
124                 }
125 #endif
126                 PARSE_TRACE("clk_mm_i_eb enable ok.\n");
127                 atomic_inc(&mm_enabe_cnt);
128         }else{
129 #if defined(CONFIG_SPRD_IOMMU)
130                 {
131                         sprd_iommu_module_disable(IOMMU_MM);
132                 }
133 #endif
134                 clk_disable(clk_mm_i);
135                 clk_put(clk_mm_i);
136                 clk_mm_i = NULL;
137                 udelay(500);
138                 atomic_dec(&mm_enabe_cnt);
139                 PARSE_TRACE("clk_mm_i_eb disable ok.\n");
140         }
141
142 #else
143         if(enable){
144                 if(atomic_inc_return(&mm_enabe_cnt) == 1) {
145                         REG_OWR(REG_AON_APB_APB_EB0,BIT_MM_EB);
146                         REG_AWR(REG_PMU_APB_PD_MM_TOP_CFG,~BIT_PD_MM_TOP_FORCE_SHUTDOWN);
147                         REG_OWR(REG_MM_AHB_GEN_CKG_CFG,BIT_SENSOR_CKG_EN|BIT_DCAM_AXI_CKG_EN);
148                         PARSE_TRACE("mm enable ok.\n");
149                 }
150         }else{
151                 if(atomic_dec_return(&mm_enabe_cnt) == 0) {
152                         REG_AWR(REG_MM_AHB_GEN_CKG_CFG,~(BIT_SENSOR_CKG_EN|BIT_DCAM_AXI_CKG_EN));
153                         REG_OWR(REG_PMU_APB_PD_MM_TOP_CFG,BIT_PD_MM_TOP_FORCE_SHUTDOWN);
154                         REG_AWR(REG_AON_APB_APB_EB0,~BIT_MM_EB);
155                         udelay(500);
156                         PARSE_TRACE("mm disable ok.\n");
157                 }
158         }
159 #endif
160
161         PARSE_TRACE("mm_enabe_cnt = %d.\n",atomic_read(&mm_enabe_cnt));
162 #ifdef PARSE_DEBUG
163         if(enable)
164                 mm_clk_register_trace();
165 #endif
166         return 0;
167 #endif
168 }
169
170 #ifndef GPIO_SUB_SENSOR_RESET
171 #define GPIO_SUB_SENSOR_RESET             0
172 #endif
173
174 #define GPIO_SENSOR_DEV0_PWN              GPIO_MAIN_SENSOR_PWN
175 #define GPIO_SENSOR_DEV1_PWN              GPIO_SUB_SENSOR_PWN
176 #define GPIO_SENSOR_DEV2_PWN              0
177 #define GPIO_SENSOR_DEV0_RST              GPIO_SENSOR_RESET
178 #define GPIO_SENSOR_DEV1_RST              GPIO_SUB_SENSOR_RESET
179 #define GPIO_SENSOR_DEV2_RST              0
180
181 int get_gpio_id(struct device_node *dn, int *pwn, int *reset, uint32_t sensor_id)
182 {
183         if (NULL == pwn || NULL == reset)
184                 return -1;
185
186 #ifdef CONFIG_OF
187         if (0 == sensor_id) {
188                 *pwn   = of_get_gpio(dn, 1);
189                 *reset = of_get_gpio(dn, 0);
190         } else if (1 == sensor_id) {
191                 *pwn   = of_get_gpio(dn, 3);
192                 *reset = of_get_gpio(dn, 2);
193         } else {
194                 *pwn   = 0;
195                 *reset = 0;
196         }
197 #else
198         if (0 == sensor_id) {
199                 *pwn   = GPIO_SENSOR_DEV0_PWN;
200                 *reset = GPIO_SENSOR_DEV0_RST;
201         } else if (1 == sensor_id) {
202                 *pwn   = GPIO_SENSOR_DEV1_PWN;
203                 *reset = GPIO_SENSOR_DEV1_RST;
204         } else {
205                 *pwn   = GPIO_SENSOR_DEV2_PWN;
206                 *reset = GPIO_SENSOR_DEV2_RST;
207         }
208 #endif
209
210         return 0;
211 }
212
213 int get_gpio_id_ex(struct device_node *dn, int type, int *id, uint32_t sensor_id)
214 {
215         if (NULL == id)
216                 return -1;
217
218 #ifdef CONFIG_OF
219         switch (type) {
220         case GPIO_CAMDVDD:
221                 if (SENSOR_DEV_0 == sensor_id)
222                         *id = of_get_gpio(dn, 4);
223                 if (SENSOR_DEV_1 == sensor_id)
224                         *id = of_get_gpio(dn, 6);
225                 break;
226         case GPIO_CAMIOVDD:
227                 *id = of_get_gpio(dn, 5);
228                 break;
229         default:
230                 *id = 0;
231                 break;
232         }
233 #else
234         *id = 0;
235 #endif
236
237         return 0;
238 }
239
240
241 #ifndef REGU_DEV0_CAMAVDD
242 #define REGU_DEV0_CAMAVDD                 "vddcama"
243 #endif
244 #ifndef REGU_DEV1_CAMAVDD
245 #define REGU_DEV1_CAMAVDD                 "vddcama"
246 #endif
247 #ifndef REGU_DEV2_CAMAVDD
248 #define REGU_DEV2_CAMAVDD                 "vddcama"
249 #endif
250 #ifndef REGU_DEV0_CAMDVDD
251 #define REGU_DEV0_CAMDVDD                 "vddcamd"
252 #endif
253 #ifndef REGU_DEV1_CAMDVDD
254 #define REGU_DEV1_CAMDVDD                 "vddcamd"
255 #endif
256 #ifndef REGU_DEV2_CAMDVDD
257 #define REGU_DEV2_CAMDVDD                 "vddcamd"
258 #endif
259 #ifndef REGU_DEV0_CAMIOVDD
260 #define REGU_DEV0_CAMIOVDD                "vddcamio"
261 #endif
262 #ifndef REGU_DEV1_CAMIOVDD
263 #define REGU_DEV1_CAMIOVDD                "vddcamio"
264 #endif
265 #ifndef REGU_DEV2_CAMIOVDD
266 #define REGU_DEV2_CAMIOVDD                "vddcamio"
267 #endif
268 #ifndef REGU_DEV0_CAMMOT
269 #define REGU_DEV0_CAMMOT                  "vddcammot"
270 #endif
271 #ifndef REGU_DEV1_CAMMOT
272 #define REGU_DEV1_CAMMOT                  "vddcammot"
273 #endif
274 #ifndef REGU_DEV2_CAMMOT
275 #define REGU_DEV2_CAMMOT                  "vddcammot"
276 #endif
277
278 const char *c_sensor_avdd_name[] = {
279                                                 REGU_DEV0_CAMAVDD,
280                                                 REGU_DEV1_CAMAVDD,
281                                                 REGU_DEV2_CAMAVDD};
282
283 const char *c_sensor_iovdd_name[] = {
284                                                 REGU_DEV0_CAMIOVDD,
285                                                 REGU_DEV1_CAMIOVDD,
286                                                 REGU_DEV2_CAMIOVDD};
287
288 const char *c_sensor_dvdd_name[] = {
289                                                 REGU_DEV0_CAMDVDD,
290                                                 REGU_DEV1_CAMDVDD,
291                                                 REGU_DEV2_CAMDVDD};
292
293 const char *c_sensor_mot_name[] = {
294                                                 REGU_DEV0_CAMMOT,
295                                                 REGU_DEV1_CAMMOT,
296                                                 REGU_DEV2_CAMMOT};
297
298 int get_regulator_name(struct device_node *dn, int *type, uint32_t sensor_id, char **name)
299 {
300         const char *ldostr;
301         int ret = 0;
302
303         switch (*type) {
304         case REGU_CAMAVDD:
305                 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 1, &ldostr);
306                 if(!ret) {
307                         *name = ldostr;
308                         PARSE_TRACE("REGU_CAMAVDD = >%s\n",*name);
309                 } else {
310                         *name = (char*)c_sensor_avdd_name[sensor_id];
311                 }
312                 break;
313
314         case REGU_CAMDVDD:
315                 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 2, &ldostr);
316                 if(!ret) {
317                         *name = ldostr;
318                         PARSE_TRACE("REGU_CAMDVDD = >%s\n",*name);
319                 } else {
320                         *name = (char*)c_sensor_dvdd_name[sensor_id];
321                 }
322                 break;
323
324         case REGU_CAMIOVDD:
325                 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 3, &ldostr);
326                 if(!ret) {
327                         *name = ldostr;
328                         PARSE_TRACE("REGU_CAMIOVDD = >%s\n",*name);
329                 } else {
330                         *name = (char*)c_sensor_iovdd_name[sensor_id];
331                 }
332                 break;
333
334         case REGU_CAMMOT:
335                 ret = of_property_read_string_index(dn, "vdds", sensor_id*4, &ldostr);
336                 if(!ret) {
337                         *name = ldostr;
338                         PARSE_TRACE("REGU_CAMMOT = >%s\n",*name);
339                 } else {
340                         *name = (char*)c_sensor_mot_name[sensor_id];
341                 }
342                 break;
343
344         default:
345                 break;
346         }
347
348         if(strcmp(name, "vddcammot")==0) {
349                 *type = REGU_CAMMOT;
350         } else if(strcmp(name, "vddcama")==0){
351                 *type = REGU_CAMAVDD;
352         } else if(strcmp(name, "vddcamd")==0){
353                 *type = REGU_CAMDVDD;
354         } else if(strcmp(name, "vddcamio")==0){
355                 *type = REGU_CAMIOVDD;
356         }
357          of_node_put(dn);
358         return 0;
359 }