From 738e686055332a11884081ea85514514cb12fa20 Mon Sep 17 00:00:00 2001
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Tue, 19 Aug 2008 11:45:55 +1000
Subject: hotplug/rpaphp: Remove unused error path code

Commit f46753c5e354b857b20ab8e0fe7b2579831dc369 ("PCI: introduce pci_slot") removed the need for this error path.  Eliminate this warning:

drivers/pci/hotplug/rpaphp_slot.c: In function 'rpaphp_register_slot':
drivers/pci/hotplug/rpaphp_slot.c:151: warning: label 'sysfs_fail' defined but not used

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 drivers/pci/hotplug/rpaphp_slot.c | 4 ----
 1 file changed, 4 deletions(-)

(limited to 'drivers')

diff --git a/drivers/pci/hotplug/rpaphp_slot.c b/drivers/pci/hotplug/rpaphp_slot.c
index 9b714ea..5088450 100644
--- a/drivers/pci/hotplug/rpaphp_slot.c
+++ b/drivers/pci/hotplug/rpaphp_slot.c
@@ -147,9 +147,5 @@ int rpaphp_register_slot(struct slot *slot)
 	list_add(&slot->rpaphp_slot_list, &rpaphp_slot_head);
 	info("Slot [%s] registered\n", slot->name);
 	return 0;
-
-sysfs_fail:
-	pci_hp_deregister(php_slot);
-	return retval;
 }
 
-- 
cgit v1.1


From f6f11018dc7ea62482f36846e9f6eb0f27df7c3c Mon Sep 17 00:00:00 2001
From: Stephen Rothwell <sfr@canb.auug.org.au>
Date: Mon, 11 Aug 2008 17:04:32 +1000
Subject: powerpc/drivers: Use linux/of_device.h instead of asm/of_device.h

Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
Acked-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
 drivers/hwmon/ams/ams.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/hwmon/ams/ams.h b/drivers/hwmon/ams/ams.h
index a6221e5..221ef69 100644
--- a/drivers/hwmon/ams/ams.h
+++ b/drivers/hwmon/ams/ams.h
@@ -4,7 +4,7 @@
 #include <linux/mutex.h>
 #include <linux/spinlock.h>
 #include <linux/types.h>
-#include <asm/of_device.h>
+#include <linux/of_device.h>
 
 enum ams_irq {
 	AMS_IRQ_FREEFALL = 0x01,
-- 
cgit v1.1


From 7cfc4e5e7f9b5fa598aa69b5344b6fd0539f71d6 Mon Sep 17 00:00:00 2001
From: Kumar Gala <galak@kernel.crashing.org>
Date: Mon, 4 Aug 2008 08:27:52 -0500
Subject: serial/cpm_uart: Remove dead Kconfig options

With the change to device tree based setup we no longer need the explicit
Kconfig options for each SCC{1,4} or SMC{1,2} port.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/serial/Kconfig | 36 ------------------------------------
 1 file changed, 36 deletions(-)

(limited to 'drivers')

diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 77cb342..b87b1cf 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1136,42 +1136,6 @@ config SERIAL_CPM_CONSOLE
 	  your boot loader (lilo or loadlin) about how to pass options to the
 	  kernel at boot time.)
 
-config SERIAL_CPM_SCC1
-	bool "Support for SCC1 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SCC1 as a serial port
-
-config SERIAL_CPM_SCC2
-	bool "Support for SCC2 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SCC2 as a serial port
-
-config SERIAL_CPM_SCC3
-	bool "Support for SCC3 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SCC3 as a serial port
-
-config SERIAL_CPM_SCC4
-	bool "Support for SCC4 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SCC4 as a serial port
-
-config SERIAL_CPM_SMC1
-	bool "Support for SMC1 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SMC1 as a serial port
-
-config SERIAL_CPM_SMC2
-	bool "Support for SMC2 serial port"
-	depends on SERIAL_CPM=y
-	help
-	  Select this option to use SMC2 as a serial port
-
 config SERIAL_SGI_L1_CONSOLE
 	bool "SGI Altix L1 serial console support"
 	depends on IA64_GENERIC || IA64_SGI_SN2
-- 
cgit v1.1


From 8b05cefca73bfbd98c89f16327f5d7da52ab7c3c Mon Sep 17 00:00:00 2001
From: Becky Bruce <becky.bruce@freescale.com>
Date: Fri, 12 Sep 2008 10:42:56 -0500
Subject: cpm_uart: Pass actual dev ptr to dma_* in ucc and cpm_uart serial

We're currently passing NULL, and really shouldn't be.

Signed-off-by: Becky Bruce <becky.bruce@freescale.com>
Acked-By: Timur Tabi <timur@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/serial/cpm_uart/cpm_uart_core.c | 3 +++
 drivers/serial/cpm_uart/cpm_uart_cpm1.c | 6 +++---
 drivers/serial/cpm_uart/cpm_uart_cpm2.c | 6 +++---
 drivers/serial/ucc_uart.c               | 4 ++--
 4 files changed, 11 insertions(+), 8 deletions(-)

(limited to 'drivers')

diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index 25efca5..a6c4d74 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -1333,6 +1333,9 @@ static int __devinit cpm_uart_probe(struct of_device *ofdev,
 	if (ret)
 		return ret;
 
+	/* initialize the device pointer for the port */
+	pinfo->port.dev = &ofdev->dev;
+
 	return uart_add_one_port(&cpm_reg, &pinfo->port);
 }
 
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm1.c b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
index 0f0aff0..1b94c56 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm1.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm1.c
@@ -100,7 +100,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 		mem_addr = (u8 *) cpm_dpram_addr(cpm_dpalloc(memsz, 8));
 		dma_addr = (u32)cpm_dpram_phys(mem_addr);
 	} else
-		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+		mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
 					      GFP_KERNEL);
 
 	if (mem_addr == NULL) {
@@ -127,8 +127,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 
 void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
 {
-	dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
-					       pinfo->rx_fifosize) +
+	dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+							  pinfo->rx_fifosize) +
 			  L1_CACHE_ALIGN(pinfo->tx_nrfifos *
 					 pinfo->tx_fifosize), pinfo->mem_addr,
 			  pinfo->dma_addr);
diff --git a/drivers/serial/cpm_uart/cpm_uart_cpm2.c b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
index b8db4d3..141c0a3 100644
--- a/drivers/serial/cpm_uart/cpm_uart_cpm2.c
+++ b/drivers/serial/cpm_uart/cpm_uart_cpm2.c
@@ -136,7 +136,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 		dma_addr = virt_to_bus(mem_addr);
 	}
 	else
