Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c85bce6 authored by Mike Rapoport's avatar Mike Rapoport Committed by Russell King
Browse files

[ARM] 5101/2: EM-X270 updates



Convert EM-X270 pin configuration to use MFP tables and gpio library
Make device initialization dependent on respective driver CONFIG_ value (like
in zylonite)
Add keypad and gpio_key devices

Signed-off-by: default avatarMike Rapoport <mike@compulab.co.il>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent c0b8556f
Loading
Loading
Loading
Loading
+293 −80
Original line number Original line Diff line number Diff line
/*
/*
 * Support for CompuLab EM-x270 platform
 * Support for CompuLab EM-X270 platform
 *
 *
 * Copyright (C) 2007 CompuLab, Ltd.
 * Copyright (C) 2007, 2008 CompuLab, Ltd.
 * Author: Mike Rapoport <mike@compulab.co.il>
 * Author: Mike Rapoport <mike@compulab.co.il>
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
@@ -14,31 +14,159 @@


#include <linux/dm9000.h>
#include <linux/dm9000.h>
#include <linux/rtc-v3020.h>
#include <linux/rtc-v3020.h>

#include <linux/mtd/nand.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/partitions.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
#include <linux/gpio.h>


#include <asm/mach-types.h>
#include <asm/mach-types.h>

#include <asm/mach/arch.h>
#include <asm/mach/arch.h>


#include <asm/arch/mfp-pxa27x.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa-regs.h>
#include <asm/arch/pxa2xx-gpio.h>
#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/pxa27x-udc.h>
#include <asm/arch/audio.h>
#include <asm/arch/audio.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/pxafb.h>
#include <asm/arch/ohci.h>
#include <asm/arch/ohci.h>
#include <asm/arch/mmc.h>
#include <asm/arch/mmc.h>
#include <asm/arch/bitfield.h>
#include <asm/arch/pxa27x_keypad.h>


#include "generic.h"
#include "generic.h"


/* GPIO IRQ usage */
/* GPIO IRQ usage */
#define EM_X270_MMC_PD		(105)
#define GPIO41_ETHIRQ		(41)
#define EM_X270_ETHIRQ		IRQ_GPIO(41)
#define GPIO13_MMC_CD		(13)
#define EM_X270_MMC_IRQ		IRQ_GPIO(13)
#define EM_X270_ETHIRQ		IRQ_GPIO(GPIO41_ETHIRQ)
#define EM_X270_MMC_CD		IRQ_GPIO(GPIO13_MMC_CD)

/* NAND control GPIOs */
#define GPIO11_NAND_CS	(11)
#define GPIO56_NAND_RB	(56)

static unsigned long em_x270_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,

	/* power controls */
	GPIO20_GPIO	| MFP_LPM_DRIVE_LOW,	/* GPRS_PWEN */
	GPIO115_GPIO	| MFP_LPM_DRIVE_LOW,	/* WLAN_PWEN */

	/* NAND controls */
	GPIO11_GPIO	| MFP_LPM_DRIVE_HIGH,	/* NAND CE# */
	GPIO56_GPIO,				/* NAND Ready/Busy */

	/* interrupts */
	GPIO13_GPIO,	/* MMC card detect */
	GPIO41_GPIO,	/* DM9000 interrupt */
};


