Fixed powerpc-mkvmlinuz-support-powerpc.patch for 2.6.20-rc4

Re-enabled powerpc-mkvmlinuz-support-ppc.patch which was disabled without reason
Updated efika patches to  2.6.20-rc4.

svn path=/dists/trunk/linux-2.6/; revision=8162
This commit is contained in:
Sven Luther 2007-01-11 14:19:52 +00:00
parent 81efc1bb84
commit c63758bace
42 changed files with 9089 additions and 9022 deletions

View File

@ -29,12 +29,12 @@
PHONY += $(BOOT_TARGETS)
--- linux-2.6.19/arch/powerpc/boot/Makefile.orig 2006-12-05 16:14:42.000000000 +0000
+++ linux-2.6.19/arch/powerpc/boot/Makefile 2006-12-05 16:13:37.000000000 +0000
@@ -176,3 +176,18 @@
--- linux-2.6.20-rc3/arch/powerpc/boot/Makefile.orig 2007-01-04 16:22:53.000000000 +0100
+++ linux-2.6.20-rc3/arch/powerpc/boot/Makefile 2007-01-04 16:23:40.000000000 +0100
@@ -186,3 +186,19 @@
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.strip.gz)
clean-files += $(addprefix $(objtree)/, $(obj-boot) vmlinux.bin.gz)
clean-files += $(image-)
+
+#-----------------------------------------------------------
+# install mkvmlinuz support files
@ -48,5 +48,6 @@
+ mkdir -p $(INSTALL_MKVMLINUZ)
+ $(call cmd,mkvmlinuz)
+
+targets += mkvmlinuz_support_install
+targets += mkvmlinuz_support_install
+
+

View File

@ -1,26 +0,0 @@
From 9f3ff0ffed7c1fc1dbf3c0628f1a22a20d0846ce Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 12:40:48 +0100
Subject: [PATCH] Fix compilation issue when PPC_MPC52xx and PPC_MERGE are selected
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
include/asm-ppc/io.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/include/asm-ppc/io.h b/include/asm-ppc/io.h
index a4c411b..8ed380c 100644
--- a/include/asm-ppc/io.h
+++ b/include/asm-ppc/io.h
@@ -26,7 +26,7 @@ #define PREP_PCI_DRAM_OFFSET 0x80000000
#if defined(CONFIG_4xx)
#include <asm/ibm4xx.h>
-#elif defined(CONFIG_PPC_MPC52xx)
+#elif defined(CONFIG_PPC_MPC52xx) && !defined(CONFIG_PPC_MERGE)
#include <asm/mpc52xx.h>
#elif defined(CONFIG_8xx)
#include <asm/mpc8xx.h>
--
1.4.3.2

View File

