// Roku IO driver
//
// (C) 2007, 2008, 2009 Roku LLC
//
// Authors:
//   Mike Crowe <mcrowe@roku.com>
//
// This driver deals with inputs and outputs on the Monaco
// board. Both come in two varieties. The first variety are simply
// connected to single GPIOs and can be read/written at will. The
// second variety are connected to one of eight GPIOs that are shared
// via various latches between different uses. These are called
// "banked".
//
// The banked inputs are connected to the shared GPIOs when the
// required latch is driven low. This allows the value to be read. So
// the sequence is: set latch control low, read GPIOs, set latch
// control high.
//
// The banked outputs are latched from the shared GPIOs when the
// required latch goes low. So the sequence is: write GPIOs as
// required, set latch control low, set latch control high. It is the
// setting of the latch control high that causes the data to be
// latched.
//
// Because there is no way to retrieve the current state of the
// outputs it is necessary for the driver to store a mirror of the
// current state of each bank so that future changes to a single
// output can preserve the state of the other outputs in the same
// bank.
//
// The driver leaves the shared GPIO range tristated most of the time
// because many times a second the timer interrupt causes the inputs
// to be read so this is more efficient. When an output operation is
// required they are reconfigured temporarily.
//
// A limited number of GPIOs are bidirectional. To enable for the
// direction associated with the event device set the "LED" for the
// pin+32.

//
// This driver 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 driver 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 driver; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301 USA. Alternatively visit http://www.gnu.org/licenses/.
//

#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/timer.h>
#include <linux/reboot.h>

#include <asm/irq.h>
#include <asm/io.h>
#include <asm/mach-pnx833x/gpio.h>

MODULE_AUTHOR("Mike Crowe <mcrowe@roku.com>");
MODULE_DESCRIPTION("Roku Monaco IO driver");
MODULE_LICENSE("GPL");

#define ALWAYS_RUNNING 1

//#define debug printk
#define debug(...) do {} while(0)

static uint initial_outputs;
module_param(initial_outputs, uint, 0);
MODULE_PARM_DESC(initial_outputs, "Initial value of Monaco GPIO outputs.");

#ifndef TRUE
#define TRUE 1
#define FALSE 0
#endif

#define POLLS_PER_SECOND 40
#define JIFFY_INCREMENT (HZ/POLLS_PER_SECOND)

#define INPUT_COUNT 13

// Compact has eight simple inputs, a front button and a reset button
#define INPUT_BITS (0xff | (1<<11) | (1<<12))

// The total number of outputs we support
#define OUTPUT_COUNT 11

// Compact has eight simple outputs and two LEDs
#define OUTPUT_BITS (0xff | (1<<9) | (1<<10))

// The number of latches used to connect inputs to the shared GPIO range
#define INPUT_LATCHES 1

// The number of latches used to connect outputs to the shared GPIO range
#define OUTPUT_LATCHES 1

// The button that we treat as the Ctrl-Alt-Delete sequence. We
// consider the RESET button to have this behaviour if it is not enabled
// as an input but in order to let people reenable the special
// behaviour we also permit it to be set as an output.
#define RESET_BUTTON 11

// We need to appears as "buttons" rather than "keys" otherwise we'll
// end up generating keyboard events too.
#define FIRST_BUTTON BTN_MOUSE

struct io_bidirectional
{
	u16 outputs;
};

struct io_input_dev
{
	struct input_dev *input_dev;
#if !ALWAYS_RUNNING
	struct timer_list timer;
#endif

	u32 last_input_state;
};

struct io_output_dev
{
	struct input_dev *input_dev;

	u8 last_output_state[OUTPUT_LATCHES];
};

static spinlock_t shared_gpio_lock;
static struct io_input_dev io_input_dev;
static struct io_output_dev io_output_dev;
static struct io_bidirectional io_bidi;
#if ALWAYS_RUNNING
static struct timer_list io_timer;
#endif

static enum
{
	REVA = 0,
	REVC = 1
} io_rev;

#if !ALWAYS_RUNNING
static int io_open_count = 0;
#endif

static inline int is_input_bidi(u8 input)
{
	return (input < 8) || (input == RESET_BUTTON);
}