static struct resource em_x270_dm9k_resource[] = {
#if defined(CONFIG_DM9000) || defined(CONFIG_DM9000_MODULE)
static struct resource em_x270_dm9000_resource[] = {
	[0] = {
	[0] = {
		.start = PXA_CS2_PHYS,
		.start = PXA_CS2_PHYS,
		.end   = PXA_CS2_PHYS + 3,
		.end   = PXA_CS2_PHYS + 3,
@@ -52,36 +180,34 @@ static struct resource em_x270_dm9k_resource[] = {
	[2] = {
	[2] = {
		.start = EM_X270_ETHIRQ,
		.start = EM_X270_ETHIRQ,
		.end   = EM_X270_ETHIRQ,
		.end   = EM_X270_ETHIRQ,
		.flags = IORESOURCE_IRQ,
		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,
	}
	}
};
};


/* for the moment we limit ourselves to 32bit IO until some
static struct dm9000_plat_data em_x270_dm9000_platdata = {
 * better IO routines can be written and tested
 */
static struct dm9000_plat_data em_x270_dm9k_platdata = {
	.flags		= DM9000_PLATF_32BITONLY,
	.flags		= DM9000_PLATF_32BITONLY,
};
};


/* Ethernet device */
static struct platform_device em_x270_dm9000 = {
static struct platform_device em_x270_dm9k = {
	.name		= "dm9000",
	.name		= "dm9000",
	.id		= 0,
	.id		= 0,
	.num_resources	= ARRAY_SIZE(em_x270_dm9k_resource),
	.num_resources	= ARRAY_SIZE(em_x270_dm9000_resource),
	.resource	= em_x270_dm9k_resource,
	.resource	= em_x270_dm9000_resource,
	.dev		= {
	.dev		= {
		.platform_data = &em_x270_dm9k_platdata,
		.platform_data = &em_x270_dm9000_platdata,
	}
	}
};
};


/* WM9712 touchscreen controller. Hopefully the driver will make it to
static void __init em_x270_init_dm9000(void)
 * the mainstream sometime */
{
static struct platform_device em_x270_ts = {
	platform_device_register(&em_x270_dm9000);
	.name		= "wm97xx-ts",
}
	.id		= -1,
#else
};
static inline void em_x270_init_dm9000(void) {}
#endif


/* RTC */
/* V3020 RTC */
#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE)
static struct resource em_x270_v3020_resource[] = {
static struct resource em_x270_v3020_resource[] = {
	[0] = {
	[0] = {
		.start = PXA_CS4_PHYS,
		.start = PXA_CS4_PHYS,
@@ -104,20 +230,26 @@ static struct platform_device em_x270_rtc = {
	}
	}
};
};


/* NAND flash */
static void __init em_x270_init_rtc(void)
#define GPIO_NAND_CS	(11)
{
#define GPIO_NAND_RB	(56)
	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)
static inline void nand_cs_on(void)
{
{
	GPCR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
	gpio_set_value(GPIO11_NAND_CS, 0);
}
}


static void nand_cs_off(void)
static void nand_cs_off(void)
{
{
	dsb();
	dsb();


	GPSR(GPIO_NAND_CS) = GPIO_bit(GPIO_NAND_CS);
	gpio_set_value(GPIO11_NAND_CS, 1);
}
}


/* hardware specific access to control-lines */
/* hardware specific access to control-lines */
@@ -157,7 +289,7 @@ static int em_x270_nand_device_ready(struct mtd_info *mtd)
{
{
	dsb();
	dsb();


	return GPLR(GPIO_NAND_RB) & GPIO_bit(GPIO_NAND_RB);
	return gpio_get_value(GPIO56_NAND_RB);
}
}


static struct mtd_partition em_x270_partition_info[] = {
static struct mtd_partition em_x270_partition_info[] = {
@@ -210,16 +342,35 @@ static struct platform_device em_x270_nand = {
	}
	}
};
};


/* platform devices */
static void __init em_x270_init_nand(void)
static struct platform_device *platform_devices[] __initdata = {
{
	&em_x270_dm9k,
	int err;
	&em_x270_ts,

	&em_x270_rtc,
	err = gpio_request(GPIO11_NAND_CS, "NAND CS");
	&em_x270_nand,
	if (err) {
};
		pr_warning("EM-X270: failed to request NAND CS gpio\n");
		return;
	}

	gpio_direction_output(GPIO11_NAND_CS, 1);

