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 58e57291b79..6fe69e124d3 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) |
