xref: /linux/arch/arm/mach-orion5x/mpp.c (revision 19cfd5c09f780ac870fd9d89201c4ebc0b22be81)
1*19cfd5c0SLennert Buytenhek /*
2*19cfd5c0SLennert Buytenhek  * arch/arm/mach-orion5x/mpp.c
3*19cfd5c0SLennert Buytenhek  *
4*19cfd5c0SLennert Buytenhek  * MPP functions for Marvell Orion 5x SoCs
5*19cfd5c0SLennert Buytenhek  *
6*19cfd5c0SLennert Buytenhek  * This file is licensed under the terms of the GNU General Public
7*19cfd5c0SLennert Buytenhek  * License version 2.  This program is licensed "as is" without any
8*19cfd5c0SLennert Buytenhek  * warranty of any kind, whether express or implied.
9*19cfd5c0SLennert Buytenhek  */
10*19cfd5c0SLennert Buytenhek 
11*19cfd5c0SLennert Buytenhek #include <linux/kernel.h>
12*19cfd5c0SLennert Buytenhek #include <linux/init.h>
13*19cfd5c0SLennert Buytenhek #include <linux/mbus.h>
14*19cfd5c0SLennert Buytenhek #include <asm/hardware.h>
15*19cfd5c0SLennert Buytenhek #include <asm/io.h>
16*19cfd5c0SLennert Buytenhek #include "common.h"
17*19cfd5c0SLennert Buytenhek #include "mpp.h"
18*19cfd5c0SLennert Buytenhek 
19*19cfd5c0SLennert Buytenhek static int is_5181l(void)
20*19cfd5c0SLennert Buytenhek {
21*19cfd5c0SLennert Buytenhek 	u32 dev;
22*19cfd5c0SLennert Buytenhek 	u32 rev;
23*19cfd5c0SLennert Buytenhek 
24*19cfd5c0SLennert Buytenhek 	orion5x_pcie_id(&dev, &rev);
25*19cfd5c0SLennert Buytenhek 
26*19cfd5c0SLennert Buytenhek 	return !!(dev == MV88F5181_DEV_ID && rev >= MV88F5181L_REV_A0);
27*19cfd5c0SLennert Buytenhek }
28*19cfd5c0SLennert Buytenhek 
29*19cfd5c0SLennert Buytenhek static int is_5182(void)
30*19cfd5c0SLennert Buytenhek {
31*19cfd5c0SLennert Buytenhek 	u32 dev;
32*19cfd5c0SLennert Buytenhek 	u32 rev;
33*19cfd5c0SLennert Buytenhek 
34*19cfd5c0SLennert Buytenhek 	orion5x_pcie_id(&dev, &rev);
35*19cfd5c0SLennert Buytenhek 
36*19cfd5c0SLennert Buytenhek 	return !!(dev == MV88F5182_DEV_ID);
37*19cfd5c0SLennert Buytenhek }
38*19cfd5c0SLennert Buytenhek 
39*19cfd5c0SLennert Buytenhek static int is_5281(void)
40*19cfd5c0SLennert Buytenhek {
41*19cfd5c0SLennert Buytenhek 	u32 dev;
42*19cfd5c0SLennert Buytenhek 	u32 rev;
43*19cfd5c0SLennert Buytenhek 
44*19cfd5c0SLennert Buytenhek 	orion5x_pcie_id(&dev, &rev);
45*19cfd5c0SLennert Buytenhek 
46*19cfd5c0SLennert Buytenhek 	return !!(dev == MV88F5281_DEV_ID);
47*19cfd5c0SLennert Buytenhek }
48*19cfd5c0SLennert Buytenhek 
49*19cfd5c0SLennert Buytenhek static int __init determine_type_encoding(int mpp, enum orion5x_mpp_type type)
50*19cfd5c0SLennert Buytenhek {
51*19cfd5c0SLennert Buytenhek 	switch (type) {
52*19cfd5c0SLennert Buytenhek 	case MPP_UNUSED:
53*19cfd5c0SLennert Buytenhek 	case MPP_GPIO:
54*19cfd5c0SLennert Buytenhek 		if (mpp == 0)
55*19cfd5c0SLennert Buytenhek 			return 3;
56*19cfd5c0SLennert Buytenhek 		if (mpp >= 1 && mpp <= 15)
57*19cfd5c0SLennert Buytenhek 			return 0;
58*19cfd5c0SLennert Buytenhek 		if (mpp >= 16 && mpp <= 19) {
59*19cfd5c0SLennert Buytenhek 			if (is_5182())
60*19cfd5c0SLennert Buytenhek 				return 5;
61*19cfd5c0SLennert Buytenhek 			if (type == MPP_UNUSED)
62*19cfd5c0SLennert Buytenhek 				return 0;
63*19cfd5c0SLennert Buytenhek 		}
64*19cfd5c0SLennert Buytenhek 		return -1;
65*19cfd5c0SLennert Buytenhek 
66*19cfd5c0SLennert Buytenhek 	case MPP_PCIE_RST_OUTn:
67*19cfd5c0SLennert Buytenhek 		if (mpp == 0)
68*19cfd5c0SLennert Buytenhek 			return 0;
69*19cfd5c0SLennert Buytenhek 		return -1;
70*19cfd5c0SLennert Buytenhek 
71*19cfd5c0SLennert Buytenhek 	case MPP_PCI_ARB:
72*19cfd5c0SLennert Buytenhek 		if (mpp >= 0 && mpp <= 7)
73*19cfd5c0SLennert Buytenhek 			return 2;
74*19cfd5c0SLennert Buytenhek 		return -1;
75*19cfd5c0SLennert Buytenhek 
76*19cfd5c0SLennert Buytenhek 	case MPP_PCI_PMEn:
77*19cfd5c0SLennert Buytenhek 		if (mpp == 2)
78*19cfd5c0SLennert Buytenhek 			return 3;
79*19cfd5c0SLennert Buytenhek 		return -1;
80*19cfd5c0SLennert Buytenhek 
81*19cfd5c0SLennert Buytenhek 	case MPP_GIGE:
82*19cfd5c0SLennert Buytenhek 		if (mpp >= 8 && mpp <= 19)
83*19cfd5c0SLennert Buytenhek 			return 1;
84*19cfd5c0SLennert Buytenhek 		return -1;
85*19cfd5c0SLennert Buytenhek 
86*19cfd5c0SLennert Buytenhek 	case MPP_NAND:
87*19cfd5c0SLennert Buytenhek 		if (is_5182() || is_5281()) {
88*19cfd5c0SLennert Buytenhek 			if (mpp >= 4 && mpp <= 7)
89*19cfd5c0SLennert Buytenhek 				return 4;
90*19cfd5c0SLennert Buytenhek 			if (mpp >= 12 && mpp <= 17)
91*19cfd5c0SLennert Buytenhek 				return 4;
92*19cfd5c0SLennert Buytenhek 		}
93*19cfd5c0SLennert Buytenhek 		return -1;
94*19cfd5c0SLennert Buytenhek 
95*19cfd5c0SLennert Buytenhek 	case MPP_PCI_CLK:
96*19cfd5c0SLennert Buytenhek 		if (is_5181l() && mpp >= 6 && mpp <= 7)
97*19cfd5c0SLennert Buytenhek 			return 5;
98*19cfd5c0SLennert Buytenhek 		return -1;
99*19cfd5c0SLennert Buytenhek 
100*19cfd5c0SLennert Buytenhek 	case MPP_SATA_LED:
101*19cfd5c0SLennert Buytenhek 		if (is_5182()) {
102*19cfd5c0SLennert Buytenhek 			if (mpp >= 4 && mpp <= 7)
103*19cfd5c0SLennert Buytenhek 				return 5;
104*19cfd5c0SLennert Buytenhek 			if (mpp >= 12 && mpp <= 15)
105*19cfd5c0SLennert Buytenhek 				return 5;
106*19cfd5c0SLennert Buytenhek 		}
107*19cfd5c0SLennert Buytenhek 		return -1;
108*19cfd5c0SLennert Buytenhek 
109*19cfd5c0SLennert Buytenhek 	case MPP_UART:
110*19cfd5c0SLennert Buytenhek 		if (mpp >= 16 && mpp <= 19)
111*19cfd5c0SLennert Buytenhek 			return 0;
112*19cfd5c0SLennert Buytenhek 		return -1;
113*19cfd5c0SLennert Buytenhek 	}
114*19cfd5c0SLennert Buytenhek 
115*19cfd5c0SLennert Buytenhek 	printk(KERN_INFO "unknown MPP type %d\n", type);
116*19cfd5c0SLennert Buytenhek 
117*19cfd5c0SLennert Buytenhek 	return -1;
118*19cfd5c0SLennert Buytenhek }
119*19cfd5c0SLennert Buytenhek 
120*19cfd5c0SLennert Buytenhek void __init orion5x_mpp_conf(struct orion5x_mpp_mode *mode)
121*19cfd5c0SLennert Buytenhek {
122*19cfd5c0SLennert Buytenhek 	u32 mpp_0_7_ctrl = readl(MPP_0_7_CTRL);
123*19cfd5c0SLennert Buytenhek 	u32 mpp_8_15_ctrl = readl(MPP_8_15_CTRL);
124*19cfd5c0SLennert Buytenhek 	u32 mpp_16_19_ctrl = readl(MPP_16_19_CTRL);
125*19cfd5c0SLennert Buytenhek 
126*19cfd5c0SLennert Buytenhek 	while (mode->mpp >= 0) {
127*19cfd5c0SLennert Buytenhek 		u32 *reg;
128*19cfd5c0SLennert Buytenhek 		int num_type;
129*19cfd5c0SLennert Buytenhek 		int shift;
130*19cfd5c0SLennert Buytenhek 
131*19cfd5c0SLennert Buytenhek 		if (mode->mpp >= 0 && mode->mpp <= 7)
132*19cfd5c0SLennert Buytenhek 			reg = &mpp_0_7_ctrl;
133*19cfd5c0SLennert Buytenhek 		else if (mode->mpp >= 8 && mode->mpp <= 15)
134*19cfd5c0SLennert Buytenhek 			reg = &mpp_8_15_ctrl;
135*19cfd5c0SLennert Buytenhek 		else if (mode->mpp >= 16 && mode->mpp <= 19)
136*19cfd5c0SLennert Buytenhek 			reg = &mpp_16_19_ctrl;
137*19cfd5c0SLennert Buytenhek 		else {
138*19cfd5c0SLennert Buytenhek 			printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
139*19cfd5c0SLennert Buytenhek 					"(%d)\n", mode->mpp);
140*19cfd5c0SLennert Buytenhek 			continue;
141*19cfd5c0SLennert Buytenhek 		}
142*19cfd5c0SLennert Buytenhek 
143*19cfd5c0SLennert Buytenhek 		num_type = determine_type_encoding(mode->mpp, mode->type);
144*19cfd5c0SLennert Buytenhek 		if (num_type < 0) {
145*19cfd5c0SLennert Buytenhek 			printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
146*19cfd5c0SLennert Buytenhek 					"combination (%d, %d)\n", mode->mpp,
147*19cfd5c0SLennert Buytenhek 					mode->type);
148*19cfd5c0SLennert Buytenhek 			continue;
149*19cfd5c0SLennert Buytenhek 		}
150*19cfd5c0SLennert Buytenhek 
151*19cfd5c0SLennert Buytenhek 		shift = (mode->mpp & 7) << 2;
152*19cfd5c0SLennert Buytenhek 		*reg &= ~(0xf << shift);
153*19cfd5c0SLennert Buytenhek 		*reg |= (num_type & 0xf) << shift;
154*19cfd5c0SLennert Buytenhek 
155*19cfd5c0SLennert Buytenhek 		orion5x_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
156*19cfd5c0SLennert Buytenhek 
157*19cfd5c0SLennert Buytenhek 		mode++;
158*19cfd5c0SLennert Buytenhek 	}
159*19cfd5c0SLennert Buytenhek 
160*19cfd5c0SLennert Buytenhek 	writel(mpp_0_7_ctrl, MPP_0_7_CTRL);
161*19cfd5c0SLennert Buytenhek 	writel(mpp_8_15_ctrl, MPP_8_15_CTRL);
162*19cfd5c0SLennert Buytenhek 	writel(mpp_16_19_ctrl, MPP_16_19_CTRL);
163*19cfd5c0SLennert Buytenhek }
164