/*
 * Broadcom specific AMBA
 * Broadcom MIPS32 74K core driver
 *
 * Copyright 2009, Broadcom Corporation
 * Copyright 2006, 2007, Michael Buesch <mb@bu3sch.de>
 * Copyright 2010, Bernhard Loos <bernhardloos@googlemail.com>
 * Copyright 2011, Hauke Mehrtens <hauke@hauke-m.de>
 *
 * Licensed under the GNU/GPL. See COPYING for details.
 */

#include "bcma_private.h"

#include <linux/bcma/bcma.h>

#include <linux/serial.h>
#include <linux/serial_core.h>
#include <linux/serial_reg.h>
#include <linux/time.h>

/* The 47162a0 hangs when reading MIPS DMP registers registers */
static inline bool bcma_core_mips_bcm47162a0_quirk(struct bcma_device *dev)
{
	return dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM47162 &&
	       dev->bus->chipinfo.rev == 0 && dev->id.id == BCMA_CORE_MIPS_74K;
}

/* The 5357b0 hangs when reading USB20H DMP registers */
static inline bool bcma_core_mips_bcm5357b0_quirk(struct bcma_device *dev)
{
	return (dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM5357 ||
		dev->bus->chipinfo.id == BCMA_CHIP_ID_BCM4749) &&
	       dev->bus->chipinfo.pkg == 11 &&
	       dev->id.id == BCMA_CORE_USB20_HOST;
}

static inline u32 mips_read32(struct bcma_drv_mips *mcore,
			      u16 offset)
{
	return bcma_read32(mcore->core, offset);
}

static inline void mips_write32(struct bcma_drv_mips *mcore,
				u16 offset,
				u32 value)
{
	bcma_write32(mcore->core, offset, value);
}

static const u32 ipsflag_irq_mask[] = {
	0,
	BCMA_MIPS_IPSFLAG_IRQ1,
	BCMA_MIPS_IPSFLAG_IRQ2,
	BCMA_MIPS_IPSFLAG_IRQ3,
	BCMA_MIPS_IPSFLAG_IRQ4,
};

static const u32 ipsflag_irq_shift[] = {
	0,
	BCMA_MIPS_IPSFLAG_IRQ1_SHIFT,
	BCMA_MIPS_IPSFLAG_IRQ2_SHIFT,
	BCMA_MIPS_IPSFLAG_IRQ3_SHIFT,
	BCMA_MIPS_IPSFLAG_IRQ4_SHIFT,
};

static u32 bcma_core_mips_irqflag(struct bcma_device *dev)
{
	u32 flag;

	if (bcma_core_mips_bcm47162a0_quirk(dev))
		return dev->core_index;
	if (bcma_core_mips_bcm5357b0_quirk(dev))
		return dev->core_index;
	flag = bcma_aread32(dev, BCMA_MIPS_OOBSELOUTA30);

	return flag & 0x1F;
}

/* Get the MIPS IRQ assignment for a specified device.
 * If unassigned, 0 is returned.
 */
unsigned int bcma_core_mips_irq(struct bcma_device *dev)
{
	struct bcma_device *mdev = dev->bus->drv_mips.core;
	u32 irqflag;
	unsigned int irq;

	irqflag = bcma_core_mips_irqflag(dev);

	for (irq = 1; irq <= 4; irq++)
		if (bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq)) &
		    (1 << irqflag))
			return irq;

	return 0;
}
EXPORT_SYMBOL(bcma_core_mips_irq);

static void bcma_core_mips_set_irq(struct bcma_device *dev, unsigned int irq)
{
	unsigned int oldirq = bcma_core_mips_irq(dev);
	struct bcma_bus *bus = dev->bus;
	struct bcma_device *mdev = bus->drv_mips.core;
	u32 irqflag;

	irqflag = bcma_core_mips_irqflag(dev);
	BUG_ON(oldirq == 6);

	dev->irq = irq + 2;

	/* clear the old irq */
	if (oldirq == 0)
		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) &
			    ~(1 << irqflag));
	else
		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(oldirq), 0);

	/* assign the new one */
	if (irq == 0) {
		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0),
			    bcma_read32(mdev, BCMA_MIPS_MIPS74K_INTMASK(0)) |
			    (1 << irqflag));
	} else {
		u32 oldirqflag = bcma_read32(mdev,
					     BCMA_MIPS_MIPS74K_INTMASK(irq));
		if (oldirqflag) {
			struct bcma_device *core;

			/* backplane irq line is in use, find out who uses
			 * it and set user to irq 0
			 */
			list_for_each_entry(core, &bus->cores, list) {
				if ((1 << bcma_core_mips_irqflag(core)) ==
				    oldirqflag) {
					bcma_core_mips_set_irq(core, 0);
					break;
				}
			}
		}
		bcma_write32(mdev, BCMA_MIPS_MIPS74K_INTMASK(irq),
			     1 << irqflag);
	}

	bcma_info(bus, "set_irq: core 0x%04x, irq %d => %d\n",
		  dev->id.id, oldirq + 2, irq + 2);
}

