/*
 * 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.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation.
 */

#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;
}
