/*
 * Apple Motion Sensor driver
 *
 * Copyright (C) 2005 Stelian Pop (stelian@popies.net)
 * Copyright (C) 2006 Michael Hanselmann (linux-kernel@hansmi.ch)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <linux/module.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/of_platform.h>
#include <asm/pmac_pfunc.h>

#include "ams.h"

/* There is only one motion sensor per machine */
struct ams ams_info;

static unsigned int verbose;
module_param(verbose, bool, 0644);
MODULE_PARM_DESC(verbose, "Show free falls and shocks in kernel output");

/* Call with ams_info.lock held! */
void ams_sensors(s8 *x, s8 *y, s8 *z)
{
	u32 orient = ams_info.vflag? ams_info.orient1 : ams_info.orient2;

	if (orient & 0x80)
		/* X and Y swapped */
		ams_info.get_xyz(y, x, z);
	else
		ams_info.get_xyz(x, y, z);

	if (orient & 0x04)
		*z = ~(*z);
	if (orient & 0x02)
		*y = ~(*y);
	if (orient & 0x01)
		*x = ~(*x);
}

static ssize_t ams_show_current(struct device *dev,
	struct device_attribute *attr, char *buf)
{
	s8 x, y, z;

	mutex_lock(&ams_info.lock);
	ams_sensors(&x, &y, &z);
	mutex_unlock(&ams_info.lock);

	return snprintf(buf, PAGE_SIZE, "%d %d %d\n", x, y, z);
}

static DEVICE_ATTR(current, S_IRUGO, ams_show_current, NULL);

static void ams_handle_irq(void *data)
{
	enum ams_irq irq = *((enum ams_irq *)data);

	spin_lock(&ams_info.irq_lock);

	ams_info.worker_irqs |= irq;
	schedule_work(&ams_info.worker);

	spin_unlock(&ams_info.irq_lock);
}

static enum ams_irq ams_freefall_irq_data = AMS_IRQ_FREEFALL;
static struct pmf_irq_client ams_freefall_client = {
	.owner = THIS_MODULE,
	.handler = ams_handle_irq,
	.data = &ams_freefall_irq_data,
};

static enum ams_irq ams_shock_irq_data = AMS_IRQ_SHOCK;
static struct pmf_irq_client ams_shock_client = {
	.owner = THIS_MODULE,
	.handler = ams_handle_irq,
	.data = &ams_shock_irq_data,
};

/* Once hard disk parking is implemented in the kernel, this function can
 * trigger it.
 */
static void ams_worker(struct work_struct *work)
{
	mutex_lock(&ams_info.lock);

	if (ams_info.has_device) {
		unsigned long flags;

		spin_lock_irqsave(&ams_info.irq_lock, flags);

		if (ams_info.worker_irqs & AMS_IRQ_FREEFALL) {
			if (verbose)
				printk(KERN_INFO "ams: freefall detected!\n");

			ams_info.worker_irqs &= ~AMS_IRQ_FREEFALL;

			/* we must call this with interrupts enabled */
			spin_unlock_irqrestore(&ams_info.irq_lock, flags);
			ams_info.clear_irq(AMS_IRQ_FREEFALL);
			spin_lock_irqsave(&ams_info.irq_lock, flags);
		}

		if (ams_info.worker_irqs & AMS_IRQ_SHOCK) {
			if (verbose)
				printk(KERN_INFO "ams: shock detected!\n");

			ams_info.worker_irqs &= ~AMS_IRQ_SHOCK;

			/* we must call this with interrupts enabled */
			spin_unlock_irqrestore(&ams_info.irq_lock, flags);
			ams_info.clear_irq(AMS_IRQ_SHOCK);
			spin_lock_irqsave(&ams_info.irq_lock, flags);
		}

		spin_unlock_irqrestore(&ams_info.irq_lock, flags);
	}

	mutex_unlock(&ams_info.lock);
}

/* Call with ams_info.lock held! */
int ams_sensor_attach(void)
{
	int result;
	const u32 *prop;

	/* Get orientation */
	prop = of_get_property(ams_info.of_node, "orientation", NULL);
	if (!prop)
		return -ENODEV;
	ams_info.orient1 = *prop;
	ams_info.orient2 = *(prop + 1);

	/* Register freefall interrupt handler */
	result = pmf_register_irq_client(ams_info.of_node,
			"accel-int-1",
			&ams_freefall_client);
	if (result < 0)
		return -ENODEV;

	/* Reset saved irqs */
	ams_info.worker_irqs = 0;

	/* Register shock interrupt handler */
	result = pmf_register_irq_client(ams_info.of_node,
			"accel-int-2",
			&ams_shock_client);
	if (result < 0)
		goto release_freefall;

	/* Create device */
	ams_info.of_dev = of_platform_device_create(ams_info.of_node, "ams", NULL);
	if (!ams_info.of_dev) {
		result = -ENODEV;
		goto release_shock;
	}

	/* Create attributes */
	result = device_create_file(&ams_info.of_dev->dev, &dev_attr_current);
	if (result)
		goto release_of;

	ams_info.vflag = !!(ams_info.get_vendor() & 0x10);

	/* Init input device */
	result = ams_input_init();
	if (result)
		goto release_device_file;

	return result;
release_device_file:
	device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);
release_of:
	of_device_unregister(ams_info.of_dev);
release_shock:
	pmf_unregister_irq_client(&ams_shock_client);
release_freefall:
	pmf_unregister_irq_client(&ams_freefall_client);
	return result;
}

int __init ams_init(void)
{
	struct device_node *np;

	spin_lock_init(&ams_info.irq_lock);
	mutex_init(&ams_info.lock);
	INIT_WORK(&ams_info.worker, ams_worker);

#ifdef CONFIG_SENSORS_AMS_I2C
	np = of_find_node_by_name(NULL, "accelerometer");
	if (np && of_device_is_compatible(np, "AAPL,accelerometer_1"))
		/* Found I2C motion sensor */
		return ams_i2c_init(np);
#endif

#ifdef CONFIG_SENSORS_AMS_PMU
	np = of_find_node_by_name(NULL, "sms");
	if (np && of_device_is_compatible(np, "sms"))
		/* Found PMU motion sensor */
		return ams_pmu_init(np);
#endif
	return -ENODEV;
}

void ams_exit(void)
{
	mutex_lock(&ams_info.lock);

	if (ams_info.has_device) {
		/* Remove input device */
		ams_input_exit();

		/* Shut down implementation */
		ams_info.exit();

		/* Flush interrupt worker
		 *
		 * We do this after ams_info.exit(), because an interrupt might
		 * have arrived before disabling them.
		 */
		flush_scheduled_work();

		/* Remove attributes */
		device_remove_file(&ams_info.of_dev->dev, &dev_attr_current);

		/* Remove device */
		of_device_unregister(ams_info.of_dev);

		/* Remove handler */
		pmf_unregister_irq_client(&ams_shock_client);
		pmf_unregister_irq_client(&ams_freefall_client);
	}

	mutex_unlock(&ams_info.lock);
}

MODULE_AUTHOR("Stelian Pop, Michael Hanselmann");
MODULE_DESCRIPTION("Apple Motion Sensor driver");
MODULE_LICENSE("GPL");

module_init(ams_init);
module_exit(ams_exit);
