aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm
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
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')
-rw-r--r--arch/arm/mach-mx3/mx31pdk.c150
-rw-r--r--arch/arm/plat-mxc/include/mach/board-mx31pdk.h45
-rw-r--r--arch/arm/plat-mxc/include/mach/mx3x.h6
3 files changed, 199 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,
diff --git a/arch/arm/plat-mxc/include/mach/board-mx31pdk.h b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h
index b1e6463f41af..519bab3eb28b 100644
--- a/arch/arm/plat-mxc/include/mach/board-mx31pdk.h
+++ b/arch/arm/plat-mxc/include/mach/board-mx31pdk.h
@@ -16,4 +16,49 @@
16#define MXC_LL_UART_PADDR UART1_BASE_ADDR 16#define MXC_LL_UART_PADDR UART1_BASE_ADDR
17#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR) 17#define MXC_LL_UART_VADDR AIPS1_IO_ADDRESS(UART1_BASE_ADDR)
18 18
19/* Definitions for components on the Debug board */
20
21/* Base address of CPLD controller on the Debug board */
22#define DEBUG_BASE_ADDRESS CS5_IO_ADDRESS(CS5_BASE_ADDR)
23
24/* LAN9217 ethernet base address */
25#define LAN9217_BASE_ADDR CS5_BASE_ADDR
26
27/* CPLD config and interrupt base address */
28#define CPLD_ADDR (DEBUG_BASE_ADDRESS + 0x20000)
29
30/* LED switchs */
31#define CPLD_LED_REG (CPLD_ADDR + 0x00)
32/* buttons */
33#define CPLD_SWITCH_BUTTONS_REG (EXPIO_ADDR + 0x08)
34/* status, interrupt */
35#define CPLD_INT_STATUS_REG (CPLD_ADDR + 0x10)
36#define CPLD_INT_MASK_REG (CPLD_ADDR + 0x38)
37#define CPLD_INT_RESET_REG (CPLD_ADDR + 0x20)
38/* magic word for debug CPLD */
39#define CPLD_MAGIC_NUMBER1_REG (CPLD_ADDR + 0x40)
40#define CPLD_MAGIC_NUMBER2_REG (CPLD_ADDR + 0x48)
41/* CPLD code version */
42#define CPLD_CODE_VER_REG (CPLD_ADDR + 0x50)
43/* magic word for debug CPLD */
44#define CPLD_MAGIC_NUMBER3_REG (CPLD_ADDR + 0x58)
45/* module reset register */
46#define CPLD_MODULE_RESET_REG (CPLD_ADDR + 0x60)
47/* CPU ID and Personality ID */
48#define CPLD_MCU_BOARD_ID_REG (CPLD_ADDR + 0x68)
49
50/* CPLD IRQ line for external uart, external ethernet etc */
51#define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
52
53#define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START)
54#define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE)
55
56#define EXPIO_INT_ENET (MXC_EXP_IO_BASE + 0)
57#define EXPIO_INT_XUART_A (MXC_EXP_IO_BASE + 1)
58#define EXPIO_INT_XUART_B (MXC_EXP_IO_BASE + 2)
59#define EXPIO_INT_BUTTON_A (MXC_EXP_IO_BASE + 3)
60#define EXPIO_INT_BUTTON_B (MXC_EXP_IO_BASE + 4)
61
62#define MXC_MAX_EXP_IO_LINES 16
63
19#endif /* __ASM_ARCH_MXC_BOARD_MX31PDK_H__ */ 64#endif /* __ASM_ARCH_MXC_BOARD_MX31PDK_H__ */
diff --git a/arch/arm/plat-mxc/include/mach/mx3x.h b/arch/arm/plat-mxc/include/mach/mx3x.h
index 3878c6085d5c..b559a4bb5769 100644
--- a/arch/arm/plat-mxc/include/mach/mx3x.h
+++ b/arch/arm/plat-mxc/include/mach/mx3x.h
@@ -48,6 +48,9 @@
48#define CS4_SIZE SZ_32M 48#define CS4_SIZE SZ_32M
49 49
50#define CS5_BASE_ADDR 0xB6000000 50#define CS5_BASE_ADDR 0xB6000000
51#define CS5_BASE_ADDR_VIRT 0xF6000000
52#define CS5_SIZE SZ_32M
53
51#define PCMCIA_MEM_BASE_ADDR 0xBC000000 54#define PCMCIA_MEM_BASE_ADDR 0xBC000000
52 55
53/* 56/*
@@ -191,6 +194,9 @@
191#define CS4_IO_ADDRESS(x) \ 194#define CS4_IO_ADDRESS(x) \
192 (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT) 195 (((x) - CS4_BASE_ADDR) + CS4_BASE_ADDR_VIRT)
193 196
197#define CS5_IO_ADDRESS(x) \
198 (((x) - CS5_BASE_ADDR) + CS5_BASE_ADDR_VIRT)
199
194#define X_MEMC_IO_ADDRESS(x) \ 200#define X_MEMC_IO_ADDRESS(x) \
195 (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT) 201 (((x) - X_MEMC_BASE_ADDR) + X_MEMC_BASE_ADDR_VIRT)
196 202