aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx3/mx31pdk.c
diff options
context:
space:
mode:
authorMagnus Lilja <lilja.magnus@gmail.com>2009-05-17 14:18:08 -0400
committerSascha Hauer <s.hauer@pengutronix.de>2009-05-18 02:36:27 -0400
commit135cad366b4e7d6a79f6369f6cb5b721985aa62f (patch)
treea0494359f38c4f9592821db0d0c3167506249c86 /arch/arm/mach-mx3/mx31pdk.c
parent2eec8c318b9bbfe9e0f2a889b4ad3f4b4e5ba429 (diff)
i.MX31: Add support for the CPLD on PDK Debug board.
The i.MX31 PDK consists of several boards, one of them is a debug board containing a CPLD which controls some debug leds, switch buttons, an interrupt chip and an Ethernet controller. This patch adds support for detecting if the PDK board is present (during boot) and adds the interrupt chip to the kernel. Signed-off-by: Magnus Lilja <lilja.magnus@gmail.com> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-mx3/mx31pdk.c')
-rw-r--r--arch/arm/mach-mx3/mx31pdk.c150
1 files changed, 148 insertions, 2 deletions
diff --git a/arch/arm/mach-mx3/mx31pdk.c b/arch/arm/mach-mx3/mx31pdk.c
index 5345498aeff3..32599e507534 100644
--- a/arch/arm/mach-mx3/mx31pdk.c
+++ b/arch/arm/mach-mx3/mx31pdk.c
@@ -20,6 +20,7 @@
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/clk.h> 21#include <linux/clk.h>
22#include <linux/irq.h> 22#include <linux/irq.h>
23#include <linux/gpio.h>
23 24
24#include <mach/hardware.h> 25#include <mach/hardware.h>
25#include <asm/mach-types.h> 26#include <asm/mach-types.h>
@@ -46,13 +47,156 @@ static int mx31pdk_pins[] = {
46 MX31_PIN_CTS1__CTS1, 47 MX31_PIN_CTS1__CTS1,
47 MX31_PIN_RTS1__RTS1, 48 MX31_PIN_RTS1__RTS1,
48 MX31_PIN_TXD1__TXD1, 49 MX31_PIN_TXD1__TXD1,
49 MX31_PIN_RXD1__RXD1 50 MX31_PIN_RXD1__RXD1,
51 IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
50}; 52};
51 53
52static struct imxuart_platform_data uart_pdata = { 54static struct imxuart_platform_data uart_pdata = {
53 .flags = IMXUART_HAVE_RTSCTS, 55 .flags = IMXUART_HAVE_RTSCTS,
54}; 56};
55 57
58/*
59 * Routines for the CPLD on the debug board. It contains a CPLD handling
60 * LEDs, switches, interrupts for Ethernet.
61 */
62
63static void mx31pdk_expio_irq_handler(uint32_t irq, struct irq_desc *desc)
64{
65 uint32_t imr_val;
66 uint32_t int_valid;
67 uint32_t expio_irq;
68
69 imr_val = __raw_readw(CPLD_INT_MASK_REG);
70 int_valid = __raw_readw(CPLD_INT_STATUS_REG) & ~imr_val;
71
72 expio_irq = MXC_EXP_IO_BASE;
73 for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
74 if ((int_valid & 1) == 0)
75 continue;
76 generic_handle_irq(expio_irq);
77 }
78}
79
80/*
81 * Disable an expio pin's interrupt by setting the bit in the imr.
82 * @param irq an expio virtual irq number
83 */
84static void expio_mask_irq(uint32_t irq)
85{
86 uint16_t reg;
87 uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
88
89 /* mask the interrupt */
90 reg = __raw_readw(CPLD_INT_MASK_REG);
91 reg |= 1 << expio;
92 __raw_writew(reg, CPLD_INT_MASK_REG);
93}
94
95/*
96 * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
97 * @param irq an expanded io virtual irq number
98 */
99static void expio_ack_irq(uint32_t irq)
100{
101 uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
102
103 /* clear the interrupt status */
104 __raw_writew(1 << expio, CPLD_INT_RESET_REG);
105 __raw_writew(0, CPLD_INT_RESET_REG);
106 /* mask the interrupt */
107 expio_mask_irq(irq);
108}
109
110/*
111 * Enable a expio pin's interrupt by clearing the bit in the imr.
112 * @param irq a expio virtual irq number
113 */
114static void expio_unmask_irq(uint32_t irq)
115{
116 uint16_t reg;
117 uint32_t expio = MXC_IRQ_TO_EXPIO(irq);
118
119 /* unmask the interrupt */
120 reg = __raw_readw(CPLD_INT_MASK_REG);
121 reg &= ~(1 << expio);
122 __raw_writew(reg, CPLD_INT_MASK_REG);
123}
124
125static struct irq_chip expio_irq_chip = {
126 .ack = expio_ack_irq,
127 .mask = expio_mask_irq,
128 .unmask = expio_unmask_irq,
129};
130
131static int __init mx31pdk_init_expio(void)
132{
133 int i;
134 int ret;
135
136 /* Check if there's a debug board connected */
137 if ((__raw_readw(CPLD_MAGIC_NUMBER1_REG) != 0xAAAA) ||
138 (__raw_readw(CPLD_MAGIC_NUMBER2_REG) != 0x5555) ||
139 (__raw_readw(CPLD_MAGIC_NUMBER3_REG) != 0xCAFE)) {
140 /* No Debug board found */
141 return -ENODEV;
142 }
143
144 pr_info("i.MX31PDK Debug board detected, rev = 0x%04X\n",
145 __raw_readw(CPLD_CODE_VER_REG));
146
147 /*
148 * Configure INT line as GPIO input
149 */
150 ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "sms9217-irq");
151 if (ret)
152 pr_warning("could not get LAN irq gpio\n");
153 else
154 gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1));
155
156 /* Disable the interrupts and clear the status */
157 __raw_writew(0, CPLD_INT_MASK_REG);
158 __raw_writew(0xFFFF, CPLD_INT_RESET_REG);
159 __raw_writew(0, CPLD_INT_RESET_REG);
160 __raw_writew(0x1F, CPLD_INT_MASK_REG);
161 for (i = MXC_EXP_IO_BASE;
162 i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES);
163 i++) {
164 set_irq_chip(i, &expio_irq_chip);
165 set_irq_handler(i, handle_level_irq);
166 set_irq_flags(i, IRQF_VALID);
167 }
168 set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW);
169 set_irq_chained_handler(EXPIO_PARENT_INT, mx31pdk_expio_irq_handler);
170
171 return 0;
172}
173
174/*
175 * This structure defines the MX31 memory map.
176 */
177static struct map_desc mx31pdk_io_desc[] __initdata = {
178 {
179 .virtual = SPBA0_BASE_ADDR_VIRT,
180 .pfn = __phys_to_pfn(SPBA0_BASE_ADDR),
181 .length = SPBA0_SIZE,
182 .type = MT_DEVICE_NONSHARED,
183 }, {
184 .virtual = CS5_BASE_ADDR_VIRT,
185 .pfn = __phys_to_pfn(CS5_BASE_ADDR),
186 .length = CS5_SIZE,
187 .type = MT_DEVICE,
188 },
189};
190
191/*
192 * Set up static virtual mappings.
193 */
194static void __init mx31pdk_map_io(void)
195{
196 mx31_map_io();
197 iotable_init(mx31pdk_io_desc, ARRAY_SIZE(mx31pdk_io_desc));
198}
199
56/*! 200/*!
57 * Board specific initialization. 201 * Board specific initialization.
58 */ 202 */
@@ -62,6 +206,8 @@ static void __init mxc_board_init(void)
62 "mx31pdk"); 206 "mx31pdk");
63 207
64 mxc_register_device(&mxc_uart_device0, &uart_pdata); 208 mxc_register_device(&mxc_uart_device0, &uart_pdata);
209
210 mx31pdk_init_expio();
65} 211}
66 212
67static void __init mx31pdk_timer_init(void) 213static void __init mx31pdk_timer_init(void)
@@ -82,7 +228,7 @@ MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
82 .phys_io = AIPS1_BASE_ADDR, 228 .phys_io = AIPS1_BASE_ADDR,
83 .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc, 229 .io_pg_offst = ((AIPS1_BASE_ADDR_VIRT) >> 18) & 0xfffc,
84 .boot_params = PHYS_OFFSET + 0x100, 230 .boot_params = PHYS_OFFSET + 0x100,
85 .map_io = mx31_map_io, 231 .map_io = mx31pdk_map_io,
86 .init_irq = mxc_init_irq, 232 .init_irq = mxc_init_irq,
87 .init_machine = mxc_board_init, 233 .init_machine = mxc_board_init,
88 .timer = &mx31pdk_timer, 234 .timer = &mx31pdk_timer,