/*
 * Copyright (c) 2003-2012 Broadcom Corporation
 * All Rights Reserved
 *
 * This software is available to you under a choice of one of two
 * licenses.  You may choose to be licensed under the terms of the GNU
 * 1. Redistributions of source code must retain the above copyright
 * General Public License (GPL) Version 2, available from the file
 * COPYING in the main directory of this source tree, or the Broadcom
 * license below:
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/resource.h>
#include <linux/phy.h>

#include <asm/netlogic/haldefs.h>
#include <asm/netlogic/common.h>
#include <asm/netlogic/xlr/fmn.h>
#include <asm/netlogic/xlr/xlr.h>
#include <asm/netlogic/psb-bootinfo.h>
#include <asm/netlogic/xlr/pic.h>
#include <asm/netlogic/xlr/iomap.h>

#include "platform_net.h"

/* Linux Net */
#define MAX_NUM_GMAC		8
#define MAX_NUM_XLS_GMAC	8
#define MAX_NUM_XLR_GMAC	4

static u32 xlr_gmac_offsets[] = {
	NETLOGIC_IO_GMAC_0_OFFSET, NETLOGIC_IO_GMAC_1_OFFSET,
	NETLOGIC_IO_GMAC_2_OFFSET, NETLOGIC_IO_GMAC_3_OFFSET,
	NETLOGIC_IO_GMAC_4_OFFSET, NETLOGIC_IO_GMAC_5_OFFSET,
	NETLOGIC_IO_GMAC_6_OFFSET, NETLOGIC_IO_GMAC_7_OFFSET
};

static u32 xlr_gmac_irqs[] = { PIC_GMAC_0_IRQ, PIC_GMAC_1_IRQ,
	PIC_GMAC_2_IRQ, PIC_GMAC_3_IRQ,
	PIC_GMAC_4_IRQ, PIC_GMAC_5_IRQ,
	PIC_GMAC_6_IRQ, PIC_GMAC_7_IRQ
};

static struct resource xlr_net0_res[8];
static struct resource xlr_net1_res[8];
static u32 __iomem *gmac4_addr;
static u32 __iomem *gpio_addr;

static void xlr_resource_init(struct resource *res, int offset, int irq)
{
	res->name = "gmac";

	res->start = CPHYSADDR(nlm_mmio_base(offset));
	res->end = res->start + 0xfff;
	res->flags = IORESOURCE_MEM;

	res++;
	res->name = "gmac";
	res->start = irq;
	res->end = irq;
	res->flags = IORESOURCE_IRQ;
}

static struct platform_device *gmac_controller2_init(void *gmac0_addr)
{
	int mac;
	static struct xlr_net_data ndata1 = {
		.phy_interface	= PHY_INTERFACE_MODE_SGMII,
		.rfr_station	= FMN_STNID_GMAC1_FR_0,
		.bucket_size	= xlr_board_fmn_config.bucket_size,
		.gmac_fmn_info	= &xlr_board_fmn_config.gmac[1],
	};

	static struct platform_device xlr_net_dev1 = {
		.name		= "xlr-net",
		.id		= 1,
		.dev.platform_data = &ndata1,
	};

	gmac4_addr = ioremap(CPHYSADDR(
		nlm_mmio_base(NETLOGIC_IO_GMAC_4_OFFSET)), 0xfff);
	ndata1.serdes_addr = gmac4_addr;
	ndata1.pcs_addr	= gmac4_addr;
	ndata1.mii_addr	= gmac0_addr;
	ndata1.gpio_addr = gpio_addr;
	ndata1.cpu_mask = nlm_current_node()->coremask;

	xlr_net_dev1.resource = xlr_net1_res;

	for (mac = 0; mac < 4; mac++) {
		ndata1.tx_stnid[mac] = FMN_STNID_GMAC1_TX0 + mac;
		ndata1.phy_addr[mac] = mac + 4 + 0x10;

		xlr_resource_init(&xlr_net1_res[mac * 2],
				  xlr_gmac_offsets[mac + 4],
				  xlr_gmac_irqs[mac + 4]);
	}
	xlr_net_dev1.num_resources = 8;

	return &xlr_net_dev1;
}

