/* SPDX-License-Identifier: GPL-2.0-only */

#include <device/mmio.h>
#include <device/pci_ops.h>
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <option.h>
#include <acpi/acpi_sata.h>
#include <types.h>

#include "chip.h"
#include "pch.h"

typedef struct southbridge_intel_bd82x6x_config config_t;

static inline u32 sir_read(struct device *dev, int idx)
{
	pci_write_config32(dev, SATA_SIRI, idx);
	return pci_read_config32(dev, SATA_SIRD);
}

static inline void sir_write(struct device *dev, int idx, u32 value)
{
	pci_write_config32(dev, SATA_SIRI, idx);
	pci_write_config32(dev, SATA_SIRD, value);
}

static void sata_read_resources(struct device *dev)
{
	struct resource *res;

	pci_dev_read_resources(dev);

	/* Assign fixed resources for IDE legacy mode */

	u8 sata_mode = get_int_option("sata_mode", 0);
	if (sata_mode != 2)
		return;

	res = probe_resource(dev, PCI_BASE_ADDRESS_0);
	if (res) {
		res->base = 0x1f0;
		res->size = 8;
		res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
	}

	res = probe_resource(dev, PCI_BASE_ADDRESS_1);
	if (res) {
		res->base = 0x3f4;
		res->size = 4;
		res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
	}

	res = probe_resource(dev, PCI_BASE_ADDRESS_2);
	if (res) {
		res->base = 0x170;
		res->size = 8;
		res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
	}

	res = probe_resource(dev, PCI_BASE_ADDRESS_3);
	if (res) {
		res->base = 0x374;
		res->size = 4;
		res->flags = IORESOURCE_IO | IORESOURCE_ASSIGNED | IORESOURCE_FIXED;
	}
}

static void sata_set_resources(struct device *dev)
{
	/* work around bug in pci_dev_set_resources(), it bails out on FIXED */
	u8 sata_mode = get_int_option("sata_mode", 0);
	if (sata_mode == 2) {
		unsigned int i;
		for (i = PCI_BASE_ADDRESS_0; i <= PCI_BASE_ADDRESS_3; i += 4) {
			struct resource *const res = probe_resource(dev, i);
			if (res)
				res->flags &= ~IORESOURCE_FIXED;
		}
	}

	pci_dev_set_resources(dev);
}

