diff options
Diffstat (limited to 'arch/arm/mach-pxa')
48 files changed, 3546 insertions, 788 deletions
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig index 17d3fbd368a..f4533f8ff4e 100644 --- a/arch/arm/mach-pxa/Kconfig +++ b/arch/arm/mach-pxa/Kconfig @@ -51,6 +51,12 @@ config MACH_INTELMOTE2 select IWMMXT select PXA_HAVE_BOARD_IRQS +config MACH_STARGATE2 + bool "Intel Stargate 2 Platform" + select PXA27x + select IWMMXT + select PXA_HAVE_BOARD_IRQS + config ARCH_LUBBOCK bool "Intel DBPXA250 Development Platform" select PXA25x @@ -88,6 +94,10 @@ config PXA_SHARPSL SL-C3000 (Spitz), SL-C3100 (Borzoi) or SL-C6000x (Tosa) handheld computer. +config SHARPSL_PM + bool + select APM_EMULATION + config CORGI_SSP_DEPRECATED bool select PXA_SSP @@ -280,6 +290,7 @@ config MACH_ZYLONITE select PXA3xx select PXA_SSP select HAVE_PWM + select PXA_HAVE_BOARD_IRQS config MACH_LITTLETON bool "PXA3xx Form Factor Platform (aka Littleton)" @@ -308,6 +319,14 @@ config MACH_CM_X300 select PXA3xx select CPU_PXA300 +config MACH_H4700 + bool "HP iPAQ hx4700" + select PXA27x + select IWMMXT + select PXA_SSP + select HAVE_PWM + select PXA_HAVE_BOARD_IRQS + config MACH_MAGICIAN bool "Enable HTC Magician Support" select PXA27x @@ -505,12 +524,6 @@ config PXA_SSP help Enable support for PXA2xx SSP ports -config PXA_PWM - tristate - default BACKLIGHT_PWM - help - Enable support for PXA2xx/PXA3xx PWM controllers - config TOSA_BT tristate "Control the state of built-in bluetooth chip on Sharp SL-6000" depends on MACH_TOSA diff --git a/arch/arm/mach-pxa/Makefile b/arch/arm/mach-pxa/Makefile index 682dbf4e14b..d18ffef44b8 100644 --- a/arch/arm/mach-pxa/Makefile +++ b/arch/arm/mach-pxa/Makefile @@ -15,7 +15,6 @@ endif # Generic drivers that other drivers may depend upon obj-$(CONFIG_PXA_SSP) += ssp.o -obj-$(CONFIG_PXA_PWM) += pwm.o # SoC-specific code obj-$(CONFIG_PXA25x) += mfp-pxa2xx.o pxa2xx.o pxa25x.o @@ -47,6 +46,7 @@ obj-$(CONFIG_MACH_PCM027) += pcm027.o obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o obj-$(CONFIG_MACH_TOSA) += tosa.o obj-$(CONFIG_MACH_EM_X270) += em-x270.o +obj-$(CONFIG_MACH_H4700) += hx4700.o obj-$(CONFIG_MACH_MAGICIAN) += magician.o obj-$(CONFIG_MACH_HIMALAYA) += himalaya.o obj-$(CONFIG_MACH_MIOA701) += mioa701.o mioa701_bootresume.o @@ -78,6 +78,7 @@ obj-$(CONFIG_MACH_CM_X300) += cm-x300.o obj-$(CONFIG_PXA_EZX) += ezx.o obj-$(CONFIG_MACH_INTELMOTE2) += imote2.o +obj-$(CONFIG_MACH_STARGATE2) += stargate2.o obj-$(CONFIG_MACH_CSB726) += csb726.o obj-$(CONFIG_CSB726_CSB701) += csb701.o diff --git a/arch/arm/mach-pxa/clock.c b/arch/arm/mach-pxa/clock.c index db52d2c4791..49ae3829231 100644 --- a/arch/arm/mach-pxa/clock.c +++ b/arch/arm/mach-pxa/clock.c @@ -86,20 +86,3 @@ void clks_register(struct clk_lookup *clks, size_t num) for (i = 0; i < num; i++) clkdev_add(&clks[i]); } - -int clk_add_alias(const char *alias, const char *alias_dev_name, char *id, - struct device *dev) -{ - struct clk *r = clk_get(dev, id); - struct clk_lookup *l; - - if (!r) - return -ENODEV; - - l = clkdev_alloc(r, alias, alias_dev_name); - clk_put(r); - if (!l) - return -ENODEV; - clkdev_add(l); - return 0; -} diff --git a/arch/arm/mach-pxa/cm-x270.c b/arch/arm/mach-pxa/cm-x270.c index 34576ba5f5f..1d2cec25391 100644 --- a/arch/arm/mach-pxa/cm-x270.c +++ b/arch/arm/mach-pxa/cm-x270.c @@ -335,6 +335,10 @@ void __init cmx270_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(cmx270_pin_config)); +#ifdef CONFIG_PM + pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP); +#endif + cmx270_init_rtc(); cmx270_init_mmc(); cmx270_init_ohci(); diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index a9f48b1cb54..465da26591b 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -21,18 +21,20 @@ #include <linux/gpio.h> #include <linux/dm9000.h> #include <linux/leds.h> +#include <linux/rtc-v3020.h> #include <linux/i2c.h> #include <linux/i2c/pca953x.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> +#include <asm/setup.h> #include <mach/pxa300.h> #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/ohci.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/pxa3xx_nand.h> #include <asm/mach/map.h> @@ -46,6 +48,11 @@ #define CM_X300_MMC2_IRQ IRQ_GPIO(GPIO82_MMC2_IRQ) +#define GPIO95_RTC_CS (95) +#define GPIO96_RTC_WR (96) +#define GPIO97_RTC_RD (97) +#define GPIO98_RTC_IO (98) + static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = { /* LCD */ GPIO54_LCD_LDD_0, @@ -135,6 +142,12 @@ static mfp_cfg_t cm_x300_mfp_cfg[] __initdata = { GPIO85_GPIO, /* MMC WP */ GPIO99_GPIO, /* Ethernet IRQ */ + /* RTC GPIOs */ + GPIO95_GPIO, /* RTC CS */ + GPIO96_GPIO, /* RTC WR */ + GPIO97_GPIO, /* RTC RD */ + GPIO98_GPIO, /* RTC IO */ + /* Standard I2C */ GPIO21_I2C_SCL, GPIO22_I2C_SDA, @@ -265,6 +278,7 @@ static struct mtd_partition cm_x300_nand_partitions[] = { static struct pxa3xx_nand_platform_data cm_x300_nand_info = { .enable_arbiter = 1, + .keep_config = 1, .parts = cm_x300_nand_partitions, .nr_parts = ARRAY_SIZE(cm_x300_nand_partitions), }; @@ -441,6 +455,31 @@ static void __init cm_x300_init_i2c(void) static inline void cm_x300_init_i2c(void) {} #endif +#if defined(CONFIG_RTC_DRV_V3020) || defined(CONFIG_RTC_DRV_V3020_MODULE) +struct v3020_platform_data cm_x300_v3020_pdata = { + .use_gpio = 1, + .gpio_cs = GPIO95_RTC_CS, + .gpio_wr = GPIO96_RTC_WR, + .gpio_rd = GPIO97_RTC_RD, + .gpio_io = GPIO98_RTC_IO, +}; + +static struct platform_device cm_x300_rtc_device = { + .name = "v3020", + .id = -1, + .dev = { + .platform_data = &cm_x300_v3020_pdata, + } +}; + +static void __init cm_x300_init_rtc(void) +{ + platform_device_register(&cm_x300_rtc_device); +} +#else +static inline void cm_x300_init_rtc(void) {} +#endif + static void __init cm_x300_init(void) { /* board-processor specific GPIO initialization */ @@ -453,6 +492,19 @@ static void __init cm_x300_init(void) cm_x300_init_nand(); cm_x300_init_leds(); cm_x300_init_i2c(); + cm_x300_init_rtc(); +} + +static void __init cm_x300_fixup(struct machine_desc *mdesc, struct tag *tags, + char **cmdline, struct meminfo *mi) +{ + mi->nr_banks = 2; + mi->bank[0].start = 0xa0000000; + mi->bank[0].node = 0; + mi->bank[0].size = (64*1024*1024); + mi->bank[1].start = 0xc0000000; + mi->bank[1].node = 0; + mi->bank[1].size = (64*1024*1024); } MACHINE_START(CM_X300, "CM-X300 module") @@ -463,4 +515,5 @@ MACHINE_START(CM_X300, "CM-X300 module") .init_irq = pxa3xx_init_irq, .timer = &pxa_timer, .init_machine = cm_x300_init, + .fixup = cm_x300_fixup, MACHINE_END diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c index 930e364ccde..962dda2e154 100644 --- a/arch/arm/mach-pxa/corgi.c +++ b/arch/arm/mach-pxa/corgi.c @@ -42,7 +42,7 @@ #include <asm/mach/irq.h> #include <mach/pxa25x.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/irda.h> #include <mach/mmc.h> #include <mach/udc.h> @@ -445,13 +445,8 @@ static struct ads7846_platform_data corgi_ads7846_info = { .wait_for_sync = corgi_wait_for_hsync, }; -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, + .gpio_cs = CORGI_GPIO_ADS7846_CS, }; static void corgi_bl_kick_battery(void) @@ -475,22 +470,12 @@ static struct corgi_lcd_platform_data corgi_lcdcon_info = { .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, + .gpio_cs = CORGI_GPIO_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, + .gpio_cs = CORGI_GPIO_MAX1111_CS, }; static struct spi_board_info corgi_spi_devices[] = { @@ -520,32 +505,8 @@ static struct spi_board_info corgi_spi_devices[] = { 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) {} diff --git a/arch/arm/mach-pxa/corgi_pm.c b/arch/arm/mach-pxa/corgi_pm.c index 7f04b3a761d..a093282fe4d 100644 --- a/arch/arm/mach-pxa/corgi_pm.c +++ b/arch/arm/mach-pxa/corgi_pm.c @@ -41,7 +41,6 @@ static void corgi_charger_init(void) pxa_gpio_mode(CORGI_GPIO_CHRG_ON | GPIO_OUT); pxa_gpio_mode(CORGI_GPIO_CHRG_UKN | GPIO_OUT); pxa_gpio_mode(CORGI_GPIO_KEY_INT | GPIO_IN); - sharpsl_pm_pxa_init(); } static void corgi_measure_temp(int on) @@ -191,7 +190,7 @@ unsigned long corgipm_read_devdata(int type) static struct sharpsl_charger_machinfo corgi_pm_machinfo = { .init = corgi_charger_init, - .exit = sharpsl_pm_pxa_remove, + .exit = NULL, .gpio_batlock = CORGI_GPIO_BAT_COVER, .gpio_acin = CORGI_GPIO_AC_IN, .gpio_batfull = CORGI_GPIO_CHRG_FULL, diff --git a/arch/arm/mach-pxa/cpufreq-pxa2xx.c b/arch/arm/mach-pxa/cpufreq-pxa2xx.c index 083a1d851d4..3a8ee2272ad 100644 --- a/arch/arm/mach-pxa/cpufreq-pxa2xx.c +++ b/arch/arm/mach-pxa/cpufreq-pxa2xx.c @@ -36,6 +36,8 @@ #include <linux/sched.h> #include <linux/init.h> #include <linux/cpufreq.h> +#include <linux/err.h> +#include <linux/regulator/consumer.h> #include <mach/pxa2xx-regs.h> @@ -47,6 +49,8 @@ MODULE_PARM_DESC(freq_debug, "Set the debug messages to on=1/off=0"); #define freq_debug 0 #endif +static struct regulator *vcc_core; + static unsigned int pxa27x_maxfreq; module_param(pxa27x_maxfreq, uint, 0); MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz" @@ -58,6 +62,8 @@ typedef struct { unsigned int cccr; unsigned int div2; unsigned int cclkcfg; + int vmin; + int vmax; } pxa_freqs_t; /* Define the refresh period in mSec for the SDRAM and the number of rows */ @@ -82,24 +88,24 @@ static unsigned int sdram_rows; static pxa_freqs_t pxa255_run_freqs[] = { - /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ - { 99500, 99500, 0x121, 1, CCLKCFG}, /* 99, 99, 50, 50 */ - {132700, 132700, 0x123, 1, CCLKCFG}, /* 133, 133, 66, 66 */ - {199100, 99500, 0x141, 0, CCLKCFG}, /* 199, 199, 99, 99 */ - {265400, 132700, 0x143, 1, CCLKCFG}, /* 265, 265, 133, 66 */ - {331800, 165900, 0x145, 1, CCLKCFG}, /* 331, 331, 166, 83 */ - {398100, 99500, 0x161, 0, CCLKCFG}, /* 398, 398, 196, 99 */ + /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ + { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ + {132700, 132700, 0x123, 1, CCLKCFG, -1, -1}, /* 133, 133, 66, 66 */ + {199100, 99500, 0x141, 0, CCLKCFG, -1, -1}, /* 199, 199, 99, 99 */ + {265400, 132700, 0x143, 1, CCLKCFG, -1, -1}, /* 265, 265, 133, 66 */ + {331800, 165900, 0x145, 1, CCLKCFG, -1, -1}, /* 331, 331, 166, 83 */ + {398100, 99500, 0x161, 0, CCLKCFG, -1, -1}, /* 398, 398, 196, 99 */ }; /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ static pxa_freqs_t pxa255_turbo_freqs[] = { /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ - { 99500, 99500, 0x121, 1, CCLKCFG}, /* 99, 99, 50, 50 */ - {199100, 99500, 0x221, 0, CCLKCFG}, /* 99, 199, 50, 99 */ - {298500, 99500, 0x321, 0, CCLKCFG}, /* 99, 287, 50, 99 */ - {298600, 99500, 0x1c1, 0, CCLKCFG}, /* 199, 287, 99, 99 */ - {398100, 99500, 0x241, 0, CCLKCFG}, /* 199, 398, 99, 99 */ + { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ + {199100, 99500, 0x221, 0, CCLKCFG, -1, -1}, /* 99, 199, 50, 99 */ + {298500, 99500, 0x321, 0, CCLKCFG, -1, -1}, /* 99, 287, 50, 99 */ + {298600, 99500, 0x1c1, 0, CCLKCFG, -1, -1}, /* 199, 287, 99, 99 */ + {398100, 99500, 0x241, 0, CCLKCFG, -1, -1}, /* 199, 398, 99, 99 */ }; #define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) @@ -148,13 +154,13 @@ MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table ((T) ? CCLKCFG_TURBO : 0)) static pxa_freqs_t pxa27x_freqs[] = { - {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1)}, - {156000, 104000, PXA27x_CCCR(1, 8, 6), 0, CCLKCFG2(1, 1, 1)}, - {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1)}, - {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1)}, - {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1)}, - {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1)}, - {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1)} + {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 }, + {156000, 104000, PXA27x_CCCR(1, 8, 6), 0, CCLKCFG2(1, 1, 1), 1000000, 1705000 }, + {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 }, + {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 }, + {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 }, + {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 }, + {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 } }; #define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs) @@ -163,6 +169,47 @@ static struct cpufreq_frequency_table extern unsigned get_clk_frequency_khz(int info); +#ifdef CONFIG_REGULATOR + +static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) +{ + int ret = 0; + int vmin, vmax; + + if (!cpu_is_pxa27x()) + return 0; + + vmin = pxa_freq->vmin; + vmax = pxa_freq->vmax; + if ((vmin == -1) || (vmax == -1)) + return 0; + + ret = regulator_set_voltage(vcc_core, vmin, vmax); + if (ret) + pr_err("cpufreq: Failed to set vcc_core in [%dmV..%dmV]\n", + vmin, vmax); + return ret; +} + +static __init void pxa_cpufreq_init_voltages(void) +{ + vcc_core = regulator_get(NULL, "vcc_core"); + if (IS_ERR(vcc_core)) { + pr_info("cpufreq: Didn't find vcc_core regulator\n"); + vcc_core = NULL; + } else { + pr_info("cpufreq: Found vcc_core regulator\n"); + } +} +#else +static int pxa_cpufreq_change_voltage(pxa_freqs_t *pxa_freq) +{ + return 0; +} + +static __init void pxa_cpufreq_init_voltages(void) { } +#endif + static void find_freq_tables(struct cpufreq_frequency_table **freq_table, pxa_freqs_t **pxa_freqs) { @@ -251,6 +298,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned long flags; unsigned int new_freq_cpu, new_freq_mem; unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; + int ret = 0; /* Get the current policy */ find_freq_tables(&pxa_freqs_table, &pxa_freq_settings); @@ -273,6 +321,10 @@ static int pxa_set_target(struct cpufreq_policy *policy, freqs.new / 1000, (pxa_freq_settings[idx].div2) ? (new_freq_mem / 2000) : (new_freq_mem / 1000)); + if (vcc_core && freqs.new > freqs.old) + ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); + if (ret) + return ret; /* * Tell everyone what we're about to do... * you should add a notify client with any platform specific @@ -335,6 +387,18 @@ static int pxa_set_target(struct cpufreq_policy *policy, */ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); + /* + * Even if voltage setting fails, we don't report it, as the frequency + * change succeeded. The voltage reduction is not a critical failure, + * only power savings will suffer from this. + * + * Note: if the voltage change fails, and a return value is returned, a + * bug is triggered (seems a deadlock). Should anybody find out where, + * the "return 0" should become a "return ret". + */ + if (vcc_core && freqs.new < freqs.old) + ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); + return 0; } @@ -349,6 +413,8 @@ static __init int pxa_cpufreq_init(struct cpufreq_policy *policy) if (cpu_is_pxa27x()) pxa27x_guess_max_freq(); + pxa_cpufreq_init_voltages(); + init_sdram_rows(); /* set default policy and cpuinfo */ diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c index 2b289f83a61..7d3e1b46e55 100644 --- a/arch/arm/mach-pxa/csb726.c +++ b/arch/arm/mach-pxa/csb726.c @@ -16,15 +16,17 @@ #include <linux/mtd/physmap.h> #include <linux/mtd/partitions.h> #include <linux/sm501.h> +#include <linux/smsc911x.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> #include <mach/csb726.h> #include <mach/mfp-pxa27x.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/mmc.h> #include <mach/ohci.h> #include <mach/pxa2xx-regs.h> +#include <mach/audio.h> #include "generic.h" #include "devices.h" @@ -275,15 +277,26 @@ static struct resource csb726_lan_resources[] = { { .start = CSB726_IRQ_LAN, .end = CSB726_IRQ_LAN, - .flags = IORESOURCE_IRQ, + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE, }, }; +struct smsc911x_platform_config csb726_lan_config = { + .irq_type = SMSC911X_IRQ_POLARITY_ACTIVE_LOW, + .irq_type = SMSC911X_IRQ_TYPE_PUSH_PULL, + .flags = SMSC911X_USE_32BIT, + .phy_interface = PHY_INTERFACE_MODE_MII, +}; + + static struct platform_device csb726_lan = { - .name = "smc911x", + .name = "smsc911x", .id = -1, .num_resources = ARRAY_SIZE(csb726_lan_resources), .resource = csb726_lan_resources, + .dev = { + .platform_data = &csb726_lan_config, + }, }; static struct platform_device *devices[] __initdata = { @@ -303,6 +316,7 @@ static void __init csb726_init(void) pxa27x_set_i2c_power_info(NULL); pxa_set_mci_info(&csb726_mci); pxa_set_ohci_info(&csb726_ohci_platform_data); + pxa_set_ac97_info(NULL); platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c index 29970f703f3..ecc08f360b6 100644 --- a/arch/arm/mach-pxa/devices.c +++ b/arch/arm/mach-pxa/devices.c @@ -8,7 +8,7 @@ #include <mach/pxafb.h> #include <mach/mmc.h> #include <mach/irda.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/ohci.h> #include <mach/pxa27x_keypad.h> #include <mach/pxa2xx_spi.h> @@ -290,7 +290,7 @@ static struct resource pxa3xx_resources_i2c_power[] = { }; struct platform_device pxa3xx_device_i2c_power = { - .name = "pxa2xx-i2c", + .name = "pxa3xx-pwri2c", .id = 1, .resource = pxa3xx_resources_i2c_power, .num_resources = ARRAY_SIZE(pxa3xx_resources_i2c_power), diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c index bc0f73fbd4c..243e0802b5f 100644 --- a/arch/arm/mach-pxa/em-x270.c +++ b/arch/arm/mach-pxa/em-x270.c @@ -28,6 +28,8 @@ #include <linux/spi/libertas_spi.h> #include <linux/power_supply.h> #include <linux/apm-emulation.h> +#include <linux/i2c.h> +#include <linux/i2c/pca953x.h> #include <media/soc_camera.h> @@ -41,7 +43,7 @@ #include <mach/ohci.h> #include <mach/mmc.h> #include <mach/pxa27x_keypad.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/camera.h> #include <mach/pxa2xx_spi.h> @@ -52,23 +54,31 @@ #define GPIO13_MMC_CD (13) #define GPIO95_MMC_WP (95) #define GPIO56_NAND_RB (56) +#define GPIO93_CAM_RESET (93) +#define GPIO16_USB_HUB_RESET (16) /* eXeda specific GPIOs */ #define GPIO114_MMC_CD (114) #define GPIO20_NAND_RB (20) #define GPIO38_SD_PWEN (38) +#define GPIO37_WLAN_RST (37) +#define GPIO95_TOUCHPAD_INT (95) +#define GPIO130_CAM_RESET (130) +#define GPIO10_USB_HUB_RESET (10) /* common GPIOs */ #define GPIO11_NAND_CS (11) -#define GPIO93_CAM_RESET (93) #define GPIO41_ETHIRQ (41) #define EM_X270_ETHIRQ IRQ_GPIO(GPIO41_ETHIRQ) #define GPIO115_WLAN_PWEN (115) #define GPIO19_WLAN_STRAP (19) +#define GPIO9_USB_VBUS_EN (9) static int mmc_cd; static int nand_rb; static int dm9000_flags; +static int cam_reset; +static int usb_hub_reset; static unsigned long common_pin_config[] = { /* AC'97 */ @@ -180,7 +190,6 @@ static unsigned long common_pin_config[] = { /* 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 */ @@ -191,14 +200,18 @@ static unsigned long common_pin_config[] = { }; static unsigned long em_x270_pin_config[] = { - GPIO13_GPIO, /* MMC card detect */ - GPIO56_GPIO, /* NAND Ready/Busy */ - GPIO95_GPIO, /* MMC Write protect */ + GPIO13_GPIO, /* MMC card detect */ + GPIO16_GPIO, /* USB hub reset */ + GPIO56_GPIO, /* NAND Ready/Busy */ + GPIO93_GPIO | MFP_LPM_DRIVE_LOW, /* Camera reset */ + GPIO95_GPIO, /* MMC Write protect */ }; static unsigned long exeda_pin_config[] = { + GPIO10_GPIO, /* USB hub reset */ GPIO20_GPIO, /* NAND Ready/Busy */ GPIO38_GPIO | MFP_LPM_DRIVE_LOW, /* SD slot power */ + GPIO95_GPIO, /* touchpad IRQ */ GPIO114_GPIO, /* MMC card detect */ }; @@ -464,18 +477,79 @@ static inline void em_x270_init_nor(void) {} /* PXA27x OHCI controller setup */ #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) +static struct regulator *em_x270_usb_ldo; + +static int em_x270_usb_hub_init(void) +{ + int err; + + em_x270_usb_ldo = regulator_get(NULL, "vcc usb"); + if (IS_ERR(em_x270_usb_ldo)) + return PTR_ERR(em_x270_usb_ldo); + + err = gpio_request(GPIO9_USB_VBUS_EN, "vbus en"); + if (err) + goto err_free_usb_ldo; + + err = gpio_request(usb_hub_reset, "hub rst"); + if (err) + goto err_free_vbus_gpio; + + /* USB Hub power-on and reset */ + gpio_direction_output(usb_hub_reset, 0); + regulator_enable(em_x270_usb_ldo); + gpio_set_value(usb_hub_reset, 1); + gpio_set_value(usb_hub_reset, 0); + regulator_disable(em_x270_usb_ldo); + regulator_enable(em_x270_usb_ldo); + gpio_set_value(usb_hub_reset, 1); + + /* enable VBUS */ + gpio_direction_output(GPIO9_USB_VBUS_EN, 1); + + return 0; + +err_free_vbus_gpio: + gpio_free(GPIO9_USB_VBUS_EN); +err_free_usb_ldo: + regulator_put(em_x270_usb_ldo); + + return err; +} + static int em_x270_ohci_init(struct device *dev) { + int err; + + /* we don't want to entirely disable USB if the HUB init failed */ + err = em_x270_usb_hub_init(); + if (err) + pr_err("USB Hub initialization failed: %d\n", err); + /* enable port 2 transiever */ UP2OCR = UP2OCR_HXS | UP2OCR_HXOE; return 0; } +static void em_x270_ohci_exit(struct device *dev) +{ + gpio_free(usb_hub_reset); + gpio_free(GPIO9_USB_VBUS_EN); + + if (!IS_ERR(em_x270_usb_ldo)) { + if (regulator_is_enabled(em_x270_usb_ldo)) + regulator_disable(em_x270_usb_ldo); + + regulator_put(em_x270_usb_ldo); + } +} + 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, + .exit = em_x270_ohci_exit, }; static void __init em_x270_init_ohci(void) @@ -677,26 +751,52 @@ static int em_x270_libertas_setup(struct spi_device *spi) if (err) return err; + err = gpio_request(GPIO19_WLAN_STRAP, "WLAN STRAP"); + if (err) + goto err_free_pwen; + + if (machine_is_exeda()) { + err = gpio_request(GPIO37_WLAN_RST, "WLAN RST"); + if (err) + goto err_free_strap; + + gpio_direction_output(GPIO37_WLAN_RST, 1); + msleep(100); + } + gpio_direction_output(GPIO19_WLAN_STRAP, 1); - mdelay(100); + msleep(100); pxa2xx_mfp_config(ARRAY_AND_SIZE(em_x270_libertas_pin_config)); gpio_direction_output(GPIO115_WLAN_PWEN, 0); - mdelay(100); + msleep(100); gpio_set_value(GPIO115_WLAN_PWEN, 1); - mdelay(100); + msleep(100); spi->bits_per_word = 16; spi_setup(spi); return 0; + +err_free_strap: + gpio_free(GPIO19_WLAN_STRAP); +err_free_pwen: + gpio_free(GPIO115_WLAN_PWEN); + + return err; } static int em_x270_libertas_teardown(struct spi_device *spi) { gpio_set_value(GPIO115_WLAN_PWEN, 0); gpio_free(GPIO115_WLAN_PWEN); + gpio_free(GPIO19_WLAN_STRAP); + + if (machine_is_exeda()) { + gpio_set_value(GPIO37_WLAN_RST, 0); + gpio_free(GPIO37_WLAN_RST); + } return 0; } @@ -863,26 +963,26 @@ static int em_x270_sensor_init(struct device *dev) { int ret; - ret = gpio_request(GPIO93_CAM_RESET, "camera reset"); + ret = gpio_request(cam_reset, "camera reset"); if (ret) return ret; - gpio_direction_output(GPIO93_CAM_RESET, 0); + gpio_direction_output(cam_reset, 0); em_x270_camera_ldo = regulator_get(NULL, "vcc cam"); if (em_x270_camera_ldo == NULL) { - gpio_free(GPIO93_CAM_RESET); + gpio_free(cam_reset); return -ENODEV; } ret = regulator_enable(em_x270_camera_ldo); if (ret) { regulator_put(em_x270_camera_ldo); - gpio_free(GPIO93_CAM_RESET); + gpio_free(cam_reset); return ret; } - gpio_set_value(GPIO93_CAM_RESET, 1); + gpio_set_value(cam_reset, 1); return 0; } @@ -902,7 +1002,7 @@ static int em_x270_sensor_power(struct device *dev, int on) if (on == is_on) return 0; - gpio_set_value(GPIO93_CAM_RESET, !on); + gpio_set_value(cam_reset, !on); if (on) ret = regulator_enable(em_x270_camera_ldo); @@ -912,7 +1012,7 @@ static int em_x270_sensor_power(struct device *dev, int on) if (ret) return ret; - gpio_set_value(GPIO93_CAM_RESET, on); + gpio_set_value(cam_reset, on); return 0; } @@ -929,13 +1029,8 @@ static struct i2c_board_info em_x270_i2c_cam_info[] = { }, }; -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); } @@ -985,7 +1080,7 @@ struct led_info em_x270_led_info = { }; struct power_supply_info em_x270_psy_info = { - .name = "LP555597P6H-FPS", + .name = "battery", .technology = POWER_SUPPLY_TECHNOLOGY_LIPO, .voltage_max_design = 4200000, .voltage_min_design = 3000000, @@ -1069,6 +1164,29 @@ static void __init em_x270_init_da9030(void) i2c_register_board_info(1, &em_x270_i2c_pmic_info, 1); } +static struct pca953x_platform_data exeda_gpio_ext_pdata = { + .gpio_base = 128, +}; + +static struct i2c_board_info exeda_i2c_info[] = { + { + I2C_BOARD_INFO("pca9555", 0x21), + .platform_data = &exeda_gpio_ext_pdata, + }, +}; + +static struct i2c_pxa_platform_data em_x270_i2c_info = { + .fast_mode = 1, +}; + +static void __init em_x270_init_i2c(void) +{ + pxa_set_i2c_info(&em_x270_i2c_info); + + if (machine_is_exeda()) + i2c_register_board_info(0, ARRAY_AND_SIZE(exeda_i2c_info)); +} + static void __init em_x270_module_init(void) { pr_info("%s\n", __func__); @@ -1077,6 +1195,8 @@ static void __init em_x270_module_init(void) mmc_cd = GPIO13_MMC_CD; nand_rb = GPIO56_NAND_RB; dm9000_flags = DM9000_PLATF_32BITONLY; + cam_reset = GPIO93_CAM_RESET; + usb_hub_reset = GPIO16_USB_HUB_RESET; } static void __init em_x270_exeda_init(void) @@ -1087,12 +1207,18 @@ static void __init em_x270_exeda_init(void) mmc_cd = GPIO114_MMC_CD; nand_rb = GPIO20_NAND_RB; dm9000_flags = DM9000_PLATF_16BITONLY; + cam_reset = GPIO130_CAM_RESET; + usb_hub_reset = GPIO10_USB_HUB_RESET; } static void __init em_x270_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(common_pin_config)); +#ifdef CONFIG_PM + pxa27x_set_pwrmode(PWRMODE_DEEPSLEEP); +#endif + if (machine_is_em_x270()) em_x270_module_init(); else if (machine_is_exeda()) @@ -1111,8 +1237,9 @@ static void __init em_x270_init(void) em_x270_init_keypad(); em_x270_init_gpio_keys(); em_x270_init_ac97(); - em_x270_init_camera(); em_x270_init_spi(); + em_x270_init_i2c(); + em_x270_init_camera(); } MACHINE_START(EM_X270, "Compulab EM-X270") diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c index 7db966dc29c..588b265e575 100644 --- a/arch/arm/mach-pxa/ezx.c +++ b/arch/arm/mach-pxa/ezx.c @@ -17,6 +17,7 @@ #include <linux/delay.h> #include <linux/pwm_backlight.h> #include <linux/input.h> +#include <linux/gpio_keys.h> #include <asm/setup.h> #include <asm/mach-types.h> @@ -25,13 +26,19 @@ #include <mach/pxa27x.h> #include <mach/pxafb.h> #include <mach/ohci.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/hardware.h> #include <mach/pxa27x_keypad.h> #include "devices.h" #include "generic.h" +#define GPIO12_A780_FLIP_LID 12 +#define GPIO15_A1200_FLIP_LID 15 +#define GPIO15_A910_FLIP_LID 15 +#define GPIO12_E680_LOCK_SWITCH 12 +#define GPIO15_E6_LOCK_SWITCH 15 + static struct platform_pwm_backlight_data ezx_backlight_data = { .pwm_id = 0, .max_brightness = 1023, @@ -88,7 +95,7 @@ static struct pxafb_mach_info ezx_fb_info_2 = { .lcd_conn = LCD_COLOR_TFT_18BPP, }; -static struct platform_device *devices[] __initdata = { +static struct platform_device *ezx_devices[] __initdata = { &ezx_backlight_device, }; @@ -651,6 +658,35 @@ static struct pxa27x_keypad_platform_data e2_keypad_platform_data = { #endif /* CONFIG_MACH_EZX_E2 */ #ifdef CONFIG_MACH_EZX_A780 +/* gpio_keys */ +static struct gpio_keys_button a780_buttons[] = { + [0] = { + .code = SW_LID, + .gpio = GPIO12_A780_FLIP_LID, + .active_low = 0, + .desc = "A780 flip lid", + .type = EV_SW, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data a780_gpio_keys_platform_data = { + .buttons = a780_buttons, + .nbuttons = ARRAY_SIZE(a780_buttons), +}; + +static struct platform_device a780_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &a780_gpio_keys_platform_data, + }, +}; + +static struct platform_device *a780_devices[] __initdata = { + &a780_gpio_keys, +}; + static void __init a780_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -663,7 +699,8 @@ static void __init a780_init(void) pxa_set_keypad_info(&a780_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(a780_devices)); } MACHINE_START(EZX_A780, "Motorola EZX A780") @@ -678,10 +715,39 @@ MACHINE_END #endif #ifdef CONFIG_MACH_EZX_E680 +/* gpio_keys */ +static struct gpio_keys_button e680_buttons[] = { + [0] = { + .code = KEY_SCREENLOCK, + .gpio = GPIO12_E680_LOCK_SWITCH, + .active_low = 0, + .desc = "E680 lock switch", + .type = EV_KEY, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data e680_gpio_keys_platform_data = { + .buttons = e680_buttons, + .nbuttons = ARRAY_SIZE(e680_buttons), +}; + +static struct platform_device e680_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &e680_gpio_keys_platform_data, + }, +}; + static struct i2c_board_info __initdata e680_i2c_board_info[] = { { I2C_BOARD_INFO("tea5767", 0x81) }, }; +static struct platform_device *e680_devices[] __initdata = { + &e680_gpio_keys, +}; + static void __init e680_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -695,7 +761,8 @@ static void __init e680_init(void) pxa_set_keypad_info(&e680_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(e680_devices)); } MACHINE_START(EZX_E680, "Motorola EZX E680") @@ -710,10 +777,39 @@ MACHINE_END #endif #ifdef CONFIG_MACH_EZX_A1200 +/* gpio_keys */ +static struct gpio_keys_button a1200_buttons[] = { + [0] = { + .code = SW_LID, + .gpio = GPIO15_A1200_FLIP_LID, + .active_low = 0, + .desc = "A1200 flip lid", + .type = EV_SW, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data a1200_gpio_keys_platform_data = { + .buttons = a1200_buttons, + .nbuttons = ARRAY_SIZE(a1200_buttons), +}; + +static struct platform_device a1200_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &a1200_gpio_keys_platform_data, + }, +}; + static struct i2c_board_info __initdata a1200_i2c_board_info[] = { { I2C_BOARD_INFO("tea5767", 0x81) }, }; +static struct platform_device *a1200_devices[] __initdata = { + &a1200_gpio_keys, +}; + static void __init a1200_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -727,7 +823,8 @@ static void __init a1200_init(void) pxa_set_keypad_info(&a1200_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(a1200_devices)); } MACHINE_START(EZX_A1200, "Motorola EZX A1200") @@ -742,6 +839,35 @@ MACHINE_END #endif #ifdef CONFIG_MACH_EZX_A910 +/* gpio_keys */ +static struct gpio_keys_button a910_buttons[] = { + [0] = { + .code = SW_LID, + .gpio = GPIO15_A910_FLIP_LID, + .active_low = 0, + .desc = "A910 flip lid", + .type = EV_SW, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data a910_gpio_keys_platform_data = { + .buttons = a910_buttons, + .nbuttons = ARRAY_SIZE(a910_buttons), +}; + +static struct platform_device a910_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &a910_gpio_keys_platform_data, + }, +}; + +static struct platform_device *a910_devices[] __initdata = { + &a910_gpio_keys, +}; + static void __init a910_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -754,7 +880,8 @@ static void __init a910_init(void) pxa_set_keypad_info(&a910_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(a910_devices)); } MACHINE_START(EZX_A910, "Motorola EZX A910") @@ -769,10 +896,39 @@ MACHINE_END #endif #ifdef CONFIG_MACH_EZX_E6 +/* gpio_keys */ +static struct gpio_keys_button e6_buttons[] = { + [0] = { + .code = KEY_SCREENLOCK, + .gpio = GPIO15_E6_LOCK_SWITCH, + .active_low = 0, + .desc = "E6 lock switch", + .type = EV_KEY, + .wakeup = 1, + }, +}; + +static struct gpio_keys_platform_data e6_gpio_keys_platform_data = { + .buttons = e6_buttons, + .nbuttons = ARRAY_SIZE(e6_buttons), +}; + +static struct platform_device e6_gpio_keys = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &e6_gpio_keys_platform_data, + }, +}; + static struct i2c_board_info __initdata e6_i2c_board_info[] = { { I2C_BOARD_INFO("tea5767", 0x81) }, }; +static struct platform_device *e6_devices[] __initdata = { + &e6_gpio_keys, +}; + static void __init e6_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -786,7 +942,8 @@ static void __init e6_init(void) pxa_set_keypad_info(&e6_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(e6_devices)); } MACHINE_START(EZX_E6, "Motorola EZX E6") @@ -805,6 +962,9 @@ static struct i2c_board_info __initdata e2_i2c_board_info[] = { { I2C_BOARD_INFO("tea5767", 0x81) }, }; +static struct platform_device *e2_devices[] __initdata = { +}; + static void __init e2_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(ezx_pin_config)); @@ -818,7 +978,8 @@ static void __init e2_init(void) pxa_set_keypad_info(&e2_keypad_platform_data); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(ezx_devices)); + platform_add_devices(ARRAY_AND_SIZE(e2_devices)); } MACHINE_START(EZX_E2, "Motorola EZX E2") diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c new file mode 100644 index 00000000000..7fff467e84f --- /dev/null +++ b/arch/arm/mach-pxa/hx4700.c @@ -0,0 +1,851 @@ +/* + * Support for HP iPAQ hx4700 PDAs. + * + * Copyright (c) 2008-2009 Philipp Zabel + * + * Based on code: + * Copyright (c) 2004 Hewlett-Packard Company. + * Copyright (c) 2005 SDG Systems, LLC + * Copyright (c) 2006 Anton Vorontsov <cbou@mail.ru> + * + * 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/kernel.h> +#include <linux/init.h> +#include <linux/platform_device.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/gpio.h> +#include <linux/gpio_keys.h> +#include <linux/input.h> +#include <linux/lcd.h> +#include <linux/mfd/htc-egpio.h> +#include <linux/mfd/asic3.h> +#include <linux/mtd/physmap.h> +#include <linux/pda_power.h> +#include <linux/pwm_backlight.h> +#include <linux/regulator/bq24022.h> +#include <linux/regulator/machine.h> +#include <linux/spi/ads7846.h> +#include <linux/spi/spi.h> +#include <linux/usb/gpio_vbus.h> + +#include <mach/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> + +#include <mach/pxa27x.h> +#include <mach/hx4700.h> +#include <plat/i2c.h> +#include <mach/irda.h> +#include <mach/pxa2xx_spi.h> + +#include <video/w100fb.h> + +#include "devices.h" +#include "generic.h" + +/* Physical address space information */ + +#define ATI_W3220_PHYS PXA_CS2_PHYS /* ATI Imageon 3220 Graphics */ +#define ASIC3_PHYS PXA_CS3_PHYS +#define ASIC3_SD_PHYS (PXA_CS3_PHYS + 0x02000000) + +static unsigned long hx4700_pin_config[] __initdata = { + + /* SDRAM and Static Memory I/O Signals */ + GPIO20_nSDCS_2, + GPIO21_nSDCS_3, + GPIO15_nCS_1, + GPIO78_nCS_2, /* W3220 */ + GPIO79_nCS_3, /* ASIC3 */ + GPIO80_nCS_4, + GPIO33_nCS_5, /* EGPIO, WLAN */ + + /* PC CARD */ + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO54_nPCE_2, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + GPIO85_nPCE_1, + GPIO104_PSKTSEL, + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* FFUART (RS-232) */ + GPIO34_FFUART_RXD, + GPIO35_FFUART_CTS, + GPIO36_FFUART_DCD, + GPIO37_FFUART_DSR, + GPIO38_FFUART_RI, + GPIO39_FFUART_TXD, + GPIO40_FFUART_DTR, + GPIO41_FFUART_RTS, + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + /* PWM 1 (Backlight) */ + GPIO17_PWM1_OUT, + + /* I2S */ + GPIO28_I2S_BITCLK_OUT, + GPIO29_I2S_SDATA_IN, + GPIO30_I2S_SDATA_OUT, + GPIO31_I2S_SYNC, + GPIO113_I2S_SYSCLK, + + /* SSP 1 (NavPoint) */ + GPIO23_SSP1_SCLK, + GPIO24_SSP1_SFRM, + GPIO25_SSP1_TXD, + GPIO26_SSP1_RXD, + + /* SSP 2 (TSC2046) */ + GPIO19_SSP2_SCLK, + GPIO86_SSP2_RXD, + GPIO87_SSP2_TXD, + GPIO88_GPIO, + + /* HX4700 specific input GPIOs */ + GPIO12_GPIO, /* ASIC3_IRQ */ + GPIO13_GPIO, /* W3220_IRQ */ + GPIO14_GPIO, /* nWLAN_IRQ */ + + GPIO10_GPIO, /* GSM_IRQ */ + GPIO13_GPIO, /* CPLD_IRQ */ + GPIO107_GPIO, /* DS1WM_IRQ */ + GPIO108_GPIO, /* GSM_READY */ + GPIO58_GPIO, /* TSC2046_nPENIRQ */ + GPIO66_GPIO, /* nSDIO_IRQ */ +}; + +#define HX4700_GPIO_IN(num, _desc) \ + { .gpio = (num), .dir = 0, .desc = (_desc) } +#define HX4700_GPIO_OUT(num, _init, _desc) \ + { .gpio = (num), .dir = 1, .init = (_init), .desc = (_desc) } +struct gpio_ress { + unsigned gpio : 8; + unsigned dir : 1; + unsigned init : 1; + char *desc; +}; + +static int hx4700_gpio_request(struct gpio_ress *gpios, int size) +{ + int i, rc = 0; + int gpio; + int dir; + + for (i = 0; (!rc) && (i < size); i++) { + gpio = gpios[i].gpio; + dir = gpios[i].dir; + rc = gpio_request(gpio, gpios[i].desc); + if (rc) { + pr_err("Error requesting GPIO %d(%s) : %d\n", + gpio, gpios[i].desc, rc); + continue; + } + if (dir) + gpio_direction_output(gpio, gpios[i].init); + else + gpio_direction_input(gpio); + } + while ((rc) && (--i >= 0)) + gpio_free(gpios[i].gpio); + return rc; +} + +/* + * IRDA + */ + +static void irda_transceiver_mode(struct device *dev, int mode) +{ + gpio_set_value(GPIO105_HX4700_nIR_ON, mode & IR_OFF); +} + +static struct pxaficp_platform_data ficp_info = { + .transceiver_cap = IR_SIRMODE | IR_OFF, + .transceiver_mode = irda_transceiver_mode, +}; + +/* + * GPIO Keys + */ + +#define INIT_KEY(_code, _gpio, _active_low, _desc) \ + { \ + .code = KEY_##_code, \ + .gpio = _gpio, \ + .active_low = _active_low, \ + .desc = _desc, \ + .type = EV_KEY, \ + .wakeup = 1, \ + } + +static struct gpio_keys_button gpio_keys_buttons[] = { + INIT_KEY(POWER, GPIO0_HX4700_nKEY_POWER, 1, "Power button"), + INIT_KEY(MAIL, GPIO94_HX4700_KEY_MAIL, 0, "Mail button"), + INIT_KEY(ADDRESSBOOK, GPIO99_HX4700_KEY_CONTACTS,0, "Contacts button"), + INIT_KEY(RECORD, GPIOD6_nKEY_RECORD, 1, "Record button"), + INIT_KEY(CALENDAR, GPIOD1_nKEY_CALENDAR, 1, "Calendar button"), + INIT_KEY(HOMEPAGE, GPIOD3_nKEY_HOME, 1, "Home button"), +}; + +static struct gpio_keys_platform_data gpio_keys_data = { + .buttons = gpio_keys_buttons, + .nbuttons = ARRAY_SIZE(gpio_keys_buttons), +}; + +static struct platform_device gpio_keys = { + .name = "gpio-keys", + .dev = { + .platform_data = &gpio_keys_data, + }, + .id = -1, +}; + +/* + * ASIC3 + */ + +static u16 asic3_gpio_config[] = { + /* ASIC3 GPIO banks A and B along with some of C and D + implement the buffering for the CF slot. */ + ASIC3_CONFIG_GPIO(0, 1, 1, 0), + ASIC3_CONFIG_GPIO(1, 1, 1, 0), + ASIC3_CONFIG_GPIO(2, 1, 1, 0), + ASIC3_CONFIG_GPIO(3, 1, 1, 0), + ASIC3_CONFIG_GPIO(4, 1, 1, 0), + ASIC3_CONFIG_GPIO(5, 1, 1, 0), + ASIC3_CONFIG_GPIO(6, 1, 1, 0), + ASIC3_CONFIG_GPIO(7, 1, 1, 0), + ASIC3_CONFIG_GPIO(8, 1, 1, 0), + ASIC3_CONFIG_GPIO(9, 1, 1, 0), + ASIC3_CONFIG_GPIO(10, 1, 1, 0), + ASIC3_CONFIG_GPIO(11, 1, 1, 0), + ASIC3_CONFIG_GPIO(12, 1, 1, 0), + ASIC3_CONFIG_GPIO(13, 1, 1, 0), + ASIC3_CONFIG_GPIO(14, 1, 1, 0), + ASIC3_CONFIG_GPIO(15, 1, 1, 0), + + ASIC3_CONFIG_GPIO(16, 1, 1, 0), + ASIC3_CONFIG_GPIO(17, 1, 1, 0), + ASIC3_CONFIG_GPIO(18, 1, 1, 0), + ASIC3_CONFIG_GPIO(19, 1, 1, 0), + ASIC3_CONFIG_GPIO(20, 1, 1, 0), + ASIC3_CONFIG_GPIO(21, 1, 1, 0), + ASIC3_CONFIG_GPIO(22, 1, 1, 0), + ASIC3_CONFIG_GPIO(23, 1, 1, 0), + ASIC3_CONFIG_GPIO(24, 1, 1, 0), + ASIC3_CONFIG_GPIO(25, 1, 1, 0), + ASIC3_CONFIG_GPIO(26, 1, 1, 0), + ASIC3_CONFIG_GPIO(27, 1, 1, 0), + ASIC3_CONFIG_GPIO(28, 1, 1, 0), + ASIC3_CONFIG_GPIO(29, 1, 1, 0), + ASIC3_CONFIG_GPIO(30, 1, 1, 0), + ASIC3_CONFIG_GPIO(31, 1, 1, 0), + + /* GPIOC - CF, LEDs, SD */ + ASIC3_GPIOC0_LED0, /* red */ + ASIC3_GPIOC1_LED1, /* green */ + ASIC3_GPIOC2_LED2, /* blue */ + ASIC3_GPIOC4_CF_nCD, + ASIC3_GPIOC5_nCIOW, + ASIC3_GPIOC6_nCIOR, + ASIC3_GPIOC7_nPCE_1, + ASIC3_GPIOC8_nPCE_2, + ASIC3_GPIOC9_nPOE, + ASIC3_GPIOC10_nPWE, + ASIC3_GPIOC11_PSKTSEL, + ASIC3_GPIOC12_nPREG, + ASIC3_GPIOC13_nPWAIT, + ASIC3_GPIOC14_nPIOIS16, + ASIC3_GPIOC15_nPIOR, + + /* GPIOD: input GPIOs, CF */ + ASIC3_GPIOD11_nCIOIS16, + ASIC3_GPIOD12_nCWAIT, + ASIC3_GPIOD15_nPIOW, +}; + +static struct resource asic3_resources[] = { + /* GPIO part */ + [0] = { + .start = ASIC3_PHYS, + .end = ASIC3_PHYS + ASIC3_MAP_SIZE_16BIT - 1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), + .end = gpio_to_irq(GPIO12_HX4700_ASIC3_IRQ), + .flags = IORESOURCE_IRQ, + }, + /* SD part */ + [2] = { + .start = ASIC3_SD_PHYS, + .end = ASIC3_SD_PHYS + ASIC3_MAP_SIZE_16BIT - 1, + .flags = IORESOURCE_MEM, + }, + [3] = { + .start = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .end = gpio_to_irq(GPIO66_HX4700_ASIC3_nSDIO_IRQ), + .flags = IORESOURCE_IRQ, + }, +}; + +static struct asic3_platform_data asic3_platform_data = { + .gpio_config = asic3_gpio_config, + .gpio_config_num = ARRAY_SIZE(asic3_gpio_config), + .irq_base = IRQ_BOARD_START, + .gpio_base = HX4700_ASIC3_GPIO_BASE, +}; + +static struct platform_device asic3 = { + .name = "asic3", + .id = -1, + .resource = asic3_resources, + .num_resources = ARRAY_SIZE(asic3_resources), + .dev = { + .platform_data = &asic3_platform_data, + }, +}; + +/* + * EGPIO + */ + +static struct resource egpio_resources[] = { + [0] = { + .start = PXA_CS5_PHYS, + .end = PXA_CS5_PHYS + 0x4 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct htc_egpio_chip egpio_chips[] = { + [0] = { + .reg_start = 0, + .gpio_base = HX4700_EGPIO_BASE, + .num_gpios = 8, + .direction = HTC_EGPIO_OUTPUT, + }, +}; + +static struct htc_egpio_platform_data egpio_info = { + .reg_width = 16, + .bus_width = 16, + .chip = egpio_chips, + .num_chips = ARRAY_SIZE(egpio_chips), +}; + +static struct platform_device egpio = { + .name = "htc-egpio", + .id = -1, + .resource = egpio_resources, + .num_resources = ARRAY_SIZE(egpio_resources), + .dev = { + .platform_data = &egpio_info, + }, +}; + +/* + * LCD - Sony display connected to ATI Imageon w3220 + */ + +static int lcd_power; + +static void sony_lcd_init(void) +{ + gpio_set_value(GPIO84_HX4700_LCD_SQN, 1); + gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0); + gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0); + gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 0); + gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0); + mdelay(10); + gpio_set_value(GPIO59_HX4700_LCD_PC1, 0); + gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0); + mdelay(20); + + gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1); + mdelay(5); + gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1); + + /* FIXME: init w3220 registers here */ + + mdelay(5); + gpio_set_value(GPIO70_HX4700_LCD_SLIN1, 1); + mdelay(10); + gpio_set_value(GPIO62_HX4700_LCD_nRESET, 1); + mdelay(10); + gpio_set_value(GPIO59_HX4700_LCD_PC1, 1); + mdelay(10); + gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 1); +} + +static void sony_lcd_off(void) +{ + gpio_set_value(GPIO59_HX4700_LCD_PC1, 0); + gpio_set_value(GPIO62_HX4700_LCD_nRESET, 0); + mdelay(10); + gpio_set_value(GPIO112_HX4700_LCD_N2V7_7V3_ON, 0); + mdelay(10); + gpio_set_value(GPIO111_HX4700_LCD_AVDD_3V3_ON, 0); + mdelay(10); + gpio_set_value(GPIO110_HX4700_LCD_LVDD_3V3_ON, 0); +} + +static int hx4700_lcd_set_power(struct lcd_device *ldev, int level) +{ + switch (level) { + case FB_BLANK_UNBLANK: + sony_lcd_init(); + break; + case FB_BLANK_NORMAL: + case FB_BLANK_VSYNC_SUSPEND: + case FB_BLANK_HSYNC_SUSPEND: + case FB_BLANK_POWERDOWN: + sony_lcd_off(); + break; + } + lcd_power = level; + return 0; +} + +static int hx4700_lcd_get_power(struct lcd_device *lm) +{ + return lcd_power; +} + +static struct lcd_ops hx4700_lcd_ops = { + .get_power = hx4700_lcd_get_power, + .set_power = hx4700_lcd_set_power, +}; + +static struct lcd_device *hx4700_lcd_device; + +#ifdef CONFIG_PM +static void w3220_lcd_suspend(struct w100fb_par *wfb) +{ + sony_lcd_off(); +} + +static void w3220_lcd_resume(struct w100fb_par *wfb) +{ + sony_lcd_init(); +} +#else +#define w3220_lcd_resume NULL +#define w3220_lcd_suspend NULL +#endif + +static struct w100_tg_info w3220_tg_info = { + .suspend = w3220_lcd_suspend, + .resume = w3220_lcd_resume, +}; + +/* W3220_VGA QVGA */ +static struct w100_gen_regs w3220_regs = { + .lcd_format = 0x00000003, + .lcdd_cntl1 = 0x00000000, + .lcdd_cntl2 = 0x0003ffff, + .genlcd_cntl1 = 0x00abf003, /* 0x00fff003 */ + .genlcd_cntl2 = 0x00000003, + .genlcd_cntl3 = 0x000102aa, +}; + +static struct w100_mode w3220_modes[] = { +{ + .xres = 480, + .yres = 640, + .left_margin = 15, + .right_margin = 16, + .upper_margin = 8, + .lower_margin = 7, + .crtc_ss = 0x00000000, + .crtc_ls = 0xa1ff01f9, /* 0x21ff01f9 */ + .crtc_gs = 0xc0000000, /* 0x40000000 */ + .crtc_vpos_gs = 0x0000028f, + .crtc_ps1_active = 0x00000000, /* 0x41060010 */ + .crtc_rev = 0, + .crtc_dclk = 0x80000000, + .crtc_gclk = 0x040a0104, + .crtc_goe = 0, + .pll_freq = 95, + .pixclk_divider = 4, + .pixclk_divider_rotated = 4, + .pixclk_src = CLK_SRC_PLL, + .sysclk_divider = 0, + .sysclk_src = CLK_SRC_PLL, +}, +{ + .xres = 240, + .yres = 320, + .left_margin = 9, + .right_margin = 8, + .upper_margin = 5, + .lower_margin = 4, + .crtc_ss = 0x80150014, + .crtc_ls = 0xa0fb00f7, + .crtc_gs = 0xc0080007, + .crtc_vpos_gs = 0x00080007, + .crtc_rev = 0x0000000a, + .crtc_dclk = 0x81700030, + .crtc_gclk = 0x8015010f, + .crtc_goe = 0x00000000, + .pll_freq = 95, + .pixclk_divider = 4, + .pixclk_divider_rotated = 4, + .pixclk_src = CLK_SRC_PLL, + .sysclk_divider = 0, + .sysclk_src = CLK_SRC_PLL, +}, +}; + +struct w100_mem_info w3220_mem_info = { + .ext_cntl = 0x09640011, + .sdram_mode_reg = 0x00600021, + .ext_timing_cntl = 0x1a001545, /* 0x15001545 */ + .io_cntl = 0x7ddd7333, + .size = 0x1fffff, +}; + +struct w100_bm_mem_info w3220_bm_mem_info = { + .ext_mem_bw = 0x50413e01, + .offset = 0, + .ext_timing_ctl = 0x00043f7f, + .ext_cntl = 0x00000010, + .mode_reg = 0x00250000, + .io_cntl = 0x0fff0000, + .config = 0x08301480, +}; + +static struct w100_gpio_regs w3220_gpio_info = { + .init_data1 = 0xdfe00100, /* GPIO_DATA */ + .gpio_dir1 = 0xffff0000, /* GPIO_CNTL1 */ + .gpio_oe1 = 0x00000000, /* GPIO_CNTL2 */ + .init_data2 = 0x00000000, /* GPIO_DATA2 */ + .gpio_dir2 = 0x00000000, /* GPIO_CNTL3 */ + .gpio_oe2 = 0x00000000, /* GPIO_CNTL4 */ +}; + +static struct w100fb_mach_info w3220_info = { + .tg = &w3220_tg_info, + .mem = &w3220_mem_info, + .bm_mem = &w3220_bm_mem_info, + .gpio = &w3220_gpio_info, + .regs = &w3220_regs, + .modelist = w3220_modes, + .num_modes = 2, + .xtal_freq = 16000000, +}; + +static struct resource w3220_resources[] = { + [0] = { + .start = ATI_W3220_PHYS, + .end = ATI_W3220_PHYS + 0x00ffffff, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device w3220 = { + .name = "w100fb", + .id = -1, + .dev = { + .platform_data = &w3220_info, + }, + .num_resources = ARRAY_SIZE(w3220_resources), + .resource = w3220_resources, +}; + +/* + * Backlight + */ + +static struct platform_pwm_backlight_data backlight_data = { + .pwm_id = 1, + .max_brightness = 200, + .dft_brightness = 100, + .pwm_period_ns = 30923, +}; + +static struct platform_device backlight = { + .name = "pwm-backlight", + .id = -1, + .dev = { + .parent = &pxa27x_device_pwm1.dev, + .platform_data = &backlight_data, + }, +}; + +/* + * USB "Transceiver" + */ + +static struct gpio_vbus_mach_info gpio_vbus_info = { + .gpio_pullup = GPIO76_HX4700_USBC_PUEN, + .gpio_vbus = GPIOD14_nUSBC_DETECT, + .gpio_vbus_inverted = 1, +}; + +static struct platform_device gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .dev = { + .platform_data = &gpio_vbus_info, + }, +}; + +/* + * Touchscreen - TSC2046 connected to SSP2 + */ + +static const struct ads7846_platform_data tsc2046_info = { + .model = 7846, + .vref_delay_usecs = 100, + .pressure_max = 512, + .debounce_max = 10, + .debounce_tol = 3, + .debounce_rep = 1, + .gpio_pendown = GPIO58_HX4700_TSC2046_nPENIRQ, +}; + +static struct pxa2xx_spi_chip tsc2046_chip = { + .tx_threshold = 1, + .rx_threshold = 2, + .timeout = 64, + .gpio_cs = GPIO88_HX4700_TSC2046_CS, +}; + +static struct spi_board_info tsc2046_board_info[] __initdata = { + { + .modalias = "ads7846", + .bus_num = 2, + .max_speed_hz = 2600000, /* 100 kHz sample rate */ + .irq = gpio_to_irq(GPIO58_HX4700_TSC2046_nPENIRQ), + .platform_data = &tsc2046_info, + .controller_data = &tsc2046_chip, + }, +}; + +static struct pxa2xx_spi_master pxa_ssp2_master_info = { + .num_chipselect = 1, + .clock_enable = CKEN_SSP2, + .enable_dma = 1, +}; + +/* + * External power + */ + +static int power_supply_init(struct device *dev) +{ + return gpio_request(GPIOD9_nAC_IN, "AC charger detect"); +} + +static int hx4700_is_ac_online(void) +{ + return !gpio_get_value(GPIOD9_nAC_IN); +} + +static void power_supply_exit(struct device *dev) +{ + gpio_free(GPIOD9_nAC_IN); +} + +static char *hx4700_supplicants[] = { + "ds2760-battery.0", "backup-battery" +}; + +static struct pda_power_pdata power_supply_info = { + .init = power_supply_init, + .is_ac_online = hx4700_is_ac_online, + .exit = power_supply_exit, + .supplied_to = hx4700_supplicants, + .num_supplicants = ARRAY_SIZE(hx4700_supplicants), +}; + +static struct resource power_supply_resources[] = { + [0] = { + .name = "ac", + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + .start = gpio_to_irq(GPIOD9_nAC_IN), + .end = gpio_to_irq(GPIOD9_nAC_IN), + }, + [1] = { + .name = "usb", + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | + IORESOURCE_IRQ_LOWEDGE, + .start = gpio_to_irq(GPIOD14_nUSBC_DETECT), + .end = gpio_to_irq(GPIOD14_nUSBC_DETECT), + }, +}; + +static struct platform_device power_supply = { + .name = "pda-power", + .id = -1, + .dev = { + .platform_data = &power_supply_info, + }, + .resource = power_supply_resources, + .num_resources = ARRAY_SIZE(power_supply_resources), +}; + +/* + * Battery charger + */ + +static struct regulator_consumer_supply bq24022_consumers[] = { + { + .dev = &gpio_vbus.dev, + .supply = "vbus_draw", + }, + { + .dev = &power_supply.dev, + .supply = "ac_draw", + }, +}; + +static struct regulator_init_data bq24022_init_data = { + .constraints = { + .max_uA = 500000, + .valid_ops_mask = REGULATOR_CHANGE_CURRENT, + }, + .num_consumer_supplies = ARRAY_SIZE(bq24022_consumers), + .consumer_supplies = bq24022_consumers, +}; + +static struct bq24022_mach_info bq24022_info = { + .gpio_nce = GPIO72_HX4700_BQ24022_nCHARGE_EN, + .gpio_iset2 = GPIO96_HX4700_BQ24022_ISET2, + .init_data = &bq24022_init_data, +}; + +static struct platform_device bq24022 = { + .name = "bq24022", + .id = -1, + .dev = { + .platform_data = &bq24022_info, + }, +}; + +/* + * StrataFlash + */ + +static void hx4700_set_vpp(struct map_info *map, int vpp) +{ + gpio_set_value(GPIO91_HX4700_FLASH_VPEN, vpp); +} + +static struct resource strataflash_resource = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_128M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct physmap_flash_data strataflash_data = { + .width = 4, + .set_vpp = hx4700_set_vpp, +}; + +static struct platform_device strataflash = { + .name = "physmap-flash", + .id = -1, + .resource = &strataflash_resource, + .num_resources = 1, + .dev = { + .platform_data = &strataflash_data, + }, +}; + +/* + * PCMCIA + */ + +static struct platform_device pcmcia = { + .name = "hx4700-pcmcia", + .dev = { + .parent = &asic3.dev, + }, +}; + +/* + * Platform devices + */ + +static struct platform_device *devices[] __initdata = { + &asic3, + &gpio_keys, + &backlight, + &w3220, + &egpio, + &bq24022, + &gpio_vbus, + &power_supply, + &strataflash, + &pcmcia, +}; + +static struct gpio_ress global_gpios[] = { + HX4700_GPIO_IN(GPIO12_HX4700_ASIC3_IRQ, "ASIC3_IRQ"), + HX4700_GPIO_IN(GPIO13_HX4700_W3220_IRQ, "W3220_IRQ"), + HX4700_GPIO_IN(GPIO14_HX4700_nWLAN_IRQ, "WLAN_IRQ"), + HX4700_GPIO_OUT(GPIO59_HX4700_LCD_PC1, 1, "LCD_PC1"), + HX4700_GPIO_OUT(GPIO62_HX4700_LCD_nRESET, 1, "LCD_RESET"), + HX4700_GPIO_OUT(GPIO70_HX4700_LCD_SLIN1, 1, "LCD_SLIN1"), + HX4700_GPIO_OUT(GPIO84_HX4700_LCD_SQN, 1, "LCD_SQN"), + HX4700_GPIO_OUT(GPIO110_HX4700_LCD_LVDD_3V3_ON, 1, "LCD_LVDD"), + HX4700_GPIO_OUT(GPIO111_HX4700_LCD_AVDD_3V3_ON, 1, "LCD_AVDD"), + HX4700_GPIO_OUT(GPIO32_HX4700_RS232_ON, 1, "RS232_ON"), + HX4700_GPIO_OUT(GPIO71_HX4700_ASIC3_nRESET, 1, "ASIC3_nRESET"), + HX4700_GPIO_OUT(GPIO82_HX4700_EUART_RESET, 1, "EUART_RESET"), + HX4700_GPIO_OUT(GPIO105_HX4700_nIR_ON, 1, "nIR_EN"), +}; + +static void __init hx4700_init(void) +{ + pxa2xx_mfp_config(ARRAY_AND_SIZE(hx4700_pin_config)); + hx4700_gpio_request(ARRAY_AND_SIZE(global_gpios)); + + platform_add_devices(devices, ARRAY_SIZE(devices)); + + pxa_set_ficp_info(&ficp_info); + pxa27x_set_i2c_power_info(NULL); + pxa_set_i2c_info(NULL); + pxa2xx_set_spi_info(2, &pxa_ssp2_master_info); + spi_register_board_info(ARRAY_AND_SIZE(tsc2046_board_info)); + + hx4700_lcd_device = lcd_device_register("w100fb", NULL, + (void *)&w3220_info, &hx4700_lcd_ops); + + gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 0); + mdelay(10); + gpio_set_value(GPIO71_HX4700_ASIC3_nRESET, 1); + mdelay(10); +} + +MACHINE_START(H4700, "HP iPAQ HX4700") + .phys_io = 0x40000000, + .io_pg_offst = (io_p2v(0x40000000) >> 18) & 0xfffc, + .boot_params = 0xa0000100, + .map_io = pxa_map_io, + .init_irq = pxa27x_init_irq, + .init_machine = hx4700_init, + .timer = &pxa_timer, +MACHINE_END diff --git a/arch/arm/mach-pxa/imote2.c b/arch/arm/mach-pxa/imote2.c index 2b27336c29f..961807dc646 100644 --- a/arch/arm/mach-pxa/imote2.c +++ b/arch/arm/mach-pxa/imote2.c @@ -22,6 +22,7 @@ #include <linux/spi/spi.h> #include <linux/i2c.h> #include <linux/mfd/da903x.h> +#include <linux/sht15.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -29,7 +30,7 @@ #include <asm/mach/flash.h> #include <mach/pxa27x.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/udc.h> #include <mach/mmc.h> #include <mach/pxa2xx_spi.h> @@ -102,6 +103,10 @@ static unsigned long imote2_pin_config[] __initdata = { GPIO96_GPIO, /* accelerometer interrupt */ GPIO99_GPIO, /* ADC interrupt */ + /* SHT15 */ + GPIO100_GPIO, + GPIO98_GPIO, + /* Connector pins specified as gpios */ GPIO94_GPIO, /* large basic connector pin 14 */ GPIO10_GPIO, /* large basic connector pin 23 */ @@ -112,6 +117,26 @@ static unsigned long imote2_pin_config[] __initdata = { GPIO105_GPIO, /* blue led */ }; +static struct sht15_platform_data platform_data_sht15 = { + .gpio_data = 100, + .gpio_sck = 98, +}; + +static struct platform_device sht15 = { + .name = "sht15", + .id = -1, + .dev = { + .platform_data = &platform_data_sht15, + }, +}; + +static struct regulator_consumer_supply imote2_sensor_3_con[] = { + { + .dev = &sht15.dev, + .supply = "vcc", + }, +}; + static struct gpio_led imote2_led_pins[] = { { .name = "imote2:red", @@ -257,6 +282,8 @@ static struct regulator_init_data imote2_ldo_init_data[] = { .min_uV = 2800000, .max_uV = 3000000, }, + .num_consumer_supplies = ARRAY_SIZE(imote2_sensor_3_con), + .consumer_supplies = imote2_sensor_3_con, }, [vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/ .constraints = { @@ -432,6 +459,9 @@ static struct i2c_board_info __initdata imote2_i2c_board_info[] = { .type = "tmp175", .addr = 0x4A, .irq = IRQ_GPIO(96), + }, { /* IMB400 Multimedia board */ + .type = "wm8940", + .addr = 0x1A, }, }; @@ -456,25 +486,12 @@ static struct pxa2xx_spi_master pxa_ssp_master_2_info = { .num_chipselect = 1, }; -/* Patch posted by Eric Miao <eric.miao@marvell.com> will remove - * the need for these functions. - */ -static void spi1control(u32 command) -{ - gpio_set_value(24, command & PXA2XX_CS_ASSERT ? 0 : 1); -}; - -static void spi3control(u32 command) -{ - gpio_set_value(39, command & PXA2XX_CS_ASSERT ? 0 : 1); -}; - static struct pxa2xx_spi_chip staccel_chip_info = { .tx_threshold = 8, .rx_threshold = 8, .dma_burst_size = 8, .timeout = 235, - .cs_control = spi1control, + .gpio_cs = 24, }; static struct pxa2xx_spi_chip cc2420_info = { @@ -482,7 +499,7 @@ static struct pxa2xx_spi_chip cc2420_info = { .rx_threshold = 8, .dma_burst_size = 8, .timeout = 235, - .cs_control = spi3control, + .gpio_cs = 39, }; static struct spi_board_info spi_board_info[] __initdata = { @@ -521,6 +538,7 @@ static struct pxa2xx_udc_mach_info imote2_udc_info __initdata = { static struct platform_device *imote2_devices[] = { &imote2_flash_device, &imote2_leds, + &sht15, }; static struct i2c_pxa_platform_data i2c_pwr_pdata = { @@ -538,8 +556,6 @@ static void __init imote2_init(void) /* SPI chip select directions - all other directions should * be handled by drivers.*/ gpio_direction_output(37, 0); - gpio_direction_output(24, 0); - gpio_direction_output(39, 0); platform_add_devices(imote2_devices, ARRAY_SIZE(imote2_devices)); diff --git a/arch/arm/mach-pxa/include/mach/hx4700.h b/arch/arm/mach-pxa/include/mach/hx4700.h new file mode 100644 index 00000000000..9eaeed1f87f --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/hx4700.h @@ -0,0 +1,131 @@ +/* + * GPIO and IRQ definitions for HP iPAQ hx4700 + * + * Copyright (c) 2008 Philipp Zabel + * + * 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. + * + */ + +#ifndef _HX4700_H_ +#define _HX4700_H_ + +#include <linux/gpio.h> +#include <linux/mfd/asic3.h> + +#define HX4700_ASIC3_GPIO_BASE NR_BUILTIN_GPIO +#define HX4700_EGPIO_BASE (HX4700_ASIC3_GPIO_BASE + ASIC3_NUM_GPIOS) + +/* + * PXA GPIOs + */ + +#define GPIO0_HX4700_nKEY_POWER 0 +#define GPIO12_HX4700_ASIC3_IRQ 12 +#define GPIO13_HX4700_W3220_IRQ 13 +#define GPIO14_HX4700_nWLAN_IRQ 14 +#define GPIO18_HX4700_RDY 18 +#define GPIO22_HX4700_LCD_RL 22 +#define GPIO27_HX4700_CODEC_ON 27 +#define GPIO32_HX4700_RS232_ON 32 +#define GPIO52_HX4700_CPU_nBATT_FAULT 52 +#define GPIO58_HX4700_TSC2046_nPENIRQ 58 +#define GPIO59_HX4700_LCD_PC1 59 +#define GPIO60_HX4700_CF_RNB 60 +#define GPIO61_HX4700_W3220_nRESET 61 +#define GPIO62_HX4700_LCD_nRESET 62 +#define GPIO63_HX4700_CPU_SS_nRESET 63 +#define GPIO65_HX4700_TSC2046_PEN_PU 65 +#define GPIO66_HX4700_ASIC3_nSDIO_IRQ 66 +#define GPIO67_HX4700_EUART_PS 67 +#define GPIO70_HX4700_LCD_SLIN1 70 +#define GPIO71_HX4700_ASIC3_nRESET 71 +#define GPIO72_HX4700_BQ24022_nCHARGE_EN 72 +#define GPIO73_HX4700_LCD_UD_1 73 +#define GPIO75_HX4700_EARPHONE_nDET 75 +#define GPIO76_HX4700_USBC_PUEN 76 +#define GPIO81_HX4700_CPU_GP_nRESET 81 +#define GPIO82_HX4700_EUART_RESET 82 +#define GPIO83_HX4700_WLAN_nRESET 83 +#define GPIO84_HX4700_LCD_SQN 84 +#define GPIO85_HX4700_nPCE1 85 +#define GPIO88_HX4700_TSC2046_CS 88 +#define GPIO91_HX4700_FLASH_VPEN 91 +#define GPIO92_HX4700_HP_DRIVER 92 +#define GPIO93_HX4700_EUART_INT 93 +#define GPIO94_HX4700_KEY_MAIL 94 +#define GPIO95_HX4700_BATT_OFF 95 +#define GPIO96_HX4700_BQ24022_ISET2 96 +#define GPIO97_HX4700_nBL_DETECT 97 +#define GPIO99_HX4700_KEY_CONTACTS 99 +#define GPIO100_HX4700_AUTO_SENSE 100 /* BL auto brightness */ +#define GPIO102_HX4700_SYNAPTICS_POWER_ON 102 +#define GPIO103_HX4700_SYNAPTICS_INT 103 +#define GPIO105_HX4700_nIR_ON 105 +#define GPIO106_HX4700_CPU_BT_nRESET 106 +#define GPIO107_HX4700_SPK_nSD 107 +#define GPIO109_HX4700_CODEC_nPDN 109 +#define GPIO110_HX4700_LCD_LVDD_3V3_ON 110 +#define GPIO111_HX4700_LCD_AVDD_3V3_ON 111 +#define GPIO112_HX4700_LCD_N2V7_7V3_ON 112 +#define GPIO114_HX4700_CF_RESET 114 +#define GPIO116_HX4700_CPU_HW_nRESET 116 + +/* + * ASIC3 GPIOs + */ + +#define GPIOC_BASE (HX4700_ASIC3_GPIO_BASE + 32) +#define GPIOD_BASE (HX4700_ASIC3_GPIO_BASE + 48) + +#define GPIOC0_LED_RED (GPIOC_BASE + 0) +#define GPIOC1_LED_GREEN (GPIOC_BASE + 1) +#define GPIOC2_LED_BLUE (GPIOC_BASE + 2) +#define GPIOC3_nSD_CS (GPIOC_BASE + 3) +#define GPIOC4_CF_nCD (GPIOC_BASE + 4) /* Input */ +#define GPIOC5_nCIOW (GPIOC_BASE + 5) /* Output, to CF */ +#define GPIOC6_nCIOR (GPIOC_BASE + 6) /* Output, to CF */ +#define GPIOC7_nPCE1 (GPIOC_BASE + 7) /* Input, from CPU */ +#define GPIOC8_nPCE2 (GPIOC_BASE + 8) /* Input, from CPU */ +#define GPIOC9_nPOE (GPIOC_BASE + 9) /* Input, from CPU */ +#define GPIOC10_CF_nPWE (GPIOC_BASE + 10) /* Input */ +#define GPIOC11_PSKTSEL (GPIOC_BASE + 11) /* Input, from CPU */ +#define GPIOC12_nPREG (GPIOC_BASE + 12) /* Input, from CPU */ +#define GPIOC13_nPWAIT (GPIOC_BASE + 13) /* Output, to CPU */ +#define GPIOC14_nPIOIS16 (GPIOC_BASE + 14) /* Output, to CPU */ +#define GPIOC15_nPIOR (GPIOC_BASE + 15) /* Input, from CPU */ + +#define GPIOD0_CPU_SS_INT (GPIOD_BASE + 0) /* Input */ +#define GPIOD1_nKEY_CALENDAR (GPIOD_BASE + 1) +#define GPIOD2_BLUETOOTH_WAKEUP (GPIOD_BASE + 2) +#define GPIOD3_nKEY_HOME (GPIOD_BASE + 3) +#define GPIOD4_CF_nCD (GPIOD_BASE + 4) /* Input, from CF */ +#define GPIOD5_nPIO (GPIOD_BASE + 5) /* Input */ +#define GPIOD6_nKEY_RECORD (GPIOD_BASE + 6) +#define GPIOD7_nSDIO_DETECT (GPIOD_BASE + 7) +#define GPIOD8_COM_DCD (GPIOD_BASE + 8) /* Input */ +#define GPIOD9_nAC_IN (GPIOD_BASE + 9) +#define GPIOD10_nSDIO_IRQ (GPIOD_BASE + 10) /* Input */ +#define GPIOD11_nCIOIS16 (GPIOD_BASE + 11) /* Input, from CF */ +#define GPIOD12_nCWAIT (GPIOD_BASE + 12) /* Input, from CF */ +#define GPIOD13_CF_RNB (GPIOD_BASE + 13) /* Input */ +#define GPIOD14_nUSBC_DETECT (GPIOD_BASE + 14) +#define GPIOD15_nPIOW (GPIOD_BASE + 15) /* Input, from CPU */ + +/* + * EGPIOs + */ + +#define EGPIO0_VCC_3V3_EN (HX4700_EGPIO_BASE + 0) /* WLAN support chip */ +#define EGPIO1_WL_VREG_EN (HX4700_EGPIO_BASE + 1) /* WLAN power */ +#define EGPIO2_VCC_2V1_WL_EN (HX4700_EGPIO_BASE + 2) /* unused */ +#define EGPIO3_SS_PWR_ON (HX4700_EGPIO_BASE + 3) /* smart slot power */ +#define EGPIO4_CF_3V3_ON (HX4700_EGPIO_BASE + 4) /* CF 3.3V enable */ +#define EGPIO5_BT_3V3_ON (HX4700_EGPIO_BASE + 5) /* BT 3.3V enable */ +#define EGPIO6_WL1V8_EN (HX4700_EGPIO_BASE + 6) /* WLAN 1.8V enable */ +#define EGPIO7_VCC_3V3_WL_EN (HX4700_EGPIO_BASE + 7) /* WLAN 3.3V enable */ +#define EGPIO8_USB_3V3_ON (HX4700_EGPIO_BASE + 8) /* unused */ + +#endif /* _HX4700_H_ */ diff --git a/arch/arm/mach-pxa/include/mach/i2c.h b/arch/arm/mach-pxa/include/mach/i2c.h deleted file mode 100644 index 1a9f65e6ec0..00000000000 --- a/arch/arm/mach-pxa/include/mach/i2c.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * i2c_pxa.h - * - * Copyright (C) 2002 Intrinsyc Software Inc. - * - * 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. - * - */ -#ifndef _I2C_PXA_H_ -#define _I2C_PXA_H_ - -#if 0 -#define DEF_TIMEOUT 3 -#else -/* need a longer timeout if we're dealing with the fact we may well be - * looking at a multi-master environment -*/ -#define DEF_TIMEOUT 32 -#endif - -#define BUS_ERROR (-EREMOTEIO) -#define XFER_NAKED (-ECONNREFUSED) -#define I2C_RETRY (-2000) /* an error has occurred retry transmit */ - -/* ICR initialize bit values -* -* 15. FM 0 (100 Khz operation) -* 14. UR 0 (No unit reset) -* 13. SADIE 0 (Disables the unit from interrupting on slave addresses -* matching its slave address) -* 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration -* in master mode) -* 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) -* 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) -* 9. IRFIE 1 (Enable interrupts from full buffer received) -* 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) -* 7. GCD 1 (Disables i2c unit response to general call messages as a slave) -* 6. IUE 0 (Disable unit until we change settings) -* 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL) -* 4. MA 0 (Only send stop with the ICR stop bit) -* 3. TB 0 (We are not transmitting a byte initially) -* 2. ACKNAK 0 (Send an ACK after the unit receives a byte) -* 1. STOP 0 (Do not send a STOP) -* 0. START 0 (Do not send a START) -* -*/ -#define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) - -/* I2C status register init values - * - * 10. BED 1 (Clear bus error detected) - * 9. SAD 1 (Clear slave address detected) - * 7. IRF 1 (Clear IDBR Receive Full) - * 6. ITE 1 (Clear IDBR Transmit Empty) - * 5. ALD 1 (Clear Arbitration Loss Detected) - * 4. SSD 1 (Clear Slave Stop Detected) - */ -#define I2C_ISR_INIT 0x7FF /* status register init */ - -struct i2c_slave_client; - -struct i2c_pxa_platform_data { - unsigned int slave_addr; - struct i2c_slave_client *slave; - unsigned int class; - unsigned int use_pio :1; - unsigned int fast_mode :1; -}; - -extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); - -#ifdef CONFIG_PXA27x -extern void pxa27x_set_i2c_power_info(struct i2c_pxa_platform_data *info); -#endif - -#ifdef CONFIG_PXA3xx -extern void pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info); -#endif - -#endif diff --git a/arch/arm/mach-pxa/include/mach/irqs.h b/arch/arm/mach-pxa/include/mach/irqs.h index 32bb4a2eb7f..6a1d9599334 100644 --- a/arch/arm/mach-pxa/include/mach/irqs.h +++ b/arch/arm/mach-pxa/include/mach/irqs.h @@ -91,13 +91,23 @@ #define IRQ_TO_GPIO(i) (((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i)) /* - * The next 16 interrupts are for board specific purposes. Since + * The following interrupts are for board specific purposes. Since * the kernel can only run on one machine at a time, we can re-use - * these. If you need more, increase IRQ_BOARD_END, but keep it - * within sensible limits. + * these. There will be 16 IRQs by default. If it is not enough, + * IRQ_BOARD_END is allowed be customized for each board, but keep + * the numbers within sensible limits and in descending order, so + * when multiple config options are selected, the maximum will be + * used. */ #define IRQ_BOARD_START (PXA_GPIO_IRQ_BASE + PXA_GPIO_IRQ_NUM) + +#if defined(CONFIG_MACH_H4700) +#define IRQ_BOARD_END (IRQ_BOARD_START + 70) +#elif defined(CONFIG_MACH_ZYLONITE) +#define IRQ_BOARD_END (IRQ_BOARD_START + 32) +#else #define IRQ_BOARD_END (IRQ_BOARD_START + 16) +#endif #define IRQ_SA1111_START (IRQ_BOARD_END) #define IRQ_GPAIN0 (IRQ_BOARD_END + 0) @@ -188,8 +198,6 @@ #define NR_IRQS (IRQ_LOCOMO_SPI_TEND + 1) #elif defined(CONFIG_PXA_HAVE_BOARD_IRQS) #define NR_IRQS (IRQ_BOARD_END) -#elif defined(CONFIG_MACH_ZYLONITE) -#define NR_IRQS (IRQ_BOARD_START + 32) #else #define NR_IRQS (IRQ_BOARD_START) #endif diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h index 07897e61d05..3ce4682eabb 100644 --- a/arch/arm/mach-pxa/include/mach/mfp-pxa320.h +++ b/arch/arm/mach-pxa/include/mach/mfp-pxa320.h @@ -283,6 +283,9 @@ #define GPIO41_UART1_TXD MFP_CFG_LPM(GPIO41, AF4, FLOAT) #define GPIO42_UART1_RXD MFP_CFG_LPM(GPIO42, AF4, FLOAT) #define GPIO42_UART1_TXD MFP_CFG_LPM(GPIO42, AF2, FLOAT) +#define GPIO75_UART1_RXD MFP_CFG_LPM(GPIO75, AF1, FLOAT) +#define GPIO76_UART1_RXD MFP_CFG_LPM(GPIO76, AF3, FLOAT) +#define GPIO76_UART1_TXD MFP_CFG_LPM(GPIO76, AF1, FLOAT) #define GPIO97_UART1_RXD MFP_CFG_LPM(GPIO97, AF1, FLOAT) #define GPIO97_UART1_TXD MFP_CFG_LPM(GPIO97, AF6, FLOAT) #define GPIO98_UART1_RXD MFP_CFG_LPM(GPIO98, AF6, FLOAT) @@ -291,6 +294,9 @@ #define GPIO43_UART1_RTS MFP_CFG_LPM(GPIO43, AF4, FLOAT) #define GPIO48_UART1_CTS MFP_CFG_LPM(GPIO48, AF4, FLOAT) #define GPIO48_UART1_RTS MFP_CFG_LPM(GPIO48, AF2, FLOAT) +#define GPIO77_UART1_CTS MFP_CFG_LPM(GPIO77, AF1, FLOAT) +#define GPIO82_UART1_RTS MFP_CFG_LPM(GPIO82, AF1, FLOAT) +#define GPIO82_UART1_CTS MFP_CFG_LPM(GPIO82, AF3, FLOAT) #define GPIO99_UART1_CTS MFP_CFG_LPM(GPIO99, AF1, FLOAT) #define GPIO99_UART1_RTS MFP_CFG_LPM(GPIO99, AF6, FLOAT) #define GPIO104_UART1_CTS MFP_CFG_LPM(GPIO104, AF6, FLOAT) @@ -299,13 +305,18 @@ #define GPIO45_UART1_DSR MFP_CFG_LPM(GPIO45, AF2, FLOAT) #define GPIO47_UART1_DTR MFP_CFG_LPM(GPIO47, AF2, FLOAT) #define GPIO47_UART1_DSR MFP_CFG_LPM(GPIO47, AF4, FLOAT) +#define GPIO79_UART1_DSR MFP_CFG_LPM(GPIO79, AF1, FLOAT) +#define GPIO81_UART1_DTR MFP_CFG_LPM(GPIO81, AF1, FLOAT) +#define GPIO81_UART1_DSR MFP_CFG_LPM(GPIO81, AF3, FLOAT) #define GPIO101_UART1_DTR MFP_CFG_LPM(GPIO101, AF6, FLOAT) #define GPIO101_UART1_DSR MFP_CFG_LPM(GPIO101, AF1, FLOAT) #define GPIO103_UART1_DTR MFP_CFG_LPM(GPIO103, AF1, FLOAT) #define GPIO103_UART1_DSR MFP_CFG_LPM(GPIO103, AF6, FLOAT) #define GPIO44_UART1_DCD MFP_CFG_LPM(GPIO44, AF2, FLOAT) +#define GPIO78_UART1_DCD MFP_CFG_LPM(GPIO78, AF1, FLOAT) #define GPIO100_UART1_DCD MFP_CFG_LPM(GPIO100, AF1, FLOAT) #define GPIO46_UART1_RI MFP_CFG_LPM(GPIO46, AF2, FLOAT) +#define GPIO80_UART1_RI MFP_CFG_LPM(GPIO80, AF1, FLOAT) #define GPIO102_UART1_RI MFP_CFG_LPM(GPIO102, AF1, FLOAT) /* UART2 */ @@ -438,6 +449,9 @@ #define GPIO2_RDY MFP_CFG(GPIO2, AF1) #define GPIO5_NPIOR MFP_CFG(GPIO5, AF3) +#define GPIO6_NPIOW MFP_CFG(GPIO6, AF3) +#define GPIO7_NPIOS16 MFP_CFG(GPIO7, AF3) +#define GPIO8_NPWAIT MFP_CFG(GPIO8, AF3) #define GPIO11_PWM0_OUT MFP_CFG(GPIO11, AF1) #define GPIO12_PWM1_OUT MFP_CFG(GPIO12, AF1) diff --git a/arch/arm/mach-pxa/include/mach/palmld.h b/arch/arm/mach-pxa/include/mach/palmld.h index fb13c82ad6d..8721b801022 100644 --- a/arch/arm/mach-pxa/include/mach/palmld.h +++ b/arch/arm/mach-pxa/include/mach/palmld.h @@ -56,7 +56,6 @@ #define GPIO_NR_PALMLD_LED_AMBER 94 /* IDE */ -#define GPIO_NR_PALMLD_IDE_IRQ 95 #define GPIO_NR_PALMLD_IDE_RESET 98 #define GPIO_NR_PALMLD_IDE_PWEN 115 diff --git a/arch/arm/mach-pxa/include/mach/pm.h b/arch/arm/mach-pxa/include/mach/pm.h index a6eeef8a075..fd8360c6839 100644 --- a/arch/arm/mach-pxa/include/mach/pm.h +++ b/arch/arm/mach-pxa/include/mach/pm.h @@ -27,6 +27,8 @@ extern void pxa27x_cpu_suspend(unsigned int); extern void pxa_cpu_resume(void); extern int pxa_pm_enter(suspend_state_t state); +extern int pxa_pm_prepare(void); +extern void pxa_pm_finish(void); /* NOTE: this is for PM debugging on Lubbock, it's really a big * ugly, but let's keep the crap minimum here, instead of direct diff --git a/arch/arm/mach-pxa/include/mach/pxa27x.h b/arch/arm/mach-pxa/include/mach/pxa27x.h index 6876e16c297..0b702693f45 100644 --- a/arch/arm/mach-pxa/include/mach/pxa27x.h +++ b/arch/arm/mach-pxa/include/mach/pxa27x.h @@ -16,4 +16,7 @@ #define ARB_DMA_PARK (1<<25) /* Be parked with DMA when idle */ #define ARB_CORE_PARK (1<<24) /* Be parked with core when idle */ #define ARB_LOCK_FLAG (1<<23) /* Only Locking masters gain access to the bus */ + +extern int __init pxa27x_set_pwrmode(unsigned int mode); + #endif /* __MACH_PXA27x_H */ diff --git a/arch/arm/mach-pxa/include/mach/sharpsl_pm.h b/arch/arm/mach-pxa/include/mach/sharpsl_pm.h new file mode 100644 index 00000000000..1920dc6b05d --- /dev/null +++ b/arch/arm/mach-pxa/include/mach/sharpsl_pm.h @@ -0,0 +1,104 @@ +/* + * SharpSL Battery/PM Driver + * + * Copyright (c) 2004-2005 Richard Purdie + * + * 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. + * + */ +#ifndef _MACH_SHARPSL_PM +#define _MACH_SHARPSL_PM + +struct sharpsl_charger_machinfo { + void (*init)(void); + void (*exit)(void); + int gpio_acin; + int gpio_batfull; + int batfull_irq; + int gpio_batlock; + int gpio_fatal; + void (*discharge)(int); + void (*discharge1)(int); + void (*charge)(int); + void (*measure_temp)(int); + void (*presuspend)(void); + void (*postsuspend)(void); + void (*earlyresume)(void); + unsigned long (*read_devdata)(int); +#define SHARPSL_BATT_VOLT 1 +#define SHARPSL_BATT_TEMP 2 +#define SHARPSL_ACIN_VOLT 3 +#define SHARPSL_STATUS_ACIN 4 +#define SHARPSL_STATUS_LOCK 5 +#define SHARPSL_STATUS_CHRGFULL 6 +#define SHARPSL_STATUS_FATAL 7 + unsigned long (*charger_wakeup)(void); + int (*should_wakeup)(unsigned int resume_on_alarm); + void (*backlight_limit)(int); + int (*backlight_get_status) (void); + int charge_on_volt; + int charge_on_temp; + int charge_acin_high; + int charge_acin_low; + int fatal_acin_volt; + int fatal_noacin_volt; + int bat_levels; + struct battery_thresh *bat_levels_noac; + struct battery_thresh *bat_levels_acin; + struct battery_thresh *bat_levels_noac_bl; + struct battery_thresh *bat_levels_acin_bl; + int status_high_acin; + int status_low_acin; + int status_high_noac; + int status_low_noac; +}; + +struct battery_thresh { + int voltage; + int percentage; +}; + +struct battery_stat { + int ac_status; /* APM AC Present/Not Present */ + int mainbat_status; /* APM Main Battery Status */ + int mainbat_percent; /* Main Battery Percentage Charge */ + int mainbat_voltage; /* Main Battery Voltage */ +}; + +struct sharpsl_pm_status { + struct device *dev; + struct timer_list ac_timer; + struct timer_list chrg_full_timer; + + int charge_mode; +#define CHRG_ERROR (-1) +#define CHRG_OFF (0) +#define CHRG_ON (1) +#define CHRG_DONE (2) + + unsigned int flags; +#define SHARPSL_SUSPENDED (1 << 0) /* Device is Suspended */ +#define SHARPSL_ALARM_ACTIVE (1 << 1) /* Alarm is for charging event (not user) */ +#define SHARPSL_BL_LIMIT (1 << 2) /* Backlight Intensity Limited */ +#define SHARPSL_APM_QUEUED (1 << 3) /* APM Event Queued */ +#define SHARPSL_DO_OFFLINE_CHRG (1 << 4) /* Trigger the offline charger */ + + int full_count; + unsigned long charge_start_time; + struct sharpsl_charger_machinfo *machinfo; + struct battery_stat battstat; +}; + +extern struct sharpsl_pm_status sharpsl_pm; + + +#define SHARPSL_LED_ERROR 2 +#define SHARPSL_LED_ON 1 +#define SHARPSL_LED_OFF 0 + +void sharpsl_battery_kick(void); +void sharpsl_pm_led(int val); + +#endif diff --git a/arch/arm/mach-pxa/include/mach/uncompress.h b/arch/arm/mach-pxa/include/mach/uncompress.h index 5706cea95d1..b54749413e9 100644 --- a/arch/arm/mach-pxa/include/mach/uncompress.h +++ b/arch/arm/mach-pxa/include/mach/uncompress.h @@ -36,7 +36,8 @@ static inline void flush(void) static inline void arch_decomp_setup(void) { if (machine_is_littleton() || machine_is_intelmote2() - || machine_is_csb726()) + || machine_is_csb726() || machine_is_stargate2() + || machine_is_cm_x300()) UART = STUART; } diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index c872b9feb4d..55b3788fd1a 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -42,14 +42,17 @@ #include <mach/pxa300.h> #include <mach/pxafb.h> #include <mach/ssp.h> +#include <mach/mmc.h> #include <mach/pxa2xx_spi.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/pxa27x_keypad.h> #include <mach/pxa3xx_nand.h> #include <mach/littleton.h> #include "generic.h" +#define GPIO_MMC1_CARD_DETECT mfp_to_gpio(MFP_PIN_GPIO15) + /* Littleton MFP configurations */ static mfp_cfg_t littleton_mfp_cfg[] __initdata = { /* LCD */ @@ -98,6 +101,15 @@ static mfp_cfg_t littleton_mfp_cfg[] __initdata = { GPIO123_KP_MKOUT_2, GPIO124_KP_MKOUT_3, GPIO125_KP_MKOUT_4, + + /* MMC1 */ + GPIO3_MMC1_DAT0, + GPIO4_MMC1_DAT1, + GPIO5_MMC1_DAT2, + GPIO6_MMC1_DAT3, + GPIO7_MMC1_CLK, + GPIO8_MMC1_CMD, + GPIO15_GPIO, /* card detect */ }; static struct resource smc91x_resources[] = { @@ -179,15 +191,10 @@ static struct pxa2xx_spi_master littleton_spi_info = { .num_chipselect = 1, }; -static void littleton_tdo24m_cs(u32 cmd) -{ - gpio_set_value(LITTLETON_GPIO_LCD_CS, !(cmd == PXA2XX_CS_ASSERT)); -} - static struct pxa2xx_spi_chip littleton_tdo24m_chip = { .rx_threshold = 1, .tx_threshold = 1, - .cs_control = littleton_tdo24m_cs, + .gpio_cs = LITTLETON_GPIO_LCD_CS, }; static struct spi_board_info littleton_spi_devices[] __initdata = { @@ -202,16 +209,6 @@ static struct spi_board_info littleton_spi_devices[] __initdata = { static void __init littleton_init_spi(void) { - int err; - - err = gpio_request(LITTLETON_GPIO_LCD_CS, "LCD_CS"); - if (err) { - pr_warning("failed to request GPIO for LCS CS\n"); - return; - } - - gpio_direction_output(LITTLETON_GPIO_LCD_CS, 1); - pxa2xx_set_spi_info(2, &littleton_spi_info); spi_register_board_info(ARRAY_AND_SIZE(littleton_spi_devices)); } @@ -267,6 +264,56 @@ static void __init littleton_init_keypad(void) static inline void littleton_init_keypad(void) {} #endif +#if defined(CONFIG_MMC_PXA) || defined(CONFIG_MMC_PXA_MODULE) +static int littleton_mci_init(struct device *dev, + irq_handler_t littleton_detect_int, void *data) +{ + int err, gpio_cd = GPIO_MMC1_CARD_DETECT; + + err = gpio_request(gpio_cd, "mmc card detect"); + if (err) + goto err_request_cd; + + gpio_direction_input(gpio_cd); + + err = request_irq(gpio_to_irq(gpio_cd), littleton_detect_int, + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, + "mmc card detect", data); + if (err) { + dev_err(dev, "failed to request card detect IRQ\n"); + goto err_request_irq; + } + return 0; + +err_request_irq: + gpio_free(gpio_cd); +err_request_cd: + return err; +} + +static void littleton_mci_exit(struct device *dev, void *data) +{ + int gpio_cd = GPIO_MMC1_CARD_DETECT; + + free_irq(gpio_to_irq(gpio_cd), data); + gpio_free(gpio_cd); +} + +static struct pxamci_platform_data littleton_mci_platform_data = { + .detect_delay = 20, + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .init = littleton_mci_init, + .exit = littleton_mci_exit, +}; + +static void __init littleton_init_mmc(void) +{ + pxa_set_mci_info(&littleton_mci_platform_data); +} +#else +static inline void littleton_init_mmc(void) {} +#endif + #if defined(CONFIG_MTD_NAND_PXA3xx) || defined(CONFIG_MTD_NAND_PXA3xx_MODULE) static struct mtd_partition littleton_nand_partitions[] = { [0] = { @@ -407,6 +454,7 @@ static void __init littleton_init(void) littleton_init_spi(); littleton_init_i2c(); + littleton_init_mmc(); littleton_init_lcd(); littleton_init_keypad(); littleton_init_nand(); diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index c899bbd94dc..ca39669cffc 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -36,7 +36,7 @@ #include <mach/pxa27x.h> #include <mach/magician.h> #include <mach/pxafb.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/mmc.h> #include <mach/irda.h> #include <mach/ohci.h> @@ -745,6 +745,14 @@ static struct platform_device strataflash = { }; /* + * I2C + */ + +static struct i2c_pxa_platform_data i2c_info = { + .fast_mode = 1, +}; + +/* * Platform devices */ @@ -771,7 +779,7 @@ static void __init magician_init(void) pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config)); - platform_add_devices(devices, ARRAY_SIZE(devices)); + platform_add_devices(ARRAY_AND_SIZE(devices)); err = gpio_request(GPIO83_MAGICIAN_nIR_EN, "nIR_EN"); if (!err) { @@ -779,7 +787,7 @@ static void __init magician_init(void) pxa_set_ficp_info(&magician_ficp_info); } pxa27x_set_i2c_power_info(NULL); - pxa_set_i2c_info(NULL); + pxa_set_i2c_info(&i2c_info); pxa_set_mci_info(&magician_mci_info); pxa_set_ohci_info(&magician_ohci_info); diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index a6c8429e975..f4dabf0273c 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -46,7 +46,7 @@ #include <mach/mainstone.h> #include <mach/audio.h> #include <mach/pxafb.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/mmc.h> #include <mach/irda.h> #include <mach/ohci.h> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c index ff8052ce0a0..4dc8c2ec40a 100644 --- a/arch/arm/mach-pxa/mioa701.c +++ b/arch/arm/mach-pxa/mioa701.c @@ -48,7 +48,7 @@ #include <mach/mmc.h> #include <mach/udc.h> #include <mach/pxa27x-udc.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/camera.h> #include <mach/audio.h> #include <media/soc_camera.h> @@ -798,7 +798,7 @@ static void mioa701_restart(char c, const char *cmd) arm_machine_restart('s', cmd); } -struct gpio_ress global_gpios[] = { +static struct gpio_ress global_gpios[] = { MIO_GPIO_OUT(GPIO9_CHARGE_EN, 1, "Charger enable"), MIO_GPIO_OUT(GPIO18_POWEROFF, 0, "Power Off"), MIO_GPIO_OUT(GPIO87_LCD_POWER, 0, "LCD Power") diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c index 471a853e548..ed70f281dd0 100644 --- a/arch/arm/mach-pxa/palmld.c +++ b/arch/arm/mach-pxa/palmld.c @@ -129,7 +129,7 @@ static unsigned long palmld_pin_config[] __initdata = { GPIO81_GPIO, /* wifi reset */ /* HDD */ - GPIO95_GPIO, /* HDD irq */ + GPIO98_GPIO, /* HDD reset */ GPIO115_GPIO, /* HDD power */ /* MISC */ @@ -496,6 +496,14 @@ static struct platform_device palmld_asoc = { }; /****************************************************************************** + * HDD + ******************************************************************************/ +static struct platform_device palmld_hdd = { + .name = "pata_palmld", + .id = -1, +}; + +/****************************************************************************** * Framebuffer ******************************************************************************/ static struct pxafb_mode_info palmld_lcd_modes[] = { @@ -524,30 +532,18 @@ static struct pxafb_mach_info palmld_lcd_screen = { /****************************************************************************** * Power management - standby ******************************************************************************/ -#ifdef CONFIG_PM -static u32 *addr __initdata; -static u32 resume[3] __initdata = { - 0xe3a00101, /* mov r0, #0x40000000 */ - 0xe380060f, /* orr r0, r0, #0x00f00000 */ - 0xe590f008, /* ldr pc, [r0, #0x08] */ -}; - -static int __init palmld_pm_init(void) +static void __init palmld_pm_init(void) { - int i; - - /* this is where the bootloader jumps */ - addr = phys_to_virt(PALMLD_STR_BASE); - - for (i = 0; i < 3; i++) - addr[i] = resume[i]; - - return 0; + static u32 resume[] = { + 0xe3a00101, /* mov r0, #0x40000000 */ + 0xe380060f, /* orr r0, r0, #0x00f00000 */ + 0xe590f008, /* ldr pc, [r0, #0x08] */ + }; + + /* copy the bootloader */ + memcpy(phys_to_virt(PALMLD_STR_BASE), resume, sizeof(resume)); } -device_initcall(palmld_pm_init); -#endif - /****************************************************************************** * Machine init ******************************************************************************/ @@ -559,6 +555,7 @@ static struct platform_device *devices[] __initdata = { &palmld_leds, &power_supply, &palmld_asoc, + &palmld_hdd, }; static struct map_desc palmld_io_desc[] __initdata = { @@ -586,6 +583,7 @@ static void __init palmld_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(palmld_pin_config)); + palmld_pm_init(); set_pxa_fb_info(&palmld_lcd_screen); pxa_set_mci_info(&palmld_mci_platform_data); pxa_set_ac97_info(&palmld_ac97_pdata); diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c index 05bf979b78a..aae64a12a73 100644 --- a/arch/arm/mach-pxa/palmt5.c +++ b/arch/arm/mach-pxa/palmt5.c @@ -26,6 +26,7 @@ #include <linux/gpio.h> #include <linux/wm97xx_batt.h> #include <linux/power_supply.h> +#include <linux/usb/gpio_vbus.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -343,11 +344,18 @@ static struct pxaficp_platform_data palmt5_ficp_platform_data = { /****************************************************************************** * UDC ******************************************************************************/ -static struct pxa2xx_udc_mach_info palmt5_udc_info __initdata = { +static struct gpio_vbus_mach_info palmt5_udc_info = { .gpio_vbus = GPIO_NR_PALMT5_USB_DETECT_N, .gpio_vbus_inverted = 1, .gpio_pullup = GPIO_NR_PALMT5_USB_PULLUP, - .gpio_pullup_inverted = 0, +}; + +static struct platform_device palmt5_gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .dev = { + .platform_data = &palmt5_udc_info, + }, }; /****************************************************************************** @@ -466,30 +474,18 @@ static struct pxafb_mach_info palmt5_lcd_screen = { /****************************************************************************** * Power management - standby ******************************************************************************/ -#ifdef CONFIG_PM -static u32 *addr __initdata; -static u32 resume[3] __initdata = { - 0xe3a00101, /* mov r0, #0x40000000 */ - 0xe380060f, /* orr r0, r0, #0x00f00000 */ - 0xe590f008, /* ldr pc, [r0, #0x08] */ -}; - -static int __init palmt5_pm_init(void) +static void __init palmt5_pm_init(void) { - int i; - - /* this is where the bootloader jumps */ - addr = phys_to_virt(PALMT5_STR_BASE); - - for (i = 0; i < 3; i++) - addr[i] = resume[i]; - - return 0; + static u32 resume[] = { + 0xe3a00101, /* mov r0, #0x40000000 */ + 0xe380060f, /* orr r0, r0, #0x00f00000 */ + 0xe590f008, /* ldr pc, [r0, #0x08] */ + }; + + /* copy the bootloader */ + memcpy(phys_to_virt(PALMT5_STR_BASE), resume, sizeof(resume)); } -device_initcall(palmt5_pm_init); -#endif - /****************************************************************************** * Machine init ******************************************************************************/ @@ -500,6 +496,7 @@ static struct platform_device *devices[] __initdata = { &palmt5_backlight, &power_supply, &palmt5_asoc, + &palmt5_gpio_vbus, }; /* setup udc GPIOs initial state */ @@ -515,14 +512,15 @@ static void __init palmt5_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(palmt5_pin_config)); + palmt5_pm_init(); set_pxa_fb_info(&palmt5_lcd_screen); pxa_set_mci_info(&palmt5_mci_platform_data); palmt5_udc_init(); pxa_set_ac97_info(&palmt5_ac97_pdata); - pxa_set_udc_info(&palmt5_udc_info); pxa_set_ficp_info(&palmt5_ficp_platform_data); pxa_set_keypad_info(&palmt5_keypad_platform_data); wm97xx_bat_set_pdata(&wm97xx_batt_pdata); + platform_add_devices(devices, ARRAY_SIZE(devices)); } diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c index 43fcf2e8688..d823b09801d 100644 --- a/arch/arm/mach-pxa/palmte2.c +++ b/arch/arm/mach-pxa/palmte2.c @@ -25,6 +25,7 @@ #include <linux/gpio.h> #include <linux/wm97xx_batt.h> #include <linux/power_supply.h> +#include <linux/usb/gpio_vbus.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -37,6 +38,7 @@ #include <mach/mfp-pxa25x.h> #include <mach/irda.h> #include <mach/udc.h> +#include <mach/palmasoc.h> #include "generic.h" #include "devices.h" @@ -107,6 +109,7 @@ static unsigned long palmte2_pin_config[] __initdata = { GPIO1_RST, /* reset */ GPIO4_GPIO, /* Hotsync button */ GPIO9_GPIO, /* power detect */ + GPIO15_GPIO, /* earphone detect */ GPIO37_GPIO, /* LCD power */ GPIO56_GPIO, /* Backlight power */ }; @@ -318,11 +321,18 @@ static struct pxaficp_platform_data palmte2_ficp_platform_data = { /****************************************************************************** * UDC ******************************************************************************/ -static struct pxa2xx_udc_mach_info palmte2_udc_info __initdata = { +static struct gpio_vbus_mach_info palmte2_udc_info = { .gpio_vbus = GPIO_NR_PALMTE2_USB_DETECT_N, .gpio_vbus_inverted = 1, .gpio_pullup = GPIO_NR_PALMTE2_USB_PULLUP, - .gpio_pullup_inverted = 0, +}; + +static struct platform_device palmte2_gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .dev = { + .platform_data = &palmte2_udc_info, + }, }; /****************************************************************************** @@ -395,6 +405,21 @@ static struct wm97xx_batt_info wm97xx_batt_pdata = { }; /****************************************************************************** + * aSoC audio + ******************************************************************************/ +static struct palm27x_asoc_info palmte2_asoc_pdata = { + .jack_gpio = GPIO_NR_PALMTE2_EARPHONE_DETECT, +}; + +static struct platform_device palmte2_asoc = { + .name = "palm27x-asoc", + .id = -1, + .dev = { + .platform_data = &palmte2_asoc_pdata, + }, +}; + +/****************************************************************************** * Framebuffer ******************************************************************************/ static struct pxafb_mode_info palmte2_lcd_modes[] = { @@ -429,6 +454,8 @@ static struct platform_device *devices[] __initdata = { #endif &palmte2_backlight, &power_supply, + &palmte2_asoc, + &palmte2_gpio_vbus, }; /* setup udc GPIOs initial state */ @@ -447,7 +474,6 @@ static void __init palmte2_init(void) set_pxa_fb_info(&palmte2_lcd_screen); pxa_set_mci_info(&palmte2_mci_platform_data); palmte2_udc_init(); - pxa_set_udc_info(&palmte2_udc_info); pxa_set_ac97_info(NULL); pxa_set_ficp_info(&palmte2_ficp_platform_data); wm97xx_bat_set_pdata(&wm97xx_batt_pdata); diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c index e99a893c58a..6c15d84bde5 100644 --- a/arch/arm/mach-pxa/palmtx.c +++ b/arch/arm/mach-pxa/palmtx.c @@ -27,6 +27,7 @@ #include <linux/gpio.h> #include <linux/wm97xx_batt.h> #include <linux/power_supply.h> +#include <linux/usb/gpio_vbus.h> #include <asm/mach-types.h> #include <asm/mach/arch.h> @@ -359,11 +360,18 @@ static struct pxaficp_platform_data palmtx_ficp_platform_data = { /****************************************************************************** * UDC ******************************************************************************/ -static struct pxa2xx_udc_mach_info palmtx_udc_info __initdata = { +static struct gpio_vbus_mach_info palmtx_udc_info = { .gpio_vbus = GPIO_NR_PALMTX_USB_DETECT_N, .gpio_vbus_inverted = 1, .gpio_pullup = GPIO_NR_PALMTX_USB_PULLUP, - .gpio_pullup_inverted = 0, +}; + +static struct platform_device palmtx_gpio_vbus = { + .name = "gpio-vbus", + .id = -1, + .dev = { + .platform_data = &palmtx_udc_info, + }, }; /****************************************************************************** @@ -483,30 +491,18 @@ static struct pxafb_mach_info palmtx_lcd_screen = { /****************************************************************************** * Power management - standby ******************************************************************************/ -#ifdef CONFIG_PM -static u32 *addr __initdata; -static u32 resume[3] __initdata = { - 0xe3a00101, /* mov r0, #0x40000000 */ - 0xe380060f, /* orr r0, r0, #0x00f00000 */ - 0xe590f008, /* ldr pc, [r0, #0x08] */ -}; - -static int __init palmtx_pm_init(void) +static void __init palmtx_pm_init(void) { - int i; - - /* this is where the bootloader jumps */ - addr = phys_to_virt(PALMTX_STR_BASE); - - for (i = 0; i < 3; i++) - addr[i] = resume[i]; - - return 0; + static u32 resume[] = { + 0xe3a00101, /* mov r0, #0x40000000 */ + 0xe380060f, /* orr r0, r0, #0x00f00000 */ + 0xe590f008, /* ldr pc, [r0, #0x08] */ + }; + + /* copy the bootloader */ + memcpy(phys_to_virt(PALMTX_STR_BASE), resume, sizeof(resume)); } -device_initcall(palmtx_pm_init); -#endif - /****************************************************************************** * Machine init ******************************************************************************/ @@ -517,6 +513,7 @@ static struct platform_device *devices[] __initdata = { &palmtx_backlight, &power_supply, &palmtx_asoc, + &palmtx_gpio_vbus, }; static struct map_desc palmtx_io_desc[] __initdata = { @@ -548,11 +545,11 @@ static void __init palmtx_init(void) { pxa2xx_mfp_config(ARRAY_AND_SIZE(palmtx_pin_config)); + palmtx_pm_init(); set_pxa_fb_info(&palmtx_lcd_screen); pxa_set_mci_info(&palmtx_mci_platform_data); palmtx_udc_init(); pxa_set_ac97_info(&palmtx_ac97_pdata); - pxa_set_udc_info(&palmtx_udc_info); pxa_set_ficp_info(&palmtx_ficp_platform_data); pxa_set_keypad_info(&palmtx_keypad_platform_data); wm97xx_bat_set_pdata(&wm97xx_batt_pdata); diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c index 6c12b5a3132..01791d74e08 100644 --- a/arch/arm/mach-pxa/pcm990-baseboard.c +++ b/arch/arm/mach-pxa/pcm990-baseboard.c @@ -28,7 +28,7 @@ #include <media/soc_camera.h> #include <asm/gpio.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/camera.h> #include <asm/mach/map.h> #include <mach/pxa27x.h> @@ -380,12 +380,12 @@ static struct pca953x_platform_data pca9536_data = { .gpio_base = NR_BUILTIN_GPIO, }; -static int gpio_bus_switch; +static int gpio_bus_switch = -EINVAL; static int pcm990_camera_set_bus_param(struct soc_camera_link *link, - unsigned long flags) + unsigned long flags) { - if (gpio_bus_switch <= 0) { + if (gpio_bus_switch < 0) { if (flags == SOCAM_DATAWIDTH_10) return 0; else @@ -404,25 +404,34 @@ static unsigned long pcm990_camera_query_bus_param(struct soc_camera_link *link) { int ret; - if (!gpio_bus_switch) { + if (gpio_bus_switch < 0) { ret = gpio_request(NR_BUILTIN_GPIO, "camera"); if (!ret) { gpio_bus_switch = NR_BUILTIN_GPIO; gpio_direction_output(gpio_bus_switch, 0); - } else - gpio_bus_switch = -EINVAL; + } } - if (gpio_bus_switch > 0) + if (gpio_bus_switch >= 0) return SOCAM_DATAWIDTH_8 | SOCAM_DATAWIDTH_10; else return SOCAM_DATAWIDTH_10; } +static void pcm990_camera_free_bus(struct soc_camera_link *link) +{ + if (gpio_bus_switch < 0) + return; + + gpio_free(gpio_bus_switch); + gpio_bus_switch = -EINVAL; +} + static struct soc_camera_link iclink = { .bus_id = 0, /* Must match with the camera ID above */ .query_bus_param = pcm990_camera_query_bus_param, .set_bus_param = pcm990_camera_set_bus_param, + .free_bus = pcm990_camera_free_bus, }; /* Board I2C devices. */ diff --git a/arch/arm/mach-pxa/pm.c b/arch/arm/mach-pxa/pm.c index 884b174c8ea..7693355ee63 100644 --- a/arch/arm/mach-pxa/pm.c +++ b/arch/arm/mach-pxa/pm.c @@ -79,7 +79,7 @@ static int pxa_pm_valid(suspend_state_t state) return -EINVAL; } -static int pxa_pm_prepare(void) +int pxa_pm_prepare(void) { int ret = 0; @@ -89,7 +89,7 @@ static int pxa_pm_prepare(void) return ret; } -static void pxa_pm_finish(void) +void pxa_pm_finish(void) { if (pxa_cpu_pm_fns && pxa_cpu_pm_fns->finish) pxa_cpu_pm_fns->finish(); diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c index 036bbde4d22..ac431ed1039 100644 --- a/arch/arm/mach-pxa/poodle.c +++ b/arch/arm/mach-pxa/poodle.c @@ -39,7 +39,7 @@ #include <mach/pxa25x.h> #include <mach/mmc.h> #include <mach/udc.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/irda.h> #include <mach/poodle.h> #include <mach/pxafb.h> @@ -214,13 +214,8 @@ static struct ads7846_platform_data poodle_ads7846_info = { .gpio_pendown = POODLE_GPIO_TP_INT, }; -static void ads7846_cs(u32 command) -{ - gpio_set_value(POODLE_GPIO_TP_CS, !(command == PXA2XX_CS_ASSERT)); -} - static struct pxa2xx_spi_chip poodle_ads7846_chip = { - .cs_control = ads7846_cs, + .gpio_cs = POODLE_GPIO_TP_CS, }; static struct spi_board_info poodle_spi_devices[] = { @@ -236,14 +231,6 @@ static struct spi_board_info poodle_spi_devices[] = { static void __init poodle_init_spi(void) { - int err; - - err = gpio_request(POODLE_GPIO_TP_CS, "ADS7846_CS"); - if (err) - return; - - gpio_direction_output(POODLE_GPIO_TP_CS, 1); - pxa2xx_set_spi_info(1, &poodle_spi_info); spi_register_board_info(ARRAY_AND_SIZE(poodle_spi_devices)); } diff --git a/arch/arm/mach-pxa/pwm.c b/arch/arm/mach-pxa/pwm.c deleted file mode 100644 index fcdd374437a..00000000000 --- a/arch/arm/mach-pxa/pwm.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * linux/arch/arm/mach-pxa/pwm.c - * - * simple driver for PWM (Pulse Width Modulator) controller - * - * 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. - * - * 2008-02-13 initial version - * eric miao <eric.miao@marvell.com> - */ - -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/platform_device.h> -#include <linux/err.h> -#include <linux/clk.h> -#include <linux/io.h> -#include <linux/pwm.h> - -#include <asm/div64.h> - -/* PWM registers and bits definitions */ -#define PWMCR (0x00) -#define PWMDCR (0x04) -#define PWMPCR (0x08) - -#define PWMCR_SD (1 << 6) -#define PWMDCR_FD (1 << 10) - -struct pwm_device { - struct list_head node; - struct platform_device *pdev; - - const char *label; - struct clk *clk; - int clk_enabled; - void __iomem *mmio_base; - - unsigned int use_count; - unsigned int pwm_id; -}; - -/* - * period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE - * duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE - */ -int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) -{ - unsigned long long c; - unsigned long period_cycles, prescale, pv, dc; - - if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) - return -EINVAL; - - c = clk_get_rate(pwm->clk); - c = c * period_ns; - do_div(c, 1000000000); - period_cycles = c; - - if (period_cycles < 1) - period_cycles = 1; - prescale = (period_cycles - 1) / 1024; - pv = period_cycles / (prescale + 1) - 1; - - if (prescale > 63) - return -EINVAL; - - if (duty_ns == period_ns) - dc = PWMDCR_FD; - else - dc = (pv + 1) * duty_ns / period_ns; - - /* NOTE: the clock to PWM has to be enabled first - * before writing to the registers - */ - clk_enable(pwm->clk); - __raw_writel(prescale, pwm->mmio_base + PWMCR); - __raw_writel(dc, pwm->mmio_base + PWMDCR); - __raw_writel(pv, pwm->mmio_base + PWMPCR); - clk_disable(pwm->clk); - - return 0; -} -EXPORT_SYMBOL(pwm_config); - -int pwm_enable(struct pwm_device *pwm) -{ - int rc = 0; - - if (!pwm->clk_enabled) { - rc = clk_enable(pwm->clk); - if (!rc) - pwm->clk_enabled = 1; - } - return rc; -} -EXPORT_SYMBOL(pwm_enable); - -void pwm_disable(struct pwm_device *pwm) -{ - if (pwm->clk_enabled) { - clk_disable(pwm->clk); - pwm->clk_enabled = 0; - } -} -EXPORT_SYMBOL(pwm_disable); - -static DEFINE_MUTEX(pwm_lock); -static LIST_HEAD(pwm_list); - -struct pwm_device *pwm_request(int pwm_id, const char *label) -{ - struct pwm_device *pwm; - int found = 0; - - mutex_lock(&pwm_lock); - - list_for_each_entry(pwm, &pwm_list, node) { - if (pwm->pwm_id == pwm_id) { - found = 1; - break; - } - } - - if (found) { - if (pwm->use_count == 0) { - pwm->use_count++; - pwm->label = label; - } else - pwm = ERR_PTR(-EBUSY); - } else - pwm = ERR_PTR(-ENOENT); - - mutex_unlock(&pwm_lock); - return pwm; -} -EXPORT_SYMBOL(pwm_request); - -void pwm_free(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - - if (pwm->use_count) { - pwm->use_count--; - pwm->label = NULL; - } else - pr_warning("PWM device already freed\n"); - - mutex_unlock(&pwm_lock); -} -EXPORT_SYMBOL(pwm_free); - -static inline void __add_pwm(struct pwm_device *pwm) -{ - mutex_lock(&pwm_lock); - list_add_tail(&pwm->node, &pwm_list); - mutex_unlock(&pwm_lock); -} - -static struct pwm_device *pwm_probe(struct platform_device *pdev, - unsigned int pwm_id, struct pwm_device *parent_pwm) -{ - struct pwm_device *pwm; - struct resource *r; - int ret = 0; - - pwm = kzalloc(sizeof(struct pwm_device), GFP_KERNEL); - if (pwm == NULL) { - dev_err(&pdev->dev, "failed to allocate memory\n"); - return ERR_PTR(-ENOMEM); - } - - pwm->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(pwm->clk)) { - ret = PTR_ERR(pwm->clk); - goto err_free; - } - pwm->clk_enabled = 0; - - pwm->use_count = 0; - pwm->pwm_id = pwm_id; - pwm->pdev = pdev; - - if (parent_pwm != NULL) { - /* registers for the second PWM has offset of 0x10 */ - pwm->mmio_base = parent_pwm->mmio_base + 0x10; - __add_pwm(pwm); - return pwm; - } - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (r == NULL) { - dev_err(&pdev->dev, "no memory resource defined\n"); - ret = -ENODEV; - goto err_free_clk; - } - - r = request_mem_region(r->start, r->end - r->start + 1, pdev->name); - if (r == NULL) { - dev_err(&pdev->dev, "failed to request memory resource\n"); - ret = -EBUSY; - goto err_free_clk; - } - - pwm->mmio_base = ioremap(r->start, r->end - r->start + 1); - if (pwm->mmio_base == NULL) { - dev_err(&pdev->dev, "failed to ioremap() registers\n"); - ret = -ENODEV; - goto err_free_mem; - } - - __add_pwm(pwm); - platform_set_drvdata(pdev, pwm); - return pwm; - -err_free_mem: - release_mem_region(r->start, r->end - r->start + 1); -err_free_clk: - clk_put(pwm->clk); -err_free: - kfree(pwm); - return ERR_PTR(ret); -} - -static int __devinit pxa25x_pwm_probe(struct platform_device *pdev) -{ - struct pwm_device *pwm = pwm_probe(pdev, pdev->id, NULL); - - if (IS_ERR(pwm)) - return PTR_ERR(pwm); - - return 0; -} - -static int __devinit pxa27x_pwm_probe(struct platform_device *pdev) -{ - struct pwm_device *pwm; - - pwm = pwm_probe(pdev, pdev->id, NULL); - if (IS_ERR(pwm)) - return PTR_ERR(pwm); - - pwm = pwm_probe(pdev, pdev->id + 2, pwm); - if (IS_ERR(pwm)) - return PTR_ERR(pwm); - - return 0; -} - -static int __devexit pwm_remove(struct platform_device *pdev) -{ - struct pwm_device *pwm; - struct resource *r; - - pwm = platform_get_drvdata(pdev); - if (pwm == NULL) - return -ENODEV; - - mutex_lock(&pwm_lock); - list_del(&pwm->node); - mutex_unlock(&pwm_lock); - - iounmap(pwm->mmio_base); - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - release_mem_region(r->start, r->end - r->start + 1); - - clk_put(pwm->clk); - kfree(pwm); - return 0; -} - -static struct platform_driver pxa25x_pwm_driver = { - .driver = { - .name = "pxa25x-pwm", - }, - .probe = pxa25x_pwm_probe, - .remove = __devexit_p(pwm_remove), -}; - -static struct platform_driver pxa27x_pwm_driver = { - .driver = { - .name = "pxa27x-pwm", - }, - .probe = pxa27x_pwm_probe, - .remove = __devexit_p(pwm_remove), -}; - -static int __init pwm_init(void) -{ - int ret = 0; - - ret = platform_driver_register(&pxa25x_pwm_driver); - if (ret) { - printk(KERN_ERR "failed to register pxa25x_pwm_driver\n"); - return ret; - } - - ret = platform_driver_register(&pxa27x_pwm_driver); - if (ret) { - printk(KERN_ERR "failed to register pxa27x_pwm_driver\n"); - return ret; - } - - return ret; -} -arch_initcall(pwm_init); - -static void __exit pwm_exit(void) -{ - platform_driver_unregister(&pxa25x_pwm_driver); - platform_driver_unregister(&pxa27x_pwm_driver); -} -module_exit(pwm_exit); - -MODULE_LICENSE("GPL v2"); diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c index a425ec71e65..ec68cc16b4e 100644 --- a/arch/arm/mach-pxa/pxa27x.c +++ b/arch/arm/mach-pxa/pxa27x.c @@ -27,7 +27,7 @@ #include <mach/ohci.h> #include <mach/pm.h> #include <mach/dma.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include "generic.h" #include "devices.h" @@ -204,6 +204,23 @@ static struct clk_lookup pxa27x_clkregs[] = { #define RESTORE(x) x = sleep_save[SLEEP_SAVE_##x] /* + * allow platforms to override default PWRMODE setting used for PM_SUSPEND_MEM + */ +static unsigned int pwrmode = PWRMODE_SLEEP; + +int __init pxa27x_set_pwrmode(unsigned int mode) +{ + switch (mode) { + case PWRMODE_SLEEP: + case PWRMODE_DEEPSLEEP: + pwrmode = mode; + return 0; + } + + return -EINVAL; +} + +/* * List of global PXA peripheral registers to preserve. * More ones like CP and general purpose register values are preserved * with the stack pointer in sleep.S. @@ -254,7 +271,7 @@ void pxa27x_cpu_pm_enter(suspend_state_t state) pxa_cpu_standby(); break; case PM_SUSPEND_MEM: - pxa27x_cpu_suspend(PWRMODE_SLEEP); + pxa27x_cpu_suspend(pwrmode); break; } } diff --git a/arch/arm/mach-pxa/pxa3xx.c b/arch/arm/mach-pxa/pxa3xx.c index b02d4544dc9..6f678d93bf4 100644 --- a/arch/arm/mach-pxa/pxa3xx.c +++ b/arch/arm/mach-pxa/pxa3xx.c @@ -30,7 +30,7 @@ #include <mach/pm.h> #include <mach/dma.h> #include <mach/ssp.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include "generic.h" #include "devices.h" @@ -552,7 +552,7 @@ void __init pxa3xx_set_i2c_power_info(struct i2c_pxa_platform_data *info) } static struct platform_device *devices[] __initdata = { -/* &pxa_device_udc, The UDC driver is PXA25x only */ + &pxa27x_device_udc, &pxa_device_ffuart, &pxa_device_btuart, &pxa_device_stuart, diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c index ff823999143..8241a63ea58 100644 --- a/arch/arm/mach-pxa/saar.c +++ b/arch/arm/mach-pxa/saar.c @@ -27,7 +27,7 @@ #include <asm/mach/arch.h> #include <mach/pxa930.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/pxafb.h> #include "devices.h" diff --git a/arch/arm/mach-pxa/sharpsl.h b/arch/arm/mach-pxa/sharpsl.h index 047909a7665..55259f4756c 100644 --- a/arch/arm/mach-pxa/sharpsl.h +++ b/arch/arm/mach-pxa/sharpsl.h @@ -7,7 +7,7 @@ * */ -#include <asm/hardware/sharpsl_pm.h> +#include <mach/sharpsl_pm.h> /* * SharpSL SSP Driver @@ -44,8 +44,6 @@ void corgi_lcdtg_hw_init(int mode); extern struct battery_thresh spitz_battery_levels_acin[]; extern struct battery_thresh spitz_battery_levels_noac[]; -void sharpsl_pm_pxa_init(void); -void sharpsl_pm_pxa_remove(void); int sharpsl_pm_pxa_read_max1111(int channel); diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 16b4ec67e3b..2546c066cd6 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -15,20 +15,69 @@ #undef DEBUG #include <linux/module.h> -#include <linux/init.h> #include <linux/kernel.h> #include <linux/interrupt.h> -#include <linux/irq.h> #include <linux/platform_device.h> #include <linux/apm-emulation.h> +#include <linux/timer.h> +#include <linux/delay.h> +#include <linux/leds.h> +#include <linux/suspend.h> +#include <linux/gpio.h> -#include <mach/hardware.h> #include <asm/mach-types.h> #include <mach/pm.h> +#include <mach/pxa2xx-regs.h> #include <mach/pxa2xx-gpio.h> +#include <mach/regs-rtc.h> #include <mach/sharpsl.h> +#include <mach/sharpsl_pm.h> + #include "sharpsl.h" +/* + * Constants + */ +#define SHARPSL_CHARGE_ON_TIME_INTERVAL (msecs_to_jiffies(1*60*1000)) /* 1 min */ +#define SHARPSL_CHARGE_FINISH_TIME (msecs_to_jiffies(10*60*1000)) /* 10 min */ +#define SHARPSL_BATCHK_TIME (msecs_to_jiffies(15*1000)) /* 15 sec */ +#define SHARPSL_BATCHK_TIME_SUSPEND (60*10) /* 10 min */ + +#define SHARPSL_WAIT_CO_TIME 15 /* 15 sec */ +#define SHARPSL_WAIT_DISCHARGE_ON 100 /* 100 msec */ +#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 10 /* 10 msec */ +#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 10 /* 10 msec */ +#define SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN 10 /* 10 msec */ +#define SHARPSL_CHARGE_WAIT_TIME 15 /* 15 msec */ +#define SHARPSL_CHARGE_CO_CHECK_TIME 5 /* 5 msec */ +#define SHARPSL_CHARGE_RETRY_CNT 1 /* eqv. 10 min */ + +/* + * Prototypes + */ +#ifdef CONFIG_PM +static int sharpsl_off_charge_battery(void); +static int sharpsl_check_battery_voltage(void); +static int sharpsl_fatal_check(void); +#endif +static int sharpsl_check_battery_temp(void); +static int sharpsl_ac_check(void); +static int sharpsl_average_value(int ad); +static void sharpsl_average_clear(void); +static void sharpsl_charge_toggle(struct work_struct *private_); +static void sharpsl_battery_thread(struct work_struct *private_); + + +/* + * Variables + */ +struct sharpsl_pm_status sharpsl_pm; +static DECLARE_DELAYED_WORK(toggle_charger, sharpsl_charge_toggle); +static DECLARE_DELAYED_WORK(sharpsl_bat, sharpsl_battery_thread); +DEFINE_LED_TRIGGER(sharpsl_charge_led_trigger); + + + struct battery_thresh spitz_battery_levels_acin[] = { { 213, 100}, { 212, 98}, @@ -144,42 +193,789 @@ int sharpsl_pm_pxa_read_max1111(int channel) #endif } -void sharpsl_pm_pxa_init(void) +static int get_percentage(int voltage) +{ + int i = sharpsl_pm.machinfo->bat_levels - 1; + int bl_status = sharpsl_pm.machinfo->backlight_get_status ? sharpsl_pm.machinfo->backlight_get_status() : 0; + struct battery_thresh *thresh; + + if (sharpsl_pm.charge_mode == CHRG_ON) + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_acin_bl : sharpsl_pm.machinfo->bat_levels_acin; + else + thresh = bl_status ? sharpsl_pm.machinfo->bat_levels_noac_bl : sharpsl_pm.machinfo->bat_levels_noac; + + while (i > 0 && (voltage > thresh[i].voltage)) + i--; + + return thresh[i].percentage; +} + +static int get_apm_status(int voltage) +{ + int low_thresh, high_thresh; + + if (sharpsl_pm.charge_mode == CHRG_ON) { + high_thresh = sharpsl_pm.machinfo->status_high_acin; + low_thresh = sharpsl_pm.machinfo->status_low_acin; + } else { + high_thresh = sharpsl_pm.machinfo->status_high_noac; + low_thresh = sharpsl_pm.machinfo->status_low_noac; + } + + if (voltage >= high_thresh) + return APM_BATTERY_STATUS_HIGH; + if (voltage >= low_thresh) + return APM_BATTERY_STATUS_LOW; + return APM_BATTERY_STATUS_CRITICAL; +} + +void sharpsl_battery_kick(void) +{ + schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(125)); +} +EXPORT_SYMBOL(sharpsl_battery_kick); + + +static void sharpsl_battery_thread(struct work_struct *private_) +{ + int voltage, percent, apm_status, i = 0; + + if (!sharpsl_pm.machinfo) + return; + + sharpsl_pm.battstat.ac_status = (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN) ? APM_AC_ONLINE : APM_AC_OFFLINE); + + /* Corgi cannot confirm when battery fully charged so periodically kick! */ + if (!sharpsl_pm.machinfo->batfull_irq && (sharpsl_pm.charge_mode == CHRG_ON) + && time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_ON_TIME_INTERVAL)) + schedule_delayed_work(&toggle_charger, 0); + + while(1) { + voltage = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); + + if (voltage > 0) break; + if (i++ > 5) { + voltage = sharpsl_pm.machinfo->bat_levels_noac[0].voltage; + dev_warn(sharpsl_pm.dev, "Warning: Cannot read main battery!\n"); + break; + } + } + + voltage = sharpsl_average_value(voltage); + apm_status = get_apm_status(voltage); + percent = get_percentage(voltage); + + /* At low battery voltages, the voltage has a tendency to start + creeping back up so we try to avoid this here */ + if ((sharpsl_pm.battstat.ac_status == APM_AC_ONLINE) || (apm_status == APM_BATTERY_STATUS_HIGH) || percent <= sharpsl_pm.battstat.mainbat_percent) { + sharpsl_pm.battstat.mainbat_voltage = voltage; + sharpsl_pm.battstat.mainbat_status = apm_status; + sharpsl_pm.battstat.mainbat_percent = percent; + } + + dev_dbg(sharpsl_pm.dev, "Battery: voltage: %d, status: %d, percentage: %d, time: %ld\n", voltage, + sharpsl_pm.battstat.mainbat_status, sharpsl_pm.battstat.mainbat_percent, jiffies); + +#ifdef CONFIG_BACKLIGHT_CORGI + /* If battery is low. limit backlight intensity to save power. */ + if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) + && ((sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_LOW) || + (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL))) { + if (!(sharpsl_pm.flags & SHARPSL_BL_LIMIT)) { + sharpsl_pm.machinfo->backlight_limit(1); + sharpsl_pm.flags |= SHARPSL_BL_LIMIT; + } + } else if (sharpsl_pm.flags & SHARPSL_BL_LIMIT) { + sharpsl_pm.machinfo->backlight_limit(0); + sharpsl_pm.flags &= ~SHARPSL_BL_LIMIT; + } +#endif + + /* Suspend if critical battery level */ + if ((sharpsl_pm.battstat.ac_status != APM_AC_ONLINE) + && (sharpsl_pm.battstat.mainbat_status == APM_BATTERY_STATUS_CRITICAL) + && !(sharpsl_pm.flags & SHARPSL_APM_QUEUED)) { + sharpsl_pm.flags |= SHARPSL_APM_QUEUED; + dev_err(sharpsl_pm.dev, "Fatal Off\n"); + apm_queue_event(APM_CRITICAL_SUSPEND); + } + + schedule_delayed_work(&sharpsl_bat, SHARPSL_BATCHK_TIME); +} + +void sharpsl_pm_led(int val) +{ + if (val == SHARPSL_LED_ERROR) { + dev_err(sharpsl_pm.dev, "Charging Error!\n"); + } else if (val == SHARPSL_LED_ON) { + dev_dbg(sharpsl_pm.dev, "Charge LED On\n"); + led_trigger_event(sharpsl_charge_led_trigger, LED_FULL); + } else { + dev_dbg(sharpsl_pm.dev, "Charge LED Off\n"); + led_trigger_event(sharpsl_charge_led_trigger, LED_OFF); + } +} + +static void sharpsl_charge_on(void) +{ + dev_dbg(sharpsl_pm.dev, "Turning Charger On\n"); + + sharpsl_pm.full_count = 0; + sharpsl_pm.charge_mode = CHRG_ON; + schedule_delayed_work(&toggle_charger, msecs_to_jiffies(250)); + schedule_delayed_work(&sharpsl_bat, msecs_to_jiffies(500)); +} + +static void sharpsl_charge_off(void) +{ + dev_dbg(sharpsl_pm.dev, "Turning Charger Off\n"); + + sharpsl_pm.machinfo->charge(0); + sharpsl_pm_led(SHARPSL_LED_OFF); + sharpsl_pm.charge_mode = CHRG_OFF; + + schedule_delayed_work(&sharpsl_bat, 0); +} + +static void sharpsl_charge_error(void) { - pxa_gpio_mode(sharpsl_pm.machinfo->gpio_acin | GPIO_IN); - pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batfull | GPIO_IN); - pxa_gpio_mode(sharpsl_pm.machinfo->gpio_batlock | GPIO_IN); + sharpsl_pm_led(SHARPSL_LED_ERROR); + sharpsl_pm.machinfo->charge(0); + sharpsl_pm.charge_mode = CHRG_ERROR; +} + +static void sharpsl_charge_toggle(struct work_struct *private_) +{ + dev_dbg(sharpsl_pm.dev, "Toogling Charger at time: %lx\n", jiffies); + + if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { + sharpsl_charge_off(); + return; + } else if ((sharpsl_check_battery_temp() < 0) || (sharpsl_ac_check() < 0)) { + sharpsl_charge_error(); + return; + } + + sharpsl_pm_led(SHARPSL_LED_ON); + sharpsl_pm.machinfo->charge(0); + mdelay(SHARPSL_CHARGE_WAIT_TIME); + sharpsl_pm.machinfo->charge(1); + + sharpsl_pm.charge_start_time = jiffies; +} + +static void sharpsl_ac_timer(unsigned long data) +{ + int acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); + + dev_dbg(sharpsl_pm.dev, "AC Status: %d\n",acin); + + sharpsl_average_clear(); + if (acin && (sharpsl_pm.charge_mode != CHRG_ON)) + sharpsl_charge_on(); + else if (sharpsl_pm.charge_mode == CHRG_ON) + sharpsl_charge_off(); + + schedule_delayed_work(&sharpsl_bat, 0); +} + + +static irqreturn_t sharpsl_ac_isr(int irq, void *dev_id) +{ + /* Delay the event slightly to debounce */ + /* Must be a smaller delay than the chrg_full_isr below */ + mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); + + return IRQ_HANDLED; +} + +static void sharpsl_chrg_full_timer(unsigned long data) +{ + dev_dbg(sharpsl_pm.dev, "Charge Full at time: %lx\n", jiffies); + + sharpsl_pm.full_count++; + + if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { + dev_dbg(sharpsl_pm.dev, "Charge Full: AC removed - stop charging!\n"); + if (sharpsl_pm.charge_mode == CHRG_ON) + sharpsl_charge_off(); + } else if (sharpsl_pm.full_count < 2) { + dev_dbg(sharpsl_pm.dev, "Charge Full: Count too low\n"); + schedule_delayed_work(&toggle_charger, 0); + } else if (time_after(jiffies, sharpsl_pm.charge_start_time + SHARPSL_CHARGE_FINISH_TIME)) { + dev_dbg(sharpsl_pm.dev, "Charge Full: Interrupt generated too slowly - retry.\n"); + schedule_delayed_work(&toggle_charger, 0); + } else { + sharpsl_charge_off(); + sharpsl_pm.charge_mode = CHRG_DONE; + dev_dbg(sharpsl_pm.dev, "Charge Full: Charging Finished\n"); + } +} + +/* Charging Finished Interrupt (Not present on Corgi) */ +/* Can trigger at the same time as an AC status change so + delay until after that has been processed */ +static irqreturn_t sharpsl_chrg_full_isr(int irq, void *dev_id) +{ + if (sharpsl_pm.flags & SHARPSL_SUSPENDED) + return IRQ_HANDLED; + + /* delay until after any ac interrupt */ + mod_timer(&sharpsl_pm.chrg_full_timer, jiffies + msecs_to_jiffies(500)); + + return IRQ_HANDLED; +} + +static irqreturn_t sharpsl_fatal_isr(int irq, void *dev_id) +{ + int is_fatal = 0; + + if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) { + dev_err(sharpsl_pm.dev, "Battery now Unlocked! Suspending.\n"); + is_fatal = 1; + } + + if (!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_FATAL)) { + dev_err(sharpsl_pm.dev, "Fatal Batt Error! Suspending.\n"); + is_fatal = 1; + } + + if (!(sharpsl_pm.flags & SHARPSL_APM_QUEUED) && is_fatal) { + sharpsl_pm.flags |= SHARPSL_APM_QUEUED; + apm_queue_event(APM_CRITICAL_SUSPEND); + } + + return IRQ_HANDLED; +} + +/* + * Maintain an average of the last 10 readings + */ +#define SHARPSL_CNV_VALUE_NUM 10 +static int sharpsl_ad_index; + +static void sharpsl_average_clear(void) +{ + sharpsl_ad_index = 0; +} + +static int sharpsl_average_value(int ad) +{ + int i, ad_val = 0; + static int sharpsl_ad[SHARPSL_CNV_VALUE_NUM+1]; + + if (sharpsl_pm.battstat.mainbat_status != APM_BATTERY_STATUS_HIGH) { + sharpsl_ad_index = 0; + return ad; + } + + sharpsl_ad[sharpsl_ad_index] = ad; + sharpsl_ad_index++; + if (sharpsl_ad_index >= SHARPSL_CNV_VALUE_NUM) { + for (i=0; i < (SHARPSL_CNV_VALUE_NUM-1); i++) + sharpsl_ad[i] = sharpsl_ad[i+1]; + sharpsl_ad_index = SHARPSL_CNV_VALUE_NUM - 1; + } + for (i=0; i < sharpsl_ad_index; i++) + ad_val += sharpsl_ad[i]; + + return (ad_val / sharpsl_ad_index); +} + +/* + * Take an array of 5 integers, remove the maximum and minimum values + * and return the average. + */ +static int get_select_val(int *val) +{ + int i, j, k, temp, sum = 0; + + /* Find MAX val */ + temp = val[0]; + j=0; + for (i=1; i<5; i++) { + if (temp < val[i]) { + temp = val[i]; + j = i; + } + } + + /* Find MIN val */ + temp = val[4]; + k=4; + for (i=3; i>=0; i--) { + if (temp > val[i]) { + temp = val[i]; + k = i; + } + } + + for (i=0; i<5; i++) + if (i != j && i != k ) + sum += val[i]; + + dev_dbg(sharpsl_pm.dev, "Average: %d from values: %d, %d, %d, %d, %d\n", sum/3, val[0], val[1], val[2], val[3], val[4]); + + return (sum/3); +} + +static int sharpsl_check_battery_temp(void) +{ + int val, i, buff[5]; + + /* Check battery temperature */ + for (i=0; i<5; i++) { + mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); + sharpsl_pm.machinfo->measure_temp(1); + mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP); + buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_TEMP); + sharpsl_pm.machinfo->measure_temp(0); + } + + val = get_select_val(buff); + + dev_dbg(sharpsl_pm.dev, "Temperature: %d\n", val); + if (val > sharpsl_pm.machinfo->charge_on_temp) { + printk(KERN_WARNING "Not charging: temperature out of limits.\n"); + return -1; + } + + return 0; +} + +#ifdef CONFIG_PM +static int sharpsl_check_battery_voltage(void) +{ + int val, i, buff[5]; + + /* disable charge, enable discharge */ + sharpsl_pm.machinfo->charge(0); + sharpsl_pm.machinfo->discharge(1); + mdelay(SHARPSL_WAIT_DISCHARGE_ON); + + if (sharpsl_pm.machinfo->discharge1) + sharpsl_pm.machinfo->discharge1(1); + + /* Check battery voltage */ + for (i=0; i<5; i++) { + buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); + mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); + } + + if (sharpsl_pm.machinfo->discharge1) + sharpsl_pm.machinfo->discharge1(0); + + sharpsl_pm.machinfo->discharge(0); + + val = get_select_val(buff); + dev_dbg(sharpsl_pm.dev, "Battery Voltage: %d\n", val); + + if (val < sharpsl_pm.machinfo->charge_on_volt) + return -1; + + return 0; +} +#endif + +static int sharpsl_ac_check(void) +{ + int temp, i, buff[5]; + + for (i=0; i<5; i++) { + buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT); + mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); + } + + temp = get_select_val(buff); + dev_dbg(sharpsl_pm.dev, "AC Voltage: %d\n",temp); + + if ((temp > sharpsl_pm.machinfo->charge_acin_high) || (temp < sharpsl_pm.machinfo->charge_acin_low)) { + dev_err(sharpsl_pm.dev, "Error: AC check failed.\n"); + return -1; + } + + return 0; +} + +#ifdef CONFIG_PM +static int sharpsl_pm_suspend(struct platform_device *pdev, pm_message_t state) +{ + sharpsl_pm.flags |= SHARPSL_SUSPENDED; + flush_scheduled_work(); + + if (sharpsl_pm.charge_mode == CHRG_ON) + sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; + else + sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; + + return 0; +} + +static int sharpsl_pm_resume(struct platform_device *pdev) +{ + /* Clear the reset source indicators as they break the bootloader upon reboot */ + RCSR = 0x0f; + sharpsl_average_clear(); + sharpsl_pm.flags &= ~SHARPSL_APM_QUEUED; + sharpsl_pm.flags &= ~SHARPSL_SUSPENDED; + + return 0; +} + +static void corgi_goto_sleep(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) +{ + dev_dbg(sharpsl_pm.dev, "Time is: %08x\n",RCNR); + + dev_dbg(sharpsl_pm.dev, "Offline Charge Activate = %d\n",sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG); + /* not charging and AC-IN! */ + + if ((sharpsl_pm.flags & SHARPSL_DO_OFFLINE_CHRG) && (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN))) { + dev_dbg(sharpsl_pm.dev, "Activating Offline Charger...\n"); + sharpsl_pm.charge_mode = CHRG_OFF; + sharpsl_pm.flags &= ~SHARPSL_DO_OFFLINE_CHRG; + sharpsl_off_charge_battery(); + } + + sharpsl_pm.machinfo->presuspend(); + + PEDR = 0xffffffff; /* clear it */ + + sharpsl_pm.flags &= ~SHARPSL_ALARM_ACTIVE; + if ((sharpsl_pm.charge_mode == CHRG_ON) && ((alarm_enable && ((alarm_time - RCNR) > (SHARPSL_BATCHK_TIME_SUSPEND + 30))) || !alarm_enable)) { + RTSR &= RTSR_ALE; + RTAR = RCNR + SHARPSL_BATCHK_TIME_SUSPEND; + dev_dbg(sharpsl_pm.dev, "Charging alarm at: %08x\n",RTAR); + sharpsl_pm.flags |= SHARPSL_ALARM_ACTIVE; + } else if (alarm_enable) { + RTSR &= RTSR_ALE; + RTAR = alarm_time; + dev_dbg(sharpsl_pm.dev, "User alarm at: %08x\n",RTAR); + } else { + dev_dbg(sharpsl_pm.dev, "No alarms set.\n"); + } + + pxa_pm_enter(state); + + sharpsl_pm.machinfo->postsuspend(); + + dev_dbg(sharpsl_pm.dev, "Corgi woken up from suspend: %08x\n",PEDR); +} + +static int corgi_enter_suspend(unsigned long alarm_time, unsigned int alarm_enable, suspend_state_t state) +{ + if (!sharpsl_pm.machinfo->should_wakeup(!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE) && alarm_enable) ) + { + if (!(sharpsl_pm.flags & SHARPSL_ALARM_ACTIVE)) { + dev_dbg(sharpsl_pm.dev, "No user triggered wakeup events and not charging. Strange. Suspend.\n"); + corgi_goto_sleep(alarm_time, alarm_enable, state); + return 1; + } + if(sharpsl_off_charge_battery()) { + dev_dbg(sharpsl_pm.dev, "Charging. Suspend...\n"); + corgi_goto_sleep(alarm_time, alarm_enable, state); + return 1; + } + dev_dbg(sharpsl_pm.dev, "User triggered wakeup in offline charger.\n"); + } + + if ((!sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_LOCK)) || (sharpsl_fatal_check() < 0) ) + { + dev_err(sharpsl_pm.dev, "Fatal condition. Suspend.\n"); + corgi_goto_sleep(alarm_time, alarm_enable, state); + return 1; + } + + return 0; +} + +static int corgi_pxa_pm_enter(suspend_state_t state) +{ + unsigned long alarm_time = RTAR; + unsigned int alarm_status = ((RTSR & RTSR_ALE) != 0); + + dev_dbg(sharpsl_pm.dev, "SharpSL suspending for first time.\n"); + + corgi_goto_sleep(alarm_time, alarm_status, state); + + while (corgi_enter_suspend(alarm_time,alarm_status,state)) + {} + + if (sharpsl_pm.machinfo->earlyresume) + sharpsl_pm.machinfo->earlyresume(); + + dev_dbg(sharpsl_pm.dev, "SharpSL resuming...\n"); + + return 0; +} + +/* + * Check for fatal battery errors + * Fatal returns -1 + */ +static int sharpsl_fatal_check(void) +{ + int buff[5], temp, i, acin; + + dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); + + /* Check AC-Adapter */ + acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); + + if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { + sharpsl_pm.machinfo->charge(0); + udelay(100); + sharpsl_pm.machinfo->discharge(1); /* enable discharge */ + mdelay(SHARPSL_WAIT_DISCHARGE_ON); + } + + if (sharpsl_pm.machinfo->discharge1) + sharpsl_pm.machinfo->discharge1(1); + + /* Check battery : check inserting battery ? */ + for (i=0; i<5; i++) { + buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT); + mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT); + } + + if (sharpsl_pm.machinfo->discharge1) + sharpsl_pm.machinfo->discharge1(0); + + if (acin && (sharpsl_pm.charge_mode == CHRG_ON)) { + udelay(100); + sharpsl_pm.machinfo->charge(1); + sharpsl_pm.machinfo->discharge(0); + } + + temp = get_select_val(buff); + dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check: acin: %d, discharge voltage: %d, no discharge: %ld\n", acin, temp, sharpsl_pm.machinfo->read_devdata(SHARPSL_BATT_VOLT)); + + if ((acin && (temp < sharpsl_pm.machinfo->fatal_acin_volt)) || + (!acin && (temp < sharpsl_pm.machinfo->fatal_noacin_volt))) + return -1; + return 0; +} + +static int sharpsl_off_charge_error(void) +{ + dev_err(sharpsl_pm.dev, "Offline Charger: Error occurred.\n"); + sharpsl_pm.machinfo->charge(0); + sharpsl_pm_led(SHARPSL_LED_ERROR); + sharpsl_pm.charge_mode = CHRG_ERROR; + return 1; +} + +/* + * Charging Control while suspended + * Return 1 - go straight to sleep + * Return 0 - sleep or wakeup depending on other factors + */ +static int sharpsl_off_charge_battery(void) +{ + int time; + + dev_dbg(sharpsl_pm.dev, "Charge Mode: %d\n", sharpsl_pm.charge_mode); + + if (sharpsl_pm.charge_mode == CHRG_OFF) { + dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); + + /* AC Check */ + if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) + return sharpsl_off_charge_error(); + + /* Start Charging */ + sharpsl_pm_led(SHARPSL_LED_ON); + sharpsl_pm.machinfo->charge(0); + mdelay(SHARPSL_CHARGE_WAIT_TIME); + sharpsl_pm.machinfo->charge(1); + + sharpsl_pm.charge_mode = CHRG_ON; + sharpsl_pm.full_count = 0; + + return 1; + } else if (sharpsl_pm.charge_mode != CHRG_ON) { + return 1; + } + + if (sharpsl_pm.full_count == 0) { + int time; + + dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); + + if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) + return sharpsl_off_charge_error(); + + sharpsl_pm.machinfo->charge(0); + mdelay(SHARPSL_CHARGE_WAIT_TIME); + sharpsl_pm.machinfo->charge(1); + sharpsl_pm.charge_mode = CHRG_ON; + + mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); + + time = RCNR; + while(1) { + /* Check if any wakeup event had occurred */ + if (sharpsl_pm.machinfo->charger_wakeup() != 0) + return 0; + /* Check for timeout */ + if ((RCNR - time) > SHARPSL_WAIT_CO_TIME) + return 1; + if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { + dev_dbg(sharpsl_pm.dev, "Offline Charger: Charge full occurred. Retrying to check\n"); + sharpsl_pm.full_count++; + sharpsl_pm.machinfo->charge(0); + mdelay(SHARPSL_CHARGE_WAIT_TIME); + sharpsl_pm.machinfo->charge(1); + return 1; + } + } + } + + dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 3\n"); + + mdelay(SHARPSL_CHARGE_CO_CHECK_TIME); + + time = RCNR; + while(1) { + /* Check if any wakeup event had occurred */ + if (sharpsl_pm.machinfo->charger_wakeup() != 0) + return 0; + /* Check for timeout */ + if ((RCNR-time) > SHARPSL_WAIT_CO_TIME) { + if (sharpsl_pm.full_count > SHARPSL_CHARGE_RETRY_CNT) { + dev_dbg(sharpsl_pm.dev, "Offline Charger: Not charged sufficiently. Retrying.\n"); + sharpsl_pm.full_count = 0; + } + sharpsl_pm.full_count++; + return 1; + } + if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_CHRGFULL)) { + dev_dbg(sharpsl_pm.dev, "Offline Charger: Charging complete.\n"); + sharpsl_pm_led(SHARPSL_LED_OFF); + sharpsl_pm.machinfo->charge(0); + sharpsl_pm.charge_mode = CHRG_DONE; + return 1; + } + } +} +#else +#define sharpsl_pm_suspend NULL +#define sharpsl_pm_resume NULL +#endif + +static ssize_t battery_percentage_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_percent); +} + +static ssize_t battery_voltage_show(struct device *dev, struct device_attribute *attr, char *buf) +{ + return sprintf(buf, "%d\n",sharpsl_pm.battstat.mainbat_voltage); +} + +static DEVICE_ATTR(battery_percentage, 0444, battery_percentage_show, NULL); +static DEVICE_ATTR(battery_voltage, 0444, battery_voltage_show, NULL); + +extern void (*apm_get_power_status)(struct apm_power_info *); + +static void sharpsl_apm_get_power_status(struct apm_power_info *info) +{ + info->ac_line_status = sharpsl_pm.battstat.ac_status; + + if (sharpsl_pm.charge_mode == CHRG_ON) + info->battery_status = APM_BATTERY_STATUS_CHARGING; + else + info->battery_status = sharpsl_pm.battstat.mainbat_status; + + info->battery_flag = (1 << info->battery_status); + info->battery_life = sharpsl_pm.battstat.mainbat_percent; +} + +#ifdef CONFIG_PM +static struct platform_suspend_ops sharpsl_pm_ops = { + .prepare = pxa_pm_prepare, + .finish = pxa_pm_finish, + .enter = corgi_pxa_pm_enter, + .valid = suspend_valid_only_mem, +}; +#endif + +static int __init sharpsl_pm_probe(struct platform_device *pdev) +{ + int ret; + + if (!pdev->dev.platform_data) + return -EINVAL; + + sharpsl_pm.dev = &pdev->dev; + sharpsl_pm.machinfo = pdev->dev.platform_data; + sharpsl_pm.charge_mode = CHRG_OFF; + sharpsl_pm.flags = 0; + + init_timer(&sharpsl_pm.ac_timer); + sharpsl_pm.ac_timer.function = sharpsl_ac_timer; + + init_timer(&sharpsl_pm.chrg_full_timer); + sharpsl_pm.chrg_full_timer.function = sharpsl_chrg_full_timer; + + led_trigger_register_simple("sharpsl-charge", &sharpsl_charge_led_trigger); + + sharpsl_pm.machinfo->init(); + + gpio_request(sharpsl_pm.machinfo->gpio_acin, "AC IN"); + gpio_direction_input(sharpsl_pm.machinfo->gpio_acin); + gpio_request(sharpsl_pm.machinfo->gpio_batfull, "Battery Full"); + gpio_direction_input(sharpsl_pm.machinfo->gpio_batfull); + gpio_request(sharpsl_pm.machinfo->gpio_batlock, "Battery Lock"); + gpio_direction_input(sharpsl_pm.machinfo->gpio_batlock); /* Register interrupt handlers */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED, "AC Input Detect", sharpsl_ac_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "AC Input Detect", sharpsl_ac_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin)); } - else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin),IRQ_TYPE_EDGE_BOTH); - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED, "Battery Cover", sharpsl_fatal_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Battery Cover", sharpsl_fatal_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock)); } - else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock),IRQ_TYPE_EDGE_FALLING); if (sharpsl_pm.machinfo->gpio_fatal) { - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED, "Fatal Battery", sharpsl_fatal_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal), sharpsl_fatal_isr, IRQF_DISABLED | IRQF_TRIGGER_FALLING, "Fatal Battery", sharpsl_fatal_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal)); } - else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_fatal),IRQ_TYPE_EDGE_FALLING); } if (sharpsl_pm.machinfo->batfull_irq) { /* Register interrupt handler. */ - if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED, "CO", sharpsl_chrg_full_isr)) { + if (request_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr, IRQF_DISABLED | IRQF_TRIGGER_RISING, "CO", sharpsl_chrg_full_isr)) { dev_err(sharpsl_pm.dev, "Could not get irq %d.\n", IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull)); } - else set_irq_type(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull),IRQ_TYPE_EDGE_RISING); } + + ret = device_create_file(&pdev->dev, &dev_attr_battery_percentage); + ret |= device_create_file(&pdev->dev, &dev_attr_battery_voltage); + if (ret != 0) + dev_warn(&pdev->dev, "Failed to register attributes (%d)\n", ret); + + apm_get_power_status = sharpsl_apm_get_power_status; + +#ifdef CONFIG_PM + suspend_set_ops(&sharpsl_pm_ops); +#endif + + mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); + + return 0; } -void sharpsl_pm_pxa_remove(void) +static int sharpsl_pm_remove(struct platform_device *pdev) { + suspend_set_ops(NULL); + + device_remove_file(&pdev->dev, &dev_attr_battery_percentage); + device_remove_file(&pdev->dev, &dev_attr_battery_voltage); + + led_trigger_unregister_simple(sharpsl_charge_led_trigger); + free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_acin), sharpsl_ac_isr); free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batlock), sharpsl_fatal_isr); @@ -188,4 +984,39 @@ void sharpsl_pm_pxa_remove(void) if (sharpsl_pm.machinfo->batfull_irq) free_irq(IRQ_GPIO(sharpsl_pm.machinfo->gpio_batfull), sharpsl_chrg_full_isr); + + gpio_free(sharpsl_pm.machinfo->gpio_batlock); + gpio_free(sharpsl_pm.machinfo->gpio_batfull); + gpio_free(sharpsl_pm.machinfo->gpio_acin); + + if (sharpsl_pm.machinfo->exit) + sharpsl_pm.machinfo->exit(); + + del_timer_sync(&sharpsl_pm.chrg_full_timer); + del_timer_sync(&sharpsl_pm.ac_timer); + + return 0; } + +static struct platform_driver sharpsl_pm_driver = { + .probe = sharpsl_pm_probe, + .remove = sharpsl_pm_remove, + .suspend = sharpsl_pm_suspend, + .resume = sharpsl_pm_resume, + .driver = { + .name = "sharpsl-pm", + }, +}; + +static int __devinit sharpsl_pm_init(void) +{ + return platform_driver_register(&sharpsl_pm_driver); +} + +static void sharpsl_pm_exit(void) +{ + platform_driver_unregister(&sharpsl_pm_driver); +} + +late_initcall(sharpsl_pm_init); +module_exit(sharpsl_pm_exit); diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c index 5a45fe340a1..dda310fe71c 100644 --- a/arch/arm/mach-pxa/spitz.c +++ b/arch/arm/mach-pxa/spitz.c @@ -13,19 +13,11 @@ */ #include <linux/kernel.h> -#include <linux/init.h> #include <linux/platform_device.h> #include <linux/delay.h> -#include <linux/major.h> -#include <linux/fs.h> -#include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/leds.h> -#include <linux/mmc/host.h> #include <linux/mtd/physmap.h> -#include <linux/pm.h> -#include <linux/backlight.h> -#include <linux/io.h> #include <linux/i2c.h> #include <linux/i2c/pca953x.h> #include <linux/spi/spi.h> @@ -34,31 +26,22 @@ #include <linux/mtd/sharpsl.h> #include <asm/setup.h> -#include <asm/memory.h> #include <asm/mach-types.h> -#include <mach/hardware.h> -#include <asm/irq.h> -#include <asm/system.h> - #include <asm/mach/arch.h> -#include <asm/mach/map.h> -#include <asm/mach/irq.h> +#include <asm/mach/sharpsl_param.h> +#include <asm/hardware/scoop.h> + #include <mach/pxa27x.h> #include <mach/pxa27x-udc.h> #include <mach/reset.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/irda.h> #include <mach/mmc.h> #include <mach/ohci.h> -#include <mach/udc.h> #include <mach/pxafb.h> #include <mach/pxa2xx_spi.h> #include <mach/spitz.h> -#include <mach/sharpsl.h> - -#include <asm/mach/sharpsl_param.h> -#include <asm/hardware/scoop.h> #include "generic.h" #include "devices.h" @@ -317,13 +300,8 @@ static struct ads7846_platform_data spitz_ads7846_info = { .wait_for_sync = spitz_wait_for_hsync, }; -static void spitz_ads7846_cs(u32 command) -{ - gpio_set_value(SPITZ_GPIO_ADS7846_CS, !(command == PXA2XX_CS_ASSERT)); -} - static struct pxa2xx_spi_chip spitz_ads7846_chip = { - .cs_control = spitz_ads7846_cs, + .gpio_cs = SPITZ_GPIO_ADS7846_CS, }; static void spitz_bl_kick_battery(void) @@ -347,22 +325,12 @@ static struct corgi_lcd_platform_data spitz_lcdcon_info = { .kick_battery = spitz_bl_kick_battery, }; -static void spitz_lcdcon_cs(u32 command) -{ - gpio_set_value(SPITZ_GPIO_LCDCON_CS, !(command == PXA2XX_CS_ASSERT)); -} - static struct pxa2xx_spi_chip spitz_lcdcon_chip = { - .cs_control = spitz_lcdcon_cs, + .gpio_cs = SPITZ_GPIO_LCDCON_CS, }; -static void spitz_max1111_cs(u32 command) -{ - gpio_set_value(SPITZ_GPIO_MAX1111_CS, !(command == PXA2XX_CS_ASSERT)); -} - static struct pxa2xx_spi_chip spitz_max1111_chip = { - .cs_control = spitz_max1111_cs, + .gpio_cs = SPITZ_GPIO_MAX1111_CS, }; static struct spi_board_info spitz_spi_devices[] = { @@ -392,30 +360,6 @@ static struct spi_board_info spitz_spi_devices[] = { static void __init spitz_init_spi(void) { - int err; - - err = gpio_request(SPITZ_GPIO_ADS7846_CS, "ADS7846_CS"); - if (err) - return; - - err = gpio_request(SPITZ_GPIO_LCDCON_CS, "LCDCON_CS"); - if (err) - goto err_free_1; - - err = gpio_request(SPITZ_GPIO_MAX1111_CS, "MAX1111_CS"); - if (err) - goto err_free_2; - - err = gpio_direction_output(SPITZ_GPIO_ADS7846_CS, 1); - if (err) - goto err_free_3; - err = gpio_direction_output(SPITZ_GPIO_LCDCON_CS, 1); - if (err) - goto err_free_3; - err = gpio_direction_output(SPITZ_GPIO_MAX1111_CS, 1); - if (err) - goto err_free_3; - if (machine_is_akita()) { spitz_lcdcon_info.gpio_backlight_cont = AKITA_GPIO_BACKLIGHT_CONT; spitz_lcdcon_info.gpio_backlight_on = AKITA_GPIO_BACKLIGHT_ON; @@ -423,14 +367,6 @@ static void __init spitz_init_spi(void) pxa2xx_set_spi_info(2, &spitz_spi_info); spi_register_board_info(ARRAY_AND_SIZE(spitz_spi_devices)); - return; - -err_free_3: - gpio_free(SPITZ_GPIO_MAX1111_CS); -err_free_2: - gpio_free(SPITZ_GPIO_LCDCON_CS); -err_free_1: - gpio_free(SPITZ_GPIO_ADS7846_CS); } #else static inline void spitz_init_spi(void) {} diff --git a/arch/arm/mach-pxa/spitz_pm.c b/arch/arm/mach-pxa/spitz_pm.c index 2e4490562c9..724ffb03031 100644 --- a/arch/arm/mach-pxa/spitz_pm.c +++ b/arch/arm/mach-pxa/spitz_pm.c @@ -41,7 +41,6 @@ static void spitz_charger_init(void) { pxa_gpio_mode(SPITZ_GPIO_KEY_INT | GPIO_IN); pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); - sharpsl_pm_pxa_init(); } static void spitz_measure_temp(int on) @@ -182,7 +181,7 @@ unsigned long spitzpm_read_devdata(int type) struct sharpsl_charger_machinfo spitz_pm_machinfo = { .init = spitz_charger_init, - .exit = sharpsl_pm_pxa_remove, + .exit = NULL, .gpio_batlock = SPITZ_GPIO_BAT_COVER, .gpio_acin = SPITZ_GPIO_AC_IN, .gpio_batfull = SPITZ_GPIO_CHRG_FULL, diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c new file mode 100644 index 00000000000..3b205b69f3f --- /dev/null +++ b/arch/arm/mach-pxa/stargate2.c @@ -0,0 +1,796 @@ +/* + * linux/arch/arm/mach-pxa/stargate2.c + * + * Author: Ed C. Epp + * Created: Nov 05, 2002 + * Copyright: Intel Corp. + * + * Modified 2009: Jonathan Cameron <jic23@cam.ac.uk> + * + * 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/init.h> +#include <linux/device.h> +#include <linux/interrupt.h> +#include <linux/sched.h> +#include <linux/bitops.h> +#include <linux/fb.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/regulator/machine.h> +#include <linux/mtd/mtd.h> +#include <linux/mtd/plat-ram.h> +#include <linux/mtd/partitions.h> + +#include <linux/i2c/pcf857x.h> +#include <linux/i2c/at24.h> +#include <linux/smc91x.h> +#include <linux/gpio.h> + +#include <asm/types.h> +#include <asm/setup.h> +#include <asm/memory.h> +#include <asm/mach-types.h> +#include <asm/irq.h> + +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/mach/irq.h> +#include <asm/mach/flash.h> + +#include <mach/pxa27x.h> +#include <plat/i2c.h> +#include <mach/mmc.h> +#include <mach/udc.h> +#include <mach/pxa2xx_spi.h> +#include <mach/pxa27x-udc.h> + +#include <linux/spi/spi.h> +#include <linux/mfd/da903x.h> +#include <linux/sht15.h> + +#include "devices.h" +#include "generic.h" + +/* Bluetooth */ +#define SG2_BT_RESET 81 + +/* SD */ +#define SG2_GPIO_nSD_DETECT 90 +#define SG2_SD_POWER_ENABLE 89 + +static unsigned long stargate2_pin_config[] __initdata = { + + GPIO15_nCS_1, /* SRAM */ + /* SMC91x */ + GPIO80_nCS_4, + GPIO40_GPIO, /*cable detect?*/ + /* Device Identification for wakeup*/ + GPIO102_GPIO, + + /* Button */ + GPIO91_GPIO | WAKEUP_ON_LEVEL_HIGH, + + /* DA9030 */ + GPIO1_GPIO, + + /* Compact Flash */ + GPIO79_PSKTSEL, + GPIO48_nPOE, + GPIO49_nPWE, + GPIO50_nPIOR, + GPIO51_nPIOW, + GPIO85_nPCE_1, + GPIO54_nPCE_2, + GPIO55_nPREG, + GPIO56_nPWAIT, + GPIO57_nIOIS16, + GPIO120_GPIO, /* Buff ctrl */ + GPIO108_GPIO, /* Power ctrl */ + GPIO82_GPIO, /* Reset */ + GPIO53_GPIO, /* SG2_S0_GPIO_DETECT */ + + /* MMC */ + GPIO32_MMC_CLK, + GPIO112_MMC_CMD, + GPIO92_MMC_DAT_0, + GPIO109_MMC_DAT_1, + GPIO110_MMC_DAT_2, + GPIO111_MMC_DAT_3, + GPIO90_GPIO, /* nSD detect */ + GPIO89_GPIO, /* SD_POWER_ENABLE */ + + /* Bluetooth */ + GPIO81_GPIO, /* reset */ + + /* cc2420 802.15.4 radio */ + GPIO22_GPIO, /* CC_RSTN (out)*/ + GPIO114_GPIO, /* CC_FIFO (in) */ + GPIO116_GPIO, /* CC_CCA (in) */ + GPIO0_GPIO, /* CC_FIFOP (in) */ + GPIO16_GPIO, /* CCSFD (in) */ + GPIO39_GPIO, /* CSn (out) */ + + /* I2C */ + GPIO117_I2C_SCL, + GPIO118_I2C_SDA, + + /* SSP 3 - 802.15.4 radio */ + GPIO39_GPIO, /* chip select */ + GPIO34_SSP3_SCLK, + GPIO35_SSP3_TXD, + GPIO41_SSP3_RXD, + + /* SSP 2 */ + GPIO11_SSP2_RXD, + GPIO38_SSP2_TXD, + GPIO36_SSP2_SCLK, + GPIO37_GPIO, /* chip select */ + + /* SSP 1 */ + GPIO26_SSP1_RXD, + GPIO25_SSP1_TXD, + GPIO23_SSP1_SCLK, + GPIO24_GPIO, /* chip select */ + + /* BTUART */ + GPIO42_BTUART_RXD, + GPIO43_BTUART_TXD, + GPIO44_BTUART_CTS, + GPIO45_BTUART_RTS, + + /* STUART */ + GPIO46_STUART_RXD, + GPIO47_STUART_TXD, + + /* Basic sensor board */ + GPIO96_GPIO, /* accelerometer interrupt */ + GPIO99_GPIO, /* ADC interrupt */ + + /* Connector pins specified as gpios */ + GPIO94_GPIO, /* large basic connector pin 14 */ + GPIO10_GPIO, /* large basic connector pin 23 */ + + /* SHT15 */ + GPIO100_GPIO, + GPIO98_GPIO, +}; + +/** + * stargate2_reset_bluetooth() reset the bluecore to ensure consistent state + **/ +static int stargate2_reset_bluetooth(void) +{ + int err; + err = gpio_request(SG2_BT_RESET, "SG2_BT_RESET"); + if (err) { + printk(KERN_ERR "Could not get gpio for bluetooth reset \n"); + return err; + } + gpio_direction_output(SG2_BT_RESET, 1); + mdelay(5); + /* now reset it - 5 msec minimum */ + gpio_set_value(SG2_BT_RESET, 0); + mdelay(10); + gpio_set_value(SG2_BT_RESET, 1); + gpio_free(SG2_BT_RESET); + return 0; +} + +static struct led_info stargate2_leds[] = { + { + .name = "sg2:red", + .flags = DA9030_LED_RATE_ON, + }, { + .name = "sg2:blue", + .flags = DA9030_LED_RATE_ON, + }, { + .name = "sg2:green", + .flags = DA9030_LED_RATE_ON, + }, +}; + +static struct sht15_platform_data platform_data_sht15 = { + .gpio_data = 100, + .gpio_sck = 98, +}; + +static struct platform_device sht15 = { + .name = "sht15", + .id = -1, + .dev = { + .platform_data = &platform_data_sht15, + }, +}; + +static struct regulator_consumer_supply stargate2_sensor_3_con[] = { + { + .dev = &sht15.dev, + .supply = "vcc", + }, +}; + +enum stargate2_ldos{ + vcc_vref, + vcc_cc2420, + /* a mote connector? */ + vcc_mica, + /* the CSR bluecore chip */ + vcc_bt, + /* The two voltages available to sensor boards */ + vcc_sensor_1_8, + vcc_sensor_3, + /* directly connected to the pxa27x */ + vcc_sram_ext, + vcc_pxa_pll, + vcc_pxa_usim, /* Reference voltage for certain gpios */ + vcc_pxa_mem, + vcc_pxa_flash, + vcc_pxa_core, /*Dc-Dc buck not yet supported */ + vcc_lcd, + vcc_bb, + vcc_bbio, /*not sure!*/ + vcc_io, /* cc2420 802.15.4 radio and pxa vcc_io ?*/ +}; + +/* The values of the various regulator constraints are obviously dependent + * on exactly what is wired to each ldo. Unfortunately this information is + * not generally available. More information has been requested from Xbow. + */ +static struct regulator_init_data stargate2_ldo_init_data[] = { + [vcc_bbio] = { + .constraints = { /* board default 1.8V */ + .name = "vcc_bbio", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_bb] = { + .constraints = { /* board default 2.8V */ + .name = "vcc_bb", + .min_uV = 2700000, + .max_uV = 3000000, + }, + }, + [vcc_pxa_flash] = { + .constraints = {/* default is 1.8V */ + .name = "vcc_pxa_flash", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_cc2420] = { /* also vcc_io */ + .constraints = { + /* board default is 2.8V */ + .name = "vcc_cc2420", + .min_uV = 2700000, + .max_uV = 3300000, + }, + }, + [vcc_vref] = { /* Reference for what? */ + .constraints = { /* default 1.8V */ + .name = "vcc_vref", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_sram_ext] = { + .constraints = { /* default 2.8V */ + .name = "vcc_sram_ext", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_mica] = { + .constraints = { /* default 2.8V */ + .name = "vcc_mica", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_bt] = { + .constraints = { /* default 2.8V */ + .name = "vcc_bt", + .min_uV = 2800000, + .max_uV = 2800000, + }, + }, + [vcc_lcd] = { + .constraints = { /* default 2.8V */ + .name = "vcc_lcd", + .min_uV = 2700000, + .max_uV = 3300000, + }, + }, + [vcc_io] = { /* Same or higher than everything + * bar vccbat and vccusb */ + .constraints = { /* default 2.8V */ + .name = "vcc_io", + .min_uV = 2692000, + .max_uV = 3300000, + }, + }, + [vcc_sensor_1_8] = { + .constraints = { /* default 1.8V */ + .name = "vcc_sensor_1_8", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, + [vcc_sensor_3] = { /* curiously default 2.8V */ + .constraints = { + .name = "vcc_sensor_3", + .min_uV = 2800000, + .max_uV = 3000000, + }, + .num_consumer_supplies = ARRAY_SIZE(stargate2_sensor_3_con), + .consumer_supplies = stargate2_sensor_3_con, + }, + [vcc_pxa_pll] = { /* 1.17V - 1.43V, default 1.3V*/ + .constraints = { + .name = "vcc_pxa_pll", + .min_uV = 1170000, + .max_uV = 1430000, + }, + }, + [vcc_pxa_usim] = { + .constraints = { /* default 1.8V */ + .name = "vcc_pxa_usim", + .min_uV = 1710000, + .max_uV = 2160000, + }, + }, + [vcc_pxa_mem] = { + .constraints = { /* default 1.8V */ + .name = "vcc_pxa_mem", + .min_uV = 1800000, + .max_uV = 1800000, + }, + }, +}; + +static struct da903x_subdev_info stargate2_da9030_subdevs[] = { + { + .name = "da903x-led", + .id = DA9030_ID_LED_2, + .platform_data = &stargate2_leds[0], + }, { + .name = "da903x-led", + .id = DA9030_ID_LED_3, + .platform_data = &stargate2_leds[2], + }, { + .name = "da903x-led", + .id = DA9030_ID_LED_4, + .platform_data = &stargate2_leds[1], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO2, + .platform_data = &stargate2_ldo_init_data[vcc_bbio], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO3, + .platform_data = &stargate2_ldo_init_data[vcc_bb], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO4, + .platform_data = &stargate2_ldo_init_data[vcc_pxa_flash], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO5, + .platform_data = &stargate2_ldo_init_data[vcc_cc2420], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO6, + .platform_data = &stargate2_ldo_init_data[vcc_vref], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO7, + .platform_data = &stargate2_ldo_init_data[vcc_sram_ext], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO8, + .platform_data = &stargate2_ldo_init_data[vcc_mica], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO9, + .platform_data = &stargate2_ldo_init_data[vcc_bt], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO10, + .platform_data = &stargate2_ldo_init_data[vcc_sensor_1_8], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO11, + .platform_data = &stargate2_ldo_init_data[vcc_sensor_3], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO12, + .platform_data = &stargate2_ldo_init_data[vcc_lcd], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO15, + .platform_data = &stargate2_ldo_init_data[vcc_pxa_pll], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO17, + .platform_data = &stargate2_ldo_init_data[vcc_pxa_usim], + }, { + .name = "da903x-regulator", /*pxa vcc i/o and cc2420 vcc i/o */ + .id = DA9030_ID_LDO18, + .platform_data = &stargate2_ldo_init_data[vcc_io], + }, { + .name = "da903x-regulator", + .id = DA9030_ID_LDO19, + .platform_data = &stargate2_ldo_init_data[vcc_pxa_mem], + }, +}; + +static struct da903x_platform_data stargate2_da9030_pdata = { + .num_subdevs = ARRAY_SIZE(stargate2_da9030_subdevs), + .subdevs = stargate2_da9030_subdevs, +}; + +static struct resource smc91x_resources[] = { + [0] = { + .name = "smc91x-regs", + .start = (PXA_CS4_PHYS + 0x300), + .end = (PXA_CS4_PHYS + 0xfffff), + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = IRQ_GPIO(40), + .end = IRQ_GPIO(40), + .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, + } +}; + +static struct smc91x_platdata stargate2_smc91x_info = { + .flags = SMC91X_USE_8BIT | SMC91X_USE_16BIT | SMC91X_USE_32BIT + | SMC91X_NOWAIT | SMC91X_USE_DMA, +}; + +static struct platform_device smc91x_device = { + .name = "smc91x", + .id = -1, + .num_resources = ARRAY_SIZE(smc91x_resources), + .resource = smc91x_resources, + .dev = { + .platform_data = &stargate2_smc91x_info, + }, +}; + + + +static struct pxamci_platform_data stargate2_mci_platform_data; + +/* + * The card detect interrupt isn't debounced so we delay it by 250ms + * to give the card a chance to fully insert / eject. + */ +static int stargate2_mci_init(struct device *dev, + irq_handler_t stargate2_detect_int, + void *data) +{ + int err; + + err = gpio_request(SG2_SD_POWER_ENABLE, "SG2_sd_power_enable"); + if (err) { + printk(KERN_ERR "Can't get the gpio for SD power control"); + goto return_err; + } + gpio_direction_output(SG2_SD_POWER_ENABLE, 0); + + err = gpio_request(SG2_GPIO_nSD_DETECT, "SG2_sd_detect"); + if (err) { + printk(KERN_ERR "Can't get the sd detect gpio"); + goto free_power_en; + } + gpio_direction_input(SG2_GPIO_nSD_DETECT); + /* Delay to allow for full insertion */ + stargate2_mci_platform_data.detect_delay = msecs_to_jiffies(250); + + err = request_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), + stargate2_detect_int, + IRQ_TYPE_EDGE_BOTH, + "MMC card detect", + data); + if (err) { + printk(KERN_ERR "can't request MMC card detect IRQ\n"); + goto free_nsd_detect; + } + return 0; + + free_nsd_detect: + gpio_free(SG2_GPIO_nSD_DETECT); + free_power_en: + gpio_free(SG2_SD_POWER_ENABLE); + return_err: + return err; +} + +/** + * stargate2_mci_setpower() - set state of mmc power supply + * + * Very simple control. Either it is on or off and is controlled by + * a gpio pin */ +static void stargate2_mci_setpower(struct device *dev, unsigned int vdd) +{ + gpio_set_value(SG2_SD_POWER_ENABLE, !!vdd); +} + +static void stargate2_mci_exit(struct device *dev, void *data) +{ + free_irq(IRQ_GPIO(SG2_GPIO_nSD_DETECT), data); + gpio_free(SG2_SD_POWER_ENABLE); + gpio_free(SG2_GPIO_nSD_DETECT); +} + +static struct pxamci_platform_data stargate2_mci_platform_data = { + .ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34, + .init = stargate2_mci_init, + .setpower = stargate2_mci_setpower, + .exit = stargate2_mci_exit, +}; + +static struct mtd_partition stargate2flash_partitions[] = { + { + .name = "Bootloader", + .size = 0x00040000, + .offset = 0, + .mask_flags = 0, + }, { + .name = "Kernel", + .size = 0x00200000, + .offset = 0x00040000, + .mask_flags = 0 + }, { + .name = "Filesystem", + .size = 0x01DC0000, + .offset = 0x00240000, + .mask_flags = 0 + }, +}; + +static struct resource flash_resources = { + .start = PXA_CS0_PHYS, + .end = PXA_CS0_PHYS + SZ_32M - 1, + .flags = IORESOURCE_MEM, +}; + +static struct flash_platform_data stargate2_flash_data = { + .map_name = "cfi_probe", + .parts = stargate2flash_partitions, + .nr_parts = ARRAY_SIZE(stargate2flash_partitions), + .name = "PXA27xOnChipROM", + .width = 2, +}; + +static struct platform_device stargate2_flash_device = { + .name = "pxa2xx-flash", + .id = 0, + .dev = { + .platform_data = &stargate2_flash_data, + }, + .resource = &flash_resources, + .num_resources = 1, +}; + +/* + * SRAM - The Stargate 2 has 32MB of SRAM. + * + * Here it is made available as an MTD. This will then + * typically have a cifs filesystem created on it to provide + * fast temporary storage. + */ +static struct resource sram_resources = { + .start = PXA_CS1_PHYS, + .end = PXA_CS1_PHYS + SZ_32M-1, + .flags = IORESOURCE_MEM, +}; + +static struct platdata_mtd_ram stargate2_sram_pdata = { + .mapname = "Stargate2 SRAM", + .bankwidth = 2, +}; + +static struct platform_device stargate2_sram = { + .name = "mtd-ram", + .id = 0, + .resource = &sram_resources, + .num_resources = 1, + .dev = { + .platform_data = &stargate2_sram_pdata, + }, +}; + +static struct pcf857x_platform_data platform_data_pcf857x = { + .gpio_base = 128, + .n_latch = 0, + .setup = NULL, + .teardown = NULL, + .context = NULL, +}; + +static struct at24_platform_data pca9500_eeprom_pdata = { + .byte_len = 256, + .page_size = 4, +}; + + +static struct i2c_board_info __initdata stargate2_i2c_board_info[] = { + /* Techically this a pca9500 - but it's compatible with the 8574 + * for gpio expansion and the 24c02 for eeprom access. + */ + { + .type = "pcf8574", + .addr = 0x27, + .platform_data = &platform_data_pcf857x, + }, { + .type = "24c02", + .addr = 0x57, + .platform_data = &pca9500_eeprom_pdata, + }, { + .type = "max1238", + .addr = 0x35, + }, { /* ITS400 Sensor board only */ + .type = "max1363", + .addr = 0x34, + /* Through a nand gate - Also beware, on V2 sensor board the + * pull up resistors are missing. + */ + .irq = IRQ_GPIO(99), + }, { /* ITS400 Sensor board only */ + .type = "tsl2561", + .addr = 0x49, + /* Through a nand gate - Also beware, on V2 sensor board the + * pull up resistors are missing. + */ + .irq = IRQ_GPIO(99), + }, { /* ITS400 Sensor board only */ + .type = "tmp175", + .addr = 0x4A, + .irq = IRQ_GPIO(96), + }, +}; + +static struct i2c_board_info __initdata stargate2_pwr_i2c_board_info[] = { + { + .type = "da9030", + .addr = 0x49, + .platform_data = &stargate2_da9030_pdata, + .irq = gpio_to_irq(1), + }, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_0_info = { + .num_chipselect = 1, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_1_info = { + .num_chipselect = 1, +}; + +static struct pxa2xx_spi_master pxa_ssp_master_2_info = { + .num_chipselect = 1, +}; + +/* An upcoming kernel change will scrap SFRM usage so these + * drivers have been moved to use gpio's via cs_control */ +static struct pxa2xx_spi_chip staccel_chip_info = { + .tx_threshold = 8, + .rx_threshold = 8, + .dma_burst_size = 8, + .timeout = 235, + .gpio_cs = 24, +}; + +static struct pxa2xx_spi_chip cc2420_info = { + .tx_threshold = 8, + .rx_threshold = 8, + .dma_burst_size = 8, + .timeout = 235, + .gpio_cs = 39, +}; + +static struct spi_board_info spi_board_info[] __initdata = { + { + .modalias = "lis3l02dq", + .max_speed_hz = 8000000,/* 8MHz max spi frequency at 3V */ + .bus_num = 1, + .chip_select = 0, + .controller_data = &staccel_chip_info, + .irq = IRQ_GPIO(96), + }, { + .modalias = "cc2420", + .max_speed_hz = 6500000, + .bus_num = 3, + .chip_select = 0, + .controller_data = &cc2420_info, + }, +}; + +static void sg2_udc_command(int cmd) +{ + switch (cmd) { + case PXA2XX_UDC_CMD_CONNECT: + UP2OCR |= UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE; + break; + case PXA2XX_UDC_CMD_DISCONNECT: + UP2OCR &= ~(UP2OCR_HXOE | UP2OCR_DPPUE | UP2OCR_DPPUBE); + break; + } +} + +/* Board doesn't support cable detection - so always lie and say + * something is there. + */ +static int sg2_udc_detect(void) +{ + return 1; +} + +static struct pxa2xx_udc_mach_info stargate2_udc_info __initdata = { + .udc_is_connected = sg2_udc_detect, + .udc_command = sg2_udc_command, +}; + +static struct platform_device *stargate2_devices[] = { + &stargate2_flash_device, + &stargate2_sram, + &smc91x_device, + &sht15, +}; + +static struct i2c_pxa_platform_data i2c_pwr_pdata = { + .fast_mode = 1, +}; + +static struct i2c_pxa_platform_data i2c_pdata = { + .fast_mode = 1, +}; + +static void __init stargate2_init(void) +{ + /* This is probably a board specific hack as this must be set + prior to connecting the MFP stuff up. */ + MECR &= ~MECR_NOS; + + pxa2xx_mfp_config(ARRAY_AND_SIZE(stargate2_pin_config)); + + /* spi chip selects */ + gpio_direction_output(37, 0); + gpio_direction_output(24, 0); + gpio_direction_output(39, 0); + + platform_add_devices(ARRAY_AND_SIZE(stargate2_devices)); + + pxa2xx_set_spi_info(1, &pxa_ssp_master_0_info); + pxa2xx_set_spi_info(2, &pxa_ssp_master_1_info); + pxa2xx_set_spi_info(3, &pxa_ssp_master_2_info); + spi_register_board_info(spi_board_info, ARRAY_SIZE(spi_board_info)); + + i2c_register_board_info(0, ARRAY_AND_SIZE(stargate2_i2c_board_info)); + i2c_register_board_info(1, + ARRAY_AND_SIZE(stargate2_pwr_i2c_board_info)); + pxa27x_set_i2c_power_info(&i2c_pwr_pdata); + pxa_set_i2c_info(&i2c_pdata); + + pxa_set_mci_info(&stargate2_mci_platform_data); + + pxa_set_udc_info(&stargate2_udc_info); + + stargate2_reset_bluetooth(); +} + +MACHINE_START(STARGATE2, "Stargate 2") + .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 = stargate2_init, + .boot_params = 0xA0000100, +MACHINE_END diff --git a/arch/arm/mach-pxa/tosa-bt.c b/arch/arm/mach-pxa/tosa-bt.c index fb0294bd431..c31e601eb49 100644 --- a/arch/arm/mach-pxa/tosa-bt.c +++ b/arch/arm/mach-pxa/tosa-bt.c @@ -35,21 +35,25 @@ static void tosa_bt_off(struct tosa_bt_data *data) gpio_set_value(data->gpio_reset, 0); } -static int tosa_bt_toggle_radio(void *data, enum rfkill_state state) +static int tosa_bt_set_block(void *data, bool blocked) { - pr_info("BT_RADIO going: %s\n", - state == RFKILL_STATE_ON ? "on" : "off"); + pr_info("BT_RADIO going: %s\n", blocked ? "off" : "on"); - if (state == RFKILL_STATE_ON) { + if (!blocked) { pr_info("TOSA_BT: going ON\n"); tosa_bt_on(data); } else { pr_info("TOSA_BT: going OFF\n"); tosa_bt_off(data); } + return 0; } +static const struct rfkill_ops tosa_bt_rfkill_ops = { + .set_block = tosa_bt_set_block, +}; + static int tosa_bt_probe(struct platform_device *dev) { int rc; @@ -70,18 +74,14 @@ static int tosa_bt_probe(struct platform_device *dev) if (rc) goto err_pwr_dir; - rfk = rfkill_allocate(&dev->dev, RFKILL_TYPE_BLUETOOTH); + rfk = rfkill_alloc("tosa-bt", &dev->dev, RFKILL_TYPE_BLUETOOTH, + &tosa_bt_rfkill_ops, data); if (!rfk) { rc = -ENOMEM; goto err_rfk_alloc; } - rfk->name = "tosa-bt"; - rfk->toggle_radio = tosa_bt_toggle_radio; - rfk->data = data; -#ifdef CONFIG_RFKILL_LEDS - rfk->led_trigger.name = "tosa-bt"; -#endif + rfkill_set_led_trigger_name(rfk, "tosa-bt"); rc = rfkill_register(rfk); if (rc) @@ -92,9 +92,7 @@ static int tosa_bt_probe(struct platform_device *dev) return 0; err_rfkill: - if (rfk) - rfkill_free(rfk); - rfk = NULL; + rfkill_destroy(rfk); err_rfk_alloc: tosa_bt_off(data); err_pwr_dir: @@ -113,8 +111,10 @@ static int __devexit tosa_bt_remove(struct platform_device *dev) platform_set_drvdata(dev, NULL); - if (rfk) + if (rfk) { rfkill_unregister(rfk); + rfkill_destroy(rfk); + } rfk = NULL; tosa_bt_off(data); diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c index a0bd46ef5d3..117ad5920e5 100644 --- a/arch/arm/mach-pxa/tosa.c +++ b/arch/arm/mach-pxa/tosa.c @@ -31,7 +31,6 @@ #include <linux/input.h> #include <linux/gpio.h> #include <linux/pda_power.h> -#include <linux/rfkill.h> #include <linux/spi/spi.h> #include <asm/setup.h> @@ -40,7 +39,7 @@ #include <mach/pxa25x.h> #include <mach/reset.h> #include <mach/irda.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/mmc.h> #include <mach/udc.h> #include <mach/tosa_bt.h> diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c index f79c9cb70ae..825f540176d 100644 --- a/arch/arm/mach-pxa/trizeps4.c +++ b/arch/arm/mach-pxa/trizeps4.c @@ -47,7 +47,7 @@ #include <mach/mmc.h> #include <mach/irda.h> #include <mach/ohci.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include "generic.h" #include "devices.h" diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c index dd031cc4184..d33c232b686 100644 --- a/arch/arm/mach-pxa/viper.c +++ b/arch/arm/mach-pxa/viper.c @@ -45,7 +45,7 @@ #include <mach/pxa25x.h> #include <mach/audio.h> #include <mach/pxafb.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/regs-uart.h> #include <mach/viper.h> diff --git a/arch/arm/mach-pxa/zylonite_pxa300.c b/arch/arm/mach-pxa/zylonite_pxa300.c index c256c57642c..cefd1c0a854 100644 --- a/arch/arm/mach-pxa/zylonite_pxa300.c +++ b/arch/arm/mach-pxa/zylonite_pxa300.c @@ -21,7 +21,7 @@ #include <linux/gpio.h> #include <mach/pxa300.h> -#include <mach/i2c.h> +#include <plat/i2c.h> #include <mach/zylonite.h> #include "generic.h" |