aboutsummaryrefslogtreecommitdiff
path: root/arch/arm/mach-pxa
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-pxa')
-rw-r--r--arch/arm/mach-pxa/Kconfig25
-rw-r--r--arch/arm/mach-pxa/Makefile3
-rw-r--r--arch/arm/mach-pxa/clock.c17
-rw-r--r--arch/arm/mach-pxa/cm-x270.c4
-rw-r--r--arch/arm/mach-pxa/cm-x300.c55
-rw-r--r--arch/arm/mach-pxa/corgi.c47
-rw-r--r--arch/arm/mach-pxa/corgi_pm.c3
-rw-r--r--arch/arm/mach-pxa/cpufreq-pxa2xx.c104
-rw-r--r--arch/arm/mach-pxa/csb726.c20
-rw-r--r--arch/arm/mach-pxa/devices.c4
-rw-r--r--arch/arm/mach-pxa/em-x270.c173
-rw-r--r--arch/arm/mach-pxa/ezx.c177
-rw-r--r--arch/arm/mach-pxa/hx4700.c851
-rw-r--r--arch/arm/mach-pxa/imote2.c52
-rw-r--r--arch/arm/mach-pxa/include/mach/hx4700.h131
-rw-r--r--arch/arm/mach-pxa/include/mach/i2c.h82
-rw-r--r--arch/arm/mach-pxa/include/mach/irqs.h18
-rw-r--r--arch/arm/mach-pxa/include/mach/mfp-pxa320.h14
-rw-r--r--arch/arm/mach-pxa/include/mach/palmld.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/pm.h2
-rw-r--r--arch/arm/mach-pxa/include/mach/pxa27x.h3
-rw-r--r--arch/arm/mach-pxa/include/mach/sharpsl_pm.h104
-rw-r--r--arch/arm/mach-pxa/include/mach/uncompress.h3
-rw-r--r--arch/arm/mach-pxa/littleton.c82
-rw-r--r--arch/arm/mach-pxa/magician.c14
-rw-r--r--arch/arm/mach-pxa/mainstone.c2
-rw-r--r--arch/arm/mach-pxa/mioa701.c4
-rw-r--r--arch/arm/mach-pxa/palmld.c42
-rw-r--r--arch/arm/mach-pxa/palmt5.c46
-rw-r--r--arch/arm/mach-pxa/palmte2.c32
-rw-r--r--arch/arm/mach-pxa/palmtx.c45
-rw-r--r--arch/arm/mach-pxa/pcm990-baseboard.c25
-rw-r--r--arch/arm/mach-pxa/pm.c4
-rw-r--r--arch/arm/mach-pxa/poodle.c17
-rw-r--r--arch/arm/mach-pxa/pwm.c318
-rw-r--r--arch/arm/mach-pxa/pxa27x.c21
-rw-r--r--arch/arm/mach-pxa/pxa3xx.c4
-rw-r--r--arch/arm/mach-pxa/saar.c2
-rw-r--r--arch/arm/mach-pxa/sharpsl.h4
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c863
-rw-r--r--arch/arm/mach-pxa/spitz.c78
-rw-r--r--arch/arm/mach-pxa/spitz_pm.c3
-rw-r--r--arch/arm/mach-pxa/stargate2.c796
-rw-r--r--arch/arm/mach-pxa/tosa-bt.c30
-rw-r--r--arch/arm/mach-pxa/tosa.c3
-rw-r--r--arch/arm/mach-pxa/trizeps4.c2
-rw-r--r--arch/arm/mach-pxa/viper.c2
-rw-r--r--arch/arm/mach-pxa/zylonite_pxa300.c2
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"