// SPDX-License-Identifier: GPL-2.0-only
/*
 * Old U-boot compatibility for PowerQUICC II
 * (a.k.a. 82xx with CPM, not the 8240 family of chips)
 *
 * Author: Scott Wood <scottwood@freescale.com>
 *
 * Copyright (c) 2007 Freescale Semiconductor, Inc.
 */

#include "ops.h"
#include "stdio.h"
#include "cuboot.h"
#include "io.h"
#include "fsl-soc.h"

#define TARGET_CPM2
#define TARGET_HAS_ETH1
#include "ppcboot.h"

static bd_t bd;

struct cs_range {
	u32 csnum;
	u32 base; /* must be zero */
	u32 addr;
	u32 size;
};

struct pci_range {
	u32 flags;
	u32 pci_addr[2];
	u32 phys_addr;
	u32 size[2];
};

struct cs_range cs_ranges_buf[MAX_PROP_LEN / sizeof(struct cs_range)];
struct pci_range pci_ranges_buf[MAX_PROP_LEN / sizeof(struct pci_range)];

/* Different versions of u-boot put the BCSR in different places, and
 * some don't set up the PCI PIC at all, so we assume the device tree is
 * sane and update the BRx registers appropriately.
 *
 * For any node defined as compatible with fsl,pq2-localbus,
 * #address/#size must be 2/1 for the localbus, and 1/1 for the parent bus.
 * Ranges must be for whole chip selects.
 */
static void update_cs_ranges(void)
{
	void *bus_node, *parent_node;
	u32 *ctrl_addr;
	unsigned long ctrl_size;
	u32 naddr, nsize;
	int len;
	int i;

	bus_node = finddevice("/localbus");
	if (!bus_node || !dt_is_compatible(bus_node, "fsl,pq2-localbus"))
		return;

	dt_get_reg_format(bus_node, &naddr, &nsize);
	if (naddr != 2 || nsize != 1)
		goto err;

	parent_node = get_parent(bus_node);
	if (!parent_node)
		goto err;

	dt_get_reg_format(parent_node, &naddr, &nsize);
	if (naddr != 1 || nsize != 1)
		goto err;

	if (!dt_xlate_reg(bus_node, 0, (unsigned long *)&ctrl_addr,
	                  &ctrl_size))
		goto err;

	len = getprop(bus_node, "ranges", cs_ranges_buf, sizeof(cs_ranges_buf));

	for (i = 0; i < len / sizeof(struct cs_range); i++) {
		u32 base, option;
		int cs = cs_ranges_buf[i].csnum;
		if (cs >= ctrl_size / 8)
			goto err;

		if (cs_ranges_buf[i].base != 0)
			goto err;

		base = in_be32(&ctrl_addr[cs * 2]);

		/* If CS is already valid, use the existing flags.
		 * Otherwise, guess a sane default.
		 */
		if (base & 1) {
			base &= 0x7fff;
			option = in_be32(&ctrl_addr[cs * 2 + 1]) & 0x7fff;
		} else {
			base = 0x1801;
			option = 0x10;
		}

		out_be32(&ctrl_addr[cs * 2], 0);
		out_be32(&ctrl_addr[cs * 2 + 1],
		         option | ~(cs_ranges_buf[i].size - 1));
		out_be32(&ctrl_addr[cs * 2], base | cs_ranges_buf[i].addr);
	}

	return;

err:
	printf("Bad /localbus node\r\n");
}

/* Older u-boots don't set PCI up properly.  Update the hardware to match
 * the device tree.  The prefetch mem region and non-prefetch mem region
 * must be contiguous in the host bus.  As required by the PCI binding,
 * PCI #addr/#size must be 3/2.  The parent bus must be 1/1.  Only
 * 32-bit PCI is supported.  All three region types (prefetchable mem,
 * non-prefetchable mem, and I/O) must be present.
 */
