/*
 * arch/arm/mach-ns9xxx/gpio.c
 *
 * Copyright (C) 2006 by Digi International Inc.
 * All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 */
#include <linux/compiler.h>
#include <linux/init.h>
#include <linux/spinlock.h>
#include <linux/module.h>

#include <asm/arch-ns9xxx/gpio.h>
#include <asm/arch-ns9xxx/processor.h>
#include <asm/arch-ns9xxx/regs-bbu.h>
#include <asm/io.h>
#include <asm/bug.h>
#include <asm/types.h>
#include <asm/bitops.h>

#if defined(CONFIG_PROCESSOR_NS9360)
#define GPIO_MAX 72
#elif defined(CONFIG_PROCESSOR_NS9750)
#define GPIO_MAX 49
#endif

/* protects BBU_GCONFx and BBU_GCTRLx */
static spinlock_t gpio_lock = __SPIN_LOCK_UNLOCKED(gpio_lock);

/* only access gpiores with atomic ops */
static DECLARE_BITMAP(gpiores, GPIO_MAX + 1);

static inline int ns9xxx_valid_gpio(unsigned gpio)
{
#if defined(CONFIG_PROCESSOR_NS9360)
	if (processor_is_ns9360())
		return gpio <= 72;
	else
#endif
#if defined(CONFIG_PROCESSOR_NS9750)
	if (processor_is_ns9750())
		return gpio <= 49;
	else
#endif
		BUG();
}

static inline void __iomem *ns9xxx_gpio_get_gconfaddr(unsigned gpio)
{
	if (gpio < 56)
		return BBU_GCONFb1(gpio / 8);
	else
		/*
		 * this could be optimised away on
		 * ns9750 only builds, but it isn't ...
		 */
		return BBU_GCONFb2((gpio - 56) / 8);
}

static inline void __iomem *ns9xxx_gpio_get_gctrladdr(unsigned gpio)
{
	if (gpio < 32)
		return BBU_GCTRL1;
	else if (gpio < 64)
		return BBU_GCTRL2;
	else
		/* this could be optimised away on ns9750 only builds */
		return BBU_GCTRL3;
}

static inline void __iomem *ns9xxx_gpio_get_gstataddr(unsigned gpio)
{
	if (gpio < 32)
		return BBU_GSTAT1;
	else if (gpio < 64)
		return BBU_GSTAT2;
	else
		/* this could be optimised away on ns9750 only builds */
		return BBU_GSTAT3;
}

int gpio_request(unsigned gpio, const char *label)
{
	if (likely(ns9xxx_valid_gpio(gpio)))
		return test_and_set_bit(gpio, gpiores) ? -EBUSY : 0;
	else
		return -EINVAL;
}
EXPORT_SYMBOL(gpio_request);

void gpio_free(unsigned gpio)
{
	clear_bit(gpio, gpiores);
	return;
}
EXPORT_SYMBOL(gpio_free);

/*
 * each gpio can serve for 4 different purposes [0..3].  These are called
 * "functions" and passed in the parameter func.  Functions 0-2 are always some
 * special things, function 3 is GPIO.  If func == 3 dir specifies input or
 * output, and with inv you can enable an inverter (independent of func).
 */
static int __ns9xxx_gpio_configure(unsigned gpio, int dir, int inv, int func)
{
	void __iomem *conf = ns9xxx_gpio_get_gconfaddr(gpio);
	u32 confval;
	unsigned long flags;

	spin_lock_irqsave(&gpio_lock, flags);

	confval = __raw_readl(conf);
	REGSETIM_IDX(confval, BBU_GCONFx, DIR, gpio & 7, dir);
	REGSETIM_IDX(confval, BBU_GCONFx, INV, gpio & 7, inv);
	REGSETIM_IDX(confval, BBU_GCONFx, FUNC, gpio & 7, func);
	__raw_writel(confval, conf);

	spin_unlock_irqrestore(&gpio_lock, flags);

	return 0;
}

int ns9xxx_gpio_configure(unsigned gpio, int inv, int func)
{
	if (likely(ns9xxx_valid_gpio(gpio))) {
		if (func == 3) {
			printk(KERN_WARNING "use gpio_direction_input "
					"or gpio_direction_output\n");
			return -EINVAL;
		} else
			return __ns9xxx_gpio_configure(gpio, 0, inv, func);
	} else
		return -EINVAL;
}
EXPORT_SYMBOL(ns9xxx_gpio_configure);

int gpio_direction_input(unsigned gpio)
{
	if (likely(ns9xxx_valid_gpio(gpio))) {
		return __ns9xxx_gpio_configure(gpio, 0, 0, 3);
	} else
		return -EINVAL;
}
EXPORT_SYMBOL(gpio_direction_input);

int gpio_direction_output(unsigned gpio, int value)
{
	if (likely(ns9xxx_valid_gpio(gpio))) {
		gpio_set_value(gpio, value);

		return __ns9xxx_gpio_configure(gpio, 1, 0, 3);
	} else
		return -EINVAL;
}
EXPORT_SYMBOL(gpio_direction_output);

int gpio_get_value(unsigned gpio)
{
	void __iomem *stat = ns9xxx_gpio_get_gstataddr(gpio);
	int ret;

	ret = 1 & (__raw_readl(stat) >> (gpio & 31));

	return ret;
}
EXPORT_SYMBOL(gpio_get_value);

void gpio_set_value(unsigned gpio, int value)
{
	void __iomem *ctrl = ns9xxx_gpio_get_gctrladdr(gpio);
	u32 ctrlval;
	unsigned long flags;

	spin_lock_irqsave(&gpio_lock, flags);

	ctrlval = __raw_readl(ctrl);

	if (value)
		ctrlval |= 1 << (gpio & 31);
	else
		ctrlval &= ~(1 << (gpio & 31));

	__raw_writel(ctrlval, ctrl);

	spin_unlock_irqrestore(&gpio_lock, flags);
}
EXPORT_SYMBOL(gpio_set_value);
