arch/arm/common/locomo.c | 6 arch/arm/common/sharpsl_pm.c | 9 arch/arm/mach-pxa/Kconfig | 1 arch/arm/mach-pxa/Makefile | 2 arch/arm/mach-pxa/poodle_pm.c | 355 ++++++++++++++++++++++++++++++++++++++ include/asm-arm/hardware/locomo.h | 5 6 files changed, 377 insertions(+), 1 deletion(-) Index: linux-2.6.26/arch/arm/common/sharpsl_pm.c =================================================================== --- linux-2.6.26.orig/arch/arm/common/sharpsl_pm.c 2008-08-05 22:15:07.000000000 -0700 +++ linux-2.6.26/arch/arm/common/sharpsl_pm.c 2008-08-05 22:15:11.000000000 -0700 @@ -458,6 +458,10 @@ { int temp, i, buff[5]; + /* Some devices don't support this */ + if (!sharpsl_pm.machinfo->charge_acin_high) + return 0; + for (i=0; i<5; i++) { buff[i] = sharpsl_pm.machinfo->read_devdata(SHARPSL_ACIN_VOLT); mdelay(SHARPSL_CHECK_BATTERY_WAIT_TIME_ACIN); @@ -598,6 +602,9 @@ dev_dbg(sharpsl_pm.dev, "sharpsl_fatal_check entered\n"); + if (machine_is_poodle()) + return 0; + /* Check AC-Adapter */ acin = sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN); @@ -664,6 +671,7 @@ dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 1\n"); /* AC Check */ + if (!machine_is_poodle()) if ((sharpsl_ac_check() < 0) || (sharpsl_check_battery_temp() < 0)) return sharpsl_off_charge_error(); @@ -686,6 +694,7 @@ dev_dbg(sharpsl_pm.dev, "Offline Charger: Step 2\n"); + if (!machine_is_poodle()) if ((sharpsl_check_battery_temp() < 0) || (sharpsl_check_battery_voltage() < 0)) return sharpsl_off_charge_error(); Index: linux-2.6.26/arch/arm/mach-pxa/Kconfig =================================================================== --- linux-2.6.26.orig/arch/arm/mach-pxa/Kconfig 2008-08-05 22:15:05.000000000 -0700 +++ linux-2.6.26/arch/arm/mach-pxa/Kconfig 2008-08-05 22:16:25.000000000 -0700 @@ -210,6 +210,7 @@ bool "Enable Sharp SL-5600 (Poodle) Support" depends on PXA_SHARPSL_25x select SHARP_LOCOMO + select SHARPSL_PM select PXA_SSP config MACH_CORGI Index: linux-2.6.26/arch/arm/mach-pxa/Makefile =================================================================== --- linux-2.6.26.orig/arch/arm/mach-pxa/Makefile 2008-08-05 22:15:05.000000000 -0700 +++ linux-2.6.26/arch/arm/mach-pxa/Makefile 2008-08-05 22:16:25.000000000 -0700 @@ -30,7 +30,7 @@ obj-$(CONFIG_PXA_SHARP_C7xx) += corgi.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o corgi_pm.o obj-$(CONFIG_PXA_SHARP_Cxx00) += spitz.o corgi_ssp.o corgi_lcd.o sharpsl_pm.o spitz_pm.o obj-$(CONFIG_MACH_AKITA) += akita-ioexp.o -obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o +obj-$(CONFIG_MACH_POODLE) += poodle.o corgi_ssp.o sharpsl_pm.o poodle_pm.o obj-$(CONFIG_MACH_HX2750) += hx2750.o hx2750_test.o obj-$(CONFIG_MACH_PCM027) += pcm027.o obj-$(CONFIG_MACH_PCM990_BASEBOARD) += pcm990-baseboard.o Index: linux-2.6.26/arch/arm/mach-pxa/poodle_pm.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6.26/arch/arm/mach-pxa/poodle_pm.c 2008-08-05 22:21:31.000000000 -0700 @@ -0,0 +1,356 @@ +/* + * Battery and Power Management code for the Sharp SL-5600 + * + * Copyright (c) 2006 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. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "sharpsl.h" + +#if 0 +#define SHARPSL_CHARGE_ON_VOLT 0x99 /* 2.9V */ +#define SHARPSL_CHARGE_ON_TEMP 0xe0 /* 2.9V */ +#define SHARPSL_CHARGE_ON_ACIN_HIGH 0x9b /* 6V */ +#define SHARPSL_CHARGE_ON_ACIN_LOW 0x34 /* 2V */ +#define SHARPSL_FATAL_ACIN_VOLT 182 /* 3.45V */ +#define SHARPSL_FATAL_NOACIN_VOLT 170 /* 3.40V */ +#endif + +#define SHARPSL_CHARGE_ON_VOLT 1187 // 2.9V +#define SHARPSL_CHARGE_ON_TEMP 2441 +#define SHARPSL_FATAL_NOACIN_VOLT 1454 // 3.55V +#define SHARPSL_FATAL_ACIN_VOLT 1474 // 3.60V + + +#if 0 +#define SHARPSL_POWER_MODE_CHECK 1475 +#define SHARPSL_POODLE_FATAL_VOLT 1433 +#define SHARPSL_POODLE_FATAL_NOACIN_FLON_VOLT 1454 // 3.55V +#define SHARPSL_POODLE_FATAL_NOACIN_FLOFF_VOLT 1433 // 3.50V +#define SHARPSL_POODLE_FATAL_ACIN_FLON_VOLT 1474 // 3.60V +#define SHARPSL_POODLE_FATAL_ACIN_FLOFF_VOLT 1454 // 3.55V +#define SHARPSL_CHECK_BATTERY_WAIT_TIME_TEMP 5 // 50msec +#define SHARPSL_CHECK_BATTERY_WAIT_TIME_VOLT 1 // 10msec +#define SHARPSL_WAIT_DISCHARGE_ON 5 // 50msec +#endif + + +struct battery_thresh poodle_battery_levels_fl[] = { + {1582, 100}, + {1527, 75}, + {1482, 50}, + {1458, 25}, + {1404, 5}, + { 0, 0}, +}; + +struct battery_thresh poodle_battery_levels_nofl[] = { + {1589, 100}, + {1536, 75}, + {1490, 50}, + {1466, 25}, + {1413, 5}, + { 0, 0}, +}; + +struct battery_thresh poodle_battery_levels_acin_fl[] = { + {1601, 100}, + {1536, 75}, + {1503, 50}, + {1482, 25}, + { 0, 5}, + { 0, 0}, +}; + +struct battery_thresh poodle_battery_levels_acin_nofl[] = { + {1609, 100}, + {1548, 75}, + {1527, 50}, + {1495, 25}, + { 0, 5}, + { 0, 0}, +}; + +static void poodle_charger_init(void) +{ + pxa_gpio_mode(POODLE_GPIO_ADC_TEMP_ON | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_CHRG_ON | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_BYPASS_ON | GPIO_OUT); + pxa_gpio_mode(POODLE_GPIO_ON_KEY | GPIO_IN); + sharpsl_pm_pxa_init(); +} + +static void poodle_measure_temp(int on) +{ + if (on) + GPSR(POODLE_GPIO_ADC_TEMP_ON) = GPIO_bit(POODLE_GPIO_ADC_TEMP_ON); + else + GPCR(POODLE_GPIO_ADC_TEMP_ON) = GPIO_bit(POODLE_GPIO_ADC_TEMP_ON); +} + +extern struct locomo_dev *frontlight_dev; + +static void poodle_charge(int on) +{ + if (on) { + GPSR(POODLE_GPIO_CHRG_ON) = GPIO_bit(POODLE_GPIO_CHRG_ON); + locomo_gpio_write(&poodle_locomo_device.dev, POODLE_LOCOMO_GPIO_JK_B, 1); + } else { + GPCR(POODLE_GPIO_CHRG_ON) = GPIO_bit(POODLE_GPIO_CHRG_ON); + locomo_gpio_write(&poodle_locomo_device.dev, POODLE_LOCOMO_GPIO_JK_B, 0); + } +} + +static void poodle_discharge(int on) +{ + if (on) + GPSR(POODLE_GPIO_DISCHARGE_ON) = GPIO_bit(POODLE_GPIO_DISCHARGE_ON); + else + GPCR(POODLE_GPIO_DISCHARGE_ON) = GPIO_bit(POODLE_GPIO_DISCHARGE_ON); +} + +static void poodle_presuspend(void) +{ + int i; + unsigned long wakeup_mask; + + /* charging , so CHARGE_ON bit is HIGH during OFF. */ + if (READ_GPIO_BIT(POODLE_GPIO_CHRG_ON)) + PGSR1 |= GPIO_bit(POODLE_GPIO_CHRG_ON); + else + PGSR1 &= ~GPIO_bit(POODLE_GPIO_CHRG_ON); + +// if (READ_GPIO_BIT(CORGI_GPIO_CHRG_UKN)) +// PGSR1 |= GPIO_bit(CORGI_GPIO_CHRG_UKN); +// else +// PGSR1 &= ~GPIO_bit(CORGI_GPIO_CHRG_UKN); + + /* Resume on keyboard power key */ +// PGSR2 = (PGSR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(0); + + wakeup_mask = GPIO_bit(POODLE_GPIO_ON_KEY) | GPIO_bit(POODLE_GPIO_WAKEUP); + wakeup_mask |= GPIO_bit(POODLE_GPIO_AC_IN) | GPIO_bit(POODLE_GPIO_CHRG_FULL); + wakeup_mask |= GPIO_bit(POODLE_GPIO_MAIN_BAT_LOW) | GPIO_bit(POODLE_GPIO_CF_CD); + wakeup_mask |= GPIO_bit(POODLE_GPIO_HP_IN) | GPIO_bit(POODLE_GPIO_GA_INT) | GPIO_bit(POODLE_GPIO_nSD_INT); + + +// if (!machine_is_corgi()) +// GPDR0 &= ~(GPIO_bit(15) | GPIO_bit(8)); /* Float n_CS1 */ + + PWER = wakeup_mask | PWER_RTC; + PRER = wakeup_mask; + PFER = wakeup_mask; + + for (i = 0; i <=15; i++) { + if (PRER & PFER & GPIO_bit(i)) { + if (GPLR0 & GPIO_bit(i) ) + PRER &= ~GPIO_bit(i); + else + PFER &= ~GPIO_bit(i); + } + } +} + +static void poodle_postsuspend(void) +{ +// if (!machine_is_corgi()) +// GPDR0 |= GPIO_bit(15) | GPIO_bit(8); /* Un-Float n_CS1 */ +} + +/* + * Check what brought us out of the suspend. + * Return: 0 to sleep, otherwise wake + */ +static int poodle_should_wakeup(unsigned int resume_on_alarm) +{ + int is_resume = 0; + + dev_dbg(sharpsl_pm.dev, "GPLR0 = %x,%x\n", GPLR0, PEDR); + + if ((PEDR & GPIO_bit(POODLE_GPIO_AC_IN))) { + if (sharpsl_pm.machinfo->read_devdata(SHARPSL_STATUS_ACIN)) { + /* charge on */ + dev_dbg(sharpsl_pm.dev, "ac insert\n"); + sharpsl_pm.flags |= SHARPSL_DO_OFFLINE_CHRG; + } else { + /* charge off */ + dev_dbg(sharpsl_pm.dev, "ac remove\n"); + sharpsl_pm_led(SHARPSL_LED_OFF); + sharpsl_pm.machinfo->charge(0); + sharpsl_pm.charge_mode = CHRG_OFF; + } + } + + if ((PEDR & GPIO_bit(POODLE_GPIO_CHRG_FULL))) + dev_dbg(sharpsl_pm.dev, "Charge full interrupt\n"); + + if (PEDR & GPIO_bit(POODLE_GPIO_ON_KEY)) + is_resume |= GPIO_bit(POODLE_GPIO_ON_KEY); + + if (PEDR & GPIO_bit(POODLE_GPIO_WAKEUP)) + is_resume |= GPIO_bit(POODLE_GPIO_WAKEUP); + +// if ( (apm_wakeup_factor & GPIO_bit(GPIO_GA_INT)) && (LCM_KIC & 1) ) { +// LCM_KIC &= ~0x100; +// LCM_ICR &= ~0x100; +// is_resume |= GPIO_bit(GPIO_GA_INT); +// } + + if (PEDR & GPIO_bit(POODLE_GPIO_CF_STSCHG)) + is_resume |= GPIO_bit(POODLE_GPIO_CF_STSCHG); + + if (PEDR & GPIO_bit(POODLE_GPIO_nSD_INT)) + is_resume |= GPIO_bit(POODLE_GPIO_nSD_INT); + + if (PEDR & GPIO_bit(POODLE_GPIO_HP_IN)) + is_resume |= GPIO_bit(POODLE_GPIO_HP_IN); + + if (resume_on_alarm && (PEDR & PWER_RTC)) + is_resume |= PWER_RTC; + + dev_dbg(sharpsl_pm.dev, "is_resume: %x\n",is_resume); + return is_resume; +} + +static unsigned long poodle_charger_wakeup(void) +{ + return ~GPLR0 & ( GPIO_bit(POODLE_GPIO_AC_IN) | GPIO_bit(POODLE_GPIO_ON_KEY) | GPIO_bit(POODLE_GPIO_WAKEUP) ); +} + +#define MUX_CHL 6u +#define BATT_CHL 2u + +/* ADS7846 Touch Screen Controller bit definitions */ +#define ADSCTRL_PD0 (1u << 0) /* PD0 */ +#define ADSCTRL_PD1 (1u << 1) /* PD1 */ +#define ADSCTRL_DFR (1u << 2) /* SER/DFR */ +#define ADSCTRL_MOD (1u << 3) /* Mode */ +#define ADSCTRL_ADR_SH 4 /* Address setting */ +#define ADSCTRL_STS (1u << 7) /* Start Bit */ + +int poodle_pm_read_ads7846(int channel) +{ + int voltage; + int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | ADSCTRL_DFR | + (channel << ADSCTRL_ADR_SH) | ADSCTRL_STS; + + corgi_ssp_ads7846_lock(); + + corgi_ssp_ads7846_put(cmd); + corgi_ssp_ads7846_get(); + + corgi_ssp_ads7846_put(cmd); + voltage = corgi_ssp_ads7846_get(); + + /* Power-Down Enable */ + corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); + corgi_ssp_ads7846_get(); + + corgi_ssp_ads7846_unlock(); + + return voltage; +} + +unsigned long poodlepm_read_devdata(int type) +{ + switch(type) { + case SHARPSL_STATUS_ACIN: + return ((GPLR(POODLE_GPIO_AC_IN) & GPIO_bit(POODLE_GPIO_AC_IN)) != 0); + case SHARPSL_STATUS_LOCK: + return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batlock); + case SHARPSL_STATUS_CHRGFULL: + return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_batfull); + case SHARPSL_STATUS_FATAL: + return READ_GPIO_BIT(sharpsl_pm.machinfo->gpio_fatal); +// case SHARPSL_ACIN_VOLT: +// return poodle_pm_read_ads7846(MAX1111_ACIN_VOLT); +// FIXME + case SHARPSL_BATT_TEMP: + return poodle_pm_read_ads7846(MUX_CHL); + case SHARPSL_BATT_VOLT: + default: + return poodle_pm_read_ads7846(BATT_CHL); + } +} + +static void poodle_limit_intensity(int limit) +{ +} + +static struct sharpsl_charger_machinfo poodle_pm_machinfo = { + .init = poodle_charger_init, + .exit = sharpsl_pm_pxa_remove, + .gpio_batlock = POODLE_GPIO_BAT_COVER, + .gpio_acin = POODLE_GPIO_AC_IN, + .gpio_batfull = POODLE_GPIO_CHRG_FULL, + .batfull_irq = 1, + .discharge = poodle_discharge, + .charge = poodle_charge, + .measure_temp = poodle_measure_temp, + .presuspend = poodle_presuspend, + .postsuspend = poodle_postsuspend, + .read_devdata = poodlepm_read_devdata, + .charger_wakeup = poodle_charger_wakeup, + .should_wakeup = poodle_should_wakeup, + .backlight_limit = poodle_limit_intensity, + .charge_on_volt = SHARPSL_CHARGE_ON_VOLT, + .charge_on_temp = SHARPSL_CHARGE_ON_TEMP, + .fatal_acin_volt = SHARPSL_FATAL_ACIN_VOLT, + .fatal_noacin_volt= SHARPSL_FATAL_NOACIN_VOLT, + .bat_levels = 6, + .bat_levels_noac = poodle_battery_levels_fl, + .bat_levels_acin = poodle_battery_levels_nofl, + .status_high_acin = 1490, + .status_low_acin = 1466, + .status_high_noac = 1482, + .status_low_noac = 1458, +}; + +static struct platform_device *poodlepm_device; + +static int __devinit poodlepm_init(void) +{ + int ret; + + poodlepm_device = platform_device_alloc("sharpsl-pm", -1); + if (!poodlepm_device) + return -ENOMEM; + + poodlepm_device->dev.platform_data = &poodle_pm_machinfo; + ret = platform_device_add(poodlepm_device); + + if (ret) + platform_device_put(poodlepm_device); + + return ret; +} + +static void poodlepm_exit(void) +{ + platform_device_unregister(poodlepm_device); +} + +module_init(poodlepm_init); +module_exit(poodlepm_exit); Index: linux-2.6.26/arch/arm/common/locomo.c =================================================================== --- linux-2.6.26.orig/arch/arm/common/locomo.c 2008-07-13 14:51:29.000000000 -0700 +++ linux-2.6.26/arch/arm/common/locomo.c 2008-08-05 22:16:20.000000000 -0700 @@ -600,6 +600,7 @@ spin_lock_irqsave(&lchip->lock, flags); save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ + // FIXME - should save JK_B locomo_writel(0x00, lchip->base + LOCOMO_GPO); save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPI + LOCOMO_SPICT); /* SPI */ locomo_writel(0x40, lchip->base + LOCOMO_SPICT); @@ -1101,11 +1102,16 @@ static struct locomo *locomo_chip_driver(struct locomo_dev *ldev); +struct locomo_dev *frontlight_dev; +EXPORT_SYMBOL(frontlight_dev); + void locomo_frontlight_set(struct locomo_dev *dev, int duty, int vr, int bpwf) { unsigned long flags; struct locomo *lchip = locomo_chip_driver(dev); + frontlight_dev = dev; + if (vr) locomo_gpio_write(dev->dev.parent, LOCOMO_GPIO_FL_VR, 1); else Index: linux-2.6.26/include/asm-arm/hardware/locomo.h =================================================================== --- linux-2.6.26.orig/include/asm-arm/hardware/locomo.h 2008-07-13 14:51:29.000000000 -0700 +++ linux-2.6.26/include/asm-arm/hardware/locomo.h 2008-08-05 22:15:11.000000000 -0700 @@ -100,6 +100,12 @@ #define LOCOMO_GPIO_CARD_DETECT LOCOMO_GPIO(13) #define LOCOMO_GPIO_WRITE_PROT LOCOMO_GPIO(14) #define LOCOMO_GPIO_CARD_POWER LOCOMO_GPIO(15) +#define POODLE_LOCOMO_GPIO_AMP_ON LOCOMO_GPIO(8) +#define POODLE_LOCOMO_GPIO_MUTE_L LOCOMO_GPIO(10) +#define POODLE_LOCOMO_GPIO_MUTE_R LOCOMO_GPIO(11) +#define POODLE_LOCOMO_GPIO_232VCC_ON LOCOMO_GPIO(12) +#define POODLE_LOCOMO_GPIO_JK_B LOCOMO_GPIO(13) + /* Start the definitions of the devices. Each device has an initial * base address and a series of offsets from that base address. */