/*
 * This file is part of the coreboot project.
 *
 * Copyright (C) 2017 Intel Corp.
 *
 * 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.
 */
#include <assert.h>
#include <intelblocks/gpio.h>
#include <gpio.h>
#include <intelblocks/itss.h>
#include <intelblocks/pcr.h>
#include <soc/pm.h>
#include <types.h>

#define GPIO_DWx_SIZE(x)	(sizeof(uint32_t) * (x))
#define PAD_CFG_OFFSET(x, dw_num)	((x) + GPIO_DWx_SIZE(dw_num))
#define PAD_CFG0_OFFSET(x)	PAD_CFG_OFFSET(x, 0)
#define PAD_CFG1_OFFSET(x)	PAD_CFG_OFFSET(x, 1)
#define PAD_CFG2_OFFSET(x)	PAD_CFG_OFFSET(x, 2)
#define PAD_CFG3_OFFSET(x)	PAD_CFG_OFFSET(x, 3)

#define PAD_DW0_MASK	(PAD_CFG0_TX_STATE |				\
	PAD_CFG0_TX_DISABLE | PAD_CFG0_RX_DISABLE | PAD_CFG0_MODE_MASK |\
	PAD_CFG0_ROUTE_MASK | PAD_CFG0_RXTENCFG_MASK |			\
	PAD_CFG0_RXINV_MASK | PAD_CFG0_PREGFRXSEL |			\
	PAD_CFG0_TRIG_MASK | PAD_CFG0_RXRAW1_MASK |			\
	PAD_CFG0_RXPADSTSEL_MASK | PAD_CFG0_RESET_MASK)

#if IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_GPIO_PADCFG_PADTOL)
#define PAD_DW1_MASK	(PAD_CFG1_IOSTERM_MASK |			\
			PAD_CFG1_PULL_MASK |				\
			PAD_CFG1_TOL_MASK |				\
			PAD_CFG1_IOSSTATE_MASK)
#else
#define PAD_DW1_MASK	(PAD_CFG1_IOSTERM_MASK |			\
			PAD_CFG1_PULL_MASK |				\
			PAD_CFG1_IOSSTATE_MASK)
#endif

#define PAD_DW2_MASK	(PAD_CFG2_DEBOUNCE_MASK)
#define PAD_DW3_MASK	(0)

#define MISCCFG_GPE0_DW0_SHIFT 8
#define MISCCFG_GPE0_DW0_MASK (0xf << MISCCFG_GPE0_DW0_SHIFT)
#define MISCCFG_GPE0_DW1_SHIFT 12
#define MISCCFG_GPE0_DW1_MASK (0xf << MISCCFG_GPE0_DW1_SHIFT)
#define MISCCFG_GPE0_DW2_SHIFT 16
#define MISCCFG_GPE0_DW2_MASK (0xf << MISCCFG_GPE0_DW2_SHIFT)

#define GPI_SMI_STS_OFFSET(comm, group) ((comm)->gpi_smi_sts_reg_0 +	\
				((group) * sizeof(uint32_t)))
#define GPI_SMI_EN_OFFSET(comm, group) ((comm)->gpi_smi_en_reg_0 +	\
				((group) * sizeof(uint32_t)))

static inline size_t relative_pad_in_comm(const struct pad_community *comm,
						gpio_t gpio)
{
	return gpio - comm->first_pad;
}

/* find the group within the community that the pad is a part of */
static inline size_t gpio_group_index(const struct pad_community *comm,
					unsigned int relative_pad)
{
	size_t i;

	if (!comm->groups)
		die("Failed to get comm->groups.");

	/* find the base pad number for this pad's group */
	for (i = 0; i < comm->num_groups; i++) {
		if (relative_pad >= comm->groups[i].first_pad &&
			relative_pad < comm->groups[i].first_pad +
			comm->groups[i].size) {
			return i;
		}
	}

	assert(0);

	return i;
}

static inline size_t gpio_group_index_scaled(const struct pad_community *comm,
					unsigned int relative_pad, size_t scale)
{
	return gpio_group_index(comm, relative_pad) * scale;
}

