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.
11 #include <linux/kernel.h>
12 #include <linux/gpio.h>
15 #include <mach/dove.h>
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)
31 static struct dove_mpp_grp dove_mpp_grp[] = {
54 static void dove_mpp_gpio_mode(int start, int end, int gpio_mode)
58 for (i = start; i <= end; i++)
59 orion_gpio_set_valid(i, gpio_mode);
62 static void dove_mpp_dump_regs(void)
67 pr_debug("MPP_CTRL regs:");
68 for (i = 0; i < MPP_NR_REGS; i++)
69 printk(" %08x", readl(MPP_CTRL(i)));
72 pr_debug("PMU_SIG_CTRL regs:");
73 for (i = 0; i < PMU_SIG_REGS; i++)
74 printk(" %08x", readl(PMU_SIG_CTRL(i)));
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));
82 static void dove_mpp_cfg_nfc(int sel)
84 u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
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);
108 dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
111 global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
112 dove_mpp_gpio_mode(56, 57, 0);
115 mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
116 dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
119 ssp_ctrl1 |= DOVE_SSP_ON_AU1;
120 dove_mpp_gpio_mode(52, 55, 0);
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];
150 /* Initialize gpiolib. */
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;
169 pr_err("dove: invalid MPP number (%u)\n", num);
173 if (*mpp_list & MPP_NFC_MASK) {
174 dove_mpp_cfg_nfc(sel);
178 if (*mpp_list & MPP_AU1_MASK) {
179 dove_mpp_cfg_au1(sel);
183 if (*mpp_list & MPP_GRP_MASK) {
184 dove_mpp_conf_grp(num, sel, &mpp_ctrl[3]);
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;
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();