static inline int is_output_bidi(u8 output)
{
	return (output < 8);
}

static inline u8 map_output_to_bidi_index(u8 output)
{
	BUG_ON(!is_output_bidi(output));
	return output;
}

static inline u8 map_input_to_bidi_index(u8 input)
{
	BUG_ON(!is_input_bidi(input));
	return input;
}

static inline u8 map_bidi_index_to_output(u8 bidi)
{
	BUG_ON(!is_output_bidi(bidi));
	return bidi;
}

static inline u8 map_bidi_index_to_input(u8 bidi)
{
	BUG_ON(!is_input_bidi(bidi));
	return bidi;
}

static inline int is_reset_enabled(void)
{
	return (io_bidi.outputs & (1<<RESET_BUTTON)) != 0;
}

#define DIRECTION_IN 0
#define DIRECTION_OUT 1

#define BUS_CLOCK_GPIO49 0

// The REVA bank GPIOs are:
//    0 - GPIO34 - 2
//    1 - GPIO35 - 3
//    2 - GPIO36 - 4
//    3 - GPIO37 - 5
//    4 - GPIO38 - 6
//    5 - GPIO40 - 8
//    6 - GPIO41 - 9
//    7 - GPIO46 - 14
//

// The REVC bank GPIOs are:
//    0 - GPIO34 - 2
//    1 - GPIO35 - 3
//    2 - GPIO36 - 4
//    3 - GPIO37 - 5
//    4 - GPIO38 - 6
//    5 - GPIO41 - 9
//    6 - GPIO46 - 14
//    7 - GPIO48 - 16
//

static inline u32 to_bus_bits(u8 value)
{
	if (unlikely(io_rev == REVA))
		return ((((value) & 0x1f) << 2) | (((value) & 0x60) << 3) | (((value) & 0x80) << 7));
	else
		return ((((value) & 0x1f) << 2) | (((value) & 0x20) << 4) | (((value) & 0x40) << 8) | (((value) & 0x80) << 9));
}

static inline u8 from_bus_bits(u32 regs)
{
	if (unlikely(io_rev == REVA))
		return (u8)((((regs) >> 2) & 0x1f) | (((regs) >> 3) & 0x60) | (((regs) >> 7) & 0x80));
	else
		return (u8)((((regs) >> 2) & 0x1f) | (((regs) >> 4) & 0x20) | (((regs) >> 8) & 0x40) | (((regs) >> 9) & 0x80));
}
		    
static inline void io_set_banked(u8 value, u8 clock)
{
	u32 regs;
	unsigned long flags;

	spin_lock_irqsave(&shared_gpio_lock, flags);

	// Set the bank as output
	PNX833X_PIO_DIR2 |= to_bus_bits(0xff);

	// Set the value on the bank
	regs = PNX833X_PIO_OUT2;
	regs &= ~to_bus_bits(0xff);
	regs |= to_bus_bits(value);
	PNX833X_PIO_OUT2 = regs;

	// Clock the data out with a low pulse
	gpio_write(0, clock);
	gpio_write(1, clock);
	
	// Set bank as input
	PNX833X_PIO_DIR2 &= ~to_bus_bits(0xff);

	spin_unlock_irqrestore(&shared_gpio_lock, flags);
}

static inline int gpio_output_state(unsigned int pin)
{
	if (pin < 32)
	{
		return (PNX833X_PIO_OUT >> pin) & 1;
	}
	else
	{
		return (PNX833X_PIO_OUT2 >> (pin & 31)) & 1;
	}
}

static inline u8 io_read_banked(u8 latch)
{
	u32 regs1, regs2;
	u32 mask = to_bus_bits(0xff);
	int tries = 0;
	unsigned long flags;

	spin_lock_irqsave(&shared_gpio_lock, flags);
	
	// Drive the latch low so we can read.
	gpio_write(0, latch);

	// It would seem that on rare occasions the latch doesn't go
	// low quickly enough for us to read the GPIOs
	// immediately. Inserting this causes enough of a delay that
	// this doesn't happen.
	mb();
	mb();

	do
	{
		regs1 = PNX833X_PIO_IN2;
		regs2 = PNX833X_PIO_IN2;
		++tries;
	} while (((regs1 ^ regs2) & mask) && (tries < 8));

	mb();

	if (gpio_output_state(latch))
		pr_err("Something set latch GPIO %u high again. Bad.\n", latch);

	if (tries > 1)
		pr_info("Banked read took more than one attempt: %d\n", tries);

	// Drive the latch back high again so others can use the bank.
	gpio_write(1, latch);

	spin_unlock_irqrestore(&shared_gpio_lock, flags);

	return from_bus_bits(regs1);
}