static inline size_t gpio_within_group(const struct pad_community *comm,
						unsigned int relative_pad)
{
	size_t i;

	i = gpio_group_index(comm, relative_pad);

	return relative_pad - comm->groups[i].first_pad;
}

static inline uint32_t gpio_bitmask_within_group(
					const struct pad_community *comm,
					unsigned int relative_pad)
{
	return 1U << gpio_within_group(comm, relative_pad);
}

static const struct pad_community *gpio_get_community(gpio_t pad)
{
	size_t gpio_communities;
	size_t i;
	const struct pad_community *comm;
	comm = soc_gpio_get_community(&gpio_communities);
	for (i = 0; i < gpio_communities; i++, comm++) {
		if (pad >= comm->first_pad && pad <= comm->last_pad)
			return comm;
	}
	printk(BIOS_ERR, "%s pad %d not found\n", __func__, pad);
	die("Invalid GPIO pad number\n");
	return NULL;
}

static void gpio_configure_owner(const struct pad_config *cfg,
				const struct pad_community *comm)
{
	uint32_t hostsw_own;
	uint16_t hostsw_own_offset;
	int pin;

	pin = relative_pad_in_comm(comm, cfg->pad);

	/* Based on the gpio pin number configure the corresponding bit in
	 * HOSTSW_OWN register. Value of 0x1 indicates GPIO Driver onwership.
	 */
	hostsw_own_offset = comm->host_own_reg_0;
	hostsw_own_offset += gpio_group_index_scaled(comm, pin,
		sizeof(uint32_t));

	hostsw_own = pcr_read32(comm->port, hostsw_own_offset);

	/* The 4th bit in pad_config 1 (RO) is used to indicate if the pad
	 * needs GPIO driver ownership.  Set the bit if GPIO driver ownership
	 * requested, otherwise clear the bit.
	 */
	if (cfg->pad_config[1] & PAD_CFG1_GPIO_DRIVER)
		hostsw_own |= gpio_bitmask_within_group(comm, pin);
	else
		hostsw_own &= ~gpio_bitmask_within_group(comm, pin);

	pcr_write32(comm->port, hostsw_own_offset, hostsw_own);
}

static void gpi_enable_smi(const struct pad_config *cfg,
				const struct pad_community *comm)
{
	uint32_t value;
	uint16_t sts_reg;
	uint16_t en_reg;
	int group;
	int pin;

	if (((cfg->pad_config[0]) & PAD_CFG0_ROUTE_SMI) != PAD_CFG0_ROUTE_SMI)
		return;

	pin = relative_pad_in_comm(comm, cfg->pad);
	group = gpio_group_index(comm, pin);

	sts_reg = GPI_SMI_STS_OFFSET(comm, group);
	value = pcr_read32(comm->port, sts_reg);
	/* Write back 1 to reset the sts bits */
	pcr_write32(comm->port, sts_reg, value);

	/* Set enable bits */
	en_reg = GPI_SMI_EN_OFFSET(comm, group);
	pcr_or32(comm->port, en_reg, gpio_bitmask_within_group(comm, pin));
}

static void gpio_configure_itss(const struct pad_config *cfg, uint16_t port,
	uint16_t  pad_cfg_offset)
{
	/* No ITSS configuration in SMM. */
	if (ENV_SMM)
		return;

	if (!IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_GPIO_ITSS_POL_CFG))
		return;

	int irq;

	/* Set up ITSS polarity if pad is routed to APIC.
	 *
	 * The ITSS takes only active high interrupt signals. Therefore,
	 * if the pad configuration indicates an inversion assume the
	 * intent is for the ITSS polarity. Before forwarding on the
	 * request to the APIC there's an inversion setting for how the
	 * signal is forwarded to the APIC. Honor the inversion setting
	 * in the GPIO pad configuration so that a hardware active low
	 * signal looks that way to the APIC (double inversion).
	 */
	if (!(cfg->pad_config[0] & PAD_CFG0_ROUTE_IOAPIC))
		return;

	irq = pcr_read32(port, PAD_CFG1_OFFSET(pad_cfg_offset));
	irq &= PAD_CFG1_IRQ_MASK;
	if (!irq) {
		printk(BIOS_ERR, "GPIO %u doesn't support APIC routing,\n",
			cfg->pad);
		return;
	}
	itss_set_irq_polarity(irq, !!(cfg->pad_config[0] &
			PAD_CFG0_RX_POL_INVERT));
}

