/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2012 Google 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 as published by
 * the Free Software Foundation; version 2 of the License.
 *
 * 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.
 */

#include <stdint.h>
#include <string.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>

#include "pch.h"
#include "lp_gpio.h"

static u16 get_gpio_base(void)
{
#if defined(__PRE_RAM__) || defined(__SMM__)
	return pci_read_config16(PCH_LPC_DEV, GPIO_BASE) & 0xfffc;
#else
	return pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)),
				 GPIO_BASE) & 0xfffc;
#endif
}


/*
 * This function will return a number that indicates which PIRQ
 * this GPIO maps to.  If this is not a PIRQ capable GPIO then
 * it will return -1.  The GPIO to PIRQ mapping is not linear.
 */
static int lp_gpio_to_pirq(int gpio)
{
	switch (gpio) {
	case 8:  return 0;	/* PIRQI */
	case 9:  return 1;	/* PIRQJ */
	case 10: return 2;	/* PIRQK */
	case 13: return 3;	/* PIRQL */
	case 14: return 4;	/* PIRQM */
	case 45: return 5;	/* PIRQN */
	case 46: return 6;	/* PIRQO */
	case 47: return 7;	/* PIRQP */
	case 48: return 8;	/* PIRQQ */
	case 49: return 9;	/* PIRQR */
	case 50: return 10;	/* PIRQS */
	case 51: return 11;	/* PIRQT */
	case 52: return 12;	/* PIRQU */
	case 53: return 13;	/* PIRQV */
	case 54: return 14;	/* PIRQW */
	case 55: return 15;	/* PIRQX */
	default: return -1;
	};
}

void setup_pch_lp_gpios(const struct pch_lp_gpio_map map[])
{
	u16 gpio_base = get_gpio_base();
	const struct pch_lp_gpio_map *config;
	u32 owner[3] = {0};
	u32 route[3] = {0};
	u32 irqen[3] = {0};
	u32 reset[3] = {0};
	u32 blink = 0;
	u16 pirq2apic = 0;
	int set, bit, gpio = 0;

	for (config = map; config->conf0 != GPIO_LIST_END; config++, gpio++) {
		if (gpio > MAX_GPIO_NUMBER)
			break;

		/* Setup Configuration registers 1 and 2 */
		outl(config->conf0, gpio_base + GPIO_CONFIG0(gpio));
		outl(config->conf1, gpio_base + GPIO_CONFIG1(gpio));

		/* Determine set and bit based on GPIO number */
		set = gpio >> 5;
		bit = gpio % 32;

		/* Apply settings to set specific bits */
		owner[set] |= config->owner << bit;
		route[set] |= config->route << bit;
		irqen[set] |= config->irqen << bit;
		reset[set] |= config->reset << bit;

		if (set == 0)
			blink |= config->blink << bit;

		/* PIRQ to IO-APIC map */
		if (config->pirq == GPIO_PIRQ_APIC_ROUTE) {
			set = lp_gpio_to_pirq(gpio);
			if (set >= 0)
				pirq2apic |= 1 << set;
		}
	}

	for (set = 0; set <= 2; set++) {
		outl(owner[set], gpio_base + GPIO_OWNER(set));
		outl(route[set], gpio_base + GPIO_ROUTE(set));
		outl(irqen[set], gpio_base + GPIO_IRQ_IE(set));
		outl(reset[set], gpio_base + GPIO_RESET(set));
	}

	outl(blink, gpio_base + GPIO_BLINK);
	outl(pirq2apic, gpio_base + GPIO_PIRQ_APIC_EN);
}

int get_gpio(int gpio_num)
{
	u16 gpio_base = get_gpio_base();

	if (gpio_num > MAX_GPIO_NUMBER)
		return 0;

	return !!(inl(gpio_base + GPIO_CONFIG0(gpio_num)) & GPI_LEVEL);
}

/*
 * get a number comprised of multiple GPIO values. gpio_num_array points to
 * the array of gpio pin numbers to scan, terminated by -1.
 */
unsigned get_gpios(const int *gpio_num_array)
{
	int gpio;
	unsigned bitmask = 1;
	unsigned vector = 0;

	while (bitmask &&
	       ((gpio = *gpio_num_array++) != -1)) {
		if (get_gpio(gpio))
			vector |= bitmask;
		bitmask <<= 1;
	}
	return vector;
}

void set_gpio(int gpio_num, int value)
{
	u16 gpio_base = get_gpio_base();
	u32 conf0;

	if (gpio_num > MAX_GPIO_NUMBER)
		return;

	conf0 = inl(gpio_base + GPIO_CONFIG0(gpio_num));
	conf0 &= ~GPO_LEVEL_MASK;
	conf0 |= value << GPO_LEVEL_SHIFT;
	outl(conf0, gpio_base + GPIO_CONFIG0(gpio_num));
}

int gpio_is_native(int gpio_num)
{
	u16 gpio_base = get_gpio_base();

	return !(inl(gpio_base + GPIO_CONFIG0(gpio_num)) & 1);
}
