LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: mmotm threatens ppc preemption again
From: Jeremy Fitzhardinge @ 2011-03-22 13:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Andrew Morton, Hugh Dickins, Peter Zijlstra
In-Reply-To: <1300747942.2402.262.camel@pasglop>

On 03/21/2011 10:52 PM, Benjamin Herrenschmidt wrote:
> On Mon, 2011-03-21 at 11:24 +0000, Jeremy Fitzhardinge wrote:
>> I'm very sorry about that, I didn't realize power was also using that
>> interface.  Unfortunately, the "no preemption" definition was an error,
>> and had to be changed to match the pre-existing locking rules.
>>
>> Could you implement a similar "flush batched pte updates on context
>> switch" as x86? 
> Well, we already do that for -rt & co.
>
> However, we have another issue which is the reason we used those
> lazy_mmu hooks to do our flushing.
>
> Our PTEs eventually get faulted into a hash table which is what the real
> MMU uses. We must never (ever) allow that hash table to contain a
> duplicate entry for a given virtual address.
>
> When we do a batch, we remove things from the linux PTE, and keep a
> reference in our batch structure, and only update the hash table at the
> end of the batch.

Wouldn't implicitly ending a batch on context switch get the same effect?

> That means that we must not allow a hash fault to populate the hash with
> a "new" PTE value prior to the old one having been flushed out (which is
> possible if they different in protection attributes for example). For
> that to happen, we must basically not allow a page fault to re-populate
> a PTE invalidated by a batch before that batch has completed.

Kernel ptes are not generally populated on fault though, unless there's
something in power?  On x86 it can happen when syncing a process's
kernel pmd with the init_mm one, but that shouldn't happen in the middle
of an update since you'd deadlock anyway.  If a particular kernel
subsystem has its own locks to manage the ptes for a kernel mapping,
then that should prevent any nested updates within a batch shouldn't it?

> That translates to batches must only happen within a PTE lock section.

Well, in that case, I guess your best bet is to disable batching for
kernel pagetable updates.  These apply_to_page_range() changes are the
first time any attempt to batch kernel pagetable updates has been made
(otherwise you would have seen this problem earlier), so not batching
them will not be a regression for you.

But I'm not sure what the proper fix to get batching in your case will
be.  But the assumption that there's a pte lock for kernel ptes is not
valid.

    J

^ permalink raw reply

* Re: [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Grant Likely @ 2011-03-22 20:58 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
	linux-kernel, Ben Dooks, Randy Dunlap, Paul Mundt, linuxppc-dev,
	Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

On Tue, Mar 22, 2011 at 2:27 AM, Heiko Schocher <hs@denx.de> wrote:
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: linux-fbdev@vger.kernel.org
> cc: devicetree-discuss@ozlabs.org
> cc: Ben Dooks <ben@simtec.co.uk>
> cc: Vincent Sanders <vince@simtec.co.uk>
> cc: Samuel Ortiz <sameo@linux.intel.com>
> cc: linux-kernel@vger.kernel.org
> cc: Randy Dunlap <rdunlap@xenotime.net>
> cc: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
>
> changes since v5:
> - repost complete patchseries, as Paul Mundt suggested
> - rebased against current head
> - add Acked-by from Samuel Ortiz (MFD parts)
> =A0http://www.spinics.net/lists/linux-fbdev/msg02550.html
> =A0http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>
> =A0and Benjamin Herrenschmidt (DTS parts)
> =A0http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.ht=
ml
> - removed patch
> =A0"powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
> =A0therefore added
> =A0"powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."

Why?  As Wolfram mentioned, I'd rather see mpc5200 defconfig used.
Eventually I'd like to remove tqm5200_defconfig

I'll look through the rest of the patches soon.

g.

^ permalink raw reply

* Re: [PATCH 3/3, v2] fs_enet: Add PHY interface selection for MPC5121 fs_enet.
From: vooon341 @ 2011-03-22 14:10 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: netdev, linux-kernel, Vitaly Bordug

Add PHY interface selection for MPC5121 fs_enet.

Adds phy-connection-type optional property for ethernet node.
It should be rmii or mii.

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---
v2:
 - replace Kconfig to device tree
 - add phy-connection-type for mpc5121-fec nodes
---
 drivers/net/fs_enet/fec.h          |    6 ++++--
 drivers/net/fs_enet/fs_enet-main.c |   14 ++++++++++++--
 drivers/net/fs_enet/mac-fec.c      |    9 ++++++---
 3 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/drivers/net/fs_enet/fec.h b/drivers/net/fs_enet/fec.h
index e980527..9fd1ff5 100644
--- a/drivers/net/fs_enet/fec.h
+++ b/drivers/net/fs_enet/fec.h
@@ -23,6 +23,10 @@
 #define FEC_ECNTRL_ETHER_EN	0x00000002
 #define FEC_ECNTRL_RESET	0x00000001

+/* RMII mode enabled only when MII_MODE bit is set too. */
+#define FEC_RCNTRL_RMII_MODE	(0x00000100 | \
+		FEC_RCNTRL_MII_MODE | FEC_RCNTRL_FCE)
+#define FEC_RCNTRL_FCE		0x00000020
 #define FEC_RCNTRL_BC_REJ	0x00000010
 #define FEC_RCNTRL_PROM		0x00000008
 #define FEC_RCNTRL_MII_MODE	0x00000004
@@ -33,8 +37,6 @@
 #define FEC_TCNTRL_HBC		0x00000002
 #define FEC_TCNTRL_GTS		0x00000001

-
-
 /*
  * Delay to wait for FEC reset command to complete (in us)
  */
diff --git a/drivers/net/fs_enet/fs_enet-main.c
b/drivers/net/fs_enet/fs_enet-main.c
index 24cb953..c424159 100644
--- a/drivers/net/fs_enet/fs_enet-main.c
+++ b/drivers/net/fs_enet/fs_enet-main.c
@@ -788,16 +788,20 @@ static int fs_init_phy(struct net_device *dev)
 {
 	struct fs_enet_private *fep = netdev_priv(dev);
 	struct phy_device *phydev;
+	phy_interface_t iface;

 	fep->oldlink = 0;
 	fep->oldspeed = 0;
 	fep->oldduplex = -1;

+	iface = (fep->fpi->use_rmii) ?
+		PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII;
+
 	phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0,
-				PHY_INTERFACE_MODE_MII);
+				iface);
 	if (!phydev) {
 		phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link,
-						   PHY_INTERFACE_MODE_MII);
+						   iface);
 	}
 	if (!phydev) {
 		dev_err(&dev->dev, "Could not attach to PHY\n");
@@ -1005,6 +1009,7 @@ static int __devinit fs_enet_probe(struct
platform_device *ofdev)
 	struct fs_platform_info *fpi;
 	const u32 *data;
 	const u8 *mac_addr;
+	char *phy_connection_type;
 	int privsize, len, ret = -ENODEV;

 	if (!ofdev->dev.of_match)
@@ -1032,6 +1037,11 @@ static int __devinit fs_enet_probe(struct
platform_device *ofdev)
 						  NULL)))
 		goto out_free_fpi;

+	phy_connection_type = of_get_property(ofdev->dev.of_node,
+			"phy-connection-type", NULL);
+	if (phy_connection_type && strcmp("rmii", phy_connection_type) == 0)
+		fpi->use_rmii = 1;
+
 	privsize = sizeof(*fep) +
 	           sizeof(struct sk_buff **) *
 	           (fpi->rx_ring + fpi->tx_ring);
diff --git a/drivers/net/fs_enet/mac-fec.c b/drivers/net/fs_enet/mac-fec.c
index 61035fc..7ba36c1 100644
--- a/drivers/net/fs_enet/mac-fec.c
+++ b/drivers/net/fs_enet/mac-fec.c
@@ -322,10 +322,11 @@ static void restart(struct net_device *dev)
 	FW(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
 #else
 	/*
-	 * Only set MII mode - do not touch maximum frame length
+	 * Only set MII/RMII mode - do not touch maximum frame length
 	 * configured before.
 	 */
-	FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);
+	FS(fecp, r_cntrl, (fpi->use_rmii) ?
+			FEC_RCNTRL_RMII_MODE : FEC_RCNTRL_MII_MODE);
 #endif
 	/*
 	 * adjust to duplex mode
@@ -381,7 +382,9 @@ static void stop(struct net_device *dev)

 	/* shut down FEC1? that's where the mii bus is */
 	if (fpi->has_phy) {
-		FS(fecp, r_cntrl, FEC_RCNTRL_MII_MODE);	/* MII enable */
+		FS(fecp, r_cntrl, (fpi->use_rmii) ?
+				FEC_RCNTRL_RMII_MODE :
+				FEC_RCNTRL_MII_MODE);	/* MII/RMII enable */
 		FS(fecp, ecntrl, FEC_ECNTRL_PINMUX | FEC_ECNTRL_ETHER_EN);
 		FW(fecp, ievent, FEC_ENET_MII);
 		FW(fecp, mii_speed, feci->mii_speed);
-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH 2/3,v2] serial: Add PSC UART support for MPC5125 SoC
From: vooon341 @ 2011-03-22 14:07 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Anatolij Gustschin, linux-kernel

Adds PSC UART support for MPC5125 SoC.

MPC5125 has different register map than in MPC5121.

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---
v2:
 - Replace hack with replacing struct mpc52xx_psc to proper code.
---
 arch/powerpc/include/asm/mpc52xx_psc.h |   49 ++++
 drivers/tty/serial/mpc52xx_uart.c      |  406 ++++++++++++++++++++++++++++----
 2 files changed, 414 insertions(+), 41 deletions(-)

diff --git a/arch/powerpc/include/asm/mpc52xx_psc.h
b/arch/powerpc/include/asm/mpc52xx_psc.h
index 2966df6..d0ece25 100644
--- a/arch/powerpc/include/asm/mpc52xx_psc.h
+++ b/arch/powerpc/include/asm/mpc52xx_psc.h
@@ -299,4 +299,53 @@ struct mpc512x_psc_fifo {
 #define rxdata_32 rxdata.rxdata_32
 };

+struct mpc5125_psc {
+	u8		mr1;			/* PSC + 0x00 */
+	u8		reserved0[3];
+	u8		mr2;			/* PSC + 0x04 */
+	u8		reserved1[3];
+	struct {
+		u16		status;		/* PSC + 0x08 */
+		u8		reserved2[2];
+		u8		clock_select;	/* PSC + 0x0c */
+		u8		reserved3[3];
+	} sr_csr;
+	u8		command;		/* PSC + 0x10 */
+	u8		reserved4[3];
+	union {					/* PSC + 0x14 */
+		u8		buffer_8;
+		u16		buffer_16;
+		u32		buffer_32;
+	} buffer;
+	struct {
+		u8		ipcr;		/* PSC + 0x18 */
+		u8		reserved5[3];
+		u8		acr;		/* PSC + 0x1c */
+		u8		reserved6[3];
+	} ipcr_acr;
+	struct {
+		u16		isr;		/* PSC + 0x20 */
+		u8		reserved7[2];
+		u16		imr;		/* PSC + 0x24 */
+		u8		reserved8[2];
+	} isr_imr;
+	u8		ctur;			/* PSC + 0x28 */
+	u8		reserved9[3];
+	u8		ctlr;			/* PSC + 0x2c */
+	u8		reserved10[3];
+	u32		ccr;			/* PSC + 0x30 */
+	u32		ac97slots;		/* PSC + 0x34 */
+	u32		ac97cmd;		/* PSC + 0x38 */
+	u32		ac97data;		/* PSC + 0x3c */
+	u8		reserved11[4];
+	u8		ip;			/* PSC + 0x44 */
+	u8		reserved12[3];
+	u8		op1;			/* PSC + 0x48 */
+	u8		reserved13[3];
+	u8		op0;			/* PSC + 0x4c */
+	u8		reserved14[3];
+	u32		sicr;			/* PSC + 0x50 */
+	u8		reserved15[4];	/* make eq. sizeof(mpc52xx_psc) */
+};
+
 #endif  /* __ASM_MPC52xx_PSC_H__ */
diff --git a/drivers/tty/serial/mpc52xx_uart.c
b/drivers/tty/serial/mpc52xx_uart.c
index a0bcd8a..b53c03a 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -121,6 +121,15 @@ struct psc_ops {
 	void		(*fifoc_uninit)(void);
 	void		(*get_irq)(struct uart_port *, struct device_node *);
 	irqreturn_t	(*handle_irq)(struct uart_port *port);
+	u16		(*get_status)(struct uart_port *port);
+	u8		(*get_ipcr)(struct uart_port *port);
+	void		(*command)(struct uart_port *port, u8 cmd);
+	void		(*set_mode)(struct uart_port *port, u8 mr1, u8 mr2);
+	void		(*set_rts)(struct uart_port *port, int state);
+	void		(*enable_ms)(struct uart_port *port);
+	void		(*set_sicr)(struct uart_port *port, u32 val);
+	void		(*set_imr)(struct uart_port *port, u16 val);
+	u8		(*get_mr1)(struct uart_port *port);
 };

 /* setting the prescaler and divisor reg is common for all chips */
@@ -133,6 +142,74 @@ static inline void mpc52xx_set_divisor(struct
mpc52xx_psc __iomem *psc,
 	out_8(&psc->ctlr, divisor & 0xff);
 }

+static inline void mpc5125_set_divisor(struct mpc5125_psc __iomem *psc,
+		u8 prescaler, unsigned int divisor)
+{
+	/* select prescaler */
+	out_8(&psc->mpc52xx_psc_clock_select, prescaler);
+	out_8(&psc->ctur, divisor >> 8);
+	out_8(&psc->ctlr, divisor & 0xff);
+}
+
+static u16 mpc52xx_psc_get_status(struct uart_port *port)
+{
+	return in_be16(&PSC(port)->mpc52xx_psc_status);
+}
+
+static u8 mpc52xx_psc_get_ipcr(struct uart_port *port)
+{
+	return in_8(&PSC(port)->mpc52xx_psc_ipcr);
+}
+
+static void mpc52xx_psc_command(struct uart_port *port, u8 cmd)
+{
+	out_8(&PSC(port)->command, cmd);
+}
+
+static void mpc52xx_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2)
+{
+	out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1);
+	out_8(&PSC(port)->mode, mr1);
+	out_8(&PSC(port)->mode, mr2);
+}
+
+static void mpc52xx_psc_set_rts(struct uart_port *port, int state)
+{
+	if (state)
+		out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS);
+	else
+		out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS);
+}
+
+static void mpc52xx_psc_enable_ms(struct uart_port *port)
+{
+	struct mpc52xx_psc __iomem *psc = PSC(port);
+
+	/* clear D_*-bits by reading them */
+	in_8(&psc->mpc52xx_psc_ipcr);
+	/* enable CTS and DCD as IPC interrupts */
+	out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
+
+	port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
+	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
+}
+
+static void mpc52xx_psc_set_sicr(struct uart_port *port, u32 val)
+{
+	out_be32(&PSC(port)->sicr, val);
+}
+
+static void mpc52xx_psc_set_imr(struct uart_port *port, u16 val)
+{
+	out_be16(&PSC(port)->mpc52xx_psc_imr, val);
+}
+
+static u8 mpc52xx_psc_get_mr1(struct uart_port *port)
+{
+	out_8(&PSC(port)->command, MPC52xx_PSC_SEL_MODE_REG_1);
+	return in_8(&PSC(port)->mode);
+}
+
 #ifdef CONFIG_PPC_MPC52xx
 #define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
 static void mpc52xx_psc_fifo_init(struct uart_port *port)