/* Number of DWx config registers can be different for different SOCs */
static uint16_t pad_config_offset(const struct pad_community *comm, gpio_t pad)
{
	size_t offset;

	offset = relative_pad_in_comm(comm, pad);
	offset *= GPIO_DWx_SIZE(GPIO_NUM_PAD_CFG_REGS);
	return offset + comm->pad_cfg_base;
}

static uint32_t gpio_pad_reset_config_override(const struct pad_community *comm,
	uint32_t config_value)
{
	const struct reset_mapping *rst_map = comm->reset_map;
	int i;

	if (rst_map == NULL || comm->num_reset_vals == 0)
		return config_value;/* Logical reset values equal chipset
					values */
	for (i = 0; i < comm->num_reset_vals; i++, rst_map++) {
		if ((config_value & PAD_CFG0_RESET_MASK) == rst_map->logical) {
			config_value &= ~PAD_CFG0_RESET_MASK;
			config_value |= rst_map->chipset;
			return config_value;
		}
	}
	printk(BIOS_ERR, "%s: Logical to Chipset mapping not found\n",
			__func__);
	return config_value;
}

static const int mask[4] = {
	PAD_DW0_MASK, PAD_DW1_MASK, PAD_DW2_MASK, PAD_DW3_MASK
};

static void gpio_configure_pad(const struct pad_config *cfg)
{
	const struct pad_community *comm = gpio_get_community(cfg->pad);
	uint16_t config_offset;
	uint32_t pad_conf, soc_pad_conf;
	int i;

	config_offset = pad_config_offset(comm, cfg->pad);
	for (i = 0; i < GPIO_NUM_PAD_CFG_REGS; i++) {
		pad_conf = pcr_read32(comm->port,
			PAD_CFG_OFFSET(config_offset, i));

		soc_pad_conf = cfg->pad_config[i];
		if (i == 0)
			soc_pad_conf = gpio_pad_reset_config_override(comm,
				soc_pad_conf);
		soc_pad_conf &= mask[i];
		soc_pad_conf |= pad_conf & ~mask[i];

		/* Patch GPIO settings for SoC specifically */
		soc_pad_conf = soc_gpio_pad_config_fixup(cfg, i, soc_pad_conf);

		if (IS_ENABLED(CONFIG_DEBUG_GPIO))
			printk(BIOS_DEBUG,
			"gpio_padcfg [0x%02x, %02zd] DW%d [0x%08x : 0x%08x"
			" : 0x%08x]\n",
			comm->port, relative_pad_in_comm(comm, cfg->pad), i,
			pad_conf,/* old value */
			cfg->pad_config[i],/* value passed from gpio table */
			soc_pad_conf);/*new value*/
		pcr_write32(comm->port, PAD_CFG_OFFSET(config_offset, i),
			soc_pad_conf);
	}
	gpio_configure_itss(cfg, comm->port, config_offset);
	gpio_configure_owner(cfg, comm);
	gpi_enable_smi(cfg, comm);
}

void gpio_configure_pads(const struct pad_config *cfg, size_t num_pads)
{
	size_t i;

	for (i = 0; i < num_pads; i++)
		gpio_configure_pad(cfg + i);
}

/*
 * This functions checks to see if there is an override config present for the
 * provided pad_config. If no override config is present, then the input config
 * is returned. Else, it returns the override config.
 */
static const struct pad_config *gpio_get_config(const struct pad_config *c,
				const struct pad_config *override_cfg_table,
				size_t num)
{
	size_t i;

	if (override_cfg_table == NULL)
		return c;

	for (i = 0; i < num; i++) {
		if (c->pad == override_cfg_table[i].pad)
			return override_cfg_table + i;
	}

	return c;
}

void gpio_configure_pads_with_override(const struct pad_config *base_cfg,
					size_t base_num_pads,
					const struct pad_config *override_cfg,
					size_t override_num_pads)
{
	size_t i;
	const struct pad_config *c;

	for (i = 0; i < base_num_pads; i++) {
		c = gpio_get_config(base_cfg + i, override_cfg,
				override_num_pads);
		gpio_configure_pad(c);
	}
}

