/*
 * OMAP3XXX L3 Interconnect Driver
 *
 * Copyright (C) 2011 Texas Corporation
 *	Felipe Balbi <balbi@ti.com>
 *	Santosh Shilimkar <santosh.shilimkar@ti.com>
 *	Sricharan <r.sricharan@ti.com>
 *
 * 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 <linux/kernel.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include "omap_l3_smx.h"

static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
{
	return __raw_readll(base + reg);
}

static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
{
	__raw_writell(value, base + reg);
}

static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
{
	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
}

static inline u32 omap3_l3_decode_addr(u64 error_addr)
{
	return error_addr & 0xffffffff;
}

static inline unsigned omap3_l3_decode_cmd(u64 error)
{
	return (error & 0x07) >> L3_ERROR_LOG_CMD;
}

static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
{
	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
}

static inline unsigned omap3_l3_decode_req_info(u64 error)
{
	return (error >> 32) & 0xffff;
}

static char *omap3_l3_code_string(u8 code)
{
	switch (code) {
	case OMAP_L3_CODE_NOERROR:
		return "No Error";
	case OMAP_L3_CODE_UNSUP_CMD:
		return "Unsupported Command";
	case OMAP_L3_CODE_ADDR_HOLE:
		return "Address Hole";
	case OMAP_L3_CODE_PROTECT_VIOLATION:
		return "Protection Violation";
	case OMAP_L3_CODE_IN_BAND_ERR:
		return "In-band Error";
	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
		return "Request Timeout Not Accepted";
	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
		return "Request Timeout, no response";
	default:
		return "UNKNOWN error";
	}
}

static char *omap3_l3_initiator_string(u8 initid)
{
	switch (initid) {
	case OMAP_L3_LCD:
		return "LCD";
	case OMAP_L3_SAD2D:
		return "SAD2D";
	case OMAP_L3_IA_MPU_SS_1:
	case OMAP_L3_IA_MPU_SS_2:
	case OMAP_L3_IA_MPU_SS_3:
	case OMAP_L3_IA_MPU_SS_4:
	case OMAP_L3_IA_MPU_SS_5:
		return "MPU";
	case OMAP_L3_IA_IVA_SS_1:
	case OMAP_L3_IA_IVA_SS_2:
	case OMAP_L3_IA_IVA_SS_3:
		return "IVA_SS";
	case OMAP_L3_IA_IVA_SS_DMA_1:
	case OMAP_L3_IA_IVA_SS_DMA_2:
	case OMAP_L3_IA_IVA_SS_DMA_3:
	case OMAP_L3_IA_IVA_SS_DMA_4:
	case OMAP_L3_IA_IVA_SS_DMA_5:
	case OMAP_L3_IA_IVA_SS_DMA_6:
		return "IVA_SS_DMA";
	case OMAP_L3_IA_SGX:
		return "SGX";
	case OMAP_L3_IA_CAM_1:
	case OMAP_L3_IA_CAM_2:
	case OMAP_L3_IA_CAM_3:
		return "CAM";
	case OMAP_L3_IA_DAP:
		return "DAP";
	case OMAP_L3_SDMA_WR_1:
	case OMAP_L3_SDMA_WR_2:
		return "SDMA_WR";
	case OMAP_L3_SDMA_RD_1:
	case OMAP_L3_SDMA_RD_2:
	case OMAP_L3_SDMA_RD_3:
	case OMAP_L3_SDMA_RD_4:
		return "SDMA_RD";
	case OMAP_L3_USBOTG:
		return "USB_OTG";
	case OMAP_L3_USBHOST:
		return "USB_HOST";
	default:
		return "UNKNOWN Initiator";
	}
}

/*
 * omap3_l3_block_irq - handles a register block's irq
 * @l3: struct omap3_l3 *
 * @base: register block base address
 * @error: L3_ERROR_LOG register of our block
 *
 * Called in hard-irq context. Caller should take care of locking
 *
 * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
 * Analysis Sequence, we are following that sequence here, please
 * refer to that Figure for more information on the subject.
 */