@ -1,105 +0,0 @@
From 6f004b2fa4f9b6e5692084f7301271503788c05c Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 9 Dec 2006 02:06:55 +0100
Subject: [PATCH] powerpc: Add support for uevent to of_platform
This adds a proper uevent handler to the of_platform bus. This
allows autoloading of modules (or at least should ;).
It's _heavily_ based on the macio counterpart.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/kernel/of_platform.c | 70 +++++++++++++++++++++++++++++++++++++
1 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b3189d0..f000023 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -73,6 +73,75 @@ static int of_platform_bus_match(struct
return of_match_device(matches, of_dev) != NULL;
}
+static int of_platform_uevent(struct device *dev, char **envp, int num_envp,
+ char *buffer, int buffer_size)
+{
+ struct of_device *of;
+ const char *compat;
+ char *compat2;
+ char compat_buf[128]; /* need to be size of 'compatible' */
+
+ int i = 0;
+ int length = 0, cplen, sl, seen = 0;
+
+ if (!dev)
+ return -ENODEV;
+
+ of = to_of_device(dev);
+ if (!of)
+ return -ENODEV;
+
+ /* stuff we want to pass to /sbin/hotplug */
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_NAME=%s", of->node->name))
+ return -ENOMEM;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_TYPE=%s", of->node->type))
+ return -ENOMEM;
+
+ /* Since the compatible field can contain pretty much anything
+ * it's not really legal to split it out with commas. We split it
+ * up using a number of environment variables instead. */
+
+ compat = get_property(of->node, "compatible", &cplen);
+ compat2 = compat_buf;
+ if (compat)
+ memcpy(compat2, compat, cplen);
+ while (compat && *compat && cplen > 0) {
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_COMPATIBLE_%d=%s", seen, compat))
+ return -ENOMEM;
+
+ sl = strlen (compat) + 1;
+ compat += sl;
+ compat2 += sl;
+ cplen -= sl;
+ seen++;
+ compat2[-1] = 'C';
+ }
+ compat2[seen?-1:0] = 0;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_COMPATIBLE_N=%d", seen))
+ return -ENOMEM;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=of:N%sT%sC%s",
+ of->node->name, of->node->type,
+ compat_buf))
+ return -ENOMEM;
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
static int of_platform_device_probe(struct device *dev)
{
int error = -ENODEV;
@@ -132,6 +201,7 @@ static int of_platform_device_resume(str
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
+ .uevent = of_platform_uevent,
.probe = of_platform_device_probe,
.remove = of_platform_device_remove,
.suspend = of_platform_device_suspend,
--
1.4.2

View File

@ -0,0 +1,27 @@
From 733239db928c98f4d110fc33f0cf1278cf5385ef Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Mon, 18 Dec 2006 22:48:02 +0100
Subject: [PATCH] [PATCH] powerpc/serial: Dispose irq mapping when done in mpc52xx_serial.c
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
drivers/serial/mpc52xx_uart.c | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 9d11a75..eef3b02 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -997,6 +997,9 @@ mpc52xx_uart_of_remove(struct of_device *op)
if (port)
uart_remove_one_port(&mpc52xx_uart_driver, port);
+ if (port->irq != NO_IRQ)
+ irq_dispose_mapping(port->irq);
+
return 0;
}
--
1.4.4.2

View File

@ -0,0 +1,68 @@
From 1dbea513815ce823ccded38d5668bbae7416223f Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Thu, 21 Dec 2006 22:21:20 +0100
Subject: [PATCH] [PATCH] powerpc: 52xx, Don't use device_initcall to probe of_platform_bus
Using device_initcall makes it happen for every platform that
compiles this file in. This is really bad, for obvious reasons.
Instead, we use the .init field of the machine description. If
the platform needs the hook to do something specific it can provides
its own function and call mpc52xx_declare_of_platform_devices from
there. If not, the mpc52xx_declare_of_platform_devices function can
directly be used as the init hook.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/platforms/52xx/lite5200.c | 1 +
arch/powerpc/platforms/52xx/mpc52xx_common.c | 7 ++++---
include/asm-powerpc/mpc52xx.h | 1 +
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index eaff71e..0f21bab 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -153,6 +153,7 @@ define_machine(lite52xx) {
.name = "lite52xx",
.probe = lite52xx_probe,
.setup_arch = lite52xx_setup_arch,
+ .init = mpc52xx_declare_of_platform_devices,
.init_IRQ = mpc52xx_init_irq,
.get_irq = mpc52xx_get_irq,
.show_cpuinfo = lite52xx_show_cpuinfo,
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_common.c b/arch/powerpc/platforms/52xx/mpc52xx_common.c
index 8331ff4..cc40889 100644
--- a/arch/powerpc/platforms/52xx/mpc52xx_common.c
+++ b/arch/powerpc/platforms/52xx/mpc52xx_common.c
@@ -116,11 +116,12 @@ unmap_regs:
if (xlb) iounmap(xlb);
}
-static int __init
+void __init
mpc52xx_declare_of_platform_devices(void)
{
/* Find every child of the SOC node and add it to of_platform */
- return of_platform_bus_probe(NULL, NULL, NULL);
+ if (of_platform_bus_probe(NULL, NULL, NULL))
+ printk(KERN_ERR __FILE__ ": "
+ "Error while probing of_platform bus\n");
}
-device_initcall(mpc52xx_declare_of_platform_devices);
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 4a28a85..4560d72 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -244,6 +244,7 @@ struct mpc52xx_cdm {
extern void __iomem * mpc52xx_find_and_map(const char *);
extern unsigned int mpc52xx_find_ipb_freq(struct device_node *node);
extern void mpc52xx_setup_cpu(void);
+extern void mpc52xx_declare_of_platform_devices(void);
extern void mpc52xx_init_irq(void);
extern unsigned int mpc52xx_get_irq(void);
--
1.4.4.2

View File

@ -1,719 +0,0 @@
From 0ac70faf67a7e5e3f24a841ace4658336f8f98df Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:00:06 +0100
Subject: [PATCH] Add MPC5200 serial driver
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
drivers/serial/mpc52xx_uart.c | 287 +++++++++++++++++++++++++----------------
1 files changed, 178 insertions(+), 109 deletions(-)
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 4f80c5b..debcd7b 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -1,6 +1,4 @@
/*
- * drivers/serial/mpc52xx_uart.c
- *
* Driver for the PSC of the Freescale MPC52xx PSCs configured as UARTs.
*
* FIXME According to the usermanual the status bits in the status register
@@ -14,18 +12,18 @@
*
*
* Maintainer : Sylvain Munaut <tnt@246tNt.com>
- *
+ *
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
- *
+ *
* Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
* Copyright (C) 2003 MontaVista, Software, Inc.
- *
+ *
* This file is licensed under the terms of the GNU General Public License
* version 2. This program is licensed "as is" without any warranty of any
* kind, whether express or implied.
*/
-
+
/* Platform device Usage :
*
* Since PSCs can have multiple function, the correct driver for each one
@@ -44,7 +42,8 @@
* will be mapped to.
*/
-#include <linux/platform_device.h>
+#define DEBUG
+
#include <linux/module.h>
#include <linux/tty.h>
#include <linux/serial.h>
@@ -53,6 +52,8 @@ #include <linux/console.h>
#include <asm/delay.h>
#include <asm/io.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
#include <asm/mpc52xx_psc.h>
@@ -96,32 +97,43 @@ #else
#define uart_console(port) (0)
#endif
+static struct of_device_id mpc52xx_uart_match[] = {
+ {
+ .type = "serial",
+ .compatible = "mpc52xx-psc-uart",
+ },
+ {
+ .type = "serial",
+ .compatible = "mpc5200-psc",
+ },
+ {},
+};
/* ======================================================================== */
/* UART operations */
/* ======================================================================== */
-static unsigned int
+static unsigned int
mpc52xx_uart_tx_empty(struct uart_port *port)
{
int status = in_be16(&PSC(port)->mpc52xx_psc_status);
return (status & MPC52xx_PSC_SR_TXEMP) ? TIOCSER_TEMT : 0;
}
-static void
+static void
mpc52xx_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
/* Not implemented */
}
-static unsigned int
+static unsigned int
mpc52xx_uart_get_mctrl(struct uart_port *port)
{
/* Not implemented */
return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR;
}
-static void
+static void
mpc52xx_uart_stop_tx(struct uart_port *port)
{
/* port->lock taken by caller */
@@ -129,7 +141,7 @@ mpc52xx_uart_stop_tx(struct uart_port *p
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
}
-static void
+static void
mpc52xx_uart_start_tx(struct uart_port *port)
{
/* port->lock taken by caller */
@@ -137,12 +149,12 @@ mpc52xx_uart_start_tx(struct uart_port *
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
}
-static void
+static void
mpc52xx_uart_send_xchar(struct uart_port *port, char ch)
{
unsigned long flags;
spin_lock_irqsave(&port->lock, flags);
-
+
port->x_char = ch;
if (ch) {
/* Make sure tx interrupts are on */
@@ -150,7 +162,7 @@ mpc52xx_uart_send_xchar(struct uart_port
port->read_status_mask |= MPC52xx_PSC_IMR_TXRDY;
out_be16(&PSC(port)->mpc52xx_psc_imr,port->read_status_mask);
}
-
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -178,7 +190,7 @@ mpc52xx_uart_break_ctl(struct uart_port
out_8(&PSC(port)->command,MPC52xx_PSC_START_BRK);
else
out_8(&PSC(port)->command,MPC52xx_PSC_STOP_BRK);
-
+
spin_unlock_irqrestore(&port->lock, flags);
}
@@ -197,11 +209,11 @@ mpc52xx_uart_startup(struct uart_port *p
/* Reset/activate the port, clear and enable interrupts */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
out_8(&psc->command,MPC52xx_PSC_RST_TX);
-
+
out_be32(&psc->sicr,0); /* UART mode DCD ignored */
out_be16(&psc->mpc52xx_psc_clock_select, 0xdd00); /* /16 prescaler on */
-
+
out_8(&psc->rfcntl, 0x00);
out_be16(&psc->rfalarm, 0x1ff);
out_8(&psc->tfcntl, 0x07);
@@ -209,10 +221,10 @@ mpc52xx_uart_startup(struct uart_port *p
port->read_status_mask |= MPC52xx_PSC_IMR_RXRDY | MPC52xx_PSC_IMR_TXRDY;
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
-
+
out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
-
+
return 0;
}
@@ -220,19 +232,19 @@ static void
mpc52xx_uart_shutdown(struct uart_port *port)
{
struct mpc52xx_psc __iomem *psc = PSC(port);
-
+
/* Shut down the port, interrupt and all */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
out_8(&psc->command,MPC52xx_PSC_RST_TX);
-
- port->read_status_mask = 0;
+
+ port->read_status_mask = 0;
out_be16(&psc->mpc52xx_psc_imr,port->read_status_mask);
/* Release interrupt */
free_irq(port->irq, port);
}
-static void
+static void
mpc52xx_uart_set_termios(struct uart_port *port, struct termios *new,
struct termios *old)
{
@@ -241,10 +253,10 @@ mpc52xx_uart_set_termios(struct uart_por
unsigned char mr1, mr2;
unsigned short ctr;
unsigned int j, baud, quot;
-
+
/* Prepare what we're gonna write */
mr1 = 0;
-
+
switch (new->c_cflag & CSIZE) {
case CS5: mr1 |= MPC52xx_PSC_MODE_5_BITS;
break;
@@ -261,8 +273,8 @@ mpc52xx_uart_set_termios(struct uart_por
MPC52xx_PSC_MODE_PARODD : MPC52xx_PSC_MODE_PAREVEN;
} else
mr1 |= MPC52xx_PSC_MODE_PARNONE;
-
-
+
+
mr2 = 0;
if (new->c_cflag & CSTOPB)
@@ -276,7 +288,7 @@ mpc52xx_uart_set_termios(struct uart_por
baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
ctr = quot & 0xffff;
-
+
/* Get the lock */
spin_lock_irqsave(&port->lock, flags);
@@ -290,14 +302,14 @@ mpc52xx_uart_set_termios(struct uart_por
* boot for the console, all stuff is not yet ready to receive at that
* time and that just makes the kernel oops */
/* while (j-- && mpc52xx_uart_int_rx_chars(port)); */
- while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
+ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
--j)
udelay(1);
if (!j)
printk( KERN_ERR "mpc52xx_uart.c: "
"Unable to flush RX & TX fifos in-time in set_termios."
- "Some chars may have been lost.\n" );
+ "Some chars may have been lost.\n" );
/* Reset the TX & RX */
out_8(&psc->command,MPC52xx_PSC_RST_RX);
@@ -309,7 +321,7 @@ mpc52xx_uart_set_termios(struct uart_por
out_8(&psc->mode,mr2);
out_8(&psc->ctur,ctr >> 8);
out_8(&psc->ctlr,ctr & 0xff);
-
+
/* Reenable TX & RX */
out_8(&psc->command,MPC52xx_PSC_TX_ENABLE);
out_8(&psc->command,MPC52xx_PSC_RX_ENABLE);
@@ -332,7 +344,7 @@ mpc52xx_uart_release_port(struct uart_po
port->membase = NULL;
}
- release_mem_region(port->mapbase, MPC52xx_PSC_SIZE);
+ release_mem_region(port->mapbase, sizeof(struct mpc52xx_psc));
}
static int
@@ -341,12 +353,13 @@ mpc52xx_uart_request_port(struct uart_po
int err;
if (port->flags & UPF_IOREMAP) /* Need to remap ? */
- port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
+ port->membase = ioremap(port->mapbase,
+ sizeof(struct mpc52xx_psc));
if (!port->membase)
return -EINVAL;
- err = request_mem_region(port->mapbase, MPC52xx_PSC_SIZE,
+ err = request_mem_region(port->mapbase, sizeof(struct mpc52xx_psc),
"mpc52xx_psc_uart") != NULL ? 0 : -EBUSY;
if (err && (port->flags & UPF_IOREMAP)) {
@@ -373,7 +386,7 @@ mpc52xx_uart_verify_port(struct uart_por
if ( (ser->irq != port->irq) ||
(ser->io_type != SERIAL_IO_MEM) ||
- (ser->baud_base != port->uartclk) ||
+ (ser->baud_base != port->uartclk) ||
(ser->iomem_base != (void*)port->mapbase) ||
(ser->hub6 != 0 ) )
return -EINVAL;
@@ -404,11 +417,11 @@ static struct uart_ops mpc52xx_uart_ops
.verify_port = mpc52xx_uart_verify_port
};
-
+
/* ======================================================================== */
/* Interrupt handling */
/* ======================================================================== */
-
+
static inline int
mpc52xx_uart_int_rx_chars(struct uart_port *port)
{
@@ -435,11 +448,11 @@ #endif
flag = TTY_NORMAL;
port->icount.rx++;
-
+
if ( status & (MPC52xx_PSC_SR_PE |
MPC52xx_PSC_SR_FE |
MPC52xx_PSC_SR_RB) ) {
-
+
if (status & MPC52xx_PSC_SR_RB) {
flag = TTY_BREAK;
uart_handle_break(port);
@@ -464,7 +477,7 @@ #endif
}
tty_flip_buffer_push(tty);
-
+
return in_be16(&PSC(port)->mpc52xx_psc_status) & MPC52xx_PSC_SR_RXRDY;
}
@@ -509,25 +522,25 @@ mpc52xx_uart_int_tx_chars(struct uart_po
return 1;
}
-static irqreturn_t
+static irqreturn_t
mpc52xx_uart_int(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
unsigned long pass = ISR_PASS_LIMIT;
unsigned int keepgoing;
unsigned short status;
-
+
spin_lock(&port->lock);
-
+
/* While we have stuff to do, we continue */
do {
/* If we don't find anything to do, we stop */
- keepgoing = 0;
-
+ keepgoing = 0;
+
/* Read status */
status = in_be16(&PSC(port)->mpc52xx_psc_isr);
status &= port->read_status_mask;
-
+
/* Do we need to receive chars ? */
/* For this RX interrupts must be on and some chars waiting */
if ( status & MPC52xx_PSC_IMR_RXRDY )
@@ -537,15 +550,15 @@ mpc52xx_uart_int(int irq, void *dev_id)
/* For this, TX must be ready and TX interrupt enabled */
if ( status & MPC52xx_PSC_IMR_TXRDY )
keepgoing |= mpc52xx_uart_int_tx_chars(port);
-
+
/* Limit number of iteration */
if ( !(--pass) )
keepgoing = 0;
} while (keepgoing);
-
+
spin_unlock(&port->lock);
-
+
return IRQ_HANDLED;
}
@@ -563,13 +576,13 @@ mpc52xx_console_get_options(struct uart_
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);
-
+
/* CT{U,L}R are write-only ! */
- *baud = __res.bi_baudrate ?
- __res.bi_baudrate : CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
+ *baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
/* Parse them */
switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
@@ -579,26 +592,26 @@ mpc52xx_console_get_options(struct uart_
case MPC52xx_PSC_MODE_8_BITS:
default: *bits = 8;
}
-
+
if (mr1 & MPC52xx_PSC_MODE_PARNONE)
*parity = 'n';
else
*parity = mr1 & MPC52xx_PSC_MODE_PARODD ? 'o' : 'e';
}
-static void
+static void
mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
struct mpc52xx_psc __iomem *psc = PSC(port);
unsigned int i, j;
-
+
/* Disable interrupts */
out_be16(&psc->mpc52xx_psc_imr, 0);
/* Wait the TX buffer to be empty */
- j = 5000000; /* Maximum wait */
- while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
+ j = 5000000; /* Maximum wait */
+ while (!(in_be16(&psc->mpc52xx_psc_status) & MPC52xx_PSC_SR_TXEMP) &&
--j)
udelay(1);
@@ -606,14 +619,14 @@ mpc52xx_console_write(struct console *co
for (i = 0; i < count; i++, s++) {
/* Line return handling */
if (*s == '\n')
- out_8(&psc->mpc52xx_psc_buffer_8, '\r');
-
+ out_8(&psc->buffer.buffer_8, '\r');
+
/* Send the char */
- out_8(&psc->mpc52xx_psc_buffer_8, *s);
+ out_8(&psc->buffer.buffer_8, *s);
/* Wait the TX buffer to be empty */
- j = 20000; /* Maximum wait */
- while (!(in_be16(&psc->mpc52xx_psc_status) &
+ j = 20000; /* Maximum wait */
+ while (!(in_be16(&psc->mpc52xx_psc_status) &
MPC52xx_PSC_SR_TXEMP) && --j)
udelay(1);
}
@@ -626,33 +639,77 @@ static int __init
mpc52xx_console_setup(struct console *co, char *options)
{
struct uart_port *port = &mpc52xx_uart_ports[co->index];
+ struct device_node *np = NULL;
+ const struct of_device_id *dev_id = NULL;
+ struct device_node *np_idx;
+ const void *pp = NULL;
+ struct resource res;
+ int index = 0;
+ int ret;
int baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
int bits = 8;
int parity = 'n';
int flow = 'n';
- if (co->index < 0 || co->index >= MPC52xx_PSC_MAXNUM)
+ pr_debug("mpc52xx_console_setup co=%p, options=%s, index=%i\n",
+ co, options, co->index);
+
+ for_each_node_by_type(np, "serial")
+ {
+ dev_id = of_match_node(mpc52xx_uart_match, np);
+ if (dev_id)
+ if (index++ == co->index)
+ break;
+ }
+
+ if (!np) {
+ pr_debug("PSC%x not found in device tree\n", co->index);
+ return -EINVAL;
+ }
+
+ /* Fetch register locations */
+ if ((ret = of_address_to_resource(np, 0, &res)) != 0) {
+ pr_debug("Could not get resources for PSC%x\n", index);
+ return ret;
+ }
+
+ /* Search for bus-frequency property in this node or a parent */
+ np_idx = np;
+ while (np_idx) {
+ if ((pp = get_property(np_idx, "bus-frequency", NULL)) != NULL)
+ break;
+ np_idx = of_get_parent(np_idx);
+ }
+ if (!pp) {
+ pr_debug("Could not find bus-frequency property!\n");
return -EINVAL;
-
+ }
+
/* Basic port init. Needed since we use some uart_??? func before
* real init for early access */
spin_lock_init(&port->lock);
- port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
+ port->uartclk = *(const u32*)pp / 2;
port->ops = &mpc52xx_uart_ops;
- port->mapbase = MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
+ port->mapbase = res.start;
+ port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
+ port->irq = irq_of_parse_and_map(np, 0);
- /* We ioremap ourself */
- port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
if (port->membase == NULL)
return -EINVAL;
+ pr_debug("mpc52xx_psc at %lx mapped to %p; irq=%x freq=%i\n",
+ port->mapbase, port->membase, port->irq, port->uartclk);
+
/* Setup the port parameters accoding to options */
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
mpc52xx_console_get_options(port, &baud, &parity, &bits, &flow);
+ pr_debug("Setting console parameters: %i %i%c1 flow=%c\n",
+ baud, bits, parity, flow);
+
return uart_set_options(port, co, baud, parity, bits, flow);
}
@@ -669,8 +726,8 @@ static struct console mpc52xx_console =
.data = &mpc52xx_uart_driver,
};
-
-static int __init
+
+static int __init
mpc52xx_console_init(void)
{
register_console(&mpc52xx_console);
@@ -705,28 +762,23 @@ static struct uart_driver mpc52xx_uart_d
/* ======================================================================== */
static int __devinit
-mpc52xx_uart_probe(struct platform_device *dev)
+mpc52xx_uart_probe(struct of_device *op, const struct of_device_id *match)
{
- struct resource *res = dev->resource;
-
+ static int idx = 0;
struct uart_port *port = NULL;
- int i, idx, ret;
+ struct resource res;
+ int ret;
+
+ dev_dbg(&op->dev, "mpc52xx_uart_probe(op=%p, match=%p)\n", op, match);
/* Check validity & presence */
- idx = dev->id;
- if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
+ if (idx >= MPC52xx_PSC_MAXNUM)
return -EINVAL;
- if (!mpc52xx_match_psc_function(idx,"uart"))
- return -ENODEV;
-
/* Init the port structure */
port = &mpc52xx_uart_ports[idx];
- memset(port, 0x00, sizeof(struct uart_port));
-
spin_lock_init(&port->lock);
- port->uartclk = __res.bi_ipbfreq / 2; /* Look at CTLR doc */
port->fifosize = 512;
port->iotype = UPIO_MEM;
port->flags = UPF_BOOT_AUTOCONF |
@@ -735,29 +787,36 @@ mpc52xx_uart_probe(struct platform_devic
port->ops = &mpc52xx_uart_ops;
/* Search for IRQ and mapbase */
- for (i=0 ; i<dev->num_resources ; i++, res++) {
- if (res->flags & IORESOURCE_MEM)
- port->mapbase = res->start;
- else if (res->flags & IORESOURCE_IRQ)
- port->irq = res->start;
- }
- if (!port->irq || !port->mapbase)
+ if ((ret = of_address_to_resource(op->node, 0, &res)) != 0)
+ return ret;
+
+ port->mapbase = res.start;
+ port->membase = ioremap(res.start, sizeof(struct mpc52xx_psc));
+ port->irq = irq_of_parse_and_map(op->node, 0);
+
+ dev_dbg(&op->dev, "mpc52xx-psc UART at %lx. mapped to %p, irq %x\n",
+ port->mapbase, port->membase, port->irq);
+
+ //if (!port->irq || !port->mapbase) {
+ if (!port->mapbase) {
+ printk(KERN_ERR "Could not allocate resources for PSC\n");
return -EINVAL;
+ }
/* Add the port to the uart sub-system */
ret = uart_add_one_port(&mpc52xx_uart_driver, port);
if (!ret)
- platform_set_drvdata(dev, (void*)port);
+ dev_set_drvdata(&op->dev, (void*)port);
+ idx++;
return ret;
}
static int
-mpc52xx_uart_remove(struct platform_device *dev)
+mpc52xx_uart_remove(struct of_device *op)
{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
- platform_set_drvdata(dev, NULL);
+ struct uart_port *port = dev_get_drvdata(&op->dev);
+ dev_set_drvdata(&op->dev, NULL);
if (port)
uart_remove_one_port(&mpc52xx_uart_driver, port);
@@ -767,20 +826,20 @@ mpc52xx_uart_remove(struct platform_devi
#ifdef CONFIG_PM
static int
-mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state)
+mpc52xx_uart_suspend(struct of_device *op, pm_message_t state)
{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev);
- if (sport)
+ if (port)
uart_suspend_port(&mpc52xx_uart_driver, port);
return 0;
}
static int
-mpc52xx_uart_resume(struct platform_device *dev)
+mpc52xx_uart_resume(struct of_device *op)
{
- struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
+ struct uart_port *port = (struct uart_port *) dev_get_drvdata(&op->dev);
if (port)
uart_resume_port(&mpc52xx_uart_driver, port);
@@ -789,7 +848,13 @@ mpc52xx_uart_resume(struct platform_devi
}
#endif
-static struct platform_driver mpc52xx_uart_platform_driver = {
+
+MODULE_DEVICE_TABLE(of, mpc52xx_uart_match);
+
+static struct of_platform_driver mpc52xx_uart_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "mpc52xx-uart",
+ .match_table = mpc52xx_uart_match,
.probe = mpc52xx_uart_probe,
.remove = mpc52xx_uart_remove,
#ifdef CONFIG_PM
@@ -804,7 +869,7 @@ #endif
/* ======================================================================== */
/* Module */
-/* ======================================================================== */
+ /* ======================================================================== */
static int __init
mpc52xx_uart_init(void)
@@ -813,20 +878,24 @@ mpc52xx_uart_init(void)
printk(KERN_INFO "Serial: MPC52xx PSC driver\n");
- ret = uart_register_driver(&mpc52xx_uart_driver);
- if (ret == 0) {
- ret = platform_driver_register(&mpc52xx_uart_platform_driver);
- if (ret)
- uart_unregister_driver(&mpc52xx_uart_driver);
+ if ((ret = uart_register_driver(&mpc52xx_uart_driver)) != 0) {
+ printk(KERN_ERR "Could not register mpc52xx uart driver\n");
+ return ret;
}
- return ret;
+ if ((ret = of_register_platform_driver(&mpc52xx_uart_of_driver)) != 0) {
+ printk(KERN_ERR "Could not register mpc52xx of driver\n");
+ uart_unregister_driver(&mpc52xx_uart_driver);
+ return ret;
+ }
+
+ return 0;
}
static void __exit
mpc52xx_uart_exit(void)
{
- platform_driver_unregister(&mpc52xx_uart_platform_driver);
+ of_unregister_platform_driver(&mpc52xx_uart_of_driver);
uart_unregister_driver(&mpc52xx_uart_driver);
}
--
1.4.3.2

View File

@ -0,0 +1,106 @@
From ae911446f91481cf26e6dc5edef034a50a6c410c Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 20:33:30 +0100
Subject: [PATCH] [PATCH] powerpc: Use common 52xx of_platform probe code for EFIKA
Now that the device tree has the good properties, we can
remove all the efika_init code by a single call to common code.
While we're modifying that file, a few whitespaces/alignement/typo
fixes are made (nothing significant).
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/platforms/52xx/efika-setup.c | 64 ++++++++---------------------
1 files changed, 18 insertions(+), 46 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
index 110c980..d61ce84 100644
--- a/arch/powerpc/platforms/52xx/efika-setup.c
+++ b/arch/powerpc/platforms/52xx/efika-setup.c
@@ -2,7 +2,7 @@
*
* Efika 5K2 platform setup
* Some code really inspired from the lite5200b platform.
- *
+ *
* Copyright (C) 2006 bplan GmbH
*
* This file is licensed under the terms of the GNU General Public License
@@ -81,35 +81,7 @@ static void __init efika_setup_arch(void)
efika_pcisetup();
if (ppc_md.progress)
- ppc_md.progress("Linux/PPC " UTS_RELEASE " runnung on Efika ;-)\n", 0x0);
-}
-
-static void __init efika_init(void)
-{
- struct device_node *np;
- struct device_node *cnp = NULL;
- const u32 *base;
-
- /* Find every child of the SOC node and add it to of_platform */
- np = of_find_node_by_name(NULL, "builtin");
- if (np) {
- char name[BUS_ID_SIZE];
- while ((cnp = of_get_next_child(np, cnp))) {
- strcpy(name, cnp->name);
-
- base = get_property(cnp, "reg", NULL);
- if (base == NULL)
- continue;
-
- snprintf(name+strlen(name), BUS_ID_SIZE, "@%x", *base);
- of_platform_device_create(cnp, name, NULL);
-
- printk(KERN_INFO EFIKA_PLATFORM_NAME" : Added %s (type '%s' at '%s') to the known devices\n", name, cnp->type, cnp->full_name);
- }
- }
-
- if (ppc_md.progress)
- ppc_md.progress(" Have fun with your Efika! ", 0x7777);
+ ppc_md.progress("Linux/PPC " UTS_RELEASE " running on Efika ;-)\n", 0x0);
}
static int __init efika_probe(void)
@@ -131,20 +103,20 @@ static int __init efika_probe(void)
define_machine(efika)
{
- .name = EFIKA_PLATFORM_NAME,
- .probe = efika_probe,
- .setup_arch = efika_setup_arch,
- .init = efika_init,
- .show_cpuinfo = efika_show_cpuinfo,
- .init_IRQ = mpc52xx_init_irq,
- .get_irq = mpc52xx_get_irq,
- .restart = rtas_restart,
- .power_off = rtas_power_off,
- .halt = rtas_halt,
- .set_rtc_time = rtas_set_rtc_time,
- .get_rtc_time = rtas_get_rtc_time,
- .progress = rtas_progress,
- .get_boot_time = rtas_get_boot_time,
- .calibrate_decr = generic_calibrate_decr,
- .phys_mem_access_prot = pci_phys_mem_access_prot,
+ .name = EFIKA_PLATFORM_NAME,
+ .probe = efika_probe,
+ .setup_arch = efika_setup_arch,
+ .init = mpc52xx_declare_of_platform_devices,
+ .show_cpuinfo = efika_show_cpuinfo,
+ .init_IRQ = mpc52xx_init_irq,
+ .get_irq = mpc52xx_get_irq,
+ .restart = rtas_restart,
+ .power_off = rtas_power_off,
+ .halt = rtas_halt,
+ .set_rtc_time = rtas_set_rtc_time,
+ .get_rtc_time = rtas_get_rtc_time,
+ .progress = rtas_progress,
+ .get_boot_time = rtas_get_boot_time,
+ .calibrate_decr = generic_calibrate_decr,
+ .phys_mem_access_prot = pci_phys_mem_access_prot,
};
--
1.4.4.2

View File

@ -1,306 +0,0 @@
From e63b95820892f44ac7eec431900378763a83ae9d Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:05:34 +0100
Subject: [PATCH] Add MPC5200 specific header
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
include/asm-powerpc/mpc52xx.h | 287 +++++++++++++++++++++++++++++++++++++++++
1 files changed, 287 insertions(+), 0 deletions(-)
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
new file mode 100644
index 0000000..e9aa622
--- /dev/null
+++ b/include/asm-powerpc/mpc52xx.h
@@ -0,0 +1,287 @@
+/*
+ * Prototypes, etc. for the Freescale MPC52xx embedded cpu chips
+ * May need to be cleaned as the port goes on ...
+ *
+ * Copyright (C) 2004-2005 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __ASM_POWERPC_MPC52xx_H__
+#define __ASM_POWERPC_MPC52xx_H__
+
+#ifndef __ASSEMBLY__
+#include <asm/types.h>
+#include <asm/prom.h>
+#endif /* __ASSEMBLY__ */
+
+
+/* ======================================================================== */
+/* HW IRQ mapping */
+/* ======================================================================== */
+
+#define MPC52xx_IRQ_L1_CRIT (0)
+#define MPC52xx_IRQ_L1_MAIN (1)
+#define MPC52xx_IRQ_L1_PERP (2)
+#define MPC52xx_IRQ_L1_SDMA (3)
+
+#define MPC52xx_IRQ_L1_OFFSET (6)
+#define MPC52xx_IRQ_L1_MASK (0xc0)
+
+#define MPC52xx_IRQ_L2_OFFSET (0)
+#define MPC52xx_IRQ_L2_MASK (0x3f)
+
+#define MPC52xx_IRQ_HIGHTESTHWIRQ (0xd0)
+
+
+/* ======================================================================== */
+/* Structures mapping of some unit register set */
+/* ======================================================================== */
+
+#ifndef __ASSEMBLY__
+
+/* Interrupt controller Register set */
+struct mpc52xx_intr {
+ u32 per_mask; /* INTR + 0x00 */
+ u32 per_pri1; /* INTR + 0x04 */
+ u32 per_pri2; /* INTR + 0x08 */
+ u32 per_pri3; /* INTR + 0x0c */
+ u32 ctrl; /* INTR + 0x10 */
+ u32 main_mask; /* INTR + 0x14 */
+ u32 main_pri1; /* INTR + 0x18 */
+ u32 main_pri2; /* INTR + 0x1c */
+ u32 reserved1; /* INTR + 0x20 */
+ u32 enc_status; /* INTR + 0x24 */
+ u32 crit_status; /* INTR + 0x28 */
+ u32 main_status; /* INTR + 0x2c */
+ u32 per_status; /* INTR + 0x30 */
+ u32 reserved2; /* INTR + 0x34 */
+ u32 per_error; /* INTR + 0x38 */
+};
+
+/* Memory Mapping Control */
+struct mpc52xx_mmap_ctl {
+ u32 mbar; /* MMAP_CTRL + 0x00 */
+
+ u32 cs0_start; /* MMAP_CTRL + 0x04 */
+ u32 cs0_stop; /* MMAP_CTRL + 0x08 */
+ u32 cs1_start; /* MMAP_CTRL + 0x0c */
+ u32 cs1_stop; /* MMAP_CTRL + 0x10 */
+ u32 cs2_start; /* MMAP_CTRL + 0x14 */
+ u32 cs2_stop; /* MMAP_CTRL + 0x18 */
+ u32 cs3_start; /* MMAP_CTRL + 0x1c */
+ u32 cs3_stop; /* MMAP_CTRL + 0x20 */
+ u32 cs4_start; /* MMAP_CTRL + 0x24 */
+ u32 cs4_stop; /* MMAP_CTRL + 0x28 */
+ u32 cs5_start; /* MMAP_CTRL + 0x2c */
+ u32 cs5_stop; /* MMAP_CTRL + 0x30 */
+
+ u32 sdram0; /* MMAP_CTRL + 0x34 */
+ u32 sdram1; /* MMAP_CTRL + 0X38 */
+
+ u32 reserved[4]; /* MMAP_CTRL + 0x3c .. 0x48 */
+
+ u32 boot_start; /* MMAP_CTRL + 0x4c */
+ u32 boot_stop; /* MMAP_CTRL + 0x50 */
+
+ u32 ipbi_ws_ctrl; /* MMAP_CTRL + 0x54 */
+
+ u32 cs6_start; /* MMAP_CTRL + 0x58 */
+ u32 cs6_stop; /* MMAP_CTRL + 0x5c */
+ u32 cs7_start; /* MMAP_CTRL + 0x60 */
+ u32 cs7_stop; /* MMAP_CTRL + 0x64 */
+};
+
+/* SDRAM control */
+struct mpc52xx_sdram {
+ u32 mode; /* SDRAM + 0x00 */
+ u32 ctrl; /* SDRAM + 0x04 */
+ u32 config1; /* SDRAM + 0x08 */
+ u32 config2; /* SDRAM + 0x0c */
+};
+
+/* SDMA */
+struct mpc52xx_sdma {
+ u32 taskBar; /* SDMA + 0x00 */
+ u32 currentPointer; /* SDMA + 0x04 */
+ u32 endPointer; /* SDMA + 0x08 */
+ u32 variablePointer; /* SDMA + 0x0c */
+
+ u8 IntVect1; /* SDMA + 0x10 */
+ u8 IntVect2; /* SDMA + 0x11 */
+ u16 PtdCntrl; /* SDMA + 0x12 */
+
+ u32 IntPend; /* SDMA + 0x14 */
+ u32 IntMask; /* SDMA + 0x18 */
+
+ u16 tcr[16]; /* SDMA + 0x1c .. 0x3a */
+
+ u8 ipr[32]; /* SDMA + 0x3c .. 0x5b */
+
+ u32 cReqSelect; /* SDMA + 0x5c */
+ u32 task_size0; /* SDMA + 0x60 */
+ u32 task_size1; /* SDMA + 0x64 */
+ u32 MDEDebug; /* SDMA + 0x68 */
+ u32 ADSDebug; /* SDMA + 0x6c */
+ u32 Value1; /* SDMA + 0x70 */
+ u32 Value2; /* SDMA + 0x74 */
+ u32 Control; /* SDMA + 0x78 */
+ u32 Status; /* SDMA + 0x7c */
+ u32 PTDDebug; /* SDMA + 0x80 */
+};
+
+/* GPT */
+struct mpc52xx_gpt {
+ u32 mode; /* GPTx + 0x00 */
+ u32 count; /* GPTx + 0x04 */
+ u32 pwm; /* GPTx + 0x08 */
+ u32 status; /* GPTx + 0X0c */
+};
+
+/* GPIO */
+struct mpc52xx_gpio {
+ u32 port_config; /* GPIO + 0x00 */
+ u32 simple_gpioe; /* GPIO + 0x04 */
+ u32 simple_ode; /* GPIO + 0x08 */
+ u32 simple_ddr; /* GPIO + 0x0c */
+ u32 simple_dvo; /* GPIO + 0x10 */
+ u32 simple_ival; /* GPIO + 0x14 */
+ u8 outo_gpioe; /* GPIO + 0x18 */
+ u8 reserved1[3]; /* GPIO + 0x19 */
+ u8 outo_dvo; /* GPIO + 0x1c */
+ u8 reserved2[3]; /* GPIO + 0x1d */
+ u8 sint_gpioe; /* GPIO + 0x20 */
+ u8 reserved3[3]; /* GPIO + 0x21 */
+ u8 sint_ode; /* GPIO + 0x24 */
+ u8 reserved4[3]; /* GPIO + 0x25 */
+ u8 sint_ddr; /* GPIO + 0x28 */
+ u8 reserved5[3]; /* GPIO + 0x29 */
+ u8 sint_dvo; /* GPIO + 0x2c */
+ u8 reserved6[3]; /* GPIO + 0x2d */
+ u8 sint_inten; /* GPIO + 0x30 */
+ u8 reserved7[3]; /* GPIO + 0x31 */
+ u16 sint_itype; /* GPIO + 0x34 */
+ u16 reserved8; /* GPIO + 0x36 */
+ u8 gpio_control; /* GPIO + 0x38 */
+ u8 reserved9[3]; /* GPIO + 0x39 */
+ u8 sint_istat; /* GPIO + 0x3c */
+ u8 sint_ival; /* GPIO + 0x3d */
+ u8 bus_errs; /* GPIO + 0x3e */
+ u8 reserved10; /* GPIO + 0x3f */
+};
+
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITHOUT_CD 4
+#define MPC52xx_GPIO_PSC_CONFIG_UART_WITH_CD 5
+#define MPC52xx_GPIO_PCI_DIS (1<<15)
+
+/* GPIO with WakeUp*/
+struct mpc52xx_gpio_wkup {
+ u8 wkup_gpioe; /* GPIO_WKUP + 0x00 */
+ u8 reserved1[3]; /* GPIO_WKUP + 0x03 */
+ u8 wkup_ode; /* GPIO_WKUP + 0x04 */
+ u8 reserved2[3]; /* GPIO_WKUP + 0x05 */
+ u8 wkup_ddr; /* GPIO_WKUP + 0x08 */
+ u8 reserved3[3]; /* GPIO_WKUP + 0x09 */
+ u8 wkup_dvo; /* GPIO_WKUP + 0x0C */
+ u8 reserved4[3]; /* GPIO_WKUP + 0x0D */
+ u8 wkup_inten; /* GPIO_WKUP + 0x10 */
+ u8 reserved5[3]; /* GPIO_WKUP + 0x11 */
+ u8 wkup_iinten; /* GPIO_WKUP + 0x14 */
+ u8 reserved6[3]; /* GPIO_WKUP + 0x15 */
+ u16 wkup_itype; /* GPIO_WKUP + 0x18 */
+ u8 reserved7[2]; /* GPIO_WKUP + 0x1A */
+ u8 wkup_maste; /* GPIO_WKUP + 0x1C */
+ u8 reserved8[3]; /* GPIO_WKUP + 0x1D */
+ u8 wkup_ival; /* GPIO_WKUP + 0x20 */
+ u8 reserved9[3]; /* GPIO_WKUP + 0x21 */
+ u8 wkup_istat; /* GPIO_WKUP + 0x24 */
+ u8 reserved10[3]; /* GPIO_WKUP + 0x25 */
+};
+
+/* XLB Bus control */
+struct mpc52xx_xlb {
+ u8 reserved[0x40];
+ u32 config; /* XLB + 0x40 */
+ u32 version; /* XLB + 0x44 */
+ u32 status; /* XLB + 0x48 */
+ u32 int_enable; /* XLB + 0x4c */
+ u32 addr_capture; /* XLB + 0x50 */
+ u32 bus_sig_capture; /* XLB + 0x54 */
+ u32 addr_timeout; /* XLB + 0x58 */
+ u32 data_timeout; /* XLB + 0x5c */
+ u32 bus_act_timeout; /* XLB + 0x60 */
+ u32 master_pri_enable; /* XLB + 0x64 */
+ u32 master_priority; /* XLB + 0x68 */
+ u32 base_address; /* XLB + 0x6c */
+ u32 snoop_window; /* XLB + 0x70 */
+};
+
+#define MPC52xx_XLB_CFG_PLDIS (1 << 31)
+#define MPC52xx_XLB_CFG_SNOOP (1 << 15)
+
+/* Clock Distribution control */
+struct mpc52xx_cdm {
+ u32 jtag_id; /* CDM + 0x00 reg0 read only */
+ u32 rstcfg; /* CDM + 0x04 reg1 read only */
+ u32 breadcrumb; /* CDM + 0x08 reg2 */
+
+ u8 mem_clk_sel; /* CDM + 0x0c reg3 byte0 */
+ u8 xlb_clk_sel; /* CDM + 0x0d reg3 byte1 read only */
+ u8 ipb_clk_sel; /* CDM + 0x0e reg3 byte2 */
+ u8 pci_clk_sel; /* CDM + 0x0f reg3 byte3 */
+
+ u8 ext_48mhz_en; /* CDM + 0x10 reg4 byte0 */
+ u8 fd_enable; /* CDM + 0x11 reg4 byte1 */
+ u16 fd_counters; /* CDM + 0x12 reg4 byte2,3 */
+
+ u32 clk_enables; /* CDM + 0x14 reg5 */
+
+ u8 osc_disable; /* CDM + 0x18 reg6 byte0 */
+ u8 reserved0[3]; /* CDM + 0x19 reg6 byte1,2,3 */
+
+ u8 ccs_sleep_enable; /* CDM + 0x1c reg7 byte0 */
+ u8 osc_sleep_enable; /* CDM + 0x1d reg7 byte1 */
+ u8 reserved1; /* CDM + 0x1e reg7 byte2 */
+ u8 ccs_qreq_test; /* CDM + 0x1f reg7 byte3 */
+
+ u8 soft_reset; /* CDM + 0x20 u8 byte0 */
+ u8 no_ckstp; /* CDM + 0x21 u8 byte0 */
+ u8 reserved2[2]; /* CDM + 0x22 u8 byte1,2,3 */
+
+ u8 pll_lock; /* CDM + 0x24 reg9 byte0 */
+ u8 pll_looselock; /* CDM + 0x25 reg9 byte1 */
+ u8 pll_sm_lockwin; /* CDM + 0x26 reg9 byte2 */
+ u8 reserved3; /* CDM + 0x27 reg9 byte3 */
+
+ u16 reserved4; /* CDM + 0x28 reg10 byte0,1 */
+ u16 mclken_div_psc1; /* CDM + 0x2a reg10 byte2,3 */
+
+ u16 reserved5; /* CDM + 0x2c reg11 byte0,1 */
+ u16 mclken_div_psc2; /* CDM + 0x2e reg11 byte2,3 */
+
+ u16 reserved6; /* CDM + 0x30 reg12 byte0,1 */
+ u16 mclken_div_psc3; /* CDM + 0x32 reg12 byte2,3 */
+
+ u16 reserved7; /* CDM + 0x34 reg13 byte0,1 */
+ u16 mclken_div_psc6; /* CDM + 0x36 reg13 byte2,3 */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+/* ========================================================================= */
+/* Prototypes for MPC52xx sysdev */
+/* ========================================================================= */
+
+#ifndef __ASSEMBLY__
+
+extern void mpc52xx_init_irq(void);
+extern unsigned int mpc52xx_get_irq(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_POWERPC_MPC52xx_H__ */
+
--
1.4.3.2

View File

@ -0,0 +1,33 @@
From 720e2caeeff0d9585d5627d29ffd660a5a9d9f88 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 20:43:39 +0100
Subject: [PATCH] [PATCH] powerpc: Restore 'proper' link order in platform
The 52xx was put before CHRP to allow EFIKA to be recognized
properly. Now the efika tree is fixed up in prom_init so
no need for this ugly hack. So we restore the 'normal'
order.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/platforms/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index 507d1b9..44d95ea 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -5,9 +5,9 @@ ifeq ($(CONFIG_PPC64),y)
obj-$(CONFIG_PPC_PMAC) += powermac/
endif
endif
-obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_CHRP) += chrp/
obj-$(CONFIG_4xx) += 4xx/
+obj-$(CONFIG_PPC_MPC52xx) += 52xx/
obj-$(CONFIG_PPC_83xx) += 83xx/
obj-$(CONFIG_PPC_85xx) += 85xx/
obj-$(CONFIG_PPC_86xx) += 86xx/
--
1.4.4.2

View File

@ -1,570 +0,0 @@
From b20c97e6f809bff52b864db1352a866c66a2bbd1 Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:06:28 +0100
Subject: [PATCH] Add MPC5200 interrupt controller driver
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
arch/powerpc/sysdev/Makefile | 1 +
arch/powerpc/sysdev/mpc52xx_pic.c | 538 +++++++++++++++++++++++++++++++++++++
2 files changed, 539 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 91f052d..5b5b61e 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -13,6 +13,7 @@ obj-$(CONFIG_FSL_SOC) += fsl_soc.o
obj-$(CONFIG_PPC_TODC) += todc.o
obj-$(CONFIG_TSI108_BRIDGE) += tsi108_pci.o tsi108_dev.o
obj-$(CONFIG_QUICC_ENGINE) += qe_lib/
+obj-$(CONFIG_PPC_MPC52xx) += mpc52xx_pic.o
ifeq ($(CONFIG_PPC_MERGE),y)
obj-$(CONFIG_PPC_I8259) += i8259.o
diff --git a/arch/powerpc/sysdev/mpc52xx_pic.c b/arch/powerpc/sysdev/mpc52xx_pic.c
new file mode 100644
index 0000000..6df51f0
--- /dev/null
+++ b/arch/powerpc/sysdev/mpc52xx_pic.c
@@ -0,0 +1,538 @@
+/*
+ *
+ * Programmable Interrupt Controller functions for the Freescale MPC52xx.
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * Based on the code from the 2.4 kernel by
+ * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Montavista Software, Inc
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/stddef.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/stddef.h>
+#include <linux/delay.h>
+#include <linux/irq.h>
+#include <linux/hardirq.h>
+
+#include <asm/io.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/prom.h>
+#include <asm/mpc52xx.h>
+
+/*
+ *
+*/
+
+static struct mpc52xx_intr __iomem *intr;
+static struct mpc52xx_sdma __iomem *sdma;
+static struct irq_host *mpc52xx_irqhost = NULL;
+
+static unsigned char mpc52xx_map_senses[4] = {
+ IRQ_TYPE_LEVEL_HIGH,
+ IRQ_TYPE_EDGE_RISING,
+ IRQ_TYPE_EDGE_FALLING,
+ IRQ_TYPE_LEVEL_LOW,
+};
+
+/*
+ *
+*/
+
+static inline void io_be_setbit(u32 __iomem * addr, int bitno)
+{
+ out_be32(addr, in_be32(addr) | (1 << bitno));
+}
+
+static inline void io_be_clrbit(u32 __iomem * addr, int bitno)
+{
+ out_be32(addr, in_be32(addr) & ~(1 << bitno));
+}
+
+/*
+ * IRQ[0-3] interrupt irq_chip
+*/
+
+static void mpc52xx_extirq_mask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_clrbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_unmask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_setbit(&intr->ctrl, 11 - l2irq);
+}
+
+static void mpc52xx_extirq_ack(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_setbit(&intr->ctrl, 27 - l2irq);
+}
+
+static struct irq_chip mpc52xx_extirq_irqchip = {
+ .typename = " MPC52xx IRQ[0-3] ",
+ .mask = mpc52xx_extirq_mask,
+ .unmask = mpc52xx_extirq_unmask,
+ .ack = mpc52xx_extirq_ack,
+};
+
+/*
+ * Main interrupt irq_chip
+*/
+
+static void mpc52xx_main_mask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_setbit(&intr->main_mask, 15 - l2irq);
+}
+
+static void mpc52xx_main_unmask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_clrbit(&intr->main_mask, 15 - l2irq);
+}
+
+static struct irq_chip mpc52xx_main_irqchip = {
+ .typename = "MPC52xx Main",
+ .mask = mpc52xx_main_mask,
+ .mask_ack = mpc52xx_main_mask,
+ .unmask = mpc52xx_main_unmask,
+};
+
+/*
+ * Peripherals interrupt irq_chip
+*/
+
+static void mpc52xx_periph_mask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_setbit(&intr->per_mask, 31 - l2irq);
+}
+
+static void mpc52xx_periph_unmask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_clrbit(&intr->per_mask, 31 - l2irq);
+}
+
+static struct irq_chip mpc52xx_periph_irqchip = {
+ .typename = "MPC52xx Peripherals",
+ .mask = mpc52xx_periph_mask,
+ .mask_ack = mpc52xx_periph_mask,
+ .unmask = mpc52xx_periph_unmask,
+};
+
+/*
+ * SDMA interrupt irq_chip
+*/
+
+static void mpc52xx_sdma_mask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_setbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_unmask(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ io_be_clrbit(&sdma->IntMask, l2irq);
+}
+
+static void mpc52xx_sdma_ack(unsigned int virq)
+{
+ int irq;
+ int l2irq;
+
+ irq = irq_map[virq].hwirq;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ pr_debug("%s: irq=%x. l2=%d\n", __func__, irq, l2irq);
+
+ out_be32(&sdma->IntPend, 1 << l2irq);
+}
+
+static struct irq_chip mpc52xx_sdma_irqchip = {
+ .typename = "MPC52xx SDMA",
+ .mask = mpc52xx_sdma_mask,
+ .unmask = mpc52xx_sdma_unmask,
+ .ack = mpc52xx_sdma_ack,
+};
+
+/*
+ * irq_host
+*/
+
+static int mpc52xx_irqhost_match(struct irq_host *h, struct device_node *node)
+{
+ pr_debug("%s: node=%p\n", __func__, node);
+ return mpc52xx_irqhost->host_data == node;
+}
+
+static int mpc52xx_irqhost_xlate(struct irq_host *h, struct device_node *ct,
+ u32 * intspec, unsigned int intsize,
+ irq_hw_number_t * out_hwirq,
+ unsigned int *out_flags)
+{
+ int intrvect_l1;
+ int intrvect_l2;
+ int intrvect_type;
+ int intrvect_linux;
+
+ if (intsize != 3)
+ return -1;
+
+ intrvect_l1 = (int)intspec[0];
+ intrvect_l2 = (int)intspec[1];
+ intrvect_type = (int)intspec[2];
+
+ intrvect_linux =
+ (intrvect_l1 << MPC52xx_IRQ_L1_OFFSET) & MPC52xx_IRQ_L1_MASK;
+ intrvect_linux |=
+ (intrvect_l2 << MPC52xx_IRQ_L2_OFFSET) & MPC52xx_IRQ_L2_MASK;
+
+ pr_debug("return %x, l1=%d, l2=%d\n", intrvect_linux, intrvect_l1,
+ intrvect_l2);
+
+ *out_hwirq = intrvect_linux;
+ *out_flags = mpc52xx_map_senses[intrvect_type];
+
+ return 0;
+}
+
+/*
+ * this function retrieves the correct IRQ type out
+ * of the MPC regs
+ * Only externals IRQs needs this
+*/
+static int mpc52xx_irqx_gettype(int irq)
+{
+ int type;
+ u32 ctrl_reg;
+
+ ctrl_reg = in_be32(&intr->ctrl);
+ type = (ctrl_reg >> (22 - irq * 2)) & 0x3;
+
+ return mpc52xx_map_senses[type];
+}
+
+static int mpc52xx_irqhost_map(struct irq_host *h, unsigned int virq,
+ irq_hw_number_t irq)
+{
+ int l1irq;
+ int l2irq;
+ struct irq_chip *good_irqchip;
+ void *good_handle;
+ int type;
+
+ l1irq = (irq & MPC52xx_IRQ_L1_MASK) >> MPC52xx_IRQ_L1_OFFSET;
+ l2irq = (irq & MPC52xx_IRQ_L2_MASK) >> MPC52xx_IRQ_L2_OFFSET;
+
+ /*
+ * Most of ours IRQs will be level low
+ * Only external IRQs on some platform may be others
+ */
+ type = IRQ_TYPE_LEVEL_LOW;
+
+ switch (l1irq) {
+ case MPC52xx_IRQ_L1_CRIT:
+ pr_debug("%s: Critical. l2=%x\n", __func__, l2irq);
+
+ BUG_ON(l2irq != 0);
+
+ type = mpc52xx_irqx_gettype(l2irq);
+ good_irqchip = &mpc52xx_extirq_irqchip;
+ break;
+
+ case MPC52xx_IRQ_L1_MAIN:
+ pr_debug("%s: Main IRQ[1-3] l2=%x\n", __func__, l2irq);
+
+ if ((l2irq >= 1) && (l2irq <= 3)) {
+ type = mpc52xx_irqx_gettype(l2irq);
+ good_irqchip = &mpc52xx_extirq_irqchip;
+ } else {
+ good_irqchip = &mpc52xx_main_irqchip;
+ }
+ break;
+
+ case MPC52xx_IRQ_L1_PERP:
+ pr_debug("%s: Peripherals. l2=%x\n", __func__, l2irq);
+ good_irqchip = &mpc52xx_periph_irqchip;
+ break;
+
+ case MPC52xx_IRQ_L1_SDMA:
+ pr_debug("%s: SDMA. l2=%x\n", __func__, l2irq);
+ good_irqchip = &mpc52xx_sdma_irqchip;
+ break;
+
+ default:
+ pr_debug("%s: Error, unknown L1 IRQ (0x%x)\n", __func__, l1irq);
+ printk(KERN_ERR "Unknow IRQ!\n");
+ return -EINVAL;
+ }
+
+ switch (type) {
+ case IRQ_TYPE_EDGE_FALLING:
+ case IRQ_TYPE_EDGE_RISING:
+ good_handle = handle_edge_irq;
+ break;
+ default:
+ good_handle = handle_level_irq;
+ }
+
+ set_irq_chip_and_handler(virq, good_irqchip, good_handle);
+
+ pr_debug("%s: virq=%x, hw=%x. type=%x\n", __func__, virq,
+ (int)irq, type);
+
+ return 0;
+}
+
+static struct irq_host_ops mpc52xx_irqhost_ops = {
+ .match = mpc52xx_irqhost_match,
+ .xlate = mpc52xx_irqhost_xlate,
+ .map = mpc52xx_irqhost_map,
+};
+
+/*
+ * init (public)
+*/
+
+void __init mpc52xx_init_irq(void)
+{
+ struct device_node *picnode = NULL;
+ int picnode_regsize;
+ u32 picnode_regoffset;
+
+ struct device_node *sdmanode = NULL;
+ int sdmanode_regsize;
+ u32 sdmanode_regoffset;
+
+ u64 size64;
+ int flags;
+
+ u32 intr_ctrl;
+
+ picnode = of_find_compatible_node(NULL, "interrupt-controller",
+ "mpc5200-pic");
+ if (picnode == NULL) {
+ printk(KERN_ERR "MPC52xx PIC: "
+ "Unable to find the interrupt controller "
+ "in the OpenFirmware device tree\n");
+ goto end;
+ }
+
+ sdmanode = of_find_compatible_node(NULL, "dma-controller",
+ "mpc5200-bestcomm");
+ if (sdmanode == NULL) {
+ printk(KERN_ERR "MPC52xx PIC"
+ "Unable to find the Bestcomm DMA controller device "
+ "in the OpenFirmware device tree\n");
+ goto end;
+ }
+
+ /* Retrieve PIC ressources */
+ picnode_regoffset = (u32) of_get_address(picnode, 0, &size64, &flags);
+ if (picnode_regoffset == 0) {
+ printk(KERN_ERR "MPC52xx PIC"
+ "Unable to get the interrupt controller address\n");
+ goto end;
+ }
+
+ picnode_regoffset =
+ of_translate_address(picnode, (u32 *) picnode_regoffset);
+ picnode_regsize = (int)size64;
+
+ /* Retrieve SDMA ressources */
+ sdmanode_regoffset = (u32) of_get_address(sdmanode, 0, &size64, &flags);
+ if (sdmanode_regoffset == 0) {
+ printk(KERN_ERR "MPC52xx PIC: "
+ "Unable to get the Bestcomm DMA controller address\n");
+ goto end;
+ }
+
+ sdmanode_regoffset =
+ of_translate_address(sdmanode, (u32 *) sdmanode_regoffset);
+ sdmanode_regsize = (int)size64;
+
+ /* Remap the necessary zones */
+ intr = ioremap(picnode_regoffset, picnode_regsize);
+ if (intr == NULL) {
+ printk(KERN_ERR "MPC52xx PIC: "
+ "Unable to ioremap interrupt controller registers!\n");
+ goto end;
+ }
+
+ sdma = ioremap(sdmanode_regoffset, sdmanode_regsize);
+ if (sdma == NULL) {
+ iounmap(intr);
+ printk(KERN_ERR "MPC52xx PIC: "
+ "Unable to ioremap Bestcomm DMA registers!\n");
+ goto end;
+ }
+
+ printk(KERN_INFO "MPC52xx PIC: MPC52xx PIC Remapped at 0x%8.8x\n",
+ picnode_regoffset);
+ printk(KERN_INFO "MPC52xx PIC: MPC52xx SDMA Remapped at 0x%8.8x\n",
+ sdmanode_regoffset);
+
+ /* Disable all interrupt sources. */
+ out_be32(&sdma->IntPend, 0xffffffff); /* 1 means clear pending */
+ out_be32(&sdma->IntMask, 0xffffffff); /* 1 means disabled */
+ out_be32(&intr->per_mask, 0x7ffffc00); /* 1 means disabled */
+ out_be32(&intr->main_mask, 0x00010fff); /* 1 means disabled */
+ intr_ctrl = in_be32(&intr->ctrl);
+ intr_ctrl &= 0x00ff0000; /* Keeps IRQ[0-3] config */
+ intr_ctrl |= 0x0f000000 | /* clear IRQ 0-3 */
+ 0x00001000 | /* MEE master external enable */
+ 0x00000000 | /* 0 means disable IRQ 0-3 */
+ 0x00000001; /* CEb route critical normally */
+ out_be32(&intr->ctrl, intr_ctrl);
+
+ /* Zero a bunch of the priority settings. */
+ out_be32(&intr->per_pri1, 0);
+ out_be32(&intr->per_pri2, 0);
+ out_be32(&intr->per_pri3, 0);
+ out_be32(&intr->main_pri1, 0);
+ out_be32(&intr->main_pri2, 0);
+
+ /*
+ * As last step, add an irq host to translate the real
+ * hw irq information provided by the ofw to linux virq
+ */
+
+ mpc52xx_irqhost =
+ irq_alloc_host(IRQ_HOST_MAP_LINEAR, MPC52xx_IRQ_HIGHTESTHWIRQ,
+ &mpc52xx_irqhost_ops, -1);
+
+ if (mpc52xx_irqhost) {
+ mpc52xx_irqhost->host_data = picnode;
+ printk(KERN_INFO "MPC52xx PIC is up and running!\n");
+ } else {
+ printk(KERN_ERR
+ "MPC52xx PIC: Unable to allocate the IRQ host\n");
+ }
+
+end:
+ of_node_put(picnode);
+ of_node_put(sdmanode);
+}
+
+/*
+ * get_irq (public)
+*/
+unsigned int mpc52xx_get_irq(void)
+{
+ u32 status;
+ int irq = NO_IRQ_IGNORE;
+
+ status = in_be32(&intr->enc_status);
+ if (status & 0x00000400) { /* critical */
+ irq = (status >> 8) & 0x3;
+ if (irq == 2) /* high priority peripheral */
+ goto peripheral;
+ irq |= (MPC52xx_IRQ_L1_CRIT << MPC52xx_IRQ_L1_OFFSET) &
+ MPC52xx_IRQ_L1_MASK;
+ } else if (status & 0x00200000) { /* main */
+ irq = (status >> 16) & 0x1f;
+ if (irq == 4) /* low priority peripheral */
+ goto peripheral;
+ irq |= (MPC52xx_IRQ_L1_MAIN << MPC52xx_IRQ_L1_OFFSET) &
+ MPC52xx_IRQ_L1_MASK;
+ } else if (status & 0x20000000) { /* peripheral */
+ peripheral:
+ irq = (status >> 24) & 0x1f;
+ if (irq == 0) { /* bestcomm */
+ status = in_be32(&sdma->IntPend);
+ irq = ffs(status) - 1;
+ irq |= (MPC52xx_IRQ_L1_SDMA << MPC52xx_IRQ_L1_OFFSET) &
+ MPC52xx_IRQ_L1_MASK;
+ } else
+ irq |= (MPC52xx_IRQ_L1_PERP << MPC52xx_IRQ_L1_OFFSET) &
+ MPC52xx_IRQ_L1_MASK;
+ }
+
+ pr_debug("%s: irq=%x. virq=%d\n", __func__, irq,
+ irq_linear_revmap(mpc52xx_irqhost, irq));
+
+ return irq_linear_revmap(mpc52xx_irqhost, irq);
+}
+
--
1.4.3.2

View File

@ -0,0 +1,236 @@
From 9282a04f14cef512736ac4a895fb48456e6a8989 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Thu, 14 Dec 2006 14:13:26 +1100
Subject: [PATCH] [PATCH] Rework the OHCI quirk mecanism as suggested by David
This patch applies David Brownell's suggestion for reworking the
OHCI quirk mechanism via a table of PCI IDs. It adapts the existing
quirks to use that mechanism.
This also moves the quirks to reset() as suggested by the comment
in there. This is necessary as we need to have the endian properly
set before we try to init the controller.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
drivers/usb/host/ohci-pci.c | 173 +++++++++++++++++++++++++++-----------------
1 file changed, 110 insertions(+), 63 deletions(-)
---
drivers/usb/host/ohci-pci.c | 173 +++++++++++++++++++++++++++----------------
1 files changed, 110 insertions(+), 63 deletions(-)
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 596e0b4..82fbec3 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -20,79 +20,128 @@
/*-------------------------------------------------------------------------*/
-static int
-ohci_pci_reset (struct usb_hcd *hcd)
+/* AMD 756, for most chips (early revs), corrupts register
+ * values on read ... so enable the vendor workaround.
+ */
+static int __devinit ohci_quirk_amd756(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- ohci_hcd_init (ohci);
- return ohci_init (ohci);
+ ohci->flags = OHCI_QUIRK_AMD756;
+ ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
+
+ /* also erratum 10 (suspend/resume issues) */
+ device_init_wakeup(&hcd->self.root_hub->dev, 0);
+
+ return 0;
}
-static int __devinit
-ohci_pci_start (struct usb_hcd *hcd)
+/* Apple's OHCI driver has a lot of bizarre workarounds
+ * for this chip. Evidently control and bulk lists
+ * can get confused. (B&W G3 models, and ...)
+ */
+static int __devinit ohci_quirk_opti(struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- int ret;
- /* REVISIT this whole block should move to reset(), which handles
- * all the other one-time init.
+ ohci_dbg (ohci, "WARNING: OPTi workarounds unavailable\n");
+
+ return 0;
+}
+
+/* Check for NSC87560. We have to look at the bridge (fn1) to
+ * identify the USB (fn2). This quirk might apply to more or
+ * even all NSC stuff.
+ */
+static int __devinit ohci_quirk_ns(struct usb_hcd *hcd)
+{
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ struct pci_dev *b;
+
+ b = pci_get_slot (pdev->bus, PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
+ if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
+ && b->vendor == PCI_VENDOR_ID_NS) {
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+ ohci->flags |= OHCI_QUIRK_SUPERIO;
+ ohci_dbg (ohci, "Using NSC SuperIO setup\n");
+ }
+ pci_dev_put(b);
+
+ return 0;
+}
+
+/* Check for Compaq's ZFMicro chipset, which needs short
+ * delays before control or bulk queues get re-activated
+ * in finish_unlinks()
+ */
+static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+ ohci->flags |= OHCI_QUIRK_ZFMICRO;
+ ohci_dbg (ohci, "enabled Compaq ZFMicro chipset quirk\n");
+
+ return 0;
+}
+
+
+/* List of quirks for OHCI */
+static const struct pci_device_id ohci_pci_quirks[] = {
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x740c),
+ .driver_data = (unsigned long)ohci_quirk_amd756,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_OPTI, 0xc861),
+ .driver_data = (unsigned long)ohci_quirk_opti,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_ANY_ID),
+ .driver_data = (unsigned long)ohci_quirk_ns,
+ },
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
+ .driver_data = (unsigned long)ohci_quirk_zfmicro,
+ },
+ /* FIXME for some of the early AMD 760 southbridges, OHCI
+ * won't work at all. blacklist them.
*/
+ {},
+};
+
+static int ohci_pci_reset (struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret = 0;
+
if (hcd->self.controller) {
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
+ const struct pci_device_id *quirk_id;
- /* AMD 756, for most chips (early revs), corrupts register
- * values on read ... so enable the vendor workaround.
- */
- if (pdev->vendor == PCI_VENDOR_ID_AMD
- && pdev->device == 0x740c) {
- ohci->flags = OHCI_QUIRK_AMD756;
- ohci_dbg (ohci, "AMD756 erratum 4 workaround\n");
- /* also erratum 10 (suspend/resume issues) */
- device_init_wakeup(&hcd->self.root_hub->dev, 0);
+ quirk_id = pci_match_id(ohci_pci_quirks, pdev);
+ if (quirk_id != NULL) {
+ int (*quirk)(struct usb_hcd *ohci);
+ quirk = (void *)quirk_id->driver_data;
+ ret = quirk(hcd);
}
+ }
+ if (ret == 0) {
+ ohci_hcd_init (ohci);
+ return ohci_init (ohci);
+ }
+ return ret;
+}
- /* FIXME for some of the early AMD 760 southbridges, OHCI
- * won't work at all. blacklist them.
- */
-
- /* Apple's OHCI driver has a lot of bizarre workarounds
- * for this chip. Evidently control and bulk lists
- * can get confused. (B&W G3 models, and ...)
- */
- else if (pdev->vendor == PCI_VENDOR_ID_OPTI
- && pdev->device == 0xc861) {
- ohci_dbg (ohci,
- "WARNING: OPTi workarounds unavailable\n");
- }
- /* Check for NSC87560. We have to look at the bridge (fn1) to
- * identify the USB (fn2). This quirk might apply to more or
- * even all NSC stuff.
- */
- else if (pdev->vendor == PCI_VENDOR_ID_NS) {
- struct pci_dev *b;
-
- b = pci_get_slot (pdev->bus,
- PCI_DEVFN (PCI_SLOT (pdev->devfn), 1));
- if (b && b->device == PCI_DEVICE_ID_NS_87560_LIO
- && b->vendor == PCI_VENDOR_ID_NS) {
- ohci->flags |= OHCI_QUIRK_SUPERIO;
- ohci_dbg (ohci, "Using NSC SuperIO setup\n");
- }
- pci_dev_put(b);
- }
+static int __devinit ohci_pci_start (struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+ int ret;
- /* Check for Compaq's ZFMicro chipset, which needs short
- * delays before control or bulk queues get re-activated
- * in finish_unlinks()
- */
- else if (pdev->vendor == PCI_VENDOR_ID_COMPAQ
- && pdev->device == 0xa0f8) {
- ohci->flags |= OHCI_QUIRK_ZFMICRO;
- ohci_dbg (ohci,
- "enabled Compaq ZFMicro chipset quirk\n");
- }
+#ifdef CONFIG_PM /* avoid warnings about unused pdev */
+ if (hcd->self.controller) {
+ struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
/* RWC may not be set for add-in PCI cards, since boot
* firmware probably ignored them. This transfers PCI
@@ -101,16 +150,14 @@ ohci_pci_start (struct usb_hcd *hcd)
if (device_may_wakeup(&pdev->dev))
ohci->hc_control |= OHCI_CTRL_RWC;
}
+#endif /* CONFIG_PM */
- /* NOTE: there may have already been a first reset, to
- * keep bios/smm irqs from making trouble
- */
- if ((ret = ohci_run (ohci)) < 0) {
+ ret = ohci_run (ohci);
+ if (ret < 0) {
ohci_err (ohci, "can't start\n");
ohci_stop (hcd);
- return ret;
}
- return 0;
+ return ret;
}
#ifdef CONFIG_PM
--
1.4.4.2

View File

@ -0,0 +1,367 @@
From a87f8738eb3651b7eea1feae793def3a48dc36c6 Mon Sep 17 00:00:00 2001
From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Date: Thu, 14 Dec 2006 14:13:28 +1100
Subject: [PATCH] [PATCH] Implement support for "split" endian OHCI
This patch separates support for big endian MMIO register access
and big endian descriptors in order to support the Toshiba SCC
implementation which has big endian registers but little endian
in-memory descriptors.
It simplifies the access functions a bit in ohci.h while at it.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
drivers/usb/host/Kconfig | 10 ++
drivers/usb/host/ohci-pci.c | 26 +++++++
drivers/usb/host/ohci-ppc-soc.c | 2
drivers/usb/host/ohci.h | 147 +++++++++++++++++++++++++---------------
4 files changed, 130 insertions(+), 55 deletions(-)
---
drivers/usb/host/Kconfig | 10 ++-
drivers/usb/host/ohci-pci.c | 26 +++++++
drivers/usb/host/ohci-ppc-soc.c | 2 +-
drivers/usb/host/ohci.h | 147 +++++++++++++++++++++++++--------------
4 files changed, 130 insertions(+), 55 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index cc60759..faabce8 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -101,7 +101,8 @@ config USB_OHCI_HCD_PPC_SOC
bool "OHCI support for on-chip PPC USB controller"
depends on USB_OHCI_HCD && (STB03xxx || PPC_MPC52xx)
default y
- select USB_OHCI_BIG_ENDIAN
+ select USB_OHCI_BIG_ENDIAN_DESC
+ select USB_OHCI_BIG_ENDIAN_MMIO
---help---
Enables support for the USB controller on the MPC52xx or
STB03xxx processor chip. If unsure, say Y.
@@ -115,7 +116,12 @@ config USB_OHCI_HCD_PCI
Enables support for PCI-bus plug-in USB controller cards.
If unsure, say Y.
-config USB_OHCI_BIG_ENDIAN
+config USB_OHCI_BIG_ENDIAN_DESC
+ bool
+ depends on USB_OHCI_HCD
+ default n
+
+config USB_OHCI_BIG_ENDIAN_MMIO
bool
depends on USB_OHCI_HCD
default n
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 82fbec3..292daf0 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -85,6 +85,27 @@ static int __devinit ohci_quirk_zfmicro(struct usb_hcd *hcd)
return 0;
}
+/* Check for Toshiba SCC OHCI which has big endian registers
+ * and little endian in memory data structures
+ */
+static int __devinit ohci_quirk_toshiba_scc(struct usb_hcd *hcd)
+{
+ struct ohci_hcd *ohci = hcd_to_ohci (hcd);
+
+ /* That chip is only present in the southbridge of some
+ * cell based platforms which are supposed to select
+ * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO. We verify here if
+ * that was the case though.
+ */
+#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ ohci->flags |= OHCI_QUIRK_BE_MMIO;
+ ohci_dbg (ohci, "enabled big endian Toshiba quirk\n");
+ return 0;
+#else
+ ohci_err (ohci, "unsupported big endian Toshiba quirk\n");
+ return -ENXIO;
+#endif
+}
/* List of quirks for OHCI */
static const struct pci_device_id ohci_pci_quirks[] = {
@@ -104,9 +125,14 @@ static const struct pci_device_id ohci_pci_quirks[] = {
PCI_DEVICE(PCI_VENDOR_ID_COMPAQ, 0xa0f8),
.driver_data = (unsigned long)ohci_quirk_zfmicro,
},
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_TOSHIBA_2, 0x01b6),
+ .driver_data = (unsigned long)ohci_quirk_toshiba_scc,
+ },
/* FIXME for some of the early AMD 760 southbridges, OHCI
* won't work at all. blacklist them.
*/
+
{},
};
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index e1a7eb8..c7ce8e6 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -72,7 +72,7 @@ static int usb_hcd_ppc_soc_probe(const struct hc_driver *driver,
}
ohci = hcd_to_ohci(hcd);
- ohci->flags |= OHCI_BIG_ENDIAN;
+ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
ohci_hcd_init(ohci);
retval = usb_add_hcd(hcd, irq, IRQF_DISABLED);
diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h
index 405257f..fc7c161 100644
--- a/drivers/usb/host/ohci.h
+++ b/drivers/usb/host/ohci.h
@@ -394,8 +394,9 @@ struct ohci_hcd {
#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */
#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */
#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */
-#define OHCI_BIG_ENDIAN 0x08 /* big endian HC */
-#define OHCI_QUIRK_ZFMICRO 0x10 /* Compaq ZFMicro chipset*/
+#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */
+#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */
+#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/
// there are also chip quirks/bugs in init logic
};
@@ -439,117 +440,156 @@ static inline struct usb_hcd *ohci_to_hcd (const struct ohci_hcd *ohci)
* a minority (notably the IBM STB04XXX and the Motorola MPC5200
* processors) implement them in big endian format.
*
+ * In addition some more exotic implementations like the Toshiba
+ * Spider (aka SCC) cell southbridge are "mixed" endian, that is,
+ * they have a different endianness for registers vs. in-memory
+ * descriptors.
+ *
* This attempts to support either format at compile time without a
* runtime penalty, or both formats with the additional overhead
* of checking a flag bit.
+ *
+ * That leads to some tricky Kconfig rules howevber. There are
+ * different defaults based on some arch/ppc platforms, though
+ * the basic rules are:
+ *
+ * Controller type Kconfig options needed
+ * --------------- ----------------------
+ * little endian CONFIG_USB_OHCI_LITTLE_ENDIAN
+ *
+ * fully big endian CONFIG_USB_OHCI_BIG_ENDIAN_DESC _and_
+ * CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
+ *
+ * mixed endian CONFIG_USB_OHCI_LITTLE_ENDIAN _and_
+ * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC}
+ *
+ * (If you have a mixed endian controller, you -must- also define
+ * CONFIG_USB_OHCI_LITTLE_ENDIAN or things will not work when building
+ * both your mixed endian and a fully big endian controller support in
+ * the same kernel image).
*/
-#ifdef CONFIG_USB_OHCI_BIG_ENDIAN
+#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_DESC
+#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN
+#define big_endian_desc(ohci) (ohci->flags & OHCI_QUIRK_BE_DESC)
+#else
+#define big_endian_desc(ohci) 1 /* only big endian */
+#endif
+#else
+#define big_endian_desc(ohci) 0 /* only little endian */
+#endif
+#ifdef CONFIG_USB_OHCI_BIG_ENDIAN_MMIO
#ifdef CONFIG_USB_OHCI_LITTLE_ENDIAN
-#define big_endian(ohci) (ohci->flags & OHCI_BIG_ENDIAN) /* either */
+#define big_endian_mmio(ohci) (ohci->flags & OHCI_QUIRK_BE_MMIO)
+#else
+#define big_endian_mmio(ohci) 1 /* only big endian */
+#endif
#else
-#define big_endian(ohci) 1 /* only big endian */
+#define big_endian_mmio(ohci) 0 /* only little endian */
#endif
/*
* Big-endian read/write functions are arch-specific.
* Other arches can be added if/when they're needed.
+ *
+ * REVISIT: arch/powerpc now has readl/writel_be, so the
+ * definition below can die once the STB04xxx support is
+ * finally ported over.
*/
-#if defined(CONFIG_PPC)
+#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE)
#define readl_be(addr) in_be32((__force unsigned *)addr)
#define writel_be(val, addr) out_be32((__force unsigned *)addr, val)
#endif
-static inline unsigned int ohci_readl (const struct ohci_hcd *ohci,
- __hc32 __iomem * regs)
+static inline unsigned int _ohci_readl (const struct ohci_hcd *ohci,
+ __hc32 __iomem * regs)
{
- return big_endian(ohci) ? readl_be (regs) : readl ((__force u32 *)regs);
+ return big_endian_mmio(ohci) ?
+ readl_be ((__force u32 *)regs) :
+ readl ((__force u32 *)regs);
}
-static inline void ohci_writel (const struct ohci_hcd *ohci,
- const unsigned int val, __hc32 __iomem *regs)
+static inline void _ohci_writel (const struct ohci_hcd *ohci,
+ const unsigned int val, __hc32 __iomem *regs)
{
- big_endian(ohci) ? writel_be (val, regs) :
- writel (val, (__force u32 *)regs);
+ big_endian_mmio(ohci) ?
+ writel_be (val, (__force u32 *)regs) :
+ writel (val, (__force u32 *)regs);
}
-#else /* !CONFIG_USB_OHCI_BIG_ENDIAN */
-
-#define big_endian(ohci) 0 /* only little endian */
-
#ifdef CONFIG_ARCH_LH7A404
- /* Marc Singer: at the time this code was written, the LH7A404
- * had a problem reading the USB host registers. This
- * implementation of the ohci_readl function performs the read
- * twice as a work-around.
- */
-static inline unsigned int
-ohci_readl (const struct ohci_hcd *ohci, const __hc32 *regs)
-{
- *(volatile __force unsigned int*) regs;
- return *(volatile __force unsigned int*) regs;
-}
+/* Marc Singer: at the time this code was written, the LH7A404
+ * had a problem reading the USB host registers. This
+ * implementation of the ohci_readl function performs the read
+ * twice as a work-around.
+ */
+#define ohci_readl(o,r) (_ohci_readl(o,r),_ohci_readl(o,r))
+#define ohci_writel(o,v,r) _ohci_writel(o,v,r)
#else
- /* Standard version of ohci_readl uses standard, platform
- * specific implementation. */
-static inline unsigned int
-ohci_readl (const struct ohci_hcd *ohci, __hc32 __iomem * regs)
-{
- return readl(regs);
-}
+#define ohci_readl(o,r) _ohci_readl(o,r)
+#define ohci_writel(o,v,r) _ohci_writel(o,v,r)
#endif
-static inline void ohci_writel (const struct ohci_hcd *ohci,
- const unsigned int val, __hc32 __iomem *regs)
-{
- writel (val, regs);
-}
-
-#endif /* !CONFIG_USB_OHCI_BIG_ENDIAN */
/*-------------------------------------------------------------------------*/
/* cpu to ohci */
static inline __hc16 cpu_to_hc16 (const struct ohci_hcd *ohci, const u16 x)
{
- return big_endian(ohci) ? (__force __hc16)cpu_to_be16(x) : (__force __hc16)cpu_to_le16(x);
+ return big_endian_desc(ohci) ?
+ (__force __hc16)cpu_to_be16(x) :
+ (__force __hc16)cpu_to_le16(x);
}
static inline __hc16 cpu_to_hc16p (const struct ohci_hcd *ohci, const u16 *x)
{
- return big_endian(ohci) ? cpu_to_be16p(x) : cpu_to_le16p(x);
+ return big_endian_desc(ohci) ?
+ cpu_to_be16p(x) :
+ cpu_to_le16p(x);
}
static inline __hc32 cpu_to_hc32 (const struct ohci_hcd *ohci, const u32 x)
{
- return big_endian(ohci) ? (__force __hc32)cpu_to_be32(x) : (__force __hc32)cpu_to_le32(x);
+ return big_endian_desc(ohci) ?
+ (__force __hc32)cpu_to_be32(x) :
+ (__force __hc32)cpu_to_le32(x);
}
static inline __hc32 cpu_to_hc32p (const struct ohci_hcd *ohci, const u32 *x)
{
- return big_endian(ohci) ? cpu_to_be32p(x) : cpu_to_le32p(x);
+ return big_endian_desc(ohci) ?
+ cpu_to_be32p(x) :
+ cpu_to_le32p(x);
}
/* ohci to cpu */
static inline u16 hc16_to_cpu (const struct ohci_hcd *ohci, const __hc16 x)
{
- return big_endian(ohci) ? be16_to_cpu((__force __be16)x) : le16_to_cpu((__force __le16)x);
+ return big_endian_desc(ohci) ?
+ be16_to_cpu((__force __be16)x) :
+ le16_to_cpu((__force __le16)x);
}
static inline u16 hc16_to_cpup (const struct ohci_hcd *ohci, const __hc16 *x)
{
- return big_endian(ohci) ? be16_to_cpup((__force __be16 *)x) : le16_to_cpup((__force __le16 *)x);
+ return big_endian_desc(ohci) ?
+ be16_to_cpup((__force __be16 *)x) :
+ le16_to_cpup((__force __le16 *)x);
}
static inline u32 hc32_to_cpu (const struct ohci_hcd *ohci, const __hc32 x)
{
- return big_endian(ohci) ? be32_to_cpu((__force __be32)x) : le32_to_cpu((__force __le32)x);
+ return big_endian_desc(ohci) ?
+ be32_to_cpu((__force __be32)x) :
+ le32_to_cpu((__force __le32)x);
}
static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
{
- return big_endian(ohci) ? be32_to_cpup((__force __be32 *)x) : le32_to_cpup((__force __le32 *)x);
+ return big_endian_desc(ohci) ?
+ be32_to_cpup((__force __be32 *)x) :
+ le32_to_cpup((__force __le32 *)x);
}
/*-------------------------------------------------------------------------*/
@@ -557,6 +597,9 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
/* HCCA frame number is 16 bits, but is accessed as 32 bits since not all
* hardware handles 16 bit reads. That creates a different confusion on
* some big-endian SOC implementations. Same thing happens with PSW access.
+ *
+ * FIXME: Deal with that as a runtime quirk when STB03xxx is ported over
+ * to arch/powerpc
*/
#ifdef CONFIG_STB03xxx
@@ -568,7 +611,7 @@ static inline u32 hc32_to_cpup (const struct ohci_hcd *ohci, const __hc32 *x)
static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
{
u32 tmp;
- if (big_endian(ohci)) {
+ if (big_endian_desc(ohci)) {
tmp = be32_to_cpup((__force __be32 *)&ohci->hcca->frame_no);
tmp >>= OHCI_BE_FRAME_NO_SHIFT;
} else
@@ -580,7 +623,7 @@ static inline u16 ohci_frame_no(const struct ohci_hcd *ohci)
static inline __hc16 *ohci_hwPSWp(const struct ohci_hcd *ohci,
const struct td *td, int index)
{
- return (__hc16 *)(big_endian(ohci) ?
+ return (__hc16 *)(big_endian_desc(ohci) ?
&td->hwPSW[index ^ 1] : &td->hwPSW[index]);
}
--
1.4.4.2

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,470 @@
From 51294aa1482ea961a3e51ddac587b70b7c1c8ba0 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Wed, 13 Dec 2006 20:35:37 +0100
Subject: [PATCH] [PATCH] ohci: Rework bus glue integration to allow several at once
The previous model had the module_init & module_exit function in the
bus glue .c files themselves. That's a problem if several glues need
to be selected at once and the driver is built has module. This case
is quite common in embedded system where you want to handle both the
integrated ohci controller and some extra controller on PCI.
The ohci-hcd.c file now provide the module_init & module_exit and
appropriate driver registering/unregistering is done conditionally,
using #ifdefs.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/usb/host/ohci-at91.c | 15 ------
drivers/usb/host/ohci-au1xxx.c | 16 ------
drivers/usb/host/ohci-ep93xx.c | 12 -----
drivers/usb/host/ohci-hcd.c | 98 +++++++++++++++++++++++++++++++++------
drivers/usb/host/ohci-lh7a404.c | 16 ------
drivers/usb/host/ohci-omap.c | 19 --------
drivers/usb/host/ohci-pci.c | 20 --------
drivers/usb/host/ohci-pnx4008.c | 12 -----
drivers/usb/host/ohci-pnx8550.c | 16 ------
drivers/usb/host/ohci-ppc-soc.c | 16 ------
drivers/usb/host/ohci-pxa27x.c | 16 ------
drivers/usb/host/ohci-s3c2410.c | 12 -----
drivers/usb/host/ohci-sa1111.c | 16 ------
13 files changed, 83 insertions(+), 201 deletions(-)
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index cc40551..53f62cf 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -320,18 +320,3 @@ static struct platform_driver ohci_hcd_at91_driver = {
},
};
-static int __init ohci_hcd_at91_init (void)
-{
- if (usb_disabled())
- return -ENODEV;
-
- return platform_driver_register(&ohci_hcd_at91_driver);
-}
-
-static void __exit ohci_hcd_at91_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_at91_driver);
-}
-
-module_init (ohci_hcd_at91_init);
-module_exit (ohci_hcd_at91_cleanup);
diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c
index e70b243..663a060 100644
--- a/drivers/usb/host/ohci-au1xxx.c
+++ b/drivers/usb/host/ohci-au1xxx.c
@@ -345,19 +345,3 @@ static struct platform_driver ohci_hcd_au1xxx_driver = {
},
};
-static int __init ohci_hcd_au1xxx_init (void)
-{
- pr_debug (DRIVER_INFO " (Au1xxx)");
- pr_debug ("block sizes: ed %d td %d\n",
- sizeof (struct ed), sizeof (struct td));
-
- return platform_driver_register(&ohci_hcd_au1xxx_driver);
-}
-
-static void __exit ohci_hcd_au1xxx_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_au1xxx_driver);
-}
-
-module_init (ohci_hcd_au1xxx_init);
-module_exit (ohci_hcd_au1xxx_cleanup);
diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c
index 43ae696..e9974c3 100644
--- a/drivers/usb/host/ohci-ep93xx.c
+++ b/drivers/usb/host/ohci-ep93xx.c
@@ -214,15 +214,3 @@ static struct platform_driver ohci_hcd_ep93xx_driver = {
},
};
-static int __init ohci_hcd_ep93xx_init(void)
-{
- return platform_driver_register(&ohci_hcd_ep93xx_driver);
-}
-
-static void __exit ohci_hcd_ep93xx_cleanup(void)
-{
- platform_driver_unregister(&ohci_hcd_ep93xx_driver);
-}
-
-module_init(ohci_hcd_ep93xx_init);
-module_exit(ohci_hcd_ep93xx_cleanup);
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index c1c1d87..9926b8f 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -855,63 +855,131 @@ MODULE_LICENSE ("GPL");
#ifdef CONFIG_PCI
#include "ohci-pci.c"
+#define PCI_DRIVER ohci_pci_driver
#endif
#ifdef CONFIG_SA1111
#include "ohci-sa1111.c"
+#define SA1111_DRIVER ohci_hcd_sa1111_driver
#endif
#ifdef CONFIG_ARCH_S3C2410
#include "ohci-s3c2410.c"
+#define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
#endif
#ifdef CONFIG_ARCH_OMAP
#include "ohci-omap.c"
+#define PLATFORM_DRIVER ohci_hcd_omap_driver
#endif
#ifdef CONFIG_ARCH_LH7A404
#include "ohci-lh7a404.c"
+#define PLATFORM_DRIVER ohci_hcd_lh7a404_driver
#endif
#ifdef CONFIG_PXA27x
#include "ohci-pxa27x.c"
+#define PLATFORM_DRIVER ohci_hcd_pxa27x_driver
#endif
#ifdef CONFIG_ARCH_EP93XX
#include "ohci-ep93xx.c"
+#define PLATFORM_DRIVER ohci_hcd_ep93xx_driver
#endif
#ifdef CONFIG_SOC_AU1X00
#include "ohci-au1xxx.c"
+#define PLATFORM_DRIVER ohci_hcd_au1xxx_driver
#endif
-#ifdef CONFIG_PNX8550
-#include "ohci-pnx8550.c"
-#endif
+#ifdef CONFIG_PNX8550
+#include "ohci-pnx8550.c"
+#define PLATFORM_DRIVER ohci_hcd_pnx8550_driver
+#endif
#ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
#include "ohci-ppc-soc.c"
+#define PLATFORM_DRIVER ohci_hcd_ppc_soc_driver
#endif
#ifdef CONFIG_ARCH_AT91
#include "ohci-at91.c"
+#define PLATFORM_DRIVER ohci_hcd_at91_driver
#endif
#ifdef CONFIG_ARCH_PNX4008
#include "ohci-pnx4008.c"
+#define PLATFORM_DRIVER usb_hcd_pnx4008_driver
#endif
-#if !(defined(CONFIG_PCI) \
- || defined(CONFIG_SA1111) \
- || defined(CONFIG_ARCH_S3C2410) \
- || defined(CONFIG_ARCH_OMAP) \
- || defined (CONFIG_ARCH_LH7A404) \
- || defined (CONFIG_PXA27x) \
- || defined (CONFIG_ARCH_EP93XX) \
- || defined (CONFIG_SOC_AU1X00) \
- || defined (CONFIG_USB_OHCI_HCD_PPC_SOC) \
- || defined (CONFIG_ARCH_AT91) \
- || defined (CONFIG_ARCH_PNX4008) \
- )
+
+#if !defined(PCI_DRIVER) && \
+ !defined(PLATFORM_DRIVER) && \
+ !defined(SA1111_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
+
+static int __init ohci_hcd_mod_init(void)
+{
+ int retval = 0;
+ int ls = 0;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ printk (KERN_DEBUG "%s: " DRIVER_INFO "\n", hcd_name);
+ pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
+ sizeof (struct ed), sizeof (struct td));
+
+#ifdef PLATFORM_DRIVER
+ retval = platform_driver_register(&PLATFORM_DRIVER);
+ if (retval < 0)
+ return retval;
+ ls++;
+#endif
+
+#ifdef SA1111_DRIVER
+ retval = sa1111_driver_register(&SA1111_DRIVER);
+ if (retval < 0)
+ goto error;
+ ls++;
+#endif
+
+#ifdef PCI_DRIVER
+ retval = pci_register_driver(&PCI_DRIVER);
+ if (retval < 0)
+ goto error;
+ ls++;
+#endif
+
+ return retval;
+
+ /* Error path */
+error:
+#ifdef PLATFORM_DRIVER
+ if (ls--)
+ platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+#ifdef SA1111_DRIVER
+ if (ls--)
+ sa1111_driver_unregister(&SA1111_DRIVER);
+#endif
+ return retval;
+}
+module_init(ohci_hcd_mod_init);
+
+static void __exit ohci_hcd_mod_exit(void)
+{
+#ifdef PCI_DRIVER
+ pci_unregister_driver(&PCI_DRIVER);
+#endif
+#ifdef SA1111_DRIVER
+ sa1111_driver_unregister(&SA1111_DRIVER);
+#endif
+#ifdef PLATFORM_DRIVER
+ platform_driver_unregister(&PLATFORM_DRIVER);
+#endif
+}
+module_exit(ohci_hcd_mod_exit);
+
diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c
index e9807cf..4a043ab 100644
--- a/drivers/usb/host/ohci-lh7a404.c
+++ b/drivers/usb/host/ohci-lh7a404.c
@@ -251,19 +251,3 @@ static struct platform_driver ohci_hcd_lh7a404_driver = {
},
};
-static int __init ohci_hcd_lh7a404_init (void)
-{
- pr_debug (DRIVER_INFO " (LH7A404)");
- pr_debug ("block sizes: ed %d td %d\n",
- sizeof (struct ed), sizeof (struct td));
-
- return platform_driver_register(&ohci_hcd_lh7a404_driver);
-}
-
-static void __exit ohci_hcd_lh7a404_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_lh7a404_driver);
-}
-
-module_init (ohci_hcd_lh7a404_init);
-module_exit (ohci_hcd_lh7a404_cleanup);
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 27be1f9..5cfa3d1 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -544,22 +544,3 @@ static struct platform_driver ohci_hcd_omap_driver = {
},
};
-static int __init ohci_hcd_omap_init (void)
-{
- printk (KERN_DEBUG "%s: " DRIVER_INFO " (OMAP)\n", hcd_name);
- if (usb_disabled())
- return -ENODEV;
-
- pr_debug("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
- sizeof (struct ed), sizeof (struct td));
-
- return platform_driver_register(&ohci_hcd_omap_driver);
-}
-
-static void __exit ohci_hcd_omap_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_omap_driver);
-}
-
-module_init (ohci_hcd_omap_init);
-module_exit (ohci_hcd_omap_cleanup);
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c
index 292daf0..b331ac4 100644
--- a/drivers/usb/host/ohci-pci.c
+++ b/drivers/usb/host/ohci-pci.c
@@ -311,23 +311,3 @@ static struct pci_driver ohci_pci_driver = {
.shutdown = usb_hcd_pci_shutdown,
};
-
-static int __init ohci_hcd_pci_init (void)
-{
- printk (KERN_DEBUG "%s: " DRIVER_INFO " (PCI)\n", hcd_name);
- if (usb_disabled())
- return -ENODEV;
-
- pr_debug ("%s: block sizes: ed %Zd td %Zd\n", hcd_name,
- sizeof (struct ed), sizeof (struct td));
- return pci_register_driver (&ohci_pci_driver);
-}
-module_init (ohci_hcd_pci_init);
-
-/*-------------------------------------------------------------------------*/
-
-static void __exit ohci_hcd_pci_cleanup (void)
-{
- pci_unregister_driver (&ohci_pci_driver);
-}
-module_exit (ohci_hcd_pci_cleanup);
diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c
index 3a8cbfb..893b172 100644
--- a/drivers/usb/host/ohci-pnx4008.c
+++ b/drivers/usb/host/ohci-pnx4008.c
@@ -465,15 +465,3 @@ static struct platform_driver usb_hcd_pnx4008_driver = {
.remove = usb_hcd_pnx4008_remove,
};
-static int __init usb_hcd_pnx4008_init(void)
-{
- return platform_driver_register(&usb_hcd_pnx4008_driver);
-}
-
-static void __exit usb_hcd_pnx4008_cleanup(void)
-{
- return platform_driver_unregister(&usb_hcd_pnx4008_driver);
-}
-
-module_init(usb_hcd_pnx4008_init);
-module_exit(usb_hcd_pnx4008_cleanup);
diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c
index 6922b91..de45eb0 100644
--- a/drivers/usb/host/ohci-pnx8550.c
+++ b/drivers/usb/host/ohci-pnx8550.c
@@ -240,19 +240,3 @@ static struct platform_driver ohci_hcd_pnx8550_driver = {
.remove = ohci_hcd_pnx8550_drv_remove,
};
-static int __init ohci_hcd_pnx8550_init (void)
-{
- pr_debug (DRIVER_INFO " (pnx8550)");
- pr_debug ("block sizes: ed %d td %d\n",
- sizeof (struct ed), sizeof (struct td));
-
- return platform_driver_register(&ohci_hcd_pnx8550_driver);
-}
-
-static void __exit ohci_hcd_pnx8550_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_pnx8550_driver);
-}
-
-module_init (ohci_hcd_pnx8550_init);
-module_exit (ohci_hcd_pnx8550_cleanup);
diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c
index c7ce8e6..1a2e177 100644
--- a/drivers/usb/host/ohci-ppc-soc.c
+++ b/drivers/usb/host/ohci-ppc-soc.c
@@ -208,19 +208,3 @@ static struct platform_driver ohci_hcd_ppc_soc_driver = {
},
};
-static int __init ohci_hcd_ppc_soc_init(void)
-{
- pr_debug(DRIVER_INFO " (PPC SOC)\n");
- pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
- sizeof(struct td));
-
- return platform_driver_register(&ohci_hcd_ppc_soc_driver);
-}
-
-static void __exit ohci_hcd_ppc_soc_cleanup(void)
-{
- platform_driver_unregister(&ohci_hcd_ppc_soc_driver);
-}
-
-module_init(ohci_hcd_ppc_soc_init);
-module_exit(ohci_hcd_ppc_soc_cleanup);
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3bbea84..f1563dc 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -369,19 +369,3 @@ static struct platform_driver ohci_hcd_pxa27x_driver = {
},
};
-static int __init ohci_hcd_pxa27x_init (void)
-{
- pr_debug (DRIVER_INFO " (pxa27x)");
- pr_debug ("block sizes: ed %d td %d\n",
- sizeof (struct ed), sizeof (struct td));
-
- return platform_driver_register(&ohci_hcd_pxa27x_driver);
-}
-
-static void __exit ohci_hcd_pxa27x_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_pxa27x_driver);
-}
-
-module_init (ohci_hcd_pxa27x_init);
-module_exit (ohci_hcd_pxa27x_cleanup);
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index b350d45..6829814 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -501,15 +501,3 @@ static struct platform_driver ohci_hcd_s3c2410_driver = {
},
};
-static int __init ohci_hcd_s3c2410_init (void)
-{
- return platform_driver_register(&ohci_hcd_s3c2410_driver);
-}
-
-static void __exit ohci_hcd_s3c2410_cleanup (void)
-{
- platform_driver_unregister(&ohci_hcd_s3c2410_driver);
-}
-
-module_init (ohci_hcd_s3c2410_init);
-module_exit (ohci_hcd_s3c2410_cleanup);
diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
index fe0090e..0f48f2d 100644
--- a/drivers/usb/host/ohci-sa1111.c
+++ b/drivers/usb/host/ohci-sa1111.c
@@ -269,19 +269,3 @@ static struct sa1111_driver ohci_hcd_sa1111_driver = {
.remove = ohci_hcd_sa1111_drv_remove,
};
-static int __init ohci_hcd_sa1111_init (void)
-{
- dbg (DRIVER_INFO " (SA-1111)");
- dbg ("block sizes: ed %d td %d",
- sizeof (struct ed), sizeof (struct td));
-
- return sa1111_driver_register(&ohci_hcd_sa1111_driver);
-}
-
-static void __exit ohci_hcd_sa1111_cleanup (void)
-{
- sa1111_driver_unregister(&ohci_hcd_sa1111_driver);
-}
-
-module_init (ohci_hcd_sa1111_init);
-module_exit (ohci_hcd_sa1111_cleanup);
--
1.4.4.2

