/*
 * Copyright (C) Freescale Semiconductor, Inc. 2007
 *
 * Author: Scott Wood <scottwood@freescale.com>,
 * with some bits from older board-specific PCI initialization.
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * 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.
 *
 * 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., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <common.h>
#include <pci.h>

#if defined(CONFIG_OF_LIBFDT)
#include <libfdt.h>
#include <fdt_support.h>
#endif

#include <asm/mpc8349_pci.h>

#define MAX_BUSES 2

DECLARE_GLOBAL_DATA_PTR;

static struct pci_controller pci_hose[MAX_BUSES];
static int pci_num_buses;

static void pci_init_bus(int bus, struct pci_region *reg)
{
	volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
	volatile pot83xx_t *pot = immr->ios.pot;
	volatile pcictrl83xx_t *pci_ctrl = &immr->pci_ctrl[bus];
	struct pci_controller *hose = &pci_hose[bus];
	u32 dev;
	u16 reg16;
	int i;

	if (bus == 1)
		pot += 3;

	/* Setup outbound translation windows */
	for (i = 0; i < 3; i++, reg++, pot++) {
		if (reg->size == 0)
			break;

		hose->regions[i] = *reg;
		hose->region_count++;

		pot->potar = reg->bus_start >> 12;
		pot->pobar = reg->phys_start >> 12;
		pot->pocmr = ~(reg->size - 1) >> 12;

		if (reg->flags & PCI_REGION_IO)
			pot->pocmr |= POCMR_IO;
#ifdef CONFIG_83XX_PCI_STREAMING
		else if (reg->flags & PCI_REGION_PREFETCH)
			pot->pocmr |= POCMR_SE;
#endif

		if (bus == 1)
			pot->pocmr |= POCMR_DST;

		pot->pocmr |= POCMR_EN;
	}

	/* Point inbound translation at RAM */
	pci_ctrl->pitar1 = 0;
	pci_ctrl->pibar1 = 0;
	pci_ctrl->piebar1 = 0;
	pci_ctrl->piwar1 = PIWAR_EN | PIWAR_PF | PIWAR_RTT_SNOOP |
	                   PIWAR_WTT_SNOOP | (__ilog2(gd->ram_size - 1));

	i = hose->region_count++;
	hose->regions[i].bus_start = 0;
	hose->regions[i].phys_start = 0;
	hose->regions[i].size = gd->ram_size;
	hose->regions[i].flags = PCI_REGION_MEM | PCI_REGION_MEMORY;

	hose->first_busno = 0;
	hose->last_busno = 0xff;

	pci_setup_indirect(hose, CONFIG_SYS_IMMR + 0x8300 + bus * 0x80,
	                         CONFIG_SYS_IMMR + 0x8304 + bus * 0x80);

	pci_register_hose(hose);

	/*
	 * Write to Command register
	 */
	reg16 = 0xff;
	dev = PCI_BDF(hose->first_busno, 0, 0);
	pci_hose_read_config_word(hose, dev, PCI_COMMAND, &reg16);
	reg16 |= PCI_COMMAND_SERR | PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
	pci_hose_write_config_word(hose, dev, PCI_COMMAND, reg16);

	/*
	 * Clear non-reserved bits in status register.
	 */
	pci_hose_write_config_word(hose, dev, PCI_STATUS, 0xffff);
	pci_hose_write_config_byte(hose, dev, PCI_LATENCY_TIMER, 0x80);
	pci_hose_write_config_byte(hose, dev, PCI_CACHE_LINE_SIZE, 0x08);

#ifdef CONFIG_PCI_SCAN_SHOW
	printf("PCI:   Bus Dev VenId DevId Class Int\n");
#endif
	/*
	 * Hose scan.
	 */
	hose->last_busno = pci_hose_scan(hose);
}

/*
 * The caller must have already set OCCR, and the PCI_LAW BARs
 * must have been set to cover all of the requested regions.
 *
 * If fewer than three regions are requested, then the region
 * list is terminated with a region of size 0.
 */
void mpc83xx_pci_init(int num_buses, struct pci_region **reg, int warmboot)
{
	volatile immap_t *immr = (volatile immap_t *)CONFIG_SYS_IMMR;
	int i;

	if (num_buses > MAX_BUSES) {
		printf("%d PCI buses requsted, %d supported\n",
		       num_buses, MAX_BUSES);

		num_buses = MAX_BUSES;
	}

	pci_num_buses = num_buses;

	/*
	 * Release PCI RST Output signal.
	 * Power on to RST high must be at least 100 ms as per PCI spec.
	 * On warm boots only 1 ms is required.
	 */
	udelay(warmboot ? 1000 : 100000);

	for (i = 0; i < num_buses; i++)
		immr->pci_ctrl[i].gcr = 1;

	/*
	 * RST high to first config access must be at least 2^25 cycles
	 * as per PCI spec.  This could be cut in half if we know we're
	 * running at 66MHz.  This could be insufficiently long if we're
	 * running the PCI bus at significantly less than 33MHz.
	 */
	udelay(1020000);

	for (i = 0; i < num_buses; i++)
		pci_init_bus(i, reg[i]);
}

#ifdef CONFIG_PCISLAVE

#define PCI_FUNCTION_CONFIG	0x44
#define PCI_FUNCTION_CFG_LOCK	0x20

/*
 * Unlock the configuration bit so that the host system can begin booting
 *
 * This should be used after you have:
 * 1) Called mpc83xx_pci_init()
 * 2) Set up your inbound translation windows to the appropriate size
 */
void mpc83xx_pcislave_unlock(int bus)
{
	struct pci_controller *hose = &pci_hose[bus];
	u32 dev;
	u16 reg16;

	/* Unlock configuration lock in PCI function configuration register */
	dev = PCI_BDF(hose->first_busno, 0, 0);
	pci_hose_read_config_word (hose, dev, PCI_FUNCTION_CONFIG, &reg16);
	reg16 &= ~(PCI_FUNCTION_CFG_LOCK);
	pci_hose_write_config_word (hose, dev, PCI_FUNCTION_CONFIG, reg16);
}
#endif

#if defined(CONFIG_OF_LIBFDT)
void ft_pci_setup(void *blob, bd_t *bd)
{
	int nodeoffset;
	int tmp[2];
	const char *path;

	if (pci_num_buses < 1)
		return;

	nodeoffset = fdt_path_offset(blob, "/aliases");
	if (nodeoffset >= 0) {
		path = fdt_getprop(blob, nodeoffset, "pci0", NULL);
		if (path) {
			tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
			tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
			do_fixup_by_path(blob, path, "bus-range",
				&tmp, sizeof(tmp), 1);

			tmp[0] = cpu_to_be32(gd->pci_clk);
			do_fixup_by_path(blob, path, "clock-frequency",
				&tmp, sizeof(tmp[0]), 1);
		}

		if (pci_num_buses < 2)
			return;

		path = fdt_getprop(blob, nodeoffset, "pci1", NULL);
		if (path) {
			tmp[0] = cpu_to_be32(pci_hose[0].first_busno);
			tmp[1] = cpu_to_be32(pci_hose[0].last_busno);
			do_fixup_by_path(blob, path, "bus-range",
				&tmp, sizeof(tmp), 1);

			tmp[0] = cpu_to_be32(gd->pci_clk);
			do_fixup_by_path(blob, path, "clock-frequency",
				&tmp, sizeof(tmp[0]), 1);
		}
	}
}
#endif /* CONFIG_OF_LIBFDT */