	err = gpio_request(GPIO56_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(GPIO56_NAND_RB);

	platform_device_register(&em_x270_nand);
}
#else
static inline void em_x270_init_nand(void) {}
#endif


/* PXA27x OHCI controller setup */
/* 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)
static int em_x270_ohci_init(struct device *dev)
{
{
	/* Set the Power Control Polarity Low */
	/* Set the Power Control Polarity Low */
@@ -237,25 +388,21 @@ static struct pxaohci_platform_data em_x270_ohci_platform_data = {
	.init		= em_x270_ohci_init,
	.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 int em_x270_mci_init(struct device *dev,
static int em_x270_mci_init(struct device *dev,
			    irq_handler_t em_x270_detect_int,
			    irq_handler_t em_x270_detect_int,
			    void *data)
			    void *data)
{
{
	int err;
	int err = request_irq(EM_X270_MMC_CD, em_x270_detect_int,

	/* setup GPIO for PXA27x MMC controller */
	pxa_gpio_mode(GPIO32_MMCCLK_MD);
	pxa_gpio_mode(GPIO112_MMCCMD_MD);
	pxa_gpio_mode(GPIO92_MMCDAT0_MD);
	pxa_gpio_mode(GPIO109_MMCDAT1_MD);
	pxa_gpio_mode(GPIO110_MMCDAT2_MD);
	pxa_gpio_mode(GPIO111_MMCDAT3_MD);

	/* EM-X270 uses GPIO13 as SD power enable */
	pxa_gpio_mode(EM_X270_MMC_PD | GPIO_OUT);

	err = request_irq(EM_X270_MMC_IRQ, em_x270_detect_int,
			      IRQF_DISABLED | IRQF_TRIGGER_FALLING,
			      IRQF_DISABLED | IRQF_TRIGGER_FALLING,
			      "MMC card detect", data);
			      "MMC card detect", data);
	if (err) {
	if (err) {
@@ -279,7 +426,8 @@ static void em_x270_mci_setpower(struct device *dev, unsigned int vdd)


static void em_x270_mci_exit(struct device *dev, void *data)
static void em_x270_mci_exit(struct device *dev, void *data)
{
{
	free_irq(EM_X270_MMC_IRQ, data);
	int irq = gpio_to_irq(GPIO13_MMC_CD);
	free_irq(irq, data);
}
}


static struct pxamci_platform_data em_x270_mci_platform_data = {
static struct pxamci_platform_data em_x270_mci_platform_data = {
@@ -289,7 +437,16 @@ static struct pxamci_platform_data em_x270_mci_platform_data = {
	.exit		= em_x270_mci_exit,
	.exit		= em_x270_mci_exit,
};
};


static void __init em_x270_init_mmc(void)
{
	pxa_set_mci_info(&em_x270_mci_platform_data);
}
#else
static inline void em_x270_init_mmc(void) {}
#endif

/* LCD 480x640 */
/* LCD 480x640 */
#if defined(CONFIG_FB_PXA) || defined(CONFIG_FB_PXA_MODULE)
static struct pxafb_mode_info em_x270_lcd_mode = {
static struct pxafb_mode_info em_x270_lcd_mode = {
	.pixclock	= 50000,
	.pixclock	= 50000,
	.bpp		= 16,
	.bpp		= 16,
@@ -307,40 +464,96 @@ static struct pxafb_mode_info em_x270_lcd_mode = {
static struct pxafb_mach_info em_x270_lcd = {
static struct pxafb_mach_info em_x270_lcd = {
	.modes		= &em_x270_lcd_mode,
	.modes		= &em_x270_lcd_mode,
	.num_modes	= 1,
	.num_modes	= 1,
	.cmap_inverse	= 0,
	.lcd_conn	= LCD_COLOR_TFT_16BPP,
	.cmap_static	= 0,
	.lccr0		= LCCR0_PAS,
	.lccr3		= LCCR3_PixClkDiv(0x01) | LCCR3_Acb(0xff),
};
};

static void __init em_x270_init_lcd(void)
static void __init em_x270_init(void)
{
{
	/* setup LCD */
	set_pxa_fb_info(&em_x270_lcd);
	set_pxa_fb_info(&em_x270_lcd);
}
#else
static inline void em_x270_init_lcd(void) {}
#endif


	/* register EM-X270 platform devices */
#if defined(CONFIG_SND_PXA2XX_AC97) || defined(CONFIG_SND_PXA2XX_AC97_MODULE)
	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));
static void __init em_x270_init_ac97(void)
{
	pxa_set_ac97_info(NULL);
	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_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),
};


	/* set MCI and OHCI platform parameters */
struct pxa27x_keypad_platform_data em_x270_keypad_info = {
	pxa_set_mci_info(&em_x270_mci_platform_data);
	/* code map for the matrix keys */
	pxa_set_ohci_info(&em_x270_ohci_platform_data);
	.matrix_key_rows	= 3,
	.matrix_key_cols	= 3,
	.matrix_key_map		= em_x270_matrix_keys,
	.matrix_key_map_size	= ARRAY_SIZE(em_x270_matrix_keys),
};


	/* setup STUART GPIOs */
static void __init em_x270_init_keypad(void)
	pxa_gpio_mode(GPIO46_STRXD_MD);
{
	pxa_gpio_mode(GPIO47_STTXD_MD);
	pxa_set_keypad_info(&em_x270_keypad_info);
}
#else
static inline void em_x270_init_keypad(void) {}
#endif


	/* setup BTUART GPIOs */
#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
	pxa_gpio_mode(GPIO42_BTRXD_MD);
static struct gpio_keys_button gpio_keys_button[] = {
	pxa_gpio_mode(GPIO43_BTTXD_MD);
	[0] = {
	pxa_gpio_mode(GPIO44_BTCTS_MD);
		.desc	= "sleep/wakeup",
	pxa_gpio_mode(GPIO45_BTRTS_MD);
		.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,
};


	/* Setup interrupt for dm9000 */
static struct platform_device em_x270_gpio_keys = {
	set_irq_type(EM_X270_ETHIRQ, IRQT_RISING);
	.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

static void __init em_x270_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_pin_config));

	em_x270_init_dm9000();
	em_x270_init_rtc();
	em_x270_init_nand();
	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();
}
}


MACHINE_START(EM_X270, "Compulab EM-x270")
MACHINE_START(EM_X270, "Compulab EM-X270")
	.boot_params	= 0xa0000100,
	.boot_params	= 0xa0000100,
	.phys_io	= 0x40000000,
	.phys_io	= 0x40000000,
	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,
	.io_pg_offst	= (io_p2v(0x40000000) >> 18) & 0xfffc,