void *gpio_dwx_address(const gpio_t pad)
{
	/* Calculate Address of DW0 register for given GPIO
	 * pad - GPIO number
	 * returns - address of GPIO
	 */
	const struct pad_community *comm = gpio_get_community(pad);
	uint16_t config_offset;

	config_offset = pad_config_offset(comm, pad);
	return pcr_reg_address(comm->port, config_offset);
}

uint8_t gpio_get_pad_portid(const gpio_t pad)
{
	/* Get the port id of given pad
	 * pad - GPIO number
	 * returns - given pad port id
	 */
	const struct pad_community *comm = gpio_get_community(pad);
	return comm->port;
}

void gpio_input_pulldown(gpio_t gpio)
{
	struct pad_config cfg = PAD_CFG_GPI(gpio, DN_20K, DEEP);
	gpio_configure_pad(&cfg);
}

void gpio_input_pullup(gpio_t gpio)
{
	struct pad_config cfg = PAD_CFG_GPI(gpio, UP_20K, DEEP);
	gpio_configure_pad(&cfg);
}

void gpio_input(gpio_t gpio)
{
	struct pad_config cfg = PAD_CFG_GPI(gpio, NONE, DEEP);
	gpio_configure_pad(&cfg);
}

void gpio_output(gpio_t gpio, int value)
{
	struct pad_config cfg = PAD_CFG_GPO(gpio, value, DEEP);
	gpio_configure_pad(&cfg);
}

int gpio_get(gpio_t gpio_num)
{
	const struct pad_community *comm = gpio_get_community(gpio_num);
	uint16_t config_offset;
	uint32_t reg;

	config_offset = pad_config_offset(comm, gpio_num);
	reg = pcr_read32(comm->port, config_offset);

	return !!(reg & PAD_CFG0_RX_STATE);
}

void gpio_set(gpio_t gpio_num, int value)
{
	const struct pad_community *comm = gpio_get_community(gpio_num);
	uint16_t config_offset;

	config_offset = pad_config_offset(comm, gpio_num);
	pcr_rmw32(comm->port, config_offset,
		~PAD_CFG0_TX_STATE, (!!value & PAD_CFG0_TX_STATE));
}

uint16_t gpio_acpi_pin(gpio_t gpio_num)
{
	const struct pad_community *comm;
	size_t group, pin;

	if (IS_ENABLED(CONFIG_SOC_INTEL_COMMON_BLOCK_GPIO_MULTI_ACPI_DEVICES))
		return relative_pad_in_comm(gpio_get_community(gpio_num),
					    gpio_num);

	comm = gpio_get_community(gpio_num);
	pin = relative_pad_in_comm(comm, gpio_num);
	group = gpio_group_index(comm, pin);

	/* If pad base is not set then use GPIO number as ACPI pin number. */
	if (comm->groups[group].acpi_pad_base == PAD_BASE_NONE)
		return gpio_num;

	/*
	 * If this group has a non-zero pad base then compute the ACPI pin
	 * number from the pad base and the relative pad in the group.
	 */
	return comm->groups[group].acpi_pad_base + gpio_within_group(comm, pin);
}

static void print_gpi_status(const struct gpi_status *sts)
{
	int i;
	int group;
	int index;
	int bit_set;
	int num_groups;
	int abs_bit;
	size_t gpio_communities;
	const struct pad_community *comm;

	comm = soc_gpio_get_community(&gpio_communities);
	for (i = 0; i < gpio_communities; i++) {
		num_groups = comm->num_gpi_regs;
		index = comm->gpi_status_offset;
		for (group = 0; group < num_groups; group++, index++) {
			for (bit_set = comm->max_pads_per_group - 1;
				bit_set >= 0; bit_set--) {
				if (!(sts->grp[index] & (1 << bit_set)))
					continue;

				abs_bit = bit_set;
				abs_bit += group * comm->max_pads_per_group;
				printk(BIOS_DEBUG, "%s %d\n", comm->name,
								abs_bit);
			}
		}
		comm++;
	}
}