static void sata_init(struct device *dev)
{
	u32 reg32;
	u16 reg16;
	/* Get the chip configuration */
	config_t *config = dev->chip_info;

	printk(BIOS_DEBUG, "SATA: Initializing...\n");

	if (config == NULL) {
		printk(BIOS_ERR, "SATA: ERROR: Device not in devicetree.cb!\n");
		return;
	}

	/* Default to AHCI */
	u8 sata_mode = get_int_option("sata_mode", 0);

	/* SATA configuration */

	/* Enable BARs */
	pci_write_config16(dev, PCI_COMMAND,
			   PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO);

	/* AHCI */
	if (sata_mode == 0) {
		u8 *abar;

		printk(BIOS_DEBUG, "SATA: Controller in AHCI mode.\n");

		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE);
		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE);

		/* for AHCI, Port Enable is managed in memory mapped space */
		reg16 = pci_read_config16(dev, 0x92);
		reg16 &= ~0x3f; /* 6 ports SKU + ORM */
		reg16 |= 0x8000 | config->sata_port_map;
		pci_write_config16(dev, 0x92, reg16);

		/* SATA Initialization register */
		pci_write_config32(dev, 0x94, ((config->sata_port_map ^ 0x3f) << 24) | 0x183);

		/* Initialize AHCI memory-mapped space */
		abar = (u8 *)pci_read_config32(dev, PCI_BASE_ADDRESS_5);
		printk(BIOS_DEBUG, "ABAR: %p\n", abar);
		/* CAP (HBA Capabilities) : enable power management */
		reg32 = read32(abar + 0x00);
		reg32 |= 0x0c006000;  // set PSC+SSC+SALP+SSS
		reg32 &= ~0x00020060; // clear SXS+EMS+PMS
		/* Set ISS, if available */
		if (config->sata_interface_speed_support)
		{
			reg32 &= ~0x00f00000;
			reg32 |= (config->sata_interface_speed_support & 0x03)
			  << 20;
		}
		write32(abar + 0x00, reg32);
		/* PI (Ports implemented) */
		write32(abar + 0x0c, config->sata_port_map);
		(void) read32(abar + 0x0c); /* Read back 1 */
		(void) read32(abar + 0x0c); /* Read back 2 */
		/* CAP2 (HBA Capabilities Extended)*/
		reg32 = read32(abar + 0x24);
		reg32 &= ~0x00000002;
		write32(abar + 0x24, reg32);
		/* VSP (Vendor Specific Register */
		reg32 = read32(abar + 0xa0);
		reg32 &= ~0x00000005;
		write32(abar + 0xa0, reg32);
	} else {
	        /* IDE */

		/* Without AHCI BAR no memory decoding */
		pci_and_config16(dev, PCI_COMMAND, ~PCI_COMMAND_MEMORY);

		if (sata_mode == 1) {
			/* Native mode on both primary and secondary. */
			pci_or_config8(dev, 0x09, 0x05);
			printk(BIOS_DEBUG, "SATA: Controller in IDE compat mode.\n");
		} else {
			/* Legacy mode on both primary and secondary. */
			pci_and_config8(dev, 0x09, ~0x05);
			printk(BIOS_DEBUG, "SATA: Controller in IDE legacy mode.\n");
		}

		/* Enable I/O decoding */
		pci_write_config16(dev, IDE_TIM_PRI, IDE_DECODE_ENABLE);
		pci_write_config16(dev, IDE_TIM_SEC, IDE_DECODE_ENABLE);

		/* Port enable + OOB retry mode */
		pci_update_config16(dev, 0x92, ~0x3f, config->sata_port_map | 0x8000);

		/* SATA Initialization register */
		pci_write_config32(dev, 0x94, ((config->sata_port_map ^ 0x3f) << 24) | 0x183);
	}

	/* Set Gen3 Transmitter settings if needed */
	if (config->sata_port0_gen3_tx)
		pch_iobp_update(SATA_IOBP_SP0G3IR, 0,
				config->sata_port0_gen3_tx);

	if (config->sata_port1_gen3_tx)
		pch_iobp_update(SATA_IOBP_SP1G3IR, 0,
				config->sata_port1_gen3_tx);

	/* Additional Programming Requirements */
	sir_write(dev, 0x04, 0x00001600);
	sir_write(dev, 0x28, 0xa0000033);
	reg32 = sir_read(dev, 0x54);
	reg32 &= 0xff000000;
	reg32 |= 0x5555aa;
	sir_write(dev, 0x54, reg32);
	sir_write(dev, 0x64, 0xcccc8484);
	reg32 = sir_read(dev, 0x68);
	reg32 &= 0xffff0000;
	reg32 |= 0xcccc;
	sir_write(dev, 0x68, reg32);
	reg32 = sir_read(dev, 0x78);
	reg32 &= 0x0000ffff;
	reg32 |= 0x88880000;
	sir_write(dev, 0x78, reg32);
	sir_write(dev, 0x84, 0x001c7000);
	sir_write(dev, 0x88, 0x88338822);
	sir_write(dev, 0xa0, 0x001c7000);
	// a4
	sir_write(dev, 0xc4, 0x0c0c0c0c);
	sir_write(dev, 0xc8, 0x0c0c0c0c);
	sir_write(dev, 0xd4, 0x10000000);

	pch_iobp_update(0xea004001, 0x3fffffff, 0xc0000000);
	pch_iobp_update(0xea00408a, 0xfffffcff, 0x00000100);

	pci_update_config32(dev, 0x98,
		~(1 << 16 | 0x3f << 7 | 3 << 5 | 3 << 3),
		1 << 24 | 1 << 22 | 1 << 20 | 1 << 19 |
		1 << 18 | 1 << 14 | 0x04 << 7 | 1 << 3);
}

static void sata_enable(struct device *dev)
{
	/* Get the chip configuration */
	config_t *config = dev->chip_info;
	u16 map = 0;

	if (!config)
		return;

	u8 sata_mode = get_int_option("sata_mode", 0);

	/*
	 * Set SATA controller mode early so the resource allocator can
	 * properly assign IO/Memory resources for the controller.
	 */
	if (sata_mode == 0)
		map = 0x0060;

	map |= (config->sata_port_map ^ 0x3f) << 8;

	pci_write_config16(dev, 0x90, map);
}

static const char *sata_acpi_name(const struct device *dev)
{
	return "SATA";
}

static void sata_fill_ssdt(const struct device *dev)
{
	config_t *config = dev->chip_info;
	generate_sata_ssdt_ports("\\_SB_.PCI0.SATA", config->sata_port_map);
}

static struct device_operations sata_ops = {
	.read_resources		= sata_read_resources,
	.set_resources		= sata_set_resources,
	.enable_resources	= pci_dev_enable_resources,
	.acpi_fill_ssdt		= sata_fill_ssdt,
	.init			= sata_init,
	.enable			= sata_enable,
	.ops_pci		= &pci_dev_ops_pci,
	.acpi_name		= sata_acpi_name,
};

static const unsigned short pci_device_ids[] = { 0x1c00, 0x1c01, 0x1c02, 0x1c03,
						 0x1e00, 0x1e01, 0x1e02, 0x1e03,
						 0 };

static const struct pci_driver pch_sata __pci_driver = {
	.ops	 = &sata_ops,
	.vendor	 = PCI_VENDOR_ID_INTEL,
	.devices = pci_device_ids,
};
