51c62982a3
Considering the header mess ATM, it is not always possible to include the correct header files within board code. Let's keep this simple: <mach/pxa25x.h> - for pxa25x based platforms <mach/pxa27x.h> - for pxa27x based platforms <mach/pxa300.h> - for pxa300 based platforms <mach/pxa320.h> - for pxa320 based platforms <mach/pxa930.h> - for pxa930 based platforms NOTE: 1. one header one board file, they are not compatible (i.e. they have conflicting definitions which won't compile if included together). 2. Unless strictly necessary, the following header files are considered to be SoC files use _only_, and is not recommended to be included in board code: <mach/hardware.h> <mach/pxa-regs.h> <mach/pxa2xx-regs.h> <mach/pxa3xx-regs.h> <mach/mfp.h> <mach/mfp-pxa2xx.h> <mach/mfp-pxa25x.h> <mach/mfp-pxa27x.h> <mach/mfp-pxa3xx.h> <mach/mfp-pxa300.h> <mach/mfp-pxa320.h> <mach/mfp-pxa930.h> Signed-off-by: Eric Miao <eric.miao@marvell.com>
467 lines
10 KiB
C
467 lines
10 KiB
C
/*
|
|
* linux/arch/arm/mach-pxa/cm-x300.c
|
|
*
|
|
* Support for the CompuLab CM-X300 modules
|
|
*
|
|
* Copyright (C) 2008 CompuLab Ltd.
|
|
*
|
|
* Mike Rapoport <mike@compulab.co.il>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/init.h>
|
|
#include <linux/platform_device.h>
|
|
|
|
#include <linux/gpio.h>
|
|
#include <linux/dm9000.h>
|
|
#include <linux/leds.h>
|
|
|
|
#include <linux/i2c.h>
|
|
#include <linux/i2c/pca953x.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
|
|
#include <mach/pxa300.h>
|
|
#include <mach/pxafb.h>
|
|
#include <mach/mmc.h>
|
|
#include <mach/ohci.h>
|
|
#include <mach/i2c.h>
|
|
#include <mach/pxa3xx_nand.h>
|
|
|
|
#include <asm/mach/map.h>
|
|
|
|
#include "generic.h"
|
|
|
|
#define CM_X300_ETH_PHYS 0x08000010
|
|
|
|
#define GPIO82_MMC2_IRQ (82)
|
|
#define GPIO85_MMC2_WP (85)
|
|
|
|
#define CM_X300_MMC2_IRQ IRQ_GPIO(GPIO82_MMC2_IRQ)
|
|
|
|
static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = {
|
|
/* LCD */
|
|
GPIO54_LCD_LDD_0,
|
|
GPIO55_LCD_LDD_1,
|
|
GPIO56_LCD_LDD_2,
|
|
GPIO57_LCD_LDD_3,
|
|
GPIO58_LCD_LDD_4,
|
|
GPIO59_LCD_LDD_5,
|
|
GPIO60_LCD_LDD_6,
|
|
GPIO61_LCD_LDD_7,
|
|
GPIO62_LCD_LDD_8,
|
|
GPIO63_LCD_LDD_9,
|
|
GPIO64_LCD_LDD_10,
|
|
GPIO65_LCD_LDD_11,
|
|
GPIO66_LCD_LDD_12,
|
|
GPIO67_LCD_LDD_13,
|
|
GPIO68_LCD_LDD_14,
|
|
GPIO69_LCD_LDD_15,
|
|
GPIO72_LCD_FCLK,
|
|
GPIO73_LCD_LCLK,
|
|
GPIO74_LCD_PCLK,
|
|
GPIO75_LCD_BIAS,
|
|
|
|
/* BTUART */
|
|
GPIO111_UART2_RTS,
|
|
GPIO112_UART2_RXD | MFP_LPM_EDGE_FALL,
|
|
GPIO113_UART2_TXD,
|
|
GPIO114_UART2_CTS | MFP_LPM_EDGE_BOTH,
|
|
|
|
/* STUART */
|
|
GPIO109_UART3_TXD,
|
|
GPIO110_UART3_RXD | MFP_LPM_EDGE_FALL,
|
|
|
|
/* AC97 */
|
|
GPIO23_AC97_nACRESET,
|
|
GPIO24_AC97_SYSCLK,
|
|
GPIO29_AC97_BITCLK,
|
|
GPIO25_AC97_SDATA_IN_0,
|
|
GPIO27_AC97_SDATA_OUT,
|
|
GPIO28_AC97_SYNC,
|
|
|
|
/* Keypad */
|
|
GPIO115_KP_MKIN_0 | MFP_LPM_EDGE_BOTH,
|
|
GPIO116_KP_MKIN_1 | MFP_LPM_EDGE_BOTH,
|
|
GPIO117_KP_MKIN_2 | MFP_LPM_EDGE_BOTH,
|
|
GPIO118_KP_MKIN_3 | MFP_LPM_EDGE_BOTH,
|
|
GPIO119_KP_MKIN_4 | MFP_LPM_EDGE_BOTH,
|
|
GPIO120_KP_MKIN_5 | MFP_LPM_EDGE_BOTH,
|
|
GPIO2_2_KP_MKIN_6 | MFP_LPM_EDGE_BOTH,
|
|
GPIO3_2_KP_MKIN_7 | MFP_LPM_EDGE_BOTH,
|
|
GPIO121_KP_MKOUT_0,
|
|
GPIO122_KP_MKOUT_1,
|
|
GPIO123_KP_MKOUT_2,
|
|
GPIO124_KP_MKOUT_3,
|
|
GPIO125_KP_MKOUT_4,
|
|
GPIO4_2_KP_MKOUT_5,
|
|
|
|
/* MMC1 */
|
|
GPIO3_MMC1_DAT0,
|
|
GPIO4_MMC1_DAT1 | MFP_LPM_EDGE_BOTH,
|
|
GPIO5_MMC1_DAT2,
|
|
GPIO6_MMC1_DAT3,
|
|
GPIO7_MMC1_CLK,
|
|
GPIO8_MMC1_CMD, /* CMD0 for slot 0 */
|
|
|
|
/* MMC2 */
|
|
GPIO9_MMC2_DAT0,
|
|
GPIO10_MMC2_DAT1 | MFP_LPM_EDGE_BOTH,
|
|
GPIO11_MMC2_DAT2,
|
|
GPIO12_MMC2_DAT3,
|
|
GPIO13_MMC2_CLK,
|
|
GPIO14_MMC2_CMD,
|
|
|
|
/* FFUART */
|
|
GPIO30_UART1_RXD | MFP_LPM_EDGE_FALL,
|
|
GPIO31_UART1_TXD,
|
|
GPIO32_UART1_CTS,
|
|
GPIO37_UART1_RTS,
|
|
GPIO33_UART1_DCD,
|
|
GPIO34_UART1_DSR | MFP_LPM_EDGE_FALL,
|
|
GPIO35_UART1_RI,
|
|
GPIO36_UART1_DTR,
|
|
|
|
/* GPIOs */
|
|
GPIO79_GPIO, /* LED */
|
|
GPIO82_GPIO | MFP_PULL_HIGH, /* MMC CD */
|
|
GPIO85_GPIO, /* MMC WP */
|
|
GPIO99_GPIO, /* Ethernet IRQ */
|
|
|
|
/* Standard I2C */
|
|
GPIO21_I2C_SCL,
|
|
GPIO22_I2C_SDA,
|
|
};
|
|
|
|
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
|
|
static struct resource dm9000_resources[] = {
|
|
[0] = {
|
|
.start = CM_X300_ETH_PHYS,
|
|
.end = CM_X300_ETH_PHYS + 0x3,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = CM_X300_ETH_PHYS + 0x4,
|
|
.end = CM_X300_ETH_PHYS + 0x4 + 500,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[2] = {
|
|
.start = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)),
|
|
.end = IRQ_GPIO(mfp_to_gpio(MFP_PIN_GPIO99)),
|
|
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
|
|
}
|
|
};
|
|
|
|
static struct dm9000_plat_data cm_x300_dm9000_platdata = {
|
|
.flags = DM9000_PLATF_16BITONLY,
|
|
};
|
|
|
|
static struct platform_device dm9000_device = {
|
|
.name = "dm9000",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(dm9000_resources),
|
|
.resource = dm9000_resources,
|
|
.dev = {
|
|
.platform_data = &cm_x300_dm9000_platdata,
|
|
}
|
|
|
|
};
|
|
|
|
static void __init cm_x300_init_dm9000(void)
|
|
{
|
|
platform_device_register(&dm9000_device);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_dm9000(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
|
|
static struct pxafb_mode_info cm_x300_lcd_modes[] = {
|
|
[0] = {
|
|
.pixclock = 38000,
|
|
.bpp = 16,
|
|
.xres = 480,
|
|
.yres = 640,
|
|
.hsync_len = 8,
|
|
.vsync_len = 2,
|
|
.left_margin = 8,
|
|
.upper_margin = 0,
|
|
.right_margin = 24,
|
|
.lower_margin = 4,
|
|
.cmap_greyscale = 0,
|
|
},
|
|
[1] = {
|
|
.pixclock = 153800,
|
|
.bpp = 16,
|
|
.xres = 240,
|
|
.yres = 320,
|
|
.hsync_len = 8,
|
|
.vsync_len = 2,
|
|
.left_margin = 8,
|
|
.upper_margin = 2,
|
|
.right_margin = 88,
|
|
.lower_margin = 2,
|
|
.cmap_greyscale = 0,
|
|
},
|
|
};
|
|
|
|
static struct pxafb_mach_info cm_x300_lcd = {
|
|
.modes = cm_x300_lcd_modes,
|
|
.num_modes = 2,
|
|
.lcd_conn = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL,
|
|
};
|
|
|
|
static void __init cm_x300_init_lcd(void)
|
|
{
|
|
set_pxa_fb_info(&cm_x300_lcd);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_lcd(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE)
|
|
static struct mtd_partition cm_x300_nand_partitions[] = {
|
|
[0] = {
|
|
.name = "OBM",
|
|
.offset = 0,
|
|
.size = SZ_256K,
|
|
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
|
},
|
|
[1] = {
|
|
.name = "U-Boot",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = SZ_256K,
|
|
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
|
},
|
|
[2] = {
|
|
.name = "Environment",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = SZ_256K,
|
|
},
|
|
[3] = {
|
|
.name = "reserved",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = SZ_256K + SZ_1M,
|
|
.mask_flags = MTD_WRITEABLE, /* force read-only */
|
|
},
|
|
[4] = {
|
|
.name = "kernel",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = SZ_4M,
|
|
},
|
|
[5] = {
|
|
.name = "fs",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = MTDPART_SIZ_FULL,
|
|
},
|
|
};
|
|
|
|
static struct pxa3xx_nand_platform_data cm_x300_nand_info = {
|
|
.enable_arbiter = 1,
|
|
.parts = cm_x300_nand_partitions,
|
|
.nr_parts = ARRAY_SIZE(cm_x300_nand_partitions),
|
|
};
|
|
|
|
static void __init cm_x300_init_nand(void)
|
|
{
|
|
pxa3xx_set_nand_info(&cm_x300_nand_info);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_nand(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
|
|
/* The first MMC slot of CM-X300 is hardwired to Libertas card and has
|
|
no detection/ro pins */
|
|
static int cm_x300_mci_init(struct device *dev,
|
|
irq_handler_t cm_x300_detect_int,
|
|
void *data)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
static void cm_x300_mci_exit(struct device *dev, void *data)
|
|
{
|
|
}
|
|
|
|
static struct pxamci_platform_data cm_x300_mci_platform_data = {
|
|
.detect_delay = 20,
|
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
|
.init = cm_x300_mci_init,
|
|
.exit = cm_x300_mci_exit,
|
|
};
|
|
|
|
static int cm_x300_mci2_ro(struct device *dev)
|
|
{
|
|
return gpio_get_value(GPIO85_MMC2_WP);
|
|
}
|
|
|
|
static int cm_x300_mci2_init(struct device *dev,
|
|
irq_handler_t cm_x300_detect_int,
|
|
void *data)
|
|
{
|
|
int err;
|
|
|
|
/*
|
|
* setup GPIO for CM-X300 MMC controller
|
|
*/
|
|
err = gpio_request(GPIO82_MMC2_IRQ, "mmc card detect");
|
|
if (err)
|
|
goto err_request_cd;
|
|
gpio_direction_input(GPIO82_MMC2_IRQ);
|
|
|
|
err = gpio_request(GPIO85_MMC2_WP, "mmc write protect");
|
|
if (err)
|
|
goto err_request_wp;
|
|
gpio_direction_input(GPIO85_MMC2_WP);
|
|
|
|
err = request_irq(CM_X300_MMC2_IRQ, cm_x300_detect_int,
|
|
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
|
|
"MMC card detect", data);
|
|
if (err) {
|
|
printk(KERN_ERR "%s: MMC/SD/SDIO: "
|
|
"can't request card detect IRQ\n", __func__);
|
|
goto err_request_irq;
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_request_irq:
|
|
gpio_free(GPIO85_MMC2_WP);
|
|
err_request_wp:
|
|
gpio_free(GPIO82_MMC2_IRQ);
|
|
err_request_cd:
|
|
return err;
|
|
}
|
|
|
|
static void cm_x300_mci2_exit(struct device *dev, void *data)
|
|
{
|
|
free_irq(CM_X300_MMC2_IRQ, data);
|
|
gpio_free(GPIO82_MMC2_IRQ);
|
|
gpio_free(GPIO85_MMC2_WP);
|
|
}
|
|
|
|
static struct pxamci_platform_data cm_x300_mci2_platform_data = {
|
|
.detect_delay = 20,
|
|
.ocr_mask = MMC_VDD_32_33|MMC_VDD_33_34,
|
|
.init = cm_x300_mci2_init,
|
|
.exit = cm_x300_mci2_exit,
|
|
.get_ro = cm_x300_mci2_ro,
|
|
};
|
|
|
|
static void __init cm_x300_init_mmc(void)
|
|
{
|
|
pxa_set_mci_info(&cm_x300_mci_platform_data);
|
|
pxa3xx_set_mci2_info(&cm_x300_mci2_platform_data);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_mmc(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
|
|
static struct pxaohci_platform_data cm_x300_ohci_platform_data = {
|
|
.port_mode = PMM_PERPORT_MODE,
|
|
.flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
|
|
};
|
|
|
|
static void __init cm_x300_init_ohci(void)
|
|
{
|
|
pxa_set_ohci_info(&cm_x300_ohci_platform_data);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_ohci(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
|
|
static struct gpio_led cm_x300_leds[] = {
|
|
[0] = {
|
|
.name = "cm-x300:green",
|
|
.default_trigger = "heartbeat",
|
|
.gpio = 79,
|
|
.active_low = 1,
|
|
},
|
|
};
|
|
|
|
static struct gpio_led_platform_data cm_x300_gpio_led_pdata = {
|
|
.num_leds = ARRAY_SIZE(cm_x300_leds),
|
|
.leds = cm_x300_leds,
|
|
};
|
|
|
|
static struct platform_device cm_x300_led_device = {
|
|
.name = "leds-gpio",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &cm_x300_gpio_led_pdata,
|
|
},
|
|
};
|
|
|
|
static void __init cm_x300_init_leds(void)
|
|
{
|
|
platform_device_register(&cm_x300_led_device);
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_leds(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
|
|
/* PCA9555 */
|
|
static struct pca953x_platform_data cm_x300_gpio_ext_pdata_0 = {
|
|
.gpio_base = 128,
|
|
};
|
|
|
|
static struct pca953x_platform_data cm_x300_gpio_ext_pdata_1 = {
|
|
.gpio_base = 144,
|
|
};
|
|
|
|
static struct i2c_board_info cm_x300_gpio_ext_info[] = {
|
|
[0] = {
|
|
I2C_BOARD_INFO("pca9555", 0x24),
|
|
.platform_data = &cm_x300_gpio_ext_pdata_0,
|
|
},
|
|
[1] = {
|
|
I2C_BOARD_INFO("pca9555", 0x25),
|
|
.platform_data = &cm_x300_gpio_ext_pdata_1,
|
|
},
|
|
};
|
|
|
|
static void __init cm_x300_init_i2c(void)
|
|
{
|
|
pxa_set_i2c_info(NULL);
|
|
i2c_register_board_info(0, cm_x300_gpio_ext_info,
|
|
ARRAY_SIZE(cm_x300_gpio_ext_info));
|
|
}
|
|
#else
|
|
static inline void cm_x300_init_i2c(void) {}
|
|
#endif
|
|
|
|
static void __init cm_x300_init(void)
|
|
{
|
|
/* board-processor specific GPIO initialization */
|
|
pxa3xx_mfp_config(ARRAY_AND_SIZE(cm_x300_mfp_cfg));
|
|
|
|
cm_x300_init_dm9000();
|
|
cm_x300_init_lcd();
|
|
cm_x300_init_ohci();
|
|
cm_x300_init_mmc();
|
|
cm_x300_init_nand();
|
|
cm_x300_init_leds();
|
|
cm_x300_init_i2c();
|
|
}
|
|
|
|
MACHINE_START(CM_X300, "CM-X300 module")
|
|
.phys_io = 0x40000000,
|
|
.boot_params = 0xa0000100,
|
|
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
|
.map_io = pxa_map_io,
|
|
.init_irq = pxa3xx_init_irq,
|
|
.timer = &pxa_timer,
|
|
.init_machine = cm_x300_init,
|
|
MACHINE_END
|