tizen 2.4 release
[kernel/u-boot-tm1.git] / arch / arm / cpu / arm926ejs / sc8800g / mfp_sprd.c
1 /*
2  *  linux/arch/arm/mach-sc8800s/mfp-sprd.c
3  *
4  *  Spreadtrum SoC multi-function pin configuration support
5  *
6  *  The GPIOs on SoC can be configured as one of many alternate
7  *  functions,
8  *
9  *  Author:     Yingchun Li(yingchun.li@spreadtrum.com)
10  *  Created:    March 10, 2010
11  *  Copyright:  Spreadtrum Inc.
12  *
13  *  This program is free software; you can redistribute it and/or modify
14  *  it under the terms of the GNU General Public License version 2 as
15  *  published by the Free Software Foundation.
16 */
17 //#define DEBUG
18
19 //#include <linux/module.h>
20 //#include <linux/kernel.h>
21 //#include <asm/io.h>
22 //#include <mach/mfp.h>
23 //#include <mach/regs_cpc.h>
24 #include <asm/arch/mfp.h>
25 #include <asm/arch/sc8800g_reg_base.h>
26 #include <asm/arch/sc8800g_cpc.h>
27 #include <asm/io.h>
28 #include <asm/arch/adi_hal_internal.h>
29
30 /*
31 NOTE: pin to gpio's map, you should check it from your chip's spec
32         carefully.
33         in the map table, pin as the index, for mostly we use
34         MFP_PIN_TO_GPIO to get the gpio from the pin
35
36 const static unsigned long pin_gpio_map[MFP_PIN_MAX] = {
37         [MFP_PIN_MAX - 1] = 0xffff
38 };
39
40 */
41
42 /*
43         we cann't find a easy way to map pin to gpio, so drop it.
44 */
45 unsigned long mfp_to_gpio(int pin)
46 {
47         BUG_ON(1);
48 }
49
50 static  int __mfp_validate(unsigned long c)
51 {
52         return 1;
53 }
54
55 static unsigned long __mfp_get_pin_reg(int c)
56 {
57         int pin_offset;
58         if (!(c& A_DIE_PIN)) {
59                 pin_offset = MFP_CFG_TO_REG_OFFS(c);
60                 return (unsigned long)PIN_CTL_BASE + pin_offset;
61         } else {
62                 c &= ~A_DIE_PIN;
63                 pin_offset = MFP_CFG_TO_REG_OFFS(c);
64                 return (unsigned long)ANA_PIN_CTL_BASE + pin_offset;
65         }
66 }
67
68 #define pin_is_a_die(c) (c & A_DIE_PIN)
69 #ifdef DEBUG
70 #define MFP_DBG(fmt...) pr_debug(fmt)
71 static unsigned long __mfp_get_physical(int c)
72 {
73         int pin_offset;
74         if (!(c & A_DIE_PIN)) {
75                 pin_offset = MFP_CFG_TO_REG_OFFS(c);
76                 return (unsigned long)SPRD_CPC_PHYS + pin_offset;
77         } else {
78                 c &= ~A_DIE_PIN;
79                 pin_offset = MFP_CFG_TO_REG_OFFS(c);
80                 return (unsigned long)SPRD_MISC_PHYS + 0x180 + pin_offset;
81         }
82 }
83 #else
84 #define MFP_DBG(fmt...)
85 #endif
86
87 static int __mfp_config_pin(unsigned long c)
88 {
89         unsigned long flags;
90         unsigned long pin_reg;
91         unsigned long pin_cfg;
92         int pin_area;
93
94         pin_reg = __mfp_get_pin_reg(c);
95         pin_area = pin_is_a_die(c);
96
97         MFP_DBG("register is :0x%x, old config is %x\r\n",
98                 __mfp_get_physical(c),
99                 pin_area == A_DIE_PIN ? ANA_REG_GET(pin_reg) :
100                 __raw_readl(pin_reg));
101
102         local_irq_save(flags);
103         if (pin_area == A_DIE_PIN)
104                 pin_cfg = ANA_REG_GET(pin_reg);
105         else
106         pin_cfg =__raw_readl(pin_reg);
107         if (c & MFP_IO_SET) {
108                 pin_cfg = (pin_cfg & ~MFP_IO_MASK) | (c & MFP_IO_MASK);
109         }
110
111         if (c & MFP_S_PULL_SET) {
112                 pin_cfg = (pin_cfg & ~MFP_S_PULL_MASK) | (c & MFP_S_PULL_MASK);
113         }
114
115         if (c & MFP_AF_SET) {
116                 pin_cfg = (pin_cfg & ~MFP_AF_MASK) | (c & MFP_AF_MASK);
117         }
118
119         if (c & MFP_F_PULL_SET) {
120                 pin_cfg = (pin_cfg & ~MFP_F_PULL_MASK) | (c & MFP_F_PULL_MASK);
121         }
122
123         if (c & MFP_DS_SET) {
124                 pin_cfg = (pin_cfg & ~MFP_DS_MASK) | (c & MFP_DS_MASK);
125         }
126
127         if (pin_area == A_DIE_PIN)
128                 ANA_REG_SET(pin_reg, pin_cfg);
129         else
130                 __raw_writel(pin_cfg, pin_reg);
131         local_irq_restore(flags);
132
133         MFP_DBG("new config is :%x\r\n", (int)pin_cfg);
134
135         return 0;
136 }
137
138 void sprd_mfp_config(unsigned long *mfp_cfgs, int num)
139 {
140         unsigned long flags;
141         unsigned long *c;
142         int res;
143         int i;
144
145         for (i = 0, c = mfp_cfgs; i < num; i++, c++) {
146
147                 res = __mfp_validate((*c));
148                 if (res < 0)
149                         continue;
150
151                 local_irq_save(flags);
152
153                 __mfp_config_pin(*c);
154
155                 local_irq_restore(flags);
156         }
157 }
158 //EXPORT_SYMBOL_GPL(sprd_mfp_config);