-		mem_addr = dma_alloc_coherent(NULL, memsz, &dma_addr,
+		mem_addr = dma_alloc_coherent(pinfo->port.dev, memsz, &dma_addr,
 					      GFP_KERNEL);
 
 	if (mem_addr == NULL) {
@@ -163,8 +163,8 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
 
 void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
 {
-	dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
-					       pinfo->rx_fifosize) +
+	dma_free_coherent(pinfo->port.dev, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
+							  pinfo->rx_fifosize) +
 			  L1_CACHE_ALIGN(pinfo->tx_nrfifos *
 					 pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
 			  pinfo->dma_addr);
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
index 5c5d18d..539c933 100644
--- a/drivers/serial/ucc_uart.c
+++ b/drivers/serial/ucc_uart.c
@@ -1009,7 +1009,7 @@ static int qe_uart_request_port(struct uart_port *port)
 	rx_size = L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
 	tx_size = L1_CACHE_ALIGN(qe_port->tx_nrfifos * qe_port->tx_fifosize);
 
-	bd_virt = dma_alloc_coherent(NULL, rx_size + tx_size, &bd_dma_addr,
+	bd_virt = dma_alloc_coherent(port->dev, rx_size + tx_size, &bd_dma_addr,
 		GFP_KERNEL);
 	if (!bd_virt) {
 		dev_err(port->dev, "could not allocate buffer descriptors\n");
@@ -1051,7 +1051,7 @@ static void qe_uart_release_port(struct uart_port *port)
 		container_of(port, struct uart_qe_port, port);
 	struct ucc_slow_private *uccs = qe_port->us_private;
 
-	dma_free_coherent(NULL, qe_port->bd_size, qe_port->bd_virt,
+	dma_free_coherent(port->dev, qe_port->bd_size, qe_port->bd_virt,
 			  qe_port->bd_dma_addr);
 
 	ucc_slow_free(uccs);
-- 
cgit v1.1


From 68e1ee62f0f8e556642a59ebaf0c2cc2ac6ccfa6 Mon Sep 17 00:00:00 2001
From: Kumar Gala <galak@kernel.crashing.org>
Date: Mon, 22 Sep 2008 14:41:31 -0700
Subject: powerpc: convert CONFIG_PPC_MERGE to CONFIG_PPC for legacy io checks

Now that arch/ppc is dead CONFIG_PPC_MERGE is always defined for all
powerpc platforms and we want to get rid of CONFIG_PPC_MERGE use
CONFIG_PPC instead.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/block/floppy.c           | 2 +-
 drivers/char/ipmi/ipmi_si_intf.c | 2 +-
 drivers/i2c/busses/i2c-pca-isa.c | 2 +-
 drivers/input/serio/i8042-io.h   | 2 +-
 drivers/pnp/isapnp/core.c        | 2 +-
 drivers/pnp/pnpbios/core.c       | 4 ++--
 6 files changed, 7 insertions(+), 7 deletions(-)

(limited to 'drivers')

diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c
index 395f8ea..5813e0d 100644
--- a/drivers/block/floppy.c
+++ b/drivers/block/floppy.c
@@ -4165,7 +4165,7 @@ static int __init floppy_init(void)
 	int i, unit, drive;
 	int err, dr;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
 	if (check_legacy_ioport(FDC1))
 		return -ENODEV;
 #endif
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 8e8afb6..3123bf5 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -2695,7 +2695,7 @@ static __devinit void default_find_bmc(void)
 	for (i = 0; ; i++) {
 		if (!ipmi_defaults[i].port)
 			break;
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
 		if (check_legacy_ioport(ipmi_defaults[i].port))
 			continue;
 #endif
diff --git a/drivers/i2c/busses/i2c-pca-isa.c b/drivers/i2c/busses/i2c-pca-isa.c
index a119784..28d8463 100644
--- a/drivers/i2c/busses/i2c-pca-isa.c
+++ b/drivers/i2c/busses/i2c-pca-isa.c
@@ -113,7 +113,7 @@ static int __devinit pca_isa_probe(struct device *dev, unsigned int id)
 
 	dev_info(dev, "i/o base %#08lx. irq %d\n", base, irq);
 
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
 	if (check_legacy_ioport(base)) {
 		dev_err(dev, "I/O address %#08lx is not available\n", base);
 		goto out;
diff --git a/drivers/input/serio/i8042-io.h b/drivers/input/serio/i8042-io.h
index f451c73..847f4aa 100644
--- a/drivers/input/serio/i8042-io.h
+++ b/drivers/input/serio/i8042-io.h
@@ -67,7 +67,7 @@ static inline int i8042_platform_init(void)
  * On some platforms touching the i8042 data register region can do really
  * bad things. Because of this the region is always reserved on such boxes.
  */
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
 	if (check_legacy_ioport(I8042_DATA_REG))
 		return -ENODEV;
 #endif
diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
index 101a835..46455fba 100644
--- a/drivers/pnp/isapnp/core.c
+++ b/drivers/pnp/isapnp/core.c
@@ -1012,7 +1012,7 @@ static int __init isapnp_init(void)
 		printk(KERN_INFO "isapnp: ISA Plug & Play support disabled\n");
 		return 0;
 	}
-#ifdef CONFIG_PPC_MERGE
+#ifdef CONFIG_PPC
 	if (check_legacy_ioport(_PIDXR) || check_legacy_ioport(_PNPWRP))
 		return -EINVAL;
 #endif
diff --git a/drivers/pnp/pnpbios/core.c b/drivers/pnp/pnpbios/core.c
index 19a4be1..0797dd1 100644
--- a/drivers/pnp/pnpbios/core.c
+++ b/drivers/pnp/pnpbios/core.c
@@ -519,7 +519,7 @@ static int __init pnpbios_init(void)
 {
 	int ret;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
 	if (check_legacy_ioport(PNPBIOS_BASE))
 		return -ENODEV;
 #endif
@@ -577,7 +577,7 @@ static int __init pnpbios_thread_init(void)
 {
 	struct task_struct *task;
 
-#if defined(CONFIG_PPC_MERGE)
+#if defined(CONFIG_PPC)
 	if (check_legacy_ioport(PNPBIOS_BASE))
 		return 0;
 #endif
-- 
cgit v1.1


From 8d1fb8cbaa74938d8c4379adb693d1d5f5c9e130 Mon Sep 17 00:00:00 2001
From: Kumar Gala <galak@kernel.crashing.org>
Date: Fri, 1 Aug 2008 11:09:34 -0500
Subject: serial/mpc52xx_uart: remove code associated with !CONFIG_PPC_MERGE

Now that arch/ppc is gone we don't need CONFIG_PPC_MERGE anymore
remove the dead code associated with !CONFIG_PPC_MERGE.

Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/serial/mpc52xx_uart.c | 181 +-----------------------------------------
 1 file changed, 1 insertion(+), 180 deletions(-)

(limited to 'drivers')

diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index 3612607..6117d3d 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -72,13 +72,8 @@
 #include <linux/console.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-
-#if defined(CONFIG_PPC_MERGE)
 #include <linux/of.h>
 #include <linux/of_platform.h>
-#else
-#include <linux/platform_device.h>
-#endif
 
 #include <asm/mpc52xx.h>
 #include <asm/mpc512x.h>
@@ -107,12 +102,11 @@ static struct uart_port mpc52xx_uart_ports[MPC52xx_PSC_MAXNUM];
 	 *        it's cleared, then a memset(...,0,...) should be added to
 	 *        the console_init
 	 */
-#if defined(CONFIG_PPC_MERGE)
+
 /* lookup table for matching device nodes to index numbers */
 static struct device_node *mpc52xx_uart_nodes[MPC52xx_PSC_MAXNUM];
 
 static void mpc52xx_uart_of_enumerate(void);
-#endif
 
 
 #define PSC(port) ((struct mpc52xx_psc __iomem *)((port)->membase))
@@ -255,17 +249,12 @@ static void mpc52xx_psc_cw_restore_ints(struct uart_port *port)
 /* Search for bus-frequency property in this node or a parent */
 static unsigned long mpc52xx_getuartclk(void *p)
 {
-#if defined(CONFIG_PPC_MERGE)
 	/*
 	 * 5200 UARTs have a / 32 prescaler
 	 * but the generic serial code assumes 16
 	 * so return ipb freq / 2
 	 */
 	return mpc52xx_find_ipb_freq(p) / 2;
-#else
-	pr_debug("unexpected call to mpc52xx_getuartclk with arch/ppc\n");
-	return NULL;
-#endif
 }
 
 static struct psc_ops mpc52xx_psc_ops = {
@@ -886,10 +875,6 @@ mpc52xx_console_get_options(struct uart_port *port,
 
 	/* CT{U,L}R are write-only ! */
 	*baud = CONFIG_SERIAL_MPC52xx_CONSOLE_BAUD;
-#if !defined(CONFIG_PPC_MERGE)
-	if (__res.bi_baudrate)
-		*baud = __res.bi_baudrate;
-#endif
 
 	/* Parse them */
 	switch (mr1 & MPC52xx_PSC_MODE_BITS_MASK) {
@@ -946,42 +931,6 @@ mpc52xx_console_write(struct console *co, const char *s, unsigned int count)
 	psc_ops->cw_restore_ints(port);
 }
 
-#if !defined(CONFIG_PPC_MERGE)
-static int __init
-mpc52xx_console_setup(struct console *co, char *options)
-{
-	struct uart_port *port = &mpc52xx_uart_ports[co->index];
-
-	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)
-		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->ops	= &mpc52xx_uart_ops;
-	port->mapbase	= MPC52xx_PA(MPC52xx_PSCx_OFFSET(co->index+1));
-
-	/* We ioremap ourself */
-	port->membase = ioremap(port->mapbase, MPC52xx_PSC_SIZE);
-	if (port->membase == NULL)
-		return -EINVAL;
-
-	/* 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);
-
-	return uart_set_options(port, co, baud, parity, bits, flow);
-}
-
-#else
 
 static int __init
 mpc52xx_console_setup(struct console *co, char *options)
@@ -1053,7 +1002,6 @@ mpc52xx_console_setup(struct console *co, char *options)
 
 	return uart_set_options(port, co, baud, parity, bits, flow);
 }
-#endif /* defined(CONFIG_PPC_MERGE) */
 
 
 static struct uart_driver mpc52xx_uart_driver;
@@ -1072,9 +1020,7 @@ static struct console mpc52xx_console = {
 static int __init
 mpc52xx_console_init(void)
 {
-#if defined(CONFIG_PPC_MERGE)
 	mpc52xx_uart_of_enumerate();
-#endif
 	register_console(&mpc52xx_console);
 	return 0;
 }
@@ -1100,115 +1046,6 @@ static struct uart_driver mpc52xx_uart_driver = {
 	.cons		= MPC52xx_PSC_CONSOLE,
 };
 
-
-#if !defined(CONFIG_PPC_MERGE)
-/* ======================================================================== */
-/* Platform Driver                                                          */
-/* ======================================================================== */
-
-static int __devinit
-mpc52xx_uart_probe(struct platform_device *dev)
-{
-	struct resource *res = dev->resource;
-
-	struct uart_port *port = NULL;
-	int i, idx, ret;
-
-	/* Check validity & presence */
-	idx = dev->id;
-	if (idx < 0 || idx >= MPC52xx_PSC_MAXNUM)
-		return -EINVAL;
-
-	if (!mpc52xx_match_psc_function(idx, "uart"))
-		return -ENODEV;
-
-	/* Init the port structure */
-	port = &mpc52xx_uart_ports[idx];
-
-	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 |
-			  (uart_console(port) ? 0 : UPF_IOREMAP);
-	port->line	= idx;
-	port->ops	= &mpc52xx_uart_ops;
-	port->dev	= &dev->dev;
-
-	/* 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)
-		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);
-
-	return ret;
-}
-
-static int
-mpc52xx_uart_remove(struct platform_device *dev)
-{
-	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-	platform_set_drvdata(dev, NULL);
-
-	if (port)
-		uart_remove_one_port(&mpc52xx_uart_driver, port);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int
-mpc52xx_uart_suspend(struct platform_device *dev, pm_message_t state)
-{
-	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-	if (port)
-		uart_suspend_port(&mpc52xx_uart_driver, port);
-
-	return 0;
-}
-
-static int
-mpc52xx_uart_resume(struct platform_device *dev)
-{
-	struct uart_port *port = (struct uart_port *) platform_get_drvdata(dev);
-
-	if (port)
-		uart_resume_port(&mpc52xx_uart_driver, port);
-
-	return 0;
-}
-#endif
-
-/* work with hotplug and coldplug */
-MODULE_ALIAS("platform:mpc52xx-psc");
-
-static struct platform_driver mpc52xx_uart_platform_driver = {
-	.probe		= mpc52xx_uart_probe,
-	.remove		= mpc52xx_uart_remove,
-#ifdef CONFIG_PM
-	.suspend	= mpc52xx_uart_suspend,
-	.resume		= mpc52xx_uart_resume,
-#endif
-	.driver		= {
-		.owner	= THIS_MODULE,
-		.name	= "mpc52xx-psc",
-	},
-};
-#endif /* !defined(CONFIG_PPC_MERGE) */
-
-
-#if defined(CONFIG_PPC_MERGE)
 /* ======================================================================== */
 /* OF Platform Driver                                                       */
 /* ======================================================================== */
@@ -1402,7 +1239,6 @@ static struct of_platform_driver mpc52xx_uart_of_driver = {
 		.name	= "mpc52xx-psc-uart",
 	},
 };
-#endif /* defined(CONFIG_PPC_MERGE) */
 
 
 /* ======================================================================== */
@@ -1423,7 +1259,6 @@ mpc52xx_uart_init(void)
 		return ret;
 	}
 
-#if defined(CONFIG_PPC_MERGE)
 	mpc52xx_uart_of_enumerate();
 
 	ret = of_register_platform_driver(&mpc52xx_uart_of_driver);
@@ -1433,16 +1268,6 @@ mpc52xx_uart_init(void)
 		uart_unregister_driver(&mpc52xx_uart_driver);
 		return ret;
 	}
-#else
-	psc_ops = &mpc52xx_psc_ops;
-	ret = platform_driver_register(&mpc52xx_uart_platform_driver);
-	if (ret) {
-		printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
-		       __FILE__, ret);
-		uart_unregister_driver(&mpc52xx_uart_driver);
-		return ret;
-	}
-#endif
 
 	return 0;
 }
@@ -1450,11 +1275,7 @@ mpc52xx_uart_init(void)
 static void __exit
 mpc52xx_uart_exit(void)
 {
-#if defined(CONFIG_PPC_MERGE)
 	of_unregister_platform_driver(&mpc52xx_uart_of_driver);
-#else
-	platform_driver_unregister(&mpc52xx_uart_platform_driver);
-#endif
 	uart_unregister_driver(&mpc52xx_uart_driver);
 }
 
-- 
cgit v1.1


From b68d185ab12b1fc8000432c5d5ab5404d4788b4c Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date: Thu, 4 Sep 2008 02:57:57 +0000
Subject: ibm_newemac: Allow the "no flow control" EMAC feature to work

Some PowerPC 40x chips have errata that force us not to use the integrated
flow control.  We have the feature defined, but it currently can't be used
because it is never added to EMAC_FTRS_POSSIBLE.

This adds a Kconfig option for affected platforms to select and puts the
feature in the EMAC_FTRS_POSSIBLE list.  This is set for PowerPC 405EZ
platforms as well.

Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
---
 drivers/net/ibm_newemac/Kconfig | 4 ++++
 drivers/net/ibm_newemac/core.c  | 2 ++
 drivers/net/ibm_newemac/core.h  | 3 +++
 3 files changed, 9 insertions(+)

(limited to 'drivers')

diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
index 70a3272..dfb6547 100644
--- a/drivers/net/ibm_newemac/Kconfig
+++ b/drivers/net/ibm_newemac/Kconfig
@@ -62,3 +62,7 @@ config IBM_NEW_EMAC_TAH
 config IBM_NEW_EMAC_EMAC4
 	bool
 	default n
+
+config IBM_NEW_EMAC_NO_FLOW_CTRL
+	bool
+	default n
diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index ccd9d90..4e63387 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -2567,6 +2567,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 		if (of_device_is_compatible(np, "ibm,emac-440ep") ||
 		    of_device_is_compatible(np, "ibm,emac-440gr"))
 			dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
+		if (of_device_is_compatible(np, "ibm,emac-405ez"))
+			dev->features |= EMAC_FTR_NO_FLOW_CONTROL_40x;
 	}
 
 	/* Fixup some feature bits based on the device tree */
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 6545e69..59e5a5d 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -341,6 +341,9 @@ enum {
 #ifdef CONFIG_IBM_NEW_EMAC_RGMII
 	    EMAC_FTR_HAS_RGMII	|
 #endif
+#ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
+	    EMAC_FTR_NO_FLOW_CONTROL_40x |
+#endif
 	EMAC_FTR_440EP_PHY_CLK_FIX,
 };
 
-- 
cgit v1.1


From ec4f9945b5b3e9e491a04eb1efe1c959371fa6de Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date: Thu, 4 Sep 2008 04:03:45 +0000
Subject: ibm_newemac: Introduce mal_has_feature

There are some PowerPC SoCs that do odd things with the MAL handling.  In
order to accommodate them, we need to introduce a feature mechanism that is
similar to the existing emac_has_feature function.

This adds a feature variable to the mal_instance structure, and adds a
mal_has_feature function.  Two features are defined and are guarded
by Kconfig options that are selected by the affected platforms.

MAL_FTR_CLEAR_ICINSTAT is used for platforms that need to clear the
interrupt bits in the ICINTSTAT SDR for txeob/rxeob.  This is common
on MAL implementations that have interrupt coalescing.

MAL_FTR_COMMON_ERR_INT is used for platforms that have SERR, TXDE,
and RXDE OR'd into a single interrupt bit.

Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
---
 drivers/net/ibm_newemac/Kconfig |  8 ++++++++
 drivers/net/ibm_newemac/mal.h   | 34 ++++++++++++++++++++++++++++++++++
 2 files changed, 42 insertions(+)

(limited to 'drivers')

diff --git a/drivers/net/ibm_newemac/Kconfig b/drivers/net/ibm_newemac/Kconfig
index dfb6547..44e5a0e 100644
--- a/drivers/net/ibm_newemac/Kconfig
+++ b/drivers/net/ibm_newemac/Kconfig
@@ -66,3 +66,11 @@ config IBM_NEW_EMAC_EMAC4
 config IBM_NEW_EMAC_NO_FLOW_CTRL
 	bool
 	default n
+
+config IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+	bool
+	default n
+
+config IBM_NEW_EMAC_MAL_COMMON_ERR
+	bool
+	default n
diff --git a/drivers/net/ibm_newemac/mal.h b/drivers/net/ibm_newemac/mal.h
index eaa7262..0b24138 100644
--- a/drivers/net/ibm_newemac/mal.h
+++ b/drivers/net/ibm_newemac/mal.h
@@ -213,6 +213,8 @@ struct mal_instance {
 	struct of_device	*ofdev;
 	int			index;
 	spinlock_t		lock;
+
+	unsigned int features;
 };
 
 static inline u32 get_mal_dcrn(struct mal_instance *mal, int reg)
@@ -225,6 +227,38 @@ static inline void set_mal_dcrn(struct mal_instance *mal, int reg, u32 val)
 	dcr_write(mal->dcr_host, reg, val);
 }
 
+/* Features of various MAL implementations */
+
+/* Set if you have interrupt coalescing and you have to clear the SDR
+ * register for TXEOB and RXEOB interrupts to work
+ */
+#define MAL_FTR_CLEAR_ICINTSTAT	0x00000001
+
+/* Set if your MAL has SERR, TXDE, and RXDE OR'd into a single UIC
+ * interrupt
+ */
+#define MAL_FTR_COMMON_ERR_INT	0x00000002
+
+enum {
+	MAL_FTRS_ALWAYS = 0,
+
+	MAL_FTRS_POSSIBLE =
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT
+		MAL_FTR_CLEAR_ICINTSTAT |
+#endif
+#ifdef CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR
+		MAL_FTR_COMMON_ERR_INT |
+#endif
+		0,
+};
+
+static inline int mal_has_feature(struct mal_instance *dev,
+		unsigned long feature)
+{
+	return (MAL_FTRS_ALWAYS & feature) ||
+		(MAL_FTRS_POSSIBLE & dev->features & feature);
+}
+
 /* Register MAL devices */
 int mal_init(void);
 void mal_exit(void);
-- 
cgit v1.1


From fbcc4bacee30cad4e4a13d05492a9ed0c9c3e8c7 Mon Sep 17 00:00:00 2001
From: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Date: Thu, 4 Sep 2008 04:08:20 +0000
Subject: ibm_newemac: MAL support for PowerPC 405EZ

The PowerPC 405EZ SoC has some differences in the interrupt layout and
handling for the MAL.  The SERR, TXDE, and RXDE interrupts are OR'd into
a single interrupt.  Also, due to the possibility for interrupt coalescing,
the TXEOB and RXEOB interrupts require an interrupt bit to be cleared in
the ICINTSTAT SDR.

This sets the proper MAL feature bits for 405EZ boards, and adds a common
shared handler for SERR, TXDE, and RXDE.  The defines for the ICINTSTAT DCR
are added to the proper header file as well.

This has been adapted from code originally written by Stefan Roese.

Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
---
 drivers/net/ibm_newemac/mal.c | 60 +++++++++++++++++++++++++++++++++++++++----
 1 file changed, 55 insertions(+), 5 deletions(-)

(limited to 'drivers')

diff --git a/drivers/net/ibm_newemac/mal.c b/drivers/net/ibm_newemac/mal.c
index 10c267b..1839d3f 100644
--- a/drivers/net/ibm_newemac/mal.c
+++ b/drivers/net/ibm_newemac/mal.c
@@ -28,6 +28,7 @@
 #include <linux/delay.h>
 
 #include "core.h"
+#include <asm/dcr-regs.h>
 
 static int mal_count;
 
@@ -279,6 +280,10 @@ static irqreturn_t mal_txeob(int irq, void *dev_instance)
 	mal_schedule_poll(mal);
 	set_mal_dcrn(mal, MAL_TXEOBISR, r);
 
+	if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+		mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+				(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICTX));
+
 	return IRQ_HANDLED;
 }
 
@@ -293,6 +298,10 @@ static irqreturn_t mal_rxeob(int irq, void *dev_instance)
 	mal_schedule_poll(mal);
 	set_mal_dcrn(mal, MAL_RXEOBISR, r);
 
+	if (mal_has_feature(mal, MAL_FTR_CLEAR_ICINTSTAT))
+		mtdcri(SDR0, DCRN_SDR_ICINTSTAT,
+				(mfdcri(SDR0, DCRN_SDR_ICINTSTAT) | ICINTSTAT_ICRX));
+
 	return IRQ_HANDLED;
 }
 
@@ -336,6 +345,25 @@ static irqreturn_t mal_rxde(int irq, void *dev_instance)
 	return IRQ_HANDLED;
 }
 
+static irqreturn_t mal_int(int irq, void *dev_instance)
+{
+	struct mal_instance *mal = dev_instance;
+	u32 esr = get_mal_dcrn(mal, MAL_ESR);
+
+	if (esr & MAL_ESR_EVB) {
+		/* descriptor error */
+		if (esr & MAL_ESR_DE) {
+			if (esr & MAL_ESR_CIDT)
+				return mal_rxde(irq, dev_instance);
+			else
+				return mal_txde(irq, dev_instance);
+		} else { /* SERR */
+			return mal_serr(irq, dev_instance);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
 void mal_poll_disable(struct mal_instance *mal, struct mal_commac *commac)
 {
 	/* Spinlock-type semantics: only one caller disable poll at a time */
@@ -493,6 +521,8 @@ static int __devinit mal_probe(struct of_device *ofdev,
 	unsigned int dcr_base;
 	const u32 *prop;
 	u32 cfg;
+	unsigned long irqflags;
+	irq_handler_t hdlr_serr, hdlr_txde, hdlr_rxde;
 
 	mal = kzalloc(sizeof(struct mal_instance), GFP_KERNEL);
 	if (!mal) {
@@ -542,11 +572,21 @@ static int __devinit mal_probe(struct of_device *ofdev,
 		goto fail;
 	}
 
+	if (of_device_is_compatible(ofdev->node, "ibm,mcmal-405ez"))
+		mal->features |= (MAL_FTR_CLEAR_ICINTSTAT |
+				MAL_FTR_COMMON_ERR_INT);
+
 	mal->txeob_irq = irq_of_parse_and_map(ofdev->node, 0);
 	mal->rxeob_irq = irq_of_parse_and_map(ofdev->node, 1);
 	mal->serr_irq = irq_of_parse_and_map(ofdev->node, 2);
-	mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
-	mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+
+	if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+		mal->txde_irq = mal->rxde_irq = mal->serr_irq;
+	} else {
+		mal->txde_irq = irq_of_parse_and_map(ofdev->node, 3);
+		mal->rxde_irq = irq_of_parse_and_map(ofdev->node, 4);
+	}
+
 	if (mal->txeob_irq == NO_IRQ || mal->rxeob_irq == NO_IRQ ||
 	    mal->serr_irq == NO_IRQ || mal->txde_irq == NO_IRQ ||
 	    mal->rxde_irq == NO_IRQ) {
@@ -608,16 +648,26 @@ static int __devinit mal_probe(struct of_device *ofdev,
 			     sizeof(struct mal_descriptor) *
 			     mal_rx_bd_offset(mal, i));
 
-	err = request_irq(mal->serr_irq, mal_serr, 0, "MAL SERR", mal);
+	if (mal_has_feature(mal, MAL_FTR_COMMON_ERR_INT)) {
+		irqflags = IRQF_SHARED;
+		hdlr_serr = hdlr_txde = hdlr_rxde = mal_int;
+	} else {
+		irqflags = 0;
+		hdlr_serr = mal_serr;
+		hdlr_txde = mal_txde;
+		hdlr_rxde = mal_rxde;
+	}
+
+	err = request_irq(mal->serr_irq, hdlr_serr, irqflags, "MAL SERR", mal);
 	if (err)
 		goto fail2;
-	err = request_irq(mal->txde_irq, mal_txde, 0, "MAL TX DE", mal);
+	err = request_irq(mal->txde_irq, hdlr_txde, irqflags, "MAL TX DE", mal);
 	if (err)
 		goto fail3;
 	err = request_irq(mal->txeob_irq, mal_txeob, 0, "MAL TX EOB", mal);
 	if (err)
 		goto fail4;
-	err = request_irq(mal->rxde_irq, mal_rxde, 0, "MAL RX DE", mal);
+	err = request_irq(mal->rxde_irq, hdlr_rxde, irqflags, "MAL RX DE", mal);
 	if (err)
 		goto fail5;
 	err = request_irq(mal->rxeob_irq, mal_rxeob, 0, "MAL RX EOB", mal);
-- 
cgit v1.1


From 9e3cb29497561c846d0e7efc445731764d93c749 Mon Sep 17 00:00:00 2001
From: Victor Gallardo <vgallardo@amcc.com>
Date: Wed, 1 Oct 2008 23:37:57 -0700
Subject: ibm_newemac: Add support for GPCS, SGMII and M88E1112 PHY

Add support for the phy types found on the Arches and other
PowerPC 460 based boards.

Signed-off-by: Victor Gallardo <vgallardo@amcc.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
---
 drivers/net/ibm_newemac/core.c | 58 ++++++++++++++++++++++++-----
 drivers/net/ibm_newemac/core.h |  8 ++++
 drivers/net/ibm_newemac/phy.c  | 84 ++++++++++++++++++++++++++++++++++++++++++
 drivers/net/ibm_newemac/phy.h  |  2 +
 4 files changed, 143 insertions(+), 9 deletions(-)

(limited to 'drivers')

diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c
index 4e63387..efcf21c 100644
--- a/drivers/net/ibm_newemac/core.c
+++ b/drivers/net/ibm_newemac/core.c
@@ -130,6 +130,7 @@ static inline void emac_report_timeout_error(struct emac_instance *dev,
 					     const char *error)
 {
 	if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
+				  EMAC_FTR_460EX_PHY_CLK_FIX |
 				  EMAC_FTR_440EP_PHY_CLK_FIX))
 		DBG(dev, "%s" NL, error);
 	else if (net_ratelimit())
@@ -201,13 +202,15 @@ static inline int emac_phy_supports_gige(int phy_mode)
 {
 	return  phy_mode == PHY_MODE_GMII ||
 		phy_mode == PHY_MODE_RGMII ||
+		phy_mode == PHY_MODE_SGMII ||
 		phy_mode == PHY_MODE_TBI ||
 		phy_mode == PHY_MODE_RTBI;
 }
 
 static inline int emac_phy_gpcs(int phy_mode)
 {
-	return  phy_mode == PHY_MODE_TBI ||
+	return  phy_mode == PHY_MODE_SGMII ||
+		phy_mode == PHY_MODE_TBI ||
 		phy_mode == PHY_MODE_RTBI;
 }
 
@@ -351,10 +354,24 @@ static int emac_reset(struct emac_instance *dev)
 		emac_tx_disable(dev);
 	}
 
+#ifdef CONFIG_PPC_DCR_NATIVE
+	/* Enable internal clock source */
+	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
+		dcri_clrset(SDR0, SDR0_ETH_CFG,
+			    0, SDR0_ETH_CFG_ECS << dev->cell_index);
+#endif
+
 	out_be32(&p->mr0, EMAC_MR0_SRST);
 	while ((in_be32(&p->mr0) & EMAC_MR0_SRST) && n)
 		--n;
 
+#ifdef CONFIG_PPC_DCR_NATIVE
+	 /* Enable external clock source */
+	if (emac_has_feature(dev, EMAC_FTR_460EX_PHY_CLK_FIX))
+		dcri_clrset(SDR0, SDR0_ETH_CFG,
+			    SDR0_ETH_CFG_ECS << dev->cell_index, 0);
+#endif
+
 	if (n) {
 		dev->reset_failed = 0;
 		return 0;
@@ -547,8 +564,9 @@ static int emac_configure(struct emac_instance *dev)
 	switch (dev->phy.speed) {
 	case SPEED_1000:
 		if (emac_phy_gpcs(dev->phy.mode)) {
-			mr1 |= EMAC_MR1_MF_1000GPCS |
-				EMAC_MR1_MF_IPPA(dev->phy.address);
+			mr1 |= EMAC_MR1_MF_1000GPCS | EMAC_MR1_MF_IPPA(
+				(dev->phy.gpcs_address != 0xffffffff) ?
+				 dev->phy.gpcs_address : dev->phy.address);
 
 			/* Put some arbitrary OUI, Manuf & Rev IDs so we can
 			 * identify this GPCS PHY later.
@@ -660,8 +678,12 @@ static int emac_configure(struct emac_instance *dev)
 	out_be32(&p->iser,  r);
 
 	/* We need to take GPCS PHY out of isolate mode after EMAC reset */
-	if (emac_phy_gpcs(dev->phy.mode))
-		emac_mii_reset_phy(&dev->phy);
+	if (emac_phy_gpcs(dev->phy.mode)) {
+		if (dev->phy.gpcs_address != 0xffffffff)
+			emac_mii_reset_gpcs(&dev->phy);
+		else
+			emac_mii_reset_phy(&dev->phy);
+	}
 
 	return 0;
 }
@@ -866,7 +888,9 @@ static int emac_mdio_read(struct net_device *ndev, int id, int reg)
 	struct emac_instance *dev = netdev_priv(ndev);
 	int res;
 
-	res = __emac_mdio_read(dev->mdio_instance ? dev->mdio_instance : dev,
+	res = __emac_mdio_read((dev->mdio_instance &&
+				dev->phy.gpcs_address != id) ?
+				dev->mdio_instance : dev,
 			       (u8) id, (u8) reg);
 	return res;
 }
@@ -875,7 +899,9 @@ static void emac_mdio_write(struct net_device *ndev, int id, int reg, int val)
 {
 	struct emac_instance *dev = netdev_priv(ndev);
 
-	__emac_mdio_write(dev->mdio_instance ? dev->mdio_instance : dev,
+	__emac_mdio_write((dev->mdio_instance &&
+			   dev->phy.gpcs_address != id) ?
+			   dev->mdio_instance : dev,
 			  (u8) id, (u8) reg, (u16) val);
 }
 
@@ -2367,7 +2393,11 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
 		 * XXX I probably should move these settings to the dev tree
 		 */
 		dev->phy.address = -1;
-		dev->phy.features = SUPPORTED_100baseT_Full | SUPPORTED_MII;
+		dev->phy.features = SUPPORTED_MII;
+		if (emac_phy_supports_gige(dev->phy_mode))
+			dev->phy.features |= SUPPORTED_1000baseT_Full;
+		else
+			dev->phy.features |= SUPPORTED_100baseT_Full;
 		dev->phy.pause = 1;
 
 		return 0;
@@ -2406,7 +2436,9 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
 		 * Note that the busy_phy_map is currently global
 		 * while it should probably be per-ASIC...
 		 */
-		dev->phy.address = dev->cell_index;
+		dev->phy.gpcs_address = dev->gpcs_address;
+		if (dev->phy.gpcs_address == 0xffffffff)
+			dev->phy.address = dev->cell_index;
 	}
 
 	emac_configure(dev);
@@ -2516,6 +2548,8 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 		dev->phy_address = 0xffffffff;
 	if (emac_read_uint_prop(np, "phy-map", &dev->phy_map, 0))
 		dev->phy_map = 0xffffffff;
+	if (emac_read_uint_prop(np, "gpcs-address", &dev->gpcs_address, 0))
+		dev->gpcs_address = 0xffffffff;
 	if (emac_read_uint_prop(np->parent, "clock-frequency", &dev->opb_bus_freq, 1))
 		return -ENXIO;
 	if (emac_read_uint_prop(np, "tah-device", &dev->tah_ph, 0))
@@ -2559,6 +2593,9 @@ static int __devinit emac_init_config(struct emac_instance *dev)
 	/* Check EMAC version */
 	if (of_device_is_compatible(np, "ibm,emac4sync")) {
 		dev->features |= (EMAC_FTR_EMAC4 | EMAC_FTR_EMAC4SYNC);
+		if (of_device_is_compatible(np, "ibm,emac-460ex") ||
+		    of_device_is_compatible(np, "ibm,emac-460gt"))
+			dev->features |= EMAC_FTR_460EX_PHY_CLK_FIX;
 	} else if (of_device_is_compatible(np, "ibm,emac4")) {
 		dev->features |= EMAC_FTR_EMAC4;
 		if (of_device_is_compatible(np, "ibm,emac-440gx"))
@@ -2826,6 +2863,9 @@ static int __devinit emac_probe(struct of_device *ofdev,
 	       ndev->dev_addr[0], ndev->dev_addr[1], ndev->dev_addr[2],
 	       ndev->dev_addr[3], ndev->dev_addr[4], ndev->dev_addr[5]);
 
+	if (dev->phy_mode == PHY_MODE_SGMII)
+		printk(KERN_NOTICE "%s: in SGMII mode\n", ndev->name);
+
 	if (dev->phy.address >= 0)
 		printk("%s: found %s PHY (0x%02x)\n", ndev->name,
 		       dev->phy.def->name, dev->phy.address);
diff --git a/drivers/net/ibm_newemac/core.h b/drivers/net/ibm_newemac/core.h
index 59e5a5d..18d56c6 100644
--- a/drivers/net/ibm_newemac/core.h
+++ b/drivers/net/ibm_newemac/core.h
@@ -190,6 +190,9 @@ struct emac_instance {
 	struct delayed_work		link_work;
 	int				link_polling;
 
+	/* GPCS PHY infos */
+	u32				gpcs_address;
+
 	/* Shared MDIO if any */
 	u32				mdio_ph;
 	struct of_device		*mdio_dev;
@@ -317,6 +320,10 @@ struct emac_instance {
  * The 405EX and 460EX contain the EMAC4SYNC core
  */
 #define EMAC_FTR_EMAC4SYNC		0x00000200
+/*
+ * Set if we need phy clock workaround for 460ex or 460gt
+ */
+#define EMAC_FTR_460EX_PHY_CLK_FIX	0x00000400
 
 
 /* Right now, we don't quite handle the always/possible masks on the
@@ -344,6 +351,7 @@ enum {
 #ifdef CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL
 	    EMAC_FTR_NO_FLOW_CONTROL_40x |
 #endif
+	EMAC_FTR_460EX_PHY_CLK_FIX |
 	EMAC_FTR_440EP_PHY_CLK_FIX,
 };
 
diff --git a/drivers/net/ibm_newemac/phy.c b/drivers/net/ibm_newemac/phy.c
index 37bfeea..606db53 100644
--- a/drivers/net/ibm_newemac/phy.c
+++ b/drivers/net/ibm_newemac/phy.c
@@ -38,6 +38,16 @@ static inline void phy_write(struct mii_phy *phy, int reg, int val)
 	phy->mdio_write(phy->dev, phy->address, reg, val);
 }
 
+static inline int gpcs_phy_read(struct mii_phy *phy, int reg)
+{
+	return phy->mdio_read(phy->dev, phy->gpcs_address, reg);
+}
+
+static inline void gpcs_phy_write(struct mii_phy *phy, int reg, int val)
+{
+	phy->mdio_write(phy->dev, phy->gpcs_address, reg, val);
+}
+
 int emac_mii_reset_phy(struct mii_phy *phy)
 {
 	int val;
@@ -62,6 +72,37 @@ int emac_mii_reset_phy(struct mii_phy *phy)
 	return limit <= 0;
 }
 
+int emac_mii_reset_gpcs(struct mii_phy *phy)
+{
+	int val;
+	int limit = 10000;
+
+	val = gpcs_phy_read(phy, MII_BMCR);
+	val &= ~(BMCR_ISOLATE | BMCR_ANENABLE);
+	val |= BMCR_RESET;
+	gpcs_phy_write(phy, MII_BMCR, val);
+
+	udelay(300);
+
+	while (limit--) {
+		val = gpcs_phy_read(phy, MII_BMCR);
+		if (val >= 0 && (val & BMCR_RESET) == 0)
+			break;
+		udelay(10);
+	}
+	if ((val & BMCR_ISOLATE) && limit > 0)
+		gpcs_phy_write(phy, MII_BMCR, val & ~BMCR_ISOLATE);
+
+	if (limit > 0 && phy->mode == PHY_MODE_SGMII) {
+		/* Configure GPCS interface to recommended setting for SGMII */
+		gpcs_phy_write(phy, 0x04, 0x8120); /* AsymPause, FDX */
+		gpcs_phy_write(phy, 0x07, 0x2801); /* msg_pg, toggle */
+		gpcs_phy_write(phy, 0x00, 0x0140); /* 1Gbps, FDX     */
+	}
+
+	return limit <= 0;
+}
+
 static int genmii_setup_aneg(struct mii_phy *phy, u32 advertise)
 {
 	int ctl, adv;
@@ -332,6 +373,33 @@ static int m88e1111_init(struct mii_phy *phy)
 	return  0;
 }
 
+static int m88e1112_init(struct mii_phy *phy)
+{
+	/*
+	 * Marvell 88E1112 PHY needs to have the SGMII MAC
+	 * interace (page 2) properly configured to
+	 * communicate with the 460EX/GT GPCS interface.
+	 */
+
+	u16 reg_short;
+
+	pr_debug("%s: Marvell 88E1112 Ethernet\n", __func__);
+
+	/* Set access to Page 2 */
+	phy_write(phy, 0x16, 0x0002);
+
+	phy_write(phy, 0x00, 0x0040); /* 1Gbps */
+	reg_short = (u16)(phy_read(phy, 0x1a));
+	reg_short |= 0x8000; /* bypass Auto-Negotiation */
+	phy_write(phy, 0x1a, reg_short);
+	emac_mii_reset_phy(phy); /* reset MAC interface */
+
+	/* Reset access to Page 0 */
+	phy_write(phy, 0x16, 0x0000);
+
+	return  0;
+}
+
 static int et1011c_init(struct mii_phy *phy)
 {
 	u16 reg_short;
@@ -384,11 +452,27 @@ static struct mii_phy_def m88e1111_phy_def = {
 	.ops		= &m88e1111_phy_ops,
 };
 
+static struct mii_phy_ops m88e1112_phy_ops = {
+	.init		= m88e1112_init,
+	.setup_aneg	= genmii_setup_aneg,
+	.setup_forced	= genmii_setup_forced,
+	.poll_link	= genmii_poll_link,
+	.read_link	= genmii_read_link
+};
+
+static struct mii_phy_def m88e1112_phy_def = {
+	.phy_id		= 0x01410C90,
+	.phy_id_mask	= 0x0ffffff0,
+	.name		= "Marvell 88E1112 Ethernet",
+	.ops		= &m88e1112_phy_ops,
+};
+
 static struct mii_phy_def *mii_phy_table[] = {
 	&et1011c_phy_def,
 	&cis8201_phy_def,
 	&bcm5248_phy_def,
 	&m88e1111_phy_def,
+	&m88e1112_phy_def,
 	&genmii_phy_def,
 	NULL
 };
diff --git a/drivers/net/ibm_newemac/phy.h b/drivers/net/ibm_newemac/phy.h
index 1b65c81..5d2bf4c 100644
--- a/drivers/net/ibm_newemac/phy.h
+++ b/drivers/net/ibm_newemac/phy.h
@@ -57,6 +57,7 @@ struct mii_phy {
 				   or determined automaticaly */
 	int address;		/* PHY address */
 	int mode;		/* PHY mode */
+	int gpcs_address;	/* GPCS PHY address */
 
 	/* 1: autoneg enabled, 0: disabled */
 	int autoneg;
@@ -81,5 +82,6 @@ struct mii_phy {
  */
 int emac_mii_phy_probe(struct mii_phy *phy, int address);
 int emac_mii_reset_phy(struct mii_phy *phy);
+int emac_mii_reset_gpcs(struct mii_phy *phy);
 
 #endif /* __IBM_NEWEMAC_PHY_H */
-- 
cgit v1.1


From 0bb08107edb3d38b89be8fb623b46df73f2aa8c8 Mon Sep 17 00:00:00 2001
From: Johann Felix Soden <johfel@users.sourceforge.net>
Date: Sun, 21 Sep 2008 09:02:36 +0000
Subject: powerpc/iseries: Remove unused variable in viodasd.c

The variable statindex in send_request is never read, so remove it.

Signed-off-by: Johann Felix Soden <johfel@users.sourceforge.net>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/block/viodasd.c | 3 ---
 1 file changed, 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index f1c8feb..1730d29 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -249,7 +249,6 @@ static int send_request(struct request *req)
 	struct HvLpEvent *hev;
 	struct scatterlist sg[VIOMAXBLOCKDMA];
 	int sgindex;
-	int statindex;
 	struct viodasd_device *d;
 	unsigned long flags;
 
@@ -258,11 +257,9 @@ static int send_request(struct request *req)
 	if (rq_data_dir(req) == READ) {
 		direction = DMA_FROM_DEVICE;
 		viocmd = viomajorsubtype_blockio | vioblockread;
-		statindex = 0;
 	} else {
 		direction = DMA_TO_DEVICE;
 		viocmd = viomajorsubtype_blockio | vioblockwrite;
-		statindex = 1;
 	}
 
         d = req->rq_disk->private_data;
-- 
cgit v1.1


From a897ea13f7a801e6baba8d4985f459042712244c Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Wed, 8 Oct 2008 09:02:11 -0600
Subject: powerpc/mpc5200: fix build warnings on mpc52xx_psc_spi driver

The register definitions have been changed for the mpc5200 PSC ports
to cover some of the changes in the mpc5200b.  One change is that the
ccr register is now a u32 instead of a u16.  However, for the purposes
of this driver we want to continue to use 16 bit access to avoid
changing the existing (working) behaviour.

This patch allows the driver to continue to do 16 bit accesses without
the compiler complaining about it.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/spi/mpc52xx_psc_spi.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

(limited to 'drivers')

diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c
index 25eda71..cdb3d31 100644
--- a/drivers/spi/mpc52xx_psc_spi.c
+++ b/drivers/spi/mpc52xx_psc_spi.c
@@ -108,13 +108,13 @@ static void mpc52xx_psc_spi_activate_cs(struct spi_device *spi)
 	 * Because psc->ccr is defined as 16bit register instead of 32bit
 	 * just set the lower byte of BitClkDiv
 	 */
-	ccr = in_be16(&psc->ccr);
+	ccr = in_be16((u16 __iomem *)&psc->ccr);
 	ccr &= 0xFF00;
 	if (cs->speed_hz)
 		ccr |= (MCLK / cs->speed_hz - 1) & 0xFF;
 	else /* by default SPI Clk 1MHz */
 		ccr |= (MCLK / 1000000 - 1) & 0xFF;
-	out_be16(&psc->ccr, ccr);
+	out_be16((u16 __iomem *)&psc->ccr, ccr);
 	mps->bits_per_word = cs->bits_per_word;
 
 	if (mps->activate_cs)
@@ -347,7 +347,7 @@ static int mpc52xx_psc_spi_port_config(int psc_id, struct mpc52xx_psc_spi *mps)
 	/* Configure 8bit codec mode as a SPI master and use EOF flags */
 	/* SICR_SIM_CODEC8|SICR_GENCLK|SICR_SPI|SICR_MSTR|SICR_USEEOF */
 	out_be32(&psc->sicr, 0x0180C800);
-	out_be16(&psc->ccr, 0x070F); /* by default SPI Clk 1MHz */
+	out_be16((u16 __iomem *)&psc->ccr, 0x070F); /* default SPI Clk 1MHz */
 
 	/* Set 2ms DTL delay */
 	out_8(&psc->ctur, 0x00);
-- 
cgit v1.1


From 618b26d52843c0f85b8eb143cf2695d7f6fd072d Mon Sep 17 00:00:00 2001
From: Wolfgang Grandegger <wg@grandegger.com>
Date: Wed, 8 Oct 2008 11:36:42 -0600
Subject: i2c-mpc: suppress I2C device probing

This patch suppresses I2C device probing by clearing the class field
of the "struct i2c_adapter" for the MPC I2C bus adapters. Some board
configurations which rely on probing must be fixed up by adding a
proper I2C device node to the DTS file, like the TQM85xx modules.

Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/i2c/busses/i2c-mpc.c | 1 -
 1 file changed, 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index 27443f0..a9a45fc 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -312,7 +312,6 @@ static struct i2c_adapter mpc_ops = {
 	.name = "MPC adapter",
 	.id = I2C_HW_MPC107,
 	.algo = &mpc_algo,
-	.class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
 	.timeout = 1,
 };
 
-- 
cgit v1.1


From 4c3ed7d61bd474380e0d3e1eb0da164942f7c84e Mon Sep 17 00:00:00 2001
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Tue, 23 Sep 2008 14:12:19 +0400
Subject: OF: add fsl,mcu-mpc8349emitx to the exception list

of/base.c matches on the first (most specific) entries, which isn't
quite practical but it was discussed[1] that this won't change.

The bindings specifies verbose information for the devices, but
it doesn't fit in the I2C ID's 20 characters limit. The limit won't
change[2], and the bindings won't change either as they're correct.

So we have to put an exception for the MPC8349E-mITX-compatible
MCUs.

[1] http://www.mail-archive.com/linuxppc-dev@ozlabs.org/msg21196.html
[2] http://www.nabble.com/-PATCH-1-2--i2c:-expand-I2C's-id.name-to-23-characters-td19577063.html

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---
 drivers/of/base.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/of/base.c b/drivers/of/base.c
index ad8ac1a..a726464 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -410,7 +410,7 @@ struct of_modalias_table {
 	char *modalias;
 };
 static struct of_modalias_table of_modalias_table[] = {
-	/* Empty for now; add entries as needed */
+	{ "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
 };
 
 /**
-- 
cgit v1.1


From 4538d0ca71b4f8991c4c0f433d7d17805738326e Mon Sep 17 00:00:00 2001
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Mon, 6 Oct 2008 07:26:54 +0000
Subject: powerpc: Fix no interrupt handling in pata_of_platform

When no interrupt is specified the pata_of_platform fills the irq_res
resource with -1, which is wrong to do for two reasons:

1. By definition, 'no irq' should be IRQ 0, not some negative integer;
2. pata_platform checks for irq_res.start > 0, but since irq_res.start
   is unsigned type, the check will be true for `-1'.

Reported-by: Steven A. Falco <sfalco@harris.com>
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/ata/pata_of_platform.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
index 408da30..1f18ad9 100644
--- a/drivers/ata/pata_of_platform.c
+++ b/drivers/ata/pata_of_platform.c
@@ -52,7 +52,7 @@ static int __devinit pata_of_platform_probe(struct of_device *ofdev,
 
 	ret = of_irq_to_resource(dn, 0, &irq_res);
 	if (ret == NO_IRQ)
-		irq_res.start = irq_res.end = -1;
+		irq_res.start = irq_res.end = 0;
 	else
 		irq_res.flags = 0;
 
-- 
cgit v1.1


From 58f467ce1476f5b2a347cee3a32275b737fbd667 Mon Sep 17 00:00:00 2001
From: Grant Likely <grant.likely@secretlab.ca>
Date: Wed, 8 Oct 2008 05:05:29 +0000
Subject: powerpc/of-bindings: Don't support linux,<modalias> "compatible"
 values

Compatible property values in the form linux,<modalias> is not documented
anywhere and using it leaks Linux implementation details into the device
tree data (which is bad).  Remove support for compatible values of this
form.

If any platforms exist which depended on this code (and I don't know of
any), then they can be fixed up by adding legacy translations to the
lookup table in this file.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/of/base.c | 25 +++++--------------------
 1 file changed, 5 insertions(+), 20 deletions(-)

(limited to 'drivers')

diff --git a/drivers/of/base.c b/drivers/of/base.c
index ad8ac1a..cd1ce7a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -420,13 +420,12 @@ static struct of_modalias_table of_modalias_table[] = {
  * @len:	Length of modalias value
  *
  * Based on the value of the compatible property, this routine will determine
- * an appropriate modalias value for a particular device tree node.  Three
- * separate methods are used to derive a modalias value.
+ * an appropriate modalias value for a particular device tree node.  Two
+ * separate methods are attempted to derive a modalias value.
  *
  * First method is to lookup the compatible value in of_modalias_table.
- * Second is to look for a "linux,<modalias>" entry in the compatible list
- * and used that for modalias.  Third is to strip off the manufacturer
- * prefix from the first compatible entry and use the remainder as modalias
+ * Second is to strip off the manufacturer prefix from the first
+ * compatible entry and use the remainder as modalias
  *
  * This routine returns 0 on success
  */
@@ -449,21 +448,7 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
 	if (!compatible)
 		return -ENODEV;
 
-	/* 2. search for linux,<modalias> entry */
-	p = compatible;
-	while (cplen > 0) {
-		if (!strncmp(p, "linux,", 6)) {
-			p += 6;
-			strlcpy(modalias, p, len);
-			return 0;
-		}
-
-		i = strlen(p) + 1;
-		p += i;
-		cplen -= i;
-	}
-
-	/* 3. take first compatible entry and strip manufacturer */
+	/* 2. take first compatible entry and strip manufacturer */
 	p = strchr(compatible, ',');
 	if (!p)
 		return -ENODEV;
-- 
cgit v1.1


From 64b60e096fa391c56f93e6216115e6757bf86b7e Mon Sep 17 00:00:00 2001
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Fri, 10 Oct 2008 04:43:17 +0000
Subject: of: Add new helper of_parse_phandles_with_args()

The helper is factored out of of_get_gpio(). Will be used by the QE
pin multiplexing functions (they need to parse the gpios = <> too).

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/of/base.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/of/gpio.c |  81 ++++++++++------------------------------
 2 files changed, 128 insertions(+), 62 deletions(-)

(limited to 'drivers')

diff --git a/drivers/of/base.c b/drivers/of/base.c
index cd1ce7a..4270eb4 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -458,3 +458,112 @@ int of_modalias_node(struct device_node *node, char *modalias, int len)
 }
 EXPORT_SYMBOL_GPL(of_modalias_node);
 
+/**
+ * of_parse_phandles_with_args - Find a node pointed by phandle in a list
+ * @np:		pointer to a device tree node containing a list
+ * @list_name:	property name that contains a list
+ * @cells_name:	property name that specifies phandles' arguments count
+ * @index:	index of a phandle to parse out
+ * @out_node:	pointer to device_node struct pointer (will be filled)
+ * @out_args:	pointer to arguments pointer (will be filled)
+ *
+ * This function is useful to parse lists of phandles and their arguments.
+ * Returns 0 on success and fills out_node and out_args, on error returns
+ * appropriate errno value.
+ *
+ * Example:
+ *
+ * phandle1: node1 {
+ * 	#list-cells = <2>;
+ * }
+ *
+ * phandle2: node2 {
+ * 	#list-cells = <1>;
+ * }
+ *
+ * node3 {
+ * 	list = <&phandle1 1 2 &phandle2 3>;
+ * }
+ *
+ * To get a device_node of the `node2' node you may call this:
+ * of_parse_phandles_with_args(node3, "list", "#list-cells", 2, &node2, &args);
+ */
+int of_parse_phandles_with_args(struct device_node *np, const char *list_name,
+				const char *cells_name, int index,
+				struct device_node **out_node,
+				const void **out_args)
+{
+	int ret = -EINVAL;
+	const u32 *list;
+	const u32 *list_end;
+	int size;
+	int cur_index = 0;
+	struct device_node *node = NULL;
+	const void *args;
+
+	list = of_get_property(np, list_name, &size);
+	if (!list) {
+		ret = -ENOENT;
+		goto err0;
+	}
+	list_end = list + size / sizeof(*list);
+
+	while (list < list_end) {
+		const u32 *cells;
+		const phandle *phandle;
+
+		phandle = list;
+		args = list + 1;
+
+		/* one cell hole in the list = <>; */
+		if (!*phandle) {
+			list++;
+			goto next;
+		}
+
+		node = of_find_node_by_phandle(*phandle);
+		if (!node) {
+			pr_debug("%s: could not find phandle\n",
+				 np->full_name);
+			goto err0;
+		}
+
+		cells = of_get_property(node, cells_name, &size);
+		if (!cells || size != sizeof(*cells)) {
+			pr_debug("%s: could not get %s for %s\n",
+				 np->full_name, cells_name, node->full_name);
+			goto err1;
+		}
+
+		/* Next phandle is at offset of one phandle cell + #cells */
+		list += 1 + *cells;
+		if (list > list_end) {
+			pr_debug("%s: insufficient arguments length\n",
+				 np->full_name);
+			goto err1;
+		}
+next:
+		if (cur_index == index)
+			break;
+
+		of_node_put(node);
+		node = NULL;
+		cur_index++;
+	}
+
+	if (!node) {
+		ret = -ENOENT;
+		goto err0;
+	}
+
+	*out_node = node;
+	*out_args = args;
+
+	return 0;
+err1:
+	of_node_put(node);
+err0:
+	pr_debug("%s failed with status %d\n", __func__, ret);
+	return ret;
+}
+EXPORT_SYMBOL(of_parse_phandles_with_args);
diff --git a/drivers/of/gpio.c b/drivers/of/gpio.c
index 1c9cab8..7cd7301 100644
--- a/drivers/of/gpio.c
+++ b/drivers/of/gpio.c
@@ -28,78 +28,35 @@
  */
 int of_get_gpio(struct device_node *np, int index)
 {
-	int ret = -EINVAL;
+	int ret;
 	struct device_node *gc;
 	struct of_gpio_chip *of_gc = NULL;
 	int size;
-	const u32 *gpios;
-	u32 nr_cells;
-	int i;
 	const void *gpio_spec;
 	const u32 *gpio_cells;
-	int gpio_index = 0;
 
-	gpios = of_get_property(np, "gpios", &size);
-	if (!gpios) {
-		ret = -ENOENT;
+	ret = of_parse_phandles_with_args(np, "gpios", "#gpio-cells", index,
+					  &gc, &gpio_spec);
+	if (ret) {
+		pr_debug("%s: can't parse gpios property\n", __func__);
 		goto err0;
 	}
-	nr_cells = size / sizeof(u32);
-
-	for (i = 0; i < nr_cells; gpio_index++) {
-		const phandle *gpio_phandle;
-
-		gpio_phandle = gpios + i;
-		gpio_spec = gpio_phandle + 1;
-
-		/* one cell hole in the gpios = <>; */
-		if (!*gpio_phandle) {
-			if (gpio_index == index)
-				return -ENOENT;
-			i++;
-			continue;
-		}
-
-		gc = of_find_node_by_phandle(*gpio_phandle);
-		if (!gc) {
-			pr_debug("%s: could not find phandle for gpios\n",
-				 np->full_name);
-			goto err0;
-		}
-
-		of_gc = gc->data;
-		if (!of_gc) {
-			pr_debug("%s: gpio controller %s isn't registered\n",
-				 np->full_name, gc->full_name);
-			goto err1;
-		}
-
-		gpio_cells = of_get_property(gc, "#gpio-cells", &size);
-		if (!gpio_cells || size != sizeof(*gpio_cells) ||
-				*gpio_cells != of_gc->gpio_cells) {
-			pr_debug("%s: wrong #gpio-cells for %s\n",
-				 np->full_name, gc->full_name);
-			goto err1;
-		}
-
-		/* Next phandle is at phandle cells + #gpio-cells */
-		i += sizeof(*gpio_phandle) / sizeof(u32) + *gpio_cells;
-		if (i >= nr_cells + 1) {
-			pr_debug("%s: insufficient gpio-spec length\n",
-				 np->full_name);
-			goto err1;
-		}
-
-		if (gpio_index == index)
-			break;
-
-		of_gc = NULL;
-		of_node_put(gc);
-	}
 
+	of_gc = gc->data;
 	if (!of_gc) {
-		ret = -ENOENT;
-		goto err0;
+		pr_debug("%s: gpio controller %s isn't registered\n",
+			 np->full_name, gc->full_name);
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	gpio_cells = of_get_property(gc, "#gpio-cells", &size);
+	if (!gpio_cells || size != sizeof(*gpio_cells) ||
+			*gpio_cells != of_gc->gpio_cells) {
+		pr_debug("%s: wrong #gpio-cells for %s\n",
+			 np->full_name, gc->full_name);
+		ret = -EINVAL;
+		goto err1;
 	}
 
 	ret = of_gc->xlate(of_gc, np, gpio_spec);
-- 
cgit v1.1


From 7e7385ce4115830bf5e0b43d62087a94871b78de Mon Sep 17 00:00:00 2001
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Tue, 23 Sep 2008 18:12:19 +0400
Subject: OF: add fsl,mcu-mpc8349emitx to the exception list

of/base.c matches on the first (most specific) entries, which isn't
quite practical but it was discussed[1] that this won't change.

The bindings specifies verbose information for the devices, but
it doesn't fit in the I2C ID's 20 characters limit. The limit won't
change[2], and the bindings won't change either as they're correct.

So we have to put an exception for the MPC8349E-mITX-compatible
MCUs.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/of/base.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

(limited to 'drivers')

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 4270eb4..7c79e94 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -410,7 +410,7 @@ struct of_modalias_table {
 	char *modalias;
 };
 static struct of_modalias_table of_modalias_table[] = {
-	/* Empty for now; add entries as needed */
+	{ "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" },
 };
 
 /**
-- 
cgit v1.1


From d6c3db83c5567b3a4d8d0bf33dc5687abdf65274 Mon Sep 17 00:00:00 2001
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Tue, 23 Sep 2008 18:13:00 +0400
Subject: i2c: MPC8349E-mITX Power Management and GPIO expander driver

On MPC8349E-mITX, MPC8315E-RDB and MPC837x-RDB boards there is a
Freescale MC9S08QG8 (MCU) chip with the custom firmware
pre-programmed. The chip is used to power-off the board by the
software, and to control some GPIO pins.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
---
 drivers/i2c/chips/Kconfig            |  11 ++
 drivers/i2c/chips/Makefile           |   1 +
 drivers/i2c/chips/mcu_mpc8349emitx.c | 209 +++++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+)
 create mode 100644 drivers/i2c/chips/mcu_mpc8349emitx.c

(limited to 'drivers')

diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
index a95cb94..1735682 100644
--- a/drivers/i2c/chips/Kconfig
+++ b/drivers/i2c/chips/Kconfig
@@ -172,4 +172,15 @@ config MENELAUS
 	  and other features that are often used in portable devices like
 	  cell phones and PDAs.
 
+config MCU_MPC8349EMITX
+	tristate "MPC8349E-mITX MCU driver"
+	depends on I2C && PPC_83xx
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	help
+	  Say Y here to enable soft power-off functionality on the Freescale
+	  boards with the MPC8349E-mITX-compatible MCU chips. This driver will
+	  also register MCU GPIOs with the generic GPIO API, so you'll able
+	  to use MCU pins as GPIOs.
+
 endmenu
diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
index 39e3e69..ca520fa 100644
--- a/drivers/i2c/chips/Makefile
+++ b/drivers/i2c/chips/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_ISP1301_OMAP)	+= isp1301_omap.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 obj-$(CONFIG_SENSORS_TSL2550)	+= tsl2550.o
+obj-$(CONFIG_MCU_MPC8349EMITX)	+= mcu_mpc8349emitx.o
 
 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
 EXTRA_CFLAGS += -DDEBUG
diff --git a/drivers/i2c/chips/mcu_mpc8349emitx.c b/drivers/i2c/chips/mcu_mpc8349emitx.c
new file mode 100644
index 0000000..82a9bcb
--- /dev/null
+++ b/drivers/i2c/chips/mcu_mpc8349emitx.c
@@ -0,0 +1,209 @@
+/*
+ * Power Management and GPIO expander driver for MPC8349E-mITX-compatible MCU
+ *
+ * Copyright (c) 2008  MontaVista Software, Inc.
+ *
+ * Author: Anton Vorontsov <avorontsov@ru.mvista.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <asm/prom.h>
+#include <asm/machdep.h>
+
+/*
+ * I don't have specifications for the MCU firmware, I found this register
+ * and bits positions by the trial&error method.
+ */
+#define MCU_REG_CTRL	0x20
+#define MCU_CTRL_POFF	0x40
+
+#define MCU_NUM_GPIO	2
+
+struct mcu {
+	struct mutex lock;
+	struct device_node *np;
+	struct i2c_client *client;
+	struct of_gpio_chip of_gc;
+	u8 reg_ctrl;
+};
+
+static struct mcu *glob_mcu;
+
+static void mcu_power_off(void)
+{
+	struct mcu *mcu = glob_mcu;
+
+	pr_info("Sending power-off request to the MCU...\n");
+	mutex_lock(&mcu->lock);
+	i2c_smbus_write_byte_data(glob_mcu->client, MCU_REG_CTRL,
+				  mcu->reg_ctrl | MCU_CTRL_POFF);
+	mutex_unlock(&mcu->lock);
+}
+
+static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	struct of_gpio_chip *of_gc = to_of_gpio_chip(gc);
+	struct mcu *mcu = container_of(of_gc, struct mcu, of_gc);
+	u8 bit = 1 << (4 + gpio);
+
+	mutex_lock(&mcu->lock);
+	if (val)
+		mcu->reg_ctrl &= ~bit;
+	else
+		mcu->reg_ctrl |= bit;
+
+	i2c_smbus_write_byte_data(mcu->client, MCU_REG_CTRL, mcu->reg_ctrl);
+	mutex_unlock(&mcu->lock);
+}
+
+static int mcu_gpio_dir_out(struct gpio_chip *gc, unsigned int gpio, int val)
+{
+	mcu_gpio_set(gc, gpio, val);
+	return 0;
+}
+
+static int mcu_gpiochip_add(struct mcu *mcu)
+{
+	struct device_node *np;
+	struct of_gpio_chip *of_gc = &mcu->of_gc;
+	struct gpio_chip *gc = &of_gc->gc;
+	int ret;
+
+	np = of_find_compatible_node(NULL, NULL, "fsl,mcu-mpc8349emitx");
+	if (!np)
+		return -ENODEV;
+
+	gc->owner = THIS_MODULE;
+	gc->label = np->full_name;
+	gc->can_sleep = 1;
+	gc->ngpio = MCU_NUM_GPIO;
+	gc->base = -1;
+	gc->set = mcu_gpio_set;
+	gc->direction_output = mcu_gpio_dir_out;
+	of_gc->gpio_cells = 2;
+	of_gc->xlate = of_gpio_simple_xlate;
+
+	np->data = of_gc;
+	mcu->np = np;
+
+	/*
+	 * We don't want to lose the node, its ->data and ->full_name...
+	 * So, if succeeded, we don't put the node here.
+	 */
+	ret = gpiochip_add(gc);
+	if (ret)
+		of_node_put(np);
+	return ret;
+}
+
+static int mcu_gpiochip_remove(struct mcu *mcu)
+{
+	int ret;
+
+	ret = gpiochip_remove(&mcu->of_gc.gc);
+	if (ret)
+		return ret;
+	of_node_put(mcu->np);
+
+	return 0;
+}
+
+static int __devinit mcu_probe(struct i2c_client *client,
+			       const struct i2c_device_id *id)
+{
+	struct mcu *mcu;
+	int ret;
+
+	mcu = kzalloc(sizeof(*mcu), GFP_KERNEL);
+	if (!mcu)
+		return -ENOMEM;
+
+	mutex_init(&mcu->lock);
+	mcu->client = client;
+	i2c_set_clientdata(client, mcu);
+
+	ret = i2c_smbus_read_byte_data(mcu->client, MCU_REG_CTRL);
+	if (ret < 0)
+		goto err;
+	mcu->reg_ctrl = ret;
+
+	ret = mcu_gpiochip_add(mcu);
+	if (ret)
+		goto err;
+
+	/* XXX: this is potentially racy, but there is no lock for ppc_md */
+	if (!ppc_md.power_off) {
+		glob_mcu = mcu;
+		ppc_md.power_off = mcu_power_off;
+		dev_info(&client->dev, "will provide power-off service\n");
+	}
+
+	return 0;
+err:
+	kfree(mcu);
+	return ret;
+}
+
+static int __devexit mcu_remove(struct i2c_client *client)
+{
+	struct mcu *mcu = i2c_get_clientdata(client);
+	int ret;
+
+	if (glob_mcu == mcu) {
+		ppc_md.power_off = NULL;
+		glob_mcu = NULL;
+	}
+
+	ret = mcu_gpiochip_remove(mcu);
+	if (ret)
+		return ret;
+	i2c_set_clientdata(client, NULL);
+	kfree(mcu);
+	return 0;
+}
+
+static const struct i2c_device_id mcu_ids[] = {
+	{ "mcu-mpc8349emitx", },
+	{},
+};
+MODULE_DEVICE_TABLE(i2c, mcu_ids);
+
+static struct i2c_driver mcu_driver = {
+	.driver = {
+		.name = "mcu-mpc8349emitx",
+		.owner = THIS_MODULE,
+	},
+	.probe = mcu_probe,
+	.remove	= __devexit_p(mcu_remove),
+	.id_table = mcu_ids,
+};
+
+static int __init mcu_init(void)
+{
+	return i2c_add_driver(&mcu_driver);
+}
+module_init(mcu_init);
+
+static void __exit mcu_exit(void)
+{
+	i2c_del_driver(&mcu_driver);
+}
+module_exit(mcu_exit);
+
+MODULE_DESCRIPTION("Power Management and GPIO expander driver for "
+		   "MPC8349E-mITX-compatible MCU");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
-- 
cgit v1.1


From eef2622a9fcfa964073333ea72c7c9cd20ad45e6 Mon Sep 17 00:00:00 2001
From: Christian Borntraeger <borntraeger@de.ibm.com>
Date: Sun, 12 Oct 2008 21:51:31 +0000
Subject: hvc_console: Fix free_irq in spinlocked section

    commit 611e097d7707741a336a0677d9d69bec40f29f3d
    Author: Christian Borntraeger <borntraeger@de.ibm.com>
    hvc_console: rework setup to replace irq functions with callbacks
    introduced a spinlock recursion problem. The notifier_del is
    called with a lock held, and in turns calls free_irq which then
    complains when manipulating procfs. This fixes it by moving the
    call to the notifier to outside of the locked section.

Signed-off-by: Christian Borntraeger<borntraeger@de.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/char/hvc_console.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

(limited to 'drivers')

diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index fd64137..f2e4caf 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -367,13 +367,13 @@ static void hvc_close(struct tty_struct *tty, struct file * filp)
 	spin_lock_irqsave(&hp->lock, flags);
 
 	if (--hp->count == 0) {
-		if (hp->ops->notifier_del)
-			hp->ops->notifier_del(hp, hp->data);
-
 		/* We are done with the tty pointer now. */
 		hp->tty = NULL;
 		spin_unlock_irqrestore(&hp->lock, flags);
 
+		if (hp->ops->notifier_del)
+			hp->ops->notifier_del(hp, hp->data);
+
 		/*
 		 * Chain calls chars_in_buffer() and returns immediately if
 		 * there is no buffered data otherwise sleeps on a wait queue
@@ -416,11 +416,11 @@ static void hvc_hangup(struct tty_struct *tty)
 	hp->n_outbuf = 0;
 	hp->tty = NULL;
 
+	spin_unlock_irqrestore(&hp->lock, flags);
+
 	if (hp->ops->notifier_del)
 			hp->ops->notifier_del(hp, hp->data);
 
-	spin_unlock_irqrestore(&hp->lock, flags);
-
 	while(temp_open_count) {
 		--temp_open_count;
 		kref_put(&hp->kref, destroy_hvc_struct);
-- 
cgit v1.1