/*
 * 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.
 *
 * Actually, this should be quite safe, it seems sharp leaves charger enabled by default,
 * and my collie did not explode (yet).
 */

#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/arch/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)
{
	extern struct platform_device colliescoop_device;

	/* 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).
	 */
	if (on) {
		set_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
	} else {
		reset_scoop_gpio(&colliescoop_device.dev, COLLIE_SCP_CHARGE_ON);
	}
}

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);

	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);

	mdelay(1);
	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 ?, higher = 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 500;
	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_acin[] = {
	{ 420, 100},
	{ 417,  95},
	{ 415,  90},
	{ 413,  80},
	{ 411,  75},
	{ 408,  70},
	{ 406,  60},
	{ 403,  50},
	{ 398,  40},
	{ 391,  25},
	{  10,   5},
	{   0,   0},
};

struct battery_thresh collie_battery_levels[] = {
	{ 394, 100},
	{ 390,  95},
	{ 380,  90},
	{ 370,  80},
	{ 368,  75},	/* From sharp code: battery high with frontlight */
	{ 366,  70},	/* 60..90 -- fake values invented by me for testing */
	{ 364,  60},
	{ 362,  50},
	{ 360,  40},
	{ 358,  25},	/* From sharp code: battery low with frontlight */
	{ 356,   5},	/* From sharp code: battery verylow with frontlight */
	{   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       = 12,
	.bat_levels_noac  = collie_battery_levels,
	.bat_levels_acin  = collie_battery_levels_acin,
	.status_high_acin = 368,
	.status_low_acin  = 358,
	.status_high_noac = 368,
	.status_low_noac  = 358,
	.charge_on_volt	  = 350,	/* spitz uses 2.90V, but lets play it safe. */
	.charge_on_temp   = 550,
	.charge_acin_high = 550,	/* collie does not seem to have sensor for this, anyway */
	.charge_acin_low  = 450,	/* ignored, too */
	.fatal_acin_volt  = 356,
	.fatal_noacin_volt = 356,

	.batfull_irq = 1,		/* We do not want periodical charge restarts */
};

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);