View File

@ -1,35 +1,43 @@
From bc515daf6d0845b0ddb739f3ba822b66f84344a7 Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 12:55:37 +0100
Subject: [PATCH] Add USB/OHCI glue for OpenFirmware devices
From 944afcaa19737396ed514e3e845a3db2de9377f3 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Wed, 13 Dec 2006 21:03:30 +0100
Subject: [PATCH] [PATCH] ohci: Add support for OHCI controller on the of_platform bus
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
PPC embedded systems can have a ohci controller builtin. In the
new model, it will end up as a driver on the of_platform bus,
this patches takes care of them.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Acked-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
---
drivers/usb/host/Kconfig | 19 +++
drivers/usb/host/ohci-hcd.c | 6 +
drivers/usb/host/ohci-ppc-of.c | 285 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 310 insertions(+), 0 deletions(-)
drivers/usb/host/Kconfig | 23 ++++-
drivers/usb/host/ohci-hcd.c | 20 ++++
drivers/usb/host/ohci-ppc-of.c | 232 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 274 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index cf10cbc..f5ef6f5 100644
index faabce8..c49715d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -106,6 +106,25 @@ config USB_OHCI_HCD_PPC_SOC
@@ -107,9 +107,30 @@ config USB_OHCI_HCD_PPC_SOC
Enables support for the USB controller on the MPC52xx or
STB03xxx processor chip. If unsure, say Y.
+config USB_OHCI_HCD_PPC_OF
+ bool "OHCI support for PPC USB controller for OpenFirmware platform"
+ bool "OHCI support for PPC USB controller on OF platform bus"
+ depends on USB_OHCI_HCD && PPC_OF
+ default y
+ ---help---
+ Enables support for the USB controller PowerPC OpenFirmware platform
+ Enables support for the USB controller PowerPC present on the
+ OpenFirmware platform bus.
+
+config USB_OHCI_HCD_PPC_OF_BE
+ bool "Support big endian HC"
+ depends on USB_OHCI_HCD_PPC_OF
+ default y
+ select USB_OHCI_BIG_ENDIAN
+ select USB_OHCI_BIG_ENDIAN_DESC
+ select USB_OHCI_BIG_ENDIAN_MMIO
+
+config USB_OHCI_HCD_PPC_OF_LE
+ bool "Support little endian HC"
@ -39,156 +47,91 @@ index cf10cbc..f5ef6f5 100644
+
config USB_OHCI_HCD_PCI
bool "OHCI support for PCI-bus USB controllers"
depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
- depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx)
+ depends on USB_OHCI_HCD && PCI && (STB03xxx || PPC_MPC52xx || USB_OHCI_HCD_PPC_OF)
default y
select USB_OHCI_LITTLE_ENDIAN
---help---
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 9be6b30..04413b6 100644
index 9926b8f..c6ae1ff 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -930,6 +930,10 @@ #ifdef CONFIG_USB_OHCI_HCD_PPC_SOC
#include "ohci-ppc-soc.c"
@@ -914,8 +914,14 @@ MODULE_LICENSE ("GPL");
#endif
+#ifdef CONFIG_USB_OHCI_HCD_PPC_OF
+#include "ohci-ppc-of.c"
+#define OF_PLATFORM_DRIVER ohci_hcd_ppc_of_driver
+#endif
+
#if defined(CONFIG_ARCH_AT91RM9200) || defined(CONFIG_ARCH_AT91SAM9261)
#include "ohci-at91.c"
#endif
@@ -950,6 +954,8 @@ #if !(defined(CONFIG_PCI) \
|| defined (CONFIG_ARCH_AT91RM9200) \
|| defined (CONFIG_ARCH_AT91SAM9261) \
|| defined (CONFIG_ARCH_PNX4008) \
+ || defined (CONFIG_USB_OHCI_HCD_PPC_OF_LE) \
+ || defined (CONFIG_USB_OHCI_HCD_PPC_OF_BE) \
)
#if !defined(PCI_DRIVER) && \
!defined(PLATFORM_DRIVER) && \
+ !defined(OF_PLATFORM_DRIVER) && \
!defined(SA1111_DRIVER)
#error "missing bus glue for ohci-hcd"
#endif
@@ -939,6 +945,13 @@ static int __init ohci_hcd_mod_init(void)
ls++;
#endif
+#ifdef OF_PLATFORM_DRIVER
+ retval = of_register_platform_driver(&OF_PLATFORM_DRIVER);
+ if (retval < 0)
+ goto error;
+ ls++;
+#endif
+
#ifdef SA1111_DRIVER
retval = sa1111_driver_register(&SA1111_DRIVER);
if (retval < 0)
@@ -961,6 +974,10 @@ error:
if (ls--)
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
+#ifdef OF_PLATFORM_DRIVER
+ if (ls--)
+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
#ifdef SA1111_DRIVER
if (ls--)
sa1111_driver_unregister(&SA1111_DRIVER);
@@ -977,6 +994,9 @@ static void __exit ohci_hcd_mod_exit(void)
#ifdef SA1111_DRIVER
sa1111_driver_unregister(&SA1111_DRIVER);
#endif
+#ifdef OF_PLATFORM_DRIVER
+ of_unregister_platform_driver(&OF_PLATFORM_DRIVER);
+#endif
#ifdef PLATFORM_DRIVER
platform_driver_unregister(&PLATFORM_DRIVER);
#endif
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
new file mode 100644
index 0000000..30ce520
index 0000000..84b555b
--- /dev/null
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -0,0 +1,285 @@
@@ -0,0 +1,232 @@
+/*
+ * OHCI HCD (Host Controller Driver) for USB.
+ *
+ * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at>
+ * (C) Copyright 2000-2002 David Brownell <dbrownell@users.sourceforge.net>
+ * (C) Copyright 2002 Hewlett-Packard Company
+ * (C) Copyright 2003-2005 MontaVista Software Inc.
+ * (C) Copyright 2006 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * Probe and init OHCI Big endian HC from OpenFirmware device tree
+ * Tested on Efika 5k2
+ * Bus glue for OHCI HC on the of_platform bus
+ *
+ * Modified by Dale Farnsworth <dale@farnsworth.org> from ohci-sa1111.c
+ * Modified for of_platform bus from ohci-sa1111.c
+ *
+ * This file is licenced under the GPL.
+ */
+
+#include <linux/signal.h>
+
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <asm/prom.h>
+
+/* configure so an HC device and id are always provided */
+/* always called with process context; sleeping is OK */
+
+/*
+ * usb_hcd_ppc_of_probe - initialize On-Chip HCDs
+ * Context: !in_interrupt()
+ *
+ * Allocates basic resources for this USB host controller.
+ *
+ * Store this function in the HCD's struct pci_driver as probe().
+ */
+static int usb_hcd_ppc_of_probe(const struct hc_driver *driver,
+ struct of_device *dev, int is_bigendian)
+{
+ int retval;
+ struct usb_hcd *hcd;
+ struct ohci_hcd *ohci;
+ struct resource res;
+ int irq;
+ int ret;
+
+ pr_debug("initializing PPC-OF USB Controller\n");
+
+ if ((ret = of_address_to_resource(dev->node, 0, &res)) != 0)
+ return ret;
+
+ hcd = usb_create_hcd(driver, &dev->dev, "PPC-OF USB");
+ if (!hcd)
+ return -ENOMEM;
+
+ hcd->rsrc_start = res.start;
+ hcd->rsrc_len = res.end - res.start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ pr_debug(__FILE__ ": request_mem_region failed\n");
+ retval = -EBUSY;
+ goto err1;
+ }
+
+ irq = irq_of_parse_and_map(dev->node, 0);
+ if (irq == NO_IRQ) {
+ retval = -EBUSY;
+ goto err2;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ pr_debug(__FILE__ ": ioremap failed\n");
+ retval = -ENOMEM;
+ goto err2;
+ }
+
+ ohci = hcd_to_ohci(hcd);
+ if (is_bigendian)
+ ohci->flags |= OHCI_BIG_ENDIAN;
+
+ ohci_hcd_init(ohci);
+
+ retval = usb_add_hcd(hcd, irq, 0);
+ if (retval == 0)
+ return retval;
+
+ pr_debug("Removing PPC-OF USB Controller\n");
+
+ iounmap(hcd->regs);
+ err2:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ err1:
+ usb_put_hcd(hcd);
+ return retval;
+}
+
+
+/* may be called without controller electrically present */
+/* may be called with controller, bus, and devices active */
+
+/*
+ * usb_hcd_ppc_of_remove - shutdown processing for On-Chip HCDs
+ * @pdev: USB Host Controller being removed
+ * Context: !in_interrupt()
+ *
+ * Reverses the effect of usb_hcd_ppc_of_probe().
+ * It is always called from a thread
+ * context, normally "rmmod", "apmd", or something similar.
+ *
+ */
+static void usb_hcd_ppc_of_remove(struct usb_hcd *hcd,
+ struct of_device *op)
+{
+ usb_remove_hcd(hcd);
+
+ pr_debug("stopping PPC-OF USB Controller\n");
+
+ iounmap(hcd->regs);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+ usb_put_hcd(hcd);
+}
+
+static int __devinit
+ohci_ppc_of_start(struct usb_hcd *hcd)
@ -210,6 +153,7 @@ index 0000000..30ce520
+
+static const struct hc_driver ohci_ppc_of_hc_driver = {
+ .description = hcd_name,
+ .product_desc = "OF OHCI",
+ .hcd_priv_size = sizeof(struct ohci_hcd),
+
+ /*
@ -251,17 +195,98 @@ index 0000000..30ce520
+};
+
+
+static int __devinit
+ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct device_node *dn = op->node;
+ struct usb_hcd *hcd;
+ struct ohci_hcd *ohci;
+ struct resource res;
+ int irq;
+
+static int ohci_hcd_ppc_of_drv_remove(struct of_device *op)
+ int rv;
+ int is_bigendian;
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ is_bigendian =
+ device_is_compatible(dn, "ohci-bigendian") ||
+ device_is_compatible(dn, "ohci-be");;
+
+ dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
+
+ rv = of_address_to_resource(dn, 0, &res);
+ if (rv)
+ return rv;
+
+ hcd = usb_create_hcd(&ohci_ppc_of_hc_driver, &op->dev, "PPC-OF USB");
+ if (!hcd)
+ return -ENOMEM;
+
+ hcd->rsrc_start = res.start;
+ hcd->rsrc_len = res.end - res.start + 1;
+
+ if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) {
+ printk(KERN_ERR __FILE__ ": request_mem_region failed\n");
+ rv = -EBUSY;
+ goto err_rmr;
+ }
+
+ irq = irq_of_parse_and_map(dn, 0);
+ if (irq == NO_IRQ) {
+ printk(KERN_ERR __FILE__ ": irq_of_parse_and_map failed\n");
+ rv = -EBUSY;
+ goto err_irq;
+ }
+
+ hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+ if (!hcd->regs) {
+ printk(KERN_ERR __FILE__ ": ioremap failed\n");
+ rv = -ENOMEM;
+ goto err_ioremap;
+ }
+
+ ohci = hcd_to_ohci(hcd);
+ if (is_bigendian)
+ ohci->flags |= OHCI_QUIRK_BE_MMIO | OHCI_QUIRK_BE_DESC;
+
+ ohci_hcd_init(ohci);
+
+ rv = usb_add_hcd(hcd, irq, 0);
+ if (rv == 0)
+ return 0;
+
+ iounmap(hcd->regs);
+err_ioremap:
+ irq_dispose_mapping(irq);
+err_irq:
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+err_rmr:
+ usb_put_hcd(hcd);
+
+ return rv;
+}
+
+static int ohci_hcd_ppc_of_remove(struct of_device *op)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+ dev_set_drvdata(&op->dev, NULL);
+
+ usb_hcd_ppc_of_remove(hcd, op);
+ dev_dbg(&op->dev, "stopping PPC-OF USB Controller\n");
+
+ usb_remove_hcd(hcd);
+
+ iounmap(hcd->regs);
+ irq_dispose_mapping(hcd->irq);
+ release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
+
+ usb_put_hcd(hcd);
+
+ return 0;
+}
+
+static int ohci_hcd_ppc_of_drv_shutdown(struct of_device *op)
+static int ohci_hcd_ppc_of_shutdown(struct of_device *op)
+{
+ struct usb_hcd *hcd = dev_get_drvdata(&op->dev);
+
@ -271,9 +296,6 @@ index 0000000..30ce520
+ return 0;
+}
+
+/*
+ *
+*/
+
+static struct of_device_id ohci_hcd_ppc_of_match[] = {
+#ifdef CONFIG_USB_OHCI_HCD_PPC_OF_BE
@ -298,37 +320,21 @@ index 0000000..30ce520
+#endif
+ {},
+};
+MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
+
+static int __devinit
+ohci_hcd_ppc_of_drv_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct device_node *dev;
+ int ret;
+ int is_bigendian;
+#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
+ !defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
+#error "No endianess selected for ppc-of-ohci"
+#endif
+
+ if (usb_disabled())
+ return -ENODEV;
+
+ dev = op->node;
+ is_bigendian = 0;
+
+ if ( device_is_compatible(dev, "ohci-bigendian") )
+ is_bigendian = 1;
+
+ if ( device_is_compatible(dev, "ohci-be") )
+ is_bigendian = 1;
+
+ ret = usb_hcd_ppc_of_probe(&ohci_ppc_of_hc_driver, op, is_bigendian);
+ return ret;
+}
+
+static struct of_platform_driver ohci_hcd_ppc_of_driver = {
+ .name = "ppc-of-ohci",
+ .match_table = ohci_hcd_ppc_of_match,
+ .probe = ohci_hcd_ppc_of_drv_probe,
+ .remove = ohci_hcd_ppc_of_drv_remove,
+ .shutdown = ohci_hcd_ppc_of_drv_shutdown,
+#ifdef CONFIG_PM
+ .probe = ohci_hcd_ppc_of_probe,
+ .remove = ohci_hcd_ppc_of_remove,
+ .shutdown = ohci_hcd_ppc_of_shutdown,
+#ifdef CONFIG_PM
+ /*.suspend = ohci_hcd_ppc_soc_drv_suspend,*/
+ /*.resume = ohci_hcd_ppc_soc_drv_resume,*/
+#endif
@ -338,23 +344,6 @@ index 0000000..30ce520
+ },
+};
+
+static int __init ohci_hcd_ppc_of_init(void)
+{
+ pr_debug(DRIVER_INFO " (PPC OF)\n");
+ pr_debug("block sizes: ed %d td %d\n", sizeof(struct ed),
+ sizeof(struct td));
+
+ return of_register_platform_driver(&ohci_hcd_ppc_of_driver);
+}
+
+static void __exit ohci_hcd_ppc_of_cleanup(void)
+{
+ of_unregister_platform_driver(&ohci_hcd_ppc_of_driver);
+}
+
+module_init(ohci_hcd_ppc_of_init);
+module_exit(ohci_hcd_ppc_of_cleanup);
+
--
1.4.3.2
1.4.4.2

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +1,24 @@
From bb6dea9b9a251e42efcec030af2d5272d5d5714a Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:01:30 +0100
Subject: [PATCH] Add MPC5200 CPU/PIO driver using libata
From 83ebd6314e55f9baf2c4e795397346b338274ef5 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Fri, 8 Dec 2006 00:08:14 +0100
Subject: [PATCH] [PATCH] libata: Add support for the MPC52xx ATA controller
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
This patch adds initial libata support for the Freescale
MPC5200 integrated IDE controller.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
---
drivers/ata/Kconfig | 9 +
drivers/ata/Makefile | 1 +
drivers/ata/pata_mpc52xx.c | 510 ++++++++++++++++++++++++++++++++++++++++++++
drivers/ata/pata_mpc52xx.h | 107 +++++++++
4 files changed, 627 insertions(+), 0 deletions(-)
drivers/ata/pata_mpc52xx.c | 563 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 573 insertions(+), 0 deletions(-)
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index 03f6338..be01ddf 100644
index b34e0a9..fa1d327 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -328,6 +328,15 @@ config PATA_TRIFLEX
@@ -337,6 +337,15 @@ config PATA_MARVELL
If unsure, say N.
@ -32,23 +35,23 @@ index 03f6338..be01ddf 100644
tristate "Intel PATA MPIIX support"
depends on PCI
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 72243a6..e3a741c 100644
index bc3d81a..3081e1f 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netce
@@ -38,6 +38,7 @@ obj-$(CONFIG_PATA_NETCELL) += pata_netcell.o
obj-$(CONFIG_PATA_NS87410) += pata_ns87410.o
obj-$(CONFIG_PATA_OPTI) += pata_opti.o
obj-$(CONFIG_PATA_OPTIDMA) += pata_optidma.o
+obj-$(CONFIG_PATA_MPC52xx) += pata_mpc52xx.o
obj-$(CONFIG_PATA_MARVELL) += pata_marvell.o
obj-$(CONFIG_PATA_MPIIX) += pata_mpiix.o
obj-$(CONFIG_PATA_OLDPIIX) += pata_oldpiix.o
obj-$(CONFIG_PATA_PCMCIA) += pata_pcmcia.o
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
new file mode 100644
index 0000000..c75d4c9
index 0000000..8b7019a
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.c
@@ -0,0 +1,510 @@
@@ -0,0 +1,563 @@
+/*
+ * drivers/ata/pata_mpc52xx.c
+ *
@ -65,15 +68,15 @@ index 0000000..c75d4c9
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/libata.h>
+
+#include <asm/io.h>
+#include <asm/types.h>
+#include <asm/prom.h>
+#include <asm/of_platform.h>
+#include <asm/mpc52xx.h>
+
+#include "pata_mpc52xx.h"
+
+
+#define DRV_NAME "mpc52xx_ata"
+#define DRV_VERSION "0.1.0"
@ -106,38 +109,91 @@ index 0000000..c75d4c9
+#define CALC_CLKCYC(c,v) ((((v)+(c)-1)/(c)))
+
+
+/* Bit definitions inside the registers */
+#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+ /* Host interface registers */
+ u32 config; /* ATA + 0x00 Host configuration */
+ u32 host_status; /* ATA + 0x04 Host controller status */
+ u32 pio1; /* ATA + 0x08 PIO Timing 1 */
+ u32 pio2; /* ATA + 0x0c PIO Timing 2 */
+ u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
+ u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
+ u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
+ u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
+ u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
+ u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
+ u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
+ u32 share_cnt; /* ATA + 0x2c ATA share counter */
+ u32 reserved0[3];
+
+ /* FIFO registers */
+ u32 fifo_data; /* ATA + 0x3c */
+ u8 fifo_status_frame; /* ATA + 0x40 */
+ u8 fifo_status; /* ATA + 0x41 */
+ u16 reserved7[1];
+ u8 fifo_control; /* ATA + 0x44 */
+ u8 reserved8[5];
+ u16 fifo_alarm; /* ATA + 0x4a */
+ u16 reserved9;
+ u16 fifo_rdp; /* ATA + 0x4e */
+ u16 reserved10;
+ u16 fifo_wrp; /* ATA + 0x52 */
+ u16 reserved11;
+ u16 fifo_lfrdp; /* ATA + 0x56 */
+ u16 reserved12;
+ u16 fifo_lfwrp; /* ATA + 0x5a */
+
+ /* Drive TaskFile registers */
+ u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
+ u8 reserved13[3];
+ u16 tf_data; /* ATA + 0x60 TASKFILE Data */
+ u16 reserved14;
+ u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
+ u8 reserved15[3];
+ u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
+ u8 reserved16[3];
+ u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */
+ u8 reserved17[3];
+ u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */
+ u8 reserved18[3];
+ u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */
+ u8 reserved19[3];
+ u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */
+ u8 reserved20[3];
+ u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */
+ u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */
+ u8 reserved21[2];
+};
+
+
+/* ======================================================================== */
+/* Aux fns */
+/* ======================================================================== */
+
+
+/* OF device tree */
+
+static unsigned int
+mpc52xx_find_ipb_freq(struct device_node *on)
+{
+ struct device_node *onp;
+ const unsigned int *p_ipb_freq = NULL;
+
+ of_node_get(on);
+ while (on) {
+ p_ipb_freq = get_property(on, "bus-frequency", NULL);
+
+ if (p_ipb_freq)
+ break;
+
+ onp = of_get_parent(on);
+ of_node_put(on);
+ on = onp;
+ }
+
+ if (on)
+ of_node_put(on);
+
+ return p_ipb_freq ? *p_ipb_freq : 0;
+}
+
+
+/* MPC52xx low level hw control */
+
+static int
@ -559,119 +615,6 @@ index 0000000..c75d4c9
+MODULE_DEVICE_TABLE(of, mpc52xx_ata_of_match);
+MODULE_VERSION(DRV_VERSION);
+
diff --git a/drivers/ata/pata_mpc52xx.h b/drivers/ata/pata_mpc52xx.h
new file mode 100644
index 0000000..2430ae2
--- /dev/null
+++ b/drivers/ata/pata_mpc52xx.h
@@ -0,0 +1,107 @@
+/*
+ * drivers/ata/pata_mpc52xx.h
+ *
+ * Definitions for the Freescale MPC52xx on-chip IDE interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 Mipsys - Benjamin Herrenschmidt
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __PATA_MPC52xx_H__
+#define __PATA_MPC52xx_H__
+
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/ide.h>
+#include <asm/types.h>
+#include <asm/io.h>
+
+
+
+/* Bit definitions inside the registers */
+
+#define MPC52xx_ATA_HOSTCONF_SMR 0x80000000UL /* State machine reset */
+#define MPC52xx_ATA_HOSTCONF_FR 0x40000000UL /* FIFO Reset */
+#define MPC52xx_ATA_HOSTCONF_IE 0x02000000UL /* Enable interrupt in PIO */
+#define MPC52xx_ATA_HOSTCONF_IORDY 0x01000000UL /* Drive supports IORDY protocol */
+
+#define MPC52xx_ATA_HOSTSTAT_TIP 0x80000000UL /* Transaction in progress */
+#define MPC52xx_ATA_HOSTSTAT_UREP 0x40000000UL /* UDMA Read Extended Pause */
+#define MPC52xx_ATA_HOSTSTAT_RERR 0x02000000UL /* Read Error */
+#define MPC52xx_ATA_HOSTSTAT_WERR 0x01000000UL /* Write Error */
+
+#define MPC52xx_ATA_FIFOSTAT_EMPTY 0x01 /* FIFO Empty */
+
+#define MPC52xx_ATA_DMAMODE_WRITE 0x01 /* Write DMA */
+#define MPC52xx_ATA_DMAMODE_READ 0x02 /* Read DMA */
+#define MPC52xx_ATA_DMAMODE_UDMA 0x04 /* UDMA enabled */
+#define MPC52xx_ATA_DMAMODE_IE 0x08 /* Enable drive interrupt to CPU in DMA mode */
+#define MPC52xx_ATA_DMAMODE_FE 0x10 /* FIFO Flush enable in Rx mode */
+#define MPC52xx_ATA_DMAMODE_FR 0x20 /* FIFO Reset */
+#define MPC52xx_ATA_DMAMODE_HUT 0x40 /* Host UDMA burst terminate */
+
+
+/* Structure of the hardware registers */
+struct mpc52xx_ata {
+
+ /* Host interface registers */
+ u32 config; /* ATA + 0x00 Host configuration */
+ u32 host_status; /* ATA + 0x04 Host controller status */
+ u32 pio1; /* ATA + 0x08 PIO Timing 1 */
+ u32 pio2; /* ATA + 0x0c PIO Timing 2 */
+ u32 mdma1; /* ATA + 0x10 MDMA Timing 1 */
+ u32 mdma2; /* ATA + 0x14 MDMA Timing 2 */
+ u32 udma1; /* ATA + 0x18 UDMA Timing 1 */
+ u32 udma2; /* ATA + 0x1c UDMA Timing 2 */
+ u32 udma3; /* ATA + 0x20 UDMA Timing 3 */
+ u32 udma4; /* ATA + 0x24 UDMA Timing 4 */
+ u32 udma5; /* ATA + 0x28 UDMA Timing 5 */
+ u32 share_cnt; /* ATA + 0x2c ATA share counter */
+ u32 reserved0[3];
+
+ /* FIFO registers */
+ u32 fifo_data; /* ATA + 0x3c */
+ u8 fifo_status_frame; /* ATA + 0x40 */
+ u8 fifo_status; /* ATA + 0x41 */
+ u16 reserved7[1];
+ u8 fifo_control; /* ATA + 0x44 */
+ u8 reserved8[5];
+ u16 fifo_alarm; /* ATA + 0x4a */
+ u16 reserved9;
+ u16 fifo_rdp; /* ATA + 0x4e */
+ u16 reserved10;
+ u16 fifo_wrp; /* ATA + 0x52 */
+ u16 reserved11;
+ u16 fifo_lfrdp; /* ATA + 0x56 */
+ u16 reserved12;
+ u16 fifo_lfwrp; /* ATA + 0x5a */
+
+ /* Drive TaskFile registers */
+ u8 tf_control; /* ATA + 0x5c TASKFILE Control/Alt Status */
+ u8 reserved13[3];
+ u16 tf_data; /* ATA + 0x60 TASKFILE Data */
+ u16 reserved14;
+ u8 tf_features; /* ATA + 0x64 TASKFILE Features/Error */
+ u8 reserved15[3];
+ u8 tf_sec_count; /* ATA + 0x68 TASKFILE Sector Count */
+ u8 reserved16[3];
+ u8 tf_sec_num; /* ATA + 0x6c TASKFILE Sector Number */
+ u8 reserved17[3];
+ u8 tf_cyl_low; /* ATA + 0x70 TASKFILE Cylinder Low */
+ u8 reserved18[3];
+ u8 tf_cyl_high; /* ATA + 0x74 TASKFILE Cylinder High */
+ u8 reserved19[3];
+ u8 tf_dev_head; /* ATA + 0x78 TASKFILE Device/Head */
+ u8 reserved20[3];
+ u8 tf_command; /* ATA + 0x7c TASKFILE Command/Status */
+ u8 dma_mode; /* ATA + 0x7d ATA Host DMA Mode configuration */
+ u8 reserved21[2];
+};
+
+#endif /* __PATA_MPC52xx_H__ */
+
--
1.4.3.2
1.4.4.2

