Merge git://git.kernel.org/pub/scm/linux/kernel/git/nico/orion into fixes
[pandora-kernel.git] / arch / arm / mach-dove / mpp.c
1 /*
2  * arch/arm/mach-dove/mpp.c
3  *
4  * MPP functions for Marvell Dove SoCs
5  *
6  * This file is licensed under the terms of the GNU General Public
7  * License version 2.  This program is licensed "as is" without any
8  * warranty of any kind, whether express or implied.
9  */
10
11 #include <linux/kernel.h>
12 #include <linux/gpio.h>
13 #include <linux/io.h>
14
15 #include <mach/dove.h>
16
17 #include "mpp.h"
18
19 #define MPP_NR_REGS 4
20 #define MPP_CTRL(i)     ((i) == 3 ?                             \
21                          DOVE_MPP_CTRL4_VIRT_BASE :             \
22                          DOVE_MPP_VIRT_BASE + (i) * 4)
23 #define PMU_SIG_REGS 2
24 #define PMU_SIG_CTRL(i) (DOVE_PMU_SIG_CTRL + (i) * 4)
25
26 struct dove_mpp_grp {
27         int start;
28         int end;
29 };
30
31 static struct dove_mpp_grp dove_mpp_grp[] = {
32         [MPP_24_39] = {
33                 .start  = 24,
34                 .end    = 39,
35         },
36         [MPP_40_45] = {
37                 .start  = 40,
38                 .end    = 45,
39         },
40         [MPP_46_51] = {
41                 .start  = 40,
42                 .end    = 45,
43         },
44         [MPP_58_61] = {
45                 .start  = 58,
46                 .end    = 61,
47         },
48         [MPP_62_63] = {
49                 .start  = 62,
50                 .end    = 63,
51         },
52 };
53
54 static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
55 {
56         int i;
57
58         for (i = start; i <= end; i++)
59                 orion_gpio_set_valid(i, gpio_mode);
60 }
61
62 static void dove_mpp_dump_regs(void)
63 {
64 #ifdef DEBUG
65         int i;
66
67         pr_debug("MPP_CTRL regs:");
68         for (i = 0; i < MPP_NR_REGS; i++)
69                 printk(" %08x", readl(MPP_CTRL(i)));
70         printk("\n");
71
72         pr_debug("PMU_SIG_CTRL regs:");
73         for (i = 0; i < PMU_SIG_REGS; i++)
74                 printk(" %08x", readl(PMU_SIG_CTRL(i)));
75         printk("\n");
76
77         pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n", readl(DOVE_PMU_MPP_GENERAL_CTRL));
78         pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
79 #endif
80 }
81
82 static void dove_mpp_cfg_nfc(int sel)
83 {
84         u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
85
86         mpp_gen_cfg &= ~0x1;
87         mpp_gen_cfg |= sel;
88         writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
89
90         dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
91 }
92
93 static void dove_mpp_cfg_au1(int sel)
94 {
95         u32 mpp_ctrl4           = readl(DOVE_MPP_CTRL4_VIRT_BASE);
96         u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
97         u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
98         u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);
99
100         mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
101         ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
102         mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
103         global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);
104
105         if (!sel || sel == 0x2)
106                 dove_mpp_gpio_mode(52, 57, 0);
107         else
108                 dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
109
110         if (sel & 0x1) {
111                 global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
112                 dove_mpp_gpio_mode(56, 57, 0);
113         }
114         if (sel & 0x2) {
115                 mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
116                 dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
117         }
118         if (sel & 0x4) {
119                 ssp_ctrl1 |= DOVE_SSP_ON_AU1;
120                 dove_mpp_gpio_mode(52, 55, 0);
121         }
122         if (sel & 0x8)
123                 mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
124
125         writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
126         writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
127         writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
128         writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
129 }
130
131 static void dove_mpp_conf_grp(int num, int sel, u32 *mpp_ctrl)
132 {
133         int start = dove_mpp_grp[num].start;
134         int end = dove_mpp_grp[num].end;
135         int gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
136
137         *mpp_ctrl &= ~(0x1 << num);
138         *mpp_ctrl |= sel << num;
139
140         dove_mpp_gpio_mode(start, end, gpio_mode);
141 }
142
143 void __init dove_mpp_conf(unsigned int *mpp_list)
144 {
145         u32 mpp_ctrl[MPP_NR_REGS];
146         u32 pmu_mpp_ctrl = 0;
147         u32 pmu_sig_ctrl[PMU_SIG_REGS];
148         int i;
149
150         for (i = 0; i < MPP_NR_REGS; i++)
151                 mpp_ctrl[i] = readl(MPP_CTRL(i));
152
153         for (i = 0; i < PMU_SIG_REGS; i++)
154                 pmu_sig_ctrl[i] = readl(PMU_SIG_CTRL(i));
155
156         pmu_mpp_ctrl = readl(DOVE_PMU_MPP_GENERAL_CTRL);
157
158         dove_mpp_dump_regs();
159
160         for ( ; *mpp_list != MPP_END; mpp_list++) {
161                 unsigned int num = MPP_NUM(*mpp_list);
162                 unsigned int sel = MPP_SEL(*mpp_list);
163                 int shift, gpio_mode;
164
165                 if (num > MPP_MAX) {
166                         pr_err("dove: invalid MPP number (%u)\n", num);
167                         continue;
168                 }
169
170                 if (*mpp_list & MPP_NFC_MASK) {
171                         dove_mpp_cfg_nfc(sel);
172                         continue;
173                 }
174
175                 if (*mpp_list & MPP_AU1_MASK) {
176                         dove_mpp_cfg_au1(sel);
177                         continue;
178                 }
179
180                 if (*mpp_list & MPP_GRP_MASK) {
181                         dove_mpp_conf_grp(num, sel, &mpp_ctrl[3]);
182                         continue;
183                 }
184
185                 shift = (num & 7) << 2;
186                 if (*mpp_list & MPP_PMU_MASK) {
187                         pmu_mpp_ctrl |= (0x1 << num);
188                         pmu_sig_ctrl[num / 8] &= ~(0xf << shift);
189                         pmu_sig_ctrl[num / 8] |= 0xf << shift;
190                         gpio_mode = 0;
191                 } else {
192                         mpp_ctrl[num / 8] &= ~(0xf << shift);
193                         mpp_ctrl[num / 8] |= sel << shift;
194                         gpio_mode = GPIO_OUTPUT_OK | GPIO_INPUT_OK;
195                 }
196
197                 orion_gpio_set_valid(num, gpio_mode);
198         }
199
200         for (i = 0; i < MPP_NR_REGS; i++)
201                 writel(mpp_ctrl[i], MPP_CTRL(i));
202
203         for (i = 0; i < PMU_SIG_REGS; i++)
204                 writel(pmu_sig_ctrl[i], PMU_SIG_CTRL(i));
205
206         writel(pmu_mpp_ctrl, DOVE_PMU_MPP_GENERAL_CTRL);
207
208         dove_mpp_dump_regs();
209 }