static inline void io_gpio_write(u8 value, u8 reg)
{
	unsigned long flags;
	
	// Because a GPIO write is a read-modify-write operation we
	// need to protect ourselves against others nipping in. There
	// is code in NXP proprietary code that also accesses these
	// registers but it also protects itself by disabling
	// interrupts so we're compatible.
	spin_lock_irqsave(&shared_gpio_lock, flags);
	gpio_write(value, reg);
	spin_unlock_irqrestore(&shared_gpio_lock, flags);
}

static inline int io_gpio_read(u8 reg)
{
	return gpio_read(reg);
}

static void io_configure_gpio(void)
{
	unsigned long flags;
	spin_lock_irqsave(&shared_gpio_lock, flags);
	
	// First we need to identify the board
	gpio_select_input(6);
	gpio_select_input(7);

	debug("Board ID: %ld\n", ((PNX833X_PIO_IN >> 6) & 3));

	switch ((PNX833X_PIO_IN >> 6) & 3)
	{
	case 2:
		pr_info("Monaco IO driver detected REVA/B board\n");
		io_rev = REVA;
		break;
	case 0:
	case 1:
		pr_err("\nUnknown board hardware revision\n\n");
		/* fall through */
	case 3:
		pr_info("Monaco IO driver detected REVC+ board\n");
		io_rev = REVC;
		break;
	};
	
	
	// Set all the latch clocks as outputs
	gpio_select_output(6);  // Direction flags latch
	gpio_select_output(45); // I/O inputs latch
	gpio_select_output(49); // I/O outputs latch

	// Make sure all the latch clocks are inactive (high)
	gpio_write(1, 6);
	gpio_write(1, 45);
	gpio_write(1, 49);

	gpio_select_input(23); // FRNT BT
	
	gpio_select_output(16); // BUTTON4
	gpio_select_output(17); // BUTTON5
	gpio_select_output(24); // BUTTON6
	gpio_select_output(50); // BUTTON7
	
	gpio_select_output(14); // UPGRADE LED

	// We don't want the status LED to blink at startup so we have
	// to set it high before we make it an output.
	gpio_write(1, 7);
	gpio_select_output(7); // STATUS LED
	
	// Although we don't use these they are connected to
	// BUTTON5, 6, 7 so we make sure they are set as
	// inputs so that we don't accidentally drive
	// the lines.
	gpio_select_input(0);
	gpio_select_input(1);

	// This is also used for IR. We set it as an input
	// here so that we aren't driving the line in a funny
	// direction but once the IR driver loads it will
	// reconfigure the pin to alternate mode anyway.
	gpio_select_input(39);

	// Configure the latched bank as inputs (tristated)
	PNX833X_PIO_DIR2 &= ~to_bus_bits(0xff);

	spin_unlock_irqrestore(&shared_gpio_lock, flags);
}

static void io_bidi_configure(u8 bidi, int direction)
{
	u16 new_outputs = io_bidi.outputs;
	debug("io_bidi_configure(%u, %d)\n", bidi, direction);
	if (direction)
		new_outputs |= (1<<bidi);
	else
		new_outputs &= ~(1<<bidi);

	debug("io_bidi_outputs=0x%x, new_outputs=0x%x\n", io_bidi.outputs, new_outputs);
	if (io_bidi.outputs ^ new_outputs) {
		// We only need to bother reconfiguring the hardware
		// if we're changing something other than the reset button.
		if ((io_bidi.outputs ^ new_outputs) & 0xff)
			io_set_banked(new_outputs, 6);

		// Report the change to both the input and output devices.
		if (is_output_bidi(bidi)) {
			debug("Sending output LED event: %u+32, %d\n", map_bidi_index_to_output(bidi), direction);
			input_event(io_output_dev.input_dev, EV_LED, map_bidi_index_to_output(bidi) + 32, direction);
		}
		if (is_input_bidi(bidi)) {
			debug("Sending input LED event: %u+32, %d\n", map_bidi_index_to_input(bidi), !direction);
			input_event(io_input_dev.input_dev, EV_LED, map_bidi_index_to_input(bidi) + 32, !direction);
		}

		io_bidi.outputs = new_outputs;
		debug("io_bidi.outputs is now %u\n", io_bidi.outputs);
	}
}