View File

@ -1,38 +0,0 @@
From 473274f1f615316cf5828caa47704f4d2f9ad1be Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:34:18 +0100
Subject: [PATCH] Filter out efika
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
arch/powerpc/platforms/chrp/setup.c | 9 +++++++++
1 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 49b8dab..1337da8 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -580,11 +580,20 @@ static int __init chrp_probe(void)
{
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
"device_type", NULL);
+
+ char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "model", NULL);
if (dtype == NULL)
return 0;
if (strcmp(dtype, "chrp"))
return 0;
+ /*
+ * Filter out efika because it has its own platform
+ */
+ if (model && (strcmp(model, "EFIKA5K2") == 0) )
+ return 0;
+
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;
--
1.4.3.2

View File

@ -0,0 +1,38 @@
From 947dc060772ceb8b33a35bd2ded245908fa9442f Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 22:16:05 +0100
Subject: [PATCH] [PATCH] ohci: Whitespace and typo fix in ohci-ppc-of.c
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
drivers/usb/host/ohci-ppc-of.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index 84b555b..08e237c 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -96,9 +96,9 @@ ohci_hcd_ppc_of_probe(struct of_device *op, const struct of_device_id *match)
if (usb_disabled())
return -ENODEV;
- is_bigendian =
+ is_bigendian =
device_is_compatible(dn, "ohci-bigendian") ||
- device_is_compatible(dn, "ohci-be");;
+ device_is_compatible(dn, "ohci-be");
dev_dbg(&op->dev, "initializing PPC-OF USB Controller\n");
@@ -206,7 +206,7 @@ static struct of_device_id ohci_hcd_ppc_of_match[] = {
#endif
{},
};
-MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
+MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
#if !defined(CONFIG_USB_OHCI_HCD_PPC_OF_BE) && \
!defined(CONFIG_USB_OHCI_HCD_PPC_OF_LE)
--
1.4.4.2

View File

@ -1,900 +0,0 @@
From 2842fd40de284f328016997ba40d7b83823510c5 Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:49:57 +0100
Subject: [PATCH] Backport of_platform
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
arch/powerpc/kernel/Makefile | 2 +-
arch/powerpc/kernel/of_device.c | 172 +++------------
arch/powerpc/kernel/of_platform.c | 374 +++++++++++++++++++++++++++++++
arch/powerpc/platforms/powermac/setup.c | 1 +
drivers/macintosh/smu.c | 3 +-
drivers/macintosh/therm_adt746x.c | 2 +-
drivers/macintosh/therm_pm72.c | 5 +-
drivers/macintosh/therm_windtunnel.c | 7 +-
drivers/video/platinumfb.c | 5 +-
include/asm-powerpc/of_device.h | 34 +---
include/asm-powerpc/of_platform.h | 60 +++++
11 files changed, 478 insertions(+), 187 deletions(-)
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 7af23c4..6d9476f 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_PPC64) += setup_64.o binfm
obj-$(CONFIG_PPC64) += vdso64/
obj-$(CONFIG_ALTIVEC) += vecemu.o vector.o
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
-obj-$(CONFIG_PPC_OF) += of_device.o prom_parse.o
+obj-$(CONFIG_PPC_OF) += of_device.o of_platform.o prom_parse.o
procfs-$(CONFIG_PPC64) := proc_ppc64.o
obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64) := rtas_pci.o
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index 397c83e..5c65398 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -9,30 +9,26 @@ #include <asm/errno.h>
#include <asm/of_device.h>
/**
- * of_match_device - Tell if an of_device structure has a matching
- * of_match structure
+ * of_match_node - Tell if an device_node has a matching of_match structure
* @ids: array of of device match structures to search in
- * @dev: the of device structure to match against
+ * @node: the of device structure to match against
*
- * Used by a driver to check whether an of_device present in the
- * system is in its list of supported devices.
+ * Low level utility function used by device matching.
*/
-const struct of_device_id *of_match_device(const struct of_device_id *matches,
- const struct of_device *dev)
+const struct of_device_id *of_match_node(const struct of_device_id *matches,
+ const struct device_node *node)
{
- if (!dev->node)
- return NULL;
while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
int match = 1;
if (matches->name[0])
- match &= dev->node->name
- && !strcmp(matches->name, dev->node->name);
+ match &= node->name
+ && !strcmp(matches->name, node->name);
if (matches->type[0])
- match &= dev->node->type
- && !strcmp(matches->type, dev->node->type);
+ match &= node->type
+ && !strcmp(matches->type, node->type);
if (matches->compatible[0])
- match &= device_is_compatible(dev->node,
- matches->compatible);
+ match &= device_is_compatible(node,
+ matches->compatible);
if (match)
return matches;
matches++;
@@ -40,16 +36,21 @@ const struct of_device_id *of_match_devi
return NULL;
}
-static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+/**
+ * of_match_device - Tell if an of_device structure has a matching
+ * of_match structure
+ * @ids: array of of device match structures to search in
+ * @dev: the of device structure to match against
+ *
+ * Used by a driver to check whether an of_device present in the
+ * system is in its list of supported devices.
+ */
+const struct of_device_id *of_match_device(const struct of_device_id *matches,
+ const struct of_device *dev)
{
- struct of_device * of_dev = to_of_device(dev);
- struct of_platform_driver * of_drv = to_of_platform_driver(drv);
- const struct of_device_id * matches = of_drv->match_table;
-
- if (!matches)
- return 0;
-
- return of_match_device(matches, of_dev) != NULL;
+ if (!dev->node)
+ return NULL;
+ return of_match_node(matches, dev->node);
}
struct of_device *of_dev_get(struct of_device *dev)
@@ -71,96 +72,8 @@ void of_dev_put(struct of_device *dev)
put_device(&dev->dev);
}
-
-static int of_device_probe(struct device *dev)
-{
- int error = -ENODEV;
- struct of_platform_driver *drv;
- struct of_device *of_dev;
- const struct of_device_id *match;
-
- drv = to_of_platform_driver(dev->driver);
- of_dev = to_of_device(dev);
-
- if (!drv->probe)
- return error;
-
- of_dev_get(of_dev);
-
- match = of_match_device(drv->match_table, of_dev);
- if (match)
- error = drv->probe(of_dev, match);
- if (error)
- of_dev_put(of_dev);
-
- return error;
-}
-
-static int of_device_remove(struct device *dev)
-{
- struct of_device * of_dev = to_of_device(dev);
- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
-
- if (dev->driver && drv->remove)
- drv->remove(of_dev);
- return 0;
-}
-
-static int of_device_suspend(struct device *dev, pm_message_t state)
-{
- struct of_device * of_dev = to_of_device(dev);
- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
- int error = 0;
-
- if (dev->driver && drv->suspend)
- error = drv->suspend(of_dev, state);
- return error;
-}
-
-static int of_device_resume(struct device * dev)
-{
- struct of_device * of_dev = to_of_device(dev);
- struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
- int error = 0;
-
- if (dev->driver && drv->resume)
- error = drv->resume(of_dev);
- return error;
-}
-
-struct bus_type of_platform_bus_type = {
- .name = "of_platform",
- .match = of_platform_bus_match,
- .probe = of_device_probe,
- .remove = of_device_remove,
- .suspend = of_device_suspend,
- .resume = of_device_resume,
-};
-
-static int __init of_bus_driver_init(void)
-{
- return bus_register(&of_platform_bus_type);
-}
-
-postcore_initcall(of_bus_driver_init);
-
-int of_register_driver(struct of_platform_driver *drv)
-{
- /* initialize common driver fields */
- drv->driver.name = drv->name;
- drv->driver.bus = &of_platform_bus_type;
-
- /* register with core */
- return driver_register(&drv->driver);
-}
-
-void of_unregister_driver(struct of_platform_driver *drv)
-{
- driver_unregister(&drv->driver);
-}
-
-
-static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t dev_show_devspec(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
struct of_device *ofdev;
@@ -208,41 +121,10 @@ void of_device_unregister(struct of_devi
device_unregister(&ofdev->dev);
}
-struct of_device* of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent)
-{
- struct of_device *dev;
-
- dev = kmalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev)
- return NULL;
- memset(dev, 0, sizeof(*dev));
-
- dev->node = of_node_get(np);
- dev->dma_mask = 0xffffffffUL;
- dev->dev.dma_mask = &dev->dma_mask;
- dev->dev.parent = parent;
- dev->dev.bus = &of_platform_bus_type;
- dev->dev.release = of_release_dev;
-
- strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
-
- if (of_device_register(dev) != 0) {
- kfree(dev);
- return NULL;
- }
-
- return dev;
-}
EXPORT_SYMBOL(of_match_device);
-EXPORT_SYMBOL(of_platform_bus_type);
-EXPORT_SYMBOL(of_register_driver);
-EXPORT_SYMBOL(of_unregister_driver);
EXPORT_SYMBOL(of_device_register);
EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
-EXPORT_SYMBOL(of_platform_device_create);
EXPORT_SYMBOL(of_release_dev);
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
new file mode 100644
index 0000000..41c71bc
--- /dev/null
+++ b/arch/powerpc/kernel/of_platform.c
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * 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.
+ *
+ */
+
+#undef DEBUG
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/slab.h>
+
+#include <asm/errno.h>
+#ifdef CONFIG_PPC_DCR
+#include <asm/dcr.h>
+#endif
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+
+
+/*
+ * The list of OF IDs below is used for matching bus types in the
+ * system whose devices are to be exposed as of_platform_devices.
+ *
+ * This is the default list valid for most platforms. This file provides
+ * functions who can take an explicit list if necessary though
+ *
+ * The search is always performed recursively looking for children of
+ * the provided device_node and recursively if such a children matches
+ * a bus type in the list
+ */
+
+static struct of_device_id of_default_bus_ids[] = {
+ { .type = "soc", },
+ { .compatible = "soc", },
+ { .type = "spider", },
+ { .type = "axon", },
+ { .type = "plb5", },
+ { .type = "plb4", },
+ { .type = "opb", },
+ {},
+};
+
+/*
+ *
+ * OF platform device type definition & base infrastructure
+ *
+ */
+
+static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * of_drv = to_of_platform_driver(drv);
+ const struct of_device_id * matches = of_drv->match_table;
+
+ if (!matches)
+ return 0;
+
+ return of_match_device(matches, of_dev) != NULL;
+}
+
+static int of_platform_device_probe(struct device *dev)
+{
+ int error = -ENODEV;
+ struct of_platform_driver *drv;
+ struct of_device *of_dev;
+ const struct of_device_id *match;
+
+ drv = to_of_platform_driver(dev->driver);
+ of_dev = to_of_device(dev);
+
+ if (!drv->probe)
+ return error;
+
+ of_dev_get(of_dev);
+
+ match = of_match_device(drv->match_table, of_dev);
+ if (match)
+ error = drv->probe(of_dev, match);
+ if (error)
+ of_dev_put(of_dev);
+
+ return error;
+}
+
+static int of_platform_device_remove(struct device *dev)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+
+ if (dev->driver && drv->remove)
+ drv->remove(of_dev);
+ return 0;
+}
+
+static int of_platform_device_suspend(struct device *dev, pm_message_t state)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->suspend)
+ error = drv->suspend(of_dev, state);
+ return error;
+}
+
+static int of_platform_device_resume(struct device * dev)
+{
+ struct of_device * of_dev = to_of_device(dev);
+ struct of_platform_driver * drv = to_of_platform_driver(dev->driver);
+ int error = 0;
+
+ if (dev->driver && drv->resume)
+ error = drv->resume(of_dev);
+ return error;
+}
+
+struct bus_type of_platform_bus_type = {
+ .name = "of_platform",
+ .match = of_platform_bus_match,
+ .probe = of_platform_device_probe,
+ .remove = of_platform_device_remove,
+ .suspend = of_platform_device_suspend,
+ .resume = of_platform_device_resume,
+};
+EXPORT_SYMBOL(of_platform_bus_type);
+
+static int __init of_bus_driver_init(void)
+{
+ return bus_register(&of_platform_bus_type);
+}
+
+postcore_initcall(of_bus_driver_init);
+
+int of_register_platform_driver(struct of_platform_driver *drv)
+{
+ /* initialize common driver fields */
+ drv->driver.name = drv->name;
+ drv->driver.bus = &of_platform_bus_type;
+
+ /* register with core */
+ return driver_register(&drv->driver);
+}
+EXPORT_SYMBOL(of_register_platform_driver);
+
+void of_unregister_platform_driver(struct of_platform_driver *drv)
+{
+ driver_unregister(&drv->driver);
+}
+EXPORT_SYMBOL(of_unregister_platform_driver);
+
+static void of_platform_make_bus_id(struct of_device *dev)
+{
+ struct device_node *node = dev->node;
+ char *name = dev->dev.bus_id;
+ const u32 *reg;
+ u64 addr;
+
+ /*
+ * If it's a DCR based device, use 'd' for native DCRs
+ * and 'D' for MMIO DCRs.
+ */
+#ifdef CONFIG_PPC_DCR
+ reg = get_property(node, "dcr-reg", NULL);
+ if (reg) {
+#ifdef CONFIG_PPC_DCR_NATIVE
+ snprintf(name, BUS_ID_SIZE, "d%x.%s",
+ *reg, node->name);
+#else /* CONFIG_PPC_DCR_NATIVE */
+ addr = of_translate_dcr_address(node, *reg, NULL);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "D%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+#endif /* !CONFIG_PPC_DCR_NATIVE */
+ }
+#endif /* CONFIG_PPC_DCR */
+
+ /*
+ * For MMIO, get the physical address
+ */
+ reg = get_property(node, "reg", NULL);
+ if (reg) {
+ addr = of_translate_address(node, reg);
+ if (addr != OF_BAD_ADDR) {
+ snprintf(name, BUS_ID_SIZE,
+ "%llx.%s", (unsigned long long)addr,
+ node->name);
+ return;
+ }
+ }
+
+ /*
+ * No BusID, use the node name and pray
+ */
+ snprintf(name, BUS_ID_SIZE, "%s", node->name);
+}
+
+struct of_device* of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent)
+{
+ struct of_device *dev;
+
+ dev = kmalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return NULL;
+ memset(dev, 0, sizeof(*dev));
+
+ dev->node = of_node_get(np);
+ dev->dma_mask = 0xffffffffUL;
+ dev->dev.dma_mask = &dev->dma_mask;
+ dev->dev.parent = parent;
+ dev->dev.bus = &of_platform_bus_type;
+ dev->dev.release = of_release_dev;
+
+ if (bus_id)
+ strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE);
+ else
+ of_platform_make_bus_id(dev);
+
+ if (of_device_register(dev) != 0) {
+ kfree(dev);
+ return NULL;
+ }
+
+ return dev;
+}
+EXPORT_SYMBOL(of_platform_device_create);
+
+
+
+/**
+ * of_platform_bus_create - Create an OF device for a bus node and all its
+ * children. Optionally recursively instanciate matching busses.
+ * @bus: device node of the bus to instanciate
+ * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
+ * disallow recursive creation of child busses
+ */
+static int of_platform_bus_create(struct device_node *bus,
+ struct of_device_id *matches,
+ struct device *parent)
+{
+ struct device_node *child;
+ struct of_device *dev;
+ int rc = 0;
+
+ for (child = NULL; (child = of_get_next_child(bus, child)); ) {
+ pr_debug(" create child: %s\n", child->full_name);
+ dev = of_platform_device_create(child, NULL, parent);
+ if (dev == NULL)
+ rc = -ENOMEM;
+ else if (!of_match_node(matches, child))
+ continue;
+ if (rc == 0) {
+ pr_debug(" and sub busses\n");
+ rc = of_platform_bus_create(child, matches, &dev->dev);
+ } if (rc) {
+ of_node_put(child);
+ break;
+ }
+ }
+ return rc;
+}
+
+/**
+ * of_platform_bus_probe - Probe the device-tree for platform busses
+ * @root: parent of the first level to probe or NULL for the root of the tree
+ * @matches: match table, NULL to use the default
+ * @parent: parent to hook devices from, NULL for toplevel
+ *
+ * Note that children of the provided root are not instanciated as devices
+ * unless the specified root itself matches the bus list and is not NULL.
+ */
+
+int of_platform_bus_probe(struct device_node *root,
+ struct of_device_id *matches,
+ struct device *parent)
+{
+ struct device_node *child;
+ struct of_device *dev;
+ int rc = 0;
+
+ if (matches == NULL)
+ matches = of_default_bus_ids;
+ if (matches == OF_NO_DEEP_PROBE)
+ return -EINVAL;
+ if (root == NULL)
+ root = of_find_node_by_path("/");
+ else
+ of_node_get(root);
+
+ pr_debug("of_platform_bus_probe()\n");
+ pr_debug(" starting at: %s\n", root->full_name);
+
+ /* Do a self check of bus type, if there's a match, create
+ * children
+ */
+ if (of_match_node(matches, root)) {
+ pr_debug(" root match, create all sub devices\n");
+ dev = of_platform_device_create(root, NULL, parent);
+ if (dev == NULL) {
+ rc = -ENOMEM;
+ goto bail;
+ }
+ pr_debug(" create all sub busses\n");
+ rc = of_platform_bus_create(root, matches, &dev->dev);
+ goto bail;
+ }
+ for (child = NULL; (child = of_get_next_child(root, child)); ) {
+ if (!of_match_node(matches, child))
+ continue;
+
+ pr_debug(" match: %s\n", child->full_name);
+ dev = of_platform_device_create(child, NULL, parent);
+ if (dev == NULL)
+ rc = -ENOMEM;
+ else
+ rc = of_platform_bus_create(child, matches, &dev->dev);
+ if (rc) {
+ of_node_put(child);
+ break;
+ }
+ }
+ bail:
+ of_node_put(root);
+ return rc;
+}
+EXPORT_SYMBOL(of_platform_bus_probe);
+
+static int of_dev_node_match(struct device *dev, void *data)
+{
+ return to_of_device(dev)->node == data;
+}
+
+struct of_device *of_find_device_by_node(struct device_node *np)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&of_platform_bus_type,
+ NULL, np, of_dev_node_match);
+ if (dev)
+ return to_of_device(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_node);
+
+static int of_dev_phandle_match(struct device *dev, void *data)
+{
+ phandle *ph = data;
+ return to_of_device(dev)->node->linux_phandle == *ph;
+}
+
+struct of_device *of_find_device_by_phandle(phandle ph)
+{
+ struct device *dev;
+
+ dev = bus_find_device(&of_platform_bus_type,
+ NULL, &ph, of_dev_phandle_match);
+ if (dev)
+ return to_of_device(dev);
+ return NULL;
+}
+EXPORT_SYMBOL(of_find_device_by_phandle);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 824a618..e25a0bd 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -70,6 +70,7 @@ #include <asm/btext.h>
#include <asm/pmac_feature.h>
#include <asm/time.h>
#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include <asm/mmu_context.h>
#include <asm/iommu.h>
#include <asm/smu.h>
diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c
index ade25b3..4f724cd 100644
--- a/drivers/macintosh/smu.c
+++ b/drivers/macintosh/smu.c
@@ -46,6 +46,7 @@ #include <asm/sections.h>
#include <asm/abs_addr.h>
#include <asm/uaccess.h>
#include <asm/of_device.h>
+#include <asm/of_platform.h>
#define VERSION "0.7"
#define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp."
@@ -653,7 +654,7 @@ static int __init smu_init_sysfs(void)
* I'm a bit too far from figuring out how that works with those
* new chipsets, but that will come back and bite us
*/
- of_register_driver(&smu_of_platform_driver);
+ of_register_platform_driver(&smu_of_platform_driver);
return 0;
}
diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c
index a0f30d0..13b953a 100644
--- a/drivers/macintosh/therm_adt746x.c
+++ b/drivers/macintosh/therm_adt746x.c
@@ -30,7 +30,7 @@ #include <asm/machdep.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sections.h>
-#include <asm/of_device.h>
+#include <asm/of_platform.h>
#undef DEBUG
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index d00c0c3..2e4ad44 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -129,6 +129,7 @@ #include <asm/system.h>
#include <asm/sections.h>
#include <asm/of_device.h>
#include <asm/macio.h>
+#include <asm/of_platform.h>
#include "therm_pm72.h"
@@ -2236,14 +2237,14 @@ static int __init therm_pm72_init(void)
return -ENODEV;
}
- of_register_driver(&fcu_of_platform_driver);
+ of_register_platform_driver(&fcu_of_platform_driver);
return 0;
}
static void __exit therm_pm72_exit(void)
{
- of_unregister_driver(&fcu_of_platform_driver);
+ of_unregister_platform_driver(&fcu_of_platform_driver);
if (of_dev)
of_device_unregister(of_dev);
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 738faab..a1d3a98 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -36,12 +36,13 @@ #include <linux/sched.h>
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/init.h>
+
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/sections.h>
-#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include <asm/macio.h>
#define LOG_TEMP 0 /* continously log temperature */
@@ -511,14 +512,14 @@ g4fan_init( void )
return -ENODEV;
}
- of_register_driver( &therm_of_driver );
+ of_register_platform_driver( &therm_of_driver );
return 0;
}
static void __exit
g4fan_exit( void )
{
- of_unregister_driver( &therm_of_driver );
+ of_unregister_platform_driver( &therm_of_driver );
if( x.of_dev )
of_device_unregister( x.of_dev );
diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c
index fdb33cd..cb26c6d 100644
--- a/drivers/video/platinumfb.c
+++ b/drivers/video/platinumfb.c
@@ -34,6 +34,7 @@ #include <asm/io.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/of_device.h>
+#include <asm/of_platform.h>
#include "macmodes.h"
#include "platinumfb.h"
@@ -682,14 +683,14 @@ #ifndef MODULE
return -ENODEV;
platinumfb_setup(option);
#endif
- of_register_driver(&platinum_driver);
+ of_register_platform_driver(&platinum_driver);
return 0;
}
static void __exit platinumfb_exit(void)
{
- of_unregister_driver(&platinum_driver);
+ of_unregister_platform_driver(&platinum_driver);
}
MODULE_LICENSE("GPL");
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index c5c0b0b..1ef7e9e 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -6,12 +6,6 @@ #include <linux/device.h>
#include <linux/mod_devicetable.h>
#include <asm/prom.h>
-/*
- * The of_platform_bus_type is a bus type used by drivers that do not
- * attach to a macio or similar bus but still use OF probing
- * mechanism
- */
-extern struct bus_type of_platform_bus_type;
/*
* The of_device is a kind of "base class" that is a superset of
@@ -26,40 +20,16 @@ struct of_device
};
#define to_of_device(d) container_of(d, struct of_device, dev)
+extern const struct of_device_id *of_match_node(
+ const struct of_device_id *matches, const struct device_node *node);
extern const struct of_device_id *of_match_device(
const struct of_device_id *matches, const struct of_device *dev);
extern struct of_device *of_dev_get(struct of_device *dev);
extern void of_dev_put(struct of_device *dev);
-/*
- * An of_platform_driver driver is attached to a basic of_device on
- * the "platform bus" (of_platform_bus_type)
- */
-struct of_platform_driver
-{
- char *name;
- struct of_device_id *match_table;
- struct module *owner;
-
- int (*probe)(struct of_device* dev, const struct of_device_id *match);
- int (*remove)(struct of_device* dev);
-
- int (*suspend)(struct of_device* dev, pm_message_t state);
- int (*resume)(struct of_device* dev);
- int (*shutdown)(struct of_device* dev);
-
- struct device_driver driver;
-};
-#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver)
-
-extern int of_register_driver(struct of_platform_driver *drv);
-extern void of_unregister_driver(struct of_platform_driver *drv);
extern int of_device_register(struct of_device *ofdev);
extern void of_device_unregister(struct of_device *ofdev);
-extern struct of_device *of_platform_device_create(struct device_node *np,
- const char *bus_id,
- struct device *parent);
extern void of_release_dev(struct device *dev);
#endif /* __KERNEL__ */
diff --git a/include/asm-powerpc/of_platform.h b/include/asm-powerpc/of_platform.h
new file mode 100644
index 0000000..217eafb
--- /dev/null
+++ b/include/asm-powerpc/of_platform.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
+ * <benh@kernel.crashing.org>
+ *
+ * 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.
+ *
+ */
+
+#include <asm/of_device.h>
+
+/*
+ * The of_platform_bus_type is a bus type used by drivers that do not
+ * attach to a macio or similar bus but still use OF probing
+ * mechanism
+ */
+extern struct bus_type of_platform_bus_type;
+
+/*
+ * An of_platform_driver driver is attached to a basic of_device on
+ * the "platform bus" (of_platform_bus_type)
+ */
+struct of_platform_driver
+{
+ char *name;
+ struct of_device_id *match_table;
+ struct module *owner;
+
+ int (*probe)(struct of_device* dev,
+ const struct of_device_id *match);
+ int (*remove)(struct of_device* dev);
+
+ int (*suspend)(struct of_device* dev, pm_message_t state);
+ int (*resume)(struct of_device* dev);
+ int (*shutdown)(struct of_device* dev);
+
+ struct device_driver driver;
+};
+#define to_of_platform_driver(drv) \
+ container_of(drv,struct of_platform_driver, driver)
+
+/* Platform drivers register/unregister */
+extern int of_register_platform_driver(struct of_platform_driver *drv);
+extern void of_unregister_platform_driver(struct of_platform_driver *drv);
+
+/* Platform devices and busses creation */
+extern struct of_device *of_platform_device_create(struct device_node *np,
+ const char *bus_id,
+ struct device *parent);
+/* pseudo "matches" value to not do deep probe */
+#define OF_NO_DEEP_PROBE ((struct of_device_id *)-1)
+
+extern int of_platform_bus_probe(struct device_node *root,
+ struct of_device_id *matches,
+ struct device *parent);
+
+extern struct of_device *of_find_device_by_node(struct device_node *np);
+extern struct of_device *of_find_device_by_phandle(phandle ph);
--
1.4.3.2

View File

