diff options
Diffstat (limited to 'arch/arm/mach-mx3/mach-mx31_3ds.c')
-rw-r--r-- | arch/arm/mach-mx3/mach-mx31_3ds.c | 256 |
1 files changed, 68 insertions, 188 deletions
diff --git a/arch/arm/mach-mx3/mach-mx31_3ds.c b/arch/arm/mach-mx3/mach-mx31_3ds.c index 58e57291b79d..6fe69e124d30 100644 --- a/arch/arm/mach-mx3/mach-mx31_3ds.c +++ b/arch/arm/mach-mx3/mach-mx31_3ds.c | |||
@@ -10,10 +10,6 @@ | |||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | * GNU General Public License for more details. | 12 | * GNU General Public License for more details. |
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | 13 | */ |
18 | 14 | ||
19 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
@@ -22,7 +18,6 @@ | |||
22 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
23 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
24 | #include <linux/gpio.h> | 20 | #include <linux/gpio.h> |
25 | #include <linux/smsc911x.h> | ||
26 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
27 | #include <linux/mfd/mc13783.h> | 22 | #include <linux/mfd/mc13783.h> |
28 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
@@ -37,19 +32,47 @@ | |||
37 | #include <asm/memory.h> | 32 | #include <asm/memory.h> |
38 | #include <asm/mach/map.h> | 33 | #include <asm/mach/map.h> |
39 | #include <mach/common.h> | 34 | #include <mach/common.h> |
40 | #include <mach/board-mx31_3ds.h> | ||
41 | #include <mach/imx-uart.h> | ||
42 | #include <mach/iomux-mx3.h> | 35 | #include <mach/iomux-mx3.h> |
43 | #include <mach/mxc_nand.h> | 36 | #include <mach/3ds_debugboard.h> |
44 | #include <mach/spi.h> | 37 | |
38 | #include "devices-imx31.h" | ||
45 | #include "devices.h" | 39 | #include "devices.h" |
46 | 40 | ||
47 | /*! | 41 | /* Definitions for components on the Debug board */ |
48 | * @file mx31_3ds.c | 42 | |
49 | * | 43 | /* Base address of CPLD controller on the Debug board */ |
50 | * @brief This file contains the board-specific initialization routines. | 44 | #define DEBUG_BASE_ADDRESS CS5_IO_ADDRESS(MX3x_CS5_BASE_ADDR) |
51 | * | 45 | |
52 | * @ingroup System | 46 | /* LAN9217 ethernet base address */ |
47 | #define LAN9217_BASE_ADDR MX3x_CS5_BASE_ADDR | ||
48 | |||
49 | /* CPLD config and interrupt base address */ | ||
50 | #define CPLD_ADDR (DEBUG_BASE_ADDRESS + 0x20000) | ||
51 | |||
52 | /* status, interrupt */ | ||
53 | #define CPLD_INT_STATUS_REG (CPLD_ADDR + 0x10) | ||
54 | #define CPLD_INT_MASK_REG (CPLD_ADDR + 0x38) | ||
55 | #define CPLD_INT_RESET_REG (CPLD_ADDR + 0x20) | ||
56 | /* magic word for debug CPLD */ | ||
57 | #define CPLD_MAGIC_NUMBER1_REG (CPLD_ADDR + 0x40) | ||
58 | #define CPLD_MAGIC_NUMBER2_REG (CPLD_ADDR + 0x48) | ||
59 | /* CPLD code version */ | ||
60 | #define CPLD_CODE_VER_REG (CPLD_ADDR + 0x50) | ||
61 | /* magic word for debug CPLD */ | ||
62 | #define CPLD_MAGIC_NUMBER3_REG (CPLD_ADDR + 0x58) | ||
63 | |||
64 | /* CPLD IRQ line for external uart, external ethernet etc */ | ||
65 | #define EXPIO_PARENT_INT IOMUX_TO_IRQ(MX31_PIN_GPIO1_1) | ||
66 | |||
67 | #define MXC_EXP_IO_BASE (MXC_BOARD_IRQ_START) | ||
68 | #define MXC_IRQ_TO_EXPIO(irq) ((irq) - MXC_EXP_IO_BASE) | ||
69 | |||
70 | #define EXPIO_INT_ENET (MXC_EXP_IO_BASE + 0) | ||
71 | |||
72 | #define MXC_MAX_EXP_IO_LINES 16 | ||
73 | |||
74 | /* | ||
75 | * This file contains the board-specific initialization routines. | ||
53 | */ | 76 | */ |
54 | 77 | ||
55 | static int mx31_3ds_pins[] = { | 78 | static int mx31_3ds_pins[] = { |
@@ -145,7 +168,7 @@ static int spi1_internal_chipselect[] = { | |||
145 | MXC_SPI_CS(2), | 168 | MXC_SPI_CS(2), |
146 | }; | 169 | }; |
147 | 170 | ||
148 | static struct spi_imx_master spi1_pdata = { | 171 | static const struct spi_imx_master spi1_pdata __initconst = { |
149 | .chipselect = spi1_internal_chipselect, | 172 | .chipselect = spi1_internal_chipselect, |
150 | .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect), | 173 | .num_chipselect = ARRAY_SIZE(spi1_internal_chipselect), |
151 | }; | 174 | }; |
@@ -165,7 +188,8 @@ static struct spi_board_info mx31_3ds_spi_devs[] __initdata = { | |||
165 | /* | 188 | /* |
166 | * NAND Flash | 189 | * NAND Flash |
167 | */ | 190 | */ |
168 | static struct mxc_nand_platform_data imx31_3ds_nand_flash_pdata = { | 191 | static const struct mxc_nand_platform_data |
192 | mx31_3ds_nand_board_info __initconst = { | ||
169 | .width = 1, | 193 | .width = 1, |
170 | .hw_ecc = 1, | 194 | .hw_ecc = 1, |
171 | #ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT | 195 | #ifdef MACH_MX31_3DS_MXC_NAND_USE_BBT |
@@ -182,8 +206,10 @@ static struct mxc_nand_platform_data imx31_3ds_nand_flash_pdata = { | |||
182 | 206 | ||
183 | #define USBOTG_RST_B IOMUX_TO_GPIO(MX31_PIN_USB_PWR) | 207 | #define USBOTG_RST_B IOMUX_TO_GPIO(MX31_PIN_USB_PWR) |
184 | 208 | ||
185 | static void mx31_3ds_usbotg_init(void) | 209 | static int mx31_3ds_usbotg_init(void) |
186 | { | 210 | { |
211 | int err; | ||
212 | |||
187 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG); | 213 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG); |
188 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG); | 214 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG); |
189 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG); | 215 | mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG); |
@@ -197,10 +223,25 @@ static void mx31_3ds_usbotg_init(void) | |||
197 | mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG); | 223 | mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG); |
198 | mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG); | 224 | mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG); |
199 | 225 | ||
200 | gpio_request(USBOTG_RST_B, "otgusb-reset"); | 226 | err = gpio_request(USBOTG_RST_B, "otgusb-reset"); |
201 | gpio_direction_output(USBOTG_RST_B, 0); | 227 | if (err) { |
228 | pr_err("Failed to request the USB OTG reset gpio\n"); | ||
229 | return err; | ||
230 | } | ||
231 | |||
232 | err = gpio_direction_output(USBOTG_RST_B, 0); | ||
233 | if (err) { | ||
234 | pr_err("Failed to drive the USB OTG reset gpio\n"); | ||
235 | goto usbotg_free_reset; | ||
236 | } | ||
237 | |||
202 | mdelay(1); | 238 | mdelay(1); |
203 | gpio_set_value(USBOTG_RST_B, 1); | 239 | gpio_set_value(USBOTG_RST_B, 1); |
240 | return 0; | ||
241 | |||
242 | usbotg_free_reset: | ||
243 | gpio_free(USBOTG_RST_B); | ||
244 | return err; | ||
204 | } | 245 | } |
205 | 246 | ||
206 | static struct fsl_usb2_platform_data usbotg_pdata = { | 247 | static struct fsl_usb2_platform_data usbotg_pdata = { |
@@ -208,178 +249,16 @@ static struct fsl_usb2_platform_data usbotg_pdata = { | |||
208 | .phy_mode = FSL_USB2_PHY_ULPI, | 249 | .phy_mode = FSL_USB2_PHY_ULPI, |
209 | }; | 250 | }; |
210 | 251 | ||
211 | static struct imxuart_platform_data uart_pdata = { | 252 | static const struct imxuart_platform_data uart_pdata __initconst = { |
212 | .flags = IMXUART_HAVE_RTSCTS, | 253 | .flags = IMXUART_HAVE_RTSCTS, |
213 | }; | 254 | }; |
214 | 255 | ||
215 | /* | 256 | /* |
216 | * Support for the SMSC9217 on the Debug board. | ||
217 | */ | ||
218 | |||
219 | static struct smsc911x_platform_config smsc911x_config = { | ||
220 | .irq_polarity = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, | ||
221 | .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, | ||
222 | .flags = SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY, | ||
223 | .phy_interface = PHY_INTERFACE_MODE_MII, | ||
224 | }; | ||
225 | |||
226 | static struct resource smsc911x_resources[] = { | ||
227 | { | ||
228 | .start = LAN9217_BASE_ADDR, | ||
229 | .end = LAN9217_BASE_ADDR + 0xff, | ||
230 | .flags = IORESOURCE_MEM, | ||
231 | }, { | ||
232 | .start = EXPIO_INT_ENET, | ||
233 | .end = EXPIO_INT_ENET, | ||
234 | .flags = IORESOURCE_IRQ, | ||
235 | }, | ||
236 | }; | ||
237 | |||
238 | static struct platform_device smsc911x_device = { | ||
239 | .name = "smsc911x", | ||
240 | .id = -1, | ||
241 | .num_resources = ARRAY_SIZE(smsc911x_resources), | ||
242 | .resource = smsc911x_resources, | ||
243 | .dev = { | ||
244 | .platform_data = &smsc911x_config, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | /* | ||
249 | * Routines for the CPLD on the debug board. It contains a CPLD handling | ||
250 | * LEDs, switches, interrupts for Ethernet. | ||
251 | */ | ||
252 | |||
253 | static void mx31_3ds_expio_irq_handler(uint32_t irq, struct irq_desc *desc) | ||
254 | { | ||
255 | uint32_t imr_val; | ||
256 | uint32_t int_valid; | ||
257 | uint32_t expio_irq; | ||
258 | |||
259 | imr_val = __raw_readw(CPLD_INT_MASK_REG); | ||
260 | int_valid = __raw_readw(CPLD_INT_STATUS_REG) & ~imr_val; | ||
261 | |||
262 | expio_irq = MXC_EXP_IO_BASE; | ||
263 | for (; int_valid != 0; int_valid >>= 1, expio_irq++) { | ||
264 | if ((int_valid & 1) == 0) | ||
265 | continue; | ||
266 | generic_handle_irq(expio_irq); | ||
267 | } | ||
268 | } | ||
269 | |||
270 | /* | ||
271 | * Disable an expio pin's interrupt by setting the bit in the imr. | ||
272 | * @param irq an expio virtual irq number | ||
273 | */ | ||
274 | static void expio_mask_irq(uint32_t irq) | ||
275 | { | ||
276 | uint16_t reg; | ||
277 | uint32_t expio = MXC_IRQ_TO_EXPIO(irq); | ||
278 | |||
279 | /* mask the interrupt */ | ||
280 | reg = __raw_readw(CPLD_INT_MASK_REG); | ||
281 | reg |= 1 << expio; | ||
282 | __raw_writew(reg, CPLD_INT_MASK_REG); | ||
283 | } | ||
284 | |||
285 | /* | ||
286 | * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr. | ||
287 | * @param irq an expanded io virtual irq number | ||
288 | */ | ||
289 | static void expio_ack_irq(uint32_t irq) | ||
290 | { | ||
291 | uint32_t expio = MXC_IRQ_TO_EXPIO(irq); | ||
292 | |||
293 | /* clear the interrupt status */ | ||
294 | __raw_writew(1 << expio, CPLD_INT_RESET_REG); | ||
295 | __raw_writew(0, CPLD_INT_RESET_REG); | ||
296 | /* mask the interrupt */ | ||
297 | expio_mask_irq(irq); | ||
298 | } | ||
299 | |||
300 | /* | ||
301 | * Enable a expio pin's interrupt by clearing the bit in the imr. | ||
302 | * @param irq a expio virtual irq number | ||
303 | */ | ||
304 | static void expio_unmask_irq(uint32_t irq) | ||
305 | { | ||
306 | uint16_t reg; | ||
307 | uint32_t expio = MXC_IRQ_TO_EXPIO(irq); | ||
308 | |||
309 | /* unmask the interrupt */ | ||
310 | reg = __raw_readw(CPLD_INT_MASK_REG); | ||
311 | reg &= ~(1 << expio); | ||
312 | __raw_writew(reg, CPLD_INT_MASK_REG); | ||
313 | } | ||
314 | |||
315 | static struct irq_chip expio_irq_chip = { | ||
316 | .ack = expio_ack_irq, | ||
317 | .mask = expio_mask_irq, | ||
318 | .unmask = expio_unmask_irq, | ||
319 | }; | ||
320 | |||
321 | static int __init mx31_3ds_init_expio(void) | ||
322 | { | ||
323 | int i; | ||
324 | int ret; | ||
325 | |||
326 | /* Check if there's a debug board connected */ | ||
327 | if ((__raw_readw(CPLD_MAGIC_NUMBER1_REG) != 0xAAAA) || | ||
328 | (__raw_readw(CPLD_MAGIC_NUMBER2_REG) != 0x5555) || | ||
329 | (__raw_readw(CPLD_MAGIC_NUMBER3_REG) != 0xCAFE)) { | ||
330 | /* No Debug board found */ | ||
331 | return -ENODEV; | ||
332 | } | ||
333 | |||
334 | pr_info("i.MX31 3DS Debug board detected, rev = 0x%04X\n", | ||
335 | __raw_readw(CPLD_CODE_VER_REG)); | ||
336 | |||
337 | /* | ||
338 | * Configure INT line as GPIO input | ||
339 | */ | ||
340 | ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1), "sms9217-irq"); | ||
341 | if (ret) | ||
342 | pr_warning("could not get LAN irq gpio\n"); | ||
343 | else | ||
344 | gpio_direction_input(IOMUX_TO_GPIO(MX31_PIN_GPIO1_1)); | ||
345 | |||
346 | /* Disable the interrupts and clear the status */ | ||
347 | __raw_writew(0, CPLD_INT_MASK_REG); | ||
348 | __raw_writew(0xFFFF, CPLD_INT_RESET_REG); | ||
349 | __raw_writew(0, CPLD_INT_RESET_REG); | ||
350 | __raw_writew(0x1F, CPLD_INT_MASK_REG); | ||
351 | for (i = MXC_EXP_IO_BASE; | ||
352 | i < (MXC_EXP_IO_BASE + MXC_MAX_EXP_IO_LINES); | ||
353 | i++) { | ||
354 | set_irq_chip(i, &expio_irq_chip); | ||
355 | set_irq_handler(i, handle_level_irq); | ||
356 | set_irq_flags(i, IRQF_VALID); | ||
357 | } | ||
358 | set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_LOW); | ||
359 | set_irq_chained_handler(EXPIO_PARENT_INT, mx31_3ds_expio_irq_handler); | ||
360 | |||
361 | return 0; | ||
362 | } | ||
363 | |||
364 | /* | ||
365 | * This structure defines the MX31 memory map. | ||
366 | */ | ||
367 | static struct map_desc mx31_3ds_io_desc[] __initdata = { | ||
368 | { | ||
369 | .virtual = MX31_CS5_BASE_ADDR_VIRT, | ||
370 | .pfn = __phys_to_pfn(MX31_CS5_BASE_ADDR), | ||
371 | .length = MX31_CS5_SIZE, | ||
372 | .type = MT_DEVICE, | ||
373 | }, | ||
374 | }; | ||
375 | |||
376 | /* | ||
377 | * Set up static virtual mappings. | 257 | * Set up static virtual mappings. |
378 | */ | 258 | */ |
379 | static void __init mx31_3ds_map_io(void) | 259 | static void __init mx31_3ds_map_io(void) |
380 | { | 260 | { |
381 | mx31_map_io(); | 261 | mx31_map_io(); |
382 | iotable_init(mx31_3ds_io_desc, ARRAY_SIZE(mx31_3ds_io_desc)); | ||
383 | } | 262 | } |
384 | 263 | ||
385 | /*! | 264 | /*! |
@@ -390,10 +269,10 @@ static void __init mxc_board_init(void) | |||
390 | mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins), | 269 | mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins), |
391 | "mx31_3ds"); | 270 | "mx31_3ds"); |
392 | 271 | ||
393 | mxc_register_device(&mxc_uart_device0, &uart_pdata); | 272 | imx31_add_imx_uart0(&uart_pdata); |
394 | mxc_register_device(&mxc_nand_device, &imx31_3ds_nand_flash_pdata); | 273 | imx31_add_mxc_nand(&mx31_3ds_nand_board_info); |
395 | 274 | ||
396 | mxc_register_device(&mxc_spi_device1, &spi1_pdata); | 275 | imx31_add_spi_imx0(&spi1_pdata); |
397 | spi_register_board_info(mx31_3ds_spi_devs, | 276 | spi_register_board_info(mx31_3ds_spi_devs, |
398 | ARRAY_SIZE(mx31_3ds_spi_devs)); | 277 | ARRAY_SIZE(mx31_3ds_spi_devs)); |
399 | 278 | ||
@@ -402,8 +281,9 @@ static void __init mxc_board_init(void) | |||
402 | mx31_3ds_usbotg_init(); | 281 | mx31_3ds_usbotg_init(); |
403 | mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata); | 282 | mxc_register_device(&mxc_otg_udc_device, &usbotg_pdata); |
404 | 283 | ||
405 | if (!mx31_3ds_init_expio()) | 284 | if (!mxc_expio_init(CS5_BASE_ADDR, EXPIO_PARENT_INT)) |
406 | platform_device_register(&smsc911x_device); | 285 | printk(KERN_WARNING "Init of the debugboard failed, all " |
286 | "devices on the board are unusable.\n"); | ||
407 | } | 287 | } |
408 | 288 | ||
409 | static void __init mx31_3ds_timer_init(void) | 289 | static void __init mx31_3ds_timer_init(void) |