Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9693ebd4 authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

Merge remote branch 'kumar/merge' into merge

parents 3fb79338 6ff31453
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -157,6 +157,8 @@ struct fsl_lbc_regs {
#define LBCR_EPAR_SHIFT    16
#define LBCR_EPAR_SHIFT    16
#define LBCR_BMT   0x0000FF00
#define LBCR_BMT   0x0000FF00
#define LBCR_BMT_SHIFT      8
#define LBCR_BMT_SHIFT      8
#define LBCR_BMTPS 0x0000000F
#define LBCR_BMTPS_SHIFT    0
#define LBCR_INIT  0x00040000
#define LBCR_INIT  0x00040000
	__be32 lcrr;            /**< Clock Ratio Register */
	__be32 lcrr;            /**< Clock Ratio Register */
#define LCRR_DBYP    0x80000000
#define LCRR_DBYP    0x80000000
+5 −0
Original line number Original line Diff line number Diff line
@@ -14,5 +14,10 @@
#define ASM_PPC_RIO_H
#define ASM_PPC_RIO_H


extern void platform_rio_init(void);
extern void platform_rio_init(void);
#ifdef CONFIG_RAPIDIO
extern int fsl_rio_mcheck_exception(struct pt_regs *);
#else
static inline int fsl_rio_mcheck_exception(struct pt_regs *regs) {return 0; }
#endif


#endif				/* ASM_PPC_RIO_H */
#endif				/* ASM_PPC_RIO_H */
+13 −0
Original line number Original line Diff line number Diff line
@@ -55,6 +55,7 @@
#endif
#endif
#include <asm/kexec.h>
#include <asm/kexec.h>
#include <asm/ppc-opcode.h>
#include <asm/ppc-opcode.h>
#include <asm/rio.h>


#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
#if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
int (*__debugger)(struct pt_regs *regs) __read_mostly;
int (*__debugger)(struct pt_regs *regs) __read_mostly;
@@ -424,6 +425,12 @@ int machine_check_e500mc(struct pt_regs *regs)
	unsigned long reason = mcsr;
	unsigned long reason = mcsr;
	int recoverable = 1;
	int recoverable = 1;


	if (reason & MCSR_BUS_RBERR) {
		recoverable = fsl_rio_mcheck_exception(regs);
		if (recoverable == 1)
			goto silent_out;
	}

	printk("Machine check in kernel mode.\n");
	printk("Machine check in kernel mode.\n");
	printk("Caused by (from MCSR=%lx): ", reason);
	printk("Caused by (from MCSR=%lx): ", reason);


@@ -499,6 +506,7 @@ int machine_check_e500mc(struct pt_regs *regs)
		       reason & MCSR_MEA ? "Effective" : "Physical", addr);
		       reason & MCSR_MEA ? "Effective" : "Physical", addr);
	}
	}


silent_out:
	mtspr(SPRN_MCSR, mcsr);
	mtspr(SPRN_MCSR, mcsr);
	return mfspr(SPRN_MCSR) == 0 && recoverable;
	return mfspr(SPRN_MCSR) == 0 && recoverable;
}
}
@@ -507,6 +515,11 @@ int machine_check_e500(struct pt_regs *regs)
{
{
	unsigned long reason = get_mc_reason(regs);
	unsigned long reason = get_mc_reason(regs);


	if (reason & MCSR_BUS_RBERR) {
		if (fsl_rio_mcheck_exception(regs))
			return 1;
	}

	printk("Machine check in kernel mode.\n");
	printk("Machine check in kernel mode.\n");
	printk("Caused by (from MCSR=%lx): ", reason);
	printk("Caused by (from MCSR=%lx): ", reason);


+7 −2
Original line number Original line Diff line number Diff line
@@ -184,7 +184,8 @@ int fsl_upm_run_pattern(struct fsl_upm *upm, void __iomem *io_base, u32 mar)
}
}
EXPORT_SYMBOL(fsl_upm_run_pattern);
EXPORT_SYMBOL(fsl_upm_run_pattern);


static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl,
				       struct device_node *node)
{
{
	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;


@@ -198,6 +199,10 @@ static int __devinit fsl_lbc_ctrl_init(struct fsl_lbc_ctrl *ctrl)
	/* Enable interrupts for any detected events */
	/* Enable interrupts for any detected events */
	out_be32(&lbc->lteir, LTEIR_ENABLE);
	out_be32(&lbc->lteir, LTEIR_ENABLE);


	/* Set the monitor timeout value to the maximum for erratum A001 */
	if (of_device_is_compatible(node, "fsl,elbc"))
		clrsetbits_be32(&lbc->lbcr, LBCR_BMT, LBCR_BMTPS);

	return 0;
	return 0;
}
}


