diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-15 11:31:54 +1100 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2008-10-15 11:31:54 +1100 |
commit | 6dc6472581f693b5fc95aebedf67b4960fb85cf0 (patch) | |
tree | 06a5a9a08519950575505273eabced331ed51405 /arch/arm/mach-pxa/corgi.c | |
parent | ee673eaa72d8d185012b1027a05e25aba18c267f (diff) | |
parent | 8acd3a60bcca17c6d89c73cee3ad6057eb83ba1e (diff) |
Merge commit 'origin'
Manual fixup of conflicts on:
arch/powerpc/include/asm/dcr-regs.h
drivers/net/ibm_newemac/core.h
Diffstat (limited to 'arch/arm/mach-pxa/corgi.c')
-rw-r--r-- | arch/arm/mach-pxa/corgi.c | 478 |
1 files changed, 263 insertions, 215 deletions
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index e703a8d209e..65558d6aa22 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -20,7 +20,12 @@ #include <linux/interrupt.h> #include <linux/mmc/host.h> #include <linux/pm.h> +#include <linux/gpio.h> #include <linux/backlight.h> +#include <linux/io.h> +#include <linux/spi/spi.h> +#include <linux/spi/ads7846.h> +#include <linux/spi/corgi_lcd.h> #include <video/w100fb.h> #include <asm/setup.h> @@ -28,7 +33,6 @@ #include <asm/mach-types.h> #include <mach/hardware.h> #include <asm/irq.h> -#include <asm/io.h> #include <asm/system.h> #include <asm/mach/arch.h> @@ -37,11 +41,12 @@ #include <mach/pxa-regs.h> #include <mach/pxa2xx-regs.h> -#include <mach/pxa2xx-gpio.h> +#include <mach/mfp-pxa25x.h> #include <mach/i2c.h> #include <mach/irda.h> #include <mach/mmc.h> #include <mach/udc.h> +#include <mach/pxa2xx_spi.h> #include <mach/corgi.h> #include <mach/sharpsl.h> @@ -52,6 +57,61 @@ #include "devices.h" #include "sharpsl.h" +static unsigned long corgi_pin_config[] __initdata = { + /* Static Memory I/O */ + GPIO78_nCS_2, /* w100fb */ + GPIO80_nCS_4, /* scoop */ + + /* SSP1 */ + GPIO23_SSP1_SCLK, + GPIO25_SSP1_TXD, + GPIO26_SSP1_RXD, + GPIO24_GPIO, /* CORGI_GPIO_ADS7846_CS - SFRM as chip select */ + + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO30_I2S_SDATA_OUT, + GPIO31_I2S_SYNC, + GPIO32_I2S_SYSCLK, + + /* Infra-Red */ + GPIO47_FICP_TXD, + GPIO46_FICP_RXD, + + /* FFUART */ + GPIO40_FFUART_DTR, + GPIO41_FFUART_RTS, + GPIO39_FFUART_TXD, + GPIO37_FFUART_DSR, + GPIO34_FFUART_RXD, + GPIO35_FFUART_CTS, + + /* PC Card */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO52_nPCE_1, + GPIO53_nPCE_2, + GPIO54_nPSKTSEL, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + + /* MMC */ + GPIO6_MMC_CLK, + GPIO8_MMC_CS0, + + /* GPIO */ + GPIO9_GPIO, /* CORGI_GPIO_nSD_DETECT */ + GPIO7_GPIO, /* CORGI_GPIO_nSD_WP */ + GPIO33_GPIO, /* CORGI_GPIO_SD_PWR */ + GPIO22_GPIO, /* CORGI_GPIO_IR_ON */ + GPIO44_GPIO, /* CORGI_GPIO_HSYNC */ + + GPIO1_GPIO | WAKEUP_ON_EDGE_RISE, +}; /* * Corgi SCOOP Device @@ -67,6 +127,7 @@ static struct resource corgi_scoop_resources[] = { static struct scoop_config corgi_scoop_setup = { .io_dir = CORGI_SCOOP_IO_DIR, .io_out = CORGI_SCOOP_IO_OUT, + .gpio_base = CORGI_SCOOP_GPIO_BASE, }; struct platform_device corgiscoop_device = { @@ -79,27 +140,6 @@ struct platform_device corgiscoop_device = { .resource = corgi_scoop_resources, }; -static void corgi_pcmcia_init(void) -{ - /* Setup default state of GPIO outputs - before we enable them as outputs. */ - GPSR(GPIO48_nPOE) = GPIO_bit(GPIO48_nPOE) | - GPIO_bit(GPIO49_nPWE) | GPIO_bit(GPIO50_nPIOR) | - GPIO_bit(GPIO51_nPIOW) | GPIO_bit(GPIO52_nPCE_1) | - GPIO_bit(GPIO53_nPCE_2); - - pxa_gpio_mode(GPIO48_nPOE_MD); - pxa_gpio_mode(GPIO49_nPWE_MD); - pxa_gpio_mode(GPIO50_nPIOR_MD); - pxa_gpio_mode(GPIO51_nPIOW_MD); - pxa_gpio_mode(GPIO55_nPREG_MD); - pxa_gpio_mode(GPIO56_nPWAIT_MD); - pxa_gpio_mode(GPIO57_nIOIS16_MD); - pxa_gpio_mode(GPIO52_nPCE_1_MD); - pxa_gpio_mode(GPIO53_nPCE_2_MD); - pxa_gpio_mode(GPIO54_pSKTSEL_MD); -} - static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { { .dev = &corgiscoop_device.dev, @@ -112,58 +152,10 @@ static struct scoop_pcmcia_dev corgi_pcmcia_scoop[] = { static struct scoop_pcmcia_config corgi_pcmcia_config = { .devs = &corgi_pcmcia_scoop[0], .num_devs = 1, - .pcmcia_init = corgi_pcmcia_init, }; EXPORT_SYMBOL(corgiscoop_device); - -/* - * Corgi SSP Device - * - * Set the parent as the scoop device because a lot of SSP devices - * also use scoop functions and this makes the power up/down order - * work correctly. - */ -struct platform_device corgissp_device = { - .name = "corgi-ssp", - .dev = { - .parent = &corgiscoop_device.dev, - }, - .id = -1, -}; - -struct corgissp_machinfo corgi_ssp_machinfo = { - .port = 1, - .cs_lcdcon = CORGI_GPIO_LCDCON_CS, - .cs_ads7846 = CORGI_GPIO_ADS7846_CS, - .cs_max1111 = CORGI_GPIO_MAX1111_CS, - .clk_lcdcon = 76, - .clk_ads7846 = 2, - .clk_max1111 = 8, -}; - - -/* - * LCD/Framebuffer - */ -static void w100_lcdtg_suspend(struct w100fb_par *par) -{ - corgi_lcdtg_suspend(); -} - -static void w100_lcdtg_init(struct w100fb_par *par) -{ - corgi_lcdtg_hw_init(par->xres); -} - - -static struct w100_tg_info corgi_lcdtg_info = { - .change = w100_lcdtg_init, - .suspend = w100_lcdtg_suspend, - .resume = w100_lcdtg_init, -}; - static struct w100_mem_info corgi_fb_mem = { .ext_cntl = 0x00040003, .sdram_mode_reg = 0x00650021, @@ -242,7 +234,6 @@ static struct w100_mode corgi_fb_modes[] = { }; static struct w100fb_mach_info corgi_fb_info = { - .tg = &corgi_lcdtg_info, .init_mode = INIT_MODE_ROTATED, .mem = &corgi_fb_mem, .regs = &corgi_fb_regs, @@ -268,60 +259,10 @@ static struct platform_device corgifb_device = { .resource = corgi_fb_resources, .dev = { .platform_data = &corgi_fb_info, - .parent = &corgissp_device.dev, }, }; - -/* - * Corgi Backlight Device - */ -static void corgi_bl_kick_battery(void) -{ - void (*kick_batt)(void); - - kick_batt = symbol_get(sharpsl_battery_kick); - if (kick_batt) { - kick_batt(); - symbol_put(sharpsl_battery_kick); - } -} - -static void corgi_bl_set_intensity(int intensity) -{ - if (intensity > 0x10) - intensity += 0x10; - - /* Bits 0-4 are accessed via the SSP interface */ - corgi_ssp_blduty_set(intensity & 0x1f); - - /* Bit 5 is via SCOOP */ - if (intensity & 0x0020) - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT); - else - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_BACKLIGHT_CONT); -} - -static struct generic_bl_info corgi_bl_machinfo = { - .name = "corgi-bl", - .max_intensity = 0x2f, - .default_intensity = 0x1f, - .limit_mask = 0x0b, - .set_bl_intensity = corgi_bl_set_intensity, - .kick_battery = corgi_bl_kick_battery, -}; - -static struct platform_device corgibl_device = { - .name = "generic-bl", - .dev = { - .parent = &corgifb_device.dev, - .platform_data = &corgi_bl_machinfo, - }, - .id = -1, -}; - - /* * Corgi Keyboard Device */ @@ -330,75 +271,35 @@ static struct platform_device corgikbd_device = { .id = -1, }; - /* * Corgi LEDs */ -static struct platform_device corgiled_device = { - .name = "corgi-led", - .id = -1, -}; - - -/* - * Corgi Touch Screen Device - */ -static unsigned long (*get_hsync_invperiod)(struct device *dev); - -static void inline sharpsl_wait_sync(int gpio) -{ - while((GPLR(gpio) & GPIO_bit(gpio)) == 0); - while((GPLR(gpio) & GPIO_bit(gpio)) != 0); -} - -static unsigned long corgi_get_hsync_invperiod(void) -{ - if (!get_hsync_invperiod) - get_hsync_invperiod = symbol_get(w100fb_get_hsynclen); - if (!get_hsync_invperiod) - return 0; - - return get_hsync_invperiod(&corgifb_device.dev); -} - -static void corgi_put_hsync(void) -{ - if (get_hsync_invperiod) - symbol_put(w100fb_get_hsynclen); - get_hsync_invperiod = NULL; -} - -static void corgi_wait_hsync(void) -{ - sharpsl_wait_sync(CORGI_GPIO_HSYNC); -} - -static struct resource corgits_resources[] = { - [0] = { - .start = CORGI_IRQ_GPIO_TP_INT, - .end = CORGI_IRQ_GPIO_TP_INT, - .flags = IORESOURCE_IRQ, +static struct gpio_led corgi_gpio_leds[] = { + { + .name = "corgi:amber:charge", + .default_trigger = "sharpsl-charge", + .gpio = CORGI_GPIO_LED_ORANGE, + }, + { + .name = "corgi:green:mail", + .default_trigger = "nand-disk", + .gpio = CORGI_GPIO_LED_GREEN, }, }; -static struct corgits_machinfo corgi_ts_machinfo = { - .get_hsync_invperiod = corgi_get_hsync_invperiod, - .put_hsync = corgi_put_hsync, - .wait_hsync = corgi_wait_hsync, +static struct gpio_led_platform_data corgi_gpio_leds_info = { + .leds = corgi_gpio_leds, + .num_leds = ARRAY_SIZE(corgi_gpio_leds), }; -static struct platform_device corgits_device = { - .name = "corgi-ts", +static struct platform_device corgiled_device = { + .name = "leds-gpio", + .id = -1, .dev = { - .parent = &corgissp_device.dev, - .platform_data = &corgi_ts_machinfo, + .platform_data = &corgi_gpio_leds_info, }, - .id = -1, - .num_resources = ARRAY_SIZE(corgits_resources), - .resource = corgits_resources, }; - /* * MMC/SD Device * @@ -411,20 +312,42 @@ static int corgi_mci_init(struct device *dev, irq_handler_t corgi_detect_int, vo { int err; - /* setup GPIO for PXA25x MMC controller */ - pxa_gpio_mode(GPIO6_MMCCLK_MD); - pxa_gpio_mode(GPIO8_MMCCS0_MD); - pxa_gpio_mode(CORGI_GPIO_nSD_DETECT | GPIO_IN); - pxa_gpio_mode(CORGI_GPIO_SD_PWR | GPIO_OUT); + err = gpio_request(CORGI_GPIO_nSD_DETECT, "nSD_DETECT"); + if (err) + goto err_out; - corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); + err = gpio_request(CORGI_GPIO_nSD_WP, "nSD_WP"); + if (err) + goto err_free_1; - err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, - IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - "MMC card detect", data); + err = gpio_request(CORGI_GPIO_SD_PWR, "SD_PWR"); if (err) - printk(KERN_ERR "corgi_mci_init: MMC/SD: can't request MMC card detect IRQ\n"); + goto err_free_2; + gpio_direction_input(CORGI_GPIO_nSD_DETECT); + gpio_direction_input(CORGI_GPIO_nSD_WP); + gpio_direction_output(CORGI_GPIO_SD_PWR, 0); + + corgi_mci_platform_data.detect_delay = msecs_to_jiffies(250); + + err = request_irq(CORGI_IRQ_GPIO_nSD_DETECT, corgi_detect_int, + IRQF_DISABLED | IRQF_TRIGGER_RISING | + IRQF_TRIGGER_FALLING, + "MMC card detect", data); + if (err) { + pr_err("%s: MMC/SD: can't request MMC card detect IRQ\n", + __func__); + goto err_free_3; + } + return 0; + +err_free_3: + gpio_free(CORGI_GPIO_SD_PWR); +err_free_2: + gpio_free(CORGI_GPIO_nSD_WP); +err_free_1: + gpio_free(CORGI_GPIO_nSD_DETECT); +err_out: return err; } @@ -432,20 +355,20 @@ static void corgi_mci_setpower(struct device *dev, unsigned int vdd) { struct pxamci_platform_data* p_d = dev->platform_data; - if (( 1 << vdd) & p_d->ocr_mask) - GPSR1 = GPIO_bit(CORGI_GPIO_SD_PWR); - else - GPCR1 = GPIO_bit(CORGI_GPIO_SD_PWR); + gpio_set_value(CORGI_GPIO_SD_PWR, ((1 << vdd) & p_d->ocr_mask)); } static int corgi_mci_get_ro(struct device *dev) { - return GPLR(CORGI_GPIO_nSD_WP) & GPIO_bit(CORGI_GPIO_nSD_WP); + return gpio_get_value(CORGI_GPIO_nSD_WP); } static void corgi_mci_exit(struct device *dev, void *data) { free_irq(CORGI_IRQ_GPIO_nSD_DETECT, data); + gpio_free(CORGI_GPIO_SD_PWR); + gpio_free(CORGI_GPIO_nSD_WP); + gpio_free(CORGI_GPIO_nSD_DETECT); } static struct pxamci_platform_data corgi_mci_platform_data = { @@ -462,16 +385,32 @@ static struct pxamci_platform_data corgi_mci_platform_data = { */ static void corgi_irda_transceiver_mode(struct device *dev, int mode) { - if (mode & IR_OFF) - GPSR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); - else - GPCR(CORGI_GPIO_IR_ON) = GPIO_bit(CORGI_GPIO_IR_ON); + gpio_set_value(CORGI_GPIO_IR_ON, mode & IR_OFF); pxa2xx_transceiver_mode(dev, mode); } +static int corgi_irda_startup(struct device *dev) +{ + int err; + + err = gpio_request(CORGI_GPIO_IR_ON, "IR_ON"); + if (err) + return err; + + gpio_direction_output(CORGI_GPIO_IR_ON, 1); + return 0; +} + +static void corgi_irda_shutdown(struct device *dev) +{ + gpio_free(CORGI_GPIO_IR_ON); +} + static struct pxaficp_platform_data corgi_ficp_platform_data = { - .transceiver_cap = IR_SIRMODE | IR_OFF, - .transceiver_mode = corgi_irda_transceiver_mode, + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = corgi_irda_transceiver_mode, + .startup = corgi_irda_startup, + .shutdown = corgi_irda_shutdown, }; @@ -483,14 +422,129 @@ static struct pxa2xx_udc_mach_info udc_info __initdata = { .gpio_pullup = CORGI_GPIO_USB_PULLUP, }; +#if defined(CONFIG_SPI_PXA2XX) || defined(CONFIG_SPI_PXA2XX_MASTER) +static struct pxa2xx_spi_master corgi_spi_info = { + .num_chipselect = 3, +}; + +static struct ads7846_platform_data corgi_ads7846_info = { + .model = 7846, + .vref_delay_usecs = 100, + .x_plate_ohms = 419, + .y_plate_ohms = 486, + .gpio_pendown = CORGI_GPIO_TP_INT, +}; + +static void corgi_ads7846_cs(u32 command) +{ + gpio_set_value(CORGI_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT)); +} + +static struct pxa2xx_spi_chip corgi_ads7846_chip = { + .cs_control = corgi_ads7846_cs, +}; + +static void corgi_bl_kick_battery(void) +{ + void (*kick_batt)(void); + + kick_batt = symbol_get(sharpsl_battery_kick); + if (kick_batt) { + kick_batt(); + symbol_put(sharpsl_battery_kick); + } +} + +static struct corgi_lcd_platform_data corgi_lcdcon_info = { + .init_mode = CORGI_LCD_MODE_VGA, + .max_intensity = 0x2f, + .default_intensity = 0x1f, + .limit_mask = 0x0b, + .gpio_backlight_cont = CORGI_GPIO_BACKLIGHT_CONT, + .gpio_backlight_on = -1, + .kick_battery = corgi_bl_kick_battery, +}; + +static void corgi_lcdcon_cs(u32 command) +{ + gpio_set_value(CORGI_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT)); +} + +static struct pxa2xx_spi_chip corgi_lcdcon_chip = { + .cs_control = corgi_lcdcon_cs, +}; + +static void corgi_max1111_cs(u32 command) +{ + gpio_set_value(CORGI_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT)); +} + +static struct pxa2xx_spi_chip corgi_max1111_chip = { + .cs_control = corgi_max1111_cs, +}; + +static struct spi_board_info corgi_spi_devices[] = { + { + .modalias = "ads7846", + .max_speed_hz = 1200000, + .bus_num = 1, + .chip_select = 0, + .platform_data = &corgi_ads7846_info, + .controller_data= &corgi_ads7846_chip, + .irq = gpio_to_irq(CORGI_GPIO_TP_INT), + }, { + .modalias = "corgi-lcd", + .max_speed_hz = 50000, + .bus_num = 1, + .chip_select = 1, + .platform_data = &corgi_lcdcon_info, + .controller_data= &corgi_lcdcon_chip, + }, { + .modalias = "max1111", + .max_speed_hz = 450000, + .bus_num = 1, + .chip_select = 2, + .controller_data= &corgi_max1111_chip, + }, +}; + +static void __init corgi_init_spi(void) +{ + int err; + + err = gpio_request(CORGI_GPIO_ADS7846_CS, "ADS7846_CS"); + if (err) + return; + + err = gpio_request(CORGI_GPIO_LCDCON_CS, "LCDCON_CS"); + if (err) + goto err_free_1; + + err = gpio_request(CORGI_GPIO_MAX1111_CS, "MAX1111_CS"); + if (err) + goto err_free_2; + + gpio_direction_output(CORGI_GPIO_ADS7846_CS, 1); + gpio_direction_output(CORGI_GPIO_LCDCON_CS, 1); + gpio_direction_output(CORGI_GPIO_MAX1111_CS, 1); + + pxa2xx_set_spi_info(1, &corgi_spi_info); + spi_register_board_info(ARRAY_AND_SIZE(corgi_spi_devices)); + return; + +err_free_2: + gpio_free(CORGI_GPIO_LCDCON_CS); +err_free_1: + gpio_free(CORGI_GPIO_ADS7846_CS); +} +#else +static inline void corgi_init_spi(void) {} +#endif static struct platform_device *devices[] __initdata = { &corgiscoop_device, - &corgissp_device, &corgifb_device, &corgikbd_device, - &corgibl_device, - &corgits_device, &corgiled_device, }; @@ -498,7 +552,8 @@ static void corgi_poweroff(void) { if (!machine_is_corgi()) /* Green LED off tells the bootloader to halt */ - reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + gpio_set_value(CORGI_GPIO_LED_GREEN, 0); + arm_machine_restart('h'); } @@ -506,7 +561,8 @@ static void corgi_restart(char mode) { if (!machine_is_corgi()) /* Green LED on tells the bootloader to reboot */ - set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); + gpio_set_value(CORGI_GPIO_LED_GREEN, 1); + arm_machine_restart('h'); } @@ -515,20 +571,12 @@ static void __init corgi_init(void) pm_power_off = corgi_poweroff; arm_pm_restart = corgi_restart; - /* setup sleep mode values */ - PWER = 0x00000002; - PFER = 0x00000000; - PRER = 0x00000002; - PGSR0 = 0x0158C000; - PGSR1 = 0x00FF0080; - PGSR2 = 0x0001C004; /* Stop 3.6MHz and drive HIGH to PCMCIA and CS */ PCFR |= PCFR_OPDE; - corgi_ssp_set_machinfo(&corgi_ssp_machinfo); + pxa2xx_mfp_config(ARRAY_AND_SIZE(corgi_pin_config)); - pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT); - pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN); + corgi_init_spi(); pxa_set_udc_info(&udc_info); pxa_set_mci_info(&corgi_mci_platform_data); |