xref: /OK3568_Linux_fs/kernel/arch/arm/mach-dove/mpp.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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