• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6.36/arch/arm/mach-orion5x/
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>
17#include "common.h"
18#include "mpp.h"
19
20static int is_5181l(void)
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}
29
30static int is_5182(void)
31{
32	u32 dev;
33	u32 rev;
34
35	orion5x_pcie_id(&dev, &rev);
36
37	return !!(dev == MV88F5182_DEV_ID);
38}
39
40static int is_5281(void)
41{
42	u32 dev;
43	u32 rev;
44
45	orion5x_pcie_id(&dev, &rev);
46
47	return !!(dev == MV88F5281_DEV_ID);
48}
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	/* Initialize gpiolib. */
128	orion_gpio_init();
129
130	while (mode->mpp >= 0) {
131		u32 *reg;
132		int num_type;
133		int shift;
134
135		if (mode->mpp >= 0 && mode->mpp <= 7)
136			reg = &mpp_0_7_ctrl;
137		else if (mode->mpp >= 8 && mode->mpp <= 15)
138			reg = &mpp_8_15_ctrl;
139		else if (mode->mpp >= 16 && mode->mpp <= 19)
140			reg = &mpp_16_19_ctrl;
141		else {
142			printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
143					"(%d)\n", mode->mpp);
144			continue;
145		}
146
147		num_type = determine_type_encoding(mode->mpp, mode->type);
148		if (num_type < 0) {
149			printk(KERN_ERR "orion5x_mpp_conf: invalid MPP "
150					"combination (%d, %d)\n", mode->mpp,
151					mode->type);
152			continue;
153		}
154
155		shift = (mode->mpp & 7) << 2;
156		*reg &= ~(0xf << shift);
157		*reg |= (num_type & 0xf) << shift;
158
159		if (mode->type == MPP_UNUSED && (mode->mpp < 16 || is_5182()))
160			orion_gpio_set_unused(mode->mpp);
161
162		orion_gpio_set_valid(mode->mpp, !!(mode->type == MPP_GPIO));
163
164		mode++;
165	}
166
167	writel(mpp_0_7_ctrl, MPP_0_7_CTRL);
168	writel(mpp_8_15_ctrl, MPP_8_15_CTRL);
169	writel(mpp_16_19_ctrl, MPP_16_19_CTRL);
170}
171