static void fixup_pci(void)
{
	struct pci_range *mem = NULL, *mmio = NULL,
	                 *io = NULL, *mem_base = NULL;
	u32 *pci_regs[3];
	u8 *soc_regs;
	int i, len;
	void *node, *parent_node;
	u32 naddr, nsize, mem_pow2, mem_mask;

	node = finddevice("/pci");
	if (!node || !dt_is_compatible(node, "fsl,pq2-pci"))
		return;

	for (i = 0; i < 3; i++)
		if (!dt_xlate_reg(node, i,
		                  (unsigned long *)&pci_regs[i], NULL))
			goto err;

	soc_regs = (u8 *)fsl_get_immr();
	if (!soc_regs)
		goto unhandled;

	dt_get_reg_format(node, &naddr, &nsize);
	if (naddr != 3 || nsize != 2)
		goto err;

	parent_node = get_parent(node);
	if (!parent_node)
		goto err;

	dt_get_reg_format(parent_node, &naddr, &nsize);
	if (naddr != 1 || nsize != 1)
		goto unhandled;

	len = getprop(node, "ranges", pci_ranges_buf,
	              sizeof(pci_ranges_buf));

	for (i = 0; i < len / sizeof(struct pci_range); i++) {
		u32 flags = pci_ranges_buf[i].flags & 0x43000000;

		if (flags == 0x42000000)
			mem = &pci_ranges_buf[i];
		else if (flags == 0x02000000)
			mmio = &pci_ranges_buf[i];
		else if (flags == 0x01000000)
			io = &pci_ranges_buf[i];
	}

	if (!mem || !mmio || !io)
		goto unhandled;
	if (mem->size[1] != mmio->size[1])
		goto unhandled;
	if (mem->size[1] & (mem->size[1] - 1))
		goto unhandled;
	if (io->size[1] & (io->size[1] - 1))
		goto unhandled;

	if (mem->phys_addr + mem->size[1] == mmio->phys_addr)
		mem_base = mem;
	else if (mmio->phys_addr + mmio->size[1] == mem->phys_addr)
		mem_base = mmio;
	else
		goto unhandled;

	out_be32(&pci_regs[1][0], mem_base->phys_addr | 1);
	out_be32(&pci_regs[2][0], ~(mem->size[1] + mmio->size[1] - 1));

	out_be32(&pci_regs[1][1], io->phys_addr | 1);
	out_be32(&pci_regs[2][1], ~(io->size[1] - 1));

	out_le32(&pci_regs[0][0], mem->pci_addr[1] >> 12);
	out_le32(&pci_regs[0][2], mem->phys_addr >> 12);
	out_le32(&pci_regs[0][4], (~(mem->size[1] - 1) >> 12) | 0xa0000000);

	out_le32(&pci_regs[0][6], mmio->pci_addr[1] >> 12);
	out_le32(&pci_regs[0][8], mmio->phys_addr >> 12);
	out_le32(&pci_regs[0][10], (~(mmio->size[1] - 1) >> 12) | 0x80000000);

	out_le32(&pci_regs[0][12], io->pci_addr[1] >> 12);
	out_le32(&pci_regs[0][14], io->phys_addr >> 12);
	out_le32(&pci_regs[0][16], (~(io->size[1] - 1) >> 12) | 0xc0000000);

	/* Inbound translation */
	out_le32(&pci_regs[0][58], 0);
	out_le32(&pci_regs[0][60], 0);

	mem_pow2 = 1 << (__ilog2_u32(bd.bi_memsize - 1) + 1);
	mem_mask = ~(mem_pow2 - 1) >> 12;
	out_le32(&pci_regs[0][62], 0xa0000000 | mem_mask);

	/* If PCI is disabled, drive RST high to enable. */
	if (!(in_le32(&pci_regs[0][32]) & 1)) {
		 /* Tpvrh (Power valid to RST# high) 100 ms */
		udelay(100000);

		out_le32(&pci_regs[0][32], 1);

		/* Trhfa (RST# high to first cfg access) 2^25 clocks */
		udelay(1020000);
	}

	/* Enable bus master and memory access */
	out_le32(&pci_regs[0][64], 0x80000004);
	out_le32(&pci_regs[0][65], in_le32(&pci_regs[0][65]) | 6);

	/* Park the bus on PCI, and elevate PCI's arbitration priority,
	 * as required by section 9.6 of the user's manual.
	 */
	out_8(&soc_regs[0x10028], 3);
	out_be32((u32 *)&soc_regs[0x1002c], 0x01236745);

	return;

err:
	printf("Bad PCI node -- using existing firmware setup.\r\n");
	return;

unhandled:
	printf("Unsupported PCI node -- using existing firmware setup.\r\n");
}

static void pq2_platform_fixups(void)
{
	void *node;

	dt_fixup_memory(bd.bi_memstart, bd.bi_memsize);
	dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr);
	dt_fixup_cpu_clocks(bd.bi_intfreq, bd.bi_busfreq / 4, bd.bi_busfreq);

	node = finddevice("/soc/cpm");
	if (node)
		setprop(node, "clock-frequency", &bd.bi_cpmfreq, 4);

	node = finddevice("/soc/cpm/brg");
	if (node)
		setprop(node, "clock-frequency",  &bd.bi_brgfreq, 4);

	update_cs_ranges();
	fixup_pci();
}

void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,
                   unsigned long r6, unsigned long r7)
{
	CUBOOT_INIT();
	fdt_init(_dtb_start);
	serial_console_init();
	platform_ops.fixups = pq2_platform_fixups;
}