@@ -302,6 +379,15 @@ static struct psc_ops mpc52xx_psc_ops = {
 	.set_baudrate = mpc5200_psc_set_baudrate,
 	.get_irq = mpc52xx_psc_get_irq,
 	.handle_irq = mpc52xx_psc_handle_irq,
+	.get_status = mpc52xx_psc_get_status,
+	.get_ipcr = mpc52xx_psc_get_ipcr,
+	.command = mpc52xx_psc_command,
+	.set_mode = mpc52xx_psc_set_mode,
+	.set_rts = mpc52xx_psc_set_rts,
+	.enable_ms = mpc52xx_psc_enable_ms,
+	.set_sicr = mpc52xx_psc_set_sicr,
+	.set_imr = mpc52xx_psc_set_imr,
+	.get_mr1 = mpc52xx_psc_get_mr1,
 };

 static struct psc_ops mpc5200b_psc_ops = {
@@ -323,6 +409,15 @@ static struct psc_ops mpc5200b_psc_ops = {
 	.set_baudrate = mpc5200b_psc_set_baudrate,
 	.get_irq = mpc52xx_psc_get_irq,
 	.handle_irq = mpc52xx_psc_handle_irq,
+	.get_status = mpc52xx_psc_get_status,
+	.get_ipcr = mpc52xx_psc_get_ipcr,
+	.command = mpc52xx_psc_command,
+	.set_mode = mpc52xx_psc_set_mode,
+	.set_rts = mpc52xx_psc_set_rts,
+	.enable_ms = mpc52xx_psc_enable_ms,
+	.set_sicr = mpc52xx_psc_set_sicr,
+	.set_imr = mpc52xx_psc_set_imr,
+	.get_mr1 = mpc52xx_psc_get_mr1,
 };

 #endif /* CONFIG_MPC52xx */
@@ -593,9 +688,253 @@ static struct psc_ops mpc512x_psc_ops = {
 	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
 	.get_irq = mpc512x_psc_get_irq,
 	.handle_irq = mpc512x_psc_handle_irq,
+	.get_status = mpc52xx_psc_get_status,
+	.get_ipcr = mpc52xx_psc_get_ipcr,
+	.command = mpc52xx_psc_command,
+	.set_mode = mpc52xx_psc_set_mode,
+	.set_rts = mpc52xx_psc_set_rts,
+	.enable_ms = mpc52xx_psc_enable_ms,
+	.set_sicr = mpc52xx_psc_set_sicr,
+	.set_imr = mpc52xx_psc_set_imr,
+	.get_mr1 = mpc52xx_psc_get_mr1,
 };
 #endif

+#if defined(CONFIG_PPC_MPC5125) && defined(CONFIG_PPC_MPC512x)
+#define PSC_5125(port) ((struct mpc5125_psc __iomem *)((port)->membase))
+#define FIFO_5125(port) ((struct mpc512x_psc_fifo __iomem *)(PSC_5125(port)+1))
+
+static void mpc5125_psc_fifo_init(struct uart_port *port)
+{
+	/* /32 prescaler */
+	out_8(&PSC_5125(port)->mpc52xx_psc_clock_select, 0xdd);
+
+	out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
+	out_be32(&FIFO_5125(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
+	out_be32(&FIFO_5125(port)->txalarm, 1);
+	out_be32(&FIFO_5125(port)->tximr, 0);
+
+	out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
+	out_be32(&FIFO_5125(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
+	out_be32(&FIFO_5125(port)->rxalarm, 1);
+	out_be32(&FIFO_5125(port)->rximr, 0);
+
+	out_be32(&FIFO_5125(port)->tximr, MPC512x_PSC_FIFO_ALARM);
+	out_be32(&FIFO_5125(port)->rximr, MPC512x_PSC_FIFO_ALARM);
+}
+
+static int mpc5125_psc_raw_rx_rdy(struct uart_port *port)
+{
+	return !(in_be32(&FIFO_5125(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
+}
+
+static int mpc5125_psc_raw_tx_rdy(struct uart_port *port)
+{
+	return !(in_be32(&FIFO_5125(port)->txsr) & MPC512x_PSC_FIFO_FULL);
+}
+
+static int mpc5125_psc_rx_rdy(struct uart_port *port)
+{
+	return in_be32(&FIFO_5125(port)->rxsr)
+	    & in_be32(&FIFO_5125(port)->rximr)
+	    & MPC512x_PSC_FIFO_ALARM;
+}
+
+static int mpc5125_psc_tx_rdy(struct uart_port *port)
+{
+	return in_be32(&FIFO_5125(port)->txsr)
+	    & in_be32(&FIFO_5125(port)->tximr)
+	    & MPC512x_PSC_FIFO_ALARM;
+}
+
+static int mpc5125_psc_tx_empty(struct uart_port *port)
+{
+	return in_be32(&FIFO_5125(port)->txsr)
+	    & MPC512x_PSC_FIFO_EMPTY;
+}
+
+static void mpc5125_psc_stop_rx(struct uart_port *port)
+{
+	unsigned long rx_fifo_imr;
+
+	rx_fifo_imr = in_be32(&FIFO_5125(port)->rximr);
+	rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
+	out_be32(&FIFO_5125(port)->rximr, rx_fifo_imr);
+}
+
+static void mpc5125_psc_start_tx(struct uart_port *port)
+{
+	unsigned long tx_fifo_imr;
+
+	tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr);
+	tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
+	out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr);
+}
+
+static void mpc5125_psc_stop_tx(struct uart_port *port)
+{
+	unsigned long tx_fifo_imr;
+
+	tx_fifo_imr = in_be32(&FIFO_5125(port)->tximr);
+	tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
+	out_be32(&FIFO_5125(port)->tximr, tx_fifo_imr);
+}
+
+static void mpc5125_psc_rx_clr_irq(struct uart_port *port)
+{
+	out_be32(&FIFO_5125(port)->rxisr, in_be32(&FIFO_5125(port)->rxisr));
+}
+
+static void mpc5125_psc_tx_clr_irq(struct uart_port *port)
+{
+	out_be32(&FIFO_5125(port)->txisr, in_be32(&FIFO_5125(port)->txisr));
+}
+
+static void mpc5125_psc_write_char(struct uart_port *port, unsigned char c)
+{
+	out_8(&FIFO_5125(port)->txdata_8, c);
+}
+
+static unsigned char mpc5125_psc_read_char(struct uart_port *port)
+{
+	return in_8(&FIFO_5125(port)->rxdata_8);
+}
+
+static void mpc5125_psc_cw_disable_ints(struct uart_port *port)
+{
+	port->read_status_mask =
+		in_be32(&FIFO_5125(port)->tximr) << 16 |
+		in_be32(&FIFO_5125(port)->rximr);
+	out_be32(&FIFO_5125(port)->tximr, 0);
+	out_be32(&FIFO_5125(port)->rximr, 0);
+}
+
+static void mpc5125_psc_cw_restore_ints(struct uart_port *port)
+{
+	out_be32(&FIFO_5125(port)->tximr,
+		(port->read_status_mask >> 16) & 0x7f);
+	out_be32(&FIFO_5125(port)->rximr, port->read_status_mask & 0x7f);
+}
+
+static unsigned int mpc5125_psc_set_baudrate(struct uart_port *port,
+					     struct ktermios *new,
+					     struct ktermios *old)
+{
+	unsigned int baud;
+	unsigned int divisor;
+
+	/*
+	 * Calculate with a /16 prescaler here.
+	 */
+
+	/* uartclk contains the ips freq */
+	baud = uart_get_baud_rate(port, new, old,
+				  port->uartclk / (16 * 0xffff) + 1,
+				  port->uartclk / 16);
+	divisor = (port->uartclk + 8 * baud) / (16 * baud);
+
+	/* enable the /16 prescaler and set the divisor */
+	mpc5125_set_divisor(PSC_5125(port), 0xdd, divisor);
+	return baud;
+}
+
+/* MPC5125 have compatible PSC FIFO Controller.
+ * Special init not needed.
+ */
+
+static u16 mpc5125_psc_get_status(struct uart_port *port)
+{
+	return in_be16(&PSC_5125(port)->mpc52xx_psc_status);
+}
+
+static u8 mpc5125_psc_get_ipcr(struct uart_port *port)
+{
+	return in_8(&PSC_5125(port)->mpc52xx_psc_ipcr);
+}
+
+static void mpc5125_psc_command(struct uart_port *port, u8 cmd)
+{
+	out_8(&PSC_5125(port)->command, cmd);
+}
+
+static void mpc5125_psc_set_mode(struct uart_port *port, u8 mr1, u8 mr2)
+{
+	out_8(&PSC_5125(port)->mr1, mr1);
+	out_8(&PSC_5125(port)->mr2, mr2);
+}
+
+static void mpc5125_psc_set_rts(struct uart_port *port, int state)
+{
+	if (state & TIOCM_RTS)
+		out_8(&PSC_5125(port)->op1, MPC52xx_PSC_OP_RTS);
+	else
+		out_8(&PSC_5125(port)->op0, MPC52xx_PSC_OP_RTS);
+}
+
+static void
+mpc5125_psc_enable_ms(struct uart_port *port)
+{
+	struct mpc5125_psc __iomem *psc = PSC_5125(port);
+
+	/* clear D_*-bits by reading them */
+	in_8(&psc->mpc52xx_psc_ipcr);
+	/* enable CTS and DCD as IPC interrupts */
+	out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
+
+	port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
+	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
+}
+
+static void mpc5125_psc_set_sicr(struct uart_port *port, u32 val)
+{
+	out_be32(&PSC_5125(port)->sicr, val);
+}
+
+static void mpc5125_psc_set_imr(struct uart_port *port, u16 val)
+{
+	out_be16(&PSC_5125(port)->mpc52xx_psc_imr, val);
+}
+
+static u8 mpc5125_psc_get_mr1(struct uart_port *port)
+{
+	return in_8(&PSC_5125(port)->mr1);
+}
+
+static struct psc_ops mpc5125_psc_ops = {
+	.fifo_init = mpc5125_psc_fifo_init,
+	.raw_rx_rdy = mpc5125_psc_raw_rx_rdy,
+	.raw_tx_rdy = mpc5125_psc_raw_tx_rdy,
+	.rx_rdy = mpc5125_psc_rx_rdy,
+	.tx_rdy = mpc5125_psc_tx_rdy,
+	.tx_empty = mpc5125_psc_tx_empty,
+	.stop_rx = mpc5125_psc_stop_rx,
+	.start_tx = mpc5125_psc_start_tx,
+	.stop_tx = mpc5125_psc_stop_tx,
+	.rx_clr_irq = mpc5125_psc_rx_clr_irq,
+	.tx_clr_irq = mpc5125_psc_tx_clr_irq,
+	.write_char = mpc5125_psc_write_char,
+	.read_char = mpc5125_psc_read_char,
+	.cw_disable_ints = mpc5125_psc_cw_disable_ints,
+	.cw_restore_ints = mpc5125_psc_cw_restore_ints,
+	.set_baudrate = mpc5125_psc_set_baudrate,
+	.clock = mpc512x_psc_clock,
+	.fifoc_init = mpc512x_psc_fifoc_init,
+	.fifoc_uninit = mpc512x_psc_fifoc_uninit,
+	.get_irq = mpc512x_psc_get_irq,
+	.handle_irq = mpc512x_psc_handle_irq,
+	.get_status = mpc5125_psc_get_status,
+	.get_ipcr = mpc5125_psc_get_ipcr,
+	.command = mpc5125_psc_command,
+	.set_mode = mpc5125_psc_set_mode,
+	.set_rts = mpc5125_psc_set_rts,
+	.enable_ms = mpc5125_psc_enable_ms,
+	.set_sicr = mpc5125_psc_set_sicr,
+	.set_imr = mpc5125_psc_set_imr,
+	.get_mr1 = mpc5125_psc_get_mr1,
+};
+#endif /* CONFIG_PPC_MPC5125 */
+
+
 static struct psc_ops *psc_ops;

 /* ======================================================================== */
@@ -611,17 +950,14 @@ mpc52xx_uart_tx_empty(struct uart_port *port)
 static void
 mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-	if (mctrl & TIOCM_RTS)
-		out_8(&PSC(port)->op1, MPC52xx_PSC_OP_RTS);
-	else
-		out_8(&PSC(port)->op0, MPC52xx_PSC_OP_RTS);
+	psc_ops->set_rts(port, mctrl & TIOCM_RTS);
 }

 static unsigned int
 mpc52xx_uart_get_mctrl(struct uart_port *port)
 {
 	unsigned int ret = TIOCM_DSR;
-	u8 status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
+	u8 status = psc_ops->get_ipcr(port);

 	if (!(status & MPC52xx_PSC_CTS))
 		ret |= TIOCM_CTS;
@@ -671,15 +1007,7 @@ mpc52xx_uart_stop_rx(struct uart_port *port)
 static void
 mpc52xx_uart_enable_ms(struct uart_port *port)
 {
-	struct mpc52xx_psc __iomem *psc = PSC(port);
-
-	/* clear D_*-bits by reading them */
-	in_8(&psc->mpc52xx_psc_ipcr);
-	/* enable CTS and DCD as IPC interrupts */
-	out_8(&psc->mpc52xx_psc_acr, MPC52xx_PSC_IEC_CTS | MPC52xx_PSC_IEC_DCD);
-
-	port->read_status_mask |= MPC52xx_PSC_IMR_IPC;
-	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
+	psc_ops->enable_ms(port);
 }

 static void
@@ -689,9 +1017,9 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
 	spin_lock_irqsave(&port->lock, flags);

 	if (ctl == -1)
-		out_8(&PSC(port)->command, MPC52xx_PSC_START_BRK);
+		psc_ops->command(port, MPC52xx_PSC_START_BRK);
 	else
-		out_8(&PSC(port)->command, MPC52xx_PSC_STOP_BRK);
+		psc_ops->command(port, MPC52xx_PSC_STOP_BRK);

 	spin_unlock_irqrestore(&port->lock, flags);
 }
@@ -699,7 +1027,6 @@ mpc52xx_uart_break_ctl(struct uart_port *port, int ctl)
 static int
 mpc52xx_uart_startup(struct uart_port *port)
 {
-	struct mpc52xx_psc __iomem *psc = PSC(port);
 	int ret;

 	if (psc_ops->clock) {
@@ -715,15 +1042,15 @@ mpc52xx_uart_startup(struct uart_port *port)
 		return ret;

 	/* Reset/activate the port, clear and enable interrupts */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
-	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	psc_ops->command(port, MPC52xx_PSC_RST_RX);
+	psc_ops->command(port, MPC52xx_PSC_RST_TX);

-	out_be32(&psc->sicr, 0);	/* UART mode DCD ignored */
+	psc_ops->set_sicr(port, 0);	/* UART mode DCD ignored */

 	psc_ops->fifo_init(port);

-	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
-	out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
+	psc_ops->command(port, MPC52xx_PSC_TX_ENABLE);
+	psc_ops->command(port, MPC52xx_PSC_RX_ENABLE);

 	return 0;
 }
@@ -731,15 +1058,13 @@ mpc52xx_uart_startup(struct uart_port *port)
 static void
 mpc52xx_uart_shutdown(struct uart_port *port)
 {
-	struct mpc52xx_psc __iomem *psc = PSC(port);
-
 	/* Shut down the port.  Leave TX active if on a console port */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
+	psc_ops->command(port, MPC52xx_PSC_RST_RX);
 	if (!uart_console(port))
-		out_8(&psc->command, MPC52xx_PSC_RST_TX);
+		psc_ops->command(port, MPC52xx_PSC_RST_TX);

 	port->read_status_mask = 0;
-	out_be16(&psc->mpc52xx_psc_imr, port->read_status_mask);
+	psc_ops->set_imr(port, port->read_status_mask);

 	if (psc_ops->clock)
 		psc_ops->clock(port, 0);
@@ -752,7 +1077,6 @@ static void
 mpc52xx_uart_set_termios(struct uart_port *port, struct ktermios *new,
 			 struct ktermios *old)
 {
-	struct mpc52xx_psc __iomem *psc = PSC(port);
 	unsigned long flags;
 	unsigned char mr1, mr2;
 	unsigned int j;
@@ -812,13 +1136,11 @@ mpc52xx_uart_set_termios(struct uart_port
*port, struct ktermios *new,
 			"Some chars may have been lost.\n");

 	/* Reset the TX & RX */
-	out_8(&psc->command, MPC52xx_PSC_RST_RX);
-	out_8(&psc->command, MPC52xx_PSC_RST_TX);
+	psc_ops->command(port, MPC52xx_PSC_RST_RX);
+	psc_ops->command(port, MPC52xx_PSC_RST_TX);

 	/* Send new mode settings */
-	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
-	out_8(&psc->mode, mr1);
-	out_8(&psc->mode, mr2);
+	psc_ops->set_mode(port, mr1, mr2);
 	baud = psc_ops->set_baudrate(port, new, old);

 	/* Update the per-port timeout */
@@ -828,8 +1150,8 @@ mpc52xx_uart_set_termios(struct uart_port *port,
struct ktermios *new,
 		mpc52xx_uart_enable_ms(port);

 	/* Reenable TX & RX */
-	out_8(&psc->command, MPC52xx_PSC_TX_ENABLE);
-	out_8(&psc->command, MPC52xx_PSC_RX_ENABLE);
+	psc_ops->command(port, MPC52xx_PSC_TX_ENABLE);
+	psc_ops->command(port, MPC52xx_PSC_RX_ENABLE);

 	/* We're all set, release the lock */
 	spin_unlock_irqrestore(&port->lock, flags);
@@ -957,7 +1279,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
 		flag = TTY_NORMAL;
 		port->icount.rx++;

-		status = in_be16(&PSC(port)->mpc52xx_psc_status);
+		status = psc_ops->get_status(port);

 		if (status & (MPC52xx_PSC_SR_PE |
 			      MPC52xx_PSC_SR_FE |
@@ -977,7 +1299,7 @@ mpc52xx_uart_int_rx_chars(struct uart_port *port)
 			}

 			/* Clear error condition */
-			out_8(&PSC(port)->command, MPC52xx_PSC_RST_ERR_STAT);
+			psc_ops->command(port, MPC52xx_PSC_RST_ERR_STAT);

 		}
 		tty_insert_flip_char(tty, ch, flag);
@@ -1060,7 +1382,7 @@ mpc5xxx_uart_process_int(struct uart_port *port)
 		if (psc_ops->tx_rdy(port))
 			keepgoing |= mpc52xx_uart_int_tx_chars(port);

-		status = in_8(&PSC(port)->mpc52xx_psc_ipcr);
+		status = psc_ops->get_ipcr(port);
 		if (status & MPC52xx_PSC_D_DCD)
 			uart_handle_dcd_change(port, !(status & MPC52xx_PSC_DCD));

@@ -1101,14 +1423,12 @@ static void __init
 mpc52xx_console_get_options(struct uart_port *port,
 			    int *baud, int *parity, int *bits, int *flow)
 {
-	struct mpc52xx_psc __iomem *psc = PSC(port);
 	unsigned char mr1;

 	pr_debug("mpc52xx_console_get_options(port=%p)\n", port);

 	/* Read the mode registers */
-	out_8(&psc->command, MPC52xx_PSC_SEL_MODE_REG_1);
-	mr1 = in_8(&psc->mode);
+	mr1 = psc_ops->get_mr1(port);

 	/* CT{U,L}R are write-only ! */
 	*baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
@@ -1299,6 +1619,10 @@ static struct of_device_id mpc52xx_uart_of_match[] = {
 #ifdef CONFIG_PPC_MPC512x
 	{ .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
 #endif
+#ifdef CONFIG_PPC_MPC5125
+	{ .compatible = "fsl,mpc5125-psc-uart", .data = &mpc5125_psc_ops, },
+#endif
+
 	{},
 };

-- 
1.7.1

^ permalink raw reply related

* Re: [PATCH 1/3, v4] powerpc/mpc512x: Add initial support for TWR-MPC5125
From: vooon341 @ 2011-03-22 14:03 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, linux-kernel
In-Reply-To: <AANLkTimDDpCHf7Cpjt5mi=d18OpX2Q4yiwNDK_26j0kD@mail.gmail.com>

Adds Freescale TWR-MPC5125 device tree and platform code.

Currently following is supported:
 - NAND
 - FEC1 and FEC2
 - RTC
 - PSC UART

NAND flash controller require more tests, so it will be later.

Signed-off-by: Vladimir Ermakov <vooon341@gmail.com>
---
v2:
 - add PSC compat string selection
 - add ioctl defines

v3:
 - less verbose interrupt-parent
 - move mpc512x_select_psc_compat() to mpc512x_shared.c
 - remove unneded mpc5125_psc_iopad_init()
 - fix board prefixes

v4:
 - remove device_type from ethernet nodes
 - add aliases for ethernet nodes
 - add phy-connection-type
 - extend size of rootfs partition
---
 arch/powerpc/boot/dts/mpc5125twr.dts         |  376 ++++++++++++++++++++++++++
 arch/powerpc/platforms/512x/Kconfig          |   14 +
 arch/powerpc/platforms/512x/Makefile         |    1 +
 arch/powerpc/platforms/512x/clock.c          |    9 +-
 arch/powerpc/platforms/512x/mpc5125_twr.c    |  142 ++++++++++
 arch/powerpc/platforms/512x/mpc512x.h        |    5 +-
 arch/powerpc/platforms/512x/mpc512x_shared.c |   26 ++-
 7 files changed, 569 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/boot/dts/mpc5125twr.dts
b/arch/powerpc/boot/dts/mpc5125twr.dts
new file mode 100644
index 0000000..ca3851d
--- /dev/null
+++ b/arch/powerpc/boot/dts/mpc5125twr.dts
@@ -0,0 +1,376 @@
+/*
+ * STx/Freescale ADS5125 MPC5125 silicon
+ *
+ * Copyright (C) 2009 Freescale Semiconductor Inc. All rights reserved.
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "mpc5125twr"; // In BSP "mpc5125ads"
+	compatible = "fsl,mpc5125ads";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&ipic>;
+
+	aliases {
+		ethernet0 = &eth0;
+		ethernet1 = &eth1;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5125@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <0x20>;	// 32 bytes
+			i-cache-line-size = <0x20>;	// 32 bytes
+			d-cache-size = <0x8000>;	// L1, 32K
+			i-cache-size = <0x8000>;	// L1, 32K
+			timebase-frequency = <49500000>;// 49.5 MHz (csb/4)
+			bus-frequency = <198000000>;	// 198 MHz csb bus
+			clock-frequency = <396000000>;	// 396 MHz ppc core
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x10000000>;	// 256MB at 0
+	};
+
+	sram@30000000 {
+		compatible = "fsl,mpc5121-sram";
+		reg = <0x30000000 0x08000>;		// 32K at 0x30000000
+	};
+
+	nfc@40000000 {
+		compatible = "fsl,mpc5125-nfc";
+		reg = <0x40000000 0x100000>;	// 1M at 0x40000000
+		interrupts = <6 0x8>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		bank-width = <1>;
+		write-size = <4096>;
+		spare-size = <128>;
+		chips = <1>;
+		// NOTE: partition map different than in BSP
+		// First three is the same as in BSP, other differ.
+		nand-spl@0 {
+			label = "loader";
+			reg = <0x00000000 0x00100000>;
+			read-only;
+		};
+		uboot@100000 {
+			label = "uboot";
+			reg = <0x00100000 0x00100000>;
+			read-only;
+		};
+		uboot-env@200000 {
+			label = "uboot-env";
+			reg = <0x00200000 0x00100000>;
+			read-only;
+		};
+		kernel@300000 {
+			label = "kernel";
+			reg = <0x00300000 0x00800000>;
+		};
+		device-tree@b00000 {
+			label = "device-tree";
+			reg = <0x00b00000 0x00100000>;
+		};
+		ramboot-rootfs@c00000 {
+			label = "ramboot-rootfs";
+			reg = <0x00c00000 0x00800000>;
+		};
+		rootfs@1400000 {
+			label = "rootfs";
+			reg = <0x01400000 0x02800000>;
+		};
+		user@2800000 {
+			label = "user";
+			reg = <0x03C00000 0x01400000>;
+		};
+		SRAM@4200000 {
+			label = "SRAM"; // NVRAM emul
+			reg = <0x05000000 0x01400000>;
+		};
+		prom@5600000 {
+			label = "prom";
+			reg = <0x06400000 0x01400000>;
+		};
+		//data@2800000 {
+		//	label = "data";
+		//	reg = <0x28000000 0xeac00000>;
+		//};
+	};
+
+	soc@80000000 {
+		compatible = "fsl,mpc5121-immr";
+		device_type = "soc";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <2>;
+		ranges = <0x0 0x80000000 0x400000>;
+		reg = <0x80000000 0x400000>;
+		bus-frequency = <66000000>;	// 66 MHz ips bus
+
+		// IPIC
+		// interrupts cell = <intr #, sense>
+		// sense values match linux IORESOURCE_IRQ_* defines:
+		// sense == 8: Level, low assertion
+		// sense == 2: Edge, high-to-low change
+		//
+		ipic: interrupt-controller@c00 {
+			compatible = "fsl,mpc5121-ipic", "fsl,ipic";
+			interrupt-controller;
+			#address-cells = <0>;
+			#interrupt-cells = <2>;
+			reg = <0xc00 0x100>;
+		};
+
+		rtc@a00 {	// Real time clock
+			compatible = "fsl,mpc5121-rtc";
+			reg = <0xa00 0x100>;
+			interrupts = <79 0x8 80 0x8>;
+		};
+
+		reset@e00 {	// Reset module
+			compatible = "fsl,mpc5121-reset";
+			reg = <0xe00 0x100>;
+		};
+
+		clock@f00 {	// Clock control
+			compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
+			reg = <0xf00 0x100>;
+		};
+
+		pmc@1000{  // Power Management Controller
+			compatible = "fsl,mpc5121-pmc";
+			reg = <0x1000 0x100>;
+			interrupts = <83 0x2>;
+		};
+
+		gpio@1100 {
+			compatible = "fsl,mpc5125-gpio";
+			cell-index = <0>;
+			reg = <0x1100 0x080>;
+			interrupts = <78 0x8>;
+		};
+
+		gpio@1180 {
+			compatible = "fsl,mpc5125-gpio1";
+			cell-index = <1>;
+			reg = <0x1180 0x080>;
+			interrupts = <78 0x8>;
+		};
+
+		can@1300 { // CAN rev.2
+			compatible = "fsl,mpc5121-mscan";
+			cell-index = <0>;
+			interrupts = <12 0x8>;
+			reg = <0x1300 0x80>;
+		};
+
+		can@1380 {
+			compatible = "fsl,mpc5121-mscan";
+			cell-index = <1>;
+			interrupts = <13 0x8>;
+			reg = <0x1380 0x80>;
+		};
+
+		sdhc@1500 {
+			compatible = "fsl,mpc5125-sdhc";
+			interrupts = <8 0x8>;
+			reg = <0x1500 0x100>;
+		};
+
+		i2c@1700 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <0>;
+			reg = <0x1700 0x20>;
+			interrupts = <0x9 0x8>;
+			fsl5200-clocking;
+		};
+
+		i2c@1720 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <1>;
+			reg = <0x1720 0x20>;
+			interrupts = <0xa 0x8>;
+			fsl5200-clocking;
+		};
+
+		i2c@1740 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl-i2c";
+			cell-index = <2>;
+			reg = <0x1740 0x20>;
+			interrupts = <0xb 0x8>;
+			fsl5200-clocking;
+		};
+
+		i2ccontrol@1760 {
+			compatible = "fsl,mpc5121-i2c-ctrl";
+			reg = <0x1760 0x8>;
+		};
+
+		//diu@2100 {
+		//	device_type = "display";
+		//	compatible = "fsl-diu";
+		//	reg = <0x2100 0x100>;
+		//	interrupts = <64 0x8>;
+		//};
+
+		// MPC5125e has two more CAN ports
+		// but they are not used on ADS5125
+		//can@2300 {
+		//	compatible = "fsl,mpc5121-mscan";
+		//	cell-index = <2>;
+		//	interrupts = <90 0x8>;
+		//	reg = <0x2300 0x80>;
+		//};
+
+		//can@2380 {
+		//	compatible = "fsl,mpc5121-mscan";
+		//	cell-index = <3>;
+		//	interrupts = <91 0x8>;
+		//	reg = <0x2380 0x80>;
+		//};
+
+		mdio@2800 {
+			compatible = "fsl,mpc5121-fec-mdio";
+			reg = <0x2800 0x800>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy0: ethernet-phy@0 {
+				compatible = "smsc,lan8710";
+				reg = <1>;
+			};
+		};
+
+		eth0: ethernet@2800 {
+			compatible = "fsl,mpc5121-fec";
+			reg = <0x2800 0x800>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <4 0x8>;
+			phy-handle = < &phy0 >;
+			phy-connection-type = "rmii";
+		};
+
+		// USB ULPI1
+		//usb@3000 {
+		//	device_type = "usb";
+		//	compatible = "fsl-usb2-dr";
+		//	reg = <0x3000 0x400>;
+		//	#address-cells = <1>;
+		//	#size-cells = <0>;
+		//	interrupts = <43 0x8>;
+		//	dr_mode = "host";
+		//	phy_type = "ulpi";
+		//	big-endian-regs;
+		//};
+
+		// USB ULPI2
+		//usb@4000 {
+		//	device_type = "usb";
+		//	compatible = "fsl-usb2-dr";
+		//	reg = <0x4000 0x400>;
+		//	#address-cells = <1>;
+		//	#size-cells = <0>;
+		//	interrupts = <44 0x8>;
+		//	dr_mode = "otg";
+		//	phy_type = "ulpi";
+		//	big-endian-regs;
+		//};
+
+		mdio@4800 {
+			compatible = "fsl,mpc5121-fec-mdio";
+			reg = <0x4800 0x800>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			phy1: ethernet-phy@0 {
+				compatible = "micrel,ksz8041";
+				reg = <1>;
+			};
+		};
+
+		eth1: ethernet@4800 {
+			device_type = "network";
+			compatible = "fsl,mpc5121-fec";
+			reg = <0x4800 0x800>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <5 0x8>;
+			phy-handle = < &phy1 >;
+			phy-connection-type = "rmii";
+		};
+
+		// IO control
+		ioctl@a000 {
+			compatible = "fsl,mpc5125-ioctl";
+			reg = <0xA000 0x1000>;
+		};
+
+		// PSC0 in ac97 mode
+		//ac97@11000 {
+		//	device_type = "sound";
+		//	compatible = "fsl,mpc5125-psc-ac97", "fsl,mpc5125-psc";
+		//	cell-index = <0>;
+		//	reg = <0x11000 0x100>;
+		//	interrupts = <40 0x8>;
+		//	fsl,mode = "ac97-slave";
+		//	rx-fifo-size = <384>;
+		//	tx-fifo-size = <384>;
+		//};
+
+		// 5125 PSCs are not 52xx or 5121 PSC compatible
+		// PSC1 uart0 aka ttyPSC0
+		serial@11100 {
+			device_type = "serial";
+			compatible = "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number = <0>;
+			cell-index = <1>;
+			reg = <0x11100 0x100>;
+			interrupts = <40 0x8 71 0x8>;
+			fsl,rx-fifo-size = <16>;
+			fsl,tx-fifo-size = <16>;
+			nodcd;
+		};
+
+		// PSC9 uart1 aka ttyPSC1
+		serial@11900 {
+			device_type = "serial";
+			compatible = "fsl,mpc5125-psc-uart", "fsl,mpc5125-psc";
+			port-number = <1>;
+			cell-index = <9>;
+			reg = <0x11900 0x100>;
+			interrupts = <40 0x8 32 0x8>;
+			fsl,rx-fifo-size = <16>;
+			fsl,tx-fifo-size = <16>;
+			nodcd;
+		};
+
+		pscfifo@11f00 {
+			compatible = "fsl,mpc5121-psc-fifo";
+			reg = <0x11f00 0x100>;
+			interrupts = <40 0x8>;
+		};
+
+		dma@14000 {
+			compatible = "fsl,mpc5121-dma"; // BSP name: "mpc512x-dma2"
+			reg = <0x14000 0x1800>;
+			interrupts = <65 0x8>;
+		};
+	};
+};
diff --git a/arch/powerpc/platforms/512x/Kconfig
b/arch/powerpc/platforms/512x/Kconfig
index 27b0651..0dde4b0 100644
--- a/arch/powerpc/platforms/512x/Kconfig
+++ b/arch/powerpc/platforms/512x/Kconfig
@@ -26,6 +26,20 @@ config MPC5121_GENERIC
 	  Compatible boards include:  Protonic LVT base boards (ZANMCU
 	  and VICVT2).

+config PPC_MPC5125
+	bool "Generic support for MPC5125 based boards"
+	depends on PPC_MPC512x
+	select DEFAULT_UIMAGE
+	select PPC_INDIRECT_PCI
+	default n
+
+config MPC5125_TWR
+	bool "Freescale MPC5125 Tower system"
+	depends on PPC_MPC512x
+	select PPC_MPC5125
+	help
+	  This option enables support for the MPC5125 TWR board.
+
 config PDM360NG
 	bool "ifm PDM360NG board"
 	depends on PPC_MPC512x
diff --git a/arch/powerpc/platforms/512x/Makefile
b/arch/powerpc/platforms/512x/Makefile
index 4efc1c4..5c17561 100644
--- a/arch/powerpc/platforms/512x/Makefile
+++ b/arch/powerpc/platforms/512x/Makefile
@@ -5,3 +5,4 @@ obj-y				+= clock.o mpc512x_shared.o
 obj-$(CONFIG_MPC5121_ADS)	+= mpc5121_ads.o mpc5121_ads_cpld.o
 obj-$(CONFIG_MPC5121_GENERIC)	+= mpc5121_generic.o
 obj-$(CONFIG_PDM360NG)		+= pdm360ng.o
+obj-$(CONFIG_MPC5125_TWR)	+= mpc5125_twr.o
diff --git a/arch/powerpc/platforms/512x/clock.c
b/arch/powerpc/platforms/512x/clock.c
index 3dc2a8d..07e0bc0 100644
--- a/arch/powerpc/platforms/512x/clock.c
+++ b/arch/powerpc/platforms/512x/clock.c
@@ -27,6 +27,8 @@
 #include <asm/mpc5xxx.h>
 #include <asm/clk_interface.h>

+#include "mpc512x.h"
+
 #undef CLK_DEBUG

 static int clocks_initialized;
@@ -679,8 +681,13 @@ static void psc_clks_init(void)
 	struct device_node *np;
 	const u32 *cell_index;
 	struct platform_device *ofdev;
+	char *psc_compat;
+
+	psc_compat = mpc512x_select_psc_compat();
+	if (!psc_compat)
+		return;

-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	for_each_compatible_node(np, NULL, psc_compat) {
 		cell_index = of_get_property(np, "cell-index", NULL);
 		if (cell_index) {
 			int pscnum = *cell_index;
diff --git a/arch/powerpc/platforms/512x/mpc5125_twr.c
b/arch/powerpc/platforms/512x/mpc5125_twr.c
new file mode 100644
index 0000000..7c7facf
--- /dev/null
+++ b/arch/powerpc/platforms/512x/mpc5125_twr.c
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2010 LimePC Multimedia Technologies Co., Limited
+ * Copyright (C) 2011 Vladimir Ermakov <vooon341@gmail.com>
+ *
+ * Based on original Freescale Semiconductor BSP
+ * written by Cloudy Chen <chen_yunsong@mtcera.com>
+ *
+ * MPC5125 Tower board setup
+ *
+ * This 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/of_platform.h>
+
+#include <asm/machdep.h>
+#include <asm/ipic.h>
+#include <asm/prom.h>
+#include <asm/time.h>
+
+#include <sysdev/fsl_soc.h>
+
+#include <linux/bootmem.h>
+#include <asm/rheap.h>
+
+#include "mpc512x.h"
+
+/* IOCTL registers for USB1/FEC2 */
+#define IOCTL_USB1_DATA0	0x63
+#define IOCTL_USB1_DATA1	0x64
+#define IOCTL_USB1_DATA2	0x65
+#define IOCTL_USB1_DATA3	0x66
+#define IOCTL_USB1_DATA4	0x67
+#define IOCTL_USB1_DATA5	0x68
+#define IOCTL_USB1_DATA6	0x69
+#define IOCTL_USB1_DATA7	0x6A
+#define IOCTL_USB1_STOP		0x6B
+#define IOCTL_USB1_CLK		0x6C
+#define IOCTL_USB1_NEXT		0x6D
+#define IOCTL_USB1_DIR		0x6E
+
+/* Pin modes */
+#define IOCTL_DEFAULT_MODE	0x03 /* FUNCMUX=0, PUD=0, PUE=0, DS=3 */
+#define IOCTL_FEC2_MODE		0x43 /* FUNCMUX=2, PUD=0, PUE=0, DS=3 */
+
+/* Select mode of USB1 pads.
+ * They could be configured as USB (default), FEC2
+ * and several PSC's and/or GPIO's.
+ * Board specific. It can be platform specific in the future.
+ */
+static void mpc5125_twr_fec2_usb_iopad_init(void __iomem *ioctl, int isusb)
+{
+	int i;
+	const u8 offset[12] = {
+		IOCTL_USB1_DATA0, IOCTL_USB1_DATA1,
+		IOCTL_USB1_DATA2, IOCTL_USB1_DATA3,
+		IOCTL_USB1_DATA4, IOCTL_USB1_DATA5,
+		IOCTL_USB1_DATA6, IOCTL_USB1_DATA7,
+		IOCTL_USB1_STOP, IOCTL_USB1_CLK,
+		IOCTL_USB1_NEXT, IOCTL_USB1_DIR
+	};
+	u8 mode;
+
+	mode = (isusb) ? IOCTL_DEFAULT_MODE : IOCTL_FEC2_MODE;
+	for (i = 0; i < ARRAY_SIZE(offset); i++)
+		out_8(ioctl + offset[i], mode);
+}
+
+static void __init mpc5125_twr_setup_arch(void)
+{
+	struct device_node *np;
+
+	printk(KERN_INFO "TWR-MPC5125 board from Freescale Semiconductor\n");
+
+	/*
+	 * io pad config
+	 */
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5125-ioctl");
+	if (np) {
+		void __iomem *ioctl = of_iomap(np, 0);
+
+		mpc5125_twr_fec2_usb_iopad_init(ioctl, 0);
+
+		of_node_put(np);
+		iounmap(ioctl);
+	}
+}
+
+static struct of_device_id __initdata of_bus_ids[] = {
+	{ .name = "soc", },
+	{},
+};
+
+static void __init mpc5125_twr_declare_of_platform_devices(void)
+{
+	struct device_node *np;
+
+	if (of_platform_bus_probe(NULL, of_bus_ids, NULL))
+		printk(KERN_ERR __FILE__ ": "
+			"Error while probing of_platform bus\n");
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mpc5125-nfc");
+	if (np) {
+		of_platform_device_create(np, NULL, NULL);
+		of_node_put(np);
+	}
+}
+
+static void __init mpc5125_twr_init(void)
+{
+	mpc5125_twr_declare_of_platform_devices();
+	mpc5121_clk_init();
+	mpc512x_restart_init();
+	mpc512x_psc_fifo_init();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc5125_twr_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+
+	return of_flat_dt_is_compatible(root, "fsl,mpc5125ads");
+}
+
+define_machine(mpc5125_twr) {
+	.name			= "TWR-MPC5125",
+	.probe			= mpc5125_twr_probe,
+	.setup_arch		= mpc5125_twr_setup_arch,
+	.init			= mpc5125_twr_init,
+	.init_IRQ		= mpc512x_init_IRQ,
+	.get_irq		= ipic_get_irq,
+	.calibrate_decr		= generic_calibrate_decr,
+	.restart		= mpc512x_restart,
+};
diff --git a/arch/powerpc/platforms/512x/mpc512x.h
b/arch/powerpc/platforms/512x/mpc512x.h
index 1ab6d11..91c903f 100644
--- a/arch/powerpc/platforms/512x/mpc512x.h
+++ b/arch/powerpc/platforms/512x/mpc512x.h
@@ -13,8 +13,11 @@
 #define __MPC512X_H__
 extern void __init mpc512x_init_IRQ(void);
 extern void __init mpc512x_init(void);
+extern void __init mpc512x_restart_init(void);
 extern int __init mpc5121_clk_init(void);
-void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_declare_of_platform_devices(void);
+extern void __init mpc512x_psc_fifo_init(void);
+extern char *mpc512x_select_psc_compat(void);
 extern void mpc512x_restart(char *cmd);
 extern void mpc512x_init_diu(void);
 extern void mpc512x_setup_diu(void);
diff --git a/arch/powerpc/platforms/512x/mpc512x_shared.c
b/arch/powerpc/platforms/512x/mpc512x_shared.c
index e41ebbd..e79d8ae 100644
--- a/arch/powerpc/platforms/512x/mpc512x_shared.c
+++ b/arch/powerpc/platforms/512x/mpc512x_shared.c
@@ -32,7 +32,7 @@

 static struct mpc512x_reset_module __iomem *reset_module_base;

-static void __init mpc512x_restart_init(void)
+void __init mpc512x_restart_init(void)
 {
 	struct device_node *np;

@@ -382,6 +382,21 @@ void __init mpc512x_declare_of_platform_devices(void)

 #define DEFAULT_FIFO_SIZE 16

+char *mpc512x_select_psc_compat(void)
+{
+	char *psc_compats[] = {
+		"fsl,mpc5121-psc",
+		"fsl,mpc5125-psc"
+	};
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(psc_compats); i++)
+		if (of_find_compatible_node(NULL, NULL, psc_compats[i]))
+			return psc_compats[i];
+
+	return NULL;
+}
+
 static unsigned int __init get_fifo_size(struct device_node *np,
 					 char *prop_name)
 {
@@ -407,9 +422,16 @@ void __init mpc512x_psc_fifo_init(void)
 	void __iomem *psc;
 	unsigned int tx_fifo_size;
 	unsigned int rx_fifo_size;
+	char *psc_compat;
 	int fifobase = 0; /* current fifo address in 32 bit words */

-	for_each_compatible_node(np, NULL, "fsl,mpc5121-psc") {
+	psc_compat = mpc512x_select_psc_compat();
+	if (!psc_compat) {
+		pr_err("%s: no compatible devices found\n", __func__);
+		return;
+	}
+
+	for_each_compatible_node(np, NULL, psc_compat) {
 		tx_fifo_size = get_fifo_size(np, "fsl,tx-fifo-size");
 		rx_fifo_size = get_fifo_size(np, "fsl,rx-fifo-size");

-- 
1.7.1

^ permalink raw reply related

* Booting with ramdisk in kernel
From: Guillaume Dargaud @ 2011-03-22 11:04 UTC (permalink / raw)
  To: linuxppc-dev

Hello all,
I already posted this on the buildroot mailing list, so apologies for the dupe, but maybe it's more relevant here.

I'm trying to do something very classic, but it doesn't seem to work and the more I read about it the more I'm confused 
by the amount of antiquated info and nearly-but-not-quite-so relevant info (like doing a temporary ramdisk before the 
'real' OS loads).

So I have a kernel and a buildroot-generated OS, currently on an NFS server. I boot with the following kernel parameters 
and everything goes fine:
console=ttyUL0,115200 rw root=/dev/nfs ip=bootp

Now I want to embed that OS in the kernel (no need for a network anymore as the kernel is on a flash mem and I wrote my 
own bootloader). So I did the following:
- add ROOTFS CPIO to the buildroot options and make a new version
- point CONFIG_INITRAMFS_SOURCE to the resulting rootfs.cpio file
- change the kernel parameters to "console=ttyUL0,115200 root=/dev/ram" (that's in a dts file)
- some documentation talks about CONFIG_BLK_DEV_RAM but I can't find that option in the menuconfig, so maybe that's the 
problem.

When my bootloader jumps to 0x400000, the kernel stops instantly without even a blip on the console. A debugger reveals 
that it stops at 0x401718... I have no idea what's going on at this stage.

What am I doing wrong ?
-- 
Guillaume Dargaud
http://www.gdargaud.net/

^ permalink raw reply

* Re: [PATCH v6 6/6] powerpc, tqm5200: update tqm5200_defconfig to fit for charon board.
From: Wolfram Sang @ 2011-03-22  9:10 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	linuxppc-dev, Wolfgang Denk
In-Reply-To: <1300782452-528-7-git-send-email-hs@denx.de>

[-- Attachment #1: Type: text/plain, Size: 719 bytes --]

>     As this board is tqm5200 based, added necessary changes
>     to the tqm5200_defconfig. In previous patchserie I added
>     the changes to mpc5200_defconfig, as Wolfram Sang mentioned,
>     but as tqm5200_defconfig is in mainline, and the board is
>     tqm5200 based, I think, thats the appropriate place, as

I'd think the perfect solution would have been to merge the
tqm-defconfig into the mpc5200-defconfig entirely and get rid of it.
That being said, I don't think this issue is big enough to block this
series, so fine enough with me.

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH v1 1/6] powerpc, 5200: add support for charon board
From: Wolfram Sang @ 2011-03-22  9:06 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	linuxppc-dev, Wolfgang Denk
In-Reply-To: <1300782452-528-2-git-send-email-hs@denx.de>

[-- Attachment #1: Type: text/plain, Size: 1526 bytes --]

On Tue, Mar 22, 2011 at 09:27:27AM +0100, Heiko Schocher wrote:
> Signed-off-by: Heiko Schocher <hs@denx.de>
> Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: Wolfram Sang <w.sang@pengutronix.de>
> cc: Grant Likely <grant.likely@secretlab.ca>
> cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> cc: linux-fbdev@vger.kernel.org
> cc: devicetree-discuss@ozlabs.org
> cc: Ben Dooks <ben@simtec.co.uk>
> cc: Vincent Sanders <vince@simtec.co.uk>
> cc: Samuel Ortiz <sameo@linux.intel.com>
> cc: linux-kernel@vger.kernel.org
> cc: Randy Dunlap <rdunlap@xenotime.net>
> cc: Wolfgang Denk <wd@denx.de>
> cc: Paul Mundt <lethal@linux-sh.org>
> ---
> - changes since v1:
>   add comments from Wolfram Sang
>   - no defconfig file
>   - comment corrected in DTS
>   - boardlist sorted alphabetically
>   - commit log without boardinfo
> - changes for v6:
>   - rebased against current head
>   - repost complete patchserie
>   - added Acked-by from Benjamin Herrenschmidt
> 
>  arch/powerpc/boot/dts/charon.dts             |  226 ++++++++++++++++++++++++++
>  arch/powerpc/platforms/52xx/mpc5200_simple.c |    1 +
>  2 files changed, 227 insertions(+), 0 deletions(-)
>  create mode 100644 arch/powerpc/boot/dts/charon.dts

AFAICR all my concerns have been addressed, so

Acked-by: Wolfram Sang <w.sang@pengutronix.de>

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* [PATCH v1 1/6] powerpc, 5200: add support for charon board
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  add comments from Wolfram Sang
  - no defconfig file
  - comment corrected in DTS
  - boardlist sorted alphabetically
  - commit log without boardinfo
- changes for v6:
  - rebased against current head
  - repost complete patchserie
  - added Acked-by from Benjamin Herrenschmidt

 arch/powerpc/boot/dts/charon.dts             |  226 ++++++++++++++++++++++++++
 arch/powerpc/platforms/52xx/mpc5200_simple.c |    1 +
 2 files changed, 227 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/charon.dts

diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
new file mode 100644
index 0000000..9776889
--- /dev/null
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -0,0 +1,226 @@
+/*
+ * charon board Device Tree Source
+ *
+ * Copyright (C) 2007 Semihalf
+ * Marian Balakowicz <m8@semihalf.com>
+ *
+ * Copyright (C) 2010 DENX Software Engineering GmbH
+ * Heiko Schocher <hs@denx.de>
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/ {
+	model = "anon,charon";
+	compatible = "anon,charon";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&mpc5200_pic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		PowerPC,5200@0 {
+			device_type = "cpu";
+			reg = <0>;
+			d-cache-line-size = <32>;
+			i-cache-line-size = <32>;
+			d-cache-size = <0x4000>;	// L1, 16K
+			i-cache-size = <0x4000>;	// L1, 16K
+			timebase-frequency = <0>;	// from bootloader
+			bus-frequency = <0>;		// from bootloader
+			clock-frequency = <0>;		// from bootloader
+		};
+	};
+
+	memory {
+		device_type = "memory";
+		reg = <0x00000000 0x08000000>;	// 128MB
+	};
+
+	soc5200@f0000000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "fsl,mpc5200-immr";
+		ranges = <0 0xf0000000 0x0000c000>;
+		reg = <0xf0000000 0x00000100>;
+		bus-frequency = <0>;		// from bootloader
+		system-frequency = <0>;		// from bootloader
+
+		cdm@200 {
+			compatible = "fsl,mpc5200-cdm";
+			reg = <0x200 0x38>;
+		};
+
+		mpc5200_pic: interrupt-controller@500 {
+			// 5200 interrupts are encoded into two levels;
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			compatible = "fsl,mpc5200-pic";
+			reg = <0x500 0x80>;
+		};
+
+		timer@600 {	// General Purpose Timer
+			compatible = "fsl,mpc5200-gpt";
+			reg = <0x600 0x10>;
+			interrupts = <1 9 0>;
+			fsl,has-wdt;
+		};
+
+		can@900 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 17 0>;
+			reg = <0x900 0x80>;
+		};
+
+		can@980 {
+			compatible = "fsl,mpc5200-mscan";
+			interrupts = <2 18 0>;
+			reg = <0x980 0x80>;
+		};
+
+		gpio_simple: gpio@b00 {
+			compatible = "fsl,mpc5200-gpio";
+			reg = <0xb00 0x40>;
+			interrupts = <1 7 0>;
+			gpio-controller;
+			#gpio-cells = <2>;
+		};
+
+		usb@1000 {
+			compatible = "fsl,mpc5200-ohci","ohci-be";
+			reg = <0x1000 0xff>;
+			interrupts = <2 6 0>;
+		};
+
+		dma-controller@1200 {
+			device_type = "dma-controller";
+			compatible = "fsl,mpc5200-bestcomm";
+			reg = <0x1200 0x80>;
+			interrupts = <3 0 0  3 1 0  3 2 0  3 3 0
+			              3 4 0  3 5 0  3 6 0  3 7 0
+			              3 8 0  3 9 0  3 10 0  3 11 0
+			              3 12 0  3 13 0  3 14 0  3 15 0>;
+		};
+
+		xlb@1f00 {
+			compatible = "fsl,mpc5200-xlb";
+			reg = <0x1f00 0x100>;
+		};
+
+		serial@2000 {		// PSC1
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2000 0x100>;
+			interrupts = <2 1 0>;
+		};
+
+		serial@2400 {		// PSC3
+			compatible = "fsl,mpc5200-psc-uart";
+			reg = <0x2400 0x100>;
+			interrupts = <2 3 0>;
+		};
+
+		ethernet@3000 {
+			compatible = "fsl,mpc5200-fec";
+			reg = <0x3000 0x400>;
+			local-mac-address = [ 00 00 00 00 00 00 ];
+			interrupts = <2 5 0>;
+			fixed-link = <1 1 100 0 0>;
+		};
+
+		mdio@3000 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-mdio";
+			reg = <0x3000 0x400>;       // fec range, since we need to setup fec interrupts
+			interrupts = <2 5 0>;   // these are for "mii command finished", not link changes & co.
+		};
+
+		ata@3a00 {
+			compatible = "fsl,mpc5200-ata";
+			reg = <0x3a00 0x100>;
+			interrupts = <2 7 0>;
+		};
+
+		i2c@3d00 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d00 0x40>;
+			interrupts = <2 15 0>;
+		};
+
+
+		i2c@3d40 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "fsl,mpc5200-i2c","fsl-i2c";
+			reg = <0x3d40 0x40>;
+			interrupts = <2 16 0>;
+
+			dtt@28 {
+				compatible = "national,lm80";
+				reg = <0x28>;
+			};
+
+			rtc@68 {
+				compatible = "dallas,ds1374";
+				reg = <0x68>;
+			};
+		};
+
+		sram@8000 {
+			compatible = "fsl,mpc5200-sram";
+			reg = <0x8000 0x4000>;
+		};
+	};
+
+	localbus {
+		compatible = "fsl,mpc5200-lpb","simple-bus";
+		#address-cells = <2>;
+		#size-cells = <1>;
+		ranges = <	0 0 0xfc000000 0x02000000
+				3 0 0xe8000000 0x00080000>;
+
+		flash@0,0 {
+			compatible = "cfi-flash";
+			reg = <0 0 0x02000000>;
+			bank-width = <4>;
+			device-width = <2>;
+			#size-cells = <1>;
+			#address-cells = <1>;
+		};
+
+		mram0@3,0 {
+			compatible = "mtd-ram";
+			reg = <3 0x00000 0x80000>;
+			bank-width = <1>;
+		};
+	};
+
+	pci@f0000d00 {
+		#interrupt-cells = <1>;
+		#size-cells = <2>;
+		#address-cells = <3>;
+		device_type = "pci";
+		compatible = "fsl,mpc5200-pci";
+		reg = <0xf0000d00 0x100>;
+		interrupt-map-mask = <0xf800 0 0 7>;
+		interrupt-map = <0xc000 0 0 1 &mpc5200_pic 0 0 3
+				 0xc000 0 0 2 &mpc5200_pic 0 0 3
+				 0xc000 0 0 3 &mpc5200_pic 0 0 3
+				 0xc000 0 0 4 &mpc5200_pic 0 0 3>;
+		clock-frequency = <0>; // From boot loader
+		interrupts = <2 8 0 2 9 0 2 10 0>;
+		bus-range = <0 0>;
+		ranges = <0x42000000 0 0x80000000 0x80000000 0 0x10000000
+			  0x02000000 0 0x90000000 0x90000000 0 0x10000000
+			  0x01000000 0 0x00000000 0xa0000000 0 0x01000000>;
+	};
+};
diff --git a/arch/powerpc/platforms/52xx/mpc5200_simple.c b/arch/powerpc/platforms/52xx/mpc5200_simple.c
index e36d6e2..846b789 100644
--- a/arch/powerpc/platforms/52xx/mpc5200_simple.c
+++ b/arch/powerpc/platforms/52xx/mpc5200_simple.c
@@ -50,6 +50,7 @@ static void __init mpc5200_simple_setup_arch(void)
 
 /* list of the supported boards */
 static const char *board[] __initdata = {
+	"anon,charon",
 	"intercontrol,digsy-mtc",
 	"manroland,mucmc52",
 	"manroland,uc101",
-- 
1.7.4

^ permalink raw reply related

* [PATCH v6 4/6] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

- add binding to OF, compatible name "smi,sm501"

Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
      - get rid of "#if defined(CONFIG_PPC_MPC52xx)" usage
        hide this in DTS, as Paul suggested.
    - i/o routine patch
    - edid support patch
- changes since v4
  replace remaining CONFIG_PPC_MPC52xx with CONFIG_OF, as
  it is no longer MPC52xx only.
- changes since v5
  free edid_data after its usage, as it is no longer needed,
  suggested from Paul Mundt. Also fall back to default if
  kmemdup(edid_data) fails.
- changes for v6:
  - repost complete patchserie
  - rebased against current head

 Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++++++
 drivers/mfd/sm501.c                          |    8 +++++-
 drivers/video/sm501fb.c                      |   35 +++++++++++++++++++++++++-
 3 files changed, 75 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt

diff --git a/Documentation/powerpc/dts-bindings/sm501.txt b/Documentation/powerpc/dts-bindings/sm501.txt
new file mode 100644
index 0000000..7d319fb
--- /dev/null
+++ b/Documentation/powerpc/dts-bindings/sm501.txt
@@ -0,0 +1,34 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+    - First entry: System Configuration register
+    - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+    <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+  Data from the detailed timing descriptor will be used to
+  program the display controller.
+- little-endian: availiable on big endian systems, to
+  set different foreign endian.
+- big-endian: availiable on little endian systems, to
+  set different foreign endian.
+
+Example for MPC5200:
+	display@1,0 {
+		compatible = "smi,sm501";
+		reg = <1 0x00000000 0x00800000
+		       1 0x03e00000 0x00200000>;
+		interrupts = <1 1 3>;
+		mode = "640x480-32@60";
+		edid = [edid-data];
+	};
diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 558d5f3..574f696 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -1377,7 +1377,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 			sm501_register_gpio(sm);
 	}
 
-	if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+	if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
 		if (!sm501_gpio_isregistered(sm))
 			dev_err(sm->dev, "no gpio available for i2c gpio.\n");
 		else
@@ -1735,10 +1735,16 @@ static struct pci_driver sm501_pci_driver = {
 
 MODULE_ALIAS("platform:sm501");
 
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+	{ .compatible = "smi,sm501", },
+	{ /* end */ }
+};
+
 static struct platform_driver sm501_plat_driver = {
 	.driver		= {
 		.name	= "sm501",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_sm501_match_tbl,
 	},
 	.probe		= sm501_plat_probe,
 	.remove		= sm501_plat_remove,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index f31252c..f275385 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -1729,6 +1729,15 @@ static int sm501fb_init_fb(struct fb_info *fb,
 		FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
 		FBINFO_HWACCEL_XPAN | FBINFO_HWACCEL_YPAN;
 
+#if defined(CONFIG_OF)
+#ifdef __BIG_ENDIAN
+	if (of_get_property(info->dev->parent->of_node, "little-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#else
+	if (of_get_property(info->dev->parent->of_node, "big-endian", NULL))
+		fb->flags |= FBINFO_FOREIGN_ENDIAN;
+#endif
+#endif
 	/* fixed data */
 
 	fb->fix.type		= FB_TYPE_PACKED_PIXELS;
@@ -1933,8 +1942,32 @@ static int __devinit sm501fb_probe(struct platform_device *pdev)
 	}
 
 	if (info->pdata == NULL) {
-		dev_info(dev, "using default configuration data\n");
+		int found = 0;
+#if defined(CONFIG_OF)
+		struct device_node *np = pdev->dev.parent->of_node;
+		const u8 *prop;
+		const char *cp;
+		int len;
+
 		info->pdata = &sm501fb_def_pdata;
+		if (np) {
+			/* Get EDID */
+			cp = of_get_property(np, "mode", &len);
+			if (cp)
+				strcpy(fb_mode, cp);
+			prop = of_get_property(np, "edid", &len);
+			if (prop && len == EDID_LENGTH) {
+				info->edid_data = kmemdup(prop, EDID_LENGTH,
+							  GFP_KERNEL);
+				if (info->edid_data)
+					found = 1;
+			}
+		}
+#endif
+		if (!found) {
+			dev_info(dev, "using default configuration data\n");
+			info->pdata = &sm501fb_def_pdata;
+		}
 	}
 
 	/* probe for the presence of each panel */
-- 
1.7.4

^ permalink raw reply related

* [PATCH v6 5/6] powerpc, video: add SM501 support for charon board.
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  - no board specific defconfig file for mpc52xx based boards as suggested
    from Wolfram Sang

- changes since v2:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz and lkml to cc, as
  suggested from Paul Mundt.

- changes since v3:
  - rebased against v2.6.38-rc2
- changes since v4:
  - added Paul Mundt to cc (Sorry forgot this in series v4)

 arch/powerpc/boot/dts/charon.dts |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/boot/dts/charon.dts b/arch/powerpc/boot/dts/charon.dts
index 9776889..0e00e50 100644
--- a/arch/powerpc/boot/dts/charon.dts
+++ b/arch/powerpc/boot/dts/charon.dts
@@ -186,6 +186,7 @@
 		#address-cells = <2>;
 		#size-cells = <1>;
 		ranges = <	0 0 0xfc000000 0x02000000
+				1 0 0xe0000000 0x04000000 // CS1 range, SM501
 				3 0 0xe8000000 0x00080000>;
 
 		flash@0,0 {
@@ -197,6 +198,15 @@
 			#address-cells = <1>;
 		};
 
+		display@1,0 {
+			compatible = "smi,sm501";
+			reg = <1 0x00000000 0x00800000
+			       1 0x03e00000 0x00200000>;
+			mode = "640x480-32@60";
+			interrupts = <1 1 3>;
+			little-endian;
+		};
+
 		mram0@3,0 {
 			compatible = "mtd-ram";
 			reg = <3 0x00000 0x80000>;
-- 
1.7.4

^ permalink raw reply related

* [PATCH v6 2/6] video, sm501: add I/O functions for use on powerpc
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

- add read/write functions for using this driver
  also on powerpc plattforms

Signed-off-by: Heiko Schocher <hs@denx.de>
Acked-by: Samuel Ortiz <sameo@linux.intel.com>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
    - i/o routine patch
      - use ioread/write32{be} accessors instead of
        __do_readl/__do_writel{_be}
    - edid support patch
- changes for v6:
  - repost complete patchserie
  - rebased against current head

 drivers/mfd/sm501.c     |  125 +++++++++++++++++-----------------
 drivers/video/sm501fb.c |  172 ++++++++++++++++++++++++----------------------
 include/linux/sm501.h   |    8 ++
 3 files changed, 161 insertions(+), 144 deletions(-)

diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 5de3a76..558d5f3 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -133,10 +133,10 @@ static unsigned long decode_div(unsigned long pll2, unsigned long val,
 
 static void sm501_dump_clk(struct sm501_devdata *sm)
 {
-	unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
-	unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
-	unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
-	unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
+	unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+	unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+	unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
 	unsigned long sdclk0, sdclk1;
 	unsigned long pll2 = 0;
 
@@ -193,29 +193,29 @@ static void sm501_dump_regs(struct sm501_devdata *sm)
 	void __iomem *regs = sm->regs;
 
 	dev_info(sm->dev, "System Control   %08x\n",
-			readl(regs + SM501_SYSTEM_CONTROL));
+			smc501_readl(regs + SM501_SYSTEM_CONTROL));
 	dev_info(sm->dev, "Misc Control     %08x\n",
-			readl(regs + SM501_MISC_CONTROL));
+			smc501_readl(regs + SM501_MISC_CONTROL));
 	dev_info(sm->dev, "GPIO Control Low %08x\n",
-			readl(regs + SM501_GPIO31_0_CONTROL));
+			smc501_readl(regs + SM501_GPIO31_0_CONTROL));
 	dev_info(sm->dev, "GPIO Control Hi  %08x\n",
-			readl(regs + SM501_GPIO63_32_CONTROL));
+			smc501_readl(regs + SM501_GPIO63_32_CONTROL));
 	dev_info(sm->dev, "DRAM Control     %08x\n",
-			readl(regs + SM501_DRAM_CONTROL));
+			smc501_readl(regs + SM501_DRAM_CONTROL));
 	dev_info(sm->dev, "Arbitration Ctrl %08x\n",
-			readl(regs + SM501_ARBTRTN_CONTROL));
+			smc501_readl(regs + SM501_ARBTRTN_CONTROL));
 	dev_info(sm->dev, "Misc Timing      %08x\n",
-			readl(regs + SM501_MISC_TIMING));
+			smc501_readl(regs + SM501_MISC_TIMING));
 }
 
 static void sm501_dump_gate(struct sm501_devdata *sm)
 {
 	dev_info(sm->dev, "CurrentGate      %08x\n",
-			readl(sm->regs + SM501_CURRENT_GATE));
+			smc501_readl(sm->regs + SM501_CURRENT_GATE));
 	dev_info(sm->dev, "CurrentClock     %08x\n",
-			readl(sm->regs + SM501_CURRENT_CLOCK));
+			smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
 	dev_info(sm->dev, "PowerModeControl %08x\n",
-			readl(sm->regs + SM501_POWER_MODE_CONTROL));
+			smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
 }
 
 #else
@@ -231,7 +231,7 @@ static inline void sm501_dump_clk(struct sm501_devdata *sm) { }
 
 static void sm501_sync_regs(struct sm501_devdata *sm)
 {
-	readl(sm->regs);
+	smc501_readl(sm->regs);
 }
 
 static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
@@ -261,11 +261,11 @@ int sm501_misc_control(struct device *dev,
 
 	spin_lock_irqsave(&sm->reg_lock, save);
 
-	misc = readl(sm->regs + SM501_MISC_CONTROL);
+	misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
 	to = (misc & ~clear) | set;
 
 	if (to != misc) {
-		writel(to, sm->regs + SM501_MISC_CONTROL);
+		smc501_writel(to, sm->regs + SM501_MISC_CONTROL);
 		sm501_sync_regs(sm);
 
 		dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
@@ -294,11 +294,11 @@ unsigned long sm501_modify_reg(struct device *dev,
 
 	spin_lock_irqsave(&sm->reg_lock, save);
 
-	data = readl(sm->regs + reg);
+	data = smc501_readl(sm->regs + reg);
 	data |= set;
 	data &= ~clear;
 
-	writel(data, sm->regs + reg);
+	smc501_writel(data, sm->regs + reg);
 	sm501_sync_regs(sm);
 
 	spin_unlock_irqrestore(&sm->reg_lock, save);
@@ -322,9 +322,9 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
 
 	mutex_lock(&sm->clock_lock);
 
-	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	gate = readl(sm->regs + SM501_CURRENT_GATE);
-	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 
 	mode &= 3;		/* get current power mode */
 
@@ -356,14 +356,14 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
 
 	switch (mode) {
 	case 1:
-		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
 		mode = 0;
 		break;
 	case 2:
 	case 0:
-		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
 		mode = 1;
 		break;
 
@@ -372,7 +372,7 @@ int sm501_unit_power(struct device *dev, unsigned int unit, unsigned int to)
 		goto already;
 	}
 
-	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
 	sm501_sync_regs(sm);
 
 	dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
@@ -519,9 +519,9 @@ unsigned long sm501_set_clock(struct device *dev,
 			      unsigned long req_freq)
 {
 	struct sm501_devdata *sm = dev_get_drvdata(dev);
-	unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
-	unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 	unsigned char reg;
 	unsigned int pll_reg = 0;
 	unsigned long sm501_freq; /* the actual frequency achieved */
@@ -592,9 +592,9 @@ unsigned long sm501_set_clock(struct device *dev,
 
 	mutex_lock(&sm->clock_lock);
 
-	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	gate = readl(sm->regs + SM501_CURRENT_GATE);
-	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 
 	clock = clock & ~(0xFF << clksrc);
 	clock |= reg<<clksrc;
@@ -603,14 +603,14 @@ unsigned long sm501_set_clock(struct device *dev,
 
 	switch (mode) {
 	case 1:
-		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
 		mode = 0;
 		break;
 	case 2:
 	case 0:
-		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
 		mode = 1;
 		break;
 
@@ -619,10 +619,11 @@ unsigned long sm501_set_clock(struct device *dev,
 		return -1;
 	}
 
-	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
 
 	if (pll_reg)
-		writel(pll_reg, sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
+		smc501_writel(pll_reg,
+				sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
 
 	sm501_sync_regs(sm);
 
@@ -902,7 +903,7 @@ static int sm501_gpio_get(struct gpio_chip *chip, unsigned offset)
 	struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
 	unsigned long result;
 
-	result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+	result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
 	result >>= offset;
 
 	return result & 1UL;
@@ -915,13 +916,13 @@ static void sm501_gpio_ensure_gpio(struct sm501_gpio_chip *smchip,
 
 	/* check and modify if this pin is not set as gpio. */
 
-	if (readl(smchip->control) & bit) {
+	if (smc501_readl(smchip->control) & bit) {
 		dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
 			 "changing mode of gpio, bit %08lx\n", bit);
 
-		ctrl = readl(smchip->control);
+		ctrl = smc501_readl(smchip->control);
 		ctrl &= ~bit;
-		writel(ctrl, smchip->control);
+		smc501_writel(ctrl, smchip->control);
 
 		sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
 	}
@@ -942,10 +943,10 @@ static void sm501_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+	val = smc501_readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
 	if (value)
 		val |= bit;
-	writel(val, regs);
+	smc501_writel(val, regs);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	sm501_gpio_ensure_gpio(smchip, bit);
@@ -967,8 +968,8 @@ static int sm501_gpio_input(struct gpio_chip *chip, unsigned offset)
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	ddr = readl(regs + SM501_GPIO_DDR_LOW);
-	writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+	ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+	smc501_writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	sm501_gpio_ensure_gpio(smchip, bit);
@@ -994,18 +995,18 @@ static int sm501_gpio_output(struct gpio_chip *chip,
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	val = readl(regs + SM501_GPIO_DATA_LOW);
+	val = smc501_readl(regs + SM501_GPIO_DATA_LOW);
 	if (value)
 		val |= bit;
 	else
 		val &= ~bit;
-	writel(val, regs);
+	smc501_writel(val, regs);
 
-	ddr = readl(regs + SM501_GPIO_DDR_LOW);
-	writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+	ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+	smc501_writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
-	writel(val, regs + SM501_GPIO_DATA_LOW);
+	smc501_writel(val, regs + SM501_GPIO_DATA_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	spin_unlock_irqrestore(&smgpio->lock, save);
@@ -1231,7 +1232,7 @@ static ssize_t sm501_dbg_regs(struct device *dev,
 
 	for (reg = 0x00; reg < 0x70; reg += 4) {
 		ret = sprintf(ptr, "%08x = %08x\n",
-			      reg, readl(sm->regs + reg));
+			      reg, smc501_readl(sm->regs + reg));
 		ptr += ret;
 	}
 
@@ -1255,10 +1256,10 @@ static inline void sm501_init_reg(struct sm501_devdata *sm,
 {
 	unsigned long tmp;
 
-	tmp = readl(sm->regs + reg);
+	tmp = smc501_readl(sm->regs + reg);
 	tmp &= ~r->mask;
 	tmp |= r->set;
-	writel(tmp, sm->regs + reg);
+	smc501_writel(tmp, sm->regs + reg);
 }
 
 /* sm501_init_regs
@@ -1299,7 +1300,7 @@ static void sm501_init_regs(struct sm501_devdata *sm,
 
 static int sm501_check_clocks(struct sm501_devdata *sm)
 {
-	unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned long pwrmode = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 	unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
 	unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
 
@@ -1334,7 +1335,7 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 
 	INIT_LIST_HEAD(&sm->devices);
 
-	devid = readl(sm->regs + SM501_DEVICEID);
+	devid = smc501_readl(sm->regs + SM501_DEVICEID);
 
 	if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
 		dev_err(sm->dev, "incorrect device id %08lx\n", devid);
@@ -1342,9 +1343,9 @@ static int __devinit sm501_init_dev(struct sm501_devdata *sm)
 	}
 
 	/* disable irqs */
-	writel(0, sm->regs + SM501_IRQ_MASK);
+	smc501_writel(0, sm->regs + SM501_IRQ_MASK);
 
-	dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+	dramctrl = smc501_readl(sm->regs + SM501_DRAM_CONTROL);
 	mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
 
 	dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
@@ -1489,7 +1490,7 @@ static int sm501_plat_suspend(struct platform_device *pdev, pm_message_t state)
 	struct sm501_devdata *sm = platform_get_drvdata(pdev);
 
 	sm->in_suspend = 1;
-	sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+	sm->pm_misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
 
 	sm501_dump_regs(sm);
 
@@ -1513,9 +1514,9 @@ static int sm501_plat_resume(struct platform_device *pdev)
 
 	/* check to see if we are in the same state as when suspended */
 
-	if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+	if (smc501_readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
 		dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
-		writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+		smc501_writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
 
 		/* our suspend causes the controller state to change,
 		 * either by something attempting setup, power loss,
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index bcb44a5..5df406c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -117,7 +117,7 @@ static inline int v_total(struct fb_var_screeninfo *var)
 
 static inline void sm501fb_sync_regs(struct sm501fb_info *info)
 {
-	readl(info->regs);
+	smc501_readl(info->regs);
 }
 
 /* sm501_alloc_mem
@@ -262,7 +262,7 @@ static void sm501fb_setup_gamma(struct sm501fb_info *fbi,
 
 	/* set gamma values */
 	for (offset = 0; offset < 256 * 4; offset += 4) {
-		writel(value, fbi->regs + palette + offset);
+		smc501_writel(value, fbi->regs + palette + offset);
 		value += 0x010101; 	/* Advance RGB by 1,1,1.*/
 	}
 }
@@ -476,7 +476,8 @@ static int sm501fb_set_par_common(struct fb_info *info,
 
 	/* set start of framebuffer to the screen */
 
-	writel(par->screen.sm_addr | SM501_ADDR_FLIP, fbi->regs + head_addr);
+	smc501_writel(par->screen.sm_addr | SM501_ADDR_FLIP,
+			fbi->regs + head_addr);
 
 	/* program CRT clock  */
 
@@ -519,7 +520,7 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
 	reg = info->fix.line_length;
 	reg |= ((var->xres * var->bits_per_pixel)/8) << 16;
 
-	writel(reg, fbi->regs + (par->head == HEAD_CRT ?
+	smc501_writel(reg, fbi->regs + (par->head == HEAD_CRT ?
 		    SM501_DC_CRT_FB_OFFSET :  SM501_DC_PANEL_FB_OFFSET));
 
 	/* program horizontal total */
@@ -527,27 +528,27 @@ static void sm501fb_set_par_geometry(struct fb_info *info,
 	reg  = (h_total(var) - 1) << 16;
 	reg |= (var->xres - 1);
 
-	writel(reg, base + SM501_OFF_DC_H_TOT);
+	smc501_writel(reg, base + SM501_OFF_DC_H_TOT);
 
 	/* program horizontal sync */
 
 	reg  = var->hsync_len << 16;
 	reg |= var->xres + var->right_margin - 1;
 
-	writel(reg, base + SM501_OFF_DC_H_SYNC);
+	smc501_writel(reg, base + SM501_OFF_DC_H_SYNC);
 
 	/* program vertical total */
 
 	reg  = (v_total(var) - 1) << 16;
 	reg |= (var->yres - 1);
 
-	writel(reg, base + SM501_OFF_DC_V_TOT);
+	smc501_writel(reg, base + SM501_OFF_DC_V_TOT);
 
 	/* program vertical sync */
 	reg  = var->vsync_len << 16;
 	reg |= var->yres + var->lower_margin - 1;
 
-	writel(reg, base + SM501_OFF_DC_V_SYNC);
+	smc501_writel(reg, base + SM501_OFF_DC_V_SYNC);
 }
 
 /* sm501fb_pan_crt
@@ -566,15 +567,15 @@ static int sm501fb_pan_crt(struct fb_var_screeninfo *var,
 
 	xoffs = var->xoffset * bytes_pixel;
 
-	reg = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+	reg = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
 
 	reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK;
 	reg |= ((xoffs & 15) / bytes_pixel) << 4;
-	writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
+	smc501_writel(reg, fbi->regs + SM501_DC_CRT_CONTROL);
 
 	reg = (par->screen.sm_addr + xoffs +
 	       var->yoffset * info->fix.line_length);
-	writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
+	smc501_writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR);
 
 	sm501fb_sync_regs(fbi);
 	return 0;
@@ -593,10 +594,10 @@ static int sm501fb_pan_pnl(struct fb_var_screeninfo *var,
 	unsigned long reg;
 
 	reg = var->xoffset | (var->xres_virtual << 16);
-	writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH);
 
 	reg = var->yoffset | (var->yres_virtual << 16);
-	writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT);
 
 	sm501fb_sync_regs(fbi);
 	return 0;
@@ -622,7 +623,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
 	/* enable CRT DAC - note 0 is on!*/
 	sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER);
 
-	control = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+	control = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
 
 	control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK |
 		    SM501_DC_CRT_CONTROL_GAMMA |
@@ -684,7 +685,7 @@ static int sm501fb_set_par_crt(struct fb_info *info)
  out_update:
 	dev_dbg(fbi->dev, "new control is %08lx\n", control);
 
-	writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
+	smc501_writel(control, fbi->regs + SM501_DC_CRT_CONTROL);
 	sm501fb_sync_regs(fbi);
 
 	return 0;
@@ -696,18 +697,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
 	void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL;
 	struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl;
 
-	control = readl(ctrl_reg);
+	control = smc501_readl(ctrl_reg);
 
 	if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) {
 		/* enable panel power */
 
 		control |= SM501_DC_PANEL_CONTROL_VDD;	/* FPVDDEN */
-		writel(control, ctrl_reg);
+		smc501_writel(control, ctrl_reg);
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 
 		control |= SM501_DC_PANEL_CONTROL_DATA;	/* DATA */
-		writel(control, ctrl_reg);
+		smc501_writel(control, ctrl_reg);
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 
@@ -719,7 +720,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
 			else
 				control |= SM501_DC_PANEL_CONTROL_BIAS;
 
-			writel(control, ctrl_reg);
+			smc501_writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
@@ -730,7 +731,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
 			else
 				control |= SM501_DC_PANEL_CONTROL_FPEN;
 
-			writel(control, ctrl_reg);
+			smc501_writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
@@ -742,7 +743,7 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
 			else
 				control &= ~SM501_DC_PANEL_CONTROL_FPEN;
 
-			writel(control, ctrl_reg);
+			smc501_writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
@@ -753,18 +754,18 @@ static void sm501fb_panel_power(struct sm501fb_info *fbi, int to)
 			else
 				control &= ~SM501_DC_PANEL_CONTROL_BIAS;
 
-			writel(control, ctrl_reg);
+			smc501_writel(control, ctrl_reg);
 			sm501fb_sync_regs(fbi);
 			mdelay(10);
 		}
 
 		control &= ~SM501_DC_PANEL_CONTROL_DATA;
-		writel(control, ctrl_reg);
+		smc501_writel(control, ctrl_reg);
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 
 		control &= ~SM501_DC_PANEL_CONTROL_VDD;
-		writel(control, ctrl_reg);
+		smc501_writel(control, ctrl_reg);
 		sm501fb_sync_regs(fbi);
 		mdelay(10);
 	}
@@ -799,7 +800,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
 
 	/* update control register */
 
-	control = readl(fbi->regs + SM501_DC_PANEL_CONTROL);
+	control = smc501_readl(fbi->regs + SM501_DC_PANEL_CONTROL);
 	control &= (SM501_DC_PANEL_CONTROL_GAMMA |
 		    SM501_DC_PANEL_CONTROL_VDD  |
 		    SM501_DC_PANEL_CONTROL_DATA |
@@ -833,16 +834,16 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
 		BUG();
 	}
 
-	writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
+	smc501_writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL);
 
 	/* panel plane top left and bottom right location */
 
-	writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
+	smc501_writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC);
 
 	reg  = var->xres - 1;
 	reg |= (var->yres - 1) << 16;
 
-	writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
+	smc501_writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC);
 
 	/* program panel control register */
 
@@ -855,7 +856,7 @@ static int sm501fb_set_par_pnl(struct fb_info *info)
 	if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0)
 		control |= SM501_DC_PANEL_CONTROL_VSP;
 
-	writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
+	smc501_writel(control, fbi->regs + SM501_DC_PANEL_CONTROL);
 	sm501fb_sync_regs(fbi);
 
 	/* ensure the panel interface is not tristated at this point */
@@ -924,7 +925,7 @@ static int sm501fb_setcolreg(unsigned regno,
 			val |= (green >> 8) << 8;
 			val |= blue >> 8;
 
-			writel(val, base + (regno * 4));
+			smc501_writel(val, base + (regno * 4));
 		}
 
 		break;
@@ -980,7 +981,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
 
 	dev_dbg(fbi->dev, "%s(mode=%d, %p)\n", __func__, blank_mode, info);
 
-	ctrl = readl(fbi->regs + SM501_DC_CRT_CONTROL);
+	ctrl = smc501_readl(fbi->regs + SM501_DC_CRT_CONTROL);
 
 	switch (blank_mode) {
 	case FB_BLANK_POWERDOWN:
@@ -1004,7 +1005,7 @@ static int sm501fb_blank_crt(int blank_mode, struct fb_info *info)
 
 	}
 
-	writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
+	smc501_writel(ctrl, fbi->regs + SM501_DC_CRT_CONTROL);
 	sm501fb_sync_regs(fbi);
 
 	return 0;
@@ -1041,12 +1042,14 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 	if (cursor->image.depth > 1)
 		return -EINVAL;
 
-	hwc_addr = readl(base + SM501_OFF_HWC_ADDR);
+	hwc_addr = smc501_readl(base + SM501_OFF_HWC_ADDR);
 
 	if (cursor->enable)
-		writel(hwc_addr | SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+		smc501_writel(hwc_addr | SM501_HWC_EN,
+				base + SM501_OFF_HWC_ADDR);
 	else
-		writel(hwc_addr & ~SM501_HWC_EN, base + SM501_OFF_HWC_ADDR);
+		smc501_writel(hwc_addr & ~SM501_HWC_EN,
+				base + SM501_OFF_HWC_ADDR);
 
 	/* set data */
 	if (cursor->set & FB_CUR_SETPOS) {
@@ -1060,7 +1063,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
 		//y += cursor->image.height;
 
-		writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
+		smc501_writel(x | (y << 16), base + SM501_OFF_HWC_LOC);
 	}
 
 	if (cursor->set & FB_CUR_SETCMAP) {
@@ -1080,8 +1083,8 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 
 		dev_dbg(fbi->dev, "fgcol %08lx, bgcol %08lx\n", fg, bg);
 
-		writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
-		writel(fg, base + SM501_OFF_HWC_COLOR_3);
+		smc501_writel(bg, base + SM501_OFF_HWC_COLOR_1_2);
+		smc501_writel(fg, base + SM501_OFF_HWC_COLOR_3);
 	}
 
 	if (cursor->set & FB_CUR_SETSIZE ||
@@ -1102,7 +1105,7 @@ static int sm501fb_cursor(struct fb_info *info, struct fb_cursor *cursor)
 			__func__, cursor->image.width, cursor->image.height);
 
 		for (op = 0; op < (64*64*2)/8; op+=4)
-			writel(0x0, dst + op);
+			smc501_writel(0x0, dst + op);
 
 		for (y = 0; y < cursor->image.height; y++) {
 			for (x = 0; x < cursor->image.width; x++) {
@@ -1141,7 +1144,7 @@ static ssize_t sm501fb_crtsrc_show(struct device *dev,
 	struct sm501fb_info *info = dev_get_drvdata(dev);
 	unsigned long ctrl;
 
-	ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
 	ctrl &= SM501_DC_CRT_CONTROL_SEL;
 
 	return snprintf(buf, PAGE_SIZE, "%s\n", ctrl ? "crt" : "panel");
@@ -1172,7 +1175,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
 
 	dev_info(dev, "setting crt source to head %d\n", head);
 
-	ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+	ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
 
 	if (head == HEAD_CRT) {
 		ctrl |= SM501_DC_CRT_CONTROL_SEL;
@@ -1184,7 +1187,7 @@ static ssize_t sm501fb_crtsrc_store(struct device *dev,
 		ctrl &= ~SM501_DC_CRT_CONTROL_TE;
 	}
 
-	writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+	smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
 	sm501fb_sync_regs(info);
 
 	return len;
@@ -1205,7 +1208,8 @@ static int sm501fb_show_regs(struct sm501fb_info *info, char *ptr,
 	unsigned int reg;
 
 	for (reg = start; reg < (len + start); reg += 4)
-		ptr += sprintf(ptr, "%08x = %08x\n", reg, readl(mem + reg));
+		ptr += sprintf(ptr, "%08x = %08x\n", reg,
+				smc501_readl(mem + reg));
 
 	return ptr - buf;
 }
@@ -1257,7 +1261,7 @@ static int sm501fb_sync(struct fb_info *info)
 
 	/* wait for the 2d engine to be ready */
 	while ((count > 0) &&
-	       (readl(fbi->regs + SM501_SYSTEM_CONTROL) &
+	       (smc501_readl(fbi->regs + SM501_SYSTEM_CONTROL) &
 		SM501_SYSCTRL_2D_ENGINE_STATUS) != 0)
 		count--;
 
@@ -1312,45 +1316,46 @@ static void sm501fb_copyarea(struct fb_info *info, const struct fb_copyarea *are
 		return;
 
 	/* set the base addresses */
-	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
-	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	smc501_writel(par->screen.sm_addr,
+			fbi->regs2d + SM501_2D_DESTINATION_BASE);
 
 	/* set the window width */
-	writel((info->var.xres << 16) | info->var.xres,
+	smc501_writel((info->var.xres << 16) | info->var.xres,
 	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
 
 	/* set window stride */
-	writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
 	       fbi->regs2d + SM501_2D_PITCH);
 
 	/* set data format */
 	switch (info->var.bits_per_pixel) {
 	case 8:
-		writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	case 16:
-		writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	case 32:
-		writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	}
 
 	/* 2d compare mask */
-	writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
 
 	/* 2d mask */
-	writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
 
 	/* source and destination x y */
-	writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
-	writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
+	smc501_writel((sx << 16) | sy, fbi->regs2d + SM501_2D_SOURCE);
+	smc501_writel((dx << 16) | dy, fbi->regs2d + SM501_2D_DESTINATION);
 
 	/* w/h */
-	writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
 
 	/* do area move */
-	writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
+	smc501_writel(0x800000cc | rtl, fbi->regs2d + SM501_2D_CONTROL);
 }
 
 static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
@@ -1372,47 +1377,49 @@ static void sm501fb_fillrect(struct fb_info *info, const struct fb_fillrect *rec
 		return;
 
 	/* set the base addresses */
-	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
-	writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_DESTINATION_BASE);
+	smc501_writel(par->screen.sm_addr, fbi->regs2d + SM501_2D_SOURCE_BASE);
+	smc501_writel(par->screen.sm_addr,
+			fbi->regs2d + SM501_2D_DESTINATION_BASE);
 
 	/* set the window width */
-	writel((info->var.xres << 16) | info->var.xres,
+	smc501_writel((info->var.xres << 16) | info->var.xres,
 	       fbi->regs2d + SM501_2D_WINDOW_WIDTH);
 
 	/* set window stride */
-	writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
+	smc501_writel((info->var.xres_virtual << 16) | info->var.xres_virtual,
 	       fbi->regs2d + SM501_2D_PITCH);
 
 	/* set data format */
 	switch (info->var.bits_per_pixel) {
 	case 8:
-		writel(0, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	case 16:
-		writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0x00100000, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	case 32:
-		writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
+		smc501_writel(0x00200000, fbi->regs2d + SM501_2D_STRETCH);
 		break;
 	}
 
 	/* 2d compare mask */
-	writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_COLOR_COMPARE_MASK);
 
 	/* 2d mask */
-	writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
+	smc501_writel(0xffffffff, fbi->regs2d + SM501_2D_MASK);
 
 	/* colour */
-	writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
+	smc501_writel(rect->color, fbi->regs2d + SM501_2D_FOREGROUND);
 
 	/* x y */
-	writel((rect->dx << 16) | rect->dy, fbi->regs2d + SM501_2D_DESTINATION);
+	smc501_writel((rect->dx << 16) | rect->dy,
+			fbi->regs2d + SM501_2D_DESTINATION);
 
 	/* w/h */
-	writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
+	smc501_writel((width << 16) | height, fbi->regs2d + SM501_2D_DIMENSION);
 
 	/* do rectangle fill */
-	writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
+	smc501_writel(0x800100cc, fbi->regs2d + SM501_2D_CONTROL);
 }
 
 
@@ -1470,11 +1477,12 @@ static int sm501_init_cursor(struct fb_info *fbi, unsigned int reg_base)
 
 	/* initialise the colour registers */
 
-	writel(par->cursor.sm_addr, par->cursor_regs + SM501_OFF_HWC_ADDR);
+	smc501_writel(par->cursor.sm_addr,
+			par->cursor_regs + SM501_OFF_HWC_ADDR);
 
-	writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
-	writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
-	writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_LOC);
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_1_2);
+	smc501_writel(0x00, par->cursor_regs + SM501_OFF_HWC_COLOR_3);
 	sm501fb_sync_regs(info);
 
 	return 0;
@@ -1581,7 +1589,7 @@ static int sm501fb_start(struct sm501fb_info *info,
 
 	/* clear palette ram - undefined at power on */
 	for (k = 0; k < (256 * 3); k++)
-		writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
+		smc501_writel(0, info->regs + SM501_DC_PANEL_PALETTE + (k * 4));
 
 	/* enable display controller */
 	sm501_unit_power(dev->parent, SM501_GATE_DISPLAY, 1);
@@ -1649,20 +1657,20 @@ static int sm501fb_init_fb(struct fb_info *fb,
 	switch (head) {
 	case HEAD_CRT:
 		pd = info->pdata->fb_crt;
-		ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+		ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
 		enable = (ctrl & SM501_DC_CRT_CONTROL_ENABLE) ? 1 : 0;
 
 		/* ensure we set the correct source register */
 		if (info->pdata->fb_route != SM501_FB_CRT_PANEL) {
 			ctrl |= SM501_DC_CRT_CONTROL_SEL;
-			writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+			smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
 		}
 
 		break;
 
 	case HEAD_PANEL:
 		pd = info->pdata->fb_pnl;
-		ctrl = readl(info->regs + SM501_DC_PANEL_CONTROL);
+		ctrl = smc501_readl(info->regs + SM501_DC_PANEL_CONTROL);
 		enable = (ctrl & SM501_DC_PANEL_CONTROL_EN) ? 1 : 0;
 		break;
 
@@ -1680,7 +1688,7 @@ static int sm501fb_init_fb(struct fb_info *fb,
 
 	if (head == HEAD_CRT && info->pdata->fb_route == SM501_FB_CRT_PANEL) {
 		ctrl &= ~SM501_DC_CRT_CONTROL_SEL;
-		writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
+		smc501_writel(ctrl, info->regs + SM501_DC_CRT_CONTROL);
 		enable = 0;
 	}
 
@@ -2085,7 +2093,7 @@ static int sm501fb_suspend(struct platform_device *pdev, pm_message_t state)
 	struct sm501fb_info *info = platform_get_drvdata(pdev);
 
 	/* store crt control to resume with */
-	info->pm_crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+	info->pm_crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
 
 	sm501fb_suspend_fb(info, HEAD_CRT);
 	sm501fb_suspend_fb(info, HEAD_PANEL);
@@ -2109,10 +2117,10 @@ static int sm501fb_resume(struct platform_device *pdev)
 
 	/* restore the items we want to be saved for crt control */
 
-	crt_ctrl = readl(info->regs + SM501_DC_CRT_CONTROL);
+	crt_ctrl = smc501_readl(info->regs + SM501_DC_CRT_CONTROL);
 	crt_ctrl &= ~SM501_CRT_CTRL_SAVE;
 	crt_ctrl |= info->pm_crt_ctrl & SM501_CRT_CTRL_SAVE;
-	writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
+	smc501_writel(crt_ctrl, info->regs + SM501_DC_CRT_CONTROL);
 
 	sm501fb_resume_fb(info, HEAD_CRT);
 	sm501fb_resume_fb(info, HEAD_PANEL);
diff --git a/include/linux/sm501.h b/include/linux/sm501.h
index 214f932..02fde50 100644
--- a/include/linux/sm501.h
+++ b/include/linux/sm501.h
@@ -172,3 +172,11 @@ struct sm501_platdata {
 	struct sm501_platdata_gpio_i2c	*gpio_i2c;
 	unsigned int			 gpio_i2c_nr;
 };
+
+#if defined(CONFIG_PPC32)
+#define smc501_readl(addr)		ioread32be((addr))
+#define smc501_writel(val, addr)	iowrite32be((val), (addr))
+#else
+#define smc501_readl(addr)		readl(addr)
+#define smc501_writel(val, addr)	writel(val, addr)
+#endif
-- 
1.7.4

^ permalink raw reply related

* [PATCH v6 3/6] video, sm501: add edid and commandline support
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

- add commandline options:
  sm501fb.mode:
    Specify resolution as "<xres>x<yres>[-<bpp>][@<refresh>]"
  sm501fb.bpp:
    Specify bit-per-pixel if not specified mode

- Add support for encoding display mode information
  in the device tree using verbatim EDID block.

  If the "edid" entry in the "smi,sm501" node is present,
  the driver will build mode database using EDID data
  and allow setting the display modes from this database.

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  add Ben Dooks, Vincent Sanders and Samuel Ortiz to cc, as suggested from
  Paul Mundt.
- changes since v2:
  add comments from Randy Dunlap:
  - move parameter documentation to Documentation/fb/sm501.txt
- changes since v3:
  - rebased against v2.6.38-rc2
  - split in 3 patches
    - of support patch
    - i/o routine patch
    - edid support patch
- changes since v4:
  - add "info->pdata = &sm501fb_def_pdata;" in sm501fb_probe()
    as Paul Mundt suggested (and I wrongly deleted)
  - move kfree(info->edid_data); to patch 3/4
    as edid_data is only allocated in the CONFIG_OF case
- changes for v6:
  - repost complete patchserie
  - rebased against current head

 Documentation/fb/sm501.txt |   10 +++++++
 drivers/video/sm501fb.c    |   65 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 70 insertions(+), 5 deletions(-)
 create mode 100644 Documentation/fb/sm501.txt

diff --git a/Documentation/fb/sm501.txt b/Documentation/fb/sm501.txt
new file mode 100644
index 0000000..8d17aeb
--- /dev/null
+++ b/Documentation/fb/sm501.txt
@@ -0,0 +1,10 @@
+Configuration:
+
+You can pass the following kernel command line options to sm501 videoframebuffer:
+
+	sm501fb.bpp=	SM501 Display driver:
+			Specifiy bits-per-pixel if not specified by 'mode'
+
+	sm501fb.mode=	SM501 Display driver:
+			Specify resolution as
+			"<xres>x<yres>[-<bpp>][@<refresh>]"
diff --git a/drivers/video/sm501fb.c b/drivers/video/sm501fb.c
index 5df406c..f31252c 100644
--- a/drivers/video/sm501fb.c
+++ b/drivers/video/sm501fb.c
@@ -41,6 +41,26 @@
 #include <linux/sm501.h>
 #include <linux/sm501-regs.h>
 
+#include "edid.h"
+
+static char *fb_mode = "640x480-16@60";
+static unsigned long default_bpp = 16;
+
+static struct fb_videomode __devinitdata sm501_default_mode = {
+	.refresh	= 60,
+	.xres		= 640,
+	.yres		= 480,
+	.pixclock	= 20833,
+	.left_margin	= 142,
+	.right_margin	= 13,
+	.upper_margin	= 21,
+	.lower_margin	= 1,
+	.hsync_len	= 69,
+	.vsync_len	= 3,
+	.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+	.vmode		= FB_VMODE_NONINTERLACED
+};
+
 #define NR_PALETTE	256
 
 enum sm501_controller {
@@ -77,6 +97,7 @@ struct sm501fb_info {
 	void __iomem		*regs2d;	/* 2d remapped registers */
 	void __iomem		*fbmem;		/* remapped framebuffer */
 	size_t			 fbmem_len;	/* length of remapped region */
+	u8 *edid_data;
 };
 
 /* per-framebuffer private data */
@@ -1725,9 +1746,16 @@ static int sm501fb_init_fb(struct fb_info *fb,
 	fb->var.vmode		= FB_VMODE_NONINTERLACED;
 	fb->var.bits_per_pixel  = 16;
 
+	if (info->edid_data) {
+			/* Now build modedb from EDID */
+			fb_edid_to_monspecs(info->edid_data, &fb->monspecs);
+			fb_videomode_to_modelist(fb->monspecs.modedb,
+						 fb->monspecs.modedb_len,
+						 &fb->modelist);
+	}
+
 	if (enable && (pd->flags & SM501FB_FLAG_USE_INIT_MODE) && 0) {
 		/* TODO read the mode from the current display */
-
 	} else {
 		if (pd->def_mode) {
 			dev_info(info->dev, "using supplied mode\n");
@@ -1737,12 +1765,34 @@ static int sm501fb_init_fb(struct fb_info *fb,
 			fb->var.xres_virtual = fb->var.xres;
 			fb->var.yres_virtual = fb->var.yres;
 		} else {
-			ret = fb_find_mode(&fb->var, fb,
+			if (info->edid_data)
+				ret = fb_find_mode(&fb->var, fb, fb_mode,
+					fb->monspecs.modedb,
+					fb->monspecs.modedb_len,
+					&sm501_default_mode, default_bpp);
+			else
+				ret = fb_find_mode(&fb->var, fb,
 					   NULL, NULL, 0, NULL, 8);
 
-			if (ret == 0 || ret == 4) {
-				dev_err(info->dev,
-					"failed to get initial mode\n");
+			switch (ret) {
+			case 1:
+				dev_info(info->dev, "using mode specified in "
+						"@mode\n");
+				break;
+			case 2:
+				dev_info(info->dev, "using mode specified in "
+					"@mode with ignored refresh rate\n");
+				break;
+			case 3:
+				dev_info(info->dev, "using mode default "
+					"mode\n");
+				break;
+			case 4:
+				dev_info(info->dev, "using mode from list\n");
+				break;
+			default:
+				dev_info(info->dev, "ret = %d\n", ret);
+				dev_info(info->dev, "failed to find mode\n");
 				return -EINVAL;
 			}
 		}
@@ -2157,6 +2207,11 @@ static void __exit sm501fb_cleanup(void)
 module_init(sm501fb_init);
 module_exit(sm501fb_cleanup);
 
+module_param_named(mode, fb_mode, charp, 0);
+MODULE_PARM_DESC(mode,
+	"Specify resolution as \"<xres>x<yres>[-<bpp>][@<refresh>]\" ");
+module_param_named(bpp, default_bpp, ulong, 0);
+MODULE_PARM_DESC(bpp, "Specify bit-per-pixel if not specified mode");
 MODULE_AUTHOR("Ben Dooks, Vincent Sanders");
 MODULE_DESCRIPTION("SM501 Framebuffer driver");
 MODULE_LICENSE("GPL v2");
-- 
1.7.4

^ permalink raw reply related

* [PATCH v6 0/6] powerpc, 52xx: add charon board support
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1291451028-22532-1-git-send-email-hs@denx.de>

cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>

changes since v5:
- repost complete patchseries, as Paul Mundt suggested
- rebased against current head
- add Acked-by from Samuel Ortiz (MFD parts)
  http://www.spinics.net/lists/linux-fbdev/msg02550.html
  http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html

  and Benjamin Herrenschmidt (DTS parts)
  http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
- removed patch 
  "powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
  therefore added
  "powerpc, tqm5200: update tqm5200_defconfig to fit for charon board."

  Paul: before adding this patchseries, this patch should get
        an Acked-by from a powerpc maintainer. 

checkpatch says:
total: 0 errors, 0 warnings, 233 lines checked

20110322/0001-powerpc-5200-add-support-for-charon-board.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 841 lines checked

20110322/0002-video-sm501-add-I-O-functions-for-use-on-powerpc.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 109 lines checked

20110322/0003-video-sm501-add-edid-and-commandline-support.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 106 lines checked

20110322/0004-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 22 lines checked

20110322/0005-powerpc-video-add-SM501-support-for-charon-board.patch has no obvious style problems and is ready for submission.
total: 0 errors, 0 warnings, 82 lines checked

20110322/0006-powerpc-tqm5200-update-tqm5200_defconfig-to-fit-for-.patch has no obvious style problems and is ready for submission.

Heiko Schocher (6):
  powerpc, 5200: add support for charon board
  video, sm501: add I/O functions for use on powerpc
  video, sm501: add edid and commandline support
  video, sm501: add OF binding to support SM501
  powerpc, video: add SM501 support for charon board.
  powerpc, tqm5200: update tqm5200_defconfig to fit for charon board.

 Documentation/fb/sm501.txt                   |   10 +
 Documentation/powerpc/dts-bindings/sm501.txt |   34 ++++
 arch/powerpc/boot/dts/charon.dts             |  236 ++++++++++++++++++++++
 arch/powerpc/configs/52xx/tqm5200_defconfig  |   20 ++-
 arch/powerpc/platforms/52xx/mpc5200_simple.c |    1 +
 drivers/mfd/sm501.c                          |  133 +++++++------
 drivers/video/sm501fb.c                      |  272 +++++++++++++++++---------
 include/linux/sm501.h                        |    8 +
 8 files changed, 555 insertions(+), 159 deletions(-)
 create mode 100644 Documentation/fb/sm501.txt
 create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
 create mode 100644 arch/powerpc/boot/dts/charon.dts

-- 
1.7.4

^ permalink raw reply

* [PATCH v6 6/6] powerpc, tqm5200: update tqm5200_defconfig to fit for charon board.
From: Heiko Schocher @ 2011-03-22  8:27 UTC (permalink / raw)
  To: linuxppc-dev
  Cc: Ben Dooks, linux-fbdev, devicetree-discuss, Samuel Ortiz,
	Vincent Sanders, linux-kernel, Randy Dunlap, Paul Mundt,
	Heiko Schocher, Wolfgang Denk
In-Reply-To: <1300782452-528-1-git-send-email-hs@denx.de>

added:

CONFIG_MTD_OF_PARTS
CONFIG_MTD_PLATRAM
CONFIG_FIXED_PHY
CONFIG_SENSORS_LM80
CONFIG_MFD_SM501
CONFIG_FB
CONFIG_FB_FOREIGN_ENDIAN
CONFIG_FB_SM501
CONFIG_FRAMEBUFFER_CONSOLE
CONFIG_RTC_DRV_DS1374

Signed-off-by: Heiko Schocher <hs@denx.de>
cc: Wolfram Sang <w.sang@pengutronix.de>
cc: Grant Likely <grant.likely@secretlab.ca>
cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
cc: linux-fbdev@vger.kernel.org
cc: devicetree-discuss@ozlabs.org
cc: Ben Dooks <ben@simtec.co.uk>
cc: Vincent Sanders <vince@simtec.co.uk>
cc: Samuel Ortiz <sameo@linux.intel.com>
cc: linux-kernel@vger.kernel.org
cc: Randy Dunlap <rdunlap@xenotime.net>
cc: Wolfgang Denk <wd@denx.de>
cc: Paul Mundt <lethal@linux-sh.org>
---
- changes since v1:
  added Grant Likely to cc
- changes for v6:
  - new in this version, therefore patch
    "powerpc, mpc5200: update mpc5200_defconfig to fit for charon board."
    removed.
    As this board is tqm5200 based, added necessary changes
    to the tqm5200_defconfig. In previous patchserie I added
    the changes to mpc5200_defconfig, as Wolfram Sang mentioned,
    but as tqm5200_defconfig is in mainline, and the board is
    tqm5200 based, I think, thats the appropriate place, as
    new defconfigs are not accepted. Paul, before applying
    this patch series, this patch should get an Acked by
    from a powerpc maintainer...
  - repost the complete patchserie as Paul Mundt suggested

 arch/powerpc/configs/52xx/tqm5200_defconfig |   20 ++++++++++++--------
 1 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/configs/52xx/tqm5200_defconfig b/arch/powerpc/configs/52xx/tqm5200_defconfig
index 959cd2c..716a37b 100644
--- a/arch/powerpc/configs/52xx/tqm5200_defconfig
+++ b/arch/powerpc/configs/52xx/tqm5200_defconfig
@@ -1,9 +1,10 @@
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
+CONFIG_EMBEDDED=y
 # CONFIG_SYSCTL_SYSCALL is not set
 # CONFIG_KALLSYMS is not set
 # CONFIG_EPOLL is not set
@@ -17,7 +18,6 @@ CONFIG_PPC_MPC5200_SIMPLE=y
 CONFIG_PPC_MPC5200_BUGFIX=y
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_BESTCOMM=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PM=y
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -38,17 +38,18 @@ CONFIG_MTD=y
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_ROM=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_PLATRAM=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
-# CONFIG_MISC_DEVICES is not set
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_ATA=y
@@ -56,13 +57,11 @@ CONFIG_PATA_MPC52xx=y
 CONFIG_PATA_PLATFORM=y
 CONFIG_NETDEVICES=y
 CONFIG_LXT_PHY=y
+CONFIG_FIXED_PHY=y
 CONFIG_NET_ETHERNET=y
 CONFIG_FEC_MPC52xx=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
 CONFIG_SERIAL_MPC52xx=y
 CONFIG_SERIAL_MPC52xx_CONSOLE=y
 CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
@@ -70,7 +69,13 @@ CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD=115200
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
 CONFIG_I2C_MPC=y
+CONFIG_SENSORS_LM80=y
 CONFIG_WATCHDOG=y
+CONFIG_MFD_SM501=y
+CONFIG_FB=y
+CONFIG_FB_FOREIGN_ENDIAN=y
+CONFIG_FB_SM501=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_USB=y
 CONFIG_USB_DEVICEFS=y
 # CONFIG_USB_DEVICE_CLASS is not set
@@ -80,10 +85,10 @@ CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_STORAGE=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_DS1307=y
+CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_MSDOS_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_PROC_KCORE=y
@@ -102,7 +107,6 @@ CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
-- 
1.7.4

^ permalink raw reply related

* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Heiko Schocher @ 2011-03-22  8:25 UTC (permalink / raw)
  To: Paul Mundt
  Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
	linux-kernel, Ben Dooks, Randy Dunlap, linuxppc-dev,
	Wolfgang Denk
In-Reply-To: <20110322082047.GG25925@linux-sh.org>

Hello Paul,

Paul Mundt wrote:
> On Thu, Mar 17, 2011 at 07:12:56AM +0100, Heiko Schocher wrote:
>> Paul Mundt schrieb:
>>> On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
>>>>> 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
>>>>>
>>>>>  Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++
>>>>>  drivers/mfd/sm501.c                          |    9 +++++-
>>>>>  drivers/video/sm501fb.c                      |   42 ++++++++++++++++++++++++--
>>>>>  3 files changed, 81 insertions(+), 4 deletions(-)
>>>>>  create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
>>>> This patchset is pending know for a while. I got Acked by from
>>>>
>>>> Samuel Ortiz for the mfd part, see here:
>>>>
>>>> http://www.spinics.net/lists/linux-fbdev/msg02550.html
>>>> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
>>>>
>>>> and for the DTS part from Benjamin Herrenschmidt:
>>>>
>>>> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
>>>>
>>>> Are there some more issues?
>>>>
>>> Not that I remember off the top of my head, but I think they've been lost
>>> in my backlog. Could you re-send the current series with the appropriate
>>> acked-bys? If there's nothing else obvious outstanding I'll roll them in.
>> Ok, I resend them (I also rebase them to current tree, ok?)
>>
> Ok, I've dug them up on l-k in the meantime and applied 1-3. 4/4 doesn't
> apply due to a missing dts file, but I assume you're aware of that and
> will take care of it separately. Let me know if I've overlooked anything,
> and sorry for the delay!

No problem!

Just working on this patchset (rebase and check if it boots/works) ... will
post the update (with all patches again) in some minutes, so please wait
for it.

Thanks!

bye,
Heiko
-- 
DENX Software Engineering GmbH,     MD: Wolfgang Denk & Detlev Zundel
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply

* Re: [PATCH 3/4 v5] video, sm501: add OF binding to support SM501
From: Paul Mundt @ 2011-03-22  8:20 UTC (permalink / raw)
  To: Heiko Schocher
  Cc: linux-fbdev, devicetree-discuss, Samuel Ortiz, Vincent Sanders,
	linux-kernel, Ben Dooks, Randy Dunlap, linuxppc-dev,
	Wolfgang Denk
In-Reply-To: <4D81A668.8060500@denx.de>

On Thu, Mar 17, 2011 at 07:12:56AM +0100, Heiko Schocher wrote:
> Paul Mundt schrieb:
> > On Tue, Mar 15, 2011 at 08:26:40AM +0100, Heiko Schocher wrote:
> >>> 0003-video-sm501-add-OF-binding-to-support-SM501.patch has no obvious style problems and is ready for submission.
> >>>
> >>>  Documentation/powerpc/dts-bindings/sm501.txt |   34 +++++++++++++++++++++
> >>>  drivers/mfd/sm501.c                          |    9 +++++-
> >>>  drivers/video/sm501fb.c                      |   42 ++++++++++++++++++++++++--
> >>>  3 files changed, 81 insertions(+), 4 deletions(-)
> >>>  create mode 100644 Documentation/powerpc/dts-bindings/sm501.txt
> >> This patchset is pending know for a while. I got Acked by from
> >>
> >> Samuel Ortiz for the mfd part, see here:
> >>
> >> http://www.spinics.net/lists/linux-fbdev/msg02550.html
> >> http://linux.derkeiler.com/Mailing-Lists/Kernel/2011-01/msg11798.html
> >>
> >> and for the DTS part from Benjamin Herrenschmidt:
> >>
> >> http://lists.ozlabs.org/pipermail/linuxppc-dev/2011-February/088279.html
> >>
> >> Are there some more issues?
> >>
> > Not that I remember off the top of my head, but I think they've been lost
> > in my backlog. Could you re-send the current series with the appropriate
> > acked-bys? If there's nothing else obvious outstanding I'll roll them in.
> 
> Ok, I resend them (I also rebase them to current tree, ok?)
> 
Ok, I've dug them up on l-k in the meantime and applied 1-3. 4/4 doesn't
apply due to a missing dts file, but I assume you're aware of that and
will take care of it separately. Let me know if I've overlooked anything,
and sorry for the delay!

^ permalink raw reply

* Query: PCIe range entry at pcie@0 in dts files
From: Kushwaha Prabhakar-B32579 @ 2011-03-22  4:18 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

Hi all,

 I have query about usage of range field at pcie@0 under PCIe controller. P=
lease find snap shot from mpc8536_36.dts..

	pci3: pcie@fffe0b000 {
		compatible =3D "fsl,mpc8548-pcie";
		device_type =3D "pci";
		#interrupt-cells =3D <1>;
		#size-cells =3D <2>;
		#address-cells =3D <3>;
		reg =3D <0xf 0xffe0b000 0 0x1000>;
		bus-range =3D <0 0xff>;
		ranges =3D <0x02000000 0 0xe0000000 0xc 0x20000000 0 0x20000000
			  0x01000000 0 0x00000000 0xf 0xffc30000 0 0x00010000>;
		clock-frequency =3D <33333333>;
		interrupt-parent =3D <&mpic>;
		interrupts =3D <27 0x2>;
		interrupt-map-mask =3D <0xf800 0 0 7>;
		interrupt-map =3D <
			/* IDSEL 0x0 */
			0000 0 0 1 &mpic 8 1
			0000 0 0 2 &mpic 9 1
			0000 0 0 3 &mpic 10 1
			0000 0 0 4 &mpic 11 1
			>;

		pcie@0 {
			reg =3D <0 0 0 0 0>;
			#size-cells =3D <2>;
			#address-cells =3D <3>;
			device_type =3D "pci";
			ranges =3D <0x02000000 0 0xe0000000 --> child/port start address
				  0x02000000 0 0xe0000000 --> Parent bus address
				  0 0x20000000

				  0x01000000 0 0x00000000
				  0x01000000 0 0x00000000
				  0 0x00100000>;
		};
	};

Question:
A) is ranges filed of pcie@0 really required?
	 I just went through the code and found scan_OF_for_pci_dev() called from =
pci_busdev_to_OF_node() touches pcie@0 node. But, It does not even uses ran=
ge filed.=20

	static struct device_node *scan_OF_for_pci_dev(struct device_node *parent,=
unsigned int devfn) {
		 ---
       	---
		for_each_child_of_node(parent, np) {
			reg =3D of_get_property(np, "reg", &psize);=20
     =20
		  ---
		  ---
            	    if (!strcmp(np->name, "multifunc-device")) {=20
	     =20
	}

   I also checked "Power_ePAPR_APPROVED_v1.0.pdf". It never say range filed=
 required for child bus.

B) if range field of pcie@0 required. why does child/port start address sam=
e as Parent bus address?  Range property provides mapping of port address t=
o parent address space.
So the value should be 0x00000000. Means port's address starting from 0x000=
00000 to size 0x20000000 is mapped parent's 0xe0000000.

			ranges =3D <0x02000000 0 0x00000000  --> Child/port's start address
				  0x02000000 0 0xe0000000    --> Parent bus address
				  0 0x20000000

				  0x01000000 0 0x00000000
				  0x01000000 0 0x00000000
				  0 0x00100000>;


--Prabhakar

^ permalink raw reply

* Re: [PATCH v3 3/9] fsldma: use channel name in printk output
From: Dan Williams @ 2011-03-22  0:49 UTC (permalink / raw)
  To: Ira W. Snyder; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <1299174901-16762-4-git-send-email-iws@ovro.caltech.edu>

On Thu, Mar 3, 2011 at 9:54 AM, Ira W. Snyder <iws@ovro.caltech.edu> wrote:
> This makes debugging the driver much easier when multiple channels are
> running concurrently. In addition, you can see how much descriptor
> memory each channel has allocated via the dmapool API in sysfs.
>
> Signed-off-by: Ira W. Snyder <iws@ovro.caltech.edu>
> ---
> =A0drivers/dma/fsldma.c | =A0 69 +++++++++++++++++++++++++---------------=
---------
> =A0drivers/dma/fsldma.h | =A0 =A01 +
> =A02 files changed, 36 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c
> index 2e1af45..e535cd1 100644
> --- a/drivers/dma/fsldma.c
> +++ b/drivers/dma/fsldma.c
> @@ -37,7 +37,12 @@
>
> =A0#include "fsldma.h"
>
> -static const char msg_ld_oom[] =3D "No free memory for link descriptor\n=
";
> +#define chan_dbg(chan, fmt, arg...) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0\
> + =A0 =A0 =A0 dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg)
> +#define chan_err(chan, fmt, arg...) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0\
> + =A0 =A0 =A0 dev_err(chan->dev, "%s: " fmt, chan->name, ##arg)
> +

I already have this applied, but if you want to send an incremental
cleanup patch you could achieve a similar effect without increasing
the size of fsldma_chan by using the class device that is created by
dma_async_device_register.

Something like:

#define to_chan_dev(chan) (&chan->common.dev->device)
#define chan_err(chan, fmt, arg...) \
   dev_err(chan->dev, "%s: " fmt, dev_name(to_chan_dev(chan)), ##arg)

...where dev_name() returns something like "dma0chan0".

--
Dan

^ permalink raw reply

* Re: mmotm threatens ppc preemption again
From: Benjamin Herrenschmidt @ 2011-03-21 22:52 UTC (permalink / raw)
  To: Jeremy Fitzhardinge
  Cc: linuxppc-dev, Andrew Morton, Hugh Dickins, Peter Zijlstra
In-Reply-To: <4D873571.702@goop.org>

On Mon, 2011-03-21 at 11:24 +0000, Jeremy Fitzhardinge wrote:
> 
> I'm very sorry about that, I didn't realize power was also using that
> interface.  Unfortunately, the "no preemption" definition was an error,
> and had to be changed to match the pre-existing locking rules.
> 
> Could you implement a similar "flush batched pte updates on context
> switch" as x86? 

Well, we already do that for -rt & co.

However, we have another issue which is the reason we used those
lazy_mmu hooks to do our flushing.

Our PTEs eventually get faulted into a hash table which is what the real
MMU uses. We must never (ever) allow that hash table to contain a
duplicate entry for a given virtual address.

When we do a batch, we remove things from the linux PTE, and keep a
reference in our batch structure, and only update the hash table at the
end of the batch.

That means that we must not allow a hash fault to populate the hash with
a "new" PTE value prior to the old one having been flushed out (which is
possible if they different in protection attributes for example). For
that to happen, we must basically not allow a page fault to re-populate
a PTE invalidated by a batch before that batch has completed.

That translates to batches must only happen within a PTE lock section.

Cheers,
Ben.

^ permalink raw reply

* [PATCH 1/2] powerpc: xics: fix numberspace mismatch from irq_desc conversion
From: Milton Miller @ 2011-03-21 21:38 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Lennert Buytenhek
In-Reply-To: <patches-for-39-rc1@mdm.bga.com>

commit 79f26c268ebad29bd75d078cfc09d3d82b30ccbd (powerpc:
platforms/pseries irq_data conversion) pushed irq_desc down into many
functions, dererencing the descriptor irq field as late as possible.

But it incorrectly passed a linix virtural irq number to RTAS,
resulting in the interrupt not being disabled and possibly
other bad things, such as another interrupt being disabled and/or
a checkstop.  

In addition this missed the point of xics_mask_unknown_vec and
the seperation of xics_mask_real_irq from xics_mask_irq.  When
xics_mask_unknown_vec is called it's because the hardware delivered an
irq source for which we have no linux irq allocated, and thefore we can
not have an irq_desc allocated.

Revert xics_mask_real_irq to its prior version, naming the argument
hwirq to highlight the difference.

Signed-off-by: Milton Miller <miltonm@bga.com>


--

Lennert can you please review the other patches for similar problems?

Any reference to irq_map[x].hwirq is in a different number domain.

I initially saw the problem pushing irq_desc through unknown_vec
found this due to my knowledge of the split (I added that function)
and only realized the wrong number space when preparing to test the fix.
In fact I tried without the patch and my firmware checkstops the machine
(hardware stops executing instructions)!


diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 01fea46..5686db9 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -250,26 +250,26 @@ static unsigned int xics_startup(struct irq_data *d)
 	return 0;
 }
 
-static void xics_mask_real_irq(struct irq_data *d)
+static void xics_mask_real_irq(unsigned int hwirq)
 {
 	int call_status;
 
-	if (d->irq == XICS_IPI)
+	if (hwirq == XICS_IPI)
 		return;
 
-	call_status = rtas_call(ibm_int_off, 1, 1, NULL, d->irq);
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, hwirq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
-			__func__, d->irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 
 	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, d->irq,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hwirq,
 				default_server, 0xff);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
-			__func__, d->irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 }
@@ -283,13 +283,13 @@ static void xics_mask_irq(struct irq_data *d)
 	irq = (unsigned int)irq_map[d->irq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
-	xics_mask_real_irq(d);
+	xics_mask_real_irq(irq);
 }
 
 static void xics_mask_unknown_vec(unsigned int vec)
 {
 	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-	xics_mask_real_irq(irq_get_irq_data(vec));
+	xics_mask_real_irq(vec);
 }
 
 static inline unsigned int xics_xirr_vector(unsigned int xirr)

^ permalink raw reply related

* Re: powerpc/pci: Make both ppc32 and ppc64 use sysdata for pci_controller
From: Grant Likely @ 2011-03-21 18:31 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: linuxppc-dev, Hugh Dickins, Linus Torvalds,
	Linux Kernel Mailing List
In-Reply-To: <AANLkTikgG5JHimq5a2OsgsH+z+WsHO3MO6OU1q6_DzgH@mail.gmail.com>

[reposting part of private email exchange as penance for my sins...]

On Mon, Mar 21, 2011 at 12:22 PM, Grant Likely
<grant.likely@secretlab.ca> wrote:
> On Sun, Mar 20, 2011 at 4:52 PM, Benjamin Herrenschmidt
> <benh@kernel.crashing.org> wrote:
>> Grant, what in hell makes you believe that this patch was ok to
>> merge upstream without even my Ack ?
>>
>> Yes, I told you I agree with the -principle-, but I also need to -test-
>> and review it properly which I haven't had a chance to do (and it does
>> break G5s at least it seems from the reports we are getting). In any
>> case this is clearly -NOT- within the boundaries of your devicetree
>> "tree" and should have gone through powerpc-next.
>
> Sorry Ben, I did not intend to merge that patch. =A0Quite simply I
> accidentally included it in my devicetree/next branch when I pushed
> out a bunch of other PCI related patches in February, and I overlooked
> that it was still in there when I sent Linus the pull request. =A0It was
> a complete failure on my part. =A0I apologize and submit myself for the
> required flogging.

A flogging schedule will be posted on the bulletin board in the lunch
room.  Sorry for the trouble.

g.

^ permalink raw reply

* [PATCH 2/2] powerpc: xics: use hwirq for xics domain irq number
From: Milton Miller @ 2011-03-21 18:12 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <patches-for-39-rc1@mdm.bga.com>

To try to avoid future confusion, rename irq to hwirq when it refers
to a xics domain number instead of a linux irq number.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: next.git/arch/powerpc/platforms/pseries/xics.c
===================================================================
--- next.git.orig/arch/powerpc/platforms/pseries/xics.c	2011-03-19 23:21:21.775085058 -0500
+++ next.git/arch/powerpc/platforms/pseries/xics.c	2011-03-20 00:57:33.144560092 -0500
@@ -204,33 +204,33 @@ static int get_irq_server(unsigned int v
 
 static void xics_unmask_irq(struct irq_data *d)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 	int call_status;
 	int server;
 
 	pr_devel("xics: unmask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[d->irq].hwirq;
-	pr_devel(" -> map to hwirq 0x%x\n", irq);
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	pr_devel(" -> map to hwirq 0x%x\n", hwirq);
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
 
 	server = get_irq_server(d->irq, d->affinity, 0);
 
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hwirq, server,
 				DEFAULT_PRIORITY);
 	if (call_status != 0) {
 		printk(KERN_ERR
 			"%s: ibm_set_xive irq %u server %x returned %d\n",
-			__func__, irq, server, call_status);
+			__func__, hwirq, server, call_status);
 		return;
 	}
 
 	/* Now unmask the interrupt (often a no-op) */
-	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
+	call_status = rtas_call(ibm_int_on, 1, 1, NULL, hwirq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 }
@@ -276,14 +276,14 @@ static void xics_mask_real_irq(unsigned 
 
 static void xics_mask_irq(struct irq_data *d)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 
 	pr_devel("xics: mask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[d->irq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
-	xics_mask_real_irq(irq);
+	xics_mask_real_irq(hwirq);
 }
 
 static void xics_mask_unknown_vec(unsigned int vec)
@@ -373,37 +373,37 @@ static unsigned char pop_cppr(void)
 
 static void xics_eoi_direct(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
-	direct_xirr_info_set((pop_cppr() << 24) | irq);
+	direct_xirr_info_set((pop_cppr() << 24) | hwirq);
 }
 
 static void xics_eoi_lpar(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[d->irq].hwirq;
+	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
-	lpar_xirr_info_set((pop_cppr() << 24) | irq);
+	lpar_xirr_info_set((pop_cppr() << 24) | hwirq);
 }
 
 static int
 xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 	int status;
 	int xics_status[2];
 	int irq_server;
 
-	irq = (unsigned int)irq_map[d->irq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return -1;
 
-	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+	status = rtas_call(ibm_get_xive, 1, 3, xics_status, hwirq);
 
 	if (status) {
 		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-			__func__, irq, status);
+			__func__, hwirq, status);
 		return -1;
 	}
 
@@ -418,11 +418,11 @@ xics_set_affinity(struct irq_data *d, co
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, irq_server, xics_status[1]);
+				hwirq, irq_server, xics_status[1]);
 
 	if (status) {
 		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
-			__func__, irq, status);
+			__func__, hwirq, status);
 		return -1;
 	}
 
@@ -874,7 +874,7 @@ void xics_kexec_teardown_cpu(int seconda
 void xics_migrate_irqs_away(void)
 {
 	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
-	unsigned int irq, virq;
+	int virq;
 
 	/* If we used to be the default server, move to the new "boot_cpuid" */
 	if (hw_cpu == default_server)
@@ -892,6 +892,7 @@ void xics_migrate_irqs_away(void)
 	for_each_irq(virq) {
 		struct irq_desc *desc;
 		struct irq_chip *chip;
+		unsigned int hwirq;
 		int xics_status[2];
 		int status;
 		unsigned long flags;
@@ -901,9 +902,9 @@ void xics_migrate_irqs_away(void)
 			continue;
 		if (irq_map[virq].host != xics_host)
 			continue;
-		irq = (unsigned int)irq_map[virq].hwirq;
+		hwirq = (unsigned int)irq_map[virq].hwirq;
 		/* We need to get IPIs still. */
-		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+		if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 			continue;
 
 		desc = irq_to_desc(virq);
@@ -918,10 +919,10 @@ void xics_migrate_irqs_away(void)
 
 		raw_spin_lock_irqsave(&desc->lock, flags);
 
-		status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+		status = rtas_call(ibm_get_xive, 1, 3, xics_status, hwirq);
 		if (status) {
 			printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-					__func__, irq, status);
+					__func__, hwirq, status);
 			goto unlock;
 		}
 

^ permalink raw reply

* [PATCH] powerpc: pseries/smp: query-cpu-stopped-state support won't change
From: Milton Miller @ 2011-03-21 18:12 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <patches-for-39-rc1@mdm.bga.com>

If a given firmware doesn't have a token to support query-cpu-stopped-state,
its not likely to change during the lifetime of the kernel.   

Only print this information once, not once per secondary thread.

While here, make the line wrap grep friendly.

Signed-off-by: Milton Miller <miltonm@bga.com>

Index: work.git/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- work.git.orig/arch/powerpc/platforms/pseries/smp.c	2011-03-21 11:27:54.000000000 -0500
+++ work.git/arch/powerpc/platforms/pseries/smp.c	2011-03-21 11:29:51.000000000 -0500
@@ -64,8 +64,8 @@ int smp_query_cpu_stopped(unsigned int p
 	int qcss_tok = rtas_token("query-cpu-stopped-state");
 
 	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
-		printk(KERN_INFO "Firmware doesn't support "
-				"query-cpu-stopped-state\n");
+		printk_once(KERN_INFO
+			"Firmware doesn't support query-cpu-stopped-state\n");
 		return QCSS_HARDWARE_ERROR;
 	}
 

^ permalink raw reply

* [PATCH 0/3] xics mask_irq fix and other patches
From: Milton Miller @ 2011-03-21 18:12 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev

Hi Ben.

I've submitted the fix for the xics mask real irq I mentioned.
During testing I realized current code is passing rtas a linux irq,
which means no interrupt (at least those above NR_IRQs) is being disabled.

I also created a patch to rename irq to hwirq in xics to try to make
the distiction more clear.  For your consideration, I don't care if you
don't merge it especially with the upcoming rewrite.

Also, I am sending a printk to printk_once patch that affects BML.

Thanks,
milton


MAIL FROM: <miltonm@bga.com>
RCPT TO: <miltonm@bga.com>
RCPT TO: <linuxppc-dev@lists.ozlabs.org>
RCPT TO: <buytenh@secretlab.ca>
DATA
From: Milton Miller <miltonm@bga.com>
Subject: [PATCH 1/2] powerpc: xics: fix numberspace mismatch from irq_desc conversion
To: linuxppc-dev@lists.ozlabs.org
Cc: Lennert Buytenhek <buytenh@secretlab.ca>
Message-id: <xics-mask-irq-desc-fix@mdm.bga.com>
In-Reply-To: <patches-for-39-rc1@mdm.bga.com>
References: <patches-for-39-rc1@mdm.bga.com>

commit 79f26c268ebad29bd75d078cfc09d3d82b30ccbd (powerpc:
platforms/pseries irq_data conversion) pushed irq_desc down into many
functions, dererencing the descriptor irq field as late as possible.

But it incorrectly passed a linix virtural irq number to RTAS,
resulting in the interrupt not being disabled and possibly
other bad things, such as another interrupt being disabled and/or
a checkstop.  

In addition this missed the point of xics_mask_unknown_vec and
the seperation of xics_mask_real_irq from xics_mask_irq.  When
xics_mask_unknown_vec is called it's because the hardware delivered an
irq source for which we have no linux irq allocated, and thefore we can
not have an irq_desc allocated.

Revert xics_mask_real_irq to its prior version, naming the argument
hwirq to highlight the difference.

Signed-off-by: Milton Miller <miltonm@bga.com>


--

Lennert can you please review the other patches for similar problems?

Any reference to irq_map[x].hwirq is in a different number domain.

I initially saw the problem pushing irq_desc through unknown_vec
found this due to my knowledge of the split (I added that function)
and only realized the wrong number space when preparing to test the fix.
In fact I tried without the patch and my firmware checkstops the machine
(hardware stops executing instructions)!


diff --git a/arch/powerpc/platforms/pseries/xics.c b/arch/powerpc/platforms/pseries/xics.c
index 01fea46..5686db9 100644
--- a/arch/powerpc/platforms/pseries/xics.c
+++ b/arch/powerpc/platforms/pseries/xics.c
@@ -250,26 +250,26 @@ static unsigned int xics_startup(struct irq_data *d)
 	return 0;
 }
 
-static void xics_mask_real_irq(struct irq_data *d)
+static void xics_mask_real_irq(unsigned int hwirq)
 {
 	int call_status;
 
-	if (d->irq == XICS_IPI)
+	if (hwirq == XICS_IPI)
 		return;
 
-	call_status = rtas_call(ibm_int_off, 1, 1, NULL, d->irq);
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, hwirq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
-			__func__, d->irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 
 	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, d->irq,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hwirq,
 				default_server, 0xff);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
-			__func__, d->irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 }
@@ -283,13 +283,13 @@ static void xics_mask_irq(struct irq_data *d)
 	irq = (unsigned int)irq_map[d->irq].hwirq;
 	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
 		return;
-	xics_mask_real_irq(d);
+	xics_mask_real_irq(irq);
 }
 
 static void xics_mask_unknown_vec(unsigned int vec)
 {
 	printk(KERN_ERR "Interrupt %u (real) is invalid, disabling it.\n", vec);
-	xics_mask_real_irq(irq_get_irq_data(vec));
+	xics_mask_real_irq(vec);
 }
 
 static inline unsigned int xics_xirr_vector(unsigned int xirr)

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox