diff options
author | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-01-26 06:34:55 +0000 |
---|---|---|
committer | Uwe Stuehler <uwe@cvs.openbsd.org> | 2005-01-26 06:34:55 +0000 |
commit | 8d5992f42a303bf7855b57d7aa3a24fba59ffeee (patch) | |
tree | cf9833405207add16097ea76404d2dc202411a68 /sys/arch | |
parent | bdcf45340fd9d4ef44a2ace40aae2f9d2a636631 (diff) |
New device for the dedicated SSP unit, automatic battery charging, and
reporting the remaining battery life to apmd(8).
ok drahn@
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.c | 57 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0_apm.h | 16 | ||||
-rw-r--r-- | sys/arch/arm/xscale/pxa2x0reg.h | 29 | ||||
-rw-r--r-- | sys/arch/zaurus/conf/GENERIC | 5 | ||||
-rw-r--r-- | sys/arch/zaurus/conf/RAMDISK | 5 | ||||
-rw-r--r-- | sys/arch/zaurus/conf/files.zaurus | 9 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_apm.c | 357 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoop.c | 36 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoopreg.h | 12 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_scoopvar.h | 5 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_ssp.c | 145 | ||||
-rw-r--r-- | sys/arch/zaurus/dev/zaurus_sspvar.h | 19 |
12 files changed, 621 insertions, 74 deletions
diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index 4af0b9ee836..242cdf2ca0e 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.c +++ b/sys/arch/arm/xscale/pxa2x0_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.c,v 1.2 2005/01/20 23:34:36 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.3 2005/01/26 06:34:53 uwe Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -77,8 +77,8 @@ int apm_userstandbys; int apm_suspends; int apm_battlow; -void apm_battery_info(struct pxa2x0_apm_softc *, - struct pxaapm_battery_info *); +void apm_power_info(struct pxa2x0_apm_softc *, + struct apm_power_info *); void apm_standby(struct pxa2x0_apm_softc *); void apm_suspend(struct pxa2x0_apm_softc *); void apm_resume(struct pxa2x0_apm_softc *); @@ -115,13 +115,17 @@ struct filterops apmread_filtops = #define SCFLAG_OPEN (SCFLAG_OREAD|SCFLAG_OWRITE) void -apm_battery_info(struct pxa2x0_apm_softc *sc, - struct pxaapm_battery_info *battp) +apm_power_info(struct pxa2x0_apm_softc *sc, + struct apm_power_info *power) { - bzero(battp, sizeof(struct pxaapm_battery_info)); - if (sc->sc_battery_info != NULL) - sc->sc_battery_info(battp); + power->ac_state = APM_AC_UNKNOWN; + power->battery_state = APM_BATT_UNKNOWN;; + power->battery_life = 0 /* APM_BATT_LIFE_UNKNOWN */; + power->minutes_left = 0; + + if (sc->sc_power_info != NULL) + sc->sc_power_info(sc, power); } void @@ -272,7 +276,6 @@ int apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { struct pxa2x0_apm_softc *sc; - struct pxaapm_battery_info batt; struct apm_power_info *power; int error = 0; @@ -325,41 +328,7 @@ apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) break; case APM_IOC_GETPOWER: power = (struct apm_power_info *)data; - - apm_battery_info(sc, &batt); - - power->ac_state = ((batt.flags & PXAAPM_AC_PRESENT) ? - APM_AC_ON : APM_AC_OFF); - power->battery_life = - ((batt.cur_charge * 100) / batt.max_charge); - - /* - * If the battery is charging, return the minutes left until - * charging is complete. apmd knows this. - */ - - if (!(batt.flags & PXAAPM_BATT_PRESENT)) { - power->battery_state = APM_BATT_UNKNOWN; - power->minutes_left = 0; - power->battery_life = 0; - } else if ((power->ac_state == APM_AC_ON) && - (batt.draw > 0)) { - power->minutes_left = - (((batt.max_charge - batt.cur_charge) * 3600) / - batt.draw) / 60; - power->battery_state = APM_BATT_CHARGING; - } else { - power->minutes_left = - ((batt.cur_charge * 3600) / (-batt.draw)) / 60; - - /* XXX - Arbitrary */ - if (power->battery_life > 60) - power->battery_state = APM_BATT_HIGH; - else if (power->battery_life < 10) - power->battery_state = APM_BATT_CRITICAL; - else - power->battery_state = APM_BATT_LOW; - } + apm_power_info(sc, power); break; default: diff --git a/sys/arch/arm/xscale/pxa2x0_apm.h b/sys/arch/arm/xscale/pxa2x0_apm.h index 719f0e0ddfa..9891822b118 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.h +++ b/sys/arch/arm/xscale/pxa2x0_apm.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.h,v 1.2 2005/01/20 23:34:36 uwe Exp $ */ +/* $OpenBSD: pxa2x0_apm.h,v 1.3 2005/01/26 06:34:53 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -22,16 +22,7 @@ #include <sys/event.h> #include <machine/bus.h> - -#define PXAAPM_AC_PRESENT (1<<0) -#define PXAAPM_BATT_PRESENT (1<<1) - -struct pxaapm_battery_info { - int flags; - u_int cur_charge; - u_int max_charge; - int draw; -}; +#include <machine/apmvar.h> struct pxa2x0_apm_softc { struct device sc_dev; @@ -41,8 +32,9 @@ struct pxa2x0_apm_softc { int sc_flags; bus_space_tag_t sc_iot; bus_space_handle_t sc_pm_ioh; - void (*sc_battery_info)(struct pxaapm_battery_info *); void (*sc_periodic_check)(struct pxa2x0_apm_softc *); + void (*sc_power_info)(struct pxa2x0_apm_softc *, + struct apm_power_info *); }; extern void pxa2x0_apm_attach_sub(struct pxa2x0_apm_softc *); diff --git a/sys/arch/arm/xscale/pxa2x0reg.h b/sys/arch/arm/xscale/pxa2x0reg.h index c77eff0ecde..7db654ec524 100644 --- a/sys/arch/arm/xscale/pxa2x0reg.h +++ b/sys/arch/arm/xscale/pxa2x0reg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0reg.h,v 1.8 2005/01/12 17:14:37 uwe Exp $ */ +/* $OpenBSD: pxa2x0reg.h,v 1.9 2005/01/26 06:34:53 uwe Exp $ */ /* $NetBSD: pxa2x0reg.h,v 1.4 2003/06/11 20:43:01 scw Exp $ */ /* @@ -108,7 +108,10 @@ #define PXA2X0_GPIO_SIZE 0x70 #define PXA2X0_POWMAN_BASE 0x40f00000 /* Power management */ #define PXA2X0_POWMAN_SIZE 0x100 -#define PXA2X0_SSP_BASE 0x41000000 +#define PXA2X0_SSP_BASE 0x41000000 /* SSP serial port */ +#define PXA2X0_SSP1_BASE 0x41700000 /* PXA270 */ +#define PXA2X0_SSP2_BASE 0x41900000 /* PXA270 */ +#define PXA2X0_SSP_SIZE 0x40 #define PXA2X0_MMC_BASE 0x41100000 /* MultiMediaCard */ #define PXA2X0_MMC_SIZE 0x48 #define PXA2X0_CLKMAN_BASE 0x41300000 /* Clock Manager */ @@ -218,14 +221,20 @@ struct pxa2x0_dma_desc { #define I2C_ISAR 0x16a0 /* Slave address */ /* Power Manager */ -#define POWMAN_RCSR 0x30 /* Reset Controller Status Register */ -#define RCSR_GPR (1<<3) -#define RCSR_SMR (1<<2) -#define RCSR_WDR (1<<1) +#define POWMAN_PSSR 0x04 /* Sleep Status register */ +#define PSSR_RDH (1<<5) +#define POWMAN_PCFR 0x1c /* General Configuration register */ +#define PCFR_GRP_EN (1<<4) /* PXA270 */ +#define PCFR_GP_ROD (1<<8) /* PXA270 */ +#define POWMAN_RCSR 0x30 /* Reset Controller Status register */ #define RCSR_HWR (1<<0) +#define RCSR_WDR (1<<1) +#define RCSR_SMR (1<<2) +#define RCSR_GPR (1<<3) /* Clock Manager */ #define CLKMAN_CCCR 0x00 /* Core Clock Configuration */ +#define CCCR_CPDIS (1<<31) /* PXA270 */ #define CCCR_TURBO_X1 (2<<7) #define CCCR_TURBO_X15 (3<<7) /* x 1.5 */ #define CCCR_TURBO_X2 (4<<7) @@ -715,4 +724,12 @@ struct pxa2x0_dma_desc { #define OST_OIER 0x001c /* Interrupt Enable */ #define OIER_E3 (1<<3) +/* Synchronous Serial Protocol (SSP) serial ports */ +#define SSP_SSCR0 0x00 +#define SSP_SSCR1 0x04 +#define SSP_SSSR 0x08 +#define SSSR_TNF (1<<2) +#define SSSR_RNE (1<<3) +#define SSP_SSDR 0x10 + #endif /* _ARM_XSCALE_PXA2X0REG_H_ */ diff --git a/sys/arch/zaurus/conf/GENERIC b/sys/arch/zaurus/conf/GENERIC index 092ded82753..08ac78e8395 100644 --- a/sys/arch/zaurus/conf/GENERIC +++ b/sys/arch/zaurus/conf/GENERIC @@ -1,4 +1,4 @@ -# $OpenBSD: GENERIC,v 1.23 2005/01/25 21:16:57 drahn Exp $ +# $OpenBSD: GENERIC,v 1.24 2005/01/26 06:34:53 uwe Exp $ # # GENERIC machine description file # @@ -182,6 +182,9 @@ ukphy* at mii? # "unknown" PHYs lcd0 at pxaip? wsdisplay* at lcd? console ? +# Dedicated SSP unit for ADC, touch screen, and backlight +zssp0 at pxaip? + # APM emulation apm0 at pxaip? diff --git a/sys/arch/zaurus/conf/RAMDISK b/sys/arch/zaurus/conf/RAMDISK index 00335981668..9ddf56b7633 100644 --- a/sys/arch/zaurus/conf/RAMDISK +++ b/sys/arch/zaurus/conf/RAMDISK @@ -1,4 +1,4 @@ -# $OpenBSD: RAMDISK,v 1.17 2005/01/20 23:34:36 uwe Exp $ +# $OpenBSD: RAMDISK,v 1.18 2005/01/26 06:34:53 uwe Exp $ # # GENERIC machine description file # @@ -162,6 +162,9 @@ ukphy* at mii? # "unknown" PHYs lcd0 at pxaip? wsdisplay* at lcd? console ? +# Dedicated SSP unit for ADC, touch screen, and backlight +zssp0 at pxaip? + # APM emulation apm0 at pxaip? diff --git a/sys/arch/zaurus/conf/files.zaurus b/sys/arch/zaurus/conf/files.zaurus index defaaf6e15b..ea706f82b13 100644 --- a/sys/arch/zaurus/conf/files.zaurus +++ b/sys/arch/zaurus/conf/files.zaurus @@ -1,4 +1,4 @@ -# $OpenBSD: files.zaurus,v 1.13 2005/01/20 23:34:36 uwe Exp $ +# $OpenBSD: files.zaurus,v 1.14 2005/01/26 06:34:53 uwe Exp $ # # First try for arm-specific configuration info # @@ -38,9 +38,14 @@ device scoop attach scoop at pxaip with scoop_pxaip file arch/zaurus/dev/zaurus_scoop.c scoop +# Dedicated SSP unit for ADC, touch screen, and backlight +device zssp +attach zssp at pxaip +file arch/zaurus/dev/zaurus_ssp.c zssp + # Power manager and APM emulation attach apm at pxaip with apm_pxaip -file arch/zaurus/zaurus/zaurus_apm.c apm_pxaip +file arch/zaurus/dev/zaurus_apm.c apm_pxaip # # Machine-independent ATA drivers diff --git a/sys/arch/zaurus/dev/zaurus_apm.c b/sys/arch/zaurus/dev/zaurus_apm.c new file mode 100644 index 00000000000..2fc758ea385 --- /dev/null +++ b/sys/arch/zaurus/dev/zaurus_apm.c @@ -0,0 +1,357 @@ +/* $OpenBSD: zaurus_apm.c,v 1.1 2005/01/26 06:34:54 uwe Exp $ */ + +/* + * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/conf.h> + +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0_apm.h> +#include <arm/xscale/pxa2x0_gpio.h> + +#include <zaurus/dev/zaurus_scoopvar.h> +#include <zaurus/dev/zaurus_sspvar.h> + +int apm_match(struct device *, void *, void *); +void apm_attach(struct device *, struct device *, void *); + +struct cfattach apm_pxaip_ca = { + sizeof (struct pxa2x0_apm_softc), apm_match, apm_attach +}; + +/* MAX1111 command word */ +#define MAXCTRL_PD0 (1<<0) +#define MAXCTRL_PD1 (1<<1) +#define MAXCTRL_SGL (1<<2) +#define MAXCTRL_UNI (1<<3) +#define MAXCTRL_SEL_SHIFT 4 +#define MAXCTRL_STR (1<<7) + +/* MAX1111 ADC channels */ +#define BATT_THM 2 +#define BATT_AD 4 +#define JK_VAD 6 + +/* Battery-related GPIO pins */ +#define GPIO_AC_IN_C3000 115 /* active low */ +#define GPIO_CHRG_FULL_C3000 101 +#define GPIO_BATT_COVER_C3000 90 /* active low */ + +/* Internal software power states */ +#define PS_UNKNOWN 0 +#define PS_BATT_ABSENT 1 +#define PS_NOT_CHARGING 2 +#define PS_CHARGING 3 +#define PS_BATT_FULL 4 + +#ifdef APMDEBUG +const char *zaurus_power_state_names[5] = { + "unknown", "absent", "not charging", "charging", "full" +}; +#endif + +int zaurus_power_state = PS_UNKNOWN; + +struct battery_voltage_threshold { + int voltage; + int life; + int state; +}; + +struct battery_voltage_threshold zaurus_battery_c3000[] = { + {194, 100, APM_BATT_HIGH}, + {188, 75, APM_BATT_HIGH}, + {184, 50, APM_BATT_HIGH}, + {180, 25, APM_BATT_LOW}, + {176, 5, APM_BATT_LOW}, + {0, 0, APM_BATT_CRITICAL}, +}; + +struct battery_voltage_threshold *zaurus_main_battery = + zaurus_battery_c3000; + +int max1111_adc_value(int); +int max1111_adc_value_avg(int, int); +#if 0 +int zaurus_jkvad_voltage(void); +int zaurus_battery_temp(void); +#endif +int zaurus_battery_voltage(void); +int zaurus_battery_life(void); +int zaurus_battery_state(void); +int zaurus_ac_present(void); +int zaurus_charge_complete(void); +void zaurus_charge_control(int); +void zaurus_power_check(struct pxa2x0_apm_softc *); +void zaurus_power_info(struct pxa2x0_apm_softc *, + struct apm_power_info *); + +int +apm_match(struct device *parent, void *match, void *aux) +{ + return 1; +} + +void +apm_attach(struct device *parent, struct device *self, void *aux) +{ + struct pxa2x0_apm_softc *sc = (struct pxa2x0_apm_softc *)self; + + pxa2x0_gpio_set_function(GPIO_AC_IN_C3000, GPIO_IN); + pxa2x0_gpio_set_function(GPIO_CHRG_FULL_C3000, GPIO_IN); + pxa2x0_gpio_set_function(GPIO_BATT_COVER_C3000, GPIO_IN); + +#if 0 + (void)pxa2x0_gpio_intr_establish(GPIO_AC_IN_C3000, IST_EDGE_BOTH, + IPL_BIO, apm_intr, sc, "apm_ac"); +#endif + + sc->sc_periodic_check = zaurus_power_check; + sc->sc_power_info = zaurus_power_info; + + /* Initialize the battery status before APM is enabled. */ + zaurus_power_check(sc); + + pxa2x0_apm_attach_sub(sc); +} + +int +max1111_adc_value(int chan) +{ + + return zssp_read_max1111(MAXCTRL_PD0 | MAXCTRL_PD1 | + MAXCTRL_SGL | MAXCTRL_UNI | (chan << MAXCTRL_SEL_SHIFT) | + MAXCTRL_STR); +} + +/* XXX simplify */ +int +max1111_adc_value_avg(int chan, int pause) +{ + int val[5]; + int i, j, k, x; + int sum = 0; + + for (i = 0; i < 5; i++) { + val[i] = max1111_adc_value(chan); + if (i != 4) + delay(pause * 1000); + } + + x = val[0]; + j = 0; + for (i = 1; i < 5; i++) { + if (x < val[i]) { + x = val[i]; + j = i; + } + } + + x = val[4]; + k = 4; + for (i = 3; i >= 0; i--) { + if (x > val[i]) { + x = val[i]; + k = i; + } + } + + for (i = 0; i < 5; i++) { + if (i == j || i == k) + continue; + sum += val[i]; + } + + return (sum / 3); +} + +#if 0 +/* + * Return the voltage available for charging. This will be zero, + * unless A/C power is connected. + */ +int +zaurus_jkvad_voltage(void) +{ + + return max1111_adc_value_avg(JK_VAD, 10); +} + +int +zaurus_battery_temp(void) +{ + int temp; + + scoop_battery_temp_adc(1); + delay(10000); + temp = max1111_adc_value_avg(BATT_THM, 1); + scoop_battery_temp_adc(0); + + return temp; +} +#endif + +int +zaurus_battery_voltage(void) +{ + + return max1111_adc_value_avg(BATT_AD, 10); +} + +int +zaurus_battery_life(void) +{ + int i; + int voltage; + + voltage = zaurus_battery_voltage(); + + for (i = 0; zaurus_main_battery[i].voltage > 0; i++) { + if (voltage >= zaurus_main_battery[i].voltage) + break; + } + + return zaurus_main_battery[i].life; +} + +int +zaurus_battery_state(void) +{ + int i; + int voltage; + + voltage = zaurus_battery_voltage(); + + for (i = 0; zaurus_main_battery[i].voltage > 0; i++) { + if (voltage >= zaurus_main_battery[i].voltage) + break; + } + + return zaurus_main_battery[i].state; +} + +int +zaurus_ac_present(void) +{ + + return !pxa2x0_gpio_get_bit(GPIO_AC_IN_C3000); +} + +/* + * Return non-zero if the charge complete signal is set. This signal + * is valid only after charging is restarted. + */ +int +zaurus_charge_complete(void) +{ + + return pxa2x0_gpio_get_bit(GPIO_CHRG_FULL_C3000); +} + +void +zaurus_charge_control(int state) +{ + + switch (state) { + case PS_CHARGING: + scoop_charge_battery(1, 0); + scoop_led_set(SCOOP_LED_ORANGE, 1); + break; + case PS_NOT_CHARGING: + case PS_BATT_FULL: + scoop_charge_battery(0, 0); + scoop_led_set(SCOOP_LED_ORANGE, 0); + /* Always force a 15 ms delay before charging again. */ + delay(15000); + break; + default: + printf("zaurus_charge_control: bad state %d\n", state); + break; + } + + zaurus_power_state = state; +} + +/* + * Check A/C power and control battery charging. This gets called once + * from apm_attach(), and once per second from the APM kernel thread. + */ +void +zaurus_power_check(struct pxa2x0_apm_softc *sc) +{ + int state = zaurus_power_state; + + switch (state) { + case PS_UNKNOWN: + case PS_BATT_ABSENT: + state = PS_NOT_CHARGING; + zaurus_charge_control(state); + /* FALLTHROUGH */ + + case PS_NOT_CHARGING: + if (zaurus_ac_present()) + state = PS_CHARGING; + break; + + case PS_CHARGING: + if (!zaurus_ac_present()) + state = PS_NOT_CHARGING; + else if (zaurus_charge_complete()) + state = PS_BATT_FULL; + break; + + case PS_BATT_FULL: + if (!zaurus_ac_present()) + state = PS_NOT_CHARGING; + break; + + default: + printf("zaurus_power_check: bad state %d\n", state); + break; + } + + if (state != zaurus_power_state) { +#ifdef APMDEBUG + printf("zaurus_power_check: battery state %s -> %s volt %d\n", + zaurus_power_state_names[zaurus_power_state], + zaurus_power_state_names[state], + zaurus_battery_voltage()); +#endif + zaurus_charge_control(state); + } +} + +/* + * Report A/C and battery state in response to a request from apmd. + */ +void +zaurus_power_info(struct pxa2x0_apm_softc *sc, + struct apm_power_info *power) +{ + + if (zaurus_power_state == PS_CHARGING) { + power->ac_state = APM_AC_ON; + power->battery_state = APM_BATT_CHARGING; + power->battery_life = 100; + } else { + power->ac_state = zaurus_ac_present() ? APM_AC_ON : + APM_AC_OFF; + power->battery_state = zaurus_battery_state(); + power->battery_life = zaurus_battery_life(); + } +} diff --git a/sys/arch/zaurus/dev/zaurus_scoop.c b/sys/arch/zaurus/dev/zaurus_scoop.c index 9f851de62dc..184043cafd4 100644 --- a/sys/arch/zaurus/dev/zaurus_scoop.c +++ b/sys/arch/zaurus/dev/zaurus_scoop.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoop.c,v 1.3 2005/01/20 23:34:37 uwe Exp $ */ +/* $OpenBSD: zaurus_scoop.c,v 1.4 2005/01/26 06:34:54 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -130,12 +130,42 @@ scoop_led_set(int led, int on) switch(led) { case SCOOP_LED_GREEN: scoop_gpio_pin_write(scoop_cd.cd_devs[0], - C3000_SCOOP0_LED_GREEN, on); + SCOOP0_LED_GREEN_C3000, on); break; case SCOOP_LED_ORANGE: scoop_gpio_pin_write(scoop_cd.cd_devs[0], - C3000_SCOOP0_LED_ORANGE, on); + SCOOP0_LED_ORANGE_C3000, on); break; } } } + +void +scoop_battery_temp_adc(int enable) +{ + + if (scoop_cd.cd_ndevs > 0 && scoop_cd.cd_devs[0] != NULL) + scoop_gpio_pin_write(scoop_cd.cd_devs[0], + SCOOP0_ADC_TEMP_ON_C3000, enable); +} + +void +scoop_charge_battery(int enable, int voltage_high) +{ + + if (scoop_cd.cd_ndevs > 0 && scoop_cd.cd_devs[0] != NULL) { + scoop_gpio_pin_write(scoop_cd.cd_devs[0], + SCOOP0_JK_B_C3000, voltage_high); + scoop_gpio_pin_write(scoop_cd.cd_devs[0], + SCOOP0_CHARGE_OFF_C3000, !enable); + } +} + +void +scoop_discharge_battery(int enable) +{ + + if (scoop_cd.cd_ndevs > 0 && scoop_cd.cd_devs[0] != NULL) + scoop_gpio_pin_write(scoop_cd.cd_devs[0], + SCOOP0_JK_A_C3000, enable); +} diff --git a/sys/arch/zaurus/dev/zaurus_scoopreg.h b/sys/arch/zaurus/dev/zaurus_scoopreg.h index 67abaf93e67..9b7f0c56c5e 100644 --- a/sys/arch/zaurus/dev/zaurus_scoopreg.h +++ b/sys/arch/zaurus/dev/zaurus_scoopreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoopreg.h,v 1.3 2005/01/20 23:34:36 uwe Exp $ */ +/* $OpenBSD: zaurus_scoopreg.h,v 1.4 2005/01/26 06:34:54 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -34,6 +34,10 @@ #define SCOOP_GPRR 0x28 /* GPIO bit assignments for the Zaurus C3000. */ -#define C3000_SCOOP0_LED_GREEN 1 -#define C3000_SCOOP0_LED_ORANGE 7 -#define C3000_SCOOP1_BACKLIGHT_ON 8 +#define SCOOP0_LED_GREEN_C3000 1 +#define SCOOP0_JK_B_C3000 2 +#define SCOOP0_CHARGE_OFF_C3000 3 +#define SCOOP0_LED_ORANGE_C3000 7 +#define SCOOP0_JK_A_C3000 8 +#define SCOOP0_ADC_TEMP_ON_C3000 9 +#define SCOOP1_BACKLIGHT_ON_C3000 8 diff --git a/sys/arch/zaurus/dev/zaurus_scoopvar.h b/sys/arch/zaurus/dev/zaurus_scoopvar.h index 497680e49f4..f48b0d5d58b 100644 --- a/sys/arch/zaurus/dev/zaurus_scoopvar.h +++ b/sys/arch/zaurus/dev/zaurus_scoopvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_scoopvar.h,v 1.3 2005/01/20 23:34:37 uwe Exp $ */ +/* $OpenBSD: zaurus_scoopvar.h,v 1.4 2005/01/26 06:34:54 uwe Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -21,3 +21,6 @@ void scoop_backlight_set(int); void scoop_led_set(int, int); +void scoop_battery_temp_adc(int); +void scoop_charge_battery(int, int); +void scoop_discharge_battery(int); diff --git a/sys/arch/zaurus/dev/zaurus_ssp.c b/sys/arch/zaurus/dev/zaurus_ssp.c new file mode 100644 index 00000000000..4c29aab21de --- /dev/null +++ b/sys/arch/zaurus/dev/zaurus_ssp.c @@ -0,0 +1,145 @@ +/* $OpenBSD: zaurus_ssp.c,v 1.1 2005/01/26 06:34:54 uwe Exp $ */ + +/* + * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> + +#include <machine/bus.h> + +#include <arm/xscale/pxa2x0reg.h> +#include <arm/xscale/pxa2x0var.h> +#include <arm/xscale/pxa2x0_gpio.h> + +#include <zaurus/dev/zaurus_sspvar.h> + +#define GPIO_TG_CS_C3000 53 +#define GPIO_MAX1111_CS_C3000 20 +#define GPIO_ADS7846_CS_C3000 14 /* SSP SFRM */ + +#define SSCR0_LZ9JG18 0x01ab +#define SSCR0_MAX1111 0x0387 + +struct zssp_softc { + struct device sc_dev; + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; +}; + +int zssp_match(struct device *, void *, void *); +void zssp_attach(struct device *, struct device *, void *); + +struct cfattach zssp_ca = { + sizeof (struct zssp_softc), zssp_match, zssp_attach +}; + +struct cfdriver zssp_cd = { + NULL, "zssp", DV_DULL +}; + +int +zssp_match(struct device *parent, void *match, void *aux) +{ + return 1; +} + +void +zssp_attach(struct device *parent, struct device *self, void *aux) +{ + struct zssp_softc *sc = (struct zssp_softc *)self; + + sc->sc_iot = &pxa2x0_bs_tag; + if (bus_space_map(sc->sc_iot, PXA2X0_SSP1_BASE, PXA2X0_SSP_SIZE, + 0, &sc->sc_ioh)) + panic("can't map %s", sc->sc_dev.dv_xname); + + pxa2x0_clkman_config(CKEN_SSP, 1); + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_LZ9JG18); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR1, 0); + + pxa2x0_gpio_set_function(GPIO_TG_CS_C3000, GPIO_OUT|GPIO_SET); + pxa2x0_gpio_set_function(GPIO_MAX1111_CS_C3000, GPIO_OUT|GPIO_SET); + pxa2x0_gpio_set_function(GPIO_ADS7846_CS_C3000, GPIO_OUT|GPIO_SET); + + printf("\n"); +} + +int +zssp_read_max1111(u_int32_t cmd) +{ + struct zssp_softc *sc; + int voltage[2]; + int i; + + if (zssp_cd.cd_ndevs < 1 || zssp_cd.cd_devs[0] == NULL) { + printf("zssp_read_max1111: not configured\n"); + return 0; + } + sc = (struct zssp_softc *)zssp_cd.cd_devs[0]; + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0); + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, SSCR0_MAX1111); + + pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000); + pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000); + pxa2x0_gpio_clear_bit(GPIO_MAX1111_CS_C3000); + + delay(1); + + /* Send the command word and read a dummy word back. */ + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, cmd); + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_TNF) != SSSR_TNF) + /* poll */; + /* XXX is this delay necessary? */ + delay(1); + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_RNE) != SSSR_RNE) + /* poll */; + i = bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR); + + for (i = 0; i < 2; i++) { + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSDR, 0); + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_TNF) != SSSR_TNF) + /* poll */; + /* XXX again, is this delay necessary? */ + delay(1); + while ((bus_space_read_4(sc->sc_iot, sc->sc_ioh, SSP_SSSR) + & SSSR_RNE) != SSSR_RNE) + /* poll */; + voltage[i] = bus_space_read_4(sc->sc_iot, sc->sc_ioh, + SSP_SSDR); + } + + pxa2x0_gpio_set_bit(GPIO_TG_CS_C3000); + pxa2x0_gpio_set_bit(GPIO_ADS7846_CS_C3000); + pxa2x0_gpio_set_bit(GPIO_MAX1111_CS_C3000); + + bus_space_write_4(sc->sc_iot, sc->sc_ioh, SSP_SSCR0, 0); + + /* XXX no idea what this means, but it's what Linux would do. */ + if ((voltage[0] & 0xc0) != 0 || (voltage[1] & 0x3f) != 0) + voltage[0] = -1; + else + voltage[0] = ((voltage[0] << 2) & 0xfc) | + ((voltage[1] >> 6) & 0x03); + + return voltage[0]; +} diff --git a/sys/arch/zaurus/dev/zaurus_sspvar.h b/sys/arch/zaurus/dev/zaurus_sspvar.h new file mode 100644 index 00000000000..18b7f1399c2 --- /dev/null +++ b/sys/arch/zaurus/dev/zaurus_sspvar.h @@ -0,0 +1,19 @@ +/* $OpenBSD: zaurus_sspvar.h,v 1.1 2005/01/26 06:34:54 uwe Exp $ */ + +/* + * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +int zssp_read_max1111(u_int32_t); |