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