/*
 * Copyright (c) 2012 The Chromium OS Authors.
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

/*
 * This is a GPIO driver for Intel ICH6 and later. The x86 GPIOs are accessed
 * through the PCI bus. Each PCI device has 256 bytes of configuration space,
 * consisting of a standard header and a device-specific set of registers. PCI
 * bus 0, device 31, function 0 gives us access to the chipset GPIOs (among
 * other things). Within the PCI configuration space, the GPIOBASE register
 * tells us where in the device's I/O region we can find more registers to
 * actually access the GPIOs.
 *
 * PCI bus/device/function 0:1f:0  => PCI config registers
 *   PCI config register "GPIOBASE"
 *     PCI I/O space + [GPIOBASE]  => start of GPIO registers
 *       GPIO registers => gpio pin function, direction, value
 *
 *
 * Danger Will Robinson! Bank 0 (GPIOs 0-31) seems to be fairly stable. Most
 * ICH versions have more, but the decoding the matrix that describes them is
 * absurdly complex and constantly changing. We'll provide Bank 1 and Bank 2,
 * but they will ONLY work for certain unspecified chipsets because the offset
 * from GPIOBASE changes randomly. Even then, many GPIOs are unimplemented or
 * reserved or subject to arcane restrictions.
 */

#include <common.h>
#include <pci.h>
#include <asm/gpio.h>
#include <asm/io.h>

/* Where in config space is the register that points to the GPIO registers? */
#define PCI_CFG_GPIOBASE 0x48

#define NUM_BANKS 3

/* Within the I/O space, where are the registers to control the GPIOs? */
static struct {
	u8 use_sel;
	u8 io_sel;
	u8 lvl;
} gpio_bank[NUM_BANKS] = {
	{ 0x00, 0x04, 0x0c },		/* Bank 0 */
	{ 0x30, 0x34, 0x38 },		/* Bank 1 */
	{ 0x40, 0x44, 0x48 }		/* Bank 2 */
};

static pci_dev_t dev;			/* handle for 0:1f:0 */
static u32 gpiobase;			/* offset into I/O space */
static int found_it_once;		/* valid GPIO device? */
static u32 lock[NUM_BANKS];		/* "lock" for access to pins */

static int bad_arg(int num, int *bank, int *bitnum)
{
	int i = num / 32;
	int j = num % 32;

	if (num < 0 || i > NUM_BANKS) {
		debug("%s: bogus gpio num: %d\n", __func__, num);
		return -1;
	}
	*bank = i;
	*bitnum = j;
	return 0;
}

static int mark_gpio(int bank, int bitnum)
{
	if (lock[bank] & (1UL << bitnum)) {
		debug("%s: %d.%d already marked\n", __func__, bank, bitnum);
		return -1;
	}
	lock[bank] |= (1 << bitnum);
	return 0;
}

static void clear_gpio(int bank, int bitnum)
{
	lock[bank] &= ~(1 << bitnum);
}

static int notmine(int num, int *bank, int *bitnum)
{
	if (bad_arg(num, bank, bitnum))
		return -1;
	return !(lock[*bank] & (1UL << *bitnum));
}

