* [PATCH v2 1/4] [libata] pata_platform: make probe and remove functions device type neutral
From: Anton Vorontsov @ 2007-12-04 17:06 UTC (permalink / raw)
To: linuxppc-dev, linux-ide
Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071204170442.GA10460@localhost.localdomain>
Split pata_platform_{probe,remove} into two pieces:
1. pata_platform_{probe,remove} -- platform_device-dependant bits;
2. __ptata_platform_{probe,remove} -- device type neutral bits.
This is done to not duplicate code for the OF-platform driver.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
drivers/ata/pata_platform.c | 143 ++++++++++++++++++++++++-----------------
include/linux/pata_platform.h | 9 +++
2 files changed, 94 insertions(+), 58 deletions(-)
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index ac03a90..d4cb231 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -93,14 +93,9 @@ static struct ata_port_operations pata_platform_port_ops = {
};
static void pata_platform_setup_port(struct ata_ioports *ioaddr,
- struct pata_platform_info *info)
+ unsigned int shift)
{
- unsigned int shift = 0;
-
/* Fixup the port shift for platforms that need it */
- if (info && info->ioport_shift)
- shift = info->ioport_shift;
-
ioaddr->data_addr = ioaddr->cmd_addr + (ATA_REG_DATA << shift);
ioaddr->error_addr = ioaddr->cmd_addr + (ATA_REG_ERR << shift);
ioaddr->feature_addr = ioaddr->cmd_addr + (ATA_REG_FEATURE << shift);
@@ -114,8 +109,12 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
}
/**
- * pata_platform_probe - attach a platform interface
- * @pdev: platform device
+ * __pata_platform_probe - attach a platform interface
+ * @dev: device
+ * @io_res: Resource representing I/O base
+ * @ctl_res: Resource representing CTL base
+ * @irq_res: Resource representing IRQ and its flags
+ * @ioport_shift: I/O port shift
*
* Register a platform bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing.
@@ -135,42 +134,18 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
*
* If no IRQ resource is present, PIO polling mode is used instead.
*/
-static int __devinit pata_platform_probe(struct platform_device *pdev)
+int __devinit __pata_platform_probe(struct device *dev,
+ struct resource *io_res,
+ struct resource *ctl_res,
+ struct resource *irq_res,
+ unsigned int ioport_shift,
+ int __pio_mask)
{
- struct resource *io_res, *ctl_res;
struct ata_host *host;
struct ata_port *ap;
- struct pata_platform_info *pp_info;
unsigned int mmio;
- int irq;
-
- /*
- * Simple resource validation ..
- */
- if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
- dev_err(&pdev->dev, "invalid number of resources\n");
- return -EINVAL;
- }
-
- /*
- * Get the I/O base first
- */
- io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
- if (io_res == NULL) {
- io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (unlikely(io_res == NULL))
- return -EINVAL;
- }
-
- /*
- * Then the CTL base
- */
- ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
- if (ctl_res == NULL) {
- ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
- if (unlikely(ctl_res == NULL))
- return -EINVAL;
- }
+ int irq = 0;
+ int irq_flags = 0;
/*
* Check for MMIO
@@ -181,20 +156,21 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
/*
* And the IRQ
*/
- irq = platform_get_irq(pdev, 0);
- if (irq < 0)
- irq = 0; /* no irq */
+ if (irq_res && irq_res->start > 0) {
+ irq = irq_res->start;
+ irq_flags = irq_res->flags;
+ }
/*
* Now that that's out of the way, wire up the port..
*/
- host = ata_host_alloc(&pdev->dev, 1);
+ host = ata_host_alloc(dev, 1);
if (!host)
return -ENOMEM;
ap = host->ports[0];
ap->ops = &pata_platform_port_ops;
- ap->pio_mask = pio_mask;
+ ap->pio_mask = __pio_mask;
ap->flags |= ATA_FLAG_SLAVE_POSS;
/*
@@ -209,25 +185,24 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
* Handle the MMIO case
*/
if (mmio) {
- ap->ioaddr.cmd_addr = devm_ioremap(&pdev->dev, io_res->start,
+ ap->ioaddr.cmd_addr = devm_ioremap(dev, io_res->start,
io_res->end - io_res->start + 1);
- ap->ioaddr.ctl_addr = devm_ioremap(&pdev->dev, ctl_res->start,
+ ap->ioaddr.ctl_addr = devm_ioremap(dev, ctl_res->start,
ctl_res->end - ctl_res->start + 1);
} else {
- ap->ioaddr.cmd_addr = devm_ioport_map(&pdev->dev, io_res->start,
+ ap->ioaddr.cmd_addr = devm_ioport_map(dev, io_res->start,
io_res->end - io_res->start + 1);
- ap->ioaddr.ctl_addr = devm_ioport_map(&pdev->dev, ctl_res->start,
+ ap->ioaddr.ctl_addr = devm_ioport_map(dev, ctl_res->start,
ctl_res->end - ctl_res->start + 1);
}
if (!ap->ioaddr.cmd_addr || !ap->ioaddr.ctl_addr) {
- dev_err(&pdev->dev, "failed to map IO/CTL base\n");
+ dev_err(dev, "failed to map IO/CTL base\n");
return -ENOMEM;
}
ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- pp_info = pdev->dev.platform_data;
- pata_platform_setup_port(&ap->ioaddr, pp_info);
+ pata_platform_setup_port(&ap->ioaddr, ioport_shift);
ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
(unsigned long long)io_res->start,
@@ -235,26 +210,78 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
/* activate */
return ata_host_activate(host, irq, irq ? ata_interrupt : NULL,
- pp_info ? pp_info->irq_flags : 0,
- &pata_platform_sht);
+ irq_flags, &pata_platform_sht);
}
+EXPORT_SYMBOL_GPL(__pata_platform_probe);
/**
- * pata_platform_remove - unplug a platform interface
- * @pdev: platform device
+ * __pata_platform_remove - unplug a platform interface
+ * @dev: device
*
* A platform bus ATA device has been unplugged. Perform the needed
* cleanup. Also called on module unload for any active devices.
*/
-static int __devexit pata_platform_remove(struct platform_device *pdev)
+int __devexit __pata_platform_remove(struct device *dev)
{
- struct device *dev = &pdev->dev;
struct ata_host *host = dev_get_drvdata(dev);
ata_host_detach(host);
return 0;
}
+EXPORT_SYMBOL_GPL(__pata_platform_remove);
+
+static int __devinit pata_platform_probe(struct platform_device *pdev)
+{
+ struct resource *io_res;
+ struct resource *ctl_res;
+ struct resource *irq_res;
+ struct pata_platform_info *pp_info = pdev->dev.platform_data;
+
+ /*
+ * Simple resource validation ..
+ */
+ if ((pdev->num_resources != 3) && (pdev->num_resources != 2)) {
+ dev_err(&pdev->dev, "invalid number of resources\n");
+ return -EINVAL;
+ }
+
+ /*
+ * Get the I/O base first
+ */
+ io_res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+ if (io_res == NULL) {
+ io_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (unlikely(io_res == NULL))
+ return -EINVAL;
+ }
+
+ /*
+ * Then the CTL base
+ */
+ ctl_res = platform_get_resource(pdev, IORESOURCE_IO, 1);
+ if (ctl_res == NULL) {
+ ctl_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (unlikely(ctl_res == NULL))
+ return -EINVAL;
+ }
+
+ /*
+ * And the IRQ
+ */
+ irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (irq_res)
+ irq_res->flags = pp_info ? pp_info->irq_flags : 0;
+
+ return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
+ pp_info ? pp_info->ioport_shift : 0,
+ pio_mask);
+}
+
+static int __devexit pata_platform_remove(struct platform_device *pdev)
+{
+ return __pata_platform_remove(&pdev->dev);
+}
static struct platform_driver pata_platform_driver = {
.probe = pata_platform_probe,
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 5799e8d..6a7a92d 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -15,4 +15,13 @@ struct pata_platform_info {
unsigned int irq_flags;
};
+extern int __devinit __pata_platform_probe(struct device *dev,
+ struct resource *io_res,
+ struct resource *ctl_res,
+ struct resource *irq_res,
+ unsigned int ioport_shift,
+ int __pio_mask);
+
+extern int __devexit __pata_platform_remove(struct device *dev);
+
#endif /* __LINUX_PATA_PLATFORM_H */
--
1.5.2.2
^ permalink raw reply related
* [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Anton Vorontsov @ 2007-12-04 17:07 UTC (permalink / raw)
To: linuxppc-dev, linux-ide
Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071204170442.GA10460@localhost.localdomain>
This driver nicely wraps around pata_platform library functions,
and provides OF platform bus bindings to the PATA devices.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
drivers/ata/Kconfig | 10 ++++
drivers/ata/Makefile | 1 +
drivers/ata/pata_of_platform.c | 102 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 113 insertions(+), 0 deletions(-)
create mode 100644 drivers/ata/pata_of_platform.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ba63619..5a492fa 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -614,6 +614,16 @@ config PATA_PLATFORM
If unsure, say N.
+config PATA_OF_PLATFORM
+ tristate "OpenFirmware platform device PATA support"
+ depends on PATA_PLATFORM && PPC_OF
+ help
+ This option enables support for generic directly connected ATA
+ devices commonly found on embedded systems with OpenFirmware
+ bindings.
+
+ If unsure, say N.
+
config PATA_ICSIDE
tristate "Acorn ICS PATA support"
depends on ARM && ARCH_ACORN
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index b13feb2..ebcee64 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
+obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
# Should be last but two libata driver
obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
new file mode 100644
index 0000000..738f9e0
--- /dev/null
+++ b/drivers/ata/pata_of_platform.c
@@ -0,0 +1,102 @@
+/*
+ * OF-platform PATA driver
+ *
+ * Copyright (c) 2007 MontaVista Software, Inc.
+ * 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 (Version 2) as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pata_platform.h>
+
+static int __devinit pata_of_platform_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ int ret;
+ struct device_node *dn = ofdev->node;
+ struct resource io_res;
+ struct resource ctl_res;
+ struct resource irq_res;
+ unsigned int reg_shift = 0;
+ int pio_mode = 0;
+ int pio_mask;
+ const u32 *prop;
+
+ ret = of_address_to_resource(dn, 0, &io_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get IO address from "
+ "device tree\n");
+ return -EINVAL;
+ }
+
+ ret = of_address_to_resource(dn, 1, &ctl_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get CTL address from "
+ "device tree\n");
+ return -EINVAL;
+ }
+
+ ret = of_irq_to_resource(dn, 0, &irq_res);
+ if (ret == NO_IRQ)
+ irq_res.start = irq_res.end = -1;
+ else
+ irq_res.flags = 0;
+
+ prop = (u32 *)of_get_property(dn, "reg-shift", NULL);
+ if (prop)
+ reg_shift = *prop;
+
+ prop = (u32 *)of_get_property(dn, "pio-mode", NULL);
+ if (prop) {
+ pio_mode = *prop;
+ if (pio_mode > 6) {
+ dev_err(&ofdev->dev, "invalid pio-mode\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
+ }
+
+ pio_mask = 1 << pio_mode;
+ pio_mask |= (1 << pio_mode) - 1;
+
+ return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res,
+ reg_shift, pio_mask);
+}
+
+static int __devexit pata_of_platform_remove(struct of_device *ofdev)
+{
+ return __pata_platform_remove(&ofdev->dev);
+}
+
+static struct of_device_id pata_of_platform_match[] = {
+ { .compatible = "ata-generic", },
+};
+
+static struct of_platform_driver pata_of_platform_driver = {
+ .name = "pata_of_platform",
+ .match_table = pata_of_platform_match,
+ .probe = pata_of_platform_probe,
+ .remove = __devexit_p(pata_of_platform_remove),
+};
+
+static int __init pata_of_platform_init(void)
+{
+ return of_register_platform_driver(&pata_of_platform_driver);
+}
+module_init(pata_of_platform_init);
+
+static void __exit pata_of_platform_exit(void)
+{
+ of_unregister_platform_driver(&pata_of_platform_driver);
+}
+module_exit(pata_of_platform_exit);
+
+MODULE_DESCRIPTION("OF-platform PATA driver");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
--
1.5.2.2
^ permalink raw reply related
* [PATCH v2 3/4] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
From: Anton Vorontsov @ 2007-12-04 17:07 UTC (permalink / raw)
To: linuxppc-dev, linux-ide
Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071204170442.GA10460@localhost.localdomain>
This patch adds localbus and pata nodes to use CF IDE interface
on MPC8349E-mITX boards.
Patch also adds code to probe localbus.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/boot/dts/mpc8349emitx.dts | 18 +++++++++++++++++-
arch/powerpc/platforms/83xx/mpc834x_itx.c | 17 +++++++++++++++++
2 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 5072f6d..c459b0a 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -249,6 +249,22 @@
device_type = "pci";
};
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8349emitx-localbus",
+ "fsl,mpc8349e-localbus",
+ "fsl,pq2pro-localbus";
+ reg = <e0005000 d8>;
+ ranges = <3 0 f0000000 210>;
-
+ pata@3,0 {
+ compatible = "fsl,mpc8349emitx-pata", "ata-generic";
+ reg = <3 0 10 3 20c 4>;
+ reg-shift = <1>;
+ pio-mode = <6>;
+ interrupts = <17 8>;
+ interrupt-parent = <&ipic>;
+ };
+ };
};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..ea5f176 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
+#include <linux/of_platform.h>
#include <asm/system.h>
#include <asm/atomic.h>
@@ -37,6 +38,22 @@
#include "mpc83xx.h"
+static struct of_device_id mpc834x_itx_ids[] = {
+ { .name = "localbus", },
+ {},
+};
+
+static int __init mpc834x_itx_declare_of_platform_devices(void)
+{
+ if (!machine_is(mpc834x_itx))
+ return 0;
+
+ of_platform_bus_probe(NULL, mpc834x_itx_ids, NULL);
+
+ return 0;
+}
+device_initcall(mpc834x_itx_declare_of_platform_devices);
+
/* ************************************************************************
*
* Setup the architecture
--
1.5.2.2
^ permalink raw reply related
* [PATCH v2 4/4] [libata] pata_platform: s/ioport_shift/reg_shift/g
From: Anton Vorontsov @ 2007-12-04 17:07 UTC (permalink / raw)
To: linuxppc-dev, linux-ide
Cc: Jeff Garzik, Arnd Bergmann, Paul Mundt, Olof Johansson
In-Reply-To: <20071204170442.GA10460@localhost.localdomain>
This patch renames ioport_shift member of pata_platform_info
structure to reg_shift. Users of pata_platform are followed
appropriately.
Rationale of that change is: shifting applies to the whole memory
mapped region, not only to the command block of the ATA registers,
despite the fact that shifting is meaningless for ctl register.
This patch should make Sergei Shtylyov a bit more happy. ;-)
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/arm/mach-rpc/riscpc.c | 2 +-
arch/blackfin/mach-bf527/boards/ezkit.c | 2 +-
arch/blackfin/mach-bf533/boards/cm_bf533.c | 2 +-
arch/blackfin/mach-bf533/boards/ezkit.c | 2 +-
arch/blackfin/mach-bf533/boards/stamp.c | 2 +-
arch/blackfin/mach-bf537/boards/cm_bf537.c | 2 +-
arch/blackfin/mach-bf537/boards/generic_board.c | 2 +-
arch/blackfin/mach-bf537/boards/stamp.c | 2 +-
arch/blackfin/mach-bf561/boards/cm_bf561.c | 2 +-
arch/blackfin/mach-bf561/boards/ezkit.c | 2 +-
arch/sh/boards/landisk/setup.c | 2 +-
arch/sh/boards/renesas/r7780rp/setup.c | 2 +-
arch/sh/boards/renesas/rts7751r2d/setup.c | 2 +-
drivers/ata/pata_platform.c | 8 ++++----
drivers/ide/legacy/ide_platform.c | 4 ++--
include/linux/pata_platform.h | 4 ++--
16 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index a454451..be413c1 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -161,7 +161,7 @@ static struct platform_device serial_device = {
};
static struct pata_platform_info pata_platform_data = {
- .ioport_shift = 2,
+ .reg_shift = 2,
};
static struct resource pata_resources[] = {
diff --git a/arch/blackfin/mach-bf527/boards/ezkit.c b/arch/blackfin/mach-bf527/boards/ezkit.c
index 003e2ac..c9b20bd 100644
--- a/arch/blackfin/mach-bf527/boards/ezkit.c
+++ b/arch/blackfin/mach-bf527/boards/ezkit.c
@@ -685,7 +685,7 @@ static struct platform_device bfin_sport1_uart_device = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf533/boards/cm_bf533.c b/arch/blackfin/mach-bf533/boards/cm_bf533.c
index 21df2f3..6cc697d 100644
--- a/arch/blackfin/mach-bf533/boards/cm_bf533.c
+++ b/arch/blackfin/mach-bf533/boards/cm_bf533.c
@@ -289,7 +289,7 @@ static struct platform_device isp1362_hcd_device = {
#define PATA_INT 38
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 2,
+ .reg_shift = 2,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf533/boards/ezkit.c b/arch/blackfin/mach-bf533/boards/ezkit.c
index be85203..030dc64 100644
--- a/arch/blackfin/mach-bf533/boards/ezkit.c
+++ b/arch/blackfin/mach-bf533/boards/ezkit.c
@@ -223,7 +223,7 @@ static struct platform_device bfin_uart_device = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf533/boards/stamp.c b/arch/blackfin/mach-bf533/boards/stamp.c
index 8fde8d8..6ff0b88 100644
--- a/arch/blackfin/mach-bf533/boards/stamp.c
+++ b/arch/blackfin/mach-bf533/boards/stamp.c
@@ -340,7 +340,7 @@ static struct platform_device bfin_sport1_uart_device = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf537/boards/cm_bf537.c b/arch/blackfin/mach-bf537/boards/cm_bf537.c
index c0fb06d..031da0f 100644
--- a/arch/blackfin/mach-bf537/boards/cm_bf537.c
+++ b/arch/blackfin/mach-bf537/boards/cm_bf537.c
@@ -340,7 +340,7 @@ static struct platform_device bfin_mac_device = {
#define PATA_INT 64
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 2,
+ .reg_shift = 2,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf537/boards/generic_board.c b/arch/blackfin/mach-bf537/boards/generic_board.c
index 09f4bfb..e217eb2 100644
--- a/arch/blackfin/mach-bf537/boards/generic_board.c
+++ b/arch/blackfin/mach-bf537/boards/generic_board.c
@@ -613,7 +613,7 @@ static struct platform_device bfin_sport1_uart_device = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf537/boards/stamp.c b/arch/blackfin/mach-bf537/boards/stamp.c
index 07b0dc2..daeb0d5 100644
--- a/arch/blackfin/mach-bf537/boards/stamp.c
+++ b/arch/blackfin/mach-bf537/boards/stamp.c
@@ -640,7 +640,7 @@ static struct platform_device bfin_sport1_uart_device = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_flags = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf561/boards/cm_bf561.c b/arch/blackfin/mach-bf561/boards/cm_bf561.c
index c19cd29..5628e34 100644
--- a/arch/blackfin/mach-bf561/boards/cm_bf561.c
+++ b/arch/blackfin/mach-bf561/boards/cm_bf561.c
@@ -280,7 +280,7 @@ static struct platform_device bfin_uart_device = {
#define PATA_INT 119
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 2,
+ .reg_shift = 2,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/blackfin/mach-bf561/boards/ezkit.c b/arch/blackfin/mach-bf561/boards/ezkit.c
index 4ff8f6e..6894472 100644
--- a/arch/blackfin/mach-bf561/boards/ezkit.c
+++ b/arch/blackfin/mach-bf561/boards/ezkit.c
@@ -213,7 +213,7 @@ static struct spi_board_info bfin_spi_board_info[] __initdata = {
#define PATA_INT 55
static struct pata_platform_info bfin_pata_platform_data = {
- .ioport_shift = 1,
+ .reg_shift = 1,
.irq_type = IRQF_TRIGGER_HIGH | IRQF_DISABLED,
};
diff --git a/arch/sh/boards/landisk/setup.c b/arch/sh/boards/landisk/setup.c
index eda7176..46330f7 100644
--- a/arch/sh/boards/landisk/setup.c
+++ b/arch/sh/boards/landisk/setup.c
@@ -31,7 +31,7 @@ static void landisk_power_off(void)
static struct resource cf_ide_resources[3];
static struct pata_platform_info pata_info = {
- .ioport_shift = 1,
+ .reg_shift = 1,
};
static struct platform_device cf_ide_device = {
diff --git a/arch/sh/boards/renesas/r7780rp/setup.c b/arch/sh/boards/renesas/r7780rp/setup.c
index 0fdc0bc..1fc9c9b 100644
--- a/arch/sh/boards/renesas/r7780rp/setup.c
+++ b/arch/sh/boards/renesas/r7780rp/setup.c
@@ -94,7 +94,7 @@ static struct resource cf_ide_resources[] = {
};
static struct pata_platform_info pata_info = {
- .ioport_shift = 1,
+ .reg_shift = 1,
};
static struct platform_device cf_ide_device = {
diff --git a/arch/sh/boards/renesas/rts7751r2d/setup.c b/arch/sh/boards/renesas/rts7751r2d/setup.c
index 8125d20..8bcca50 100644
--- a/arch/sh/boards/renesas/rts7751r2d/setup.c
+++ b/arch/sh/boards/renesas/rts7751r2d/setup.c
@@ -62,7 +62,7 @@ static struct resource cf_ide_resources[] = {
};
static struct pata_platform_info pata_info = {
- .ioport_shift = 1,
+ .reg_shift = 1,
};
static struct platform_device cf_ide_device = {
diff --git a/drivers/ata/pata_platform.c b/drivers/ata/pata_platform.c
index d4cb231..3e7d2eb 100644
--- a/drivers/ata/pata_platform.c
+++ b/drivers/ata/pata_platform.c
@@ -114,7 +114,7 @@ static void pata_platform_setup_port(struct ata_ioports *ioaddr,
* @io_res: Resource representing I/O base
* @ctl_res: Resource representing CTL base
* @irq_res: Resource representing IRQ and its flags
- * @ioport_shift: I/O port shift
+ * @reg_shift: I/O port shift
*
* Register a platform bus IDE interface. Such interfaces are PIO and we
* assume do not support IRQ sharing.
@@ -138,7 +138,7 @@ int __devinit __pata_platform_probe(struct device *dev,
struct resource *io_res,
struct resource *ctl_res,
struct resource *irq_res,
- unsigned int ioport_shift,
+ unsigned int reg_shift,
int __pio_mask)
{
struct ata_host *host;
@@ -202,7 +202,7 @@ int __devinit __pata_platform_probe(struct device *dev,
ap->ioaddr.altstatus_addr = ap->ioaddr.ctl_addr;
- pata_platform_setup_port(&ap->ioaddr, ioport_shift);
+ pata_platform_setup_port(&ap->ioaddr, reg_shift);
ata_port_desc(ap, "%s cmd 0x%llx ctl 0x%llx", mmio ? "mmio" : "ioport",
(unsigned long long)io_res->start,
@@ -274,7 +274,7 @@ static int __devinit pata_platform_probe(struct platform_device *pdev)
irq_res->flags = pp_info ? pp_info->irq_flags : 0;
return __pata_platform_probe(&pdev->dev, io_res, ctl_res, irq_res,
- pp_info ? pp_info->ioport_shift : 0,
+ pp_info ? pp_info->reg_shift : 0,
pio_mask);
}
diff --git a/drivers/ide/legacy/ide_platform.c b/drivers/ide/legacy/ide_platform.c
index 7bb79f5..3cee1b2 100644
--- a/drivers/ide/legacy/ide_platform.c
+++ b/drivers/ide/legacy/ide_platform.c
@@ -41,9 +41,9 @@ static ide_hwif_t *__devinit plat_ide_locate_hwif(void __iomem *base,
hwif->io_ports[IDE_DATA_OFFSET] = port;
- port += (1 << pdata->ioport_shift);
+ port += (1 << pdata->reg_shift);
for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET;
- i++, port += (1 << pdata->ioport_shift))
+ i++, port += (1 << pdata->reg_shift))
hwif->io_ports[i] = port;
hwif->io_ports[IDE_CONTROL_OFFSET] = (unsigned long)ctrl;
diff --git a/include/linux/pata_platform.h b/include/linux/pata_platform.h
index 6a7a92d..a0fc6b0 100644
--- a/include/linux/pata_platform.h
+++ b/include/linux/pata_platform.h
@@ -7,7 +7,7 @@ struct pata_platform_info {
* constantly spaced and need larger than the 1-byte
* spacing used by ata_std_ports().
*/
- unsigned int ioport_shift;
+ unsigned int reg_shift;
/*
* Indicate platform specific irq types and initial
* IRQ flags when call request_irq()
@@ -19,7 +19,7 @@ extern int __devinit __pata_platform_probe(struct device *dev,
struct resource *io_res,
struct resource *ctl_res,
struct resource *irq_res,
- unsigned int ioport_shift,
+ unsigned int reg_shift,
int __pio_mask);
extern int __devexit __pata_platform_remove(struct device *dev);
--
1.5.2.2
^ permalink raw reply related
* Re: [PATCH v2 4/4] [libata] pata_platform: s/ioport_shift/reg_shift/g
From: Sergei Shtylyov @ 2007-12-04 17:08 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Jeff Garzik, Arnd Bergmann, linux-ide, linuxppc-dev, Paul Mundt,
Olof Johansson
In-Reply-To: <20071204170745.GD15599@localhost.localdomain>
Hello.
Anton Vorontsov wrote:
> This patch renames ioport_shift member of pata_platform_info
> structure to reg_shift. Users of pata_platform are followed
> appropriately.
> Rationale of that change is: shifting applies to the whole memory
> mapped region, not only to the command block of the ATA registers,
> despite the fact that shifting is meaningless for ctl register.
> This patch should make Sergei Shtylyov a bit more happy. ;-)
In fact, I don't care about how platform driver calls this stuff. ;-)
I only care about the property name.
MBR, Sergei
^ permalink raw reply
* Re: OT: Re: solved: Re: [rtc-linux] Re: DS1337 RTC on I2C broken.
From: Jon Smirl @ 2007-12-04 17:19 UTC (permalink / raw)
To: Clemens Koller; +Cc: Alessandro Zummo, rtc-linux, linuxppc-embedded
In-Reply-To: <4755731D.4050106@anagramm.de>
On 12/4/07, Clemens Koller <clemens.koller@anagramm.de> wrote:
> That was discussed already in detail in several threads and there
> were already decisions made that the DT went into the kernel - no problem
> with that.
> I just don't see that it 'really does help' in it's current state if
> things are broken in a way they are hard to fix for non DT-familiar
> developers, almost impossible to fix for users which just need to
> compile their own kernel to achieve their project goal.
>
> Well... let's take it easy. I'll dig into the pcf8563 code now.
Most of this is addressed in the patch series starting with this message:
http://ozlabs.org/pipermail/linuxppc-dev/2007-December/047382.html
The pcf8563 driver is converted to the new format and is modified to
pick up it's address from the device tree.
This patch series is being held waiting for an ok on the low level
changes to the i2c subsystem. Hopefully it will go into 2.6.25
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: Merge dtc
From: David Woodhouse @ 2007-12-04 17:22 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev, Paul Mackerras
In-Reply-To: <20071204031027.GJ32577@localhost.localdomain>
On Tue, 2007-12-04 at 14:10 +1100, David Gibson wrote:
> We've been back and forth on this several times, Paul and I finally
> concluded this was the better option.
As long as I can just ignore it and use the separately-shipped dtc, I
suppose it doesn't have to bother me too much.
> It means we can feel free to use dtc for whatever new platforms we
> wish to without people whinging about having to install a new tool.
I think we're overestimating this 'problem'; really.
But anyway, if we have to go ahead with it, can we make sure we keep in
sync with the 'real' dtc? One way of doing that is as follows...
It's not hard to make a git repository which is a simple 'transform' of
another tree -- I have a couple, at
http://git.infradead.org/?p=users/dwmw2/jffs2-ecos-core.git and
http://git.kernel.org/?p=linux/kernel/git/dwmw2/kernel-headers.git
The scripts to generate those are at
http://david.woodhou.se/extract-jffs2-git.sh
http://david.woodhou.se/extract-khdrs-git.sh
http://david.woodhou.se/extract-khdrs-stage2.sh
(The kernel headers one is in two stages because it has to mangle the
files through unifdef too).
I'm sure there are better ways of doing it, but the scripts I have work,
and should hopefully serve as a vaguely useful example.
I'd recommend making such a 'transform' which tracks the upstream dtc
tree but with the files you want moved into the correct places. Then all
we have to do to update the kernel's copy is pull from that transformed
tree.
Of course, it's possible that git has matured to the point where it can
handle the 'renames' and you can just pull from the upstream dtc
repository directly. I don't think that's the case though.
--
dwmw2
^ permalink raw reply
* Re: Merge dtc
From: Scott Wood @ 2007-12-04 16:08 UTC (permalink / raw)
To: Jon Loeliger; +Cc: linuxppc-dev, David Woodhouse, Paul Mackerras, David Gibson
In-Reply-To: <E1IzXmf-0005RJ-27@jdl.com>
On Tue, Dec 04, 2007 at 07:25:57AM -0600, Jon Loeliger wrote:
> So, like, the other day David Woodhouse mumbled:
> >
> > I think this is a bad idea -- it's hardly a difficult for those people
> > who _do_ need dts to obtain it separately.
> >
> > We shouldn't be merging _more_ stuff in.
>
> Thanks for chiming in here, David W. As far as I can tell
> so far, the only two people who have voiced an opinion on
> this issue are Dave G, submitting patches, and me disagreeing
> with the approach. :-)
>
> Anyone else?
I vote for keeping it separate.
-Scott
^ permalink raw reply
* Re: [PATCH 1/5] PowerPC 74xx: Katana Qp device tree
From: Andrei Dolnikov @ 2007-12-04 17:28 UTC (permalink / raw)
To: Mark A. Greer; +Cc: David.Jenkins, linuxppc-dev
In-Reply-To: <20071204012329.GA18903@mag.az.mvista.com>
Mark A. Greer wrote:
> On Tue, Dec 04, 2007 at 07:52:50AM +1100, Benjamin Herrenschmidt wrote:
>
>>> #address-cells = <1>;
>>> + #size-cells = <1>;
>>> + model = "Katana-Qp"; /* Default */
>>> + compatible = "emerson,Katana-Qp";
>>> + coherency-off;
>>> +
>>>
>> What do that mean (coherency-off) ?
>>
>> Somebody is trying again to use a 74xx with non cache coherent DMA ?
>>
>
> Hi Ben.
>
> I suspect Andrei got that from the prpmc2800 dts which I made so I'll
> jump in. (BTW, this is the same debate we have every year or two. :)
>
> By looking at the dts, that board has an mv64460 which has a couple
> issues when it comes to coherency (depending on the rev of the chip).
>
> One is about not being able to use DCBST instructions with coherency on
> and the other is about limiting the length of one of the traces (which
> at least one board manufacturer that I know of refuses to implement).
> The first one is supposed to be fixed by rev A1 of the part and the second
> is supposed to be fixed by rev B0 of the part. I don't know what rev(s)
> are on the board(s) Andrei is using. If its B0 or later, in theory, the
> part should work with coherency on.
>
> Andrei, have you tested with coherency on?
>
Yes, I tested it with "coherency on", but it didn't work.
I checked chip revisions on all boards I have and they all are >=
mv64_4_60 B0.
Emerson team working on U-Boot for KatanaQP (David Jenkins copied in cc)
notified that they have newer firmware version which makes "coherency
on" functional.
At the moment I have no more details on it, but I'll investigate this
issue soon and let you know all the details.
> --
> [snip errata]
> --
>
> So, the answer depends on what part & what rev of the part you have
> (e.g., the pegasos doesn't use the MPSC and apparently has the other
> issues worked around so it can turn on coherency but the prpmc2800
> doesn't so it needs coherency off).
>
> BTW, I haven't forgotten the inherent bug you described when coherency
> is off (/me too lazy to find link to the email) but AFAIK I've never run
> into it. However, if I turn on coherency and stress the PCI bus, it
> hangs (I can't even look at memory thru a bdi).
>
> Mark
>
Thanks,
Andrei.
^ permalink raw reply
* Re: [PATCH 1/5] PowerPC 74xx: Katana Qp device tree
From: Mark A. Greer @ 2007-12-04 17:35 UTC (permalink / raw)
To: Andrei Dolnikov; +Cc: David.Jenkins, linuxppc-dev
In-Reply-To: <47558E59.4040107@ru.mvista.com>
On Tue, Dec 04, 2007 at 08:28:57PM +0300, Andrei Dolnikov wrote:
> Mark A. Greer wrote:
> >On Tue, Dec 04, 2007 at 07:52:50AM +1100, Benjamin Herrenschmidt wrote:
> >
> >>> #address-cells = <1>;
> >>>+ #size-cells = <1>;
> >>>+ model = "Katana-Qp"; /* Default */
> >>>+ compatible = "emerson,Katana-Qp";
> >>>+ coherency-off;
> >>>+
> >>>
> >>What do that mean (coherency-off) ?
> >>
> >>Somebody is trying again to use a 74xx with non cache coherent DMA ?
> >>
> >
> >Hi Ben.
> >
> >I suspect Andrei got that from the prpmc2800 dts which I made so I'll
> >jump in. (BTW, this is the same debate we have every year or two. :)
> >
> >By looking at the dts, that board has an mv64460 which has a couple
> >issues when it comes to coherency (depending on the rev of the chip).
> >
> >One is about not being able to use DCBST instructions with coherency on
> >and the other is about limiting the length of one of the traces (which
> >at least one board manufacturer that I know of refuses to implement).
> >The first one is supposed to be fixed by rev A1 of the part and the second
> >is supposed to be fixed by rev B0 of the part. I don't know what rev(s)
> >are on the board(s) Andrei is using. If its B0 or later, in theory, the
> >part should work with coherency on.
> >
> >Andrei, have you tested with coherency on?
> >
> Yes, I tested it with "coherency on", but it didn't work.
>
> I checked chip revisions on all boards I have and they all are >=
> mv64_4_60 B0.
FWIW, this is consistent with what I see.
Mark
^ permalink raw reply
* ucc_uart: add support for Freescale QUICCEngine UART
From: Timur Tabi @ 2007-12-04 17:51 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Timur Tabi
Add support for UART serial ports using a Freescale QUICC Engine
(found on some MPC83xx and MPC85xx SOCs).
Because of a silicon bug in some QE-enabled SOCs (e.g. 8323 and 8360), a new
microcode is required. This microcode implements UART via a work-around,
hence it's called "Soft-UART". This driver can use QE firmware upload feature
to upload the correct microcode to the QE.
Signed-off-by: Timur Tabi <timur@freescale.com>
---
This patch is for Kumar's for-2.6.25 branch, and it applies on top of my
previous patches, "qe: add ability to upload QE firmware" and
"qe: add function qe_clock_source()".
arch/powerpc/boot/dts/mpc832x_mds.dts | 48 +
arch/powerpc/sysdev/qe_lib/Kconfig | 2 +-
arch/powerpc/sysdev/qe_lib/ucc_slow.c | 10 +-
drivers/serial/Kconfig | 32 +
drivers/serial/Makefile | 1 +
drivers/serial/ucc_uart.c | 1586 +++++++++++++++++++++++++++++++++
6 files changed, 1677 insertions(+), 2 deletions(-)
create mode 100644 drivers/serial/ucc_uart.c
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts
index fe54489..a7605af 100644
--- a/arch/powerpc/boot/dts/mpc832x_mds.dts
+++ b/arch/powerpc/boot/dts/mpc832x_mds.dts
@@ -7,6 +7,18 @@
* 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.
+
+ * To enable external serial I/O on a Freescale MPC 8323 SYS/MDS board, do
+ * this:
+ *
+ * 1) On chip U61, lift (disconnect) pins 21 (TXD) and 22 (RXD) from the board.
+ * 2) Solder a wire from U61-21 to P19A-23. P19 is a grid of pins on the board
+ * next to the serial ports.
+ * 3) Solder a wire from U61-22 to P19K-22.
+ *
+ * Note that there's a typo in the schematic. The board labels the last column
+ * of pins "P19K", but in the schematic, that column is called "P19J". So if
+ * you're going by the schematic, the pin is called "P19J-K22".
*/
/ {
@@ -159,6 +171,23 @@
1 1e 1 0 1 0 /* TX_EN */
1 1f 2 0 1 0>;/* CRS */
};
+ pio5: ucc_pin@05 {
+ pio-map = <
+ /*
+ * open has
+ * port pin dir drain sel irq
+ */
+ 2 0 1 0 2 0 /* TxD5 */
+ 2 8 2 0 2 0 /* RxD5 */
+
+ 2 1d 2 0 0 0 /* CTS5 */
+ 2 1f 1 0 2 0 /* RTS5 */
+
+ 2 18 2 0 0 0 /* CD */
+
+ >;
+ };
+
};
};
@@ -250,6 +279,25 @@
pio-handle = < &pio4 >;
};
+ ucc@2400 {
+ device_type = "serial";
+ compatible = "ucc_uart";
+ model = "UCC";
+ device-id = <5>; /* The UCC number, 1-7*/
+ port-number = <0>; /* Which ttyQEx device */
+ reg = <2400 200>;
+ interrupts = <28>; /* From Table 18-12 */
+ interrupt-parent = < &qeic >;
+ /*
+ * For Soft-UART, we need to set TX to 1X, which
+ * means specifying separate clock sources.
+ */
+ rx-clock-name = "brg5";
+ tx-clock-name = "brg6";
+ pio-handle = < &pio5 >;
+ };
+
+
mdio@2320 {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/powerpc/sysdev/qe_lib/Kconfig b/arch/powerpc/sysdev/qe_lib/Kconfig
index f611d34..adc6621 100644
--- a/arch/powerpc/sysdev/qe_lib/Kconfig
+++ b/arch/powerpc/sysdev/qe_lib/Kconfig
@@ -4,7 +4,7 @@
config UCC_SLOW
bool
- default n
+ default y if SERIAL_QE
help
This option provides qe_lib support to UCC slow
protocols: UART, BISYNC, QMC
diff --git a/arch/powerpc/sysdev/qe_lib/ucc_slow.c b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
index 0174b3a..b2870b2 100644
--- a/arch/powerpc/sysdev/qe_lib/ucc_slow.c
+++ b/arch/powerpc/sysdev/qe_lib/ucc_slow.c
@@ -19,6 +19,7 @@
#include <linux/stddef.h>
#include <linux/interrupt.h>
#include <linux/err.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/immap_qe.h>
@@ -41,6 +42,7 @@ u32 ucc_slow_get_qe_cr_subblock(int uccs_num)
default: return QE_CR_SUBBLOCK_INVALID;
}
}
+EXPORT_SYMBOL(ucc_slow_get_qe_cr_subblock);
void ucc_slow_poll_transmitter_now(struct ucc_slow_private * uccs)
{
@@ -56,6 +58,7 @@ void ucc_slow_graceful_stop_tx(struct ucc_slow_private * uccs)
qe_issue_cmd(QE_GRACEFUL_STOP_TX, id,
QE_CR_PROTOCOL_UNSPECIFIED, 0);
}
+EXPORT_SYMBOL(ucc_slow_graceful_stop_tx);
void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
{
@@ -65,6 +68,7 @@ void ucc_slow_stop_tx(struct ucc_slow_private * uccs)
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
qe_issue_cmd(QE_STOP_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
}
+EXPORT_SYMBOL(ucc_slow_stop_tx);
void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
{
@@ -74,6 +78,7 @@ void ucc_slow_restart_tx(struct ucc_slow_private * uccs)
id = ucc_slow_get_qe_cr_subblock(us_info->ucc_num);
qe_issue_cmd(QE_RESTART_TX, id, QE_CR_PROTOCOL_UNSPECIFIED, 0);
}
+EXPORT_SYMBOL(ucc_slow_restart_tx);
void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
{
@@ -94,6 +99,7 @@ void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
}
out_be32(&us_regs->gumr_l, gumr_l);
}
+EXPORT_SYMBOL(ucc_slow_enable);
void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
{
@@ -114,6 +120,7 @@ void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
}
out_be32(&us_regs->gumr_l, gumr_l);
}
+EXPORT_SYMBOL(ucc_slow_disable);
/* Initialize the UCC for Slow operations
*
@@ -347,6 +354,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc
*uccs_ret = uccs;
return 0;
}
+EXPORT_SYMBOL(ucc_slow_init);
void ucc_slow_free(struct ucc_slow_private * uccs)
{
@@ -366,5 +374,5 @@ void ucc_slow_free(struct ucc_slow_private * uccs)
kfree(uccs);
}
-
+EXPORT_SYMBOL(ucc_slow_free);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index d7e1996..5087b58 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -1284,4 +1284,36 @@ config SERIAL_OF_PLATFORM
Currently, only 8250 compatible ports are supported, but
others can easily be added.
+config SERIAL_QE
+ tristate "Freescale QUICC Engine serial port support"
+ depends on QUICC_ENGINE
+ select SERIAL_CORE
+ default n
+ help
+ This driver supports the QE serial ports on Freescale embedded
+ PowerPC that contain a QUICC Engine.
+
+config SERIAL_QE_SOFT_UART
+ bool "Use Soft-UART Mode"
+ depends on SERIAL_QE
+ default n
+ help
+ Enable this option if you want to load and use a microcode that
+ implements a "Soft-UART". The Soft-UART emulates a UART using the
+ QMC hardware. It is necessary on older QE revisions that have broken
+ UART hardware. To access the Soft-UART microcode upload option,
+ enable "Userspace firmware loading support".
+
+config SERIAL_QE_SOFT_UART_UPLOAD
+ bool "Upload Soft-UART microcode"
+ depends on SERIAL_QE_SOFT_UART && FW_LOADER
+ default SERIAL_QE_SOFT_UART
+ help
+ Enable this option to have the driver upload request and upload
+ the Soft-UART microcode upon initialization. Otherwise, the driver
+ will assume that the Soft-UART microcode has been uploaded by some
+ other means, such as the boot loader. The hotplug interface will be
+ used to make the microcode available to the driver. The driver will
+ not allow any ports to be opened until the microcode is loaded.
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index af6377d..7eb4553 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -64,3 +64,4 @@ obj-$(CONFIG_SERIAL_UARTLITE) += uartlite.o
obj-$(CONFIG_SERIAL_NETX) += netx-serial.o
obj-$(CONFIG_SERIAL_OF_PLATFORM) += of_serial.o
obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o
+obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c
new file mode 100644
index 0000000..2998cbf
--- /dev/null
+++ b/drivers/serial/ucc_uart.c
@@ -0,0 +1,1586 @@
+/*
+ * Freescale QUICC Engine UART device driver
+ *
+ * Author: Timur Tabi <timur@freescale.com>
+ *
+ * Copyright 2007 Freescale Semiconductor, 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.
+ *
+ * This driver adds support for UART devices via Freescale's QUICC Engine
+ * found on some Freescale SOCs.
+ *
+ * If CONFIG_SERIAL_QE_SOFT_UART_UPLOAD is defined, then this driver will
+ * request and upload the "Soft-UART" microcode upon probe. The filename of
+ * the microcode should be fsl_qe_ucode_uart_X_YZ.bin, where "X" is the name
+ * of the SOC (e.g. 8323), and YZ is the revision of the SOC, (e.g. "11" for
+ * 1.1).
+ */
+
+#include <linux/module.h>
+#include <linux/serial.h>
+#include <linux/serial_core.h>
+#include <linux/io.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+
+#include <linux/fs_uart_pd.h>
+#include <asm/ucc_slow.h>
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART_UPLOAD
+#include <linux/firmware.h>
+#include <asm/reg.h>
+#endif
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+/*
+ * The GUMR flag for Soft UART. This would normally be defined in qe.h,
+ * but Soft-UART is a hack and we want to keep everything related to it in
+ * this file.
+ */
+#define UCC_SLOW_GUMR_H_SUART 0x00004000 /* Soft UART */
+
+/*
+ * firmware_loaded is 1 if the firmware has been loaded, 0 otherwise.
+ */
+#ifdef CONFIG_SERIAL_QE_SOFT_UART_UPLOAD
+static int firmware_loaded;
+#endif
+
+#endif
+
+/* Enable this macro to configure all serial ports in internal loopback
+ mode */
+/* #define LOOPBACK */
+
+/* The major and minor device numbers are defined in
+ * http://www.lanana.org/docs/device-list/devices-2.6+.txt. For the QE
+ * UART, we have major number 204 and minor numbers 46 - 49, which are the
+ * same as for the CPM2. This decision was made because no Freescale part
+ * has both a CPM and a QE.
+ */
+#define SERIAL_QE_MAJOR 204
+#define SERIAL_QE_MINOR 46
+
+/* Since we only have minor numbers 46 - 49, there is a hard limit of 4 ports */
+#define UCC_MAX_UART 4
+
+/* The number of buffer descriptors for receiving characters. */
+#define RX_NUM_FIFO 4
+
+/* The number of buffer descriptors for transmitting characters. */
+#define TX_NUM_FIFO 4
+
+/* The maximum size of the character buffer for a single RX BD. */
+#define RX_BUF_SIZE 32
+
+/* The maximum size of the character buffer for a single TX BD. */
+#define TX_BUF_SIZE 32
+
+#define UCC_WAIT_CLOSING 100
+
+struct ucc_uart_pram {
+ struct ucc_slow_pram common;
+ u8 res1[8]; /* reserved */
+ __be16 maxidl; /* Maximum idle chars */
+ __be16 idlc; /* temp idle counter */
+ __be16 brkcr; /* Break count register */
+ __be16 parec; /* receive parity error counter */
+ __be16 frmec; /* receive framing error counter */
+ __be16 nosec; /* receive noise counter */
+ __be16 brkec; /* receive break condition counter */
+ __be16 brkln; /* last received break length */
+ __be16 uaddr[2]; /* UART address character 1 & 2 */
+ __be16 rtemp; /* Temp storage */
+ __be16 toseq; /* Transmit out of sequence char */
+ __be16 cchars[8]; /* control characters 1-8 */
+ __be16 rccm; /* receive control character mask */
+ __be16 rccr; /* receive control character register */
+ __be16 rlbc; /* receive last break character */
+ __be16 res2; /* reserved */
+ __be32 res3; /* reserved, should be cleared */
+ u8 res4; /* reserved, should be cleared */
+ u8 res5[3]; /* reserved, should be cleared */
+ __be32 res6; /* reserved, should be cleared */
+ __be32 res7; /* reserved, should be cleared */
+ __be32 res8; /* reserved, should be cleared */
+ __be32 res9; /* reserved, should be cleared */
+ __be32 res10; /* reserved, should be cleared */
+ __be32 res11; /* reserved, should be cleared */
+ __be32 res12; /* reserved, should be cleared */
+ __be32 res13; /* reserved, should be cleared */
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ __be16 supsmr; /* 0x90, Shadow UPSMR */
+ __be16 res92; /* 0x92, reserved, initialize to 0 */
+ __be32 rx_state; /* 0x94, RX state, initialize to 0 */
+ __be32 rx_cnt; /* 0x98, RX count, initialize to 0 */
+ u8 rx_length; /* 0x9C, Char length, set to 1+CL+PEN+1+SL */
+ u8 rx_bitmark; /* 0x9D, reserved, initialize to 0 */
+ u8 rx_temp_dlst_qe; /* 0x9E, reserved, initialize to 0 */
+ u8 res14[0xBC - 0x9F]; /* reserved */
+ __be32 dump_ptr; /* 0xBC, Dump pointer */
+ __be32 rx_frame_rem; /* 0xC0, reserved, initialize to 0 */
+ u8 rx_frame_rem_size; /* 0xC4, reserved, initialize to 0 */
+ u8 tx_mode; /* 0xC5, mode, 0=AHDLC, 1=UART */
+ u16 tx_state; /* 0xC6, TX state */
+ u8 res15[0xD0 - 0xC8]; /* reserved */
+ __be32 resD0; /* 0xD0, reserved, initialize to 0 */
+ u8 resD4; /* 0xD4, reserved, initialize to 0 */
+ __be16 resD5; /* 0xD5, reserved, initialize to 0 */
+#endif
+} __attribute__ ((packed));
+
+#ifdef DEBUG
+static void dump_ucc_uart_pram(struct ucc_uart_pram __iomem *uccup)
+{
+ unsigned int i;
+
+ printk(KERN_DEBUG "%s: uccup=%p\n", __FUNCTION__, uccup);
+ printk(KERN_DEBUG " rbase=%04x\n", in_be16(&uccup->common.rbase));
+ printk(KERN_DEBUG " tbase=%04x\n", in_be16(&uccup->common.tbase));
+ printk(KERN_DEBUG " rbmr=%02x\n", in_8(&uccup->common.rbmr));
+ printk(KERN_DEBUG " tbmr=%02x\n", in_8(&uccup->common.tbmr));
+ printk(KERN_DEBUG " mrblr=%04x\n", in_be16(&uccup->common.mrblr));
+ printk(KERN_DEBUG " rstate=%08x\n", in_be32(&uccup->common.rstate));
+ printk(KERN_DEBUG " rptr=%08x\n", in_be32(&uccup->common.rptr));
+ printk(KERN_DEBUG " rbptr=%04x\n", in_be16(&uccup->common.rbptr));
+ printk(KERN_DEBUG " rcount=%04x\n", in_be16(&uccup->common.rcount));
+ printk(KERN_DEBUG " rtemp=%08x\n", in_be32(&uccup->common.rtemp));
+ printk(KERN_DEBUG " tstate=%08x\n", in_be32(&uccup->common.tstate));
+ printk(KERN_DEBUG " tptr=%08x\n", in_be32(&uccup->common.tptr));
+ printk(KERN_DEBUG " tbptr=%04x\n", in_be16(&uccup->common.tbptr));
+ printk(KERN_DEBUG " tcount=%04x\n", in_be16(&uccup->common.tcount));
+ printk(KERN_DEBUG " ttemp=%08x\n", in_be32(&uccup->common.ttemp));
+ printk(KERN_DEBUG " rcrc=%08x\n", in_be32(&uccup->common.rcrc));
+ printk(KERN_DEBUG " tcrc=%08x\n", in_be32(&uccup->common.tcrc));
+
+ printk(KERN_DEBUG " maxidl=%04x\n", in_be16(&uccup->maxidl));
+ printk(KERN_DEBUG " idlc=%04x\n", in_be16(&uccup->idlc));
+ printk(KERN_DEBUG " brkcr=%04x\n", in_be16(&uccup->brkcr));
+ printk(KERN_DEBUG " parec=%04x\n", in_be16(&uccup->parec));
+ printk(KERN_DEBUG " frmec=%04x\n", in_be16(&uccup->frmec));
+ printk(KERN_DEBUG " nosec=%04x\n", in_be16(&uccup->nosec));
+ printk(KERN_DEBUG " brkec=%04x\n", in_be16(&uccup->brkec));
+ printk(KERN_DEBUG " brkln=%04x\n", in_be16(&uccup->brkln));
+ for (i = 0; i < 2; i++)
+ printk(KERN_DEBUG " uaddr[%u]=%04x\n", i,
+ in_be16(&uccup->uaddr[i]));
+ printk(KERN_DEBUG " rtemp=%04x\n", in_be16(&uccup->rtemp));
+ printk(KERN_DEBUG " toseq=%04x\n", in_be16(&uccup->toseq));
+ for (i = 0; i < 8; i++)
+ printk(KERN_DEBUG " cchars[%u]=%04x\n", i,
+ in_be16(&uccup->cchars[i]));
+ printk(KERN_DEBUG " rccm=%04x\n", in_be16(&uccup->rccm));
+ printk(KERN_DEBUG " rccr=%04x\n", in_be16(&uccup->rccr));
+ printk(KERN_DEBUG " rlbc=%04x\n", in_be16(&uccup->rlbc));
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ printk(KERN_DEBUG " supsmr=%04x\n", in_be16(&uccup->supsmr));
+ printk(KERN_DEBUG " rx_state=%08x\n", in_be32(&uccup->rx_state));
+ printk(KERN_DEBUG " rx_cnt=%08x\n", in_be32(&uccup->rx_cnt));
+ printk(KERN_DEBUG " rx_length=%02x\n", in_8(&uccup->rx_length));
+
+ printk(KERN_DEBUG " rx_bitmark=%02x\n", in_8(&uccup->rx_bitmark));
+ printk(KERN_DEBUG " rx_temp_dlst_qe=%02x\n",
+ in_8(&uccup->rx_temp_dlst_qe));
+ printk(KERN_DEBUG " dump_ptr=%08x\n", in_be32(&uccup->dump_ptr));
+ printk(KERN_DEBUG " rx_frame_rem=%08x\n",
+ in_be32(&uccup->rx_frame_rem));
+ printk(KERN_DEBUG " rx_frame_rem_size=%02x\n",
+ in_8(&uccup->rx_frame_rem_size));
+ printk(KERN_DEBUG " tx_mode=%02x\n", in_8(&uccup->tx_mode));
+ printk(KERN_DEBUG " tx_state=%04x\n", in_be16(&uccup->tx_state));
+ printk(KERN_DEBUG " resD0=%08x\n", in_be32(&uccup->resD0));
+ printk(KERN_DEBUG " resD4=%02x\n", in_8(&uccup->resD4));
+#endif
+}
+
+static void print_bds(struct uart_qe_port *qe_port)
+{
+ struct qe_bd *bdp;
+ unsigned int i, j;
+
+ printk(KERN_DEBUG "%s:\n", __FUNCTION__);
+
+ bdp = qe_port->tx_bd_base;
+ for (i = 0; i < qe_port->tx_nrfifos; i++) {
+ printk(KERN_DEBUG " tx-bdp=%p buf=%x len=%u status=%x",
+ bdp, in_be32(&bdp->buf), in_be16(&bdp->length),
+ in_be16(&bdp->status));
+ for (j = 0; j < TX_BUF_SIZE; j++)
+ printk(" %02x", qe_port->tx_buf[i * TX_BUF_SIZE + j]);
+ printk("\n");
+ bdp++;
+ }
+
+ bdp = qe_port->rx_bd_base;
+ for (i = 0; i < qe_port->rx_nrfifos; i++) {
+ printk(KERN_DEBUG " rx-bdp=%p buf=%x len=%u status=%x",
+ bdp, in_be32(&bdp->buf), in_be16(&bdp->length),
+ in_be16(&bdp->status));
+ for (j = 0; j < RX_BUF_SIZE; j++)
+ printk(" %02x", qe_port->rx_buf[i * RX_BUF_SIZE + j]);
+ printk("\n");
+ bdp++;
+ }
+}
+#endif
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+#define UCC_UART_SUPSMR_SL 0x8000
+#define UCC_UART_SUPSMR_RPM_MASK 0x6000
+#define UCC_UART_SUPSMR_RPM_ODD 0x0000
+#define UCC_UART_SUPSMR_RPM_LOW 0x2000
+#define UCC_UART_SUPSMR_RPM_EVEN 0x4000
+#define UCC_UART_SUPSMR_RPM_HIGH 0x6000
+#define UCC_UART_SUPSMR_PEN 0x1000
+#define UCC_UART_SUPSMR_TPM_MASK 0x0C00
+#define UCC_UART_SUPSMR_TPM_ODD 0x0000
+#define UCC_UART_SUPSMR_TPM_LOW 0x0400
+#define UCC_UART_SUPSMR_TPM_EVEN 0x0800
+#define UCC_UART_SUPSMR_TPM_HIGH 0x0C00
+#define UCC_UART_SUPSMR_FRZ 0x0100
+#define UCC_UART_SUPSMR_UM_MASK 0x00c0
+#define UCC_UART_SUPSMR_UM_NORMAL 0x0000
+#define UCC_UART_SUPSMR_UM_MAN_MULTI 0x0040
+#define UCC_UART_SUPSMR_UM_AUTO_MULTI 0x00c0
+#define UCC_UART_SUPSMR_CL_MASK 0x0030
+#define UCC_UART_SUPSMR_CL_8 0x0030
+#define UCC_UART_SUPSMR_CL_7 0x0020
+#define UCC_UART_SUPSMR_CL_6 0x0010
+#define UCC_UART_SUPSMR_CL_5 0x0000
+
+#define UCC_UART_TX_STATE_AHDLC 0x00
+#define UCC_UART_TX_STATE_UART 0x01
+#define UCC_UART_TX_STATE_X1 0x00
+#define UCC_UART_TX_STATE_X16 0x80
+#endif
+
+#define UCC_UART_PRAM_ALIGNMENT 0x100
+
+#define UCC_UART_SIZE_OF_BD UCC_SLOW_SIZE_OF_BD
+#define NUM_CONTROL_CHARS 8
+
+/* Private per-port data structure */
+struct uart_qe_port {
+ struct uart_port port;
+ struct ucc_slow __iomem *uccp;
+ struct ucc_uart_pram __iomem *uccup;
+ struct ucc_slow_info us_info;
+ struct ucc_slow_private *us_private;
+ struct device_node *np;
+ unsigned int ucc_num; /* First ucc is 0, not 1 */
+
+ u16 rx_nrfifos;
+ u16 rx_fifosize;
+ u16 tx_nrfifos;
+ u16 tx_fifosize;
+ int wait_closing;
+ u32 flags;
+ struct qe_bd *rx_bd_base;
+ struct qe_bd *rx_cur;
+ struct qe_bd *tx_bd_base;
+ struct qe_bd *tx_cur;
+ unsigned char *tx_buf;
+ unsigned char *rx_buf;
+ void *bd_virt; /* virtual addr of BD buffers */
+ dma_addr_t bd_phys; /* physical addr of BD buffers */
+ unsigned int bd_size; /* size of BD buffer space */
+};
+
+static struct uart_driver ucc_uart_driver = {
+ .owner = THIS_MODULE,
+ .driver_name = "serial",
+ .dev_name = "ttyQE",
+ .major = SERIAL_QE_MAJOR,
+ .minor = SERIAL_QE_MINOR,
+ .nr = UCC_MAX_UART,
+};
+
+/*
+ * Virtual to physical address translation.
+ *
+ * Given the virtual address for a character buffer, this function returns
+ * the physical (DMA) equivalent.
+ */
+static inline dma_addr_t cpu2qe_addr(void *addr, struct uart_qe_port *qe_port)
+{
+ if (likely((addr >= qe_port->bd_virt)) &&
+ (addr < (qe_port->bd_virt + qe_port->bd_size)))
+ return qe_port->bd_phys + (addr - qe_port->bd_virt);
+
+ /* something nasty happened */
+ printk(KERN_ERR "%s: addr=%p\n", __FUNCTION__, addr);
+ BUG();
+ return 0;
+}
+
+/*
+ * Physical to virtual address translation.
+ *
+ * Given the physical (DMA) address for a character buffer, this function
+ * returns the virtual equivalent.
+ */
+static inline void *qe2cpu_addr(dma_addr_t addr, struct uart_qe_port *qe_port)
+{
+ /* sanity check */
+ if (likely((addr >= qe_port->bd_phys) &&
+ (addr < (qe_port->bd_phys + qe_port->bd_size))))
+ return qe_port->bd_virt + (addr - qe_port->bd_phys);
+
+ /* something nasty happened */
+ printk(KERN_ERR "%s: addr=%x\n", __FUNCTION__, addr);
+ BUG();
+ return NULL;
+}
+
+/*
+ * Return 1 if the QE is done transmitting all buffers for this port
+ *
+ * This function scan each BD in sequence. If we find a BD that is not
+ * ready (READY=1), then we return 0 indicating that the QE is still sending
+ * data. If we reach the last BD (WRAP=1), then we know we've scanned
+ * the entire list, and all BDs are done.
+ */
+static unsigned int qe_uart_tx_empty(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct qe_bd *bdp = qe_port->tx_bd_base;
+
+ while (1) {
+ if (in_be16(&bdp->status) & BD_SC_READY)
+ /* This BD is not done, so return "not done" */
+ return 0;
+
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ /*
+ * This BD is done and it's the last one, so return
+ * "done"
+ */
+ return 1;
+
+ bdp++;
+ };
+}
+
+/*
+ * Set the modem control lines
+ *
+ * We currently don't support setting modem control lines, but this function
+ * needs to exist, otherwise the kernel will panic.
+ */
+void qe_uart_set_mctrl(struct uart_port *port, unsigned int mctrl)
+{
+}
+
+/*
+ * Get the current modem control line status
+ *
+ * We don't support changing the modem control line status, so we always
+ * return Carrier Detect, Data Set Ready, and Clear To Send.
+ */
+static unsigned int qe_uart_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CAR | TIOCM_DSR | TIOCM_CTS;
+}
+
+/*
+ * Disable the transmit interrupt.
+ *
+ * Although this function is called "stop_tx", it does not actually stop
+ * transmission of data. Instead, it tells the QE to not generate an
+ * interrupt when the UCC is finished sending characters.
+ */
+static void qe_uart_stop_tx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
+}
+
+/*
+ * Transmit as many characters to the HW as possible.
+ *
+ * This function will attempt to stuff of all the characters from the
+ * kernel's transmit buffer into TX BDs.
+ *
+ * A return value of non-zero indicates that it sucessfully stuffed all
+ * characters from the kernel buffer.
+ *
+ * A return value of zero indicates that there are still characters in the
+ * kernel's buffer that have not been transmitted, but there are no more BDs
+ * available. This function should be called again after a BD has been made
+ * available.
+ */
+static int qe_uart_tx_pump(struct uart_qe_port *qe_port)
+{
+ struct qe_bd *bdp;
+ unsigned char *p;
+ unsigned int count;
+ struct uart_port *port = &qe_port->port;
+ struct circ_buf *xmit = &port->info->xmit;
+
+ bdp = qe_port->rx_cur;
+
+ /* Handle xon/xoff */
+ if (port->x_char) {
+ /* Pick next descriptor and fill from buffer */
+ bdp = qe_port->tx_cur;
+
+ p = qe2cpu_addr(bdp->buf, qe_port);
+
+ *p++ = port->x_char;
+ out_be16(&bdp->length, 1);
+ setbits16(&bdp->status, BD_SC_READY);
+ /* Get next BD. */
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->tx_bd_base;
+ else
+ bdp++;
+ qe_port->tx_cur = bdp;
+
+ port->icount.tx++;
+ port->x_char = 0;
+ return 1;
+ }
+
+ if (uart_circ_empty(xmit) || uart_tx_stopped(port)) {
+ qe_uart_stop_tx(port);
+ return 0;
+ }
+
+ /* Pick next descriptor and fill from buffer */
+ bdp = qe_port->tx_cur;
+
+ while (!(in_be16(&bdp->status) & BD_SC_READY) &&
+ (xmit->tail != xmit->head)) {
+ count = 0;
+ p = qe2cpu_addr(bdp->buf, qe_port);
+ while (count < qe_port->tx_fifosize) {
+ *p++ = xmit->buf[xmit->tail];
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ count++;
+ if (xmit->head == xmit->tail)
+ break;
+ }
+
+ out_be16(&bdp->length, count);
+ setbits16(&bdp->status, BD_SC_READY);
+
+ /* Get next BD. */
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->tx_bd_base;
+ else
+ bdp++;
+ }
+ qe_port->tx_cur = bdp;
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+
+ if (uart_circ_empty(xmit)) {
+ /* The kernel buffer is empty, so turn off TX interrupts. We
+ don't need to be told when the QE is finished transmitting
+ the data. */
+ qe_uart_stop_tx(port);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * Start transmitting data
+ *
+ * This function will start transmitting any available data, if the port
+ * isn't already transmitting data.
+ */
+static void qe_uart_start_tx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ /* If we currently are transmitting, then just return */
+ if (in_be16(&qe_port->uccp->uccm) & UCC_UART_UCCE_TX)
+ return;
+
+ /* Otherwise, pump the port and start transmission */
+ if (qe_uart_tx_pump(qe_port))
+ setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_TX);
+}
+
+/*
+ * Stop transmitting data
+ */
+static void qe_uart_stop_rx(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ clrbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
+}
+
+/*
+ * Enable status change interrupts
+ *
+ * We don't support status change interrupts, but we need to define this
+ * function otherwise the kernel will panic.
+ */
+static void qe_uart_enable_ms(struct uart_port *port)
+{
+}
+
+/* Start or stop sending break signal
+ *
+ * This function controls the sending of a break signal. If break_state=1,
+ * then we start sending a break signal. If break_state=0, then we stop
+ * sending the break signal.
+ */
+static void qe_uart_break_ctl(struct uart_port *port, int break_state)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+
+ if (break_state)
+ ucc_slow_stop_tx(qe_port->us_private);
+ else
+ ucc_slow_restart_tx(qe_port->us_private);
+}
+
+/* ISR helper function for receiving character.
+ *
+ * This function is called by the ISR to handling receiving characters
+ */
+static void qe_uart_int_rx(struct uart_qe_port *qe_port)
+{
+ int i;
+ unsigned char ch, *cp;
+ struct uart_port *port = &qe_port->port;
+ struct tty_struct *tty = port->info->tty;
+ struct qe_bd *bdp;
+ u16 status;
+ unsigned int flg;
+
+ /* Just loop through the closed BDs and copy the characters into
+ * the buffer.
+ */
+ bdp = qe_port->rx_cur;
+ while (1) {
+ status = in_be16(&bdp->status);
+
+ /* If this one is empty, then we assume we've read them all */
+ if (status & BD_SC_EMPTY)
+ break;
+
+ /* get number of characters, and check space in RX buffer */
+ i = in_be16(&bdp->length);
+
+ /* If we don't have enough room in RX buffer for the entire BD,
+ * then we try later, which will be the next RX interrupt.
+ */
+ if (tty_buffer_request_room(tty, i) < i) {
+ dev_dbg(port->dev, "ucc-uart: no room in RX buffer\n");
+ return;
+ }
+
+ /* get pointer */
+ cp = qe2cpu_addr(bdp->buf, qe_port);
+
+ /* loop through the buffer */
+ while (i-- > 0) {
+ ch = *cp++;
+ port->icount.rx++;
+ flg = TTY_NORMAL;
+
+ if (!i && status &
+ (BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV))
+ goto handle_error;
+ if (uart_handle_sysrq_char(port, ch))
+ continue;
+
+error_return:
+ tty_insert_flip_char(tty, ch, flg);
+
+ }
+
+ /* This BD is ready to be used again. Clear status. get next */
+ clrsetbits_be16(&bdp->status, BD_SC_BR | BD_SC_FR | BD_SC_PR |
+ BD_SC_OV | BD_SC_ID, BD_SC_EMPTY);
+ if (in_be16(&bdp->status) & BD_SC_WRAP)
+ bdp = qe_port->rx_bd_base;
+ else
+ bdp++;
+
+ }
+
+ /* Write back buffer pointer */
+ qe_port->rx_cur = bdp;
+
+ /* Activate BH processing */
+ tty_flip_buffer_push(tty);
+
+ return;
+
+ /* Error processing */
+
+handle_error:
+ /* Statistics */
+ if (status & BD_SC_BR)
+ port->icount.brk++;
+ if (status & BD_SC_PR)
+ port->icount.parity++;
+ if (status & BD_SC_FR)
+ port->icount.frame++;
+ if (status & BD_SC_OV)
+ port->icount.overrun++;
+
+ /* Mask out ignored conditions */
+ status &= port->read_status_mask;
+
+ /* Handle the remaining ones */
+ if (status & BD_SC_BR)
+ flg = TTY_BREAK;
+ else if (status & BD_SC_PR)
+ flg = TTY_PARITY;
+ else if (status & BD_SC_FR)
+ flg = TTY_FRAME;
+
+ /* Overrun does not affect the current character ! */
+ if (status & BD_SC_OV)
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+#ifdef SUPPORT_SYSRQ
+ port->sysrq = 0;
+#endif
+ goto error_return;
+}
+
+/* Interrupt handler
+ *
+ * This interrupt handler is called after a BD is processed.
+ */
+static irqreturn_t qe_uart_int(int irq, void *data)
+{
+ struct uart_qe_port *qe_port = (struct uart_qe_port *) data;
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ u16 events;
+
+ /* Clear the interrupts */
+ events = in_be16(&uccp->ucce);
+ out_be16(&uccp->ucce, events);
+
+ if (events & UCC_UART_UCCE_BRKE)
+ uart_handle_break(&qe_port->port);
+
+ if (events & UCC_UART_UCCE_RX)
+ qe_uart_int_rx(qe_port);
+
+ if (events & UCC_UART_UCCE_TX)
+ qe_uart_tx_pump(qe_port);
+
+ return events ? IRQ_HANDLED : IRQ_NONE;
+}
+
+/* Initialize buffer descriptors
+ *
+ * This function initializes all of the RX and TX buffer descriptors.
+ */
+static void qe_uart_initbd(struct uart_qe_port *qe_port)
+{
+ int i;
+ void *bd_virt;
+ struct qe_bd *bdp;
+
+ /* Set the physical address of the host memory buffers in the buffer
+ * descriptors, and the virtual address for us to work with.
+ */
+ bd_virt = qe_port->bd_virt;
+ bdp = qe_port->rx_bd_base;
+ qe_port->rx_cur = qe_port->rx_bd_base;
+ for (i = 0; i < (qe_port->rx_nrfifos - 1); i++) {
+ out_be16(&bdp->status, BD_SC_EMPTY | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+ bd_virt += qe_port->rx_fifosize;
+ bdp++;
+ }
+
+ /* */
+ out_be16(&bdp->status, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+
+ /* Set the physical address of the host memory
+ * buffers in the buffer descriptors, and the
+ * virtual address for us to work with.
+ */
+ bd_virt = qe_port->bd_virt +
+ L1_CACHE_ALIGN(qe_port->rx_nrfifos * qe_port->rx_fifosize);
+ qe_port->tx_cur = qe_port->tx_bd_base;
+ bdp = qe_port->tx_bd_base;
+ for (i = 0; i < (qe_port->tx_nrfifos - 1); i++) {
+ out_be16(&bdp->status, BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+ bd_virt += qe_port->tx_fifosize;
+ bdp++;
+ }
+
+ /* Loopback requires the preamble bit to be set on the first TX BD */
+#ifdef LOOPBACK
+ setbits16(&qe_port->tx_cur->status, BD_SC_P);
+#endif
+
+ out_be16(&bdp->status, BD_SC_WRAP | BD_SC_INTRPT);
+ out_be32(&bdp->buf, cpu2qe_addr(bd_virt, qe_port));
+ out_be16(&bdp->length, 0);
+}
+
+/*
+ * Initialize a UCC for UART.
+ *
+ * This function configures a given UCC to be used as a UART device. Basic
+ * UCC initialization is handled in qe_uart_request_port(). This function
+ * does all the UART-specific stuff.
+ */
+static void qe_uart_init_ucc(struct uart_qe_port *qe_port)
+{
+ u32 cecr_subblock;
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ struct ucc_uart_pram *uccup = qe_port->uccup;
+
+ unsigned int i;
+
+ /* First, disable TX and RX in the UCC */
+ ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+
+ /* Program the UCC UART parameter RAM */
+ out_8(&uccup->common.rbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
+ out_8(&uccup->common.tbmr, UCC_BMR_GBL | UCC_BMR_BO_BE);
+ out_be16(&uccup->common.mrblr, qe_port->rx_fifosize);
+ out_be16(&uccup->maxidl, 0x10);
+ out_be16(&uccup->brkcr, 1);
+ out_be16(&uccup->parec, 0);
+ out_be16(&uccup->frmec, 0);
+ out_be16(&uccup->nosec, 0);
+ out_be16(&uccup->brkec, 0);
+ out_be16(&uccup->uaddr[0], 0);
+ out_be16(&uccup->uaddr[1], 0);
+ out_be16(&uccup->toseq, 0);
+ for (i = 0; i < 8; i++)
+ out_be16(&uccup->cchars[i], 0xC000);
+ out_be16(&uccup->rccm, 0xc0ff);
+
+ /* Configure the GUMR registers for UART */
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ /* Soft-UART requires a 1X multiplier for TX */
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_1 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+#else
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_UART | UCC_SLOW_GUMR_L_TDCR_16 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+#endif
+
+ clrsetbits_be32(&uccp->gumr_h,
+ UCC_SLOW_GUMR_H_RFW,
+ UCC_SLOW_GUMR_H_TRX | UCC_SLOW_GUMR_H_TTX);
+
+#ifdef LOOPBACK
+ clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
+ UCC_SLOW_GUMR_L_DIAG_LOOP);
+ clrsetbits_be32(&uccp->gumr_h,
+ UCC_SLOW_GUMR_H_CTSP | UCC_SLOW_GUMR_H_RSYN,
+ UCC_SLOW_GUMR_H_CDS);
+#endif
+
+ /* Enable rx interrupts and clear all pending events. */
+ out_be16(&uccp->uccm, 0);
+ out_be16(&uccp->ucce, 0xffff);
+ out_be16(&uccp->udsr, 0x7e7e);
+
+ /* Initialize UPSMR */
+ out_be16(&uccp->upsmr, 0);
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+
+ out_be16(&uccup->supsmr, 0x30);
+ out_be16(&uccup->res92, 0);
+ out_be32(&uccup->rx_state, 0);
+ out_be32(&uccup->rx_cnt, 0);
+ out_8(&uccup->rx_bitmark, 0);
+ out_8(&uccup->rx_length, 10);
+ out_be32(&uccup->dump_ptr, 0x4000);
+ out_8(&uccup->rx_temp_dlst_qe, 0);
+ out_be32(&uccup->rx_frame_rem, 0);
+ out_8(&uccup->rx_frame_rem_size, 0);
+ /* Soft-UART requires TX to be 1X */
+ out_8(&uccup->tx_mode, UCC_UART_TX_STATE_UART | UCC_UART_TX_STATE_X1);
+ out_be16(&uccup->tx_state, 0);
+ out_8(&uccup->resD4, 0);
+ out_be16(&uccup->resD5, 0);
+
+ /* Set UART mode.
+ * Enable receive and transmit.
+ */
+
+ /* From the microcode errata:
+ * 1.GUMR_L register, set mode=0010 (QMC).
+ * 2.Set GUMR_H[17] bit. (UART/AHDLC mode).
+ * 3.Set GUMR_H[19:20] (Transparent mode)
+ * 4.Clear GUMR_H[26] (RFW)
+ * ...
+ * 6.Receiver must use 16x over sampling
+ */
+ clrsetbits_be32(&uccp->gumr_l,
+ UCC_SLOW_GUMR_L_MODE_MASK | UCC_SLOW_GUMR_L_TDCR_MASK |
+ UCC_SLOW_GUMR_L_RDCR_MASK,
+ UCC_SLOW_GUMR_L_MODE_QMC | UCC_SLOW_GUMR_L_TDCR_16 |
+ UCC_SLOW_GUMR_L_RDCR_16);
+
+ clrsetbits_be32(&uccp->gumr_h,
+ UCC_SLOW_GUMR_H_RFW | UCC_SLOW_GUMR_H_RSYN,
+ UCC_SLOW_GUMR_H_SUART | UCC_SLOW_GUMR_H_TRX |
+ UCC_SLOW_GUMR_H_TTX | UCC_SLOW_GUMR_H_TFL);
+
+#ifdef LOOPBACK
+ clrsetbits_be32(&uccp->gumr_l, UCC_SLOW_GUMR_L_DIAG_MASK,
+ UCC_SLOW_GUMR_L_DIAG_LOOP);
+ clrbits32(&uccp->gumr_h, UCC_SLOW_GUMR_H_CTSP |
+ UCC_SLOW_GUMR_H_CDS);
+#endif
+
+ cecr_subblock = ucc_slow_get_qe_cr_subblock(qe_port->ucc_num);
+ qe_issue_cmd(QE_INIT_TX_RX, cecr_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0);
+#endif
+}
+
+/*
+ * Initialize the port.
+ */
+static int qe_uart_startup(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ int ret;
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART_UPLOAD
+ /*
+ * If we're using Soft-UART mode, then we need to make sure the
+ * firmware has been uploaded first.
+ */
+ if (!firmware_loaded) {
+ dev_err(port->dev, "Soft-UART firmware not uploaded\n");
+ return -ENODEV;
+ }
+#endif
+
+ qe_uart_initbd(qe_port);
+ qe_uart_init_ucc(qe_port);
+
+ /* Install interrupt handler. */
+ ret = request_irq(port->irq, qe_uart_int, IRQF_SHARED, "ucc-uart",
+ qe_port);
+ if (ret) {
+ dev_err(port->dev, "could not claim IRQ %u\n", port->irq);
+ return ret;
+ }
+
+ /* Startup rx-int */
+ setbits16(&qe_port->uccp->uccm, UCC_UART_UCCE_RX);
+ ucc_slow_enable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+
+ return 0;
+}
+
+/*
+ * Shutdown the port.
+ */
+static void qe_uart_shutdown(struct uart_port *port)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ unsigned int timeout = 20;
+
+ /* Disable RX and TX */
+
+ /* Wait for all the BDs marked sent */
+ while (!qe_uart_tx_empty(port)) {
+ if (!--timeout) {
+ dev_warn(port->dev, "shutdown timeout\n");
+ break;
+ }
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(2);
+ }
+
+ if (qe_port->wait_closing) {
+ /* Wait a bit longer */
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ schedule_timeout(qe_port->wait_closing);
+ }
+
+ /* Stop uarts */
+ ucc_slow_disable(qe_port->us_private, COMM_DIR_RX_AND_TX);
+ clrbits16(&uccp->uccm, UCC_UART_UCCE_TX | UCC_UART_UCCE_RX);
+
+ /* Shut them really down and reinit buffer descriptors */
+ ucc_slow_graceful_stop_tx(qe_port->us_private);
+ qe_uart_initbd(qe_port);
+
+ free_irq(port->irq, qe_port);
+}
+
+/*
+ * Set the serial port parameters.
+ */
+static void qe_uart_set_termios(struct uart_port *port,
+ struct ktermios *termios, struct ktermios *old)
+{
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow __iomem *uccp = qe_port->uccp;
+ unsigned int baud;
+ unsigned long flags;
+ u16 upsmr = in_be16(&uccp->upsmr);
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ struct ucc_uart_pram __iomem *uccup = qe_port->uccup;
+ u16 supsmr = in_be16(&uccup->supsmr);
+ u8 char_length = 2; /* 1 + CL + PEN + 1 + SL */
+#endif
+
+ /* Character length programmed into the mode register is the
+ * sum of: 1 start bit, number of data bits, 0 or 1 parity bit,
+ * 1 or 2 stop bits, minus 1.
+ * The value 'bits' counts this for us.
+ */
+
+ /* byte size */
+ upsmr &= UCC_UART_UPSMR_CL_MASK;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr &= UCC_UART_SUPSMR_CL_MASK;
+#endif
+
+ switch (termios->c_cflag & CSIZE) {
+ case CS5:
+ upsmr |= UCC_UART_UPSMR_CL_5;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_CL_5;
+ char_length += 5;
+#endif
+ break;
+ case CS6:
+ upsmr |= UCC_UART_UPSMR_CL_6;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_CL_6;
+ char_length += 6;
+#endif
+ break;
+ case CS7:
+ upsmr |= UCC_UART_UPSMR_CL_7;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_CL_7;
+ char_length += 7;
+#endif
+ break;
+ default: /* case CS8 */
+ upsmr |= UCC_UART_UPSMR_CL_8;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_CL_8;
+ char_length += 8;
+#endif
+ break;
+ }
+
+ /* If CSTOPB is set, we want two stop bits */
+ if (termios->c_cflag & CSTOPB) {
+ upsmr |= UCC_UART_UPSMR_SL;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_SL;
+ char_length++; /* + SL */
+#endif
+ }
+
+ if (termios->c_cflag & PARENB) {
+ upsmr |= UCC_UART_UPSMR_PEN;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr |= UCC_UART_SUPSMR_PEN;
+ char_length++; /* + PEN */
+#endif
+ if (!(termios->c_cflag & PARODD)) {
+ upsmr &= ~(UCC_UART_UPSMR_RPM_MASK |
+ UCC_UART_UPSMR_TPM_MASK);
+ upsmr |= UCC_UART_UPSMR_RPM_EVEN |
+ UCC_UART_UPSMR_TPM_EVEN;
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ supsmr &= ~(UCC_UART_SUPSMR_RPM_MASK |
+ UCC_UART_SUPSMR_TPM_MASK);
+ supsmr |= UCC_UART_SUPSMR_RPM_EVEN |
+ UCC_UART_SUPSMR_TPM_EVEN;
+#endif
+ }
+ }
+
+ /*
+ * Set up parity check flag
+ */
+ port->read_status_mask = BD_SC_EMPTY | BD_SC_OV;
+ if (termios->c_iflag & INPCK)
+ port->read_status_mask |= BD_SC_FR | BD_SC_PR;
+ if (termios->c_iflag & (BRKINT | PARMRK))
+ port->read_status_mask |= BD_SC_BR;
+
+ /*
+ * Characters to ignore
+ */
+ port->ignore_status_mask = 0;
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= BD_SC_PR | BD_SC_FR;
+ if (termios->c_iflag & IGNBRK) {
+ port->ignore_status_mask |= BD_SC_BR;
+ /*
+ * If we're ignore parity and break indicators, ignore
+ * overruns too. (For real raw support).
+ */
+ if (termios->c_iflag & IGNPAR)
+ port->ignore_status_mask |= BD_SC_OV;
+ }
+ /*
+ * !!! ignore all characters if CREAD is not set
+ */
+ if ((termios->c_cflag & CREAD) == 0)
+ port->read_status_mask &= ~BD_SC_EMPTY;
+
+ baud = uart_get_baud_rate(port, termios, old, 0, 115200);
+
+ /* Do we really need a spinlock here? */
+ spin_lock_irqsave(&port->lock, flags);
+
+ out_be16(&uccp->upsmr, upsmr);
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ out_be16(&uccup->supsmr, supsmr);
+ out_8(&uccup->rx_length, char_length);
+
+ /* Soft-UART requires a 1X multiplier for TX */
+ qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
+ qe_setbrg(qe_port->us_info.tx_clock, baud, 1);
+#else
+ qe_setbrg(qe_port->us_info.rx_clock, baud, 16);
+ qe_setbrg(qe_port->us_info.tx_clock, baud, 16);
+#endif
+
+ spin_unlock_irqrestore(&port->lock, flags);
+}
+
+/*
+ * Return a pointer to a string that describes what kind of port this is.
+ */
+static const char *qe_uart_type(struct uart_port *port)
+{
+ return "QE";
+}
+
+/*
+ * Allocate any memory and I/O resources required by the port.
+ */
+static int qe_uart_request_port(struct uart_port *port)
+{
+ int ret;
+ struct uart_qe_port *qe_port =
+ container_of(port, struct uart_qe_port, port);
+ struct ucc_slow_info *us_info = &qe_port->us_info;
+ struct ucc_slow_private *uccs;
+ unsigned int rx_size, tx_size;
+ void *bd_virt;
+ dma_addr_t bd_phys = 0;
+
+ ret = ucc_slow_init(us_info, &uccs);
+ if (ret) {
+ dev_err(port->dev, "could not initialize UCC%u\n",
+ qe_port->ucc_num);
+ return ret;
+ }
+
+ qe_port->us_private = uccs;
+ qe_port->uccp = uccs->us_regs;
+ qe_port->uccup = (struct ucc_uart_pram *) uccs->us_pram;
+ qe_port->rx_bd_base = uccs->rx_bd;
+ qe_port->tx_bd_base = uccs->tx_bd;
+
+ /*
+ * Allocate the transmit and receive data buffers.
+ */
+
+ 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_phys,
+ GFP_KERNEL);
+ if (!bd_virt) {
+ dev_err(port->dev, "could not allocate buffer descriptors\n");
+ return -ENOMEM;
+ }
+
+ qe_port->bd_virt = bd_virt;
+ qe_port->bd_phys = bd_phys;
+ qe_port->bd_size = rx_size + tx_size;
+
+ qe_port->rx_buf = bd_virt;
+ qe_port->tx_buf = qe_port->rx_buf + rx_size;
+
+ return 0;
+}
+
+/*
+ * Configure the port.
+ *
+ * We say we're a CPM-type port because that's mostly true. Once the device
+ * is configured, this driver operates almost identically to the CPM serial
+ * driver.
+ */
+static void qe_uart_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_CPM;
+ qe_uart_request_port(port);
+ }
+}
+
+/*
+ * Release any memory and I/O resources that were allocated in
+ * qe_uart_request_port().
+ */
+static void qe_uart_release_port(struct uart_port *port)
+{
+ struct uart_qe_port *qe_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,
+ qe_port->bd_phys);
+
+ ucc_slow_free(uccs);
+}
+
+/*
+ * Verify that the data in serial_struct is suitable for this device.
+ */
+static int qe_uart_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_CPM)
+ return -EINVAL;
+
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ return -EINVAL;
+
+ if (ser->baud_base < 9600)
+ return -EINVAL;
+
+ return 0;
+}
+/* UART operations
+ *
+ * Details on these functions can be found in Documentation/serial/driver
+ */
+static struct uart_ops qe_uart_pops = {
+ .tx_empty = qe_uart_tx_empty,
+ .set_mctrl = qe_uart_set_mctrl,
+ .get_mctrl = qe_uart_get_mctrl,
+ .stop_tx = qe_uart_stop_tx,
+ .start_tx = qe_uart_start_tx,
+ .stop_rx = qe_uart_stop_rx,
+ .enable_ms = qe_uart_enable_ms,
+ .break_ctl = qe_uart_break_ctl,
+ .startup = qe_uart_startup,
+ .shutdown = qe_uart_shutdown,
+ .set_termios = qe_uart_set_termios,
+ .type = qe_uart_type,
+ .release_port = qe_uart_release_port,
+ .request_port = qe_uart_request_port,
+ .config_port = qe_uart_config_port,
+ .verify_port = qe_uart_verify_port,
+};
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART_UPLOAD
+/*
+ * Obtain the SOC model number and revision level
+ *
+ * This function reads and parses system registers to determine the
+ * Freescale SOC model number (e.g. 8323) and revision.
+ */
+static unsigned int soc_info(unsigned int *rev_h, unsigned int *rev_l)
+{
+ unsigned int svr;
+ unsigned int soc;
+
+ svr = mfspr(SPRN_SVR);
+
+ switch (svr >> 16) {
+ case 0x8048:
+ case 0x8049:
+ soc = 8360;
+ break;
+ case 0x8062:
+ case 0x8063:
+ soc = 8323;
+ break;
+ default:
+ return 0;
+ }
+
+ *rev_h = (svr >> 4) & 0xf;
+ *rev_l = svr & 0xf;
+
+ return soc;
+}
+
+/*
+ * requst_firmware_nowait() callback function
+ *
+ * This function is called by the kernel when a firmware is made available,
+ * or if it times out waiting for the firmware.
+ */
+static void uart_firmware_cont(const struct firmware *fw, void *context)
+{
+ struct qe_firmware *firmware;
+ struct device *dev = context;
+ int ret;
+
+ if (!fw) {
+ dev_err(dev, "firmware not found\n");
+ return;
+ }
+
+ firmware = (struct qe_firmware *) fw->data;
+
+ if (firmware->header.length != fw->size) {
+ dev_err(dev, "invalid firmware\n");
+ return;
+ }
+
+ ret = qe_upload_firmware(firmware);
+ if (ret) {
+ dev_err(dev, "could not load firmware\n");
+ return;
+ }
+
+ firmware_loaded = 1;
+}
+#endif
+
+static int ucc_uart_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ struct device_node *np = ofdev->node;
+ const unsigned int *iprop; /* Integer OF properties */
+ const char *sprop; /* String OF properties */
+ struct uart_qe_port *qe_port = NULL;
+ struct resource res;
+ int ret;
+
+#ifdef CONFIG_SERIAL_QE_SOFT_UART_UPLOAD
+ /*
+ * Soft UART is always provided via an uploaded microcode.
+ */
+ if (!firmware_loaded) {
+ char filename[32];
+ unsigned int soc;
+ unsigned int rev_h;
+ unsigned int rev_l;
+
+ soc = soc_info(&rev_h, &rev_l);
+ if (!soc) {
+ dev_err(&ofdev->dev, "unrecognized CPU model\n");
+ return -ENXIO;
+ }
+ sprintf(filename, "fsl_qe_ucode_uart_%u_%u%u.bin",
+ soc, rev_h, rev_l);
+
+ dev_info(&ofdev->dev, "waiting for firmware %s\n", filename);
+
+ /*
+ * We call request_firmware_nowait instead of request_firmware
+ * so that the driver can load and initialize the ports without
+ * holding up the rest of the kernel. If hotplug support is
+ * enabled in the kernel, then we use it.
+ */
+ ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG,
+ filename, &ofdev->dev, &ofdev->dev, uart_firmware_cont);
+ if (ret) {
+ dev_err(&ofdev->dev,
+ "could not load firmware %s\n", filename);
+ return ret;
+ }
+ }
+
+#endif
+
+ qe_port = kzalloc(sizeof(struct uart_qe_port), GFP_KERNEL);
+ if (!qe_port) {
+ dev_err(&ofdev->dev, "can't allocate QE port structure\n");
+ return -ENOMEM;
+ }
+
+ /* Search for IRQ and mapbase */
+ ret = of_address_to_resource(np, 0, &res);
+ if (ret) {
+ dev_err(&ofdev->dev, "missing 'reg' property in device tree\n");
+ kfree(qe_port);
+ return ret;
+ }
+ if (!res.start) {
+ dev_err(&ofdev->dev, "invalid 'reg' property in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ qe_port->port.mapbase = res.start;
+
+ /* Get the UCC number (device ID) */
+ /* UCCs are numbered 1-7 */
+ iprop = of_get_property(np, "device-id", NULL);
+ if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) {
+ dev_err(&ofdev->dev,
+ "missing or invalid UCC specified in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+ qe_port->ucc_num = *iprop - 1;
+
+ /* In the future, we should not require the BRG to be specified in the
+ device tree. If no clock-source is specified, then just pick a BRG
+ to use. This requires a new QE library function that manages BRG
+ assignments. */
+
+ sprop = of_get_property(np, "rx-clock-name", NULL);
+ if (!sprop) {
+ dev_err(&ofdev->dev, "missing rx-clock-name in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+ qe_port->us_info.rx_clock = qe_clock_source(sprop);
+ if ((qe_port->us_info.rx_clock < QE_BRG1) ||
+ (qe_port->us_info.rx_clock > QE_BRG16)) {
+ dev_err(&ofdev->dev, "rx-clock-name must be a BRG for UART\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+#ifdef LOOPBACK
+ /* In internal loopback mode, TX and RX must use the same clock */
+ qe_port->us_info.tx_clock = qe_port->us_info.rx_clock;
+#else
+ sprop = of_get_property(np, "tx-clock-name", NULL);
+ if (!sprop) {
+ dev_err(&ofdev->dev, "missing tx-clock-name in device tree\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+ qe_port->us_info.tx_clock = qe_clock_source(sprop);
+#endif
+ if ((qe_port->us_info.tx_clock < QE_BRG1) ||
+ (qe_port->us_info.tx_clock > QE_BRG16)) {
+ dev_err(&ofdev->dev, "tx-clock-name must be a BRG for UART\n");
+ kfree(qe_port);
+ return -ENODEV;
+ }
+
+ /* Get the port number, numbered 0-3 */
+ iprop = of_get_property(np, "port-number", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev, "missing port-number in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ qe_port->port.line = *iprop;
+ if (qe_port->port.line >= UCC_MAX_UART) {
+ dev_err(&ofdev->dev, "port-number must be 0-%u\n",
+ UCC_MAX_UART - 1);
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ qe_port->port.irq = irq_of_parse_and_map(np, 0);
+ if (qe_port->port.irq == NO_IRQ) {
+ dev_err(&ofdev->dev, "could not map IRQ for UCC%u\n",
+ qe_port->ucc_num + 1);
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ np = of_find_node_by_type(NULL, "qe");
+ if (!np) {
+ dev_err(&ofdev->dev, "could not find parent 'qe' node\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ iprop = of_get_property(np, "brg-frequency", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev,
+ "missing brg-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+
+ if (*iprop)
+ qe_port->port.uartclk = *iprop;
+ else {
+ /*
+ * Older versions of U-Boot do not initialize the brg-frequency
+ * property, so in this case we assume the BRG frequency is
+ * half the QE bus frequency.
+ */
+ iprop = of_get_property(np, "bus-frequency", NULL);
+ if (!iprop) {
+ dev_err(&ofdev->dev,
+ "missing QE bus-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ if (*iprop)
+ qe_port->port.uartclk = *iprop / 2;
+ else {
+ dev_err(&ofdev->dev,
+ "invalid QE bus-frequency in device tree\n");
+ kfree(qe_port);
+ return -EINVAL;
+ }
+ }
+
+ spin_lock_init(&qe_port->port.lock);
+ qe_port->np = np;
+ qe_port->port.dev = &ofdev->dev;
+ qe_port->port.ops = &qe_uart_pops;
+ qe_port->port.iotype = UPIO_MEM;
+
+ qe_port->tx_nrfifos = TX_NUM_FIFO;
+ qe_port->tx_fifosize = TX_BUF_SIZE;
+ qe_port->rx_nrfifos = RX_NUM_FIFO;
+ qe_port->rx_fifosize = RX_BUF_SIZE;
+
+ qe_port->wait_closing = UCC_WAIT_CLOSING;
+ qe_port->port.fifosize = 512;
+ qe_port->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP;
+
+ qe_port->us_info.ucc_num = qe_port->ucc_num;
+ qe_port->us_info.regs = (phys_addr_t) res.start;
+ qe_port->us_info.irq = qe_port->port.irq;
+
+ qe_port->us_info.rx_bd_ring_len = qe_port->rx_nrfifos;
+ qe_port->us_info.tx_bd_ring_len = qe_port->tx_nrfifos;
+
+ /* Make sure ucc_slow_init() initializes both TX and RX */
+ qe_port->us_info.init_tx = 1;
+ qe_port->us_info.init_rx = 1;
+
+ /* Add the port to the uart sub-system. This will cause
+ * qe_uart_config_port() to be called, so the us_info structure must
+ * be initialized.
+ */
+ ret = uart_add_one_port(&ucc_uart_driver, &qe_port->port);
+ if (ret) {
+ dev_err(&ofdev->dev, "could not add /dev/ttyQE%u\n",
+ qe_port->port.line);
+ kfree(qe_port);
+ return ret;
+ }
+
+ dev_set_drvdata(&ofdev->dev, qe_port);
+
+ dev_info(&ofdev->dev, "UCC%u assigned to ttyQE%u\n",
+ qe_port->ucc_num + 1, qe_port->port.line);
+
+ /* Display the mknod command for this device */
+ dev_dbg(&ofdev->dev, "mknod command is 'mknod /dev/ttyQE%u c %u %u'\n",
+ qe_port->port.line, SERIAL_QE_MAJOR,
+ SERIAL_QE_MINOR + qe_port->port.line);
+
+ return 0;
+}
+
+static int ucc_uart_remove(struct of_device *ofdev)
+{
+ struct uart_qe_port *qe_port = dev_get_drvdata(&ofdev->dev);
+
+ dev_info(&ofdev->dev, "removing /dev/ttyQE%u\n", qe_port->port.line);
+
+ uart_remove_one_port(&ucc_uart_driver, &qe_port->port);
+
+ dev_set_drvdata(&ofdev->dev, NULL);
+ kfree(qe_port);
+
+ return 0;
+}
+
+static struct of_device_id ucc_uart_match[] = {
+ {
+ .type = "serial",
+ .compatible = "ucc_uart",
+ },
+ {},
+};
+MODULE_DEVICE_TABLE(of, ucc_uart_match);
+
+static struct of_platform_driver ucc_uart_of_driver = {
+ .owner = THIS_MODULE,
+ .name = "ucc_uart",
+ .match_table = ucc_uart_match,
+ .probe = ucc_uart_probe,
+ .remove = ucc_uart_remove,
+};
+
+static int __init ucc_uart_init(void)
+{
+ int ret;
+
+ printk(KERN_INFO "Freescale QUICC Engine UART device driver\n");
+#ifdef CONFIG_SERIAL_QE_SOFT_UART
+ printk(KERN_INFO "ucc-uart: Using Soft-UART mode\n");
+#endif
+#ifdef LOOPBACK
+ printk(KERN_INFO "ucc-uart: Using loopback mode\n");
+#endif
+
+ ret = uart_register_driver(&ucc_uart_driver);
+ if (ret) {
+ printk(KERN_ERR "ucc-uart: could not register UART driver\n");
+ return ret;
+ }
+
+ ret = of_register_platform_driver(&ucc_uart_of_driver);
+ if (ret)
+ printk(KERN_ERR
+ "ucc-uart: could not register platform driver\n");
+
+ return ret;
+}
+
+static void __exit ucc_uart_exit(void)
+{
+ printk(KERN_INFO
+ "Freescale QUICC Engine UART device driver unloading\n");
+
+ of_unregister_platform_driver(&ucc_uart_of_driver);
+ uart_unregister_driver(&ucc_uart_driver);
+}
+
+module_init(ucc_uart_init);
+module_exit(ucc_uart_exit);
+
+MODULE_DESCRIPTION("Freescale QUICC Engine (QE) UART");
+MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS_CHARDEV_MAJOR(SERIAL_QE_MAJOR);
+
--
1.5.2.4
^ permalink raw reply related
* Re: [PATCH 5/7] powerpc: Replace ppc_md.power_off with pm_power_off
From: Mark A. Greer @ 2007-12-04 18:01 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1196752989.13230.265.camel@pasglop>
On Tue, Dec 04, 2007 at 06:23:09PM +1100, Benjamin Herrenschmidt wrote:
>
> On Mon, 2007-12-03 at 22:48 -0700, Mark A. Greer wrote:
> > From: Mark A. Greer <mgreer@mvista.com>
> >
> > The ppc_md.power_off hook performs the same function that the
> > pm_power_off hook is supposed to. However, it is powerpc-specific
> > and prevents kernel drivers (e.g., IPMI) from changing how a platform
> > is powered off. So, get rid of ppc_md.power_off and replace it with
> > pm_power_off.
>
> I'm less happy with that one... probably aesthetics :-)
>
> Can't we just have the generic code call pm_power_off and ppc_md and
> which ever powers the machine off wins ?
Yes, that would be easy to do. Seems like duplication though.
If you are sure you're okay with the duplication, I'll do that.
Mark
^ permalink raw reply
* Re: [PATCH 2.6.24] pasemi_mac: Fix reuse of free'd skb
From: David Woodhouse @ 2007-12-04 18:04 UTC (permalink / raw)
To: Olof Johansson; +Cc: ranger, netdev, jgarzik, linuxppc-dev
In-Reply-To: <20071204033414.GA13616@lixom.net>
Oops: Exception in kernel mode, sig: 5 [#1]
nfs: server pmac not responding, still trying
SMP NR_CPUS=128 NUMA PA Semi PWRficient
Modules linked in: appletouch cbc blkcipher dm_crypt dm_emc dm_round_robin dm_mu
ltipath dm_snapshot dm_mirror dm_zero dm_mod xfs jfs reiserfs lock_nolock gfs2 m
sdos linear raid10 raid456 async_memcpy async_tx async_xor xor raid1 raid0 sata_
mv libata pasemi_mac gpio_mdio libphy ehci_hcd ohci_hcd iscsi_tcp libiscsi scsi_
transport_iscsi sr_mod sd_mod scsi_mod ide_cd cdrom ipv6 ext2 ext4dev crc16 jbd2
ext3 mbcache jbd squashfs loop nfs nfs_acl lockd sunrpc vfat fat cramfs
NIP: c0000000003af2f0 LR: c0000000003af2ec CTR: c0000000000791c0
REGS: c00000000ffff9c0 TRAP: 0700 Not tainted (2.6.24-0.67.rc3.git7.fc9)
MSR: 9000000000029032 <EE,ME,IR,DR> CR: 24000028 XER: 00000000
TASK = c000000000677720[0] 'swapper' THREAD: c000000000758000 CPU: 0
GPR00: c0000000003af2ec c00000000ffffc40 c000000000753d98 0000000000000087
GPR04: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
GPR08: c000000000677720 0000000000000000 0000000000000004 0000000000000000
GPR12: 0000000000000000 c000000000678200 0000000000000000 0000000000000000
GPR16: 0000000000000000 0000000000000000 0000000000000000 4000000001400000
GPR20: 0000000000000040 00000000000006e0 00000000000006e8 0000000000000037
GPR24: 0000000000000000 c00000003ba40370 00000000000000dc 540045ee0111a3a8
GPR28: 00000000000005ee c00000003d104900 c000000000712b18 c00000003b939800
NIP [c0000000003af2f0] .skb_over_panic+0x50/0x58
LR [c0000000003af2ec] .skb_over_panic+0x4c/0x58
Call Trace:
[c00000000ffffc40] [c0000000003af2ec] .skb_over_panic+0x4c/0x58 (unreliable)
[c00000000ffffcd0] [d0000000002dfb10] .pasemi_mac_clean_rx+0x2f0/0x480 [pasemi_m
ac]
[c00000000ffffda0] [d0000000002e008c] .pasemi_mac_poll+0x44/0xe4 [pasemi_mac]
[c00000000ffffe40] [c0000000003bba54] .net_rx_action+0xf8/0x214
[c00000000ffffef0] [c00000000008eb58] .__do_softirq+0xa8/0x164
[c00000000fffff90] [c00000000002b468] .call_do_softirq+0x14/0x24
[c00000000075b940] [c00000000000d4d0] .do_softirq+0x68/0xac
[c00000000075b9d0] [c00000000008ecc8] .irq_exit+0x60/0xb0
[c00000000075ba50] [c00000000000db00] .do_IRQ+0x174/0x1e8
[c00000000075baf0] [c000000000004c24] hardware_interrupt_entry+0x24/0x28
--- Exception: 501 at .ppc64_runlatch_off+0x0/0x54
LR = .cpu_idle+0x70/0x1f0
[c00000000075bde0] [c0000000000135c4] .cpu_idle+0x11c/0x1f0 (unreliable)
[c00000000075be60] [c000000000009b08] .rest_init+0x78/0x90
[c00000000075bee0] [c0000000005c59ec] .start_kernel+0x3f8/0x41c
[c00000000075bf90] [c000000000008590] .start_here_common+0x60/0xd0
Instruction dump:
80a30068 e8e300c8 e90300d0 812300bc 814300c0 2fa00000 409e0008 e81e8018
e87e8028 f8010070 4bcd92cd 60000000 <0fe00000> 48000000 7c0802a6 faa1ffa8
Kernel panic - not syncing: Fatal exception in interrupt
Rebooting in 180 seconds..
--
dwmw2
^ permalink raw reply
* Re: [PATCH 2.6.24] pasemi_mac: Fix reuse of free'd skb
From: David Woodhouse @ 2007-12-04 18:12 UTC (permalink / raw)
To: Olof Johansson; +Cc: ranger, netdev, jgarzik, linuxppc-dev
In-Reply-To: <1196791478.13978.359.camel@pmac.infradead.org>
On Tue, 2007-12-04 at 18:04 +0000, David Woodhouse wrote:
> Oops: Exception in kernel mode, sig: 5 [#1]
> nfs: server pmac not responding, still trying
Oops, sorry. That was meant to be just to Olof. And it helps if I'm
actually running the kernel in which his patch is applied, too...
--
dwmw2
^ permalink raw reply
* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Olof Johansson @ 2007-12-04 18:48 UTC (permalink / raw)
To: Anton Vorontsov
Cc: Jeff Garzik, Arnd Bergmann, linux-ide, linuxppc-dev, Paul Mundt
In-Reply-To: <20071204170719.GB15599@localhost.localdomain>
Hi,
On Tue, Dec 04, 2007 at 08:07:19PM +0300, Anton Vorontsov wrote:
> This driver nicely wraps around pata_platform library functions,
> and provides OF platform bus bindings to the PATA devices.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> drivers/ata/Kconfig | 10 ++++
> drivers/ata/Makefile | 1 +
> drivers/ata/pata_of_platform.c | 102 ++++++++++++++++++++++++++++++++++++++++
> 3 files changed, 113 insertions(+), 0 deletions(-)
> create mode 100644 drivers/ata/pata_of_platform.c
>
> diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
> index ba63619..5a492fa 100644
> --- a/drivers/ata/Kconfig
> +++ b/drivers/ata/Kconfig
> @@ -614,6 +614,16 @@ config PATA_PLATFORM
>
> If unsure, say N.
>
> +config PATA_OF_PLATFORM
> + tristate "OpenFirmware platform device PATA support"
> + depends on PATA_PLATFORM && PPC_OF
> + help
> + This option enables support for generic directly connected ATA
> + devices commonly found on embedded systems with OpenFirmware
> + bindings.
> +
> + If unsure, say N.
> +
There's a typo in the dependencies for PATA_PLATFORM that you should change:
depends on EMBEDDED || ARCH_RPC
(note ARCH_>R<PC). With my font it's hard to tell a difference :)
It should really be:
depends on EMBEDDED || PPC
Care to change that while you're at it?
> +static struct of_device_id pata_of_platform_match[] = {
> + { .compatible = "ata-generic", },
> +};
Needs to be terminated by empty entry, and please add:
MODULE_DEVICE_TABLE(of, pata_of_platform_match);
-Olof
^ permalink raw reply
* Re: [PATCH v2 3/4] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
From: Olof Johansson @ 2007-12-04 19:16 UTC (permalink / raw)
To: Anton Vorontsov
Cc: linuxppc-dev, Paul Mundt, Arnd Bergmann, Jeff Garzik, linux-ide
In-Reply-To: <20071204170726.GC15599@localhost.localdomain>
Hi,
On Tue, Dec 04, 2007 at 08:07:26PM +0300, Anton Vorontsov wrote:
> diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
> index 5072f6d..c459b0a 100644
> --- a/arch/powerpc/boot/dts/mpc8349emitx.dts
> +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
> @@ -249,6 +249,22 @@
> device_type = "pci";
> };
>
> + localbus@e0005000 {
> + #address-cells = <2>;
> + #size-cells = <1>;
> + compatible = "fsl,mpc8349emitx-localbus",
> + "fsl,mpc8349e-localbus",
> + "fsl,pq2pro-localbus";
> + reg = <e0005000 d8>;
> + ranges = <3 0 f0000000 210>;
>
> -
> + pata@3,0 {
What's the ,0 for?
> + compatible = "fsl,mpc8349emitx-pata", "ata-generic";
> + reg = <3 0 10 3 20c 4>;
> + reg-shift = <1>;
> + pio-mode = <6>;
> + interrupts = <17 8>;
> + interrupt-parent = <&ipic>;
> + };
> + };
> };
> diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
> index aa76819..ea5f176 100644
> --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
> +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
> @@ -23,6 +23,7 @@
> #include <linux/delay.h>
> #include <linux/seq_file.h>
> #include <linux/root_dev.h>
> +#include <linux/of_platform.h>
>
> #include <asm/system.h>
> #include <asm/atomic.h>
> @@ -37,6 +38,22 @@
>
> #include "mpc83xx.h"
>
> +static struct of_device_id mpc834x_itx_ids[] = {
> + { .name = "localbus", },
> + {},
> +};
Please add the "compatible" field here (fsl,pq2pro-localbus should do
just fine), instead of the name.
(Sorry for not spotting this sooner)
-Olof
^ permalink raw reply
* 2.6.25-candidates branch updated in 4xx tree
From: Josh Boyer @ 2007-12-04 19:11 UTC (permalink / raw)
To: linuxppc-dev
For those following my tree, I've added a 2.6.25-candidates branch and
based it off of Paul's latest master. (If you've already pulled
you'll have to reset, sorry.)
I call it candidates because several patches (most notably Ben's) will
probably get reworked a little before I ask Paul to pull them into his
tree. There are also EMAC patches in there that will go through Jeff
Garzik rather than me.
The branch contains the commits below. I'm sure I've missed one or two,
so feel free to reply and let me know if you think a patch is needed
for 4xx in 2.6.25.
josh
Benjamin Herrenschmidt (32):
[POWERPC] ibm_newemac: Fix possible lockup on close
[POWERPC] usb: Remove OHCI useless masking/unmasking of WDH interrupt
[POWERPC] usb: Remove broken optimisation in OHCI IRQ handler
[POWERPC] drm: Fix for non-coherent DMA PowerPC
[POWERPC] ibm_newemac: Fix ZMII refcounting bug
[POWERPC] ibm_newemac: Workaround reset timeout when no link
[POWERPC] ibm_newemac: Cleanup/Fix RGMII MDIO support detection
[POWERPC] ibm_newemac: Cleanup/fix support for STACR register variants
[POWERPC] emac: Update file headers copyright notices
[POWERPC] Make isa_mem_base common to 32 and 64 bits
[POWERPC] Merge pci_process_bridge_OF_ranges()
[POWERPC] Fix powerpc 32 bits resource fixup for 64 bits resources
[POWERPC] 4xx: Fix 440/440A machine check handling
[POWERPC] 4xx: Fix 440SPE machine check
[POWERPC] 4xx: Add xmon function to dump 44x TLB
[POWERPC] Change 32 bits PCI message about resource allocation
[POWERPC] Add of_translate_dma_address
[POWERPC] 4xx: Improve support for 4xx indirect DCRs
[POWERPC] 4xx: PLB to PCI-X support
[POWERPC] 4xx: PLB to PCI 2.x support
[POWERPC] 4xx: PLB to PCI Express support
[POWERPC] 4xx: PCI support for 4xx Ebony board
[POWERPC] 4xx: Add early udbg support for 40x processors
[POWERPC] early debug forces console log level to max
[POWERPC] 4xx: EP405 boards support for arch/powerpc
[POWERPC] 4xx: Add PCI to Walnut platform
[POWERPC] 4xx: Wire up PCI on Bamboo board
[POWERPC] 4xx: Wire up 440EP USB controller support to Bamboo board
[POWERPC] 4xx: Adds decoding of 440SPE memory size to boot wrapper library
[POWERPC] 4xx: Add mfspr/mtspr inline macros to 4xx bootwrapper
[POWERPC] 4xx: Rework 4xx clock probing in boot wrapper
[POWERPC] 4xx: Base support for 440SPe "Katmai" eval board
Hugh Blemings (2):
[POWERPC] ibm_newemac: Skip EMACs that are marked unused by the firmware
[POWERPC] 4xx: Base support for 440GX Taishan eval board
Josh Boyer (1):
[POWERPC] 4xx: Fix 440grx setup function to call 440A fixup
Stefan Roese (6):
[POWERPC] 4xx: Fix TLB 0 problem with CONFIG_SERIAL_TEXT_DEBUG
[POWERPC] ibm_newemac: Add BCM5248 and Marvell 88E1111 PHY support
[POWERPC] ibm_newemac: Add ET1011c PHY support
[POWERPC] 4xx: Add 405EX CPU type needed for EMAC support on Kilauea
[POWERPC] 4xx: Change Kilauea dts to support new EMAC device tree properti
[POWERPC] 4xx: Add EMAC support to Kilauea defconfig
Valentine Barshak (7):
[POWERPC] ibm_newemac: Correct opb_bus_freq value
[POWERPC] ibm_newemac: Fix typo reading TAH channel info
[POWERPC] ibm_newemac: Call dev_set_drvdata() before tah_reset()
[POWERPC] 4xx: 440GRx Rainier bootwrapper.
[POWERPC] 4xx: 440GRx Rainier DTS.
[POWERPC] 4xx: 440GRx Rainier board support.
[POWERPC] 4xx: 440GRx Rainier default config
^ permalink raw reply
* Re: [PATCH v2 3/4] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
From: Scott Wood @ 2007-12-04 19:23 UTC (permalink / raw)
To: Olof Johansson
Cc: Arnd Bergmann, Jeff Garzik, linuxppc-dev, linux-ide, Paul Mundt
In-Reply-To: <20071204191657.GB5758@lixom.net>
Olof Johansson wrote:
> Hi,
>
> On Tue, Dec 04, 2007 at 08:07:26PM +0300, Anton Vorontsov wrote:
>> diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
>> index 5072f6d..c459b0a 100644
>> --- a/arch/powerpc/boot/dts/mpc8349emitx.dts
>> +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
>> @@ -249,6 +249,22 @@
>> device_type = "pci";
>> };
>>
>> + localbus@e0005000 {
>> + #address-cells = <2>;
>> + #size-cells = <1>;
>> + compatible = "fsl,mpc8349emitx-localbus",
>> + "fsl,mpc8349e-localbus",
>> + "fsl,pq2pro-localbus";
>> + reg = <e0005000 d8>;
>> + ranges = <3 0 f0000000 210>;
>>
>> -
>> + pata@3,0 {
>
> What's the ,0 for?
chipselect 3, offset 0.
-Scott
^ permalink raw reply
* Re: [PATCH 2/2] [POWERPC] pasemi: Register i2c_board_info
From: Olof Johansson @ 2007-12-04 19:32 UTC (permalink / raw)
To: David Woodhouse; +Cc: linuxppc-dev
In-Reply-To: <1196774926.13978.225.camel@pmac.infradead.org>
On Tue, Dec 04, 2007 at 01:28:46PM +0000, David Woodhouse wrote:
>
> On Thu, 2007-11-29 at 21:29 -0600, Olof Johansson wrote:
> > + continue;
> > +
> > + info.addr = *addr;
> > +
> > + i2c_register_board_info(PCI_FUNC(pdev->devfn),
> > &info,
> > + 1);
> > + }
> > + }
>
> + /* Ensure that buses up to 2 are reserved */
> + i2c_register_board_info(2, NULL, 0);
> +
>
>
> > + return 0;
> > +}
> > +device_initcall(pasemi_register_i2c_devices);
> > +#endif
>
>
> Otherwise when you make i2c-pasemi use i2c_add_numbered_adapter(), it
> might fail to register the third bus -- because there were no devices
> preregistered on it, so something else might have stolen that bus number
> already.
Good point, I'd missed that. Thanks!
> You might want to add the patch to use i2c_add_numbered_adapter() to
> your tree, btw.
Yep, I realized that after (re)asking Paul to pull though, and didn't
want to do a third request before he's done it. :)
If he doesn't pull in the next few days I might just keep adding new
patches as they come in though, and add it back.
-Olof
^ permalink raw reply
* Re: [PATCH v2 2/2] [POWERPC] Use new machine_xxx_initcall hooks in platform code
From: Arnd Bergmann @ 2007-12-04 19:35 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Geert Uytterhoeven, olof
In-Reply-To: <fa686aa40712040621r3103bae9hd900c23d48273360@mail.gmail.com>
On Tuesday 04 December 2007, Grant Likely wrote:
> On 12/4/07, Grant Likely <grant.likely@secretlab.ca> wrote:
> > On 12/4/07, Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com> wrote:
> > > You seem to have missed the PS3 *_initcall()s.
> > > Probably because they test for firmware_has_feature(FW_FEATURE_PS3_LV1) instead
> > > of machine_is(ps3).
> >
> > That's exactly why; I didn't know if 'machine_is(ps3)' was a suitable
> > substitute so I left it alone.
>
> On that topic; I left some pseries and iseries stuff alone also for
> the same reason.
Yes, and in many cases it's the right answer to base a decision on a specific
feature rather than a platform name, for two reasons:
1. If another platform gets added that uses the same firmware feature, it
will automatically do the right thing.
2. The call to firmware_has_feature() turns into a compile-time check in
many cases, so if the kernel does not contain support for any firmware
with the given feature, all the code referenced it can get optimized
away by the compiler.
If we have many cases where an initcall is done based on a specific fw-feature
or cpu-feature, we might want to add a similar initcall mechanism for those
along the lines of machine_xxx_initcall, but of course we should be sure
not to overengineer things here.
Arnd <><
^ permalink raw reply
* Re: [PATCH v2 3/4] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
From: Anton Vorontsov @ 2007-12-04 19:45 UTC (permalink / raw)
To: Olof Johansson
Cc: linuxppc-dev, Paul Mundt, Arnd Bergmann, Jeff Garzik, linux-ide
In-Reply-To: <20071204191657.GB5758@lixom.net>
On Tue, Dec 04, 2007 at 01:16:57PM -0600, Olof Johansson wrote:
> Hi,
>
> On Tue, Dec 04, 2007 at 08:07:26PM +0300, Anton Vorontsov wrote:
> > diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
> > index 5072f6d..c459b0a 100644
[...]
> > +static struct of_device_id mpc834x_itx_ids[] = {
> > + { .name = "localbus", },
> > + {},
> > +};
>
> Please add the "compatible" field here (fsl,pq2pro-localbus should do
> just fine), instead of the name.
Done, thanks.
- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [PATCH v2.1] [POWERPC] MPC8349E-mITX: introduce localbus and pata nodes
This patch adds localbus and pata nodes to use CF IDE interface
on MPC8349E-mITX boards.
Patch also adds code to probe localbus.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
arch/powerpc/boot/dts/mpc8349emitx.dts | 18 +++++++++++++++++-
arch/powerpc/platforms/83xx/mpc834x_itx.c | 17 +++++++++++++++++
2 files changed, 34 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts
index 5072f6d..c459b0a 100644
--- a/arch/powerpc/boot/dts/mpc8349emitx.dts
+++ b/arch/powerpc/boot/dts/mpc8349emitx.dts
@@ -249,6 +249,22 @@
device_type = "pci";
};
+ localbus@e0005000 {
+ #address-cells = <2>;
+ #size-cells = <1>;
+ compatible = "fsl,mpc8349emitx-localbus",
+ "fsl,mpc8349e-localbus",
+ "fsl,pq2pro-localbus";
+ reg = <e0005000 d8>;
+ ranges = <3 0 f0000000 210>;
-
+ pata@3,0 {
+ compatible = "fsl,mpc8349emitx-pata", "ata-generic";
+ reg = <3 0 10 3 20c 4>;
+ reg-shift = <1>;
+ pio-mode = <6>;
+ interrupts = <17 8>;
+ interrupt-parent = <&ipic>;
+ };
+ };
};
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c
index aa76819..4797850 100644
--- a/arch/powerpc/platforms/83xx/mpc834x_itx.c
+++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c
@@ -23,6 +23,7 @@
#include <linux/delay.h>
#include <linux/seq_file.h>
#include <linux/root_dev.h>
+#include <linux/of_platform.h>
#include <asm/system.h>
#include <asm/atomic.h>
@@ -37,6 +38,22 @@
#include "mpc83xx.h"
+static struct of_device_id mpc834x_itx_ids[] = {
+ { .compatible = "fsl,pq2pro-localbus", },
+ {},
+};
+
+static int __init mpc834x_itx_declare_of_platform_devices(void)
+{
+ if (!machine_is(mpc834x_itx))
+ return 0;
+
+ of_platform_bus_probe(NULL, mpc834x_itx_ids, NULL);
+
+ return 0;
+}
+device_initcall(mpc834x_itx_declare_of_platform_devices);
+
/* ************************************************************************
*
* Setup the architecture
--
1.5.2.2
^ permalink raw reply related
* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Anton Vorontsov @ 2007-12-04 19:49 UTC (permalink / raw)
To: Olof Johansson
Cc: Jeff Garzik, Arnd Bergmann, linux-ide, linuxppc-dev, Paul Mundt
In-Reply-To: <20071204184826.GA5758@lixom.net>
On Tue, Dec 04, 2007 at 12:48:26PM -0600, Olof Johansson wrote:
> Hi,
>
> On Tue, Dec 04, 2007 at 08:07:19PM +0300, Anton Vorontsov wrote:
> > This driver nicely wraps around pata_platform library functions,
[..]
> There's a typo in the dependencies for PATA_PLATFORM that you should change:
>
> depends on EMBEDDED || ARCH_RPC
>
> (note ARCH_>R<PC). With my font it's hard to tell a difference :)
>
> It should really be:
>
> depends on EMBEDDED || PPC
>
> Care to change that while you're at it?
Yup.
>
> > +static struct of_device_id pata_of_platform_match[] = {
> > + { .compatible = "ata-generic", },
> > +};
>
> Needs to be terminated by empty entry,
Fixed.
> and please add:
> MODULE_DEVICE_TABLE(of, pata_of_platform_match);
Ugh. I forgot about device table. Done.
Much thanks for spotting these.
- - - -
From: Anton Vorontsov <avorontsov@ru.mvista.com>
Subject: [PATCH v2.1] [libata] pata_of_platform: OF-Platform PATA device driver
This driver nicely wraps around pata_platform library functions,
and provides OF platform bus bindings to the PATA devices.
In addition fix ARCH_RPC typo in the PATA_PLATFORM Kconfig entry,
spotted by Olof Johansson.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
---
drivers/ata/Kconfig | 12 ++++-
drivers/ata/Makefile | 1 +
drivers/ata/pata_of_platform.c | 104 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 116 insertions(+), 1 deletions(-)
create mode 100644 drivers/ata/pata_of_platform.c
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index ba63619..e067112 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -607,13 +607,23 @@ config PATA_WINBOND_VLB
config PATA_PLATFORM
tristate "Generic platform device PATA support"
- depends on EMBEDDED || ARCH_RPC
+ depends on EMBEDDED || ARCH_PPC
help
This option enables support for generic directly connected ATA
devices commonly found on embedded systems.
If unsure, say N.
+config PATA_OF_PLATFORM
+ tristate "OpenFirmware platform device PATA support"
+ depends on PATA_PLATFORM && PPC_OF
+ help
+ This option enables support for generic directly connected ATA
+ devices commonly found on embedded systems with OpenFirmware
+ bindings.
+
+ If unsure, say N.
+
config PATA_ICSIDE
tristate "Acorn ICS PATA support"
depends on ARM && ARCH_ACORN
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index b13feb2..ebcee64 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -67,6 +67,7 @@ obj-$(CONFIG_PATA_IXP4XX_CF) += pata_ixp4xx_cf.o
obj-$(CONFIG_PATA_SCC) += pata_scc.o
obj-$(CONFIG_PATA_BF54X) += pata_bf54x.o
obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o
+obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o
obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o
# Should be last but two libata driver
obj-$(CONFIG_PATA_ACPI) += pata_acpi.o
diff --git a/drivers/ata/pata_of_platform.c b/drivers/ata/pata_of_platform.c
new file mode 100644
index 0000000..4daf118
--- /dev/null
+++ b/drivers/ata/pata_of_platform.c
@@ -0,0 +1,104 @@
+/*
+ * OF-platform PATA driver
+ *
+ * Copyright (c) 2007 MontaVista Software, Inc.
+ * 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 (Version 2) as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/pata_platform.h>
+
+static int __devinit pata_of_platform_probe(struct of_device *ofdev,
+ const struct of_device_id *match)
+{
+ int ret;
+ struct device_node *dn = ofdev->node;
+ struct resource io_res;
+ struct resource ctl_res;
+ struct resource irq_res;
+ unsigned int reg_shift = 0;
+ int pio_mode = 0;
+ int pio_mask;
+ const u32 *prop;
+
+ ret = of_address_to_resource(dn, 0, &io_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get IO address from "
+ "device tree\n");
+ return -EINVAL;
+ }
+
+ ret = of_address_to_resource(dn, 1, &ctl_res);
+ if (ret) {
+ dev_err(&ofdev->dev, "can't get CTL address from "
+ "device tree\n");
+ return -EINVAL;
+ }
+
+ ret = of_irq_to_resource(dn, 0, &irq_res);
+ if (ret == NO_IRQ)
+ irq_res.start = irq_res.end = -1;
+ else
+ irq_res.flags = 0;
+
+ prop = (u32 *)of_get_property(dn, "reg-shift", NULL);
+ if (prop)
+ reg_shift = *prop;
+
+ prop = (u32 *)of_get_property(dn, "pio-mode", NULL);
+ if (prop) {
+ pio_mode = *prop;
+ if (pio_mode > 6) {
+ dev_err(&ofdev->dev, "invalid pio-mode\n");
+ return -EINVAL;
+ }
+ } else {
+ dev_info(&ofdev->dev, "pio-mode unspecified, assuming PIO0\n");
+ }
+
+ pio_mask = 1 << pio_mode;
+ pio_mask |= (1 << pio_mode) - 1;
+
+ return __pata_platform_probe(&ofdev->dev, &io_res, &ctl_res, &irq_res,
+ reg_shift, pio_mask);
+}
+
+static int __devexit pata_of_platform_remove(struct of_device *ofdev)
+{
+ return __pata_platform_remove(&ofdev->dev);
+}
+
+static struct of_device_id pata_of_platform_match[] = {
+ { .compatible = "ata-generic", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, pata_of_platform_match);
+
+static struct of_platform_driver pata_of_platform_driver = {
+ .name = "pata_of_platform",
+ .match_table = pata_of_platform_match,
+ .probe = pata_of_platform_probe,
+ .remove = __devexit_p(pata_of_platform_remove),
+};
+
+static int __init pata_of_platform_init(void)
+{
+ return of_register_platform_driver(&pata_of_platform_driver);
+}
+module_init(pata_of_platform_init);
+
+static void __exit pata_of_platform_exit(void)
+{
+ of_unregister_platform_driver(&pata_of_platform_driver);
+}
+module_exit(pata_of_platform_exit);
+
+MODULE_DESCRIPTION("OF-platform PATA driver");
+MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
+MODULE_LICENSE("GPL");
--
1.5.2.2
^ permalink raw reply related
* Re: [PATCH 2.6.24] pasemi_mac: Fix reuse of free'd skb
From: Jeff Garzik @ 2007-12-04 19:54 UTC (permalink / raw)
To: Olof Johansson; +Cc: ranger, netdev, dwmw2, linuxppc-dev
In-Reply-To: <20071204033414.GA13616@lixom.net>
Olof Johansson wrote:
> Turns out we're freeing the skb when we detect CRC error, but we're
> not clearing out info->skb. We could either clear it and have the stack
> reallocate it, or just leave it and the rx ring refill code will reuse
> the one that was allocated.
>
> Reusing a freed skb obviously caused some nasty crashes of various kind,
> as reported by Brent Baude and David Woodhouse.
>
>
> Signed-off-by: Olof Johansson <olof@lixom.net>
>
> ---
>
> Jeff, I'd like to see this in 2.6.24, it's causing some real problems
> out there. It's not needed in the 2.6.25 queue since the other changes
> there have already covered these cases.
>
> My test network at home is quiet enough to not cause CRC errors, we
> mainly get those during interface bringup before speed is configured.
>
> diff --git a/drivers/net/pasemi_mac.c b/drivers/net/pasemi_mac.c
> index 09b4fde..6617e24 100644
> --- a/drivers/net/pasemi_mac.c
> +++ b/drivers/net/pasemi_mac.c
> @@ -586,7 +586,7 @@ static int pasemi_mac_clean_rx(struct pasemi_mac *mac, int limit)
> /* CRC error flagged */
> mac->netdev->stats.rx_errors++;
> mac->netdev->stats.rx_crc_errors++;
> - dev_kfree_skb_irq(skb);
> + /* No need to free skb, it'll be reused */
> goto next;
applied #upstream-fixes
^ permalink raw reply
* Re: [PATCH 5/7] powerpc: Replace ppc_md.power_off with pm_power_off
From: Benjamin Herrenschmidt @ 2007-12-04 19:55 UTC (permalink / raw)
To: Mark A. Greer; +Cc: linuxppc-dev
In-Reply-To: <20071204180148.GA1579@mag.az.mvista.com>
On Tue, 2007-12-04 at 11:01 -0700, Mark A. Greer wrote:
> On Tue, Dec 04, 2007 at 06:23:09PM +1100, Benjamin Herrenschmidt wrote:
> >
> > On Mon, 2007-12-03 at 22:48 -0700, Mark A. Greer wrote:
> > > From: Mark A. Greer <mgreer@mvista.com>
> > >
> > > The ppc_md.power_off hook performs the same function that the
> > > pm_power_off hook is supposed to. However, it is powerpc-specific
> > > and prevents kernel drivers (e.g., IPMI) from changing how a platform
> > > is powered off. So, get rid of ppc_md.power_off and replace it with
> > > pm_power_off.
> >
> > I'm less happy with that one... probably aesthetics :-)
> >
> > Can't we just have the generic code call pm_power_off and ppc_md and
> > which ever powers the machine off wins ?
>
> Yes, that would be easy to do. Seems like duplication though.
> If you are sure you're okay with the duplication, I'll do that.
Let's ask Paulus what he thinks.
Ben.
^ permalink raw reply
* Re: [PATCH v2 2/4] [libata] pata_of_platform: OF-Platform PATA device driver
From: Olof Johansson @ 2007-12-04 20:01 UTC (permalink / raw)
To: Anton Vorontsov
Cc: linux-ide, Paul Mundt, Arnd Bergmann, Jeff Garzik, linuxppc-dev
In-Reply-To: <20071204194921.GB1253@localhost.localdomain>
On Tue, Dec 04, 2007 at 10:49:21PM +0300, Anton Vorontsov wrote:
> tristate "Generic platform device PATA support"
> - depends on EMBEDDED || ARCH_RPC
> + depends on EMBEDDED || ARCH_PPC
It needs to be || PPC, not || ARCH_PPC.
-Olof
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox