 /*
  * 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);

	WARN(true, "%s Error seen by %s %s at address %x\n",
				 omap3_l3_code_string(code),
			  omap3_l3_initiator_string(initid),
			     multi ? "Multiple Errors" : "",
						   address);

	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;

	if (irq == l3->app_irq)
		int_type = L3_APPLICATION_ERROR;
	else
		int_type = 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 */
	for (err_source = 0; !(status & (1 << err_source)); err_source++)
									;

	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) {
		ret = -ENOMEM;
		goto err0;
	}

	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 err1;
	}
	l3->rt = ioremap(res->start, resource_size(res));
	if (!(l3->rt)) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto err2;
	}

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

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

	goto err0;

err4:
err3:
	iounmap(l3->rt);
err2:
err1:
	kfree(l3);
err0:
	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);