@ -0,0 +1,31 @@
From 20e872b5fed46ba15ed6f2c29cc2adf98657c9a4 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 22:20:06 +0100
Subject: [PATCH] [PATCH] ata: Fix pata_mpc52xx.c 'compatible' list
The list contained an entry to support a non-standard device-tree,
this is now handled by fixups in early boot.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
drivers/ata/pata_mpc52xx.c | 4 +---
1 files changed, 1 insertions(+), 3 deletions(-)
diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c
index 8b7019a..ff40016 100644
--- a/drivers/ata/pata_mpc52xx.c
+++ b/drivers/ata/pata_mpc52xx.c
@@ -509,9 +509,7 @@ mpc52xx_ata_resume(struct of_device *op)
static struct of_device_id mpc52xx_ata_of_match[] = {
{
- .compatible = "mpc5200-ata",
- },
- {
+ .type = "ata",
.compatible = "mpc52xx-ata",
},
{},
--
1.4.4.2

View File

@ -0,0 +1,28 @@
From f3736d1a7f74d7dec888a8a8d8c593ca08a31000 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 22:21:43 +0100
Subject: [PATCH] [PATCH] powerpc/serial: Fix mpc52xx_uart.c 'compatible' list
The list contained an entry to support a non-standard device-tree,
this is now handled by fixups in early boot.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
drivers/serial/mpc52xx_uart.c | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index eef3b02..c20cd81 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -128,7 +128,6 @@ static irqreturn_t mpc52xx_uart_int(int irq,void *dev_id);
#if defined(CONFIG_PPC_MERGE)
static struct of_device_id mpc52xx_uart_of_match[] = {
{ .type = "serial", .compatible = "mpc52xx-psc-uart", },
- { .type = "serial", .compatible = "mpc5200-psc", }, /* Efika only! */
{},
};
#endif
--
1.4.4.2

View File

@ -0,0 +1,144 @@
From 65cd4fcc30440e903fd99973918373ee4534b70a Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 22:39:18 +0100
Subject: [PATCH] [PATCH] powerpc: Small cleanup of EFIKA platform
This is just some cleanup to remove the efika.h header that just have
2 lines in it and is not really necessary.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/platforms/52xx/efika-pci.c | 23 ++++++++++++++++-------
arch/powerpc/platforms/52xx/efika-setup.c | 7 ++++---
arch/powerpc/platforms/52xx/efika.h | 19 -------------------
3 files changed, 20 insertions(+), 29 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/efika-pci.c b/arch/powerpc/platforms/52xx/efika-pci.c
index 62e05b2..3732dec 100644
--- a/arch/powerpc/platforms/52xx/efika-pci.c
+++ b/arch/powerpc/platforms/52xx/efika-pci.c
@@ -1,3 +1,13 @@
+/*
+ * Efika 5K2 PCI support thru RTAS
+ *
+ * Copyright (C) 2006 bplan GmbH
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ *
+ */
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -12,7 +22,6 @@
#include <asm/pci-bridge.h>
#include <asm/rtas.h>
-#include "efika.h"
#ifdef CONFIG_PCI
/*
@@ -62,7 +71,7 @@ void __init efika_pcisetup(void)
root = of_find_node_by_path("/");
if (root == NULL) {
- printk(KERN_WARNING EFIKA_PLATFORM_NAME
+ printk(KERN_WARNING __FILE__
": Unable to find the root node\n");
return;
}
@@ -76,30 +85,30 @@ void __init efika_pcisetup(void)
of_node_put(root);
if (pcictrl == NULL) {
- printk(KERN_WARNING EFIKA_PLATFORM_NAME
+ printk(KERN_WARNING __FILE__
": Unable to find the PCI bridge node\n");
return;
}
bus_range = get_property(pcictrl, "bus-range", &len);
if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING EFIKA_PLATFORM_NAME
+ printk(KERN_WARNING __FILE__
": Can't get bus-range for %s\n", pcictrl->full_name);
return;
}
if (bus_range[1] == bus_range[0])
- printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI bus %d",
+ printk(KERN_INFO __FILE__ ": PCI bus %d",
bus_range[0]);
else
- printk(KERN_INFO EFIKA_PLATFORM_NAME ": PCI buses %d..%d",
+ printk(KERN_INFO __FILE__ ": PCI buses %d..%d",
bus_range[0], bus_range[1]);
printk(" controlled by %s\n", pcictrl->full_name);
printk("\n");
hose = pcibios_alloc_controller();
if (!hose) {
- printk(KERN_WARNING EFIKA_PLATFORM_NAME
+ printk(KERN_WARNING __FILE__
": Can't allocate PCI controller structure for %s\n",
pcictrl->full_name);
return;
diff --git a/arch/powerpc/platforms/52xx/efika-setup.c b/arch/powerpc/platforms/52xx/efika-setup.c
index d61ce84..17bf73a 100644
--- a/arch/powerpc/platforms/52xx/efika-setup.c
+++ b/arch/powerpc/platforms/52xx/efika-setup.c
@@ -1,5 +1,4 @@
/*
- *
* Efika 5K2 platform setup
* Some code really inspired from the lite5200b platform.
*
@@ -32,7 +31,9 @@
#include <asm/of_platform.h>
#include <asm/mpc52xx.h>
-#include "efika.h"
+
+extern void __init efika_pcisetup(void);
+
static void efika_show_cpuinfo(struct seq_file *m)
{
@@ -103,7 +104,7 @@ static int __init efika_probe(void)
define_machine(efika)
{
- .name = EFIKA_PLATFORM_NAME,
+ .name = "Efika",
.probe = efika_probe,
.setup_arch = efika_setup_arch,
.init = mpc52xx_declare_of_platform_devices,
diff --git a/arch/powerpc/platforms/52xx/efika.h b/arch/powerpc/platforms/52xx/efika.h
deleted file mode 100644
index 2f060fd..0000000
--- a/arch/powerpc/platforms/52xx/efika.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
- * Efika 5K2 platform setup - Header file
- *
- * Copyright (C) 2006 bplan GmbH
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- *
- */
-
-#ifndef __ARCH_POWERPC_EFIKA__
-#define __ARCH_POWERPC_EFIKA__
-
-#define EFIKA_PLATFORM_NAME "Efika"
-
-extern void __init efika_pcisetup(void);
-
-#endif
--
1.4.4.2

View File

@ -0,0 +1,116 @@
From 90dc591d4c897c7a49191888c1e4d413cc08b8b7 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 23:08:56 +0100
Subject: [PATCH] [PATCH] powerpc: Add a unified uevent handler for bus based on of_device
This common uevent handler allow the several bus types based on
of_device to generate the uevent properly and avoiding
code duplication.
This handlers take a struct device as argument and can therefore
be used as the uevent call directly if no special treatment is
needed for the bus.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/kernel/of_device.c | 66 +++++++++++++++++++++++++++++++++++++++
include/asm-powerpc/of_device.h | 3 ++
2 files changed, 69 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c
index e921514..ac024ad 100644
--- a/arch/powerpc/kernel/of_device.c
+++ b/arch/powerpc/kernel/of_device.c
@@ -120,6 +120,71 @@ void of_device_unregister(struct of_device *ofdev)
}
+int of_device_uevent(struct device *dev,
+ char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct of_device *ofdev;
+ const char *compat;
+ char *compat2;
+ char compat_buf[128]; /* need to be size of 'compatible' */
+ int i = 0, length = 0, seen = 0, cplen, sl;
+
+ if (!dev)
+ return -ENODEV;
+
+ ofdev = to_of_device(dev);
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_NAME=%s", ofdev->node->name))
+ return -ENOMEM;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_TYPE=%s", ofdev->node->type))
+ return -ENOMEM;
+
+ /* Since the compatible field can contain pretty much anything
+ * it's not really legal to split it out with commas. We split it
+ * up using a number of environment variables instead. */
+
+ compat = get_property(ofdev->node, "compatible", &cplen);
+ compat2 = compat_buf;
+ if (compat)
+ memcpy(compat2, compat, cplen);
+ while (compat && *compat && cplen > 0) {
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_COMPATIBLE_%d=%s", seen, compat))
+ return -ENOMEM;
+
+ sl = strlen (compat) + 1;
+ compat += sl;
+ compat2 += sl;
+ cplen -= sl;
+ seen++;
+ compat2[-1] = 'C';
+ }
+ compat2[seen?-1:0] = 0;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "OF_COMPATIBLE_N=%d", seen))
+ return -ENOMEM;
+
+ if (add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=of:N%sT%sC%s",
+ ofdev->node->name, ofdev->node->type,
+ compat_buf))
+ return -ENOMEM;
+
+ envp[i] = NULL;
+
+ return 0;
+}
+
+
EXPORT_SYMBOL(of_match_node);
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_device_register);
@@ -127,3 +192,4 @@ EXPORT_SYMBOL(of_device_unregister);
EXPORT_SYMBOL(of_dev_get);
EXPORT_SYMBOL(of_dev_put);
EXPORT_SYMBOL(of_release_dev);
+EXPORT_SYMBOL(of_device_uevent);
diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h
index a889b20..4f1aabe 100644
--- a/include/asm-powerpc/of_device.h
+++ b/include/asm-powerpc/of_device.h
@@ -32,5 +32,8 @@ extern int of_device_register(struct of_device *ofdev);
extern void of_device_unregister(struct of_device *ofdev);
extern void of_release_dev(struct device *dev);
+extern int of_device_uevent(struct device *dev,
+ char **envp, int num_envp, char *buffer, int buffer_size);
+
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_OF_DEVICE_H */
--
1.4.4.2

View File

@ -0,0 +1,130 @@
From 2507b27c0841752a6f419439896fcb089fa4a5ba Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 23:13:56 +0100
Subject: [PATCH] [PATCH] macintosh: Use the new of_device common uevent handler
The generation of the uevent is now common to all bus using
of_device.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
drivers/macintosh/macio_asic.c | 98 +---------------------------------------
1 files changed, 1 insertions(+), 97 deletions(-)
diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c
index d562160..e851266 100644
--- a/drivers/macintosh/macio_asic.c
+++ b/drivers/macintosh/macio_asic.c
@@ -134,108 +134,12 @@ static int macio_device_resume(struct device * dev)
return 0;
}
-static int macio_uevent(struct device *dev, char **envp, int num_envp,
- char *buffer, int buffer_size)
-{
- struct macio_dev * macio_dev;
- struct of_device * of;
- char *scratch;
- const char *compat, *compat2;
-
- int i = 0;
- int length, cplen, cplen2, seen = 0;
-
- if (!dev)
- return -ENODEV;
-
- macio_dev = to_macio_device(dev);
- if (!macio_dev)
- return -ENODEV;
-
- of = &macio_dev->ofdev;
-
- /* stuff we want to pass to /sbin/hotplug */
- envp[i++] = scratch = buffer;
- length = scnprintf (scratch, buffer_size, "OF_NAME=%s", of->node->name);
- ++length;
- buffer_size -= length;
- if ((buffer_size <= 0) || (i >= num_envp))
- return -ENOMEM;
- scratch += length;
-
- envp[i++] = scratch;
- length = scnprintf (scratch, buffer_size, "OF_TYPE=%s", of->node->type);
- ++length;
- buffer_size -= length;
- if ((buffer_size <= 0) || (i >= num_envp))
- return -ENOMEM;
- scratch += length;
-
- /* Since the compatible field can contain pretty much anything
- * it's not really legal to split it out with commas. We split it
- * up using a number of environment variables instead. */
-
- compat = get_property(of->node, "compatible", &cplen);
- compat2 = compat;
- cplen2= cplen;
- while (compat && cplen > 0) {
- envp[i++] = scratch;
- length = scnprintf (scratch, buffer_size,
- "OF_COMPATIBLE_%d=%s", seen, compat);
- ++length;
- buffer_size -= length;
- if ((buffer_size <= 0) || (i >= num_envp))
- return -ENOMEM;
- scratch += length;
- length = strlen (compat) + 1;
- compat += length;
- cplen -= length;
- seen++;
- }
-
- envp[i++] = scratch;
- length = scnprintf (scratch, buffer_size, "OF_COMPATIBLE_N=%d", seen);
- ++length;
- buffer_size -= length;
- if ((buffer_size <= 0) || (i >= num_envp))
- return -ENOMEM;
- scratch += length;
-
- envp[i++] = scratch;
- length = scnprintf (scratch, buffer_size, "MODALIAS=of:N%sT%s",
- of->node->name, of->node->type);
- /* overwrite '\0' */
- buffer_size -= length;
- if ((buffer_size <= 0) || (i >= num_envp))
- return -ENOMEM;
- scratch += length;
-
- if (!compat2) {
- compat2 = "";
- cplen2 = 1;
- }
- while (cplen2 > 0) {
- length = snprintf (scratch, buffer_size, "C%s", compat2);
- buffer_size -= length;
- if (buffer_size <= 0)
- return -ENOMEM;
- scratch += length;
- length = strlen (compat2) + 1;
- compat2 += length;
- cplen2 -= length;
- }
-
- envp[i] = NULL;
-
- return 0;
-}
-
extern struct device_attribute macio_dev_attrs[];
struct bus_type macio_bus_type = {
.name = "macio",
.match = macio_bus_match,
- .uevent = macio_uevent,
+ .uevent = of_device_uevent,
.probe = macio_device_probe,
.remove = macio_device_remove,
.shutdown = macio_device_shutdown,
--
1.4.4.2

View File

@ -0,0 +1,29 @@
From 846d6cd8584eee7517543be073c8b3fe9fefd065 Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 23:16:07 +0100
Subject: [PATCH] [PATCH] powerpc: Add uevent handler for of_platform_bus
Adding this handler allow userspace to properly handle the module
autoloading. The generation of the uevent itself is now common to
all bus using of_device, so not much code here.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/kernel/of_platform.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c
index b734517..da78e44 100644
--- a/arch/powerpc/kernel/of_platform.c
+++ b/arch/powerpc/kernel/of_platform.c
@@ -133,6 +133,7 @@ static int of_platform_device_resume(struct device * dev)
struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
+ .uevent = of_device_uevent,
.probe = of_platform_device_probe,
.remove = of_platform_device_remove,
.suspend = of_platform_device_suspend,
--
1.4.4.2

View File

@ -0,0 +1,50 @@
From ddc4a7296f3abd28a902f38ae915224d6d93edca Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Sat, 23 Dec 2006 23:20:58 +0100
Subject: [PATCH] [PATCH] powerpc: Add uevent handler for ibmebus
Adding this handler allow userspace to properly handle the module
autoloading. The generation of the uevent itself is now common to
all bus using of_device, so not much code here.
But we still need a small wrapper to filter out the dummy root
device node used by this bus.
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
arch/powerpc/kernel/ibmebus.c | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 82bd2f1..2e8d9fd 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -361,9 +361,25 @@ static int ibmebus_bus_match(struct device *dev, struct device_driver *drv)
return 0;
}
+static int ibmebus_bus_uevent(struct device *dev,
+ char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct ibmebus_dev *ebus_dev;
+
+ if (!dev)
+ return -ENODEV;
+
+ ebus_dev = to_ibmebus_dev(dev);
+ if (ebus_dev==ibmebus_bus_device) /* filter dummy root device */
+ return -ENODEV;
+
+ return of_device_uevent(dev, envp, num_envp, buffer, buffer_size);
+}
+
struct bus_type ibmebus_bus_type = {
.name = "ibmebus",
.match = ibmebus_bus_match,
+ .uevent = ibmebus_bus_uevent,
};
EXPORT_SYMBOL(ibmebus_bus_type);
--
1.4.4.2

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +1,37 @@
From 0eae8b0fed7d8342c027e15d2a6d52eae10366e1 Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:09:04 +0100
Subject: [PATCH] Add MPC5200 ethernet driver
From 6b6e09cca4346ea737db427d568843034eb348fa Mon Sep 17 00:00:00 2001
From: Andrey Volkov <avolkov@varma-el.com>
Date: Fri, 18 Aug 2006 10:02:29 -0600
Subject: [PATCH] [PATCH 02/02] Fec MPC5200 eth driver
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
Second part. Contain only FEC parts.
Depended on previous bestcomm patch.
Signed-Off-By: Andrey Volkov <avolkov at varma-el.com>
---
drivers/net/Kconfig | 1 +
drivers/net/Makefile | 1 +
drivers/net/fec_mpc52xx/Kconfig | 22 +
drivers/net/fec_mpc52xx/Kconfig | 23 ++
drivers/net/fec_mpc52xx/Makefile | 2 +
drivers/net/fec_mpc52xx/fec.c | 817 +++++++++++++++++++++++++++++++++++++
drivers/net/fec_mpc52xx/fec.h | 308 ++++++++++++++
drivers/net/fec_mpc52xx/fec_phy.c | 532 ++++++++++++++++++++++++
drivers/net/fec_mpc52xx/fec.c | 768 +++++++++++++++++++++++++++++++++++++
drivers/net/fec_mpc52xx/fec.h | 308 +++++++++++++++
drivers/net/fec_mpc52xx/fec_phy.c | 526 +++++++++++++++++++++++++
drivers/net/fec_mpc52xx/fec_phy.h | 73 ++++
8 files changed, 1756 insertions(+), 0 deletions(-)
8 files changed, 1702 insertions(+), 0 deletions(-)
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 6e863aa..c0bf347 100644
index 8aa8dd0..0658e92 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -1892,6 +1892,7 @@ config NE_H8300
@@ -1902,6 +1902,7 @@ config NE_H8300
controller on the Renesas H8/300 processor.
source "drivers/net/fec_8xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
+source "drivers/net/fec_mpc52xx/Kconfig"
source "drivers/net/fs_enet/Kconfig"
endmenu
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f270bc4..a39a931 100644
index 4c0d4e5..e6f903d 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -196,6 +196,7 @@ obj-$(CONFIG_SMC91X) += smc91x.o
@ -37,27 +40,28 @@ index f270bc4..a39a931 100644
obj-$(CONFIG_FEC_8XX) += fec_8xx/
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
obj-$(CONFIG_ARM) += arm/
obj-$(CONFIG_DEV_APPLETALK) += appletalk/
obj-$(CONFIG_MACB) += macb.o
diff --git a/drivers/net/fec_mpc52xx/Kconfig b/drivers/net/fec_mpc52xx/Kconfig
new file mode 100644
index 0000000..dc3fee6
index 0000000..098c3fa
--- /dev/null
+++ b/drivers/net/fec_mpc52xx/Kconfig
@@ -0,0 +1,22 @@
@@ -0,0 +1,23 @@
+menu "MPC5200 Networking Options"
+ depends (PPC_CHRP || PPC_MPC52xx) && NET_ETHERNET
+ depends PPC_MPC52xx && NET_ETHERNET
+
+config FEC_MPC52xx
+ bool "FEC Ethernet"
+ depends on NET_ETHERNET
+ select PPC_BESTCOMM
+ select CRC32
+ ---help---
+ This option enables support for the MPC5200's on-chip
+ Fast Ethernet Controller
+
+config USE_MDIO
+ bool "Use external Ethernet MII PHY"
+ bool " Use external Ethernet MII PHY"
+ select MII
+ depends FEC_MPC52xx
+ ---help---
@ -77,10 +81,10 @@ index 0000000..b8ae05c
+obj-$(CONFIG_USE_MDIO) += fec_phy.o
diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
new file mode 100644
index 0000000..5591bb7
index 0000000..b5f1559
--- /dev/null
+++ b/drivers/net/fec_mpc52xx/fec.c
@@ -0,0 +1,817 @@
@@ -0,0 +1,768 @@
+/*
+ * drivers/net/fec_mpc52xx/fec.c
+ *
@ -110,40 +114,20 @@ index 0000000..5591bb7
+
+#include <asm/io.h>
+#include <asm/delay.h>
+#include <asm/ppcboot.h>
+#include <asm/mpc52xx.h>
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+
+#ifdef CONFIG_PPC_EFIKA
+#include <platforms/efika/bestcomm.h>
+#else
+#include <syslib/bestcomm/bestcomm.h>
+#include <syslib/bestcomm/fec.h>
+#endif
+
+/******************/
+/******************/
+static unsigned long get_ipbfreq(void)
+{
+#ifdef CONFIG_PPC_EFIKA
+ return (132*1000*1000);
+#else
+ bd_t *bd = (bd_t *)&__res;
+ return bd->bi_ipbfreq
+#endif
+}
+
+/******************/
+/******************/
+
+#include "fec_phy.h"
+#include "fec.h"
+
+#define DRIVER_NAME "mpc52xx-fec"
+
+static irqreturn_t fec_interrupt(int, void *);
+static irqreturn_t fec_rx_interrupt(int, void *);
+static irqreturn_t fec_tx_interrupt(int, void *);
+static irqreturn_t fec_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t fec_rx_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t fec_tx_interrupt(int, void *, struct pt_regs *);
+static struct net_device_stats *fec_get_stats(struct net_device *);
+static void fec_set_multicast_list(struct net_device *dev);
+static void fec_reinit(struct net_device *dev);
@ -336,7 +320,7 @@ index 0000000..5591bb7
+
+/* This handles BestComm transmit task interrupts
+ */
+static irqreturn_t fec_tx_interrupt(int irq, void *dev_id)
+static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fec_priv *priv = (struct fec_priv *)dev->priv;
@ -362,7 +346,7 @@ index 0000000..5591bb7
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fec_rx_interrupt(int irq, void *dev_id)
+static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = dev_id;
+ struct fec_priv *priv = (struct fec_priv *)dev->priv;
@ -419,7 +403,7 @@ index 0000000..5591bb7
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fec_interrupt(int irq, void *dev_id)
+static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+ struct net_device *dev = (struct net_device *)dev_id;
+ struct fec_priv *priv = (struct fec_priv *)dev->priv;
@ -427,24 +411,17 @@ index 0000000..5591bb7
+ int ievent;
+
+ ievent = in_be32(&fec->ievent);
+ if (!ievent)
+ return IRQ_NONE;
+
+ out_be32(&fec->ievent, ievent); /* clear pending events */
+
+ if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
+ if ( net_ratelimit() )
+ {
+ if (ievent & FEC_IEVENT_RFIFO_ERROR)
+ printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR (%8.8x)\n", ievent);
+ if (ievent & FEC_IEVENT_XFIFO_ERROR)
+ printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR (%8.8x)\n", ievent);
+ }
+ if (ievent & FEC_IEVENT_RFIFO_ERROR)
+ printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR\n");
+ if (ievent & FEC_IEVENT_XFIFO_ERROR)
+ printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR\n");
+ fec_reinit(dev);
+ }
+ else if (ievent & FEC_IEVENT_MII)
+ fec_mii(dev);
+
+ return IRQ_HANDLED;
+}
+
@ -605,7 +582,8 @@ index 0000000..5591bb7
+{
+ struct fec_priv *priv = (struct fec_priv *)dev->priv;
+ struct mpc52xx_fec *fec = priv->fec;
+
+ bd_t *bd = (bd_t *) &__res;
+
+ out_be32(&fec->op_pause, 0x00010020);
+ out_be32(&fec->rfifo_cntrl, 0x0f000000);
+ out_be32(&fec->rfifo_alarm, 0x0000030c);
@ -616,7 +594,7 @@ index 0000000..5591bb7
+ out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */
+ out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */
+
+ priv->phy_speed = ((get_ipbfreq() >> 20) / 5) << 1;
+ priv->phy_speed = ((bd->bi_ipbfreq >> 20) / 5) << 1;
+
+ fec_restart(dev, 0); /* always use half duplex mode only */
+ /*
@ -626,12 +604,13 @@ index 0000000..5591bb7
+ fec_update_stat(dev);
+}
+
+static void fec_update_stat(struct net_device *);
+
+static void fec_reinit(struct net_device *dev)
+{
+ struct fec_priv *priv = (struct fec_priv *)dev->priv;
+ struct mpc52xx_fec *fec = priv->fec;
+
+ static void fec_update_stat(struct net_device *);
+
+ netif_stop_queue(dev);
+ out_be32(&fec->imask, 0x0);
+
@ -660,31 +639,33 @@ index 0000000..5591bb7
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
+mpc52xx_fec_probe(struct device *dev)
+{
+ int ret;
+ int rv;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct net_device *ndev;
+ struct fec_priv *priv = NULL;
+ struct resource mem;
+ struct resource *mem;
+
+ volatile int dbg=0;
+ while(dbg)
+ __asm("nop");
+ /* Reserve FEC control zone */
+ rv = of_address_to_resource(op->node, 0, &mem);
+ if (rv) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Error while parsing device node resource\n" );
+ return rv;
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if ((mem->end - mem->start + 1) != sizeof(struct mpc52xx_fec)) {
+ printk(KERN_ERR DRIVER_NAME
+ " - invalid resource size (%lx != %x), check mpc52xx_devices.c\n",
+ mem->end - mem->start + 1, sizeof(struct mpc52xx_fec));
+ return -EINVAL;
+ }
+
+ if (!request_mem_region(mem.start, sizeof(struct mpc52xx_fec),
+ if (!request_mem_region(mem->start, sizeof(struct mpc52xx_fec),
+ DRIVER_NAME))
+ return -EBUSY;
+
+ /* Get the ether ndev & it's private zone */
+ ndev = alloc_etherdev(sizeof(struct fec_priv));
+ if (!ndev) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not allocate the ethernet device\n" );
+ ret = -ENOMEM;
+ goto probe_error;
+ }
@ -702,7 +683,7 @@ index 0000000..5591bb7
+ ndev->tx_timeout = fec_tx_timeout;
+ ndev->watchdog_timeo = FEC_WATCHDOG_TIMEOUT;
+ ndev->flags &= ~IFF_RUNNING;
+ ndev->base_addr = mem.start;
+ ndev->base_addr = mem->start;
+
+ priv->rx_fifo = ndev->base_addr + FIELD_OFFSET(mpc52xx_fec,rfifo_data);
+ priv->tx_fifo = ndev->base_addr + FIELD_OFFSET(mpc52xx_fec,tfifo_data);
@ -712,27 +693,18 @@ index 0000000..5591bb7
+
+ /* ioremap the zones */
+ priv->fec = (struct mpc52xx_fec *)
+ ioremap(mem.start, sizeof(struct mpc52xx_fec));
+ ioremap(mem->start, sizeof(struct mpc52xx_fec));
+
+ if (!priv->fec) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not remap IO memory at 0x%8.8x\n", mem.start );
+ ret = -ENOMEM;
+ goto probe_error;
+ }
+
+ /* SDMA init */
+#ifdef CONFIG_PPC_EFIKA
+ priv->rx_sdma = sdma_fex_rx_preinit(FEC_RX_NUM_BD);
+ priv->tx_sdma = sdma_fex_tx_preinit(FEC_TX_NUM_BD);
+#else
+ priv->rx_sdma = sdma_alloc(FEC_RX_NUM_BD);
+ priv->tx_sdma = sdma_alloc(FEC_TX_NUM_BD);
+#endif
+
+ if (!priv->rx_sdma || !priv->tx_sdma) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not init SDMA tasks\n" );
+ ret = -ENOMEM;
+ goto probe_error;
+ }
@ -746,10 +718,8 @@ index 0000000..5591bb7
+ goto probe_error;
+
+ /* Get the IRQ we need one by one */
+ /* Control */
+
+ ndev->irq = irq_of_parse_and_map(op->node, 0);
+
+ /* Control */
+ ndev->irq = platform_get_irq(pdev, 0);
+ if (request_irq(ndev->irq, &fec_interrupt, SA_INTERRUPT,
+ DRIVER_NAME "_ctrl", ndev)) {
+ printk(KERN_ERR DRIVER_NAME ": ctrl interrupt request failed\n");
@ -758,7 +728,7 @@ index 0000000..5591bb7
+ goto probe_error;
+ }
+
+ /* RX */
+ /* RX */
+ priv->r_irq = sdma_irq(priv->rx_sdma);
+ if (request_irq(priv->r_irq, &fec_rx_interrupt, SA_INTERRUPT,
+ DRIVER_NAME "_rx", ndev)) {
@ -768,7 +738,7 @@ index 0000000..5591bb7
+ goto probe_error;
+ }
+
+ /* TX */
+ /* TX */
+ priv->t_irq = sdma_irq(priv->tx_sdma);
+ if (request_irq(priv->t_irq, &fec_tx_interrupt, SA_INTERRUPT,
+ DRIVER_NAME "_tx", ndev)) {
@ -796,11 +766,12 @@ index 0000000..5591bb7
+ fec_mii_init(ndev);
+
+ /* We're done ! */
+ dev_set_drvdata(&op->dev, ndev);
+ dev_set_drvdata(dev, ndev);
+
+ return 0;
+
+ /* Errorx handling - free everything that might be allocated */
+
+ /* Error handling - free everything that might be allocated */
+probe_error:
+
+ if (ndev) {
@ -816,18 +787,18 @@ index 0000000..5591bb7
+ free_netdev(ndev);
+ }
+
+ release_mem_region(mem.start, sizeof(struct mpc52xx_fec));
+ release_mem_region(mem->start, sizeof(struct mpc52xx_fec));
+
+ return ret;
+}
+
+static int
+mpc52xx_fec_remove(struct of_device *op)
+mpc52xx_fec_remove(struct device *dev)
+{
+ struct net_device *ndev;
+ struct fec_priv *priv;
+
+ ndev = (struct net_device *) dev_get_drvdata(&op->dev);
+ ndev = (struct net_device *) dev_get_drvdata(dev);
+ if (!ndev)
+ return 0;
+ priv = (struct fec_priv *) ndev->priv;
@ -844,35 +815,19 @@ index 0000000..5591bb7
+
+ free_netdev(ndev);
+
+ dev_set_drvdata(&op->dev, NULL);
+ dev_set_drvdata(dev, NULL);
+ return 0;
+}
+
+static struct of_device_id mpc52xx_fec_of_match[] = {
+ {
+ .compatible = "mpc5200-ethernet",
+ },
+ {
+ .compatible = "mpc52xx-fec",
+ },
+ {},
+};
+
+
+static struct of_platform_driver mpc52xx_fec_driver = {
+static struct device_driver mpc52xx_fec_driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .match_table = mpc52xx_fec_of_match,
+ .bus = &platform_bus_type,
+ .probe = mpc52xx_fec_probe,
+ .remove = mpc52xx_fec_remove,
+#ifdef CONFIG_PM
+/* .suspend = mpc52xx_fec_suspend, TODO */
+/* .resume = mpc52xx_fec_resume, TODO */
+#endif
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+/* ======================================================================== */
@ -882,13 +837,13 @@ index 0000000..5591bb7
+static int __init
+mpc52xx_fec_init(void)
+{
+ return of_register_platform_driver(&mpc52xx_fec_driver);
+ return driver_register(&mpc52xx_fec_driver);
+}
+
+static void __exit
+mpc52xx_fec_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_fec_driver);
+ driver_unregister(&mpc52xx_fec_driver);
+}
+
+
@ -1214,10 +1169,10 @@ index 0000000..f9eed36
+#endif /* __DRIVERS_NET_MPC52XX_FEC_H__ */
diff --git a/drivers/net/fec_mpc52xx/fec_phy.c b/drivers/net/fec_mpc52xx/fec_phy.c
new file mode 100644
index 0000000..1b2f4e1
index 0000000..2a287de
--- /dev/null
+++ b/drivers/net/fec_mpc52xx/fec_phy.c
@@ -0,0 +1,532 @@
@@ -0,0 +1,526 @@
+/*
+ * arch/ppc/52xx_io/fec_phy.c
+ *
@ -1240,14 +1195,8 @@ index 0000000..1b2f4e1
+#include <linux/mii.h>
+#include <asm/io.h>
+#include <asm/mpc52xx.h>
+
+#ifdef CONFIG_PPC_EFIKA
+#include <platforms/efika/bestcomm.h>
+#else
+#include <syslib/bestcomm/bestcomm.h>
+#include <syslib/bestcomm/fec.h>
+#endif
+
+#include "fec_phy.h"
+#include "fec.h"
+
@ -1457,7 +1406,7 @@ index 0000000..1b2f4e1
+ },
+ (const phy_cmd_t []) { /* startup */
+ /* restart auto-negotiation */
+ { mk_mii_write(MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART) ),
+ { mk_mii_write(MII_BMCR, (BMCR_ANENABLE | BMCR_ANRESTART)),
+ NULL },
+ { mk_mii_end, }
+ },
@ -1830,5 +1779,5 @@ index 0000000..5c23bff
+
+extern int fec_ioctl(struct net_device *, struct ifreq *rq, int cmd);
--
1.4.3.2
1.4.4.2

View File

@ -0,0 +1,464 @@
From c4c2f5cb57335b1b47aa8007b0cfce48cc46fa06 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Tue, 21 Nov 2006 14:41:59 -0700
Subject: [PATCH] [MPC52xx] PCI now working on lite5200... ugly, but working
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/platforms/52xx/mpc52xx_pci.c | 334 +++++++++++++++++++++++++++++
arch/powerpc/platforms/52xx/mpc52xx_pci.h | 104 +++++++++
2 files changed, 438 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
new file mode 100644
index 0000000..07dce3c
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -0,0 +1,334 @@
+/*
+ * PCI code for the Freescale MPC52xx embedded CPU.
+ *
+ * Copyright (C) 2004 Secret Lab Technologies Ltd.
+ * Grant Likely <grant.likely@secretlab.ca>
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#define DEBUG
+
+#include <asm/pci.h>
+#include <asm/mpc52xx.h>
+#include "mpc52xx_pci.h"
+#include <asm/delay.h>
+#include <asm/machdep.h>
+#include <linux/kernel.h>
+
+
+/* This macro is defined to activate the workaround for the bug
+ 435 of the MPC5200 (L25R). With it activated, we don't do any
+ 32 bits configuration access during type-1 cycles */
+#define MPC5200_BUG_435_WORKAROUND
+
+
+static int
+mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#ifdef MPC5200_BUG_435_WORKAROUND
+ if (bus->number != hose->bus_offset) {
+ switch (len) {
+ case 1:
+ value = in_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3));
+ break;
+ case 2:
+ value = in_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1));
+ break;
+
+ default:
+ value = in_le16((u16 __iomem *)hose->cfg_data) |
+ (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+ break;
+ }
+ }
+ else
+#endif
+ {
+ value = in_le32(hose->cfg_data);
+
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
+ }
+
+ *val = value;
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value, mask;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#ifdef MPC5200_BUG_435_WORKAROUND
+ if (bus->number != hose->bus_offset) {
+ switch (len) {
+ case 1:
+ out_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3), val);
+ break;
+ case 2:
+ out_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1), val);
+ break;
+
+ default:
+ out_le16((u16 __iomem *)hose->cfg_data,
+ (u16)val);
+ out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+ (u16)(val>>16));
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
+
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
+
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
+
+ out_le32(hose->cfg_data, val);
+ }
+ mb();
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc52xx_pci_ops = {
+ .read = mpc52xx_pci_read_config,
+ .write = mpc52xx_pci_write_config
+};
+
+
+static void __init
+mpc52xx_pci_setup(struct pci_controller *hose,
+ struct mpc52xx_pci __iomem *pci_regs)
+{
+ struct resource *res;
+ u32 tmp;
+ int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
+
+ pr_debug("mpc52xx_pci_setup()\n");
+
+ pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
+ in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
+ in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
+ pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
+ in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
+ in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
+
+ /* Setup control regs */
+ tmp = in_be32(&pci_regs->scr);
+ tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ out_be32(&pci_regs->scr, tmp);
+
+ /* Setup windows */
+ res = &hose->mem_resources[0];
+ if (res->flags) {
+ pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw0btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr0 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ res = &hose->mem_resources[1];
+ if (res->flags) {
+ pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw1btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr1 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ res = &hose->io_resource;
+ if (!res) {
+ printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
+ return;
+ }
+ pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+ ".io_base_phys=%lx\n",
+ res->start, res->end, res->flags, hose->io_base_phys);
+ out_be32(&pci_regs->iw2btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+ res->start,
+ res->end - res->start + 1));
+ iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
+
+ pr_debug("iwcr0=%x iwcr1=%x iwcr2=%x iwcr=%x old_iwcr=%x\n",
+ iwcr0, iwcr1, iwcr2,
+ MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2),
+ in_be32(&pci_regs->iwcr));
+ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
+
+ out_be32(&pci_regs->tbatr0,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+ out_be32(&pci_regs->tbatr1,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+
+ out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+
+ /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+ /* Not necessary and can be a bad thing if for example the bootloader
+ is displaying a splash screen or ... Just left here for
+ documentation purpose if anyone need it */
+ tmp = in_be32(&pci_regs->gscr);
+#if 0
+ out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+ udelay(50);
+#endif
+ out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
+
+ pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
+ in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
+ in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
+ pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
+ in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
+ in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
+}
+
+static void
+mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
+ dev->vendor, dev->device);
+
+ /* We don't rely on boot loader for PCI and resets all
+ devices */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = &dev->resource[i];
+ if (res->end > res->start) { /* Only valid resources */
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ }
+ }
+
+ /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+ fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+ if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+ || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
+ struct resource *res = &dev->resource[1];
+ res->start = res->end = res->flags = 0;
+ }
+}
+
+int __init
+mpc52xx_add_bridge(struct device_node *node)
+{
+ int len;
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+ const int *bus_range;
+ struct resource rsrc;
+
+ pr_debug("Adding PCI host bridge %s\n", node->full_name);
+
+ pci_assign_all_buses = 1;
+
+ if (of_address_to_resource(node, 0, &rsrc) != 0) {
+ printk(KERN_ERR "Can't get %s resources\n", node->full_name);
+ return -EINVAL;
+ }
+
+ bus_range = get_property(node, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get bus-range for %s, assume"
+ " bus 0\n", node->full_name);
+ }
+
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return -ENOMEM;
+
+ ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+
+ hose->arch_data = node;
+ hose->set_cfg_type = 1;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ hose->bus_offset = 0;
+ hose->ops = &mpc52xx_pci_ops;
+
+ pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ if (!pci_regs)
+ return -ENOMEM;
+
+ pci_process_bridge_OF_ranges(hose, node, 0);
+
+ hose->cfg_addr = &pci_regs->car;
+
+ hose->cfg_data = hose->io_base_virt;
+ hose->io_base_virt = ioremap(hose->io_base_phys,
+ hose->io_resource.end + 1 -
+ hose->io_resource.start);
+ isa_io_base = (unsigned long) hose->io_base_virt;
+
+ mpc52xx_pci_setup(hose, pci_regs);
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.h b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
new file mode 100644
index 0000000..07a659e
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
@@ -0,0 +1,104 @@
+/*
+ * PCI Include file the Freescale MPC52xx embedded cpu chips
+ *
+ * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
+ * for the 2.4 kernel.
+ *
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2003 MontaVista, Software, Inc.
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#ifndef __SYSLIB_MPC52xx_PCI_H__
+#define __SYSLIB_MPC52xx_PCI_H__
+
+/* ======================================================================== */
+/* PCI windows config */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_TARGET_IO 0xf0000000
+#define MPC52xx_PCI_TARGET_MEM 0x00000000
+
+
+/* ======================================================================== */
+/* Structures mapping & Defines for PCI Unit */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_GSCR_BM 0x40000000
+#define MPC52xx_PCI_GSCR_PE 0x20000000
+#define MPC52xx_PCI_GSCR_SE 0x10000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
+#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
+#define MPC52xx_PCI_GSCR_BME 0x00004000
+#define MPC52xx_PCI_GSCR_PEE 0x00002000
+#define MPC52xx_PCI_GSCR_SEE 0x00001000
+#define MPC52xx_PCI_GSCR_PR 0x00000001
+
+
+#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
+ ( ( (proc_ad) & 0xff000000 ) | \
+ ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
+ ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+
+#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+ ((win1) << 16) | \
+ ((win2) << 8))
+
+#define MPC52xx_PCI_IWCR_DISABLE 0x0
+#define MPC52xx_PCI_IWCR_ENABLE 0x1
+#define MPC52xx_PCI_IWCR_READ 0x0
+#define MPC52xx_PCI_IWCR_READ_LINE 0x2
+#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
+#define MPC52xx_PCI_IWCR_MEM 0x0
+#define MPC52xx_PCI_IWCR_IO 0x8
+
+#define MPC52xx_PCI_TCR_P 0x01000000
+#define MPC52xx_PCI_TCR_LD 0x00010000
+
+#define MPC52xx_PCI_TBATR_DISABLE 0x0
+#define MPC52xx_PCI_TBATR_ENABLE 0x1
+
+
+#ifndef __ASSEMBLY__
+
+struct mpc52xx_pci {
+ u32 idr; /* PCI + 0x00 */
+ u32 scr; /* PCI + 0x04 */
+ u32 ccrir; /* PCI + 0x08 */
+ u32 cr1; /* PCI + 0x0C */
+ u32 bar0; /* PCI + 0x10 */
+ u32 bar1; /* PCI + 0x14 */
+ u8 reserved1[16]; /* PCI + 0x18 */
+ u32 ccpr; /* PCI + 0x28 */
+ u32 sid; /* PCI + 0x2C */
+ u32 erbar; /* PCI + 0x30 */
+ u32 cpr; /* PCI + 0x34 */
+ u8 reserved2[4]; /* PCI + 0x38 */
+ u32 cr2; /* PCI + 0x3C */
+ u8 reserved3[32]; /* PCI + 0x40 */
+ u32 gscr; /* PCI + 0x60 */
+ u32 tbatr0; /* PCI + 0x64 */
+ u32 tbatr1; /* PCI + 0x68 */
+ u32 tcr; /* PCI + 0x6C */
+ u32 iw0btar; /* PCI + 0x70 */
+ u32 iw1btar; /* PCI + 0x74 */
+ u32 iw2btar; /* PCI + 0x78 */
+ u8 reserved4[4]; /* PCI + 0x7C */
+ u32 iwcr; /* PCI + 0x80 */
+ u32 icr; /* PCI + 0x84 */
+ u32 isr; /* PCI + 0x88 */
+ u32 arb; /* PCI + 0x8C */
+ u8 reserved5[104]; /* PCI + 0x90 */
+ u32 car; /* PCI + 0xF8 */
+ u8 reserved6[4]; /* PCI + 0xFC */
+};
+
+#endif /* __ASSEMBLY__ */
+
+
+#endif /* __SYSLIB_MPC52xx_PCI_H__ */
--
1.4.4.2