void gpi_clear_get_smi_status(struct gpi_status *sts)
{
	int i;
	int group;
	int index;
	uint32_t sts_value;
	uint32_t en_value;
	size_t gpio_communities;
	int num_groups;
	const struct pad_community *comm;

	comm = soc_gpio_get_community(&gpio_communities);
	for (i = 0; i < gpio_communities; i++) {
		num_groups = comm->num_gpi_regs;
		index = comm->gpi_status_offset;
		for (group = 0; group < num_groups; group++, index++) {
			sts_value = pcr_read32(comm->port,
					GPI_SMI_STS_OFFSET(comm, group));
			en_value = pcr_read32(comm->port,
					GPI_SMI_EN_OFFSET(comm, group));
			sts->grp[index] = sts_value & en_value;
			/* Clear the set status bits. */
			pcr_write32(comm->port, GPI_SMI_STS_OFFSET(comm,
				group), sts->grp[index]);
		}
		comm++;
	}

	if (IS_ENABLED(CONFIG_DEBUG_SMI))
		print_gpi_status(sts);

}

int gpi_status_get(const struct gpi_status *sts, gpio_t pad)
{
	uint8_t sts_index;
	const struct pad_community *comm = gpio_get_community(pad);

	pad = relative_pad_in_comm(comm, pad);
	sts_index = comm->gpi_status_offset;
	sts_index += gpio_group_index(comm, pad);

	return !!(sts->grp[sts_index] & gpio_bitmask_within_group(comm, pad));
}

static int gpio_route_pmc_gpio_gpe(int pmc_gpe_num)
{
	size_t num_routes;
	const struct pmc_to_gpio_route *routes;
	int i;

	routes = soc_pmc_gpio_routes(&num_routes);
	assert (routes != NULL);
	for (i = 0; i < num_routes; i++, routes++) {
		if (pmc_gpe_num == routes->pmc)
			return routes->gpio;
	}
	return -1;
}

void gpio_route_gpe(uint8_t gpe0b, uint8_t gpe0c, uint8_t gpe0d)
{
	int i;
	uint32_t misccfg_mask;
	uint32_t misccfg_value;
	int ret;
	size_t gpio_communities;
	const struct pad_community *comm;

	/* Get the group here for community specific MISCCFG register.
	 * If any of these returns -1 then there is some error in devicetree
	 * where the group is probably hardcoded and does not comply with the
	 * PMC group defines. So we return from here and MISCFG is set to
	 * default.
	 */
	ret = gpio_route_pmc_gpio_gpe(gpe0b);
	if (ret == -1)
		return;
	gpe0b = ret;

	ret = gpio_route_pmc_gpio_gpe(gpe0c);
	if (ret == -1)
		return;
	gpe0c = ret;

	ret = gpio_route_pmc_gpio_gpe(gpe0d);
	if (ret == -1)
		return;
	gpe0d = ret;

	misccfg_value = gpe0b << MISCCFG_GPE0_DW0_SHIFT;
	misccfg_value |= gpe0c << MISCCFG_GPE0_DW1_SHIFT;
	misccfg_value |= gpe0d << MISCCFG_GPE0_DW2_SHIFT;

	/* Program GPIO_MISCCFG */
	misccfg_mask = ~(MISCCFG_GPE0_DW2_MASK |
			MISCCFG_GPE0_DW1_MASK |
			MISCCFG_GPE0_DW0_MASK);

	if (IS_ENABLED(CONFIG_DEBUG_GPIO))
		printk(BIOS_DEBUG, "misccfg_mask:%x misccfg_value:%x\n",
			misccfg_mask, misccfg_value);
	comm = soc_gpio_get_community(&gpio_communities);
	for (i = 0; i < gpio_communities; i++, comm++)
		pcr_rmw32(comm->port, GPIO_MISCCFG,
				misccfg_mask, misccfg_value);
}

const char *gpio_acpi_path(gpio_t gpio_num)
{
	const struct pad_community *comm = gpio_get_community(gpio_num);
	return comm->acpi_path;
}

uint32_t __weak soc_gpio_pad_config_fixup(const struct pad_config *cfg,
						int dw_reg, uint32_t reg_val)
{
	return reg_val;
}
