forked from Minki/linux
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>
1067 lines
24 KiB
C
1067 lines
24 KiB
C
/*
|
|
* Support for CompuLab EM-X270 platform
|
|
*
|
|
* Copyright (C) 2007, 2008 CompuLab, Ltd.
|
|
* Author: 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/irq.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/delay.h>
|
|
|
|
#include <linux/dm9000.h>
|
|
#include <linux/rtc-v3020.h>
|
|
#include <linux/mtd/nand.h>
|
|
#include <linux/mtd/partitions.h>
|
|
#include <linux/mtd/physmap.h>
|
|
#include <linux/input.h>
|
|
#include <linux/gpio_keys.h>
|
|
#include <linux/gpio.h>
|
|
#include <linux/mfd/da903x.h>
|
|
#include <linux/regulator/machine.h>
|
|
#include <linux/spi/spi.h>
|
|
#include <linux/spi/tdo24m.h>
|
|
#include <linux/power_supply.h>
|
|
#include <linux/apm-emulation.h>
|
|
|
|
#include <media/soc_camera.h>
|
|
|
|
#include <asm/mach-types.h>
|
|
#include <asm/mach/arch.h>
|
|
|
|
#include <mach/pxa27x.h>
|
|
#include <mach/pxa27x-udc.h>
|
|
#include <mach/audio.h>
|
|
#include <mach/pxafb.h>
|
|
#include <mach/ohci.h>
|
|
#include <mach/mmc.h>
|
|
#include <mach/pxa27x_keypad.h>
|
|
#include <mach/i2c.h>
|
|
#include <mach/camera.h>
|
|
#include <mach/pxa2xx_spi.h>
|
|
|
|
#include "generic.h"
|
|
#include "devices.h"
|
|
|
|
/* EM-X270 specific GPIOs */
|
|
#define GPIO13_MMC_CD (13)
|
|
#define GPIO95_MMC_WP (95)
|
|
#define GPIO56_NAND_RB (56)
|
|
|
|
/* eXeda specific GPIOs */
|
|
#define GPIO114_MMC_CD (114)
|
|
#define GPIO20_NAND_RB (20)
|
|
#define GPIO38_SD_PWEN (38)
|
|
|
|
/* common GPIOs */
|
|
#define GPIO11_NAND_CS (11)
|
|
#define GPIO93_CAM_RESET (93)
|
|
#define GPIO41_ETHIRQ (41)
|
|
#define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ)
|
|
|
|
static int mmc_cd;
|
|
static int nand_rb;
|
|
static int dm9000_flags;
|
|
|
|
static unsigned long common_pin_config[] = {
|
|
/* AC'97 */
|
|
GPIO28_AC97_BITCLK,
|
|
GPIO29_AC97_SDATA_IN_0,
|
|
GPIO30_AC97_SDATA_OUT,
|
|
GPIO31_AC97_SYNC,
|
|
GPIO98_AC97_SYSCLK,
|
|
GPIO113_AC97_nRESET,
|
|
|
|
/* BTUART */
|
|
GPIO42_BTUART_RXD,
|
|
GPIO43_BTUART_TXD,
|
|
GPIO44_BTUART_CTS,
|
|
GPIO45_BTUART_RTS,
|
|
|
|
/* STUART */
|
|
GPIO46_STUART_RXD,
|
|
GPIO47_STUART_TXD,
|
|
|
|
/* MCI controller */
|
|
GPIO32_MMC_CLK,
|
|
GPIO112_MMC_CMD,
|
|
GPIO92_MMC_DAT_0,
|
|
GPIO109_MMC_DAT_1,
|
|
GPIO110_MMC_DAT_2,
|
|
GPIO111_MMC_DAT_3,
|
|
|
|
/* LCD */
|
|
GPIO58_LCD_LDD_0,
|
|
GPIO59_LCD_LDD_1,
|
|
GPIO60_LCD_LDD_2,
|
|
GPIO61_LCD_LDD_3,
|
|
GPIO62_LCD_LDD_4,
|
|
GPIO63_LCD_LDD_5,
|
|
GPIO64_LCD_LDD_6,
|
|
GPIO65_LCD_LDD_7,
|
|
GPIO66_LCD_LDD_8,
|
|
GPIO67_LCD_LDD_9,
|
|
GPIO68_LCD_LDD_10,
|
|
GPIO69_LCD_LDD_11,
|
|
GPIO70_LCD_LDD_12,
|
|
GPIO71_LCD_LDD_13,
|
|
GPIO72_LCD_LDD_14,
|
|
GPIO73_LCD_LDD_15,
|
|
GPIO74_LCD_FCLK,
|
|
GPIO75_LCD_LCLK,
|
|
GPIO76_LCD_PCLK,
|
|
GPIO77_LCD_BIAS,
|
|
|
|
/* QCI */
|
|
GPIO84_CIF_FV,
|
|
GPIO25_CIF_LV,
|
|
GPIO53_CIF_MCLK,
|
|
GPIO54_CIF_PCLK,
|
|
GPIO81_CIF_DD_0,
|
|
GPIO55_CIF_DD_1,
|
|
GPIO51_CIF_DD_2,
|
|
GPIO50_CIF_DD_3,
|
|
GPIO52_CIF_DD_4,
|
|
GPIO48_CIF_DD_5,
|
|
GPIO17_CIF_DD_6,
|
|
GPIO12_CIF_DD_7,
|
|
|
|
/* I2C */
|
|
GPIO117_I2C_SCL,
|
|
GPIO118_I2C_SDA,
|
|
|
|
/* Keypad */
|
|
GPIO100_KP_MKIN_0 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO101_KP_MKIN_1 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO102_KP_MKIN_2 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO34_KP_MKIN_3 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO39_KP_MKIN_4 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO99_KP_MKIN_5 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO91_KP_MKIN_6 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO36_KP_MKIN_7 | WAKEUP_ON_LEVEL_HIGH,
|
|
GPIO103_KP_MKOUT_0,
|
|
GPIO104_KP_MKOUT_1,
|
|
GPIO105_KP_MKOUT_2,
|
|
GPIO106_KP_MKOUT_3,
|
|
GPIO107_KP_MKOUT_4,
|
|
GPIO108_KP_MKOUT_5,
|
|
GPIO96_KP_MKOUT_6,
|
|
GPIO22_KP_MKOUT_7,
|
|
|
|
/* SSP1 */
|
|
GPIO26_SSP1_RXD,
|
|
GPIO23_SSP1_SCLK,
|
|
GPIO24_SSP1_SFRM,
|
|
GPIO57_SSP1_TXD,
|
|
|
|
/* SSP2 */
|
|
GPIO19_SSP2_SCLK,
|
|
GPIO14_SSP2_SFRM,
|
|
GPIO89_SSP2_TXD,
|
|
GPIO88_SSP2_RXD,
|
|
|
|
/* SDRAM and local bus */
|
|
GPIO15_nCS_1,
|
|
GPIO78_nCS_2,
|
|
GPIO79_nCS_3,
|
|
GPIO80_nCS_4,
|
|
GPIO49_nPWE,
|
|
GPIO18_RDY,
|
|
|
|
/* GPIO */
|
|
GPIO1_GPIO | WAKEUP_ON_EDGE_BOTH, /* sleep/resume button */
|
|
|
|
/* power controls */
|
|
GPIO20_GPIO | MFP_LPM_DRIVE_LOW, /* GPRS_PWEN */
|
|
GPIO93_GPIO | MFP_LPM_DRIVE_LOW, /* Camera reset */
|
|
GPIO115_GPIO | MFP_LPM_DRIVE_LOW, /* WLAN_PWEN */
|
|
|
|
/* NAND controls */
|
|
GPIO11_GPIO | MFP_LPM_DRIVE_HIGH, /* NAND CE# */
|
|
|
|
/* interrupts */
|
|
GPIO41_GPIO, /* DM9000 interrupt */
|
|
};
|
|
|
|
static unsigned long em_x270_pin_config[] = {
|
|
GPIO13_GPIO, /* MMC card detect */
|
|
GPIO56_GPIO, /* NAND Ready/Busy */
|
|
GPIO95_GPIO, /* MMC Write protect */
|
|
};
|
|
|
|
static unsigned long exeda_pin_config[] = {
|
|
GPIO20_GPIO, /* NAND Ready/Busy */
|
|
GPIO38_GPIO | MFP_LPM_DRIVE_LOW, /* SD slot power */
|
|
GPIO114_GPIO, /* MMC card detect */
|
|
};
|
|
|
|
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
|
|
static struct resource em_x270_dm9000_resource[] = {
|
|
[0] = {
|
|
.start = PXA_CS2_PHYS,
|
|
.end = PXA_CS2_PHYS + 3,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[1] = {
|
|
.start = PXA_CS2_PHYS + 8,
|
|
.end = PXA_CS2_PHYS + 8 + 0x3f,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
[2] = {
|
|
.start = EM_X270_ETHIRQ,
|
|
.end = EM_X270_ETHIRQ,
|
|
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
|
|
}
|
|
};
|
|
|
|
static struct dm9000_plat_data em_x270_dm9000_platdata = {
|
|
.flags = DM9000_PLATF_NO_EEPROM,
|
|
};
|
|
|
|
static struct platform_device em_x270_dm9000 = {
|
|
.name = "dm9000",
|
|
.id = 0,
|
|
.num_resources = ARRAY_SIZE(em_x270_dm9000_resource),
|
|
.resource = em_x270_dm9000_resource,
|
|
.dev = {
|
|
.platform_data = &em_x270_dm9000_platdata,
|
|
}
|
|
};
|
|
|
|
static void __init em_x270_init_dm9000(void)
|
|
{
|
|
em_x270_dm9000_platdata.flags |= dm9000_flags;
|
|
platform_device_register(&em_x270_dm9000);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_dm9000(void) {}
|
|
#endif
|
|
|
|
/* V3020 RTC */
|
|
#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
|
|
static struct resource em_x270_v3020_resource[] = {
|
|
[0] = {
|
|
.start = PXA_CS4_PHYS,
|
|
.end = PXA_CS4_PHYS + 3,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
};
|
|
|
|
static struct v3020_platform_data em_x270_v3020_platdata = {
|
|
.leftshift = 0,
|
|
};
|
|
|
|
static struct platform_device em_x270_rtc = {
|
|
.name = "v3020",
|
|
.num_resources = ARRAY_SIZE(em_x270_v3020_resource),
|
|
.resource = em_x270_v3020_resource,
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &em_x270_v3020_platdata,
|
|
}
|
|
};
|
|
|
|
static void __init em_x270_init_rtc(void)
|
|
{
|
|
platform_device_register(&em_x270_rtc);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_rtc(void) {}
|
|
#endif
|
|
|
|
/* NAND flash */
|
|
#if defined(CONFIG_MTD_NAND_PLATFORM) || defined(CONFIG_MTD_NAND_PLATFORM_MODULE)
|
|
static inline void nand_cs_on(void)
|
|
{
|
|
gpio_set_value(GPIO11_NAND_CS, 0);
|
|
}
|
|
|
|
static void nand_cs_off(void)
|
|
{
|
|
dsb();
|
|
|
|
gpio_set_value(GPIO11_NAND_CS, 1);
|
|
}
|
|
|
|
/* hardware specific access to control-lines */
|
|
static void em_x270_nand_cmd_ctl(struct mtd_info *mtd, int dat,
|
|
unsigned int ctrl)
|
|
{
|
|
struct nand_chip *this = mtd->priv;
|
|
unsigned long nandaddr = (unsigned long)this->IO_ADDR_W;
|
|
|
|
dsb();
|
|
|
|
if (ctrl & NAND_CTRL_CHANGE) {
|
|
if (ctrl & NAND_ALE)
|
|
nandaddr |= (1 << 3);
|
|
else
|
|
nandaddr &= ~(1 << 3);
|
|
if (ctrl & NAND_CLE)
|
|
nandaddr |= (1 << 2);
|
|
else
|
|
nandaddr &= ~(1 << 2);
|
|
if (ctrl & NAND_NCE)
|
|
nand_cs_on();
|
|
else
|
|
nand_cs_off();
|
|
}
|
|
|
|
dsb();
|
|
this->IO_ADDR_W = (void __iomem *)nandaddr;
|
|
if (dat != NAND_CMD_NONE)
|
|
writel(dat, this->IO_ADDR_W);
|
|
|
|
dsb();
|
|
}
|
|
|
|
/* read device ready pin */
|
|
static int em_x270_nand_device_ready(struct mtd_info *mtd)
|
|
{
|
|
dsb();
|
|
|
|
return gpio_get_value(nand_rb);
|
|
}
|
|
|
|
static struct mtd_partition em_x270_partition_info[] = {
|
|
[0] = {
|
|
.name = "em_x270-0",
|
|
.offset = 0,
|
|
.size = SZ_4M,
|
|
},
|
|
[1] = {
|
|
.name = "em_x270-1",
|
|
.offset = MTDPART_OFS_APPEND,
|
|
.size = MTDPART_SIZ_FULL
|
|
},
|
|
};
|
|
|
|
static const char *em_x270_part_probes[] = { "cmdlinepart", NULL };
|
|
|
|
struct platform_nand_data em_x270_nand_platdata = {
|
|
.chip = {
|
|
.nr_chips = 1,
|
|
.chip_offset = 0,
|
|
.nr_partitions = ARRAY_SIZE(em_x270_partition_info),
|
|
.partitions = em_x270_partition_info,
|
|
.chip_delay = 20,
|
|
.part_probe_types = em_x270_part_probes,
|
|
},
|
|
.ctrl = {
|
|
.hwcontrol = 0,
|
|
.dev_ready = em_x270_nand_device_ready,
|
|
.select_chip = 0,
|
|
.cmd_ctrl = em_x270_nand_cmd_ctl,
|
|
},
|
|
};
|
|
|
|
static struct resource em_x270_nand_resource[] = {
|
|
[0] = {
|
|
.start = PXA_CS1_PHYS,
|
|
.end = PXA_CS1_PHYS + 12,
|
|
.flags = IORESOURCE_MEM,
|
|
},
|
|
};
|
|
|
|
static struct platform_device em_x270_nand = {
|
|
.name = "gen_nand",
|
|
.num_resources = ARRAY_SIZE(em_x270_nand_resource),
|
|
.resource = em_x270_nand_resource,
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &em_x270_nand_platdata,
|
|
}
|
|
};
|
|
|
|
static void __init em_x270_init_nand(void)
|
|
{
|
|
int err;
|
|
|
|
err = gpio_request(GPIO11_NAND_CS, "NAND CS");
|
|
if (err) {
|
|
pr_warning("EM-X270: failed to request NAND CS gpio\n");
|
|
return;
|
|
}
|
|
|
|
gpio_direction_output(GPIO11_NAND_CS, 1);
|
|
|
|
err = gpio_request(nand_rb, "NAND R/B");
|
|
if (err) {
|
|
pr_warning("EM-X270: failed to request NAND R/B gpio\n");
|
|
gpio_free(GPIO11_NAND_CS);
|
|
return;
|
|
}
|
|
|
|
gpio_direction_input(nand_rb);
|
|
|
|
platform_device_register(&em_x270_nand);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_nand(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_MTD_PHYSMAP) || defined(CONFIG_MTD_PHYSMAP_MODULE)
|
|
static struct mtd_partition em_x270_nor_parts[] = {
|
|
{
|
|
.name = "Bootloader",
|
|
.offset = 0x00000000,
|
|
.size = 0x00050000,
|
|
.mask_flags = MTD_WRITEABLE /* force read-only */
|
|
}, {
|
|
.name = "Environment",
|
|
.offset = 0x00050000,
|
|
.size = 0x00010000,
|
|
}, {
|
|
.name = "Reserved",
|
|
.offset = 0x00060000,
|
|
.size = 0x00050000,
|
|
.mask_flags = MTD_WRITEABLE /* force read-only */
|
|
}, {
|
|
.name = "Splashscreen",
|
|
.offset = 0x000b0000,
|
|
.size = 0x00050000,
|
|
}
|
|
};
|
|
|
|
static struct physmap_flash_data em_x270_nor_data[] = {
|
|
[0] = {
|
|
.width = 2,
|
|
.parts = em_x270_nor_parts,
|
|
.nr_parts = ARRAY_SIZE(em_x270_nor_parts),
|
|
},
|
|
};
|
|
|
|
static struct resource em_x270_nor_flash_resource = {
|
|
.start = PXA_CS0_PHYS,
|
|
.end = PXA_CS0_PHYS + SZ_1M - 1,
|
|
.flags = IORESOURCE_MEM,
|
|
};
|
|
|
|
static struct platform_device em_x270_physmap_flash = {
|
|
.name = "physmap-flash",
|
|
.id = 0,
|
|
.num_resources = 1,
|
|
.resource = &em_x270_nor_flash_resource,
|
|
.dev = {
|
|
.platform_data = &em_x270_nor_data,
|
|
},
|
|
};
|
|
|
|
static void __init em_x270_init_nor(void)
|
|
{
|
|
platform_device_register(&em_x270_physmap_flash);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_nor(void) {}
|
|
#endif
|
|
|
|
/* PXA27x OHCI controller setup */
|
|
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
|
|
static int em_x270_ohci_init(struct device *dev)
|
|
{
|
|
/* enable port 2 transiever */
|
|
UP2OCR = UP2OCR_HXS | UP2OCR_HXOE;
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct pxaohci_platform_data em_x270_ohci_platform_data = {
|
|
.port_mode = PMM_PERPORT_MODE,
|
|
.flags = ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,
|
|
.init = em_x270_ohci_init,
|
|
};
|
|
|
|
static void __init em_x270_init_ohci(void)
|
|
{
|
|
pxa_set_ohci_info(&em_x270_ohci_platform_data);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_ohci(void) {}
|
|
#endif
|
|
|
|
/* MCI controller setup */
|
|
#if defined(CONFIG_MMC) || defined(CONFIG_MMC_MODULE)
|
|
static struct regulator *em_x270_sdio_ldo;
|
|
|
|
static int em_x270_mci_init(struct device *dev,
|
|
irq_handler_t em_x270_detect_int,
|
|
void *data)
|
|
{
|
|
int err;
|
|
|
|
em_x270_sdio_ldo = regulator_get(dev, "vcc sdio");
|
|
if (IS_ERR(em_x270_sdio_ldo)) {
|
|
dev_err(dev, "can't request SDIO power supply: %ld\n",
|
|
PTR_ERR(em_x270_sdio_ldo));
|
|
return PTR_ERR(em_x270_sdio_ldo);
|
|
}
|
|
|
|
err = request_irq(gpio_to_irq(mmc_cd), em_x270_detect_int,
|
|
IRQF_DISABLED | IRQF_TRIGGER_RISING |
|
|
IRQF_TRIGGER_FALLING,
|
|
"MMC card detect", data);
|
|
if (err) {
|
|
dev_err(dev, "can't request MMC card detect IRQ: %d\n", err);
|
|
goto err_irq;
|
|
}
|
|
|
|
if (machine_is_em_x270()) {
|
|
err = gpio_request(GPIO95_MMC_WP, "MMC WP");
|
|
if (err) {
|
|
dev_err(dev, "can't request MMC write protect: %d\n",
|
|
err);
|
|
goto err_gpio_wp;
|
|
}
|
|
gpio_direction_input(GPIO95_MMC_WP);
|
|
} else {
|
|
err = gpio_request(GPIO38_SD_PWEN, "sdio power");
|
|
if (err) {
|
|
dev_err(dev, "can't request MMC power control : %d\n",
|
|
err);
|
|
goto err_gpio_wp;
|
|
}
|
|
gpio_direction_output(GPIO38_SD_PWEN, 1);
|
|
}
|
|
|
|
return 0;
|
|
|
|
err_gpio_wp:
|
|
free_irq(gpio_to_irq(mmc_cd), data);
|
|
err_irq:
|
|
regulator_put(em_x270_sdio_ldo);
|
|
|
|
return err;
|
|
}
|
|
|
|
static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)
|
|
{
|
|
struct pxamci_platform_data* p_d = dev->platform_data;
|
|
|
|
if ((1 << vdd) & p_d->ocr_mask) {
|
|
int vdd_uV = (2000 + (vdd - __ffs(MMC_VDD_20_21)) * 100) * 1000;
|
|
|
|
regulator_set_voltage(em_x270_sdio_ldo, vdd_uV, vdd_uV);
|
|
regulator_enable(em_x270_sdio_ldo);
|
|
} else {
|
|
regulator_disable(em_x270_sdio_ldo);
|
|
}
|
|
}
|
|
|
|
static void em_x270_mci_exit(struct device *dev, void *data)
|
|
{
|
|
free_irq(gpio_to_irq(mmc_cd), data);
|
|
regulator_put(em_x270_sdio_ldo);
|
|
|
|
if (machine_is_em_x270())
|
|
gpio_free(GPIO95_MMC_WP);
|
|
else
|
|
gpio_free(GPIO38_SD_PWEN);
|
|
}
|
|
|
|
static int em_x270_mci_get_ro(struct device *dev)
|
|
{
|
|
return gpio_get_value(GPIO95_MMC_WP);
|
|
}
|
|
|
|
static struct pxamci_platform_data em_x270_mci_platform_data = {
|
|
.ocr_mask = MMC_VDD_20_21|MMC_VDD_21_22|MMC_VDD_22_23|
|
|
MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27|
|
|
MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30|
|
|
MMC_VDD_30_31|MMC_VDD_31_32,
|
|
.init = em_x270_mci_init,
|
|
.setpower = em_x270_mci_setpower,
|
|
.exit = em_x270_mci_exit,
|
|
};
|
|
|
|
static void __init em_x270_init_mmc(void)
|
|
{
|
|
if (machine_is_em_x270())
|
|
em_x270_mci_platform_data.get_ro = em_x270_mci_get_ro;
|
|
|
|
em_x270_mci_platform_data.detect_delay = msecs_to_jiffies(250);
|
|
pxa_set_mci_info(&em_x270_mci_platform_data);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_mmc(void) {}
|
|
#endif
|
|
|
|
/* LCD */
|
|
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
|
|
static struct pxafb_mode_info em_x270_lcd_modes[] = {
|
|
[0] = {
|
|
.pixclock = 38250,
|
|
.bpp = 16,
|
|
.xres = 480,
|
|
.yres = 640,
|
|
.hsync_len = 8,
|
|
.vsync_len = 2,
|
|
.left_margin = 8,
|
|
.upper_margin = 2,
|
|
.right_margin = 24,
|
|
.lower_margin = 4,
|
|
.sync = 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,
|
|
.sync = 0,
|
|
},
|
|
};
|
|
|
|
static struct pxafb_mach_info em_x270_lcd = {
|
|
.modes = em_x270_lcd_modes,
|
|
.num_modes = 2,
|
|
.lcd_conn = LCD_COLOR_TFT_16BPP,
|
|
};
|
|
|
|
static void __init em_x270_init_lcd(void)
|
|
{
|
|
set_pxa_fb_info(&em_x270_lcd);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_lcd(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MODULE)
|
|
static struct pxa2xx_spi_master em_x270_spi_info = {
|
|
.num_chipselect = 1,
|
|
};
|
|
|
|
static struct pxa2xx_spi_chip em_x270_tdo24m_chip = {
|
|
.rx_threshold = 1,
|
|
.tx_threshold = 1,
|
|
};
|
|
|
|
static struct tdo24m_platform_data em_x270_tdo24m_pdata = {
|
|
.model = TDO35S,
|
|
};
|
|
|
|
static struct spi_board_info em_x270_spi_devices[] __initdata = {
|
|
{
|
|
.modalias = "tdo24m",
|
|
.max_speed_hz = 1000000,
|
|
.bus_num = 1,
|
|
.chip_select = 0,
|
|
.controller_data = &em_x270_tdo24m_chip,
|
|
.platform_data = &em_x270_tdo24m_pdata,
|
|
},
|
|
};
|
|
|
|
static void __init em_x270_init_spi(void)
|
|
{
|
|
pxa2xx_set_spi_info(1, &em_x270_spi_info);
|
|
spi_register_board_info(ARRAY_AND_SIZE(em_x270_spi_devices));
|
|
}
|
|
#else
|
|
static inline void em_x270_init_spi(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
|
|
static void __init em_x270_init_ac97(void)
|
|
{
|
|
pxa_set_ac97_info(NULL);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_ac97(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
|
|
static unsigned int em_x270_module_matrix_keys[] = {
|
|
KEY(0, 0, KEY_A), KEY(1, 0, KEY_UP), KEY(2, 1, KEY_B),
|
|
KEY(0, 2, KEY_LEFT), KEY(1, 1, KEY_ENTER), KEY(2, 0, KEY_RIGHT),
|
|
KEY(0, 1, KEY_C), KEY(1, 2, KEY_DOWN), KEY(2, 2, KEY_D),
|
|
};
|
|
|
|
struct pxa27x_keypad_platform_data em_x270_module_keypad_info = {
|
|
/* code map for the matrix keys */
|
|
.matrix_key_rows = 3,
|
|
.matrix_key_cols = 3,
|
|
.matrix_key_map = em_x270_module_matrix_keys,
|
|
.matrix_key_map_size = ARRAY_SIZE(em_x270_module_matrix_keys),
|
|
};
|
|
|
|
static unsigned int em_x270_exeda_matrix_keys[] = {
|
|
KEY(0, 0, KEY_RIGHTSHIFT), KEY(0, 1, KEY_RIGHTCTRL),
|
|
KEY(0, 2, KEY_RIGHTALT), KEY(0, 3, KEY_SPACE),
|
|
KEY(0, 4, KEY_LEFTALT), KEY(0, 5, KEY_LEFTCTRL),
|
|
KEY(0, 6, KEY_ENTER), KEY(0, 7, KEY_SLASH),
|
|
|
|
KEY(1, 0, KEY_DOT), KEY(1, 1, KEY_M),
|
|
KEY(1, 2, KEY_N), KEY(1, 3, KEY_B),
|
|
KEY(1, 4, KEY_V), KEY(1, 5, KEY_C),
|
|
KEY(1, 6, KEY_X), KEY(1, 7, KEY_Z),
|
|
|
|
KEY(2, 0, KEY_LEFTSHIFT), KEY(2, 1, KEY_SEMICOLON),
|
|
KEY(2, 2, KEY_L), KEY(2, 3, KEY_K),
|
|
KEY(2, 4, KEY_J), KEY(2, 5, KEY_H),
|
|
KEY(2, 6, KEY_G), KEY(2, 7, KEY_F),
|
|
|
|
KEY(3, 0, KEY_D), KEY(3, 1, KEY_S),
|
|
KEY(3, 2, KEY_A), KEY(3, 3, KEY_TAB),
|
|
KEY(3, 4, KEY_BACKSPACE), KEY(3, 5, KEY_P),
|
|
KEY(3, 6, KEY_O), KEY(3, 7, KEY_I),
|
|
|
|
KEY(4, 0, KEY_U), KEY(4, 1, KEY_Y),
|
|
KEY(4, 2, KEY_T), KEY(4, 3, KEY_R),
|
|
KEY(4, 4, KEY_E), KEY(4, 5, KEY_W),
|
|
KEY(4, 6, KEY_Q), KEY(4, 7, KEY_MINUS),
|
|
|
|
KEY(5, 0, KEY_0), KEY(5, 1, KEY_9),
|
|
KEY(5, 2, KEY_8), KEY(5, 3, KEY_7),
|
|
KEY(5, 4, KEY_6), KEY(5, 5, KEY_5),
|
|
KEY(5, 6, KEY_4), KEY(5, 7, KEY_3),
|
|
|
|
KEY(6, 0, KEY_2), KEY(6, 1, KEY_1),
|
|
KEY(6, 2, KEY_ENTER), KEY(6, 3, KEY_END),
|
|
KEY(6, 4, KEY_DOWN), KEY(6, 5, KEY_UP),
|
|
KEY(6, 6, KEY_MENU), KEY(6, 7, KEY_F1),
|
|
|
|
KEY(7, 0, KEY_LEFT), KEY(7, 1, KEY_RIGHT),
|
|
KEY(7, 2, KEY_BACK), KEY(7, 3, KEY_HOME),
|
|
KEY(7, 4, 0), KEY(7, 5, 0),
|
|
KEY(7, 6, 0), KEY(7, 7, 0),
|
|
};
|
|
|
|
struct pxa27x_keypad_platform_data em_x270_exeda_keypad_info = {
|
|
/* code map for the matrix keys */
|
|
.matrix_key_rows = 8,
|
|
.matrix_key_cols = 8,
|
|
.matrix_key_map = em_x270_exeda_matrix_keys,
|
|
.matrix_key_map_size = ARRAY_SIZE(em_x270_exeda_matrix_keys),
|
|
};
|
|
|
|
static void __init em_x270_init_keypad(void)
|
|
{
|
|
if (machine_is_em_x270())
|
|
pxa_set_keypad_info(&em_x270_module_keypad_info);
|
|
else
|
|
pxa_set_keypad_info(&em_x270_exeda_keypad_info);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_keypad(void) {}
|
|
#endif
|
|
|
|
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
|
|
static struct gpio_keys_button gpio_keys_button[] = {
|
|
[0] = {
|
|
.desc = "sleep/wakeup",
|
|
.code = KEY_SUSPEND,
|
|
.type = EV_PWR,
|
|
.gpio = 1,
|
|
.wakeup = 1,
|
|
},
|
|
};
|
|
|
|
static struct gpio_keys_platform_data em_x270_gpio_keys_data = {
|
|
.buttons = gpio_keys_button,
|
|
.nbuttons = 1,
|
|
};
|
|
|
|
static struct platform_device em_x270_gpio_keys = {
|
|
.name = "gpio-keys",
|
|
.id = -1,
|
|
.dev = {
|
|
.platform_data = &em_x270_gpio_keys_data,
|
|
},
|
|
};
|
|
|
|
static void __init em_x270_init_gpio_keys(void)
|
|
{
|
|
platform_device_register(&em_x270_gpio_keys);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_gpio_keys(void) {}
|
|
#endif
|
|
|
|
/* Quick Capture Interface and sensor setup */
|
|
#if defined(CONFIG_VIDEO_PXA27x) || defined(CONFIG_VIDEO_PXA27x_MODULE)
|
|
static struct regulator *em_x270_camera_ldo;
|
|
|
|
static int em_x270_sensor_init(struct device *dev)
|
|
{
|
|
int ret;
|
|
|
|
ret = gpio_request(GPIO93_CAM_RESET, "camera reset");
|
|
if (ret)
|
|
return ret;
|
|
|
|
gpio_direction_output(GPIO93_CAM_RESET, 0);
|
|
|
|
em_x270_camera_ldo = regulator_get(NULL, "vcc cam");
|
|
if (em_x270_camera_ldo == NULL) {
|
|
gpio_free(GPIO93_CAM_RESET);
|
|
return -ENODEV;
|
|
}
|
|
|
|
ret = regulator_enable(em_x270_camera_ldo);
|
|
if (ret) {
|
|
regulator_put(em_x270_camera_ldo);
|
|
gpio_free(GPIO93_CAM_RESET);
|
|
return ret;
|
|
}
|
|
|
|
gpio_set_value(GPIO93_CAM_RESET, 1);
|
|
|
|
return 0;
|
|
}
|
|
|
|
struct pxacamera_platform_data em_x270_camera_platform_data = {
|
|
.init = em_x270_sensor_init,
|
|
.flags = PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
|
|
PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
|
|
.mclk_10khz = 2600,
|
|
};
|
|
|
|
static int em_x270_sensor_power(struct device *dev, int on)
|
|
{
|
|
int ret;
|
|
int is_on = regulator_is_enabled(em_x270_camera_ldo);
|
|
|
|
if (on == is_on)
|
|
return 0;
|
|
|
|
gpio_set_value(GPIO93_CAM_RESET, !on);
|
|
|
|
if (on)
|
|
ret = regulator_enable(em_x270_camera_ldo);
|
|
else
|
|
ret = regulator_disable(em_x270_camera_ldo);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
gpio_set_value(GPIO93_CAM_RESET, on);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static struct soc_camera_link iclink = {
|
|
.bus_id = 0,
|
|
.power = em_x270_sensor_power,
|
|
};
|
|
|
|
static struct i2c_board_info em_x270_i2c_cam_info[] = {
|
|
{
|
|
I2C_BOARD_INFO("mt9m111", 0x48),
|
|
.platform_data = &iclink,
|
|
},
|
|
};
|
|
|
|
static struct i2c_pxa_platform_data em_x270_i2c_info = {
|
|
.fast_mode = 1,
|
|
};
|
|
|
|
static void __init em_x270_init_camera(void)
|
|
{
|
|
pxa_set_i2c_info(&em_x270_i2c_info);
|
|
i2c_register_board_info(0, ARRAY_AND_SIZE(em_x270_i2c_cam_info));
|
|
pxa_set_camera_info(&em_x270_camera_platform_data);
|
|
}
|
|
#else
|
|
static inline void em_x270_init_camera(void) {}
|
|
#endif
|
|
|
|
/* DA9030 related initializations */
|
|
#define REGULATOR_CONSUMER(_name, _dev, _supply) \
|
|
static struct regulator_consumer_supply _name##_consumers[] = { \
|
|
{ \
|
|
.dev = _dev, \
|
|
.supply = _supply, \
|
|
}, \
|
|
}
|
|
|
|
REGULATOR_CONSUMER(ldo3, NULL, "vcc gps");
|
|
REGULATOR_CONSUMER(ldo5, NULL, "vcc cam");
|
|
REGULATOR_CONSUMER(ldo10, &pxa_device_mci.dev, "vcc sdio");
|
|
REGULATOR_CONSUMER(ldo12, NULL, "vcc usb");
|
|
REGULATOR_CONSUMER(ldo19, NULL, "vcc gprs");
|
|
|
|
#define REGULATOR_INIT(_ldo, _min_uV, _max_uV, _ops_mask) \
|
|
static struct regulator_init_data _ldo##_data = { \
|
|
.constraints = { \
|
|
.min_uV = _min_uV, \
|
|
.max_uV = _max_uV, \
|
|
.state_mem = { \
|
|
.enabled = 0, \
|
|
}, \
|
|
.valid_ops_mask = _ops_mask, \
|
|
}, \
|
|
.num_consumer_supplies = ARRAY_SIZE(_ldo##_consumers), \
|
|
.consumer_supplies = _ldo##_consumers, \
|
|
};
|
|
|
|
REGULATOR_INIT(ldo3, 3200000, 3200000, REGULATOR_CHANGE_STATUS);
|
|
REGULATOR_INIT(ldo5, 3000000, 3000000, REGULATOR_CHANGE_STATUS);
|
|
REGULATOR_INIT(ldo10, 2000000, 3200000,
|
|
REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_VOLTAGE);
|
|
REGULATOR_INIT(ldo12, 3000000, 3000000, REGULATOR_CHANGE_STATUS);
|
|
REGULATOR_INIT(ldo19, 3200000, 3200000, REGULATOR_CHANGE_STATUS);
|
|
|
|
struct led_info em_x270_led_info = {
|
|
.name = "em-x270:orange",
|
|
.default_trigger = "battery-charging-or-full",
|
|
};
|
|
|
|
struct power_supply_info em_x270_psy_info = {
|
|
.name = "LP555597P6H-FPS",
|
|
.technology = POWER_SUPPLY_TECHNOLOGY_LIPO,
|
|
.voltage_max_design = 4200000,
|
|
.voltage_min_design = 3000000,
|
|
.use_for_apm = 1,
|
|
};
|
|
|
|
static void em_x270_battery_low(void)
|
|
{
|
|
apm_queue_event(APM_LOW_BATTERY);
|
|
}
|
|
|
|
static void em_x270_battery_critical(void)
|
|
{
|
|
apm_queue_event(APM_CRITICAL_SUSPEND);
|
|
}
|
|
|
|
struct da9030_battery_info em_x270_batterty_info = {
|
|
.battery_info = &em_x270_psy_info,
|
|
|
|
.charge_milliamp = 1000,
|
|
.charge_millivolt = 4200,
|
|
|
|
.vbat_low = 3600,
|
|
.vbat_crit = 3400,
|
|
.vbat_charge_start = 4100,
|
|
.vbat_charge_stop = 4200,
|
|
.vbat_charge_restart = 4000,
|
|
|
|
.vcharge_min = 3200,
|
|
.vcharge_max = 5500,
|
|
|
|
.tbat_low = 197,
|
|
.tbat_high = 78,
|
|
.tbat_restart = 100,
|
|
|
|
.batmon_interval = 0,
|
|
|
|
.battery_low = em_x270_battery_low,
|
|
.battery_critical = em_x270_battery_critical,
|
|
};
|
|
|
|
#define DA9030_SUBDEV(_name, _id, _pdata) \
|
|
{ \
|
|
.name = "da903x-" #_name, \
|
|
.id = DA9030_ID_##_id, \
|
|
.platform_data = _pdata, \
|
|
}
|
|
|
|
#define DA9030_LDO(num) DA9030_SUBDEV(regulator, LDO##num, &ldo##num##_data)
|
|
|
|
struct da903x_subdev_info em_x270_da9030_subdevs[] = {
|
|
DA9030_LDO(3),
|
|
DA9030_LDO(5),
|
|
DA9030_LDO(10),
|
|
DA9030_LDO(12),
|
|
DA9030_LDO(19),
|
|
|
|
DA9030_SUBDEV(led, LED_PC, &em_x270_led_info),
|
|
DA9030_SUBDEV(backlight, WLED, &em_x270_led_info),
|
|
DA9030_SUBDEV(battery, BAT, &em_x270_batterty_info),
|
|
};
|
|
|
|
static struct da903x_platform_data em_x270_da9030_info = {
|
|
.num_subdevs = ARRAY_SIZE(em_x270_da9030_subdevs),
|
|
.subdevs = em_x270_da9030_subdevs,
|
|
};
|
|
|
|
static struct i2c_board_info em_x270_i2c_pmic_info = {
|
|
I2C_BOARD_INFO("da9030", 0x49),
|
|
.irq = IRQ_GPIO(0),
|
|
.platform_data = &em_x270_da9030_info,
|
|
};
|
|
|
|
static struct i2c_pxa_platform_data em_x270_pwr_i2c_info = {
|
|
.use_pio = 1,
|
|
};
|
|
|
|
static void __init em_x270_init_da9030(void)
|
|
{
|
|
pxa27x_set_i2c_power_info(&em_x270_pwr_i2c_info);
|
|
i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1);
|
|
}
|
|
|
|
static void __init em_x270_module_init(void)
|
|
{
|
|
pr_info("%s\n", __func__);
|
|
pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));
|
|
|
|
mmc_cd = GPIO13_MMC_CD;
|
|
nand_rb = GPIO56_NAND_RB;
|
|
dm9000_flags = DM9000_PLATF_32BITONLY;
|
|
}
|
|
|
|
static void __init em_x270_exeda_init(void)
|
|
{
|
|
pr_info("%s\n", __func__);
|
|
pxa2xx_mfp_config(ARRAY_AND_SIZE(exeda_pin_config));
|
|
|
|
mmc_cd = GPIO114_MMC_CD;
|
|
nand_rb = GPIO20_NAND_RB;
|
|
dm9000_flags = DM9000_PLATF_16BITONLY;
|
|
}
|
|
|
|
static void __init em_x270_init(void)
|
|
{
|
|
pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config));
|
|
|
|
if (machine_is_em_x270())
|
|
em_x270_module_init();
|
|
else if (machine_is_exeda())
|
|
em_x270_exeda_init();
|
|
else
|
|
panic("Unsupported machine: %d\n", machine_arch_type);
|
|
|
|
em_x270_init_da9030();
|
|
em_x270_init_dm9000();
|
|
em_x270_init_rtc();
|
|
em_x270_init_nand();
|
|
em_x270_init_nor();
|
|
em_x270_init_lcd();
|
|
em_x270_init_mmc();
|
|
em_x270_init_ohci();
|
|
em_x270_init_keypad();
|
|
em_x270_init_gpio_keys();
|
|
em_x270_init_ac97();
|
|
em_x270_init_camera();
|
|
em_x270_init_spi();
|
|
}
|
|
|
|
MACHINE_START(EM_X270, "Compulab EM-X270")
|
|
.boot_params = 0xa0000100,
|
|
.phys_io = 0x40000000,
|
|
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
|
.map_io = pxa_map_io,
|
|
.init_irq = pxa27x_init_irq,
|
|
.timer = &pxa_timer,
|
|
.init_machine = em_x270_init,
|
|
MACHINE_END
|
|
|
|
MACHINE_START(EXEDA, "Compulab eXeda")
|
|
.boot_params = 0xa0000100,
|
|
.phys_io = 0x40000000,
|
|
.io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc,
|
|
.map_io = pxa_map_io,
|
|
.init_irq = pxa27x_init_irq,
|
|
.timer = &pxa_timer,
|
|
.init_machine = em_x270_init,
|
|
MACHINE_END
|