static void bcma_core_mips_print_irq(struct bcma_device *dev, unsigned int irq)
{
	int i;
	static const char *irq_name[] = {"2(S)", "3", "4", "5", "6", "D", "I"};
	printk(KERN_INFO KBUILD_MODNAME ": core 0x%04x, irq :", dev->id.id);
	for (i = 0; i <= 6; i++)
		printk(" %s%s", irq_name[i], i == irq ? "*" : " ");
	printk("\n");
}

static void bcma_core_mips_dump_irq(struct bcma_bus *bus)
{
	struct bcma_device *core;

	list_for_each_entry(core, &bus->cores, list) {
		bcma_core_mips_print_irq(core, bcma_core_mips_irq(core));
	}
}

u32 bcma_cpu_clock(struct bcma_drv_mips *mcore)
{
	struct bcma_bus *bus = mcore->core->bus;

	if (bus->drv_cc.capabilities & BCMA_CC_CAP_PMU)
		return bcma_pmu_get_cpu_clock(&bus->drv_cc);

	bcma_err(bus, "No PMU available, need this to get the cpu clock\n");
	return 0;
}
EXPORT_SYMBOL(bcma_cpu_clock);

static void bcma_core_mips_flash_detect(struct bcma_drv_mips *mcore)
{
	struct bcma_bus *bus = mcore->core->bus;
	struct bcma_drv_cc *cc = &bus->drv_cc;

	switch (cc->capabilities & BCMA_CC_CAP_FLASHT) {
	case BCMA_CC_FLASHT_STSER:
	case BCMA_CC_FLASHT_ATSER:
		bcma_debug(bus, "Found serial flash\n");
		bcma_sflash_init(cc);
		break;
	case BCMA_CC_FLASHT_PARA:
		bcma_debug(bus, "Found parallel flash\n");
		cc->pflash.present = true;
		cc->pflash.window = BCMA_SOC_FLASH2;
		cc->pflash.window_size = BCMA_SOC_FLASH2_SZ;

		if ((bcma_read32(cc->core, BCMA_CC_FLASH_CFG) &
		     BCMA_CC_FLASH_CFG_DS) == 0)
			cc->pflash.buswidth = 1;
		else
			cc->pflash.buswidth = 2;
		break;
	default:
		bcma_err(bus, "Flash type not supported\n");
	}

	if (cc->core->id.rev == 38 ||
	    bus->chipinfo.id == BCMA_CHIP_ID_BCM4706) {
		if (cc->capabilities & BCMA_CC_CAP_NFLASH) {
			bcma_debug(bus, "Found NAND flash\n");
			bcma_nflash_init(cc);
		}
	}
}

void bcma_core_mips_early_init(struct bcma_drv_mips *mcore)
{
	struct bcma_bus *bus = mcore->core->bus;

	if (mcore->early_setup_done)
		return;

	bcma_chipco_serial_init(&bus->drv_cc);
	bcma_core_mips_flash_detect(mcore);

	mcore->early_setup_done = true;
}

void bcma_core_mips_init(struct bcma_drv_mips *mcore)
{
	struct bcma_bus *bus;
	struct bcma_device *core;
	bus = mcore->core->bus;

	if (mcore->setup_done)
		return;

	bcma_info(bus, "Initializing MIPS core...\n");

	bcma_core_mips_early_init(mcore);

	mcore->assigned_irqs = 1;

	/* Assign IRQs to all cores on the bus */
	list_for_each_entry(core, &bus->cores, list) {
		int mips_irq;
		if (core->irq)
			continue;

		mips_irq = bcma_core_mips_irq(core);
		if (mips_irq > 4)
			core->irq = 0;
		else
			core->irq = mips_irq + 2;
		if (core->irq > 5)
			continue;
		switch (core->id.id) {
		case BCMA_CORE_PCI:
		case BCMA_CORE_PCIE:
		case BCMA_CORE_ETHERNET:
		case BCMA_CORE_ETHERNET_GBIT:
		case BCMA_CORE_MAC_GBIT:
		case BCMA_CORE_80211:
		case BCMA_CORE_USB20_HOST:
			/* These devices get their own IRQ line if available,
			 * the rest goes on IRQ0
			 */
			if (mcore->assigned_irqs <= 4)
				bcma_core_mips_set_irq(core,
						       mcore->assigned_irqs++);
			break;
		}
	}
	bcma_info(bus, "IRQ reconfiguration done\n");
	bcma_core_mips_dump_irq(bus);

	mcore->setup_done = true;
}
