/*
 * Allocator for I/O pins. All pins are allocated to GPIO at bootup.
 * Unassigned pins and GPIO pins can be allocated to a fixed interface
 * or the I/O processor instead.
 *
 * Copyright (c) 2004 Axis Communications AB.
 */

#include <linux/init.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/spinlock.h>
#include <arch/hwregs/reg_map.h>
#include <arch/hwregs/reg_rdwr.h>
#include <arch/pinmux.h>
#include <arch/hwregs/pinmux_defs.h>

#undef DEBUG

#define PORT_PINS 18
#define PORTS 4

static char pins[PORTS][PORT_PINS];
static DEFINE_SPINLOCK(pinmux_lock);

static void crisv32_pinmux_set(int port);

int
crisv32_pinmux_init(void)
{
	static int initialized = 0;

	if (!initialized) {
		reg_pinmux_rw_pa pa = REG_RD(pinmux, regi_pinmux, rw_pa);
		initialized = 1;
		pa.pa0 = pa.pa1 = pa.pa2 = pa.pa3 =
		pa.pa4 = pa.pa5 = pa.pa6 = pa.pa7 = regk_pinmux_yes;
		REG_WR(pinmux, regi_pinmux, rw_pa, pa);
		crisv32_pinmux_alloc(PORT_B, 0, PORT_PINS - 1, pinmux_gpio);
		crisv32_pinmux_alloc(PORT_C, 0, PORT_PINS - 1, pinmux_gpio);
		crisv32_pinmux_alloc(PORT_D, 0, PORT_PINS - 1, pinmux_gpio);
		crisv32_pinmux_alloc(PORT_E, 0, PORT_PINS - 1, pinmux_gpio);
	}

	return 0;
}

int
crisv32_pinmux_alloc(int port, int first_pin, int last_pin, enum pin_mode mode)
{
	int i;
	unsigned long flags;

	crisv32_pinmux_init();

	if (port > PORTS || port < 0)
		return -EINVAL;

	spin_lock_irqsave(&pinmux_lock, flags);

	for (i = first_pin; i <= last_pin; i++)
	{
		if ((pins[port][i] != pinmux_none) && (pins[port][i] != pinmux_gpio) &&
		    (pins[port][i] != mode))
		{
			spin_unlock_irqrestore(&pinmux_lock, flags);
#ifdef DEBUG
			panic("Pinmux alloc failed!\n");
#endif
			return -EPERM;
		}
	}

	for (i = first_pin; i <= last_pin; i++)
		pins[port][i] = mode;

	crisv32_pinmux_set(port);

	spin_unlock_irqrestore(&pinmux_lock, flags);

	return 0;
}

int
crisv32_pinmux_alloc_fixed(enum fixed_function function)
{
	int ret = -EINVAL;
	char saved[sizeof pins];
	unsigned long flags;

	spin_lock_irqsave(&pinmux_lock, flags);

	/* Save internal data for recovery */
	memcpy(saved, pins, sizeof pins);

	reg_pinmux_rw_hwprot hwprot = REG_RD(pinmux, regi_pinmux, rw_hwprot);

	switch(function)
	{
	case pinmux_ser1:
		ret = crisv32_pinmux_alloc(PORT_C, 4, 7, pinmux_fixed);
		hwprot.ser1 = regk_pinmux_yes;
		break;
	case pinmux_ser2:
		ret = crisv32_pinmux_alloc(PORT_C, 8, 11, pinmux_fixed);
		hwprot.ser2 = regk_pinmux_yes;
		break;
	case pinmux_ser3:
		ret = crisv32_pinmux_alloc(PORT_C, 12, 15, pinmux_fixed);
		hwprot.ser3 = regk_pinmux_yes;
		break;
	case pinmux_sser0:
		ret = crisv32_pinmux_alloc(PORT_C, 0, 3, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
		hwprot.sser0 = regk_pinmux_yes;
		break;
	case pinmux_sser1:
		ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
		hwprot.sser1 = regk_pinmux_yes;
		break;
	case pinmux_ata0:
		ret = crisv32_pinmux_alloc(PORT_D, 5, 7, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_D, 15, 17, pinmux_fixed);
		hwprot.ata0 = regk_pinmux_yes;
		break;
	case pinmux_ata1:
		ret = crisv32_pinmux_alloc(PORT_D, 0, 4, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_E, 17, 17, pinmux_fixed);
		hwprot.ata1 = regk_pinmux_yes;
		break;
	case pinmux_ata2:
		ret = crisv32_pinmux_alloc(PORT_C, 11, 15, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_E, 3, 3, pinmux_fixed);
		hwprot.ata2 = regk_pinmux_yes;
		break;
	case pinmux_ata3:
		ret = crisv32_pinmux_alloc(PORT_C, 8, 10, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_C, 0, 2, pinmux_fixed);
		hwprot.ata2 = regk_pinmux_yes;
		break;
	case pinmux_ata:
		ret = crisv32_pinmux_alloc(PORT_B, 0, 15, pinmux_fixed);
		ret |= crisv32_pinmux_alloc(PORT_D, 8, 15, pinmux_fixed);
		hwprot.ata = regk_pinmux_yes;
		break;
	case pinmux_eth1:
		ret = crisv32_pinmux_alloc(PORT_E, 0, 17, pinmux_fixed);
		hwprot.eth1 = regk_pinmux_yes;
		hwprot.eth1_mgm = regk_pinmux_yes;
		break;
	case pinmux_timer:
		ret = crisv32_pinmux_alloc(PORT_C, 16, 16, pinmux_fixed);
		hwprot.timer = regk_pinmux_yes;
		spin_unlock_irqrestore(&pinmux_lock, flags);
		return ret;
	}

	if (!ret)
		REG_WR(pinmux, regi_pinmux, rw_hwprot, hwprot);
	else
		memcpy(pins, saved, sizeof pins);

  spin_unlock_irqrestore(&pinmux_lock, flags);

  return ret;
}

void
crisv32_pinmux_set(int port)
{
	int i;
	int gpio_val = 0;
	int iop_val = 0;

	for (i = 0; i < PORT_PINS; i++)
	{
		if (pins[port][i] == pinmux_gpio)
			gpio_val |= (1 << i);
		else if (pins[port][i] == pinmux_iop)
			iop_val |= (1 << i);
	}

	REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_gio + 8*port, gpio_val);
	REG_WRITE(int, regi_pinmux + REG_RD_ADDR_pinmux_rw_pb_iop + 8*port, iop_val);

#ifdef DEBUG
       crisv32_pinmux_dump();
#endif
}

int
crisv32_pinmux_dealloc(int port, int first_pin, int last_pin)
{
	int i;
	unsigned long flags;

	crisv32_pinmux_init();

	if (port > PORTS || port < 0)
		return -EINVAL;

	spin_lock_irqsave(&pinmux_lock, flags);

	for (i = first_pin; i <= last_pin; i++)
		pins[port][i] = pinmux_none;

	crisv32_pinmux_set(port);
	spin_unlock_irqrestore(&pinmux_lock, flags);

	return 0;
}

void
crisv32_pinmux_dump(void)
{
	int i, j;

	crisv32_pinmux_init();

	for (i = 0; i < PORTS; i++)
	{
		printk("Port %c\n", 'B'+i);
		for (j = 0; j < PORT_PINS; j++)
			printk("  Pin %d = %d\n", j, pins[i][j]);
	}
}

__initcall(crisv32_pinmux_init);
