kernel-hacking-2024-linux-s.../arch/arm/mach-sa1100/collie_pm.c
Thomas Gleixner 52e405eaa9 [PATCH] ARM: fixup irqflags breakage after ARM genirq merge
The irgflags consolidation did conflict with the ARM to generic IRQ
conversion and was not applied for ARM. Fix it up.

Use the new IRQF_ constants and remove the SA_INTERRUPT define

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
2006-07-02 17:29:22 -07:00

278 lines
6.6 KiB
C

/*
* Based on spitz_pm.c and sharp code.
*
* Copyright (C) 2001 SHARP
* Copyright 2005 Pavel Machek <pavel@suse.cz>
*
* Distribute under GPLv2.
*
* Li-ion batteries are angry beasts, and they like to explode. This driver is not finished,
* and sometimes charges them when it should not. If it makes angry lithium to come your way...
* ...well, you have been warned.
*/
#include <linux/module.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <asm/irq.h>
#include <asm/mach-types.h>
#include <asm/hardware.h>
#include <asm/hardware/scoop.h>
#include <asm/dma.h>
#include <asm/arch/collie.h>
#include <asm/mach/sharpsl_param.h>
#include <asm/hardware/sharpsl_pm.h>
#include "../drivers/mfd/ucb1x00.h"
static struct ucb1x00 *ucb;
static int ad_revise;
#define ADCtoPower(x) ((330 * x * 2) / 1024)
static void collie_charger_init(void)
{
int err;
if (sharpsl_param.adadj != -1) {
ad_revise = sharpsl_param.adadj;
}
/* Register interrupt handler. */
if ((err = request_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr, IRQF_DISABLED,
"ACIN", sharpsl_ac_isr))) {
printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_AC_IN);
return;
}
if ((err = request_irq(COLLIE_IRQ_GPIO_CO, sharpsl_chrg_full_isr, IRQF_DISABLED,
"CO", sharpsl_chrg_full_isr))) {
free_irq(COLLIE_IRQ_GPIO_AC_IN, sharpsl_ac_isr);
printk("Could not get irq %d.\n", COLLIE_IRQ_GPIO_CO);
return;
}
ucb1x00_io_set_dir(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON | COLLIE_TC35143_GPIO_TMP_ON |
COLLIE_TC35143_GPIO_BBAT_ON);
return;
}
static void collie_measure_temp(int on)
{
if (on)
ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
else
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
}
static void collie_charge(int on)
{
if (on) {
printk("Should start charger\n");
} else {
printk("Should stop charger\n");
}
#ifdef I_AM_SURE
/* Zaurus seems to contain LTC1731 ; it should know when to
* stop charging itself, so setting charge on should be
* relatively harmless (as long as it is not done too often).
*/
#define CF_BUF_CTRL_BASE 0xF0800000
#define SCOOP_REG(adr) (*(volatile unsigned short*)(CF_BUF_CTRL_BASE+(adr)))
#define SCOOP_REG_GPWR SCOOP_REG(SCOOP_GPWR)
if (on) {
set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
} else {
reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
}
#endif
}
static void collie_discharge(int on)
{
}
static void collie_discharge1(int on)
{
}
static void collie_presuspend(void)
{
}
static void collie_postsuspend(void)
{
}
static int collie_should_wakeup(unsigned int resume_on_alarm)
{
return 0;
}
static unsigned long collie_charger_wakeup(void)
{
return 0;
}
int collie_read_backup_battery(void)
{
int voltage;
ucb1x00_adc_enable(ucb);
/* Gives 75..130 */
ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_BBAT_ON, 0);
voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
ucb1x00_adc_disable(ucb);
printk("Backup battery = %d(%d)\n", ADCtoPower(voltage), voltage);
return ADCtoPower(voltage);
}
int collie_read_main_battery(void)
{
int voltage, voltage_rev, voltage_volts;
ucb1x00_adc_enable(ucb);
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_BBAT_ON);
ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_MBAT_ON, 0);
/* gives values 160..255 with battery removed... and
145..255 with battery inserted. (on AC), goes as low as
80 on DC. */
voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD1, UCB_SYNC);
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_MBAT_ON);
ucb1x00_adc_disable(ucb);
voltage_rev = voltage + ((ad_revise * voltage) / 652);
voltage_volts = ADCtoPower(voltage_rev);
printk("Main battery = %d(%d)\n", voltage_volts, voltage);
if (voltage != -1)
return voltage_volts;
else
return voltage;
}
int collie_read_temp(void)
{
int voltage;
/* According to Sharp, temp must be > 973, main battery must be < 465,
FIXME: sharpsl_pm.c has both conditions negated? FIXME: values
are way out of range? */
ucb1x00_adc_enable(ucb);
ucb1x00_io_write(ucb, COLLIE_TC35143_GPIO_TMP_ON, 0);
/* >1010 = battery removed, 460 = 22C ?, higer = lower temp ? */
voltage = ucb1x00_adc_read(ucb, UCB_ADC_INP_AD0, UCB_SYNC);
ucb1x00_io_write(ucb, 0, COLLIE_TC35143_GPIO_TMP_ON);
ucb1x00_adc_disable(ucb);
printk("Battery temp = %d\n", voltage);
return voltage;
}
static unsigned long read_devdata(int which)
{
switch (which) {
case SHARPSL_BATT_VOLT:
return collie_read_main_battery();
case SHARPSL_BATT_TEMP:
return collie_read_temp();
case SHARPSL_ACIN_VOLT:
return 0x1;
case SHARPSL_STATUS_ACIN: {
int ret = GPLR & COLLIE_GPIO_AC_IN;
printk("AC status = %d\n", ret);
return ret;
}
case SHARPSL_STATUS_FATAL: {
int ret = GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
printk("Fatal bat = %d\n", ret);
return ret;
}
default:
return ~0;
}
}
struct battery_thresh collie_battery_levels[] = {
{ 368, 100},
{ 358, 25},
{ 356, 5},
{ 0, 0},
};
struct sharpsl_charger_machinfo collie_pm_machinfo = {
.init = collie_charger_init,
.read_devdata = read_devdata,
.discharge = collie_discharge,
.discharge1 = collie_discharge1,
.charge = collie_charge,
.measure_temp = collie_measure_temp,
.presuspend = collie_presuspend,
.postsuspend = collie_postsuspend,
.charger_wakeup = collie_charger_wakeup,
.should_wakeup = collie_should_wakeup,
.bat_levels = 3,
.bat_levels_noac = collie_battery_levels,
.bat_levels_acin = collie_battery_levels,
.status_high_acin = 368,
.status_low_acin = 358,
.status_high_noac = 368,
.status_low_noac = 358,
};
static int __init collie_pm_ucb_add(struct ucb1x00_dev *pdev)
{
sharpsl_pm.machinfo = &collie_pm_machinfo;
ucb = pdev->ucb;
return 0;
}
static struct ucb1x00_driver collie_pm_ucb_driver = {
.add = collie_pm_ucb_add,
};
static struct platform_device *collie_pm_device;
static int __init collie_pm_init(void)
{
int ret;
collie_pm_device = platform_device_alloc("sharpsl-pm", -1);
if (!collie_pm_device)
return -ENOMEM;
collie_pm_device->dev.platform_data = &collie_pm_machinfo;
ret = platform_device_add(collie_pm_device);
if (ret)
platform_device_put(collie_pm_device);
if (!ret)
ret = ucb1x00_register_driver(&collie_pm_ucb_driver);
return ret;
}
static void __exit collie_pm_exit(void)
{
ucb1x00_unregister_driver(&collie_pm_ucb_driver);
platform_device_unregister(collie_pm_device);
}
module_init(collie_pm_init);
module_exit(collie_pm_exit);