//
// OUTPUT
//

static void io_set_latched_output(struct io_output_dev *dev, u8 latch_index, u8 index, u8 value)
{
	u8 bank;
	BUG_ON(latch_index >= OUTPUT_LATCHES);
	
	bank = dev->last_output_state[latch_index];

	// Set the bit we want to set correctly
	if (value)
		bank |= (1<<index);
	else
		bank &= ~(1<<index);

	switch (latch_index)
	{
	case BUS_CLOCK_GPIO49:
		io_set_banked(bank, 49);
		break;
	default:
		BUG();
		break;
	}

	dev->last_output_state[latch_index] = bank;
}

static int io_set_output(struct io_output_dev *dev, u8 index, int value)
{
	debug("io_set_output(%u, %d)\n", index, value);
	switch (index)
	{
	case 0:
	case 1:
	case 2:
	case 3:
		io_set_latched_output(dev, BUS_CLOCK_GPIO49, index, value);
		break;
	case 4:
		io_gpio_write(value, 16);
		break;
	case 5:
		io_gpio_write(value, 17);
		break;
	case 6:
		io_gpio_write(value, 24);
		break;
	case 7:
		io_gpio_write(value, 50);
		break;
	case 9:
		// This LED is upsidedown
		io_gpio_write(!value, 7);
		break;
	case 10:
		io_gpio_write(value, 14);
		break;
	default:
		// Invalid
		return -1;
	}
	return 0;
}

static inline int io_set_output_enabled(struct io_output_dev *dev, u8 index, int value)
{
	debug("io_set_output_enabled(%u, %d)\n", index, value);
	if (is_output_bidi(index)) {
		io_bidi_configure(map_output_to_bidi_index(index), value ? DIRECTION_OUT : DIRECTION_IN);
		return 0;
	} else
		return -1;
}

static void io_set_outputs(struct io_output_dev *dev, u32 value)
{
	u8 index;
	for(index = 0; index < OUTPUT_COUNT; ++index, value >>= 1) {
		io_set_output(dev, index, value & 1);
		input_event(dev->input_dev, EV_LED, index, value & 1);
	}
}

static int io_output_event(struct input_dev *input_dev, unsigned int type, unsigned int code, int value)
{
	struct io_output_dev *dev = input_dev->private;

	debug("io_output_event %u, %d\n", code, value);

	if (type == EV_LED) {
		if (code >= 32)
			return io_set_output_enabled(dev, code - 32, value);
		else
			return io_set_output(dev, code, value);
	}
	else
		return -1;
}

//
// INPUT
//
static inline u32 io_read_inputs(struct io_input_dev *dev)
{
	u32 result = 0U;
	u32 gpio0;

	// First read the IO connector from the bank.
	result = io_read_banked(45);

	// Now read the side buttons
	gpio0 = PNX833X_PIO_IN;

	// BOOT_SELECT
	result |= ((gpio0 >> 12) & 1) << 11;

	// FRNT_BT
	result |= ((gpio0 >> 23) & 1) << 12;

	return result;
}

static int io_set_input_enabled(struct io_input_dev *dev, u8 index, int value)
{
	debug("io_set_input_enabled(index=%u, value=%d)\n", index, value);
	if (is_input_bidi(index)) {
		io_bidi_configure(map_input_to_bidi_index(index), value ? DIRECTION_IN : DIRECTION_OUT);
		return 0;
	} else
		return -1;
}

static void io_set_inputs_enabled(struct io_input_dev *dev, u32 value)
{
	u8 index;
	for(index = 0; index < INPUT_COUNT; ++index, value >>= 1) {
		io_set_input_enabled(dev, index, value & 1);
	}
}