View File

@ -0,0 +1,700 @@
From 3c687b616fee5d7097e965fce80f8f8b2b6e14cf Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 4 Dec 2006 22:29:03 -0700
Subject: [PATCH] [POWERPC] Make FEC work on the lite5200
This patch may very well break Eth support on the Efika, and it's not
very pretty. But is works well enough for an NFS rootfs. This also
makes major bestcomm changes by removing Efika-specific bestcomm
support and porting the arch/ppc bestcomm support driver which
was posted to linuxppc-embedded about a year ago.
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/Kconfig | 5 +
arch/powerpc/platforms/52xx/Makefile | 3 +
arch/powerpc/platforms/52xx/bestcomm.c | 98 ++++++++++-------------
arch/powerpc/platforms/52xx/bestcomm.h | 13 ++-
arch/powerpc/platforms/52xx/fec.c | 1 -
arch/powerpc/platforms/52xx/lite5200.c | 9 ++
drivers/net/fec_mpc52xx/Kconfig | 2 +-
drivers/net/fec_mpc52xx/fec.c | 137 +++++++++++++++++++++++++++----
drivers/net/fec_mpc52xx/fec_phy.c | 6 ++
9 files changed, 196 insertions(+), 78 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 8699dad..23d7d73 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -429,6 +429,11 @@ config PPC_MPC52xx
bool
default n
+config PPC_BESTCOMM
+ bool
+ depends on PPC_MPC52xx
+ default y
+
config PPC_EFIKA
bool "bPlan Efika 5k2. MPC5200B based computer"
depends on PPC_MULTIPLATFORM && PPC32
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index a46184a..d85ea04 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -3,6 +3,9 @@
#
ifeq ($(CONFIG_PPC_MERGE),y)
obj-y += mpc52xx_pic.o mpc52xx_common.o
+obj-$(CONFIG_PCI) += mpc52xx_pci.o
+obj-$(CONFIG_PPC_BESTCOMM) += bestcomm.o
+obj-$(CONFIG_FEC_MPC52xx) += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
endif
obj-$(CONFIG_PPC_EFIKA) += efika-setup.o efika-pci.o
diff --git a/arch/powerpc/platforms/52xx/bestcomm.c b/arch/powerpc/platforms/52xx/bestcomm.c
index ef45e02..9935b01 100644
--- a/arch/powerpc/platforms/52xx/bestcomm.c
+++ b/arch/powerpc/platforms/52xx/bestcomm.c
@@ -16,7 +16,6 @@
* Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
*/
-#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
@@ -24,17 +23,19 @@
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/string.h>
-#include <linux/device.h>
#include <asm/bug.h>
#include <asm/io.h>
#include <asm/mpc52xx.h>
+#include <asm/of_platform.h>
#include "bestcomm.h"
-#define DRIVER_NAME "mpc52xx-sdma"
+#define DRIVER_NAME "mpc52xx-bestcomm"
struct sdma_io sdma;
+struct device_node *sdma_node;
+struct device_node *sram_node;
static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
@@ -42,7 +43,8 @@ static spinlock_t sdma_lock = SPIN_LOCK_UNLOCKED;
void sdma_dump(void)
{
int i;
- printk("** SDMA registers: pa = %08x, va = %08x\n", sdma.base_reg_addr, sdma.io);
+ printk("** SDMA registers: pa = %.8lx, va = %p\n",
+ sdma.base_reg_addr, sdma.io);
printk("** taskBar = %08x\n", sdma.io->taskBar);
printk("** currentPointer = %08x\n", sdma.io->currentPointer);
printk("** endPointer = %08x\n", sdma.io->endPointer);
@@ -254,6 +256,7 @@ struct sdma *sdma_alloc(int queue_size)
}
s->num_bd = queue_size;
+ s->node = sdma_node;
return s;
}
@@ -264,29 +267,49 @@ void sdma_free(struct sdma *s)
kfree(s);
}
-static int __devinit mpc52xx_sdma_probe(struct device *dev)
+static int __init mpc52xx_sdma_init(void)
{
- struct platform_device *pdev = to_platform_device(dev);
int task;
u32 *context;
u32 *fdt;
struct sdma_tdt *tdt;
- struct resource *mem_io, *mem_sram;
- u32 tdt_pa, var_pa, context_pa, fdt_pa;
+ struct resource mem_io, mem_sram;
+ u32 tdt_pa, var_pa, context_pa, fdt_pa;
int ret = -ENODEV;
- mem_io = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- mem_sram = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (!mem_io || !mem_sram)
+ /* Find SDMA registers */
+ sdma_node = of_find_compatible_node(NULL, "dma-controller", "mpc52xx-bestcomm");
+ if (!sdma_node) {
+ printk (KERN_ERR DRIVER_NAME ": could not locate SDRAM controller\n");
goto out;
+ }
+
+ if ((ret = of_address_to_resource(sdma_node, 0, &mem_io)) != 0) {
+ printk(KERN_ERR "Could not get address of SDMA controller\n");
+ goto out;
+ }
+
+ /* Find SRAM location */
+ sram_node = of_find_compatible_node(NULL, "sram", "mpc52xx-sram");
+ if (!sram_node) {
+ printk (KERN_ERR DRIVER_NAME ": could not locate SRAM\n");
+ goto out;
+ }
+
+ if ((ret = of_address_to_resource(sram_node, 0, &mem_sram)) != 0) {
+ printk(KERN_ERR "Could not get address of SRAM\n");
+ goto out;
+ }
- if (!request_mem_region(mem_io->start, mem_io->end - mem_io->start + 1, DRIVER_NAME)) {
+ /* Map register regions */
+ if (!request_mem_region(mem_io.start, mem_io.end - mem_io.start + 1,
+ DRIVER_NAME)) {
printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
goto out;
}
- sdma.base_reg_addr = mem_io->start;
+ sdma.base_reg_addr = mem_io.start;
- sdma.io = ioremap_nocache(mem_io->start, sizeof(struct mpc52xx_sdma));
+ sdma.io = ioremap_nocache(mem_io.start, sizeof(struct mpc52xx_sdma));
if (!sdma.io ) {
printk(KERN_ERR DRIVER_NAME " - failed to map sdma regs\n");
@@ -296,14 +319,14 @@ static int __devinit mpc52xx_sdma_probe(struct device *dev)
SDMA_DUMP_REGS();
- sdma.sram_size = mem_sram->end - mem_sram->start + 1;
- if (!request_mem_region(mem_sram->start, sdma.sram_size, DRIVER_NAME)) {
+ sdma.sram_size = mem_sram.end - mem_sram.start + 1;
+ if (!request_mem_region(mem_sram.start, sdma.sram_size, DRIVER_NAME)) {
printk(KERN_ERR DRIVER_NAME " - resource unavailable\n");
goto req_sram_error;
}
- sdma.base_sram_addr = mem_sram->start;
- sdma.sram = ioremap_nocache(mem_sram->start, sdma.sram_size);
+ sdma.base_sram_addr = mem_sram.start;
+ sdma.sram = ioremap_nocache(mem_sram.start, sdma.sram_size);
if (!sdma.sram ) {
printk(KERN_ERR DRIVER_NAME " - failed to map sdma sram\n");
ret = -ENOMEM;
@@ -350,50 +373,17 @@ static int __devinit mpc52xx_sdma_probe(struct device *dev)
return 0;
map_sram_error:
- release_mem_region(mem_sram->start, sdma.sram_size);
+ release_mem_region(mem_sram.start, sdma.sram_size);
req_sram_error:
iounmap(sdma.io);
map_io_error:
- release_mem_region(mem_io->start, mem_io->end - mem_io->start + 1);
+ release_mem_region(mem_io.start, mem_io.end - mem_io.start + 1);
out:
printk(KERN_ERR "DMA: MPC52xx BestComm init FAILED !!!\n");
return ret;
}
-
-static struct device_driver mpc52xx_sdma_driver = {
- .owner = THIS_MODULE,
- .name = DRIVER_NAME,
- .bus = &platform_bus_type,
- .probe = mpc52xx_sdma_probe,
-/* .remove = mpc52xx_sdma_remove, TODO */
-#ifdef CONFIG_PM
-/* .suspend = mpc52xx_sdma_suspend, TODO */
-/* .resume = mpc52xx_sdma_resume, TODO */
-#endif
-};
-
-static int __init
-mpc52xx_sdma_init(void)
-{
- printk(KERN_INFO "DMA: MPC52xx BestComm driver\n");
- return driver_register(&mpc52xx_sdma_driver);
-}
-
-#ifdef MODULE
-static void __exit
-mpc52xx_sdma_exit(void)
-{
- driver_unregister(&mpc52xx_sdma_driver);
-}
-#endif
-
-#ifndef MODULE
- subsys_initcall(mpc52xx_sdma_init);
-#else
- module_init(mpc52xx_sdma_init);
- module_exit(mpc52xx_sdma_exit);
-#endif
+subsys_initcall(mpc52xx_sdma_init);
MODULE_DESCRIPTION("Freescale MPC52xx BestComm DMA");
diff --git a/arch/powerpc/platforms/52xx/bestcomm.h b/arch/powerpc/platforms/52xx/bestcomm.h
index 14bf397..bd2619d 100644
--- a/arch/powerpc/platforms/52xx/bestcomm.h
+++ b/arch/powerpc/platforms/52xx/bestcomm.h
@@ -19,6 +19,8 @@
#ifndef __BESTCOMM_BESTCOMM_H__
#define __BESTCOMM_BESTCOMM_H__
+#include "mpc52xx_pic.h"
+
/* Buffer Descriptor definitions */
struct sdma_bd {
u32 status;
@@ -70,6 +72,7 @@ struct sdma {
u16 num_bd;
s16 tasknum;
u32 flags;
+ struct device_node *node;
};
#define SDMA_FLAGS_NONE 0x0000
@@ -116,7 +119,9 @@ struct sdma_tdt {
static inline void sdma_enable_task(int task)
{
- DPRINTK("***DMA enable task (%d): tdt = %08x\n",task, sdma.tdt);
+ u16 reg;
+
+ DPRINTK("***DMA enable task (%d): tdt = %p\n",task, sdma.tdt);
DPRINTK("***tdt->start = %08x\n",sdma.tdt[task].start);
DPRINTK("***tdt->stop = %08x\n",sdma.tdt[task].stop);
DPRINTK("***tdt->var = %08x\n",sdma.tdt[task].var);
@@ -127,8 +132,8 @@ static inline void sdma_enable_task(int task)
DPRINTK("***tdt->litbase = %08x\n",sdma.tdt[task].litbase);
DPRINTK("***--------------\n");
- u16 reg = in_be16(&sdma.io->tcr[task]);
- DPRINTK("***enable task: &sdma.io->tcr=%08x, reg = %04x\n", &sdma.io->tcr, reg);
+ reg = in_be16(&sdma.io->tcr[task]);
+ DPRINTK("***enable task: &sdma.io->tcr=%p, reg = %04x\n", &sdma.io->tcr, reg);
out_be16(&sdma.io->tcr[task], reg | TASK_ENABLE);
}
@@ -141,7 +146,7 @@ static inline void sdma_disable_task(int task)
static inline int sdma_irq(struct sdma *s)
{
- return MPC52xx_SDMA_IRQ_BASE + s->tasknum;
+ return irq_of_parse_and_map(s->node, s->tasknum);
}
static inline void sdma_enable(struct sdma *s)
diff --git a/arch/powerpc/platforms/52xx/fec.c b/arch/powerpc/platforms/52xx/fec.c
index 8756856..90df6f4 100644
--- a/arch/powerpc/platforms/52xx/fec.c
+++ b/arch/powerpc/platforms/52xx/fec.c
@@ -16,7 +16,6 @@
* Andrey Volkov <avolkov@varma-el.com>, Varma Electronics Oy
*/
-#include <linux/config.h>
#include <linux/version.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index 0f21bab..f1bbe24 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -107,6 +107,15 @@ static void __init lite52xx_setup_arch(void)
mpc52xx_setup_cpu(); /* Generic */
lite52xx_setup_cpu(); /* Platorm specific */
+#ifdef CONFIG_PCI
+ np = of_find_node_by_type(np, "pci");
+ if (np)
+ mpc52xx_add_bridge(np);
+
+ //ppc_md.pci_swizzle = common_swizzle;
+ //ppc_md.pci_exclude_device = mpc52xx_exclude_device;
+#endif
+
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start)
ROOT_DEV = Root_RAM0;
diff --git a/drivers/net/fec_mpc52xx/Kconfig b/drivers/net/fec_mpc52xx/Kconfig
index 098c3fa..b6bce55 100644
--- a/drivers/net/fec_mpc52xx/Kconfig
+++ b/drivers/net/fec_mpc52xx/Kconfig
@@ -11,7 +11,7 @@ config FEC_MPC52xx
Fast Ethernet Controller
config USE_MDIO
- bool " Use external Ethernet MII PHY"
+ bool "Use external Ethernet MII PHY"
select MII
depends FEC_MPC52xx
---help---
diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
index b5f1559..894da79 100644
--- a/drivers/net/fec_mpc52xx/fec.c
+++ b/drivers/net/fec_mpc52xx/fec.c
@@ -30,17 +30,24 @@
#include <asm/ppcboot.h>
#include <asm/mpc52xx.h>
+#if defined(CONFIG_PPC_MERGE)
+#include <asm/of_device.h>
+#include <asm/of_platform.h>
+#include <platforms/52xx/bestcomm.h>
+#include <platforms/52xx/fec.h>
+#else
#include <syslib/bestcomm/bestcomm.h>
#include <syslib/bestcomm/fec.h>
+#endif
#include "fec_phy.h"
#include "fec.h"
#define DRIVER_NAME "mpc52xx-fec"
-static irqreturn_t fec_interrupt(int, void *, struct pt_regs *);
-static irqreturn_t fec_rx_interrupt(int, void *, struct pt_regs *);
-static irqreturn_t fec_tx_interrupt(int, void *, struct pt_regs *);
+static irqreturn_t fec_interrupt(int, void *);
+static irqreturn_t fec_rx_interrupt(int, void *);
+static irqreturn_t fec_tx_interrupt(int, void *);
static struct net_device_stats *fec_get_stats(struct net_device *);
static void fec_set_multicast_list(struct net_device *dev);
static void fec_reinit(struct net_device *dev);
@@ -233,7 +240,7 @@ static int fec_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
/* This handles BestComm transmit task interrupts
*/
-static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fec_tx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct fec_priv *priv = (struct fec_priv *)dev->priv;
@@ -259,7 +266,7 @@ static irqreturn_t fec_tx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fec_rx_interrupt(int irq, void *dev_id)
{
struct net_device *dev = dev_id;
struct fec_priv *priv = (struct fec_priv *)dev->priv;
@@ -316,7 +323,7 @@ static irqreturn_t fec_rx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
return IRQ_HANDLED;
}
-static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+static irqreturn_t fec_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *)dev_id;
struct fec_priv *priv = (struct fec_priv *)dev->priv;
@@ -324,13 +331,18 @@ static irqreturn_t fec_interrupt(int irq, void *dev_id, struct pt_regs *regs)
int ievent;
ievent = in_be32(&fec->ievent);
+ if (!ievent)
+ return IRQ_NONE;
+
out_be32(&fec->ievent, ievent); /* clear pending events */
if (ievent & (FEC_IEVENT_RFIFO_ERROR | FEC_IEVENT_XFIFO_ERROR)) {
- if (ievent & FEC_IEVENT_RFIFO_ERROR)
- printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR\n");
- if (ievent & FEC_IEVENT_XFIFO_ERROR)
- printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR\n");
+ if (net_ratelimit() && (ievent & FEC_IEVENT_RFIFO_ERROR))
+ printk(KERN_WARNING "FEC_IEVENT_RFIFO_ERROR (%.8x)\n",
+ ievent);
+ if (net_ratelimit() && (ievent & FEC_IEVENT_XFIFO_ERROR))
+ printk(KERN_WARNING "FEC_IEVENT_XFIFO_ERROR (%.8x)\n",
+ ievent);
fec_reinit(dev);
}
else if (ievent & FEC_IEVENT_MII)
@@ -495,7 +507,9 @@ static void fec_hw_init(struct net_device *dev)
{
struct fec_priv *priv = (struct fec_priv *)dev->priv;
struct mpc52xx_fec *fec = priv->fec;
+#if !defined(CONFIG_PPC_MERGE)
bd_t *bd = (bd_t *) &__res;
+#endif
out_be32(&fec->op_pause, 0x00010020);
out_be32(&fec->rfifo_cntrl, 0x0f000000);
@@ -507,7 +521,9 @@ static void fec_hw_init(struct net_device *dev)
out_be32(&fec->iaddr1, 0x00000000); /* No individual filter */
out_be32(&fec->iaddr2, 0x00000000); /* No individual filter */
+#if !defined(CONFIG_PPC_MERGE)
priv->phy_speed = ((bd->bi_ipbfreq >> 20) / 5) << 1;
+#endif
fec_restart(dev, 0); /* always use half duplex mode only */
/*
@@ -522,7 +538,6 @@ static void fec_reinit(struct net_device *dev)
{
struct fec_priv *priv = (struct fec_priv *)dev->priv;
struct mpc52xx_fec *fec = priv->fec;
- static void fec_update_stat(struct net_device *);
netif_stop_queue(dev);
out_be32(&fec->imask, 0x0);
@@ -551,19 +566,38 @@ static void fec_reinit(struct net_device *dev)
/* Platform Driver */
/* ======================================================================== */
+#if defined(CONFIG_PPC_MERGE)
+static int __devinit
+mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match)
+#else
static int __devinit
mpc52xx_fec_probe(struct device *dev)
+#endif
{
int ret;
+#if defined(CONFIG_PPC_MERGE)
+ int rv;
+ struct resource __mem;
+ struct resource *mem = &__mem;
+#else
struct platform_device *pdev = to_platform_device(dev);
+ struct resource *mem;
+#endif
struct net_device *ndev;
struct fec_priv *priv = NULL;
- struct resource *mem;
volatile int dbg=0;
while(dbg)
__asm("nop");
/* Reserve FEC control zone */
+#if defined(CONFIG_PPC_MERGE)
+ rv = of_address_to_resource(op->node, 0, mem);
+ if (rv) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Error while parsing device node resource\n" );
+ return rv;
+ }
+#else
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if ((mem->end - mem->start + 1) != sizeof(struct mpc52xx_fec)) {
printk(KERN_ERR DRIVER_NAME
@@ -571,7 +605,8 @@ mpc52xx_fec_probe(struct device *dev)
mem->end - mem->start + 1, sizeof(struct mpc52xx_fec));
return -EINVAL;
}
-
+#endif
+
if (!request_mem_region(mem->start, sizeof(struct mpc52xx_fec),
DRIVER_NAME))
return -EBUSY;
@@ -579,6 +614,8 @@ mpc52xx_fec_probe(struct device *dev)
/* Get the ether ndev & it's private zone */
ndev = alloc_etherdev(sizeof(struct fec_priv));
if (!ndev) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not allocate the ethernet device\n" );
ret = -ENOMEM;
goto probe_error;
}
@@ -609,6 +646,8 @@ mpc52xx_fec_probe(struct device *dev)
ioremap(mem->start, sizeof(struct mpc52xx_fec));
if (!priv->fec) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not remap IO memory at 0x%8.8x\n", mem->start );
ret = -ENOMEM;
goto probe_error;
}
@@ -618,6 +657,8 @@ mpc52xx_fec_probe(struct device *dev)
priv->tx_sdma = sdma_alloc(FEC_TX_NUM_BD);
if (!priv->rx_sdma || !priv->tx_sdma) {
+ printk(KERN_ERR DRIVER_NAME ": "
+ "Can not init SDMA tasks\n" );
ret = -ENOMEM;
goto probe_error;
}
@@ -631,8 +672,13 @@ mpc52xx_fec_probe(struct device *dev)
goto probe_error;
/* Get the IRQ we need one by one */
- /* Control */
+ /* Control */
+#if defined(CONFIG_PPC_MERGE)
+ ndev->irq = irq_of_parse_and_map(op->node, 0);
+#else
ndev->irq = platform_get_irq(pdev, 0);
+#endif
+
if (request_irq(ndev->irq, &fec_interrupt, SA_INTERRUPT,
DRIVER_NAME "_ctrl", ndev)) {
printk(KERN_ERR DRIVER_NAME ": ctrl interrupt request failed\n");
@@ -641,26 +687,32 @@ mpc52xx_fec_probe(struct device *dev)
goto probe_error;
}
- /* RX */
+ /* RX */
priv->r_irq = sdma_irq(priv->rx_sdma);
if (request_irq(priv->r_irq, &fec_rx_interrupt, SA_INTERRUPT,
DRIVER_NAME "_rx", ndev)) {
- printk(KERN_ERR DRIVER_NAME ": rx interrupt request failed\n");
+ printk(KERN_ERR DRIVER_NAME ": rx request_irq(0x%x) failed\n",
+ priv->r_irq);
ret = -EBUSY;
priv->r_irq = -1; /* Don't try to free it */
goto probe_error;
}
- /* TX */
+ /* TX */
priv->t_irq = sdma_irq(priv->tx_sdma);
if (request_irq(priv->t_irq, &fec_tx_interrupt, SA_INTERRUPT,
DRIVER_NAME "_tx", ndev)) {
- printk(KERN_ERR DRIVER_NAME ": tx interrupt request failed\n");
+ printk(KERN_ERR DRIVER_NAME ": tx request_irq(0x%x) failed\n",
+ priv->t_irq);
ret = -EBUSY;
priv->t_irq = -1; /* Don't try to free it */
goto probe_error;
}
+#if defined(CONFIG_PPC_MERGE)
+ priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1;
+#endif
+
/* MAC address init */
if (memcmp(mpc52xx_fec_mac_addr, null_mac, 6) != 0)
memcpy(ndev->dev_addr, mpc52xx_fec_mac_addr, 6);
@@ -679,7 +731,11 @@ mpc52xx_fec_probe(struct device *dev)
fec_mii_init(ndev);
/* We're done ! */
+#if defined(CONFIG_PPC_MERGE)
+ dev_set_drvdata(&op->dev, ndev);
+#else
dev_set_drvdata(dev, ndev);
+#endif
return 0;
@@ -705,13 +761,22 @@ probe_error:
return ret;
}
+#if defined(CONFIG_PPC_MERGE)
+static int
+mpc52xx_fec_remove(struct of_device *op)
+#else
static int
mpc52xx_fec_remove(struct device *dev)
+#endif
{
struct net_device *ndev;
struct fec_priv *priv;
+#if defined(CONFIG_PPC_MERGE)
+ ndev = (struct net_device *) dev_get_drvdata(&op->dev);
+#else
ndev = (struct net_device *) dev_get_drvdata(dev);
+#endif
if (!ndev)
return 0;
priv = (struct fec_priv *) ndev->priv;
@@ -728,10 +793,37 @@ mpc52xx_fec_remove(struct device *dev)
free_netdev(ndev);
+#if defined(CONFIG_PPC_MERGE)
+ dev_set_drvdata(&op->dev, NULL);
+#else
dev_set_drvdata(dev, NULL);
+#endif
return 0;
}
+#if defined(CONFIG_PPC_MERGE)
+static struct of_device_id mpc52xx_fec_of_match[] = {
+ { .compatible = "mpc5200-ethernet", },
+ { .compatible = "mpc52xx-fec", },
+ {},
+};
+
+static struct of_platform_driver mpc52xx_fec_driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .match_table = mpc52xx_fec_of_match,
+ .probe = mpc52xx_fec_probe,
+ .remove = mpc52xx_fec_remove,
+#ifdef CONFIG_PM
+/* .suspend = mpc52xx_fec_suspend, TODO */
+/* .resume = mpc52xx_fec_resume, TODO */
+#endif
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+#else
static struct device_driver mpc52xx_fec_driver = {
.name = DRIVER_NAME,
.bus = &platform_bus_type,
@@ -742,6 +834,7 @@ static struct device_driver mpc52xx_fec_driver = {
/* .resume = mpc52xx_fec_resume, TODO */
#endif
};
+#endif
/* ======================================================================== */
/* Module */
@@ -750,13 +843,21 @@ static struct device_driver mpc52xx_fec_driver = {
static int __init
mpc52xx_fec_init(void)
{
+#if defined(CONFIG_PPC_MERGE)
+ return of_register_platform_driver(&mpc52xx_fec_driver);
+#else
return driver_register(&mpc52xx_fec_driver);
+#endif
}
static void __exit
mpc52xx_fec_exit(void)
{
+#if defined(CONFIG_PPC_MERGE)
+ of_unregister_platform_driver(&mpc52xx_fec_driver);
+#else
driver_unregister(&mpc52xx_fec_driver);
+#endif
}
diff --git a/drivers/net/fec_mpc52xx/fec_phy.c b/drivers/net/fec_mpc52xx/fec_phy.c
index 2a287de..25e0409 100644
--- a/drivers/net/fec_mpc52xx/fec_phy.c
+++ b/drivers/net/fec_mpc52xx/fec_phy.c
@@ -20,8 +20,14 @@
#include <linux/mii.h>
#include <asm/io.h>
#include <asm/mpc52xx.h>
+
+#ifdef CONFIG_PPC_MERGE
+#include <platforms/52xx/bestcomm.h>
+#else
#include <syslib/bestcomm/bestcomm.h>
#include <syslib/bestcomm/fec.h>
+#endif
+
#include "fec_phy.h"
#include "fec.h"
--
1.4.4.2

View File

@ -0,0 +1,26 @@
From 4ad1395745f590eba1b5220c8dd3ca6541f49db7 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 4 Dec 2006 22:55:49 -0700
Subject: [PATCH] Add missing function prototype
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
include/asm-powerpc/mpc52xx.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/include/asm-powerpc/mpc52xx.h b/include/asm-powerpc/mpc52xx.h
index 4560d72..7afd5bf 100644
--- a/include/asm-powerpc/mpc52xx.h
+++ b/include/asm-powerpc/mpc52xx.h
@@ -249,6 +249,8 @@ extern void mpc52xx_declare_of_platform_devices(void);
extern void mpc52xx_init_irq(void);
extern unsigned int mpc52xx_get_irq(void);
+extern int __init mpc52xx_add_bridge(struct device_node *node);
+
#endif /* __ASSEMBLY__ */
#endif /* __ASM_POWERPC_MPC52xx_H__ */
--
1.4.4.2

View File

@ -1,19 +1,19 @@
From 6d3cbf9a4549928be8ed15cf6a3576c217723895 Mon Sep 17 00:00:00 2001
From: Nicolas DET <nd@bplan-gmbh.de>
Date: Fri, 24 Nov 2006 13:22:22 +0100
Subject: [PATCH] Added RTAS support for 32bit PowerPC
From 95f80c44731c46261b0ba334b35ee803f21ef60b Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 4 Dec 2006 23:01:13 -0700
Subject: [PATCH] [POWERPC] Misc EFIKA fixups for rtas/chrp
Signed-off-by: Nicolas DET <nd@bplan-gmbh.de>
---
arch/powerpc/kernel/proc_ppc64.c | 9 ---------
arch/powerpc/kernel/rtas-proc.c | 36 ++++++++++++++++++++++++++----------
2 files changed, 26 insertions(+), 19 deletions(-)
arch/powerpc/kernel/proc_ppc64.c | 9 --------
arch/powerpc/kernel/rtas-proc.c | 36 +++++++++++++++++++++++++---------
arch/powerpc/platforms/chrp/setup.c | 9 ++++++++
3 files changed, 35 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/kernel/proc_ppc64.c b/arch/powerpc/kernel/proc_ppc64.c
index f598cb5..9b9c32d 100644
index dd7001c..fa54220 100644
--- a/arch/powerpc/kernel/proc_ppc64.c
+++ b/arch/powerpc/kernel/proc_ppc64.c
@@ -51,15 +51,6 @@ static int __init proc_ppc64_create(void
@@ -51,15 +51,6 @@ static int __init proc_ppc64_create(void)
if (!root)
return 1;
@ -33,7 +33,7 @@ diff --git a/arch/powerpc/kernel/rtas-proc.c b/arch/powerpc/kernel/rtas-proc.c
index 2fe82ab..4c06c32 100644
--- a/arch/powerpc/kernel/rtas-proc.c
+++ b/arch/powerpc/kernel/rtas-proc.c
@@ -253,43 +253,59 @@ static void get_location_code(struct seq
@@ -253,43 +253,59 @@ static void get_location_code(struct seq_file *m,
static void check_location_string(struct seq_file *m, const char *c);
static void check_location(struct seq_file *m, const char *c);
@ -103,6 +103,31 @@ index 2fe82ab..4c06c32 100644
if (entry)
entry->proc_fops = &ppc_rtas_rmo_buf_ops;
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index e1f51d4..ec4515c 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -580,11 +580,20 @@ static int __init chrp_probe(void)
{
char *dtype = of_get_flat_dt_prop(of_get_flat_dt_root(),
"device_type", NULL);
+
+ char *model = of_get_flat_dt_prop(of_get_flat_dt_root(),
+ "model", NULL);
if (dtype == NULL)
return 0;
if (strcmp(dtype, "chrp"))
return 0;
+ /*
+ * Filter out efika because it has its own platform
+ */
+ if (model && (strcmp(model, "EFIKA5K2") == 0) )
+ return 0;
+
ISA_DMA_THRESHOLD = ~0L;
DMA_MODE_READ = 0x44;
DMA_MODE_WRITE = 0x48;
--
1.4.3.2
1.4.4.2

View File

@ -0,0 +1,911 @@
From 78aaa3476bf62a50d85a9753bf1ef82fd296ca73 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 11 Dec 2006 22:41:49 -0700
Subject: [PATCH] [POWERPC] Cleanup mpc52xx PCI support
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/Kconfig | 17 ++-
arch/powerpc/platforms/52xx/mpc52xx_pci.c | 334 ------------------------
arch/powerpc/platforms/52xx/mpc52xx_pci.h | 104 --------
arch/powerpc/platforms/52xx/pci.c | 404 +++++++++++++++++++++++++++++
4 files changed, 420 insertions(+), 439 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 23d7d73..ec17225 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -429,6 +429,21 @@ config PPC_MPC52xx
bool
default n
+config PPC_MPC5200
+ bool
+ select PPC_MPC52xx
+ default n
+
+config PPC_MPC5200_BUGFIX
+ bool "MPC5200 (L25R) bugfix support"
+ depends on PPC_MPC5200
+ default n
+ help
+ Enable workarounds for original MPC5200 errata. This is not required
+ for MPC5200B based boards.
+
+ It is safe to say 'Y' here
+
config PPC_BESTCOMM
bool
depends on PPC_MPC52xx
@@ -446,7 +461,7 @@ config PPC_EFIKA
config PPC_LITE5200
bool "Freescale Lite5200 Eval Board"
depends on PPC_MULTIPLATFORM && PPC32
- select PPC_MPC52xx
+ select PPC_MPC5200
default n
config PPC_PMAC
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
deleted file mode 100644
index 07dce3c..0000000
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.c
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * PCI code for the Freescale MPC52xx embedded CPU.
- *
- * Copyright (C) 2004 Secret Lab Technologies Ltd.
- * Grant Likely <grant.likely@secretlab.ca>
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#define DEBUG
-
-#include <asm/pci.h>
-#include <asm/mpc52xx.h>
-#include "mpc52xx_pci.h"
-#include <asm/delay.h>
-#include <asm/machdep.h>
-#include <linux/kernel.h>
-
-
-/* This macro is defined to activate the workaround for the bug
- 435 of the MPC5200 (L25R). With it activated, we don't do any
- 32 bits configuration access during type-1 cycles */
-#define MPC5200_BUG_435_WORKAROUND
-
-
-static int
-mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- u32 value;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- out_be32(hose->cfg_addr,
- (1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
- (devfn << 8) |
- (offset & 0xfc));
- mb();
-
-#ifdef MPC5200_BUG_435_WORKAROUND
- if (bus->number != hose->bus_offset) {
- switch (len) {
- case 1:
- value = in_8(((u8 __iomem *)hose->cfg_data) +
- (offset & 3));
- break;
- case 2:
- value = in_le16(((u16 __iomem *)hose->cfg_data) +
- ((offset>>1) & 1));
- break;
-
- default:
- value = in_le16((u16 __iomem *)hose->cfg_data) |
- (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
- break;
- }
- }
- else
-#endif
- {
- value = in_le32(hose->cfg_data);
-
- if (len != 4) {
- value >>= ((offset & 0x3) << 3);
- value &= 0xffffffff >> (32 - (len << 3));
- }
- }
-
- *val = value;
-
- out_be32(hose->cfg_addr, 0);
- mb();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- u32 value, mask;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- out_be32(hose->cfg_addr,
- (1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
- (devfn << 8) |
- (offset & 0xfc));
- mb();
-
-#ifdef MPC5200_BUG_435_WORKAROUND
- if (bus->number != hose->bus_offset) {
- switch (len) {
- case 1:
- out_8(((u8 __iomem *)hose->cfg_data) +
- (offset & 3), val);
- break;
- case 2:
- out_le16(((u16 __iomem *)hose->cfg_data) +
- ((offset>>1) & 1), val);
- break;
-
- default:
- out_le16((u16 __iomem *)hose->cfg_data,
- (u16)val);
- out_le16(((u16 __iomem *)hose->cfg_data) + 1,
- (u16)(val>>16));
- break;
- }
- }
- else
-#endif
- {
- if (len != 4) {
- value = in_le32(hose->cfg_data);
-
- offset = (offset & 0x3) << 3;
- mask = (0xffffffff >> (32 - (len << 3)));
- mask <<= offset;
-
- value &= ~mask;
- val = value | ((val << offset) & mask);
- }
-
- out_le32(hose->cfg_data, val);
- }
- mb();
-
- out_be32(hose->cfg_addr, 0);
- mb();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops mpc52xx_pci_ops = {
- .read = mpc52xx_pci_read_config,
- .write = mpc52xx_pci_write_config
-};
-
-
-static void __init
-mpc52xx_pci_setup(struct pci_controller *hose,
- struct mpc52xx_pci __iomem *pci_regs)
-{
- struct resource *res;
- u32 tmp;
- int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
-
- pr_debug("mpc52xx_pci_setup()\n");
-
- pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
- in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
- in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
- pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
- in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
- in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
-
- /* Setup control regs */
- tmp = in_be32(&pci_regs->scr);
- tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
- out_be32(&pci_regs->scr, tmp);
-
- /* Setup windows */
- res = &hose->mem_resources[0];
- if (res->flags) {
- pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
- res->start, res->end, res->flags);
- out_be32(&pci_regs->iw0btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
- iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
- if (res->flags & IORESOURCE_PREFETCH)
- iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
- else
- iwcr0 |= MPC52xx_PCI_IWCR_READ;
- }
-
- res = &hose->mem_resources[1];
- if (res->flags) {
- pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
- res->start, res->end, res->flags);
- out_be32(&pci_regs->iw1btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
- iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
- if (res->flags & IORESOURCE_PREFETCH)
- iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
- else
- iwcr1 |= MPC52xx_PCI_IWCR_READ;
- }
-
- res = &hose->io_resource;
- if (!res) {
- printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
- return;
- }
- pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
- ".io_base_phys=%lx\n",
- res->start, res->end, res->flags, hose->io_base_phys);
- out_be32(&pci_regs->iw2btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
- res->start,
- res->end - res->start + 1));
- iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
-
- pr_debug("iwcr0=%x iwcr1=%x iwcr2=%x iwcr=%x old_iwcr=%x\n",
- iwcr0, iwcr1, iwcr2,
- MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2),
- in_be32(&pci_regs->iwcr));
- out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
-
- out_be32(&pci_regs->tbatr0,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
- out_be32(&pci_regs->tbatr1,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
-
- out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
-
- /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
- /* Not necessary and can be a bad thing if for example the bootloader
- is displaying a splash screen or ... Just left here for
- documentation purpose if anyone need it */
- tmp = in_be32(&pci_regs->gscr);
-#if 0
- out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
- udelay(50);
-#endif
- out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
-
- pr_debug("iw0btar=%x iw1btar=%x iw2btar=%x iwcr=%x\n",
- in_be32(&pci_regs->iw0btar), in_be32(&pci_regs->iw1btar),
- in_be32(&pci_regs->iw2btar), in_be32(&pci_regs->iwcr));
- pr_debug("tbatr0=%x tbatr1=%x tcr=%x gscr=%x\n",
- in_be32(&pci_regs->tbatr0), in_be32(&pci_regs->tbatr1),
- in_be32(&pci_regs->tcr), in_be32(&pci_regs->gscr));
-}
-
-static void
-mpc52xx_pci_fixup_resources(struct pci_dev *dev)
-{
- int i;
-
- pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
- dev->vendor, dev->device);
-
- /* We don't rely on boot loader for PCI and resets all
- devices */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = &dev->resource[i];
- if (res->end > res->start) { /* Only valid resources */
- res->end -= res->start;
- res->start = 0;
- res->flags |= IORESOURCE_UNSET;
- }
- }
-
- /* The PCI Host bridge of MPC52xx has a prefetch memory resource
- fixed to 1Gb. Doesn't fit in the resource system so we remove it */
- if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
- ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
- || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
- struct resource *res = &dev->resource[1];
- res->start = res->end = res->flags = 0;
- }
-}
-
-int __init
-mpc52xx_add_bridge(struct device_node *node)
-{
- int len;
- struct mpc52xx_pci __iomem *pci_regs;
- struct pci_controller *hose;
- const int *bus_range;
- struct resource rsrc;
-
- pr_debug("Adding PCI host bridge %s\n", node->full_name);
-
- pci_assign_all_buses = 1;
-
- if (of_address_to_resource(node, 0, &rsrc) != 0) {
- printk(KERN_ERR "Can't get %s resources\n", node->full_name);
- return -EINVAL;
- }
-
- bus_range = get_property(node, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get bus-range for %s, assume"
- " bus 0\n", node->full_name);
- }
-
- hose = pcibios_alloc_controller();
- if (!hose)
- return -ENOMEM;
-
- ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
-
- hose->arch_data = node;
- hose->set_cfg_type = 1;
-
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- hose->bus_offset = 0;
- hose->ops = &mpc52xx_pci_ops;
-
- pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
- if (!pci_regs)
- return -ENOMEM;
-
- pci_process_bridge_OF_ranges(hose, node, 0);
-
- hose->cfg_addr = &pci_regs->car;
-
- hose->cfg_data = hose->io_base_virt;
- hose->io_base_virt = ioremap(hose->io_base_phys,
- hose->io_resource.end + 1 -
- hose->io_resource.start);
- isa_io_base = (unsigned long) hose->io_base_virt;
-
- mpc52xx_pci_setup(hose, pci_regs);
-
- return 0;
-}
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.h b/arch/powerpc/platforms/52xx/mpc52xx_pci.h
deleted file mode 100644
index 07a659e..0000000
--- a/arch/powerpc/platforms/52xx/mpc52xx_pci.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * PCI Include file the Freescale MPC52xx embedded cpu chips
- *
- * Inspired from code written by Dale Farnsworth <dfarnsworth@mvista.com>
- * for the 2.4 kernel.
- *
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
- * Copyright (C) 2003 MontaVista, Software, Inc.
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#ifndef __SYSLIB_MPC52xx_PCI_H__
-#define __SYSLIB_MPC52xx_PCI_H__
-
-/* ======================================================================== */
-/* PCI windows config */
-/* ======================================================================== */
-
-#define MPC52xx_PCI_TARGET_IO 0xf0000000
-#define MPC52xx_PCI_TARGET_MEM 0x00000000
-
-
-/* ======================================================================== */
-/* Structures mapping & Defines for PCI Unit */
-/* ======================================================================== */
-
-#define MPC52xx_PCI_GSCR_BM 0x40000000
-#define MPC52xx_PCI_GSCR_PE 0x20000000
-#define MPC52xx_PCI_GSCR_SE 0x10000000
-#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
-#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
-#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
-#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
-#define MPC52xx_PCI_GSCR_BME 0x00004000
-#define MPC52xx_PCI_GSCR_PEE 0x00002000
-#define MPC52xx_PCI_GSCR_SEE 0x00001000
-#define MPC52xx_PCI_GSCR_PR 0x00000001
-
-
-#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
- ( ( (proc_ad) & 0xff000000 ) | \
- ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
- ( ((pci_ad) >> 16) & 0x0000ff00 ) )
-
-#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
- ((win1) << 16) | \
- ((win2) << 8))
-
-#define MPC52xx_PCI_IWCR_DISABLE 0x0
-#define MPC52xx_PCI_IWCR_ENABLE 0x1
-#define MPC52xx_PCI_IWCR_READ 0x0
-#define MPC52xx_PCI_IWCR_READ_LINE 0x2
-#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
-#define MPC52xx_PCI_IWCR_MEM 0x0
-#define MPC52xx_PCI_IWCR_IO 0x8
-
-#define MPC52xx_PCI_TCR_P 0x01000000
-#define MPC52xx_PCI_TCR_LD 0x00010000
-
-#define MPC52xx_PCI_TBATR_DISABLE 0x0
-#define MPC52xx_PCI_TBATR_ENABLE 0x1
-
-
-#ifndef __ASSEMBLY__
-
-struct mpc52xx_pci {
- u32 idr; /* PCI + 0x00 */
- u32 scr; /* PCI + 0x04 */
- u32 ccrir; /* PCI + 0x08 */
- u32 cr1; /* PCI + 0x0C */
- u32 bar0; /* PCI + 0x10 */
- u32 bar1; /* PCI + 0x14 */
- u8 reserved1[16]; /* PCI + 0x18 */
- u32 ccpr; /* PCI + 0x28 */
- u32 sid; /* PCI + 0x2C */
- u32 erbar; /* PCI + 0x30 */
- u32 cpr; /* PCI + 0x34 */
- u8 reserved2[4]; /* PCI + 0x38 */
- u32 cr2; /* PCI + 0x3C */
- u8 reserved3[32]; /* PCI + 0x40 */
- u32 gscr; /* PCI + 0x60 */
- u32 tbatr0; /* PCI + 0x64 */
- u32 tbatr1; /* PCI + 0x68 */
- u32 tcr; /* PCI + 0x6C */
- u32 iw0btar; /* PCI + 0x70 */
- u32 iw1btar; /* PCI + 0x74 */
- u32 iw2btar; /* PCI + 0x78 */
- u8 reserved4[4]; /* PCI + 0x7C */
- u32 iwcr; /* PCI + 0x80 */
- u32 icr; /* PCI + 0x84 */
- u32 isr; /* PCI + 0x88 */
- u32 arb; /* PCI + 0x8C */
- u8 reserved5[104]; /* PCI + 0x90 */
- u32 car; /* PCI + 0xF8 */
- u8 reserved6[4]; /* PCI + 0xFC */
-};
-
-#endif /* __ASSEMBLY__ */
-
-
-#endif /* __SYSLIB_MPC52xx_PCI_H__ */
diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
new file mode 100644
index 0000000..14940af
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/pci.c
@@ -0,0 +1,404 @@
+/*
+ * PCI code for the Freescale MPC52xx embedded CPU.
+ *
+ * Copyright (C) 2004 Secret Lab Technologies Ltd.
+ * Grant Likely <grant.likely@secretlab.ca>
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#undef DEBUG
+
+#include <asm/pci.h>
+#include <asm/mpc52xx.h>
+#include <asm/delay.h>
+#include <asm/machdep.h>
+#include <linux/kernel.h>
+
+
+/* ======================================================================== */
+/* PCI windows config */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_TARGET_IO 0xf0000000
+#define MPC52xx_PCI_TARGET_MEM 0x00000000
+
+/* ======================================================================== */
+/* Structures mapping & Defines for PCI Unit */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_GSCR_BM 0x40000000
+#define MPC52xx_PCI_GSCR_PE 0x20000000
+#define MPC52xx_PCI_GSCR_SE 0x10000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
+#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
+#define MPC52xx_PCI_GSCR_BME 0x00004000
+#define MPC52xx_PCI_GSCR_PEE 0x00002000
+#define MPC52xx_PCI_GSCR_SEE 0x00001000
+#define MPC52xx_PCI_GSCR_PR 0x00000001
+
+
+#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
+ ( ( (proc_ad) & 0xff000000 ) | \
+ ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
+ ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+
+#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+ ((win1) << 16) | \
+ ((win2) << 8))
+
+#define MPC52xx_PCI_IWCR_DISABLE 0x0
+#define MPC52xx_PCI_IWCR_ENABLE 0x1
+#define MPC52xx_PCI_IWCR_READ 0x0
+#define MPC52xx_PCI_IWCR_READ_LINE 0x2
+#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
+#define MPC52xx_PCI_IWCR_MEM 0x0
+#define MPC52xx_PCI_IWCR_IO 0x8
+
+#define MPC52xx_PCI_TCR_P 0x01000000
+#define MPC52xx_PCI_TCR_LD 0x00010000
+
+#define MPC52xx_PCI_TBATR_DISABLE 0x0
+#define MPC52xx_PCI_TBATR_ENABLE 0x1
+
+struct mpc52xx_pci {
+ u32 idr; /* PCI + 0x00 */
+ u32 scr; /* PCI + 0x04 */
+ u32 ccrir; /* PCI + 0x08 */
+ u32 cr1; /* PCI + 0x0C */
+ u32 bar0; /* PCI + 0x10 */
+ u32 bar1; /* PCI + 0x14 */
+ u8 reserved1[16]; /* PCI + 0x18 */
+ u32 ccpr; /* PCI + 0x28 */
+ u32 sid; /* PCI + 0x2C */
+ u32 erbar; /* PCI + 0x30 */
+ u32 cpr; /* PCI + 0x34 */
+ u8 reserved2[4]; /* PCI + 0x38 */
+ u32 cr2; /* PCI + 0x3C */
+ u8 reserved3[32]; /* PCI + 0x40 */
+ u32 gscr; /* PCI + 0x60 */
+ u32 tbatr0; /* PCI + 0x64 */
+ u32 tbatr1; /* PCI + 0x68 */
+ u32 tcr; /* PCI + 0x6C */
+ u32 iw0btar; /* PCI + 0x70 */
+ u32 iw1btar; /* PCI + 0x74 */
+ u32 iw2btar; /* PCI + 0x78 */
+ u8 reserved4[4]; /* PCI + 0x7C */
+ u32 iwcr; /* PCI + 0x80 */
+ u32 icr; /* PCI + 0x84 */
+ u32 isr; /* PCI + 0x88 */
+ u32 arb; /* PCI + 0x8C */
+ u8 reserved5[104]; /* PCI + 0x90 */
+ u32 car; /* PCI + 0xF8 */
+ u8 reserved6[4]; /* PCI + 0xFC */
+};
+
+static int
+mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+ if (bus->number != hose->bus_offset) {
+ /* workaround for the bug 435 of the MPC5200 (L25R);
+ * Don't do 32 bits config access during type-1 cycles */
+ switch (len) {
+ case 1:
+ value = in_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3));
+ break;
+ case 2:
+ value = in_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1));
+ break;
+
+ default:
+ value = in_le16((u16 __iomem *)hose->cfg_data) |
+ (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+ break;
+ }
+ }
+ else
+#endif
+ {
+ value = in_le32(hose->cfg_data);
+
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
+ }
+
+ *val = value;
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value, mask;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+ if (bus->number != hose->bus_offset) {
+ /* workaround for the bug 435 of the MPC5200 (L25R);
+ * Don't do 32 bits config access during type-1 cycles */
+ switch (len) {
+ case 1:
+ out_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3), val);
+ break;
+ case 2:
+ out_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1), val);
+ break;
+
+ default:
+ out_le16((u16 __iomem *)hose->cfg_data,
+ (u16)val);
+ out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+ (u16)(val>>16));
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
+
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
+
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
+
+ out_le32(hose->cfg_data, val);
+ }
+ mb();
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc52xx_pci_ops = {
+ .read = mpc52xx_pci_read_config,
+ .write = mpc52xx_pci_write_config
+};
+
+
+static void __init
+mpc52xx_pci_setup(struct pci_controller *hose,
+ struct mpc52xx_pci __iomem *pci_regs)
+{
+ struct resource *res;
+ u32 tmp;
+ int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
+
+ pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
+
+ /* pci_process_bridge_OF_ranges() found all our addresses for us;
+ * now store them in the right places */
+ hose->cfg_addr = &pci_regs->car;
+ hose->cfg_data = hose->io_base_virt;
+ hose->io_base_virt = ioremap(hose->io_base_phys,
+ hose->io_resource.end + 1 -
+ hose->io_resource.start);
+ isa_io_base = (unsigned long) hose->io_base_virt;
+
+ /* Control regs */
+ tmp = in_be32(&pci_regs->scr);
+ tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ out_be32(&pci_regs->scr, tmp);
+
+ /* Memory windows */
+ res = &hose->mem_resources[0];
+ if (res->flags) {
+ pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw0btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr0 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ res = &hose->mem_resources[1];
+ if (res->flags) {
+ pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw1btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr1 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ /* IO resources */
+ res = &hose->io_resource;
+ if (!res) {
+ printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
+ return;
+ }
+ pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+ ".io_base_phys=%lx\n",
+ res->start, res->end, res->flags, hose->io_base_phys);
+ out_be32(&pci_regs->iw2btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+ res->start,
+ res->end - res->start + 1));
+ iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
+
+ /* Set all the IWCR fields at once; they're in the same reg */
+ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
+
+ out_be32(&pci_regs->tbatr0,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+ out_be32(&pci_regs->tbatr1,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+
+ out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+
+#if 0
+ /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+ /* Not necessary and can be a bad thing if for example the bootloader
+ is displaying a splash screen or ... Just left here for
+ documentation purpose if anyone need it */
+ tmp = in_be32(&pci_regs->gscr);
+ out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+ udelay(50);
+ out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
+#endif
+}
+
+static void
+mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
+ dev->vendor, dev->device);
+
+ /* We don't rely on boot loader for PCI and resets all
+ devices */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = &dev->resource[i];
+ if (res->end > res->start) { /* Only valid resources */
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ }
+ }
+
+ /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+ fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+ if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+ || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
+ struct resource *res = &dev->resource[1];
+ res->start = res->end = res->flags = 0;
+ }
+}
+
+int __init
+mpc52xx_add_bridge(struct device_node *node)
+{
+ int len;
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+ const int *bus_range;
+ struct resource rsrc;
+
+ pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
+
+ pci_assign_all_buses = 1;
+
+ if (of_address_to_resource(node, 0, &rsrc) != 0) {
+ printk(KERN_ERR "Can't get %s resources\n", node->full_name);
+ return -EINVAL;
+ }
+
+ bus_range = get_property(node, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
+ node->full_name);
+ bus_range = NULL;
+ }
+
+ /* There are some PCI quirks on the 52xx, register the hook to
+ * fix them. */
+ ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+
+ /* Alloc and initialize the pci controller. Values in the device
+ * tree are needed to configure the 52xx PCI controller. Rather
+ * than parse the tree here, let pci_process_bridge_OF_ranges()
+ * do it for us and extract the values after the fact */
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return -ENOMEM;
+
+ hose->arch_data = node;
+ hose->set_cfg_type = 1;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ hose->bus_offset = 0;
+ hose->ops = &mpc52xx_pci_ops;
+
+ pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ if (!pci_regs)
+ return -ENOMEM;
+
+ pci_process_bridge_OF_ranges(hose, node, 0);
+
+ /* Finish setting up PCI using values obtained by
+ * pci_proces_bridge_OF_ranges */
+ mpc52xx_pci_setup(hose, pci_regs);
+
+ return 0;
+}
--
1.4.4.2

View File

@ -0,0 +1,28 @@
From 5145742e15b45e96c623f571dee421306dc95a3e Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 11 Dec 2006 22:45:39 -0700
Subject: [PATCH] [POWERPC] Change name of mpc52xx pci support file in Makefile
Oops, missed a bit in the previous patch
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/platforms/52xx/Makefile | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index d85ea04..a7c646a 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -3,7 +3,7 @@
#
ifeq ($(CONFIG_PPC_MERGE),y)
obj-y += mpc52xx_pic.o mpc52xx_common.o
-obj-$(CONFIG_PCI) += mpc52xx_pci.o
+obj-$(CONFIG_PCI) += pci.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm.o
obj-$(CONFIG_FEC_MPC52xx) += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
endif
--
1.4.4.2

View File

@ -0,0 +1,47 @@
From 2086d309f8b8de0b41119596d43f2a7bfe028a89 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 11 Dec 2006 22:46:59 -0700
Subject: [PATCH] [POWERPC] Change link order so mpc52xx-fec always shows up as eth0
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
drivers/net/Makefile | 2 +-
drivers/net/fec_mpc52xx/fec.c | 2 ++
2 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index e6f903d..95f0963 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -24,6 +24,7 @@ ucc_geth_driver-objs := ucc_geth.o ucc_geth_phy.o
obj-$(CONFIG_PLIP) += plip.o
obj-$(CONFIG_ROADRUNNER) += rrunner.o
+obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
obj-$(CONFIG_HAPPYMEAL) += sunhme.o
obj-$(CONFIG_SUNLANCE) += sunlance.o
@@ -196,7 +197,6 @@ obj-$(CONFIG_SMC91X) += smc91x.o
obj-$(CONFIG_SMC911X) += smc911x.o
obj-$(CONFIG_DM9000) += dm9000.o
obj-$(CONFIG_FEC_8XX) += fec_8xx/
-obj-$(CONFIG_FEC_MPC52xx) += fec_mpc52xx/
obj-$(CONFIG_MACB) += macb.o
diff --git a/drivers/net/fec_mpc52xx/fec.c b/drivers/net/fec_mpc52xx/fec.c
index 894da79..30cef2b 100644
--- a/drivers/net/fec_mpc52xx/fec.c
+++ b/drivers/net/fec_mpc52xx/fec.c
@@ -731,6 +731,8 @@ mpc52xx_fec_probe(struct device *dev)
fec_mii_init(ndev);
/* We're done ! */
+ printk(KERN_INFO "%s: mpc52xx-fec at %#lx,",
+ ndev->name, (long)mem->start);
#if defined(CONFIG_PPC_MERGE)
dev_set_drvdata(&op->dev, ndev);
#else
--
1.4.4.2

View File