@@ -304,7 +309,7 @@ static int __devinit fsl_lbc_ctrl_probe(struct platform_device *dev)


	fsl_lbc_ctrl_dev->dev = &dev->dev;
	fsl_lbc_ctrl_dev->dev = &dev->dev;


	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev);
	ret = fsl_lbc_ctrl_init(fsl_lbc_ctrl_dev, dev->dev.of_node);
	if (ret < 0)
	if (ret < 0)
		goto err;
		goto err;


+80 −20
Original line number Original line Diff line number Diff line
@@ -10,7 +10,7 @@
 * - Added Port-Write message handling
 * - Added Port-Write message handling
 * - Added Machine Check exception handling
 * - Added Machine Check exception handling
 *
 *
 * Copyright (C) 2007, 2008 Freescale Semiconductor, Inc.
 * Copyright (C) 2007, 2008, 2010 Freescale Semiconductor, Inc.
 * Zhang Wei <wei.zhang@freescale.com>
 * Zhang Wei <wei.zhang@freescale.com>
 *
 *
 * Copyright 2005 MontaVista Software, Inc.
 * Copyright 2005 MontaVista Software, Inc.
@@ -47,11 +47,29 @@
#define IRQ_RIO_RX(m)		(((struct rio_priv *)(m->priv))->rxirq)
#define IRQ_RIO_RX(m)		(((struct rio_priv *)(m->priv))->rxirq)
#define IRQ_RIO_PW(m)		(((struct rio_priv *)(m->priv))->pwirq)
#define IRQ_RIO_PW(m)		(((struct rio_priv *)(m->priv))->pwirq)


#define IPWSR_CLEAR		0x98
#define OMSR_CLEAR		0x1cb3
#define IMSR_CLEAR		0x491
#define IDSR_CLEAR		0x91
#define ODSR_CLEAR		0x1c00
#define LTLEECSR_ENABLE_ALL	0xFFC000FC
#define ESCSR_CLEAR		0x07120204

#define RIO_PORT1_EDCSR		0x0640
#define RIO_PORT2_EDCSR		0x0680
#define RIO_PORT1_IECSR		0x10130
#define RIO_PORT2_IECSR		0x101B0
#define RIO_IM0SR		0x13064
#define RIO_IM1SR		0x13164
#define RIO_OM0SR		0x13004
#define RIO_OM1SR		0x13104

#define RIO_ATMU_REGS_OFFSET	0x10c00
#define RIO_ATMU_REGS_OFFSET	0x10c00
#define RIO_P_MSG_REGS_OFFSET	0x11000
#define RIO_P_MSG_REGS_OFFSET	0x11000
#define RIO_S_MSG_REGS_OFFSET	0x13000
#define RIO_S_MSG_REGS_OFFSET	0x13000
#define RIO_GCCSR		0x13c
#define RIO_GCCSR		0x13c
#define RIO_ESCSR		0x158
#define RIO_ESCSR		0x158
#define RIO_PORT2_ESCSR		0x178
#define RIO_CCSR		0x15c
#define RIO_CCSR		0x15c
#define RIO_LTLEDCSR		0x0608
#define RIO_LTLEDCSR		0x0608
#define RIO_LTLEDCSR_IER	0x80000000
#define RIO_LTLEDCSR_IER	0x80000000
@@ -88,7 +106,10 @@
#define RIO_IPWSR_PWD		0x00000008
#define RIO_IPWSR_PWD		0x00000008
#define RIO_IPWSR_PWB		0x00000004
#define RIO_IPWSR_PWB		0x00000004


#define RIO_EPWISR_PINT		0x80000000
/* EPWISR Error match value */
#define RIO_EPWISR_PINT1	0x80000000
#define RIO_EPWISR_PINT2	0x40000000
#define RIO_EPWISR_MU		0x00000002
#define RIO_EPWISR_PW		0x00000001
#define RIO_EPWISR_PW		0x00000001


#define RIO_MSG_DESC_SIZE	32
#define RIO_MSG_DESC_SIZE	32
@@ -260,9 +281,7 @@ struct rio_priv {
static void __iomem *rio_regs_win;
static void __iomem *rio_regs_win;


#ifdef CONFIG_E500
#ifdef CONFIG_E500
static int (*saved_mcheck_exception)(struct pt_regs *regs);
int fsl_rio_mcheck_exception(struct pt_regs *regs)

static int fsl_rio_mcheck_exception(struct pt_regs *regs)
{
{
	const struct exception_table_entry *entry = NULL;
	const struct exception_table_entry *entry = NULL;
	unsigned long reason = mfspr(SPRN_MCSR);
	unsigned long reason = mfspr(SPRN_MCSR);
@@ -284,11 +303,9 @@ static int fsl_rio_mcheck_exception(struct pt_regs *regs)
		}
		}
	}
	}


	if (saved_mcheck_exception)
	return 0;
		return saved_mcheck_exception(regs);
	else
		return cur_cpu_spec->machine_check(regs);
}
}
EXPORT_SYMBOL_GPL(fsl_rio_mcheck_exception);
#endif
#endif