static void xls_gmac_init(void)
{
	int mac;
	struct platform_device *xlr_net_dev1;
	void __iomem *gmac0_addr = ioremap(CPHYSADDR(
		nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)), 0xfff);

	static struct xlr_net_data ndata0 = {
		.rfr_station	= FMN_STNID_GMACRFR_0,
		.bucket_size	= xlr_board_fmn_config.bucket_size,
		.gmac_fmn_info	= &xlr_board_fmn_config.gmac[0],
	};

	static struct platform_device xlr_net_dev0 = {
		.name		= "xlr-net",
		.id		= 0,
	};
	xlr_net_dev0.dev.platform_data = &ndata0;
	ndata0.serdes_addr = gmac0_addr;
	ndata0.pcs_addr	= gmac0_addr;
	ndata0.mii_addr	= gmac0_addr;

	/* Passing GPIO base for serdes init. Only needed on sgmii ports */
	gpio_addr = ioremap(CPHYSADDR(
		nlm_mmio_base(NETLOGIC_IO_GPIO_OFFSET)), 0xfff);
	ndata0.gpio_addr = gpio_addr;
	ndata0.cpu_mask = nlm_current_node()->coremask;

	xlr_net_dev0.resource = xlr_net0_res;

	switch (nlm_prom_info.board_major_version) {
	case 12:
		/* first block RGMII or XAUI, use RGMII */
		ndata0.phy_interface = PHY_INTERFACE_MODE_RGMII;
		ndata0.tx_stnid[0] = FMN_STNID_GMAC0_TX0;
		ndata0.phy_addr[0] = 0;

		xlr_net_dev0.num_resources = 2;

		xlr_resource_init(&xlr_net0_res[0], xlr_gmac_offsets[0],
				  xlr_gmac_irqs[0]);
		platform_device_register(&xlr_net_dev0);

		/* second block is XAUI, not supported yet */
		break;
	default:
		/* default XLS config, all ports SGMII */
		ndata0.phy_interface = PHY_INTERFACE_MODE_SGMII;
		for (mac = 0; mac < 4; mac++) {
			ndata0.tx_stnid[mac] = FMN_STNID_GMAC0_TX0 + mac;
			ndata0.phy_addr[mac] = mac + 0x10;

			xlr_resource_init(&xlr_net0_res[mac * 2],
					  xlr_gmac_offsets[mac],
					xlr_gmac_irqs[mac]);
		}
		xlr_net_dev0.num_resources = 8;
		platform_device_register(&xlr_net_dev0);

		xlr_net_dev1 = gmac_controller2_init(gmac0_addr);
		platform_device_register(xlr_net_dev1);
	}
}

static void xlr_gmac_init(void)
{
	int mac;

	/* assume all GMACs for now */
	static struct xlr_net_data ndata0 = {
		.phy_interface	= PHY_INTERFACE_MODE_RGMII,
		.serdes_addr	= NULL,
		.pcs_addr	= NULL,
		.rfr_station	= FMN_STNID_GMACRFR_0,
		.bucket_size	= xlr_board_fmn_config.bucket_size,
		.gmac_fmn_info	= &xlr_board_fmn_config.gmac[0],
		.gpio_addr	= NULL,
	};

	static struct platform_device xlr_net_dev0 = {
		.name		= "xlr-net",
		.id		= 0,
		.dev.platform_data = &ndata0,
	};
	ndata0.mii_addr = ioremap(CPHYSADDR(
		nlm_mmio_base(NETLOGIC_IO_GMAC_0_OFFSET)), 0xfff);

	ndata0.cpu_mask = nlm_current_node()->coremask;

	for (mac = 0; mac < MAX_NUM_XLR_GMAC; mac++) {
		ndata0.tx_stnid[mac] = FMN_STNID_GMAC0_TX0 + mac;
		ndata0.phy_addr[mac] = mac;
		xlr_resource_init(&xlr_net0_res[mac * 2], xlr_gmac_offsets[mac],
				  xlr_gmac_irqs[mac]);
	}
	xlr_net_dev0.num_resources = 8;
	xlr_net_dev0.resource = xlr_net0_res;

	platform_device_register(&xlr_net_dev0);
}

static int __init xlr_net_init(void)
{
	if (nlm_chip_is_xls())
		xls_gmac_init();
	else
		xlr_gmac_init();

	return 0;
}

arch_initcall(xlr_net_init);
