2 * Copyright (C) 2012 Spreadtrum Communications Inc.
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.
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.
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>
20 #include <soc/sprd/hardware.h>
21 #include <soc/sprd/board.h>
22 #include <mach/irqs.h>
24 #include <soc/sprd/irqs.h>
26 #include <soc/sprd/sci.h>
27 #include <soc/sprd/sci_glb_regs.h>
29 #include <linux/sprd_iommu.h>
30 #include <linux/delay.h>
31 #include <linux/of_gpio.h>
33 #include "../../sprd_sensor/sensor_drv_sprd.h"
38 #define PARSE_TRACE printk
40 #define PARSE_TRACE pr_debug
44 #define CLK_MM_I_IN_CLOCKTREE 0
46 #define CLK_MM_I_IN_CLOCKTREE 1
50 unsigned long dcam_regbase = 0 ;
51 unsigned long isp_regbase = 0;
52 unsigned long csi_regbase = 0;
55 static atomic_t mm_enabe_cnt = ATOMIC_INIT(0);
57 void parse_baseaddress(struct device_node *dn)
62 if (0 == of_address_to_resource(dn, 0, &r)) {
63 PARSE_TRACE("PARSE BASE=0x%x\n", r.start);
65 PARSE_TRACE("PARSE BASE ADDRESS ERROR\n");
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);
81 uint32_t parse_irq(struct device_node *dn)
84 return irq_of_parse_and_map(dn, 0);
90 struct clk * parse_clk(struct device_node *dn, char *clkname)
93 PARSE_TRACE("parse_clk %s \n",clkname);
94 return of_clk_get_by_name(dn, clkname);
96 return clk_get(NULL, clkname);
100 int32_t clk_mm_i_eb(struct device_node *dn, uint32_t enable)
102 #ifdef CONFIG_SC_FPGA_CLK
105 #if CLK_MM_I_IN_CLOCKTREE
107 struct clk* clk_mm_i = NULL;
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");
116 ret = clk_enable(clk_mm_i);
118 printk("clk_mm_i_eb: enable fail.\n");
121 #if defined(CONFIG_SPRD_IOMMU)
123 sprd_iommu_module_enable(IOMMU_MM);
126 PARSE_TRACE("clk_mm_i_eb enable ok.\n");
127 atomic_inc(&mm_enabe_cnt);
129 #if defined(CONFIG_SPRD_IOMMU)
131 sprd_iommu_module_disable(IOMMU_MM);
134 clk_disable(clk_mm_i);
138 atomic_dec(&mm_enabe_cnt);
139 PARSE_TRACE("clk_mm_i_eb disable ok.\n");
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");
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);
156 PARSE_TRACE("mm disable ok.\n");
161 PARSE_TRACE("mm_enabe_cnt = %d.\n",atomic_read(&mm_enabe_cnt));
164 mm_clk_register_trace();
170 #ifndef GPIO_SUB_SENSOR_RESET
171 #define GPIO_SUB_SENSOR_RESET 0
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
181 int get_gpio_id(struct device_node *dn, int *pwn, int *reset, uint32_t sensor_id)
183 if (NULL == pwn || NULL == reset)
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);
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;
205 *pwn = GPIO_SENSOR_DEV2_PWN;
206 *reset = GPIO_SENSOR_DEV2_RST;
213 int get_gpio_id_ex(struct device_node *dn, int type, int *id, uint32_t sensor_id)
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);
227 *id = of_get_gpio(dn, 5);
241 #ifndef REGU_DEV0_CAMAVDD
242 #define REGU_DEV0_CAMAVDD "vddcama"
244 #ifndef REGU_DEV1_CAMAVDD
245 #define REGU_DEV1_CAMAVDD "vddcama"
247 #ifndef REGU_DEV2_CAMAVDD
248 #define REGU_DEV2_CAMAVDD "vddcama"
250 #ifndef REGU_DEV0_CAMDVDD
251 #define REGU_DEV0_CAMDVDD "vddcamd"
253 #ifndef REGU_DEV1_CAMDVDD
254 #define REGU_DEV1_CAMDVDD "vddcamd"
256 #ifndef REGU_DEV2_CAMDVDD
257 #define REGU_DEV2_CAMDVDD "vddcamd"
259 #ifndef REGU_DEV0_CAMIOVDD
260 #define REGU_DEV0_CAMIOVDD "vddcamio"
262 #ifndef REGU_DEV1_CAMIOVDD
263 #define REGU_DEV1_CAMIOVDD "vddcamio"
265 #ifndef REGU_DEV2_CAMIOVDD
266 #define REGU_DEV2_CAMIOVDD "vddcamio"
268 #ifndef REGU_DEV0_CAMMOT
269 #define REGU_DEV0_CAMMOT "vddcammot"
271 #ifndef REGU_DEV1_CAMMOT
272 #define REGU_DEV1_CAMMOT "vddcammot"
274 #ifndef REGU_DEV2_CAMMOT
275 #define REGU_DEV2_CAMMOT "vddcammot"
278 const char *c_sensor_avdd_name[] = {
283 const char *c_sensor_iovdd_name[] = {
288 const char *c_sensor_dvdd_name[] = {
293 const char *c_sensor_mot_name[] = {
298 int get_regulator_name(struct device_node *dn, int *type, uint32_t sensor_id, char **name)
305 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 1, &ldostr);
308 PARSE_TRACE("REGU_CAMAVDD = >%s\n",*name);
310 *name = (char*)c_sensor_avdd_name[sensor_id];
315 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 2, &ldostr);
318 PARSE_TRACE("REGU_CAMDVDD = >%s\n",*name);
320 *name = (char*)c_sensor_dvdd_name[sensor_id];
325 ret = of_property_read_string_index(dn, "vdds", sensor_id*4 + 3, &ldostr);
328 PARSE_TRACE("REGU_CAMIOVDD = >%s\n",*name);
330 *name = (char*)c_sensor_iovdd_name[sensor_id];
335 ret = of_property_read_string_index(dn, "vdds", sensor_id*4, &ldostr);
338 PARSE_TRACE("REGU_CAMMOT = >%s\n",*name);
340 *name = (char*)c_sensor_mot_name[sensor_id];
348 if(strcmp(name, "vddcammot")==0) {
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;