/**
/**
@@ -1064,6 +1081,40 @@ static int fsl_rio_doorbell_init(struct rio_mport *mport)
	return rc;
	return rc;
}
}


static void port_error_handler(struct rio_mport *port, int offset)
{
	/*XXX: Error recovery is not implemented, we just clear errors */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);

	if (offset == 0) {
		out_be32((u32 *)(rio_regs_win + RIO_PORT1_EDCSR), 0);
		out_be32((u32 *)(rio_regs_win + RIO_PORT1_IECSR), 0);
		out_be32((u32 *)(rio_regs_win + RIO_ESCSR), ESCSR_CLEAR);
	} else {
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_EDCSR), 0);
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_IECSR), 0);
		out_be32((u32 *)(rio_regs_win + RIO_PORT2_ESCSR), ESCSR_CLEAR);
	}
}

static void msg_unit_error_handler(struct rio_mport *port)
{
	struct rio_priv *priv = port->priv;

	/*XXX: Error recovery is not implemented, we just clear errors */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR), 0);

	out_be32((u32 *)(rio_regs_win + RIO_IM0SR), IMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_IM1SR), IMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_OM0SR), OMSR_CLEAR);
	out_be32((u32 *)(rio_regs_win + RIO_OM1SR), OMSR_CLEAR);

	out_be32(&priv->msg_regs->odsr, ODSR_CLEAR);
	out_be32(&priv->msg_regs->dsr, IDSR_CLEAR);

	out_be32(&priv->msg_regs->pwsr, IPWSR_CLEAR);
}

/**
/**
 * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
 * fsl_rio_port_write_handler - MPC85xx port write interrupt handler
 * @irq: Linux interrupt number
 * @irq: Linux interrupt number
@@ -1144,10 +1195,22 @@ fsl_rio_port_write_handler(int irq, void *dev_instance)
	}
	}


pw_done:
pw_done:
	if (epwisr & RIO_EPWISR_PINT) {
	if (epwisr & RIO_EPWISR_PINT1) {
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		port_error_handler(port, 0);
	}

	if (epwisr & RIO_EPWISR_PINT2) {
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		out_be32(priv->regs_win + RIO_LTLEDCSR, 0);
		port_error_handler(port, 1);
	}

	if (epwisr & RIO_EPWISR_MU) {
		tmp = in_be32(priv->regs_win + RIO_LTLEDCSR);
		pr_debug("RIO_LTLEDCSR = 0x%x\n", tmp);
		msg_unit_error_handler(port);
	}
	}


	return IRQ_HANDLED;
	return IRQ_HANDLED;
@@ -1258,12 +1321,14 @@ static int fsl_rio_port_write_init(struct rio_mport *mport)




	/* Hook up port-write handler */
	/* Hook up port-write handler */
	rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler, 0,
	rc = request_irq(IRQ_RIO_PW(mport), fsl_rio_port_write_handler,
			 "port-write", (void *)mport);
			IRQF_SHARED, "port-write", (void *)mport);
	if (rc < 0) {
	if (rc < 0) {
		pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
		pr_err("MPC85xx RIO: unable to request inbound doorbell irq");
		goto err_out;
		goto err_out;
	}
	}
	/* Enable Error Interrupt */
	out_be32((u32 *)(rio_regs_win + RIO_LTLEECSR), LTLEECSR_ENABLE_ALL);


	INIT_WORK(&priv->pw_work, fsl_pw_dpc);
	INIT_WORK(&priv->pw_work, fsl_pw_dpc);
	spin_lock_init(&priv->pw_fifo_lock);
	spin_lock_init(&priv->pw_fifo_lock);
@@ -1538,11 +1603,6 @@ int fsl_rio_setup(struct platform_device *dev)
	fsl_rio_doorbell_init(port);
	fsl_rio_doorbell_init(port);
	fsl_rio_port_write_init(port);
	fsl_rio_port_write_init(port);


#ifdef CONFIG_E500
	saved_mcheck_exception = ppc_md.machine_check_exception;
	ppc_md.machine_check_exception = fsl_rio_mcheck_exception;
#endif

	return 0;
	return 0;
err:
err:
	iounmap(priv->regs_win);
	iounmap(priv->regs_win);