static void io_report_inputs(struct io_input_dev *dev, u32 state, int report_down)
{
	u32 mask;
	u32 button;
	u32 changes;

	if (unlikely((state & (1<<RESET_BUTTON)) == 0) && (is_reset_enabled())) {
		pr_info("Requesting reboot from reset button.\n");
		ctrl_alt_del();
		return;
	}

	if (report_down)
		changes = state ^ ((1<<INPUT_COUNT)-1);
	else
		changes = dev->last_input_state ^ state;
	
	// The buttons are active low so we invert the state when we
	// pass it to report_key. We'll report buttons that don't
	// exist on the first time through here but that doesn't
	// matter because the input layer just ignores them.
	for(mask = 1, button = FIRST_BUTTON; mask <= changes; mask<<=1, ++button)
		if (changes & mask)
			input_report_key(dev->input_dev, button, !(state & mask));
	input_sync(dev->input_dev);

	// Make sure we don't report these changes again.
	dev->last_input_state = state;
}

static void io_input_timer(unsigned long data)
{
	u32 new_inputs;
	struct io_input_dev *dev = (struct io_input_dev *)data;

	new_inputs = io_read_inputs(dev);

	if (unlikely(new_inputs != dev->last_input_state))
		io_report_inputs(dev, new_inputs, FALSE);

#if !ALWAYS_RUNNING
	if (likely(io_open_count))
	{
		dev->timer.expires = jiffies + JIFFY_INCREMENT;
		add_timer(&dev->timer);
	}
#else
	io_timer.expires = jiffies + JIFFY_INCREMENT;
	add_timer(&io_timer);
#endif
}

static int io_input_open(struct input_dev *input_dev)
{
#if !ALWAYS_RUNNING
	struct io_input_dev *dev = input_dev->private;

        if (io_open_count++)
                return 0;

	// We're the first open so kick off the timer
	dev->timer.expires = jiffies;
	add_timer(&dev->timer);
#endif
        return 0;
}

static void io_input_close(struct input_dev *input_dev)
{
#if !ALWAYS_RUNNING
	struct io_input_dev *dev = input_dev->private;

        if (!--io_open_count) {
		// We're the last close so kill the timer
		del_timer_sync(&dev->timer);
	}
#endif
}

static int io_input_event(struct input_dev *input_dev, unsigned int type, unsigned int code, int value)
{
	struct io_input_dev *dev = input_dev->private;

	if (type == EV_LED) {
		if (code >= 32)
			return io_set_input_enabled(dev, code - 32, value);
		else
			return -1;
	} else
		return -1;
}

//
// DRIVER
//