@ -0,0 +1,28 @@
From 08bb999d4f8b866a570775db5788cd84edafd3f5 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 11 Dec 2006 23:00:24 -0700
Subject: [PATCH] [POWERPC] Fixup pr_print format for mpc52xx pci support
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/platforms/52xx/pci.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
index 14940af..b732fdc 100644
--- a/arch/powerpc/platforms/52xx/pci.c
+++ b/arch/powerpc/platforms/52xx/pci.c
@@ -285,8 +285,8 @@ mpc52xx_pci_setup(struct pci_controller *hose,
return;
}
pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
- ".io_base_phys=%lx\n",
- res->start, res->end, res->flags, hose->io_base_phys);
+ ".io_base_phys=0x%p\n",
+ res->start, res->end, res->flags, (void*)hose->io_base_phys);
out_be32(&pci_regs->iw2btar,
MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
res->start,
--
1.4.4.2

View File

@ -0,0 +1,871 @@
From 56aad819c662c854466a8c454c948e79dd2f0777 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Mon, 11 Dec 2006 23:23:40 -0700
Subject: [PATCH] [POWERPC] Add mpc52xx/lite5200 PCI support
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
arch/powerpc/platforms/52xx/Makefile | 2 +-
arch/powerpc/platforms/52xx/lite5200.c | 3 -
arch/powerpc/platforms/52xx/mpc52xx_pci.c | 412 +++++++++++++++++++++++++++++
arch/powerpc/platforms/52xx/pci.c | 404 ----------------------------
4 files changed, 413 insertions(+), 408 deletions(-)
diff --git a/arch/powerpc/platforms/52xx/Makefile b/arch/powerpc/platforms/52xx/Makefile
index a7c646a..d85ea04 100644
--- a/arch/powerpc/platforms/52xx/Makefile
+++ b/arch/powerpc/platforms/52xx/Makefile
@@ -3,7 +3,7 @@
#
ifeq ($(CONFIG_PPC_MERGE),y)
obj-y += mpc52xx_pic.o mpc52xx_common.o
-obj-$(CONFIG_PCI) += pci.o
+obj-$(CONFIG_PCI) += mpc52xx_pci.o
obj-$(CONFIG_PPC_BESTCOMM) += bestcomm.o
obj-$(CONFIG_FEC_MPC52xx) += sdma_fec_rx_task.o sdma_fec_tx_task.o fec.o
endif
diff --git a/arch/powerpc/platforms/52xx/lite5200.c b/arch/powerpc/platforms/52xx/lite5200.c
index f1bbe24..cdb16bf 100644
--- a/arch/powerpc/platforms/52xx/lite5200.c
+++ b/arch/powerpc/platforms/52xx/lite5200.c
@@ -111,9 +111,6 @@ static void __init lite52xx_setup_arch(void)
np = of_find_node_by_type(np, "pci");
if (np)
mpc52xx_add_bridge(np);
-
- //ppc_md.pci_swizzle = common_swizzle;
- //ppc_md.pci_exclude_device = mpc52xx_exclude_device;
#endif
#ifdef CONFIG_BLK_DEV_INITRD
diff --git a/arch/powerpc/platforms/52xx/mpc52xx_pci.c b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
new file mode 100644
index 0000000..faf161b
--- /dev/null
+++ b/arch/powerpc/platforms/52xx/mpc52xx_pci.c
@@ -0,0 +1,412 @@
+/*
+ * PCI code for the Freescale MPC52xx embedded CPU.
+ *
+ * Copyright (C) 2006 Secret Lab Technologies Ltd.
+ * Grant Likely <grant.likely@secretlab.ca>
+ * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#undef DEBUG
+
+#include <asm/pci.h>
+#include <asm/mpc52xx.h>
+#include <asm/delay.h>
+#include <asm/machdep.h>
+#include <linux/kernel.h>
+
+
+/* ======================================================================== */
+/* PCI windows config */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_TARGET_IO 0xf0000000
+#define MPC52xx_PCI_TARGET_MEM 0x00000000
+
+
+/* ======================================================================== */
+/* Structures mapping & Defines for PCI Unit */
+/* ======================================================================== */
+
+#define MPC52xx_PCI_GSCR_BM 0x40000000
+#define MPC52xx_PCI_GSCR_PE 0x20000000
+#define MPC52xx_PCI_GSCR_SE 0x10000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
+#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
+#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
+#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
+#define MPC52xx_PCI_GSCR_BME 0x00004000
+#define MPC52xx_PCI_GSCR_PEE 0x00002000
+#define MPC52xx_PCI_GSCR_SEE 0x00001000
+#define MPC52xx_PCI_GSCR_PR 0x00000001
+
+
+#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
+ ( ( (proc_ad) & 0xff000000 ) | \
+ ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
+ ( ((pci_ad) >> 16) & 0x0000ff00 ) )
+
+#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
+ ((win1) << 16) | \
+ ((win2) << 8))
+
+#define MPC52xx_PCI_IWCR_DISABLE 0x0
+#define MPC52xx_PCI_IWCR_ENABLE 0x1
+#define MPC52xx_PCI_IWCR_READ 0x0
+#define MPC52xx_PCI_IWCR_READ_LINE 0x2
+#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
+#define MPC52xx_PCI_IWCR_MEM 0x0
+#define MPC52xx_PCI_IWCR_IO 0x8
+
+#define MPC52xx_PCI_TCR_P 0x01000000
+#define MPC52xx_PCI_TCR_LD 0x00010000
+
+#define MPC52xx_PCI_TBATR_DISABLE 0x0
+#define MPC52xx_PCI_TBATR_ENABLE 0x1
+
+struct mpc52xx_pci {
+ u32 idr; /* PCI + 0x00 */
+ u32 scr; /* PCI + 0x04 */
+ u32 ccrir; /* PCI + 0x08 */
+ u32 cr1; /* PCI + 0x0C */
+ u32 bar0; /* PCI + 0x10 */
+ u32 bar1; /* PCI + 0x14 */
+ u8 reserved1[16]; /* PCI + 0x18 */
+ u32 ccpr; /* PCI + 0x28 */
+ u32 sid; /* PCI + 0x2C */
+ u32 erbar; /* PCI + 0x30 */
+ u32 cpr; /* PCI + 0x34 */
+ u8 reserved2[4]; /* PCI + 0x38 */
+ u32 cr2; /* PCI + 0x3C */
+ u8 reserved3[32]; /* PCI + 0x40 */
+ u32 gscr; /* PCI + 0x60 */
+ u32 tbatr0; /* PCI + 0x64 */
+ u32 tbatr1; /* PCI + 0x68 */
+ u32 tcr; /* PCI + 0x6C */
+ u32 iw0btar; /* PCI + 0x70 */
+ u32 iw1btar; /* PCI + 0x74 */
+ u32 iw2btar; /* PCI + 0x78 */
+ u8 reserved4[4]; /* PCI + 0x7C */
+ u32 iwcr; /* PCI + 0x80 */
+ u32 icr; /* PCI + 0x84 */
+ u32 isr; /* PCI + 0x88 */
+ u32 arb; /* PCI + 0x8C */
+ u8 reserved5[104]; /* PCI + 0x90 */
+ u32 car; /* PCI + 0xF8 */
+ u8 reserved6[4]; /* PCI + 0xFC */
+};
+
+
+/* ======================================================================== */
+/* PCI configuration acess */
+/* ======================================================================== */
+
+static int
+mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 *val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+ if (bus->number != hose->bus_offset) {
+ /* workaround for the bug 435 of the MPC5200 (L25R);
+ * Don't do 32 bits config access during type-1 cycles */
+ switch (len) {
+ case 1:
+ value = in_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3));
+ break;
+ case 2:
+ value = in_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1));
+ break;
+
+ default:
+ value = in_le16((u16 __iomem *)hose->cfg_data) |
+ (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
+ break;
+ }
+ }
+ else
+#endif
+ {
+ value = in_le32(hose->cfg_data);
+
+ if (len != 4) {
+ value >>= ((offset & 0x3) << 3);
+ value &= 0xffffffff >> (32 - (len << 3));
+ }
+ }
+
+ *val = value;
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
+ int offset, int len, u32 val)
+{
+ struct pci_controller *hose = bus->sysdata;
+ u32 value, mask;
+
+ if (ppc_md.pci_exclude_device)
+ if (ppc_md.pci_exclude_device(bus->number, devfn))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ out_be32(hose->cfg_addr,
+ (1 << 31) |
+ ((bus->number - hose->bus_offset) << 16) |
+ (devfn << 8) |
+ (offset & 0xfc));
+ mb();
+
+#if defined(CONFIG_PPC_MPC5200_BUGFIX)
+ if (bus->number != hose->bus_offset) {
+ /* workaround for the bug 435 of the MPC5200 (L25R);
+ * Don't do 32 bits config access during type-1 cycles */
+ switch (len) {
+ case 1:
+ out_8(((u8 __iomem *)hose->cfg_data) +
+ (offset & 3), val);
+ break;
+ case 2:
+ out_le16(((u16 __iomem *)hose->cfg_data) +
+ ((offset>>1) & 1), val);
+ break;
+
+ default:
+ out_le16((u16 __iomem *)hose->cfg_data,
+ (u16)val);
+ out_le16(((u16 __iomem *)hose->cfg_data) + 1,
+ (u16)(val>>16));
+ break;
+ }
+ }
+ else
+#endif
+ {
+ if (len != 4) {
+ value = in_le32(hose->cfg_data);
+
+ offset = (offset & 0x3) << 3;
+ mask = (0xffffffff >> (32 - (len << 3)));
+ mask <<= offset;
+
+ value &= ~mask;
+ val = value | ((val << offset) & mask);
+ }
+
+ out_le32(hose->cfg_data, val);
+ }
+ mb();
+
+ out_be32(hose->cfg_addr, 0);
+ mb();
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops mpc52xx_pci_ops = {
+ .read = mpc52xx_pci_read_config,
+ .write = mpc52xx_pci_write_config
+};
+
+
+/* ======================================================================== */
+/* PCI setup */
+/* ======================================================================== */
+
+static void __init
+mpc52xx_pci_setup(struct pci_controller *hose,
+ struct mpc52xx_pci __iomem *pci_regs)
+{
+ struct resource *res;
+ u32 tmp;
+ int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
+
+ pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
+
+ /* pci_process_bridge_OF_ranges() found all our addresses for us;
+ * now store them in the right places */
+ hose->cfg_addr = &pci_regs->car;
+ hose->cfg_data = hose->io_base_virt;
+
+ /* Control regs */
+ tmp = in_be32(&pci_regs->scr);
+ tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
+ out_be32(&pci_regs->scr, tmp);
+
+ /* Memory windows */
+ res = &hose->mem_resources[0];
+ if (res->flags) {
+ pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw0btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr0 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ res = &hose->mem_resources[1];
+ if (res->flags) {
+ pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
+ res->start, res->end, res->flags);
+ out_be32(&pci_regs->iw1btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
+ res->end - res->start + 1));
+ iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
+ if (res->flags & IORESOURCE_PREFETCH)
+ iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
+ else
+ iwcr1 |= MPC52xx_PCI_IWCR_READ;
+ }
+
+ /* IO resources */
+ res = &hose->io_resource;
+ if (!res) {
+ printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
+ return;
+ }
+ pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
+ ".io_base_phys=0x%p\n",
+ res->start, res->end, res->flags, (void*)hose->io_base_phys);
+ out_be32(&pci_regs->iw2btar,
+ MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
+ res->start,
+ res->end - res->start + 1));
+ iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
+
+ /* Set all the IWCR fields at once; they're in the same reg */
+ out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
+
+ out_be32(&pci_regs->tbatr0,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
+ out_be32(&pci_regs->tbatr1,
+ MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
+
+ out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
+
+ tmp = in_be32(&pci_regs->gscr);
+#if 0
+ /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
+ /* Not necessary and can be a bad thing if for example the bootloader
+ is displaying a splash screen or ... Just left here for
+ documentation purpose if anyone need it */
+ out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
+ udelay(50);
+#endif
+
+ /* Make sure the PCI bridge is out of reset */
+ out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
+}
+
+static void
+mpc52xx_pci_fixup_resources(struct pci_dev *dev)
+{
+ int i;
+
+ pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
+ dev->vendor, dev->device);
+
+ /* We don't rely on boot loader for PCI and resets all
+ devices */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ struct resource *res = &dev->resource[i];
+ if (res->end > res->start) { /* Only valid resources */
+ res->end -= res->start;
+ res->start = 0;
+ res->flags |= IORESOURCE_UNSET;
+ }
+ }
+
+ /* The PCI Host bridge of MPC52xx has a prefetch memory resource
+ fixed to 1Gb. Doesn't fit in the resource system so we remove it */
+ if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
+ ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
+ || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
+ struct resource *res = &dev->resource[1];
+ res->start = res->end = res->flags = 0;
+ }
+}
+
+int __init
+mpc52xx_add_bridge(struct device_node *node)
+{
+ int len;
+ struct mpc52xx_pci __iomem *pci_regs;
+ struct pci_controller *hose;
+ const int *bus_range;
+ struct resource rsrc;
+
+ pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
+
+ pci_assign_all_buses = 1;
+
+ if (of_address_to_resource(node, 0, &rsrc) != 0) {
+ printk(KERN_ERR "Can't get %s resources\n", node->full_name);
+ return -EINVAL;
+ }
+
+ bus_range = get_property(node, "bus-range", &len);
+ if (bus_range == NULL || len < 2 * sizeof(int)) {
+ printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
+ node->full_name);
+ bus_range = NULL;
+ }
+
+ /* There are some PCI quirks on the 52xx, register the hook to
+ * fix them. */
+ ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
+
+ /* Alloc and initialize the pci controller. Values in the device
+ * tree are needed to configure the 52xx PCI controller. Rather
+ * than parse the tree here, let pci_process_bridge_OF_ranges()
+ * do it for us and extract the values after the fact */
+ hose = pcibios_alloc_controller();
+ if (!hose)
+ return -ENOMEM;
+
+ hose->arch_data = node;
+ hose->set_cfg_type = 1;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ hose->bus_offset = 0;
+ hose->ops = &mpc52xx_pci_ops;
+
+ pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
+ if (!pci_regs)
+ return -ENOMEM;
+
+ pci_process_bridge_OF_ranges(hose, node, 1);
+
+ /* Finish setting up PCI using values obtained by
+ * pci_proces_bridge_OF_ranges */
+ mpc52xx_pci_setup(hose, pci_regs);
+
+ return 0;
+}
diff --git a/arch/powerpc/platforms/52xx/pci.c b/arch/powerpc/platforms/52xx/pci.c
deleted file mode 100644
index b732fdc..0000000
--- a/arch/powerpc/platforms/52xx/pci.c
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * PCI code for the Freescale MPC52xx embedded CPU.
- *
- * Copyright (C) 2004 Secret Lab Technologies Ltd.
- * Grant Likely <grant.likely@secretlab.ca>
- * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com>
- *
- * This file is licensed under the terms of the GNU General Public License
- * version 2. This program is licensed "as is" without any warranty of any
- * kind, whether express or implied.
- */
-
-#undef DEBUG
-
-#include <asm/pci.h>
-#include <asm/mpc52xx.h>
-#include <asm/delay.h>
-#include <asm/machdep.h>
-#include <linux/kernel.h>
-
-
-/* ======================================================================== */
-/* PCI windows config */
-/* ======================================================================== */
-
-#define MPC52xx_PCI_TARGET_IO 0xf0000000
-#define MPC52xx_PCI_TARGET_MEM 0x00000000
-
-/* ======================================================================== */
-/* Structures mapping & Defines for PCI Unit */
-/* ======================================================================== */
-
-#define MPC52xx_PCI_GSCR_BM 0x40000000
-#define MPC52xx_PCI_GSCR_PE 0x20000000
-#define MPC52xx_PCI_GSCR_SE 0x10000000
-#define MPC52xx_PCI_GSCR_XLB2PCI_MASK 0x07000000
-#define MPC52xx_PCI_GSCR_XLB2PCI_SHIFT 24
-#define MPC52xx_PCI_GSCR_IPG2PCI_MASK 0x00070000
-#define MPC52xx_PCI_GSCR_IPG2PCI_SHIFT 16
-#define MPC52xx_PCI_GSCR_BME 0x00004000
-#define MPC52xx_PCI_GSCR_PEE 0x00002000
-#define MPC52xx_PCI_GSCR_SEE 0x00001000
-#define MPC52xx_PCI_GSCR_PR 0x00000001
-
-
-#define MPC52xx_PCI_IWBTAR_TRANSLATION(proc_ad,pci_ad,size) \
- ( ( (proc_ad) & 0xff000000 ) | \
- ( (((size) - 1) >> 8) & 0x00ff0000 ) | \
- ( ((pci_ad) >> 16) & 0x0000ff00 ) )
-
-#define MPC52xx_PCI_IWCR_PACK(win0,win1,win2) (((win0) << 24) | \
- ((win1) << 16) | \
- ((win2) << 8))
-
-#define MPC52xx_PCI_IWCR_DISABLE 0x0
-#define MPC52xx_PCI_IWCR_ENABLE 0x1
-#define MPC52xx_PCI_IWCR_READ 0x0
-#define MPC52xx_PCI_IWCR_READ_LINE 0x2
-#define MPC52xx_PCI_IWCR_READ_MULTI 0x4
-#define MPC52xx_PCI_IWCR_MEM 0x0
-#define MPC52xx_PCI_IWCR_IO 0x8
-
-#define MPC52xx_PCI_TCR_P 0x01000000
-#define MPC52xx_PCI_TCR_LD 0x00010000
-
-#define MPC52xx_PCI_TBATR_DISABLE 0x0
-#define MPC52xx_PCI_TBATR_ENABLE 0x1
-
-struct mpc52xx_pci {
- u32 idr; /* PCI + 0x00 */
- u32 scr; /* PCI + 0x04 */
- u32 ccrir; /* PCI + 0x08 */
- u32 cr1; /* PCI + 0x0C */
- u32 bar0; /* PCI + 0x10 */
- u32 bar1; /* PCI + 0x14 */
- u8 reserved1[16]; /* PCI + 0x18 */
- u32 ccpr; /* PCI + 0x28 */
- u32 sid; /* PCI + 0x2C */
- u32 erbar; /* PCI + 0x30 */
- u32 cpr; /* PCI + 0x34 */
- u8 reserved2[4]; /* PCI + 0x38 */
- u32 cr2; /* PCI + 0x3C */
- u8 reserved3[32]; /* PCI + 0x40 */
- u32 gscr; /* PCI + 0x60 */
- u32 tbatr0; /* PCI + 0x64 */
- u32 tbatr1; /* PCI + 0x68 */
- u32 tcr; /* PCI + 0x6C */
- u32 iw0btar; /* PCI + 0x70 */
- u32 iw1btar; /* PCI + 0x74 */
- u32 iw2btar; /* PCI + 0x78 */
- u8 reserved4[4]; /* PCI + 0x7C */
- u32 iwcr; /* PCI + 0x80 */
- u32 icr; /* PCI + 0x84 */
- u32 isr; /* PCI + 0x88 */
- u32 arb; /* PCI + 0x8C */
- u8 reserved5[104]; /* PCI + 0x90 */
- u32 car; /* PCI + 0xF8 */
- u8 reserved6[4]; /* PCI + 0xFC */
-};
-
-static int
-mpc52xx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 *val)
-{
- struct pci_controller *hose = bus->sysdata;
- u32 value;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- out_be32(hose->cfg_addr,
- (1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
- (devfn << 8) |
- (offset & 0xfc));
- mb();
-
-#if defined(CONFIG_PPC_MPC5200_BUGFIX)
- if (bus->number != hose->bus_offset) {
- /* workaround for the bug 435 of the MPC5200 (L25R);
- * Don't do 32 bits config access during type-1 cycles */
- switch (len) {
- case 1:
- value = in_8(((u8 __iomem *)hose->cfg_data) +
- (offset & 3));
- break;
- case 2:
- value = in_le16(((u16 __iomem *)hose->cfg_data) +
- ((offset>>1) & 1));
- break;
-
- default:
- value = in_le16((u16 __iomem *)hose->cfg_data) |
- (in_le16(((u16 __iomem *)hose->cfg_data) + 1) << 16);
- break;
- }
- }
- else
-#endif
- {
- value = in_le32(hose->cfg_data);
-
- if (len != 4) {
- value >>= ((offset & 0x3) << 3);
- value &= 0xffffffff >> (32 - (len << 3));
- }
- }
-
- *val = value;
-
- out_be32(hose->cfg_addr, 0);
- mb();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static int
-mpc52xx_pci_write_config(struct pci_bus *bus, unsigned int devfn,
- int offset, int len, u32 val)
-{
- struct pci_controller *hose = bus->sysdata;
- u32 value, mask;
-
- if (ppc_md.pci_exclude_device)
- if (ppc_md.pci_exclude_device(bus->number, devfn))
- return PCIBIOS_DEVICE_NOT_FOUND;
-
- out_be32(hose->cfg_addr,
- (1 << 31) |
- ((bus->number - hose->bus_offset) << 16) |
- (devfn << 8) |
- (offset & 0xfc));
- mb();
-
-#if defined(CONFIG_PPC_MPC5200_BUGFIX)
- if (bus->number != hose->bus_offset) {
- /* workaround for the bug 435 of the MPC5200 (L25R);
- * Don't do 32 bits config access during type-1 cycles */
- switch (len) {
- case 1:
- out_8(((u8 __iomem *)hose->cfg_data) +
- (offset & 3), val);
- break;
- case 2:
- out_le16(((u16 __iomem *)hose->cfg_data) +
- ((offset>>1) & 1), val);
- break;
-
- default:
- out_le16((u16 __iomem *)hose->cfg_data,
- (u16)val);
- out_le16(((u16 __iomem *)hose->cfg_data) + 1,
- (u16)(val>>16));
- break;
- }
- }
- else
-#endif
- {
- if (len != 4) {
- value = in_le32(hose->cfg_data);
-
- offset = (offset & 0x3) << 3;
- mask = (0xffffffff >> (32 - (len << 3)));
- mask <<= offset;
-
- value &= ~mask;
- val = value | ((val << offset) & mask);
- }
-
- out_le32(hose->cfg_data, val);
- }
- mb();
-
- out_be32(hose->cfg_addr, 0);
- mb();
-
- return PCIBIOS_SUCCESSFUL;
-}
-
-static struct pci_ops mpc52xx_pci_ops = {
- .read = mpc52xx_pci_read_config,
- .write = mpc52xx_pci_write_config
-};
-
-
-static void __init
-mpc52xx_pci_setup(struct pci_controller *hose,
- struct mpc52xx_pci __iomem *pci_regs)
-{
- struct resource *res;
- u32 tmp;
- int iwcr0 = 0, iwcr1 = 0, iwcr2 = 0;
-
- pr_debug("mpc52xx_pci_setup(hose=%p, pci_regs=%p)\n", hose, pci_regs);
-
- /* pci_process_bridge_OF_ranges() found all our addresses for us;
- * now store them in the right places */
- hose->cfg_addr = &pci_regs->car;
- hose->cfg_data = hose->io_base_virt;
- hose->io_base_virt = ioremap(hose->io_base_phys,
- hose->io_resource.end + 1 -
- hose->io_resource.start);
- isa_io_base = (unsigned long) hose->io_base_virt;
-
- /* Control regs */
- tmp = in_be32(&pci_regs->scr);
- tmp |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY;
- out_be32(&pci_regs->scr, tmp);
-
- /* Memory windows */
- res = &hose->mem_resources[0];
- if (res->flags) {
- pr_debug("mem_resource[0] = {.start=%x, .end=%x, .flags=%lx}\n",
- res->start, res->end, res->flags);
- out_be32(&pci_regs->iw0btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
- iwcr0 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
- if (res->flags & IORESOURCE_PREFETCH)
- iwcr0 |= MPC52xx_PCI_IWCR_READ_MULTI;
- else
- iwcr0 |= MPC52xx_PCI_IWCR_READ;
- }
-
- res = &hose->mem_resources[1];
- if (res->flags) {
- pr_debug("mem_resource[1] = {.start=%x, .end=%x, .flags=%lx}\n",
- res->start, res->end, res->flags);
- out_be32(&pci_regs->iw1btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(res->start, res->start,
- res->end - res->start + 1));
- iwcr1 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_MEM;
- if (res->flags & IORESOURCE_PREFETCH)
- iwcr1 |= MPC52xx_PCI_IWCR_READ_MULTI;
- else
- iwcr1 |= MPC52xx_PCI_IWCR_READ;
- }
-
- /* IO resources */
- res = &hose->io_resource;
- if (!res) {
- printk(KERN_ERR "%s: Didn't find IO resources\n", __FILE__);
- return;
- }
- pr_debug(".io_resource={.start=%x,.end=%x,.flags=%lx} "
- ".io_base_phys=0x%p\n",
- res->start, res->end, res->flags, (void*)hose->io_base_phys);
- out_be32(&pci_regs->iw2btar,
- MPC52xx_PCI_IWBTAR_TRANSLATION(hose->io_base_phys,
- res->start,
- res->end - res->start + 1));
- iwcr2 = MPC52xx_PCI_IWCR_ENABLE | MPC52xx_PCI_IWCR_IO;
-
- /* Set all the IWCR fields at once; they're in the same reg */
- out_be32(&pci_regs->iwcr, MPC52xx_PCI_IWCR_PACK(iwcr0, iwcr1, iwcr2));
-
- out_be32(&pci_regs->tbatr0,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_IO );
- out_be32(&pci_regs->tbatr1,
- MPC52xx_PCI_TBATR_ENABLE | MPC52xx_PCI_TARGET_MEM );
-
- out_be32(&pci_regs->tcr, MPC52xx_PCI_TCR_LD);
-
-#if 0
- /* Reset the exteral bus ( internal PCI controller is NOT resetted ) */
- /* Not necessary and can be a bad thing if for example the bootloader
- is displaying a splash screen or ... Just left here for
- documentation purpose if anyone need it */
- tmp = in_be32(&pci_regs->gscr);
- out_be32(&pci_regs->gscr, tmp | MPC52xx_PCI_GSCR_PR);
- udelay(50);
- out_be32(&pci_regs->gscr, tmp & ~MPC52xx_PCI_GSCR_PR);
-#endif
-}
-
-static void
-mpc52xx_pci_fixup_resources(struct pci_dev *dev)
-{
- int i;
-
- pr_debug("mpc52xx_pci_fixup_resources() %.4x:%.4x\n",
- dev->vendor, dev->device);
-
- /* We don't rely on boot loader for PCI and resets all
- devices */
- for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
- struct resource *res = &dev->resource[i];
- if (res->end > res->start) { /* Only valid resources */
- res->end -= res->start;
- res->start = 0;
- res->flags |= IORESOURCE_UNSET;
- }
- }
-
- /* The PCI Host bridge of MPC52xx has a prefetch memory resource
- fixed to 1Gb. Doesn't fit in the resource system so we remove it */
- if ( (dev->vendor == PCI_VENDOR_ID_MOTOROLA) &&
- ( dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200
- || dev->device == PCI_DEVICE_ID_MOTOROLA_MPC5200B) ) {
- struct resource *res = &dev->resource[1];
- res->start = res->end = res->flags = 0;
- }
-}
-
-int __init
-mpc52xx_add_bridge(struct device_node *node)
-{
- int len;
- struct mpc52xx_pci __iomem *pci_regs;
- struct pci_controller *hose;
- const int *bus_range;
- struct resource rsrc;
-
- pr_debug("Adding MPC52xx PCI host bridge %s\n", node->full_name);
-
- pci_assign_all_buses = 1;
-
- if (of_address_to_resource(node, 0, &rsrc) != 0) {
- printk(KERN_ERR "Can't get %s resources\n", node->full_name);
- return -EINVAL;
- }
-
- bus_range = get_property(node, "bus-range", &len);
- if (bus_range == NULL || len < 2 * sizeof(int)) {
- printk(KERN_WARNING "Can't get %s bus-range, assume bus 0\n",
- node->full_name);
- bus_range = NULL;
- }
-
- /* There are some PCI quirks on the 52xx, register the hook to
- * fix them. */
- ppc_md.pcibios_fixup_resources = mpc52xx_pci_fixup_resources;
-
- /* Alloc and initialize the pci controller. Values in the device
- * tree are needed to configure the 52xx PCI controller. Rather
- * than parse the tree here, let pci_process_bridge_OF_ranges()
- * do it for us and extract the values after the fact */
- hose = pcibios_alloc_controller();
- if (!hose)
- return -ENOMEM;
-
- hose->arch_data = node;
- hose->set_cfg_type = 1;
-
- hose->first_busno = bus_range ? bus_range[0] : 0;
- hose->last_busno = bus_range ? bus_range[1] : 0xff;
-
- hose->bus_offset = 0;
- hose->ops = &mpc52xx_pci_ops;
-
- pci_regs = ioremap(rsrc.start, rsrc.end - rsrc.start + 1);
- if (!pci_regs)
- return -ENOMEM;
-
- pci_process_bridge_OF_ranges(hose, node, 0);
-
- /* Finish setting up PCI using values obtained by
- * pci_proces_bridge_OF_ranges */
- mpc52xx_pci_setup(hose, pci_regs);
-
- return 0;
-}
--
1.4.4.2

View File

@ -0,0 +1,828 @@
From 46e8903e34759728afd11dd11c481e6a94e6b06d Mon Sep 17 00:00:00 2001
From: Sylvain Munaut <tnt@246tNt.com>
Date: Mon, 18 Dec 2006 22:51:38 +0100
Subject: [PATCH] [PATCH] sound: Add support for the MPC52xx PSC AC97 Link
Messy driver, to be cleaned ... a lot ...
Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
---
include/asm-ppc/mpc52xx_psc.h | 10 +-
sound/ppc/Kconfig | 16 +
sound/ppc/Makefile | 3 +
sound/ppc/mpc52xx_ac97.c | 738 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 765 insertions(+), 2 deletions(-)
diff --git a/include/asm-ppc/mpc52xx_psc.h b/include/asm-ppc/mpc52xx_psc.h
index 9d850b2..c82b8d4 100644
--- a/include/asm-ppc/mpc52xx_psc.h
+++ b/include/asm-ppc/mpc52xx_psc.h
@@ -28,6 +28,10 @@
#define MPC52xx_PSC_MAXNUM 6
/* Programmable Serial Controller (PSC) status register bits */
+#define MPC52xx_PSC_SR_UNEX_RX 0x0001
+#define MPC52xx_PSC_SR_DATA_VAL 0x0002
+#define MPC52xx_PSC_SR_DATA_OVR 0x0004
+#define MPC52xx_PSC_SR_CMDSEND 0x0008
#define MPC52xx_PSC_SR_CDE 0x0080
#define MPC52xx_PSC_SR_RXRDY 0x0100
#define MPC52xx_PSC_SR_RXFULL 0x0200
@@ -132,8 +136,10 @@ struct mpc52xx_psc {
u8 reserved5[3];
u8 ctlr; /* PSC + 0x1c */
u8 reserved6[3];
- u16 ccr; /* PSC + 0x20 */
- u8 reserved7[14];
+ u32 ccr; /* PSC + 0x20 */
+ u32 ac97_slots; /* PSC + 0x24 */
+ u32 ac97_cmd; /* PSC + 0x28 */
+ u32 ac97_data; /* PSC + 0x2c */
u8 ivr; /* PSC + 0x30 */
u8 reserved8[3];
u8 ip; /* PSC + 0x34 */
diff --git a/sound/ppc/Kconfig b/sound/ppc/Kconfig
index a3fb149..afd58f7 100644
--- a/sound/ppc/Kconfig
+++ b/sound/ppc/Kconfig
@@ -33,3 +33,19 @@ config SND_POWERMAC_AUTO_DRC
option.
endmenu
+
+
+# ALSA ppc drivers
+
+menu "ALSA PPC devices"
+ depends on SND!=n && PPC
+
+config SND_PPC_MPC52xx_AC97
+ tristate "Freescale MPC52xx AC97 interface support"
+ depends on SND && PPC_MPC52xx
+ select SND_AC97_CODEC
+ help
+ Say Y or M if you want to support any AC97 codec attached to
+ the Freescqle MPC52xx AC97 interface.
+
+endmenu
diff --git a/sound/ppc/Makefile b/sound/ppc/Makefile
index 4d95c65..c29cb9b 100644
--- a/sound/ppc/Makefile
+++ b/sound/ppc/Makefile
@@ -4,6 +4,9 @@
#
snd-powermac-objs := powermac.o pmac.o awacs.o burgundy.o daca.o tumbler.o keywest.o beep.o
+snd-mpc52xx-ac97-objs := mpc52xx_ac97.o
# Toplevel Module Dependency
obj-$(CONFIG_SND_POWERMAC) += snd-powermac.o
+
+obj-$(CONFIG_SND_PPC_MPC52xx_AC97) += snd-mpc52xx-ac97.o
diff --git a/sound/ppc/mpc52xx_ac97.c b/sound/ppc/mpc52xx_ac97.c
new file mode 100644
index 0000000..a4f008e
--- /dev/null
+++ b/sound/ppc/mpc52xx_ac97.c
@@ -0,0 +1,738 @@
+/*
+ * Driver for the PSC of the Freescale MPC52xx configured as AC97 interface
+ *
+ *
+ * Copyright (C) 2006 Sylvain Munaut <tnt@246tNt.com>
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+
+#define DEBUG
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+
+#include <sound/driver.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/ac97_codec.h>
+
+#include <asm/of_platform.h>
+#include <asm/mpc52xx_psc.h>
+
+
+#define DRV_NAME "mpc52xx-psc-ac97"
+
+
+/* ======================================================================== */
+/* Structs / Defines */
+/* ======================================================================== */
+
+/* Private structure */
+struct mpc52xx_ac97_priv {
+ struct device *dev;
+ resource_size_t mem_start;
+ resource_size_t mem_len;
+ int irq;
+ struct mpc52xx_psc __iomem *psc;
+ struct snd_card *card;
+ struct snd_pcm *pcm;
+ struct snd_ac97 *ac97;
+
+ struct snd_pcm_substream *substream_playback;
+ unsigned int buf_pos;
+};
+
+/* Register bit definition (AC97 mode specific) */
+#define PSC_AC97_SLOT_BIT(n) (1<<(12-n))
+#define PSC_AC97_SLOTS_XMIT_SHIFT 16
+#define PSC_AC97_SLOTS_RECV_SHIFT 0
+
+
+
+/* ======================================================================== */
+/* ISR routine */
+/* ======================================================================== */
+
+static irqreturn_t
+mpc52xx_ac97_irq(int irq, void *dev_id)
+{
+ struct mpc52xx_ac97_priv *priv = dev_id;
+
+ static int icnt = 0;
+ #if 0
+ {
+ unsigned int val;
+// val = in_be32(&priv->psc->ac97_data);
+ printk(KERN_INFO "mpc52xx_ac97_irq fired (isr=%04x, status=%04x) %08x\n", in_be16(&priv->psc->mpc52xx_psc_imr), in_be16(&priv->psc->mpc52xx_psc_status), val);
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
+ }
+ #endif
+
+ /* Anti Crash during dev ;) */
+ #if 0
+ if ((icnt++) > 50000)
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0);
+ #endif
+
+ /* Copy 64 data into the buffer */
+ if (in_be16(&priv->psc->mpc52xx_psc_imr) & 0x0100) {
+ if (priv->substream_playback) {
+ struct snd_pcm_runtime *rt;
+
+ rt = priv->substream_playback->runtime;
+
+ if (snd_pcm_playback_hw_avail(rt) < bytes_to_frames(rt,128)) {
+ int i;
+ /* Push silence */
+ for (i=0; i<64; i++)
+ out_be32(&priv->psc->mpc52xx_psc_buffer_32, 0x00000800);
+ printk(KERN_DEBUG "pushed silence ...\n");
+ } else {
+ int i;
+ unsigned short *data;
+
+ data = (unsigned short *)
+ (&rt->dma_area[frames_to_bytes(rt, priv->buf_pos)]);
+
+ for (i=0; i<64; i++)
+ out_be32(&priv->psc->mpc52xx_psc_buffer_32,
+ (((unsigned int)data[i]) << 16) | 0x00000000);
+ /* Setting the sof bit looks useless */
+
+ priv->buf_pos += bytes_to_frames(rt,128);;
+ if (priv->buf_pos >= rt->buffer_size)
+ priv->buf_pos = 0;
+
+ snd_pcm_period_elapsed(priv->substream_playback);
+ }
+ } else {
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0);
+ printk(KERN_DEBUG "Interrupt with no stream ...\n");
+ }
+ } else {
+ printk(KERN_ERR "Spurious int\n");
+ }
+
+ return IRQ_HANDLED;
+}
+
+
+/* ======================================================================== */
+/* PCM interface */
+/* ======================================================================== */
+
+/* HW desc */
+
+static struct snd_pcm_hardware mpc52xx_ac97_hw = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID,
+ .formats = SNDRV_PCM_FMTBIT_S16_BE,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .channels_min = 1,
+ .channels_max = 2, /* Support for more ? */
+ .buffer_bytes_max = 128*1024,
+ .period_bytes_min = 128, /* 32, */
+ .period_bytes_max = 128, /* 16*1024, */
+ .periods_min = 8,
+ .periods_max = 256,
+ .fifo_size = 512,
+};
+
+
+/* Playback */
+
+static int
+mpc52xx_ac97_playback_open(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+
+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_open(%p)\n", substream);
+
+ substream->runtime->hw = mpc52xx_ac97_hw;
+
+ priv->substream_playback = substream;
+ priv->buf_pos = 0; /* FIXME Do that where ? */
+
+ return 0; /* FIXME */
+}
+
+static int
+mpc52xx_ac97_playback_close(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_close(%p)\n", substream);
+ priv->substream_playback = NULL;
+ return 0; /* FIXME */
+}
+
+static int
+mpc52xx_ac97_playback_prepare(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+
+ dev_dbg(priv->dev, "mpc52xx_ac97_playback_prepare(%p)\n", substream);
+
+ /* FIXME, need a spinlock to protect access */
+ if (substream->runtime->channels == 1)
+ out_be32(&priv->psc->ac97_slots, 0x01000000);
+ else
+ out_be32(&priv->psc->ac97_slots, 0x03000000);
+
+ snd_ac97_set_rate(priv->ac97, AC97_PCM_FRONT_DAC_RATE, substream->runtime->rate);
+
+ return 0; /* FIXME */
+}
+
+
+/* Capture */
+
+static int
+mpc52xx_ac97_capture_open(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ return 0; /* FIXME */
+}
+
+static int
+mpc52xx_ac97_capture_close(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ return 0; /* FIXME */
+}
+
+static int
+mpc52xx_ac97_capture_prepare(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ return 0; /* FIXME */
+}
+
+
+/* Common */
+
+static int
+mpc52xx_ac97_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ int rv;
+
+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_params(%p)\n", substream);
+
+ rv = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(params));
+ if (rv < 0) {
+ printk(KERN_ERR "hw params failes\n"); /* FIXME */
+ return rv;
+ }
+
+ printk(KERN_DEBUG "%d %d %d\n", params_buffer_bytes(params), params_period_bytes(params), params_periods(params));
+
+
+ return 0;
+}
+
+static int
+mpc52xx_ac97_hw_free(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+
+ dev_dbg(priv->dev, "mpc52xx_ac97_hw_free(%p)\n", substream);
+
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int
+mpc52xx_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+ int rv = 0;
+
+ dev_dbg(priv->dev, "mpc52xx_ac97_trigger(%p,%d)\n", substream, cmd);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ /* Enable TX interrupt */
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0100); // 0x0100
+
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ /* Disable TX interrupt */
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
+
+ break;
+
+ default:
+ rv = -EINVAL;
+ }
+
+ /* FIXME */
+ return rv;
+}
+
+static snd_pcm_uframes_t
+mpc52xx_ac97_pointer(struct snd_pcm_substream *substream)
+{
+ struct mpc52xx_ac97_priv *priv = substream->pcm->private_data;
+
+// dev_dbg(priv->dev, "mpc52xx_ac97_pointer(%p)\n", substream);
+
+ if (substream->runtime->channels == 1)
+ return priv->buf_pos; /* FIXME */
+ else
+ return priv->buf_pos >> 1; /* FIXME */
+}
+
+
+/* Ops */
+
+static struct snd_pcm_ops mpc52xx_ac97_playback_ops = {
+ .open = mpc52xx_ac97_playback_open,
+ .close = mpc52xx_ac97_playback_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = mpc52xx_ac97_hw_params,
+ .hw_free = mpc52xx_ac97_hw_free,
+ .prepare = mpc52xx_ac97_playback_prepare,
+ .trigger = mpc52xx_ac97_trigger,
+ .pointer = mpc52xx_ac97_pointer,
+};
+
+static struct snd_pcm_ops mpc52xx_ac97_capture_ops = {
+ .open = mpc52xx_ac97_capture_open,
+ .close = mpc52xx_ac97_capture_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = mpc52xx_ac97_hw_params,
+ .hw_free = mpc52xx_ac97_hw_free,
+ .prepare = mpc52xx_ac97_capture_prepare,
+ .trigger = mpc52xx_ac97_trigger,
+ .pointer = mpc52xx_ac97_pointer,
+};
+
+
+/* ======================================================================== */
+/* AC97 Bus interface */
+/* ======================================================================== */
+
+static unsigned short
+mpc52xx_ac97_bus_read(struct snd_ac97 *ac97, unsigned short reg)
+{
+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
+ int timeout;
+ unsigned int val;
+
+ dev_dbg(priv->dev, "ac97 read: reg %04x\n", reg);
+
+ /* Wait for it to be ready */
+ timeout = 1000;
+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
+ MPC52xx_PSC_SR_CMDSEND) )
+ udelay(10);
+
+ if (!timeout) {
+ printk(KERN_ERR DRV_NAME ": timeout on ac97 bus (rdy)\n");
+ return 0xffff;
+ }
+
+ /* Do the read */
+ out_be32(&priv->psc->ac97_cmd, (1<<31) | ((reg & 0x7f) << 24));
+
+ /* Wait for the answer */
+ timeout = 1000;
+ while ((--timeout) && !(in_be16(&priv->psc->mpc52xx_psc_status) &
+ MPC52xx_PSC_SR_DATA_VAL) )
+ udelay(10);
+
+ if (!timeout) {
+ printk(KERN_ERR DRV_NAME ": timeout on ac97 read (val)\n");
+ return 0xffff;
+ }
+
+ /* Get the data */
+ val = in_be32(&priv->psc->ac97_data);
+ if ( ((val>>24) & 0x7f) != reg ) {
+ printk(KERN_ERR DRV_NAME ": reg echo error on ac97 read\n");
+ return 0xffff;
+ }
+ val = (val >> 8) & 0xffff;
+
+ dev_dbg(priv->dev, "ac97 read ok: reg %04x val %04x\n",
+ reg, val);
+
+ return (unsigned short) val;
+}
+
+static void
+mpc52xx_ac97_bus_write(struct snd_ac97 *ac97,
+ unsigned short reg, unsigned short val)
+{
+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
+ int timeout;
+
+ dev_dbg(priv->dev, "ac97 write: reg %04x val %04x\n",
+ reg, val);
+
+ /* Wait for it to be ready */
+ timeout = 1000;
+ while ((--timeout) && (in_be16(&priv->psc->mpc52xx_psc_status) &
+ MPC52xx_PSC_SR_CMDSEND) )
+ udelay(10);
+
+ if (!timeout) {
+ printk(KERN_ERR DRV_NAME ": timeout on ac97 write\n");
+ return;
+ }
+
+ /* Write data */
+ out_be32(&priv->psc->ac97_cmd, ((reg & 0x7f) << 24) | (val << 8));
+}
+
+static void
+mpc52xx_ac97_bus_reset(struct snd_ac97 *ac97)
+{
+ struct mpc52xx_ac97_priv *priv = ac97->private_data;
+
+ dev_dbg(priv->dev, "ac97 codec reset\n");
+
+ /* Do a cold reset */
+ out_8(&priv->psc->op1, 0x03);
+ udelay(10);
+ out_8(&priv->psc->op0, 0x02);
+ udelay(50);
+
+ /* PSC recover from cold reset (cfr user manual, not sure if useful) */
+ out_be32(&priv->psc->sicr, in_be32(&priv->psc->sicr));
+}
+
+
+static struct snd_ac97_bus_ops mpc52xx_ac97_bus_ops = {
+ .read = mpc52xx_ac97_bus_read,
+ .write = mpc52xx_ac97_bus_write,
+ .reset = mpc52xx_ac97_bus_reset,
+};
+
+
+/* ======================================================================== */
+/* Sound driver setup */
+/* ======================================================================== */
+
+static int
+mpc52xx_ac97_setup_pcm(struct mpc52xx_ac97_priv *priv)
+{
+ int rv;
+
+ rv = snd_pcm_new(priv->card, DRV_NAME "-pcm", 0, 1, 1, &priv->pcm);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": snd_pcm_new failed\n");
+ return rv;
+ }
+
+ rv = snd_pcm_lib_preallocate_pages_for_all(priv->pcm,
+ SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL),
+ 128*1024, 128*1024);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME
+ ": snd_pcm_lib_preallocate_pages_for_all failed\n");
+ return rv;
+ }
+
+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_PLAYBACK,
+ &mpc52xx_ac97_playback_ops);
+ snd_pcm_set_ops(priv->pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &mpc52xx_ac97_capture_ops);
+
+ priv->pcm->private_data = priv;
+ priv->pcm->info_flags = 0;
+
+ strcpy(priv->pcm->name, "Freescale MPC52xx PSC-AC97 PCM");
+
+ return 0;
+}
+
+static int
+mpc52xx_ac97_setup_mixer(struct mpc52xx_ac97_priv *priv)
+{
+ struct snd_ac97_bus *ac97_bus;
+ struct snd_ac97_template ac97_template;
+ int rv;
+
+ rv = snd_ac97_bus(priv->card, 0, &mpc52xx_ac97_bus_ops, NULL, &ac97_bus);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": snd_ac97_bus failed\n");
+ return rv;
+ }
+
+ memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
+ ac97_template.private_data = priv;
+
+ rv = snd_ac97_mixer(ac97_bus, &ac97_template, &priv->ac97);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": snd_ac97_mixer failed\n");
+ return rv;
+ }
+
+ return 0;
+}
+
+
+static int
+mpc52xx_ac97_hwinit(struct mpc52xx_ac97_priv *priv)
+{
+ /* Reset everything first by safety */
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_ERR_STAT);
+
+ /* Do a cold reset of codec */
+ out_8(&priv->psc->op1, 0x03);
+ udelay(10);
+ out_8(&priv->psc->op0, 0x02);
+ udelay(50);
+
+ /* Configure AC97 enhanced mode */
+ out_be32(&priv->psc->sicr, 0x03010000);
+
+ /* No slots active */
+ out_be32(&priv->psc->ac97_slots, 0x00000000);
+
+ /* No IRQ */
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
+
+ /* FIFO levels */
+ out_8(&priv->psc->rfcntl, 0x07);
+ out_8(&priv->psc->tfcntl, 0x07);
+ out_be16(&priv->psc->rfalarm, 0x80);
+ out_be16(&priv->psc->tfalarm, 0x80);
+
+ /* Go */
+ out_8(&priv->psc->command,MPC52xx_PSC_TX_ENABLE);
+ out_8(&priv->psc->command,MPC52xx_PSC_RX_ENABLE);
+
+ return 0;
+}
+
+static int
+mpc52xx_ac97_hwshutdown(struct mpc52xx_ac97_priv *priv)
+{
+ /* No IRQ */
+ out_be16(&priv->psc->mpc52xx_psc_imr, 0x0000);
+
+ /* Disable TB & RX */
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_RX);
+ out_8(&priv->psc->command,MPC52xx_PSC_RST_TX);
+
+ /* FIXME : Reset or put codec in low power ? */
+
+ return 0;
+}
+
+
+/* ======================================================================== */
+/* OF Platform Driver */
+/* ======================================================================== */
+
+static int __devinit
+mpc52xx_ac97_probe(struct of_device *op, const struct of_device_id *match)
+{
+ struct device_node *dn = op->node;
+ struct mpc52xx_ac97_priv *priv;
+ struct snd_card *card;
+ struct resource res;
+ int rv;
+
+ dev_dbg(&op->dev, "probing MPC52xx PSC AC97 driver\n");
+
+ /* Get card structure */
+ rv = -ENOMEM;
+ card = snd_card_new(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+ THIS_MODULE, sizeof(struct mpc52xx_ac97_priv));
+ if (!card)
+ goto err_early;
+
+ priv = card->private_data;
+
+ /* Init our private structure */
+ priv->card = card;
+ priv->dev = &op->dev;
+
+ /* Get resources (mem,irq,...) */
+ rv = of_address_to_resource(dn, 0, &res);
+ if (rv)
+ goto err_early;
+
+ priv->mem_start = res.start;
+ priv->mem_len = res.end - res.start + 1;
+
+ if (!request_mem_region(priv->mem_start, priv->mem_len, DRV_NAME)) {
+ printk(KERN_ERR DRV_NAME ": request_mem_region failed\n");
+ rv = -EBUSY;
+ goto err_early;
+ }
+
+ priv->psc = ioremap(priv->mem_start, priv->mem_len);
+ if (!priv->psc) {
+ printk(KERN_ERR DRV_NAME ": ioremap failed\n");
+ rv = -ENOMEM;
+ goto err_iomap;
+ }
+
+ priv->irq = irq_of_parse_and_map(dn, 0);
+ if (priv->irq == NO_IRQ) {
+ printk(KERN_ERR DRV_NAME ": irq_of_parse_and_map failed\n");
+ rv = -EBUSY;
+ goto err_irqmap;
+ }
+
+ /* Low level HW Init */
+ mpc52xx_ac97_hwinit(priv);
+
+ /* Request IRQ now that we're 'stable' */
+ rv = request_irq(priv->irq, mpc52xx_ac97_irq, 0, DRV_NAME, priv);
+ if (rv < 0) {
+ printk(KERN_ERR DRV_NAME ": request_irq failed\n");
+ goto err_irqreq;
+ }
+
+ /* Prepare sound stuff */
+ rv = mpc52xx_ac97_setup_mixer(priv);
+ if (rv)
+ goto err_late;
+
+ rv = mpc52xx_ac97_setup_pcm(priv);
+ if (rv)
+ goto err_late;
+
+ /* Finally register the card */
+ snprintf(card->shortname, sizeof(card->shortname), DRV_NAME);
+ snprintf(card->longname, sizeof(card->longname),
+ "Freescale MPC52xx PSC-AC97 (%s)", card->mixername);
+
+ rv = snd_card_register(card);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": snd_card_register failed\n");
+ goto err_late;
+ }
+
+ dev_set_drvdata(&op->dev, priv);
+
+ return 0;
+
+err_late:
+ free_irq(priv->irq, priv);
+err_irqreq:
+ mpc52xx_ac97_hwshutdown(priv);
+ irq_dispose_mapping(priv->irq);
+err_irqmap:
+ iounmap(priv->psc);
+err_iomap:
+ release_mem_region(priv->mem_start, priv->mem_len);
+err_early:
+ if (card)
+ snd_card_free(card);
+ return rv;
+}
+
+static int
+mpc52xx_ac97_remove(struct of_device *op)
+{
+ struct mpc52xx_ac97_priv *priv;
+
+ dev_dbg(&op->dev, "removing MPC52xx PSC AC97 driver\n");
+
+ priv = dev_get_drvdata(&op->dev);
+ if (priv) {
+ /* Sound subsys shutdown */
+ snd_card_free(priv->card);
+
+ /* Low level HW shutdown */
+ mpc52xx_ac97_hwshutdown(priv);
+
+ /* Release resources */
+ iounmap(priv->psc);
+ free_irq(priv->irq, priv);
+ irq_dispose_mapping(priv->irq);
+ release_mem_region(priv->mem_start, priv->mem_len);
+ }
+
+ dev_set_drvdata(&op->dev, NULL);
+
+ return 0;
+}
+
+
+static struct of_device_id mpc52xx_ac97_of_match[] = {
+ {
+/* .type = "ac97", FIXME Efika ... */
+ .compatible = "mpc5200b-psc-ac97", /* B only for now */
+ },
+};
+/* Prevent autoload during developpment phase ... */
+/* MODULE_DEVICE_TABLE(of, mpc52xx_ac97_of_match); */
+
+
+static struct of_platform_driver mpc52xx_ac97_of_driver = {
+ .owner = THIS_MODULE,
+ .name = DRV_NAME,
+ .match_table = mpc52xx_ac97_of_match,
+ .probe = mpc52xx_ac97_probe,
+ .remove = mpc52xx_ac97_remove,
+ .driver = {
+ .name = DRV_NAME,
+ },
+};
+
+
+/* ======================================================================== */
+/* Module */
+/* ======================================================================== */
+
+static int __init
+mpc52xx_ac97_init(void)
+{
+ int rv;
+
+ /* FIXME BIG FAT EFIKA HACK */
+ {
+ void *mbar;
+ mbar = ioremap(0xf0000000, 0x100000);
+ printk(KERN_INFO "EFIKA HACK: port_config %08x\n", in_be32(mbar + 0xb00));
+ out_be32(mbar + 0xb00, 0x01051124);
+ printk(KERN_INFO "EFIKA HACK: port_config %08x\n", in_be32(mbar + 0xb00));
+ iounmap(mbar);
+ }
+ /* ------------------------ */
+
+ printk(KERN_INFO "Sound: MPC52xx PSC AC97 driver\n");
+
+ rv = of_register_platform_driver(&mpc52xx_ac97_of_driver);
+ if (rv) {
+ printk(KERN_ERR DRV_NAME ": "
+ "of_register_platform_driver failed (%i)\n", rv);
+ return rv;
+ }
+
+ return 0;
+}
+
+static void __exit
+mpc52xx_ac97_exit(void)
+{
+ of_unregister_platform_driver(&mpc52xx_ac97_of_driver);
+}
+
+module_init(mpc52xx_ac97_init);
+module_exit(mpc52xx_ac97_exit);
+
+MODULE_AUTHOR("Sylvain Munaut <tnt@246tNt.com>");
+MODULE_DESCRIPTION(DRV_NAME ": Freescale MPC52xx PSC AC97 driver");
+MODULE_LICENSE("GPL");
+
--
1.4.4.2

View File

@ -0,0 +1,113 @@
From 49029f815b10175dcec09152929d53efe0ed510c Mon Sep 17 00:00:00 2001
From: Sven Luther <sven@tael.(none)>
Date: Tue, 9 Jan 2007 11:12:51 +0100
Subject: [PATCH] Fix the bestcomm interrupt property, fixes the ethernet driver.
---
arch/powerpc/kernel/prom_init.c | 85 +++++++++++++++++++++++++++++++++++++++
1 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 520ef42..a1cf18e 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2117,11 +2117,96 @@ static void __init fixup_device_tree_pmac(void)
#define fixup_device_tree_pmac()
#endif
+#ifdef CONFIG_PPC_EFIKA
+/* The current fw of the Efika has a device tree needs quite a few
+ * fixups to be compliant with the mpc52xx bindings. It's currently
+ * unknown if it will ever be compliant (come on bPlan ...) so we do fixups.
+ * NOTE that we (barely) tolerate it because the EFIKA was out before
+ * the bindings were finished, for any new boards -> RTFM ! */
+
+struct subst_entry {
+ char *path;
+ char *property;
+ void *value;
+ int value_len;
+};
+
+static void __init fixup_device_tree_efika(void)
+{
+ /* Substitution table */
+ #define prop_cstr(x) x, sizeof(x)
+ int prop_sound_irq[3] = { 2, 2, 0 };
+ int prop_bcomm_irq[48];
+ struct subst_entry efika_subst_table[] = {
+ { "/", "device_type", prop_cstr("efika") },
+ { "/builtin", "compatible", prop_cstr("soc") },
+ { "/builtin/ata", "compatible", prop_cstr("mpc5200b-ata\0mpc52xx-ata"), },
+ { "/builtin/bestcomm", "compatible", prop_cstr("mpc5200b-bestcomm\0mpc52xx-bestcomm") },
+ { "/builtin/bestcomm", "interrupts", prop_bcomm_irq, sizeof(prop_bcomm_irq) },
+ { "/builtin/ethernet", "compatible", prop_cstr("mpc5200b-fec\0mpc52xx-fec") },
+ { "/builtin/pic", "compatible", prop_cstr("mpc5200b-pic\0mpc52xx-pic") },
+ { "/builtin/serial", "compatible", prop_cstr("mpc5200b-psc-uart\0mpc52xx-psc-uart") },
+ { "/builtin/sound", "compatible", prop_cstr("mpc5200b-psc-ac97\0mpc52xx-psc-ac97") },
+ { "/builtin/sound", "interrupts", prop_sound_irq, sizeof(prop_sound_irq) },
+ { "/builtin/sram", "compatible", prop_cstr("mpc5200b-sram\0mpc52xx-sram") },
+ { "/builtin/sram", "device_type", prop_cstr("sram") },
+ {}
+ };
+ #undef prop_cstr
+
+ /* Vars */
+ u32 node;
+ char prop[64];
+ int rv, i;
+
+ /* Check if we're really running on a EFIKA */
+ node = call_prom("finddevice", 1, 1, ADDR("/"));
+ if (!PHANDLE_VALID(node))
+ return;
+
+ rv = prom_getprop(node, "model", prop, sizeof(prop));
+ if (rv == PROM_ERROR)
+ return;
+ if (strcmp(prop, "EFIKA5K2"))
+ return;
+
+ prom_printf("Applying EFIKA device tree fixups\n");
+
+ /* Fill the prop_bcomm_irq */
+ for (i=0; i<16; i++) {
+ prop_bcomm_irq[3*i ] = 3;
+ prop_bcomm_irq[3*i+1] = i;
+ prop_bcomm_irq[3*i+2] = 0;
+ }
+
+ /* Process substitution table */
+ for (i=0; efika_subst_table[i].path; i++) {
+ struct subst_entry *se = &efika_subst_table[i];
+
+ node = call_prom("finddevice", 1, 1, ADDR(se->path));
+ if (!PHANDLE_VALID(node)) {
+ prom_printf("fixup_device_tree_efika: ",
+ "skipped entry %x - not found\n", i);
+ continue;
+ }
+
+ rv = prom_setprop(node, se->path, se->property,
+ se->value, se->value_len );
+ if (rv == PROM_ERROR)
+ prom_printf("fixup_device_tree_efika: ",
+ "skipped entry %x - setprop error\n", i);
+ }
+}
+#else
+#define fixup_device_tree_efika()
+#endif
+
static void __init fixup_device_tree(void)
{
fixup_device_tree_maple();
fixup_device_tree_chrp();
fixup_device_tree_pmac();
+ fixup_device_tree_efika();
}
static void __init prom_find_boot_cpu(void)
--
1.4.4.2

View File

@ -2,8 +2,8 @@
+ debian/kernelvariables.patch
+ debian/doc-build-parallel.patch
+ debian/scripts-kconfig-reportoldconfig.patch
#+ debian/powerpc-mkvmlinuz-support-ppc.patch
#+ debian/powerpc-mkvmlinuz-support-powerpc.patch
+ debian/powerpc-mkvmlinuz-support-ppc.patch
+ debian/powerpc-mkvmlinuz-support-powerpc.patch
+ bugfix/powerpc/build-links.patch
+ bugfix/powerpc/mv643xx-hotplug-support.patch
@ -26,3 +26,35 @@
+ features/arm/ixp4xx-net-driver-improve-mac-handling.patch
+ bugfix/Makefile-localversion-backup.patch
+ bugfix/drivers-bus_to_virt.patch
+ features/powerpc/efika/0001-powerpc-serial-Dispose-irq-mapping-when-done-in-mpc52xx_serial.c.txt
+ features/powerpc/efika/0002-powerpc-52xx-Don-t-use-device_initcall-to-probe-of_platform_bus.txt
+ features/powerpc/efika/0004-powerpc-Use-common-52xx-of_platform-probe-code-for-EFIKA.txt
+ features/powerpc/efika/0005-powerpc-Restore-proper-link-order-in-platform.txt
+ features/powerpc/efika/0006-Rework-the-OHCI-quirk-mecanism-as-suggested-by-David.txt
+ features/powerpc/efika/0007-Implement-support-for-split-endian-OHCI.txt
+ features/powerpc/efika/0008-ohci-Rework-bus-glue-integration-to-allow-several-at-once.txt
+ features/powerpc/efika/0009-ohci-Add-support-for-OHCI-controller-on-the-of_platform-bus.txt
+ features/powerpc/efika/0010-libata-Add-support-for-the-MPC52xx-ATA-controller.txt
+ features/powerpc/efika/0011-ohci-Whitespace-and-typo-fix-in-ohci-ppc-of.c.txt
+ features/powerpc/efika/0012-ata-Fix-pata_mpc52xx.c-compatible-list.txt
+ features/powerpc/efika/0013-powerpc-serial-Fix-mpc52xx_uart.c-compatible-list.txt
+ features/powerpc/efika/0014-powerpc-Small-cleanup-of-EFIKA-platform.txt
+ features/powerpc/efika/0015-powerpc-Add-a-unified-uevent-handler-for-bus-based-on-of_device.txt
+ features/powerpc/efika/0016-macintosh-Use-the-new-of_device-common-uevent-handler.txt
+ features/powerpc/efika/0017-powerpc-Add-uevent-handler-for-of_platform_bus.txt
+ features/powerpc/efika/0018-powerpc-Add-uevent-handler-for-ibmebus.txt
+ features/powerpc/efika/0019-MPC5200-Bestcomm-platform-driver.txt
+ features/powerpc/efika/0020-Fec-MPC5200-eth-driver.txt
+ features/powerpc/efika/0021-POWERPC-Copy-bestcomm-support-files-into-arch-powerpc.txt
+ features/powerpc/efika/0022-MPC52xx-PCI-now-working-on-lite5200.-ugly-but-working.txt
+ features/powerpc/efika/0023-POWERPC-Make-FEC-work-on-the-lite5200.txt
+ features/powerpc/efika/0024-Add-missing-function-prototype.txt
+ features/powerpc/efika/0025-POWERPC-Misc-EFIKA-fixups-for-rtas-chrp.txt
+ features/powerpc/efika/0026-POWERPC-Cleanup-mpc52xx-PCI-support.txt
+ features/powerpc/efika/0027-POWERPC-Change-name-of-mpc52xx-pci-support-file-in-Makefile.txt
+ features/powerpc/efika/0028-POWERPC-Change-link-order-so-mpc52xx-fec-always-shows-up-as-eth0.txt
+ features/powerpc/efika/0029-POWERPC-Fixup-pr_print-format-for-mpc52xx-pci-support.txt
+ features/powerpc/efika/0030-POWERPC-Add-mpc52xx-lite5200-PCI-support.txt
+ features/powerpc/efika/0031-sound-Add-support-for-the-MPC52xx-PSC-AC97-Link.txt
+ features/powerpc/efika/0033-Fix-the-bestcomm-interrupt-property-fixes-the-ethernet-driver.txt