1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * arch/arm/mach-dove/mpp.c
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * MPP functions for Marvell Dove SoCs
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * This file is licensed under the terms of the GNU General Public
7*4882a593Smuzhiyun * License version 2. This program is licensed "as is" without any
8*4882a593Smuzhiyun * warranty of any kind, whether express or implied.
9*4882a593Smuzhiyun */
10*4882a593Smuzhiyun
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/gpio.h>
13*4882a593Smuzhiyun #include <linux/io.h>
14*4882a593Smuzhiyun #include <plat/mpp.h>
15*4882a593Smuzhiyun #include <plat/orion-gpio.h>
16*4882a593Smuzhiyun #include "dove.h"
17*4882a593Smuzhiyun #include "mpp.h"
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun struct dove_mpp_grp {
20*4882a593Smuzhiyun int start;
21*4882a593Smuzhiyun int end;
22*4882a593Smuzhiyun };
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun /* Map a group to a range of GPIO pins in that group */
25*4882a593Smuzhiyun static const struct dove_mpp_grp dove_mpp_grp[] = {
26*4882a593Smuzhiyun [MPP_24_39] = {
27*4882a593Smuzhiyun .start = 24,
28*4882a593Smuzhiyun .end = 39,
29*4882a593Smuzhiyun },
30*4882a593Smuzhiyun [MPP_40_45] = {
31*4882a593Smuzhiyun .start = 40,
32*4882a593Smuzhiyun .end = 45,
33*4882a593Smuzhiyun },
34*4882a593Smuzhiyun [MPP_46_51] = {
35*4882a593Smuzhiyun .start = 46,
36*4882a593Smuzhiyun .end = 51,
37*4882a593Smuzhiyun },
38*4882a593Smuzhiyun [MPP_58_61] = {
39*4882a593Smuzhiyun .start = 58,
40*4882a593Smuzhiyun .end = 61,
41*4882a593Smuzhiyun },
42*4882a593Smuzhiyun [MPP_62_63] = {
43*4882a593Smuzhiyun .start = 62,
44*4882a593Smuzhiyun .end = 63,
45*4882a593Smuzhiyun },
46*4882a593Smuzhiyun };
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun /* Enable gpio for a range of pins. mode should be a combination of
49*4882a593Smuzhiyun GPIO_OUTPUT_OK | GPIO_INPUT_OK */
dove_mpp_gpio_mode(int start,int end,int gpio_mode)50*4882a593Smuzhiyun static void __init dove_mpp_gpio_mode(int start, int end, int gpio_mode)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun int i;
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun for (i = start; i <= end; i++)
55*4882a593Smuzhiyun orion_gpio_set_valid(i, gpio_mode);
56*4882a593Smuzhiyun }
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun /* Dump all the extra MPP registers. The platform code will dump the
59*4882a593Smuzhiyun registers for pins 0-23. */
dove_mpp_dump_regs(void)60*4882a593Smuzhiyun static void __init dove_mpp_dump_regs(void)
61*4882a593Smuzhiyun {
62*4882a593Smuzhiyun pr_debug("PMU_CTRL4_CTRL: %08x\n",
63*4882a593Smuzhiyun readl(DOVE_MPP_CTRL4_VIRT_BASE));
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun pr_debug("PMU_MPP_GENERAL_CTRL: %08x\n",
66*4882a593Smuzhiyun readl(DOVE_PMU_MPP_GENERAL_CTRL));
67*4882a593Smuzhiyun
68*4882a593Smuzhiyun pr_debug("MPP_GENERAL: %08x\n", readl(DOVE_MPP_GENERAL_VIRT_BASE));
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun
dove_mpp_cfg_nfc(int sel)71*4882a593Smuzhiyun static void __init dove_mpp_cfg_nfc(int sel)
72*4882a593Smuzhiyun {
73*4882a593Smuzhiyun u32 mpp_gen_cfg = readl(DOVE_MPP_GENERAL_VIRT_BASE);
74*4882a593Smuzhiyun
75*4882a593Smuzhiyun mpp_gen_cfg &= ~0x1;
76*4882a593Smuzhiyun mpp_gen_cfg |= sel;
77*4882a593Smuzhiyun writel(mpp_gen_cfg, DOVE_MPP_GENERAL_VIRT_BASE);
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun dove_mpp_gpio_mode(64, 71, GPIO_OUTPUT_OK);
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
dove_mpp_cfg_au1(int sel)82*4882a593Smuzhiyun static void __init dove_mpp_cfg_au1(int sel)
83*4882a593Smuzhiyun {
84*4882a593Smuzhiyun u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
85*4882a593Smuzhiyun u32 ssp_ctrl1 = readl(DOVE_SSP_CTRL_STATUS_1);
86*4882a593Smuzhiyun u32 mpp_gen_ctrl = readl(DOVE_MPP_GENERAL_VIRT_BASE);
87*4882a593Smuzhiyun u32 global_cfg_2 = readl(DOVE_GLOBAL_CONFIG_2);
88*4882a593Smuzhiyun
89*4882a593Smuzhiyun mpp_ctrl4 &= ~(DOVE_AU1_GPIO_SEL);
90*4882a593Smuzhiyun ssp_ctrl1 &= ~(DOVE_SSP_ON_AU1);
91*4882a593Smuzhiyun mpp_gen_ctrl &= ~(DOVE_AU1_SPDIFO_GPIO_EN);
92*4882a593Smuzhiyun global_cfg_2 &= ~(DOVE_TWSI_OPTION3_GPIO);
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (!sel || sel == 0x2)
95*4882a593Smuzhiyun dove_mpp_gpio_mode(52, 57, 0);
96*4882a593Smuzhiyun else
97*4882a593Smuzhiyun dove_mpp_gpio_mode(52, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun if (sel & 0x1) {
100*4882a593Smuzhiyun global_cfg_2 |= DOVE_TWSI_OPTION3_GPIO;
101*4882a593Smuzhiyun dove_mpp_gpio_mode(56, 57, 0);
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun if (sel & 0x2) {
104*4882a593Smuzhiyun mpp_gen_ctrl |= DOVE_AU1_SPDIFO_GPIO_EN;
105*4882a593Smuzhiyun dove_mpp_gpio_mode(57, 57, GPIO_OUTPUT_OK | GPIO_INPUT_OK);
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun if (sel & 0x4) {
108*4882a593Smuzhiyun ssp_ctrl1 |= DOVE_SSP_ON_AU1;
109*4882a593Smuzhiyun dove_mpp_gpio_mode(52, 55, 0);
110*4882a593Smuzhiyun }
111*4882a593Smuzhiyun if (sel & 0x8)
112*4882a593Smuzhiyun mpp_ctrl4 |= DOVE_AU1_GPIO_SEL;
113*4882a593Smuzhiyun
114*4882a593Smuzhiyun writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
115*4882a593Smuzhiyun writel(ssp_ctrl1, DOVE_SSP_CTRL_STATUS_1);
116*4882a593Smuzhiyun writel(mpp_gen_ctrl, DOVE_MPP_GENERAL_VIRT_BASE);
117*4882a593Smuzhiyun writel(global_cfg_2, DOVE_GLOBAL_CONFIG_2);
118*4882a593Smuzhiyun }
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun /* Configure the group registers, enabling GPIO if sel indicates the
121*4882a593Smuzhiyun pin is to be used for GPIO */
dove_mpp_conf_grp(unsigned int * mpp_grp_list)122*4882a593Smuzhiyun static void __init dove_mpp_conf_grp(unsigned int *mpp_grp_list)
123*4882a593Smuzhiyun {
124*4882a593Smuzhiyun u32 mpp_ctrl4 = readl(DOVE_MPP_CTRL4_VIRT_BASE);
125*4882a593Smuzhiyun int gpio_mode;
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun for ( ; *mpp_grp_list; mpp_grp_list++) {
128*4882a593Smuzhiyun unsigned int num = MPP_NUM(*mpp_grp_list);
129*4882a593Smuzhiyun unsigned int sel = MPP_SEL(*mpp_grp_list);
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun if (num > MPP_GRP_MAX) {
132*4882a593Smuzhiyun pr_err("dove: invalid MPP GRP number (%u)\n", num);
133*4882a593Smuzhiyun continue;
134*4882a593Smuzhiyun }
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun mpp_ctrl4 &= ~(0x1 << num);
137*4882a593Smuzhiyun mpp_ctrl4 |= sel << num;
138*4882a593Smuzhiyun
139*4882a593Smuzhiyun gpio_mode = sel ? GPIO_OUTPUT_OK | GPIO_INPUT_OK : 0;
140*4882a593Smuzhiyun dove_mpp_gpio_mode(dove_mpp_grp[num].start,
141*4882a593Smuzhiyun dove_mpp_grp[num].end, gpio_mode);
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun writel(mpp_ctrl4, DOVE_MPP_CTRL4_VIRT_BASE);
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun /* Configure the various MPP pins on Dove */
dove_mpp_conf(unsigned int * mpp_list,unsigned int * mpp_grp_list,unsigned int grp_au1_52_57,unsigned int grp_nfc_64_71)147*4882a593Smuzhiyun void __init dove_mpp_conf(unsigned int *mpp_list,
148*4882a593Smuzhiyun unsigned int *mpp_grp_list,
149*4882a593Smuzhiyun unsigned int grp_au1_52_57,
150*4882a593Smuzhiyun unsigned int grp_nfc_64_71)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun dove_mpp_dump_regs();
153*4882a593Smuzhiyun
154*4882a593Smuzhiyun /* Use platform code for pins 0-23 */
155*4882a593Smuzhiyun orion_mpp_conf(mpp_list, 0, MPP_MAX, DOVE_MPP_VIRT_BASE);
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun dove_mpp_conf_grp(mpp_grp_list);
158*4882a593Smuzhiyun dove_mpp_cfg_au1(grp_au1_52_57);
159*4882a593Smuzhiyun dove_mpp_cfg_nfc(grp_nfc_64_71);
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun dove_mpp_dump_regs();
162*4882a593Smuzhiyun }
163