Staging: rts_pstor: fix read past end of buffer
[linux-2.6.git] / arch / arm / mach-dove / mpp.c
blob71db2bdf2f284ccc55c005175e920bfe194d8f6d
1 /*
2 * arch/arm/mach-dove/mpp.c
4 * MPP functions for Marvell Dove SoCs
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 */
11 #include <linux/kernel.h>
12 #include <linux/gpio.h>
13 #include <linux/io.h>
15 #include <mach/dove.h>
17 #include "mpp.h"
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)
26 struct dove_mpp_grp {
27 int start;
28 int end;
31 static struct dove_mpp_grp dove_mpp_grp[] = {
32 [MPP_24_39] = {
33 .start = 24,
34 .end = 39,
36 [MPP_40_45] = {
37 .start = 40,
38 .end = 45,
40 [MPP_46_51] = {
41 .start = 40,
42 .end = 45,
44 [MPP_58_61] = {
45 .start = 58,
46 .end = 61,
48 [MPP_62_63] = {
49 .start = 62,
50 .end = 63,
54 static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
56 int i;
58 for (i = start; i <= end; i++)
59 orion_gpio_set_valid(i, gpio_mode);
62 static void dove_mpp_dump_regs(void)
64 #ifdef DEBUG
65 int i;
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");
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");
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
82 static void dove_mpp_cfg_nfc(int sel)
84 u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
86 mpp_gen_cfg &= ~0x1;
87 mpp_gen_cfg |= sel;
88 writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
90 dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
93 static void dove_mpp_cfg_au1(int sel)
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);
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);
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);
110 if (sel & 0x1) {
111 global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
112 dove_mpp_gpio_mode(56, 57, 0);
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);
118 if (sel & 0x4) {
119 ssp_ctrl1 |= DOVE_SSP_ON_AU1;
120 dove_mpp_gpio_mode(52, 55, 0);
122 if (sel & 0x8)
123 mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
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);
131 static void dove_mpp_conf_grp(int num, int sel, u32 *mpp_ctrl)
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;
137 *mpp_ctrl &= ~(0x1 << num);
138 *mpp_ctrl |= sel << num;
140 dove_mpp_gpio_mode(start, end, gpio_mode);
143 void __init dove_mpp_conf(unsigned int *mpp_list)
145 u32 mpp_ctrl[MPP_NR_REGS];
146 u32 pmu_mpp_ctrl = 0;
147 u32 pmu_sig_ctrl[PMU_SIG_REGS];
148 int i;
150 /* Initialize gpiolib. */
151 orion_gpio_init();
153 for (i = 0; i < MPP_NR_REGS; i++)
154 mpp_ctrl[i] = readl(MPP_CTRL(i));
156 for (i = 0; i < PMU_SIG_REGS; i++)
157 pmu_sig_ctrl[i] = readl(PMU_SIG_CTRL(i));
159 pmu_mpp_ctrl = readl(DOVE_PMU_MPP_GENERAL_CTRL);
161 dove_mpp_dump_regs();
163 for ( ; *mpp_list != MPP_END; mpp_list++) {
164 unsigned int num = MPP_NUM(*mpp_list);
165 unsigned int sel = MPP_SEL(*mpp_list);
166 int shift, gpio_mode;
168 if (num > MPP_MAX) {
169 pr_err("dove: invalid MPP number (%u)\n", num);
170 continue;
173 if (*mpp_list & MPP_NFC_MASK) {
174 dove_mpp_cfg_nfc(sel);
175 continue;
178 if (*mpp_list & MPP_AU1_MASK) {
179 dove_mpp_cfg_au1(sel);
180 continue;
183 if (*mpp_list & MPP_GRP_MASK) {
184 dove_mpp_conf_grp(num, sel, &mpp_ctrl[3]);
185 continue;
188 shift = (num & 7) << 2;
189 if (*mpp_list & MPP_PMU_MASK) {
190 pmu_mpp_ctrl |= (0x1 << num);
191 pmu_sig_ctrl[num / 8] &= ~(0xf << shift);
192 pmu_sig_ctrl[num / 8] |= 0xf << shift;
193 gpio_mode = 0;
194 } else {
195 mpp_ctrl[num / 8] &= ~(0xf << shift);
196 mpp_ctrl[num / 8] |= sel << shift;
197 gpio_mode = GPIO_OUTPUT_OK | GPIO_INPUT_OK;
200 orion_gpio_set_valid(num, gpio_mode);
203 for (i = 0; i < MPP_NR_REGS; i++)
204 writel(mpp_ctrl[i], MPP_CTRL(i));
206 for (i = 0; i < PMU_SIG_REGS; i++)
207 writel(pmu_sig_ctrl[i], PMU_SIG_CTRL(i));
209 writel(pmu_mpp_ctrl, DOVE_PMU_MPP_GENERAL_CTRL);
211 dove_mpp_dump_regs();