static int __devinit io_probe(struct platform_device *dev)
{
        struct input_dev *input_dev = NULL;
	struct input_dev *output_dev = NULL;
        int err;
	unsigned long i;
	u32 valid_input_bits, valid_output_bits;

	spin_lock_init(&shared_gpio_lock);
	
        input_dev = input_allocate_device();
        if (!input_dev) {
                err = -ENOMEM;
		goto err_free_devices;
	}

	output_dev = input_allocate_device();
	if (!output_dev) {
		err = -ENOMEM;
		goto err_free_devices;
	}

        input_dev->private = &io_input_dev;
        input_dev->name = "Roku Monaco input device",
        input_dev->phys = "brightsign/input";
	input_dev->open = io_input_open;
	input_dev->close = io_input_close;
	input_dev->event = io_input_event;
        input_dev->id.bustype = BUS_HOST;
        input_dev->id.vendor  = 0x001f;
        input_dev->id.product = 0x0001;
        input_dev->id.version = 0x0100;	
        input_dev->cdev.dev = &dev->dev;
	set_bit(EV_KEY, input_dev->evbit);
	set_bit(EV_LED, input_dev->evbit);

	valid_input_bits = INPUT_BITS;
	valid_output_bits = OUTPUT_BITS;
		
	// The buttons we support and whether they are bidirectional.
	for(i = 0; i < INPUT_COUNT; ++i) {
		if (valid_input_bits & (1<<i)) {
			set_bit(FIRST_BUTTON + i, input_dev->keybit);
			if (is_input_bidi(i))
			    set_bit(i + 32, input_dev->ledbit);
		}
	}

        output_dev->private = &io_output_dev;
        output_dev->name = "Roku Monaco output device",
        output_dev->phys = "brightsign/output";
	output_dev->event = io_output_event;
        output_dev->id.bustype = BUS_HOST;
        output_dev->id.vendor  = 0x001f;
        output_dev->id.product = 0x0001;
        output_dev->id.version = 0x0100;	
        output_dev->cdev.dev = &dev->dev;
	set_bit(EV_LED, output_dev->evbit);

	// The LEDs we support and whether they are bidirectional
	for(i = 0; i < OUTPUT_COUNT; ++i) {
		if (valid_output_bits & (1<<i)) {
			set_bit(i, output_dev->ledbit);
			if (is_output_bidi(i))
				set_bit(i + 32, output_dev->ledbit);
		}
	}

#if !ALWAYS_RUNNING
	init_timer(&io_input_dev.timer);
	io_input_dev.timer.data = (unsigned long)&io_input_dev;
	io_input_dev.timer.function = io_input_timer;
#endif
	io_input_dev.input_dev = input_dev;
	io_output_dev.input_dev = output_dev;

	// Set all the GPIOs up how we want them.
	io_configure_gpio();

	// This causes io_input_open and io_input_close to be called.
        err = input_register_device(input_dev);
	if (err)
		goto err_free_devices;

        err = input_register_device(output_dev);
	if (err) {
		input_unregister_device(input_dev);
		goto err_free_devices;
	}

	// With the exception of the reset button (which we want to
	// work as a reset button by default) configure everything as
	// input to start with but pretend they were all outputs
	// initially so that we end up generating events for them all.
	io_bidi.outputs = 0xff & ~(1<<RESET_BUTTON);
	io_set_inputs_enabled(&io_input_dev, 0xffffffff & ~(1<<RESET_BUTTON));

	io_set_outputs(&io_output_dev, initial_outputs);
	
	// Report all the buttons that are currently down before we
	// start the timer so we don't race.
	io_report_inputs(&io_input_dev, io_read_inputs(&io_input_dev), TRUE);

#if ALWAYS_RUNNING
	init_timer(&io_timer);
	io_timer.data = (unsigned long)&io_input_dev;
	io_timer.function = io_input_timer;
	io_timer.expires = jiffies;
	add_timer(&io_timer);
#endif
	return 0;

err_free_devices:
	if (output_dev)
		input_free_device(output_dev);
	if (input_dev)
		input_free_device(input_dev);
        return err;
}

static int __devexit io_remove(struct platform_device *dev)
{
#if ALWAYS_RUNNING
	del_timer_sync(&io_timer);
#else
	BUG_ON(io_open_count != 0);
#endif
        input_unregister_device(io_input_dev.input_dev);
        input_unregister_device(io_output_dev.input_dev);

        return 0;
}

static void io_shutdown(struct platform_device *dev)
{
	input_unregister_device(io_input_dev.input_dev);
	input_unregister_device(io_output_dev.input_dev);
}


static struct platform_driver io_platform_driver = {
        .driver         = {
                .name   = "roku-monaco-io",
                .owner  = THIS_MODULE,
        },
        .probe          = io_probe,
        .remove         = io_remove,
        .shutdown       = io_shutdown,
};

static struct platform_device *io_platform_device;

static int __init io_init(void)
{
	int err;
	err = platform_driver_register(&io_platform_driver);
	if (err == 0) {
		io_platform_device = platform_device_alloc("roku-monaco-io", -1);
		if (io_platform_device) {
			err = platform_device_add(io_platform_device);
			if (err == 0) {
				return 0;
			} else {
				platform_device_put(io_platform_device);
			}
		} else {
			err = -ENOMEM;
		}
		
		platform_driver_unregister(&io_platform_driver);
	}
	return err;
}

static void __exit io_exit(void)
{
	platform_device_del(io_platform_device);
	platform_driver_unregister(&io_platform_driver);
}

module_init(io_init);
module_exit(io_exit);

