/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2014 Google Inc.
 *
 * 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.
 *
 * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */

#include <stdint.h>
#include <string.h>
#include <arch/io.h>
#include <device/device.h>
#include <device/pci.h>
#include <broadwell/gpio.h>
#include <broadwell/iomap.h>
#include <broadwell/pm.h>

/*
 * 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 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 init_one_gpio(int gpio_num, struct gpio_config *config)
{
	u32 owner, route, irqen, reset;
	int set, bit;

	if (gpio_num > MAX_GPIO_NUMBER || !config)
		return;

	outl(config->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num));
	outl(config->conf1, GPIO_BASE_ADDRESS + GPIO_CONFIG1(gpio_num));

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

	/* Save settings from current GPIO config */
	owner = inl(GPIO_BASE_ADDRESS + GPIO_OWNER(set));
	route = inl(GPIO_BASE_ADDRESS + GPIO_ROUTE(set));
	irqen = inl(GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set));
	reset = inl(GPIO_BASE_ADDRESS + GPIO_RESET(set));

	owner |= config->owner << bit;
	route |= config->route << bit;
	irqen |= config->irqen << bit;
	reset |= config->reset << bit;

	outl(owner, GPIO_BASE_ADDRESS + GPIO_OWNER(set));
	outl(route, GPIO_BASE_ADDRESS + GPIO_ROUTE(set));
	outl(irqen, GPIO_BASE_ADDRESS + GPIO_IRQ_IE(set));
	outl(reset, GPIO_BASE_ADDRESS + GPIO_RESET(set));

	if (set == 0) {
		u32 blink = inl(GPIO_BASE_ADDRESS + GPIO_BLINK);
		blink |= config->blink << bit;
		outl(blink, GPIO_BASE_ADDRESS + GPIO_BLINK);
	}

	/* PIRQ to IO-APIC map */
	if (config->pirq == GPIO_PIRQ_APIC_ROUTE) {
		u32 pirq2apic = inl(GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN);
		set = gpio_to_pirq(gpio_num);
		if (set >= 0) {
			pirq2apic |= 1 << set;
			outl(pirq2apic, GPIO_BASE_ADDRESS + GPIO_PIRQ_APIC_EN);
		}
	}
}

void init_gpios(const struct gpio_config config[])
{
	const struct gpio_config *entry;
	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 (entry = config; entry->conf0 != GPIO_LIST_END; entry++, gpio++) {
		if (gpio > MAX_GPIO_NUMBER)
			break;

		/* Setup Configuration registers 1 and 2 */
		outl(entry->conf0, GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio));
		outl(entry->conf1, GPIO_BASE_ADDRESS + 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] |= entry->owner << bit;
		route[set] |= entry->route << bit;
		irqen[set] |= entry->irqen << bit;
		reset[set] |= entry->reset << bit;

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

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

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

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

int get_gpio(int gpio_num)
{
	if (gpio_num > MAX_GPIO_NUMBER)
		return 0;

	return !!(inl(GPIO_BASE_ADDRESS + 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)
{
	u32 conf0;

	if (gpio_num > MAX_GPIO_NUMBER)
		return;

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

int gpio_is_native(int gpio_num)
{
	return !(inl(GPIO_BASE_ADDRESS + GPIO_CONFIG0(gpio_num)) & 1);
}