static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
					u64 error, int error_addr)
{
	u8 code = omap3_l3_decode_error_code(error);
	u8 initid = omap3_l3_decode_initid(error);
	u8 multi = error & L3_ERROR_LOG_MULTI;
	u32 address = omap3_l3_decode_addr(error_addr);

	pr_err("%s seen by %s %s at address %x\n",
			omap3_l3_code_string(code),
			omap3_l3_initiator_string(initid),
			multi ? "Multiple Errors" : "", address);
	WARN_ON(1);

	return IRQ_HANDLED;
}

static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
{
	struct omap3_l3 *l3 = _l3;
	u64 status, clear;
	u64 error;
	u64 error_addr;
	u64 err_source = 0;
	void __iomem *base;
	int int_type;
	irqreturn_t ret = IRQ_NONE;

	int_type = irq == l3->app_irq ? L3_APPLICATION_ERROR : L3_DEBUG_ERROR;
	if (!int_type) {
		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
		/*
		 * if we have a timeout error, there's nothing we can
		 * do besides rebooting the board. So let's BUG on any
		 * of such errors and handle the others. timeout error
		 * is severe and not expected to occur.
		 */
		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
	} else {
		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
		/* No timeout error for debug sources */
	}

	/* identify the error source */
	err_source = __ffs(status);

	base = l3->rt + omap3_l3_bases[int_type][err_source];
	error = omap3_l3_readll(base, L3_ERROR_LOG);
	if (error) {
		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
		ret |= omap3_l3_block_irq(l3, error, error_addr);
	}

	/* Clear the status register */
	clear = (L3_AGENT_STATUS_CLEAR_IA << int_type) |
		L3_AGENT_STATUS_CLEAR_TA;
	omap3_l3_writell(base, L3_AGENT_STATUS, clear);

	/* clear the error log register */
	omap3_l3_writell(base, L3_ERROR_LOG, error);

	return ret;
}

static int __init omap3_l3_probe(struct platform_device *pdev)
{
	struct omap3_l3 *l3;
	struct resource *res;
	int ret;

	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
	if (!l3)
		return -ENOMEM;

	platform_set_drvdata(pdev, l3);

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(&pdev->dev, "couldn't find resource\n");
		ret = -ENODEV;
		goto err0;
	}
	l3->rt = ioremap(res->start, resource_size(res));
	if (!l3->rt) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err0;
	}

	l3->debug_irq = platform_get_irq(pdev, 0);
	ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
		IRQF_DISABLED | IRQF_TRIGGER_RISING,
		"l3-debug-irq", l3);
	if (ret) {
		dev_err(&pdev->dev, "couldn't request debug irq\n");
		goto err1;
	}

	l3->app_irq = platform_get_irq(pdev, 1);
	ret = request_irq(l3->app_irq, omap3_l3_app_irq,
		IRQF_DISABLED | IRQF_TRIGGER_RISING,
		"l3-app-irq", l3);
	if (ret) {
		dev_err(&pdev->dev, "couldn't request app irq\n");
		goto err2;
	}

	return 0;

err2:
	free_irq(l3->debug_irq, l3);
err1:
	iounmap(l3->rt);
err0:
	kfree(l3);
	return ret;
}

static int __exit omap3_l3_remove(struct platform_device *pdev)
{
	struct omap3_l3         *l3 = platform_get_drvdata(pdev);

	free_irq(l3->app_irq, l3);
	free_irq(l3->debug_irq, l3);
	iounmap(l3->rt);
	kfree(l3);

	return 0;
}

static struct platform_driver omap3_l3_driver = {
	.remove         = __exit_p(omap3_l3_remove),
	.driver         = {
	.name   = "omap_l3_smx",
	},
};

static int __init omap3_l3_init(void)
{
	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
}
postcore_initcall_sync(omap3_l3_init);

static void __exit omap3_l3_exit(void)
{
	platform_driver_unregister(&omap3_l3_driver);
}
module_exit(omap3_l3_exit);