static int gpio_init(void)
{
	u8 tmpbyte;
	u16 tmpword;
	u32 tmplong;

	/* Have we already done this? */
	if (found_it_once)
		return 0;

	/* Where should it be? */
	dev = PCI_BDF(0, 0x1f, 0);

	/* Is the device present? */
	pci_read_config_word(dev, PCI_VENDOR_ID, &tmpword);
	if (tmpword != PCI_VENDOR_ID_INTEL) {
		debug("%s: wrong VendorID\n", __func__);
		return -1;
	}

	pci_read_config_word(dev, PCI_DEVICE_ID, &tmpword);
	debug("Found %04x:%04x\n", PCI_VENDOR_ID_INTEL, tmpword);
	/*
	 * We'd like to validate the Device ID too, but pretty much any
	 * value is either a) correct with slight differences, or b)
	 * correct but undocumented. We'll have to check a bunch of other
	 * things instead...
	 */

	/* I/O should already be enabled (it's a RO bit). */
	pci_read_config_word(dev, PCI_COMMAND, &tmpword);
	if (!(tmpword & PCI_COMMAND_IO)) {
		debug("%s: device IO not enabled\n", __func__);
		return -1;
	}

	/* Header Type must be normal (bits 6-0 only; see spec.) */
	pci_read_config_byte(dev, PCI_HEADER_TYPE, &tmpbyte);
	if ((tmpbyte & 0x7f) != PCI_HEADER_TYPE_NORMAL) {
		debug("%s: invalid Header type\n", __func__);
		return -1;
	}

	/* Base Class must be a bridge device */
	pci_read_config_byte(dev, PCI_CLASS_CODE, &tmpbyte);
	if (tmpbyte != PCI_CLASS_CODE_BRIDGE) {
		debug("%s: invalid class\n", __func__);
		return -1;
	}
	/* Sub Class must be ISA */
	pci_read_config_byte(dev, PCI_CLASS_SUB_CODE, &tmpbyte);
	if (tmpbyte != PCI_CLASS_SUB_CODE_BRIDGE_ISA) {
		debug("%s: invalid subclass\n", __func__);
		return -1;
	}

	/* Programming Interface must be 0x00 (no others exist) */
	pci_read_config_byte(dev, PCI_CLASS_PROG, &tmpbyte);
	if (tmpbyte != 0x00) {
		debug("%s: invalid interface type\n", __func__);
		return -1;
	}

	/*
	 * GPIOBASE moved to its current offset with ICH6, but prior to
	 * that it was unused (or undocumented). Check that it looks
	 * okay: not all ones or zeros, and mapped to I/O space (bit 0).
	 */
	pci_read_config_dword(dev, PCI_CFG_GPIOBASE, &tmplong);
	if (tmplong == 0x00000000 || tmplong == 0xffffffff ||
	    !(tmplong & 0x00000001)) {
		debug("%s: unexpected GPIOBASE value\n", __func__);
		return -1;
	}

	/*
	 * Okay, I guess we're looking at the right device. The actual
	 * GPIO registers are in the PCI device's I/O space, starting
	 * at the offset that we just read. Bit 0 indicates that it's
	 * an I/O address, not a memory address, so mask that off.
	 */
	gpiobase = tmplong & 0xfffffffe;

	/* Finally. These are the droids we're looking for. */
	found_it_once = 1;
	return 0;
}

int gpio_request(unsigned num, const char *label /* UNUSED */)
{
	u32 tmplong;
	int i = 0, j = 0;

	/* Is the hardware ready? */
	if (gpio_init())
		return -1;

	if (bad_arg(num, &i, &j))
		return -1;

	/*
	 * Make sure that the GPIO pin we want isn't already in use for some
	 * built-in hardware function. We have to check this for every
	 * requested pin.
	 */
	tmplong = inl(gpiobase + gpio_bank[i].use_sel);
	if (!(tmplong & (1UL << j))) {
		debug("%s: gpio %d is reserved for internal use\n", __func__,
		      num);
		return -1;
	}

	return mark_gpio(i, j);
}

int gpio_free(unsigned num)
{
	int i = 0, j = 0;

	if (notmine(num, &i, &j))
		return -1;

	clear_gpio(i, j);
	return 0;
}

int gpio_direction_input(unsigned num)
{
	u32 tmplong;
	int i = 0, j = 0;

	if (notmine(num, &i, &j))
		return -1;

	tmplong = inl(gpiobase + gpio_bank[i].io_sel);
	tmplong |= (1UL << j);
	outl(gpiobase + gpio_bank[i].io_sel, tmplong);
	return 0;
}

int gpio_direction_output(unsigned num, int value)
{
	u32 tmplong;
	int i = 0, j = 0;

	if (notmine(num, &i, &j))
		return -1;

	tmplong = inl(gpiobase + gpio_bank[i].io_sel);
	tmplong &= ~(1UL << j);
	outl(gpiobase + gpio_bank[i].io_sel, tmplong);
	return 0;
}

int gpio_get_value(unsigned num)
{
	u32 tmplong;
	int i = 0, j = 0;
	int r;

	if (notmine(num, &i, &j))
		return -1;

	tmplong = inl(gpiobase + gpio_bank[i].lvl);
	r = (tmplong & (1UL << j)) ? 1 : 0;
	return r;
}

int gpio_set_value(unsigned num, int value)
{
	u32 tmplong;
	int i = 0, j = 0;

	if (notmine(num, &i, &j))
		return -1;

	tmplong = inl(gpiobase + gpio_bank[i].lvl);
	if (value)
		tmplong |= (1UL << j);
	else
		tmplong &= ~(1UL << j);
	outl(gpiobase + gpio_bank[i].lvl, tmplong);
	return 0;
}
