* Re: [PATCH v2] Integrated Flash Controller support
From: Artem Bityutskiy @ 2011-11-30 8:51 UTC (permalink / raw)
To: Kumar Gala
Cc: Li Yang-R58472, linuxppc-dev@lists.ozlabs.org list,
b35362@freescale.com>, linux-kernel@vger.kernel.org Kernel,
linux-mtd, Scott Wood, Andrew Morton, David Woodhouse
In-Reply-To: <EFF451D9-552A-4820-90D3-BF3156D5B25F@kernel.crashing.org>
[-- Attachment #1: Type: text/plain, Size: 404 bytes --]
On Tue, 2011-11-29 at 19:47 -0600, Kumar Gala wrote:
> As Scott said, I was more asking about the 2nd patch in the sequence
> which did touch MTD. Since that one is dependent on this patch,
> wondering how we wanted to handle them.
I do not have time to review it, but it looks OK, so I'd suggest to
merge it vie the same tree as the rest of the patches.
--
Best Regards,
Artem Bityutskiy
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply
* [PATCH net-next v5 3/4] can: cc770: add platform bus driver for the CC770 and AN82527
From: Wolfgang Grandegger @ 2011-11-30 8:18 UTC (permalink / raw)
To: netdev
Cc: Stanislav Yelenskiy, Devicetree-discuss, linux-can, linuxppc-dev,
IreneV, socketcan-users
In-Reply-To: <1322641094-12175-1-git-send-email-wg@grandegger.com>
This driver works with both, static platform data and device tree
bindings. It has been tested on a TQM855L board with two AN82527
CAN controllers on the local bus.
CC: Devicetree-discuss@lists.ozlabs.org
CC: linuxppc-dev@ozlabs.org
CC: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>
---
.../devicetree/bindings/net/can/cc770.txt | 56 ++++
drivers/net/can/cc770/Kconfig | 7 +
drivers/net/can/cc770/Makefile | 1 +
drivers/net/can/cc770/cc770_platform.c | 273 ++++++++++++++++++++
4 files changed, 337 insertions(+), 0 deletions(-)
create mode 100644 Documentation/devicetree/bindings/net/can/cc770.txt
create mode 100644 drivers/net/can/cc770/cc770_platform.c
diff --git a/Documentation/devicetree/bindings/net/can/cc770.txt b/Documentation/devicetree/bindings/net/can/cc770.txt
new file mode 100644
index 0000000..01e282d
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/can/cc770.txt
@@ -0,0 +1,56 @@
+Memory mapped Bosch CC770 and Intel AN82527 CAN controller
+
+Note: The CC770 is a CAN controller from Bosch, which is 100%
+compatible with the old AN82527 from Intel, but with "bugs" being fixed.
+
+Required properties:
+
+- compatible : should be "bosch,cc770" for the CC770 and "intc,82527"
+ for the AN82527.
+
+- reg : should specify the chip select, address offset and size required
+ to map the registers of the controller. The size is usually 0x80.
+
+- interrupts : property with a value describing the interrupt source
+ (number and sensitivity) required for the controller.
+
+Optional properties:
+
+- bosch,external-clock-frequency : frequency of the external oscillator
+ clock in Hz. Note that the internal clock frequency used by the
+ controller is half of that value. If not specified, a default
+ value of 16000000 (16 MHz) is used.
+
+- bosch,clock-out-frequency : slock frequency in Hz on the CLKOUT pin.
+ If not specified or if the specified value is 0, the CLKOUT pin
+ will be disabled.
+
+- bosch,slew-rate : slew rate of the CLKOUT signal. If not specified,
+ a resonable value will be calculated.
+
+- bosch,disconnect-rx0-input : see data sheet.
+
+- bosch,disconnect-rx1-input : see data sheet.
+
+- bosch,disconnect-tx1-output : see data sheet.
+
+- bosch,polarity-dominant : see data sheet.
+
+- bosch,divide-memory-clock : see data sheet.
+
+- bosch,iso-low-speed-mux : see data sheet.
+
+For further information, please have a look to the CC770 or AN82527.
+
+Examples:
+
+can@3,100 {
+ compatible = "bosch,cc770";
+ reg = <3 0x100 0x80>;
+ interrupts = <2 0>;
+ interrupt-parent = <&mpic>;
+ bosch,external-clock-frequency = <16000000>;
+};
+
+
+
diff --git a/drivers/net/can/cc770/Kconfig b/drivers/net/can/cc770/Kconfig
index 28e4d48..22c07a8 100644
--- a/drivers/net/can/cc770/Kconfig
+++ b/drivers/net/can/cc770/Kconfig
@@ -11,4 +11,11 @@ config CAN_CC770_ISA
connected to the ISA bus using I/O port, memory mapped or
indirect access.
+config CAN_CC770_PLATFORM
+ tristate "Generic Platform Bus based CC770 driver"
+ ---help---
+ This driver adds support for the CC770 and AN82527 chips
+ connected to the "platform bus" (Linux abstraction for directly
+ to the processor attached devices).
+
endif
diff --git a/drivers/net/can/cc770/Makefile b/drivers/net/can/cc770/Makefile
index 872ecff..9fb8321 100644
--- a/drivers/net/can/cc770/Makefile
+++ b/drivers/net/can/cc770/Makefile
@@ -4,5 +4,6 @@
obj-$(CONFIG_CAN_CC770) += cc770.o
obj-$(CONFIG_CAN_CC770_ISA) += cc770_isa.o
+obj-$(CONFIG_CAN_CC770_PLATFORM) += cc770_platform.o
ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff --git a/drivers/net/can/cc770/cc770_platform.c b/drivers/net/can/cc770/cc770_platform.c
new file mode 100644
index 0000000..fb87b22
--- /dev/null
+++ b/drivers/net/can/cc770/cc770_platform.c
@@ -0,0 +1,273 @@
+/*
+ * Driver for CC770 and AN82527 CAN controllers on the platform bus
+ *
+ * Copyright (C) 2009, 2011 Wolfgang Grandegger <wg@grandegger.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License
+ * as published by the Free Software Foundation
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+/*
+ * If platform data are used you should have similar definitions
+ * in your board-specific code:
+ *
+ * static struct cc770_platform_data myboard_cc770_pdata = {
+ * .osc_freq = 16000000,
+ * .cir = 0x41,
+ * .cor = 0x20,
+ * .bcr = 0x40,
+ * };
+ *
+ * Please see include/linux/can/platform/cc770.h for description of
+ * above fields.
+ *
+ * If the device tree is used, you need a CAN node definition in your
+ * DTS file similar to:
+ *
+ * can@3,100 {
+ * compatible = "bosch,cc770";
+ * reg = <3 0x100 0x80>;
+ * interrupts = <2 0>;
+ * interrupt-parent = <&mpic>;
+ * bosch,external-clock-frequency = <16000000>;
+ * };
+ *
+ * See "Documentation/devicetree/bindings/net/can/cc770.txt" for further
+ * information.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/netdevice.h>
+#include <linux/delay.h>
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/platform/cc770.h>
+
+#include <linux/of_platform.h>
+
+#include "cc770.h"
+
+#define DRV_NAME "cc770_platform"
+
+MODULE_AUTHOR("Wolfgang Grandegger <wg@grandegger.com>");
+MODULE_DESCRIPTION("Socket-CAN driver for CC770 on the platform bus");
+MODULE_LICENSE("GPL v2");
+
+#define CC770_PLATFORM_CAN_CLOCK 16000000
+
+static u8 cc770_platform_read_reg(const struct cc770_priv *priv, int reg)
+{
+ return in_8(priv->reg_base + reg);
+}
+
+static void cc770_platform_write_reg(const struct cc770_priv *priv, int reg,
+ u8 val)
+{
+ out_8(priv->reg_base + reg, val);
+}
+
+static int __devinit cc770_get_of_node_data(struct platform_device *pdev,
+ struct cc770_priv *priv)
+{
+ struct device_node *np = pdev->dev.of_node;
+ const u32 *prop;
+ int prop_size;
+ u32 clkext;
+
+ prop = of_get_property(np, "bosch,external-clock-frequency",
+ &prop_size);
+ if (prop && (prop_size == sizeof(u32)))
+ clkext = *prop;
+ else
+ clkext = CC770_PLATFORM_CAN_CLOCK; /* default */
+ priv->can.clock.freq = clkext;
+
+ /* The system clock may not exceed 10 MHz */
+ if (priv->can.clock.freq > 10000000) {
+ priv->cpu_interface |= CPUIF_DSC;
+ priv->can.clock.freq /= 2;
+ }
+
+ /* The memory clock may not exceed 8 MHz */
+ if (priv->can.clock.freq > 8000000)
+ priv->cpu_interface |= CPUIF_DMC;
+
+ if (of_get_property(np, "bosch,divide-memory-clock", NULL))
+ priv->cpu_interface |= CPUIF_DMC;
+ if (of_get_property(np, "bosch,iso-low-speed-mux", NULL))
+ priv->cpu_interface |= CPUIF_MUX;
+
+ if (!of_get_property(np, "bosch,no-comperator-bypass", NULL))
+ priv->bus_config |= BUSCFG_CBY;
+ if (of_get_property(np, "bosch,disconnect-rx0-input", NULL))
+ priv->bus_config |= BUSCFG_DR0;
+ if (of_get_property(np, "bosch,disconnect-rx1-input", NULL))
+ priv->bus_config |= BUSCFG_DR1;
+ if (of_get_property(np, "bosch,disconnect-tx1-output", NULL))
+ priv->bus_config |= BUSCFG_DT1;
+ if (of_get_property(np, "bosch,polarity-dominant", NULL))
+ priv->bus_config |= BUSCFG_POL;
+
+ prop = of_get_property(np, "bosch,clock-out-frequency", &prop_size);
+ if (prop && (prop_size == sizeof(u32)) && *prop > 0) {
+ u32 cdv = clkext / *prop;
+ int slew;
+
+ if (cdv > 0 && cdv < 16) {
+ priv->cpu_interface |= CPUIF_CEN;
+ priv->clkout |= (cdv - 1) & CLKOUT_CD_MASK;
+
+ prop = of_get_property(np, "bosch,slew-rate",
+ &prop_size);
+ if (prop && (prop_size == sizeof(u32))) {
+ slew = *prop;
+ } else {
+ /* Determine default slew rate */
+ slew = (CLKOUT_SL_MASK >>
+ CLKOUT_SL_SHIFT) -
+ ((cdv * clkext - 1) / 8000000);
+ if (slew < 0)
+ slew = 0;
+ }
+ priv->clkout |= (slew << CLKOUT_SL_SHIFT) &
+ CLKOUT_SL_MASK;
+ } else {
+ dev_dbg(&pdev->dev, "invalid clock-out-frequency\n");
+ }
+ }
+
+ return 0;
+}
+
+static int __devinit cc770_get_platform_data(struct platform_device *pdev,
+ struct cc770_priv *priv)
+{
+
+ struct cc770_platform_data *pdata = pdev->dev.platform_data;
+
+ priv->can.clock.freq = pdata->osc_freq;
+ if (priv->cpu_interface | CPUIF_DSC)
+ priv->can.clock.freq /= 2;
+ priv->clkout = pdata->cor;
+ priv->bus_config = pdata->bcr;
+ priv->cpu_interface = pdata->cir;
+
+ return 0;
+}
+
+static int __devinit cc770_platform_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct cc770_priv *priv;
+ struct resource *mem;
+ resource_size_t mem_size;
+ void __iomem *base;
+ int err, irq;
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irq = platform_get_irq(pdev, 0);
+ if (!mem || irq <= 0)
+ return -ENODEV;
+
+ mem_size = resource_size(mem);
+ if (!request_mem_region(mem->start, mem_size, pdev->name))
+ return -EBUSY;
+
+ base = ioremap(mem->start, mem_size);
+ if (!base) {
+ err = -ENOMEM;
+ goto exit_release_mem;
+ }
+
+ dev = alloc_cc770dev(0);
+ if (!dev) {
+ err = -ENOMEM;
+ goto exit_unmap_mem;
+ }
+
+ dev->irq = irq;
+ priv = netdev_priv(dev);
+ priv->read_reg = cc770_platform_read_reg;
+ priv->write_reg = cc770_platform_write_reg;
+ priv->irq_flags = IRQF_SHARED;
+ priv->reg_base = base;
+
+ if (pdev->dev.of_node)
+ err = cc770_get_of_node_data(pdev, priv);
+ else if (pdev->dev.platform_data)
+ err = cc770_get_platform_data(pdev, priv);
+ else
+ err = -ENODEV;
+ if (err)
+ goto exit_free_cc770;
+
+ dev_dbg(&pdev->dev,
+ "reg_base=0x%p irq=%d clock=%d cpu_interface=0x%02x "
+ "bus_config=0x%02x clkout=0x%02x\n",
+ priv->reg_base, dev->irq, priv->can.clock.freq,
+ priv->cpu_interface, priv->bus_config, priv->clkout);
+
+ dev_set_drvdata(&pdev->dev, dev);
+ SET_NETDEV_DEV(dev, &pdev->dev);
+
+ err = register_cc770dev(dev);
+ if (err) {
+ dev_err(&pdev->dev,
+ "couldn't register CC700 device (err=%d)\n", err);
+ goto exit_free_cc770;
+ }
+
+ return 0;
+
+exit_free_cc770:
+ free_cc770dev(dev);
+exit_unmap_mem:
+ iounmap(base);
+exit_release_mem:
+ release_mem_region(mem->start, mem_size);
+
+ return err;
+}
+
+static int __devexit cc770_platform_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = dev_get_drvdata(&pdev->dev);
+ struct cc770_priv *priv = netdev_priv(dev);
+ struct resource *mem;
+
+ unregister_cc770dev(dev);
+ iounmap(priv->reg_base);
+ free_cc770dev(dev);
+
+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mem->start, resource_size(mem));
+
+ return 0;
+}
+
+static struct of_device_id __devinitdata cc770_platform_table[] = {
+ {.compatible = "bosch,cc770"}, /* CC770 from Bosch */
+ {.compatible = "intc,82527"}, /* AN82527 from Intel CP */
+ {},
+};
+
+static struct platform_driver cc770_platform_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = cc770_platform_table,
+ },
+ .probe = cc770_platform_probe,
+ .remove = __devexit_p(cc770_platform_remove),
+};
+
+module_platform_driver(cc770_platform_driver);
+
--
1.7.4.1
^ permalink raw reply related
* [PATCH net-next v5 4/4] powerpc: tqm8548/tqm8xx: add and update CAN device nodes
From: Wolfgang Grandegger @ 2011-11-30 8:18 UTC (permalink / raw)
To: netdev
Cc: Stanislav Yelenskiy, devicetree-discuss, linux-can, linuxppc-dev,
IreneV, socketcan-users
In-Reply-To: <1322641094-12175-1-git-send-email-wg@grandegger.com>
This patch enables or updates support for the CC770 and AN82527
CAN controller on the TQM8548 and TQM8xx boards.
CC: devicetree-discuss@lists.ozlabs.org
CC: linuxppc-dev@ozlabs.org
CC: Kumar Gala <galak@kernel.crashing.org>
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
---
arch/powerpc/boot/dts/tqm8548-bigflash.dts | 19 ++++++++++++++-----
arch/powerpc/boot/dts/tqm8548.dts | 19 ++++++++++++++-----
arch/powerpc/boot/dts/tqm8xx.dts | 25 +++++++++++++++++++++++++
3 files changed, 53 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/boot/dts/tqm8548-bigflash.dts b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
index 9452c3c..d918752 100644
--- a/arch/powerpc/boot/dts/tqm8548-bigflash.dts
+++ b/arch/powerpc/boot/dts/tqm8548-bigflash.dts
@@ -352,7 +352,7 @@
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR FLASH bank 1
1 0x0 0xf8000000 0x08000000 // NOR FLASH bank 0
- 2 0x0 0xa3000000 0x00008000 // CAN (2 x i82527)
+ 2 0x0 0xa3000000 0x00008000 // CAN (2 x CC770)
3 0x0 0xa3010000 0x00008000 // NAND FLASH
>;
@@ -393,18 +393,27 @@
};
/* Note: CAN support needs be enabled in U-Boot */
- can0@2,0 {
- compatible = "intel,82527"; // Bosch CC770
+ can@2,0 {
+ compatible = "bosch,cc770"; // Bosch CC770
reg = <2 0x0 0x100>;
interrupts = <4 1>;
interrupt-parent = <&mpic>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
+ bosch,clock-out-frequency = <16000000>;
};
- can1@2,100 {
- compatible = "intel,82527"; // Bosch CC770
+ can@2,100 {
+ compatible = "bosch,cc770"; // Bosch CC770
reg = <2 0x100 0x100>;
interrupts = <4 1>;
interrupt-parent = <&mpic>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
};
/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8548.dts b/arch/powerpc/boot/dts/tqm8548.dts
index 619776f..988d887 100644
--- a/arch/powerpc/boot/dts/tqm8548.dts
+++ b/arch/powerpc/boot/dts/tqm8548.dts
@@ -352,7 +352,7 @@
ranges = <
0 0x0 0xfc000000 0x04000000 // NOR FLASH bank 1
1 0x0 0xf8000000 0x08000000 // NOR FLASH bank 0
- 2 0x0 0xe3000000 0x00008000 // CAN (2 x i82527)
+ 2 0x0 0xe3000000 0x00008000 // CAN (2 x CC770)
3 0x0 0xe3010000 0x00008000 // NAND FLASH
>;
@@ -393,18 +393,27 @@
};
/* Note: CAN support needs be enabled in U-Boot */
- can0@2,0 {
- compatible = "intel,82527"; // Bosch CC770
+ can@2,0 {
+ compatible = "bosch,cc770"; // Bosch CC770
reg = <2 0x0 0x100>;
interrupts = <4 1>;
interrupt-parent = <&mpic>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
+ bosch,clock-out-frequency = <16000000>;
};
- can1@2,100 {
- compatible = "intel,82527"; // Bosch CC770
+ can@2,100 {
+ compatible = "bosch,cc770"; // Bosch CC770
reg = <2 0x100 0x100>;
interrupts = <4 1>;
interrupt-parent = <&mpic>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
};
/* Note: NAND support needs to be enabled in U-Boot */
diff --git a/arch/powerpc/boot/dts/tqm8xx.dts b/arch/powerpc/boot/dts/tqm8xx.dts
index f6da7ec..c3dba25 100644
--- a/arch/powerpc/boot/dts/tqm8xx.dts
+++ b/arch/powerpc/boot/dts/tqm8xx.dts
@@ -57,6 +57,7 @@
ranges = <
0x0 0x0 0x40000000 0x800000
+ 0x3 0x0 0xc0000000 0x200
>;
flash@0,0 {
@@ -67,6 +68,30 @@
bank-width = <4>;
device-width = <2>;
};
+
+ /* Note: CAN support needs be enabled in U-Boot */
+ can@3,0 {
+ compatible = "intc,82527";
+ reg = <3 0x0 0x80>;
+ interrupts = <8 1>;
+ interrupt-parent = <&PIC>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
+ bosch,clock-out-frequency = <16000000>;
+ };
+
+ can@3,100 {
+ compatible = "intc,82527";
+ reg = <3 0x100 0x80>;
+ interrupts = <8 1>;
+ interrupt-parent = <&PIC>;
+ bosch,external-clock-frequency = <16000000>;
+ bosch,disconnect-rx1-input;
+ bosch,disconnect-tx1-output;
+ bosch,iso-low-speed-mux;
+ };
};
soc@fff00000 {
--
1.7.4.1
^ permalink raw reply related
* [PATCH] powerpc: use rwsem.h from generic location
From: Richard Kuo @ 2011-11-29 18:28 UTC (permalink / raw)
To: benh, paulus, linuxppc-dev, linux-arch
As of commit dd472da38, rwsem.h was moved into asm-generic.
This patch removes the arch file and points the build at
its new location.
Signed-off-by: Richard Kuo <rkuo@codeaurora.org>
---
arch/powerpc/include/asm/Kbuild | 2 +
arch/powerpc/include/asm/rwsem.h | 132 --------------------------------------
2 files changed, 2 insertions(+), 132 deletions(-)
delete mode 100644 arch/powerpc/include/asm/rwsem.h
diff --git a/arch/powerpc/include/asm/Kbuild b/arch/powerpc/include/asm/Kbuild
index d51df17..7e313f1 100644
--- a/arch/powerpc/include/asm/Kbuild
+++ b/arch/powerpc/include/asm/Kbuild
@@ -34,3 +34,5 @@ header-y += termios.h
header-y += types.h
header-y += ucontext.h
header-y += unistd.h
+
+generic-y += rwsem.h
diff --git a/arch/powerpc/include/asm/rwsem.h b/arch/powerpc/include/asm/rwsem.h
deleted file mode 100644
index bb1e2cd..0000000
--- a/arch/powerpc/include/asm/rwsem.h
+++ /dev/null
@@ -1,132 +0,0 @@
-#ifndef _ASM_POWERPC_RWSEM_H
-#define _ASM_POWERPC_RWSEM_H
-
-#ifndef _LINUX_RWSEM_H
-#error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
-#endif
-
-#ifdef __KERNEL__
-
-/*
- * R/W semaphores for PPC using the stuff in lib/rwsem.c.
- * Adapted largely from include/asm-i386/rwsem.h
- * by Paul Mackerras <paulus@samba.org>.
- */
-
-/*
- * the semaphore definition
- */
-#ifdef CONFIG_PPC64
-# define RWSEM_ACTIVE_MASK 0xffffffffL
-#else
-# define RWSEM_ACTIVE_MASK 0x0000ffffL
-#endif
-
-#define RWSEM_UNLOCKED_VALUE 0x00000000L
-#define RWSEM_ACTIVE_BIAS 0x00000001L
-#define RWSEM_WAITING_BIAS (-RWSEM_ACTIVE_MASK-1)
-#define RWSEM_ACTIVE_READ_BIAS RWSEM_ACTIVE_BIAS
-#define RWSEM_ACTIVE_WRITE_BIAS (RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-
-/*
- * lock for reading
- */
-static inline void __down_read(struct rw_semaphore *sem)
-{
- if (unlikely(atomic_long_inc_return((atomic_long_t *)&sem->count) <= 0))
- rwsem_down_read_failed(sem);
-}
-
-static inline int __down_read_trylock(struct rw_semaphore *sem)
-{
- long tmp;
-
- while ((tmp = sem->count) >= 0) {
- if (tmp == cmpxchg(&sem->count, tmp,
- tmp + RWSEM_ACTIVE_READ_BIAS)) {
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * lock for writing
- */
-static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
-{
- long tmp;
-
- tmp = atomic_long_add_return(RWSEM_ACTIVE_WRITE_BIAS,
- (atomic_long_t *)&sem->count);
- if (unlikely(tmp != RWSEM_ACTIVE_WRITE_BIAS))
- rwsem_down_write_failed(sem);
-}
-
-static inline void __down_write(struct rw_semaphore *sem)
-{
- __down_write_nested(sem, 0);
-}
-
-static inline int __down_write_trylock(struct rw_semaphore *sem)
-{
- long tmp;
-
- tmp = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
- RWSEM_ACTIVE_WRITE_BIAS);
- return tmp == RWSEM_UNLOCKED_VALUE;
-}
-
-/*
- * unlock after reading
- */
-static inline void __up_read(struct rw_semaphore *sem)
-{
- long tmp;
-
- tmp = atomic_long_dec_return((atomic_long_t *)&sem->count);
- if (unlikely(tmp < -1 && (tmp & RWSEM_ACTIVE_MASK) == 0))
- rwsem_wake(sem);
-}
-
-/*
- * unlock after writing
- */
-static inline void __up_write(struct rw_semaphore *sem)
-{
- if (unlikely(atomic_long_sub_return(RWSEM_ACTIVE_WRITE_BIAS,
- (atomic_long_t *)&sem->count) < 0))
- rwsem_wake(sem);
-}
-
-/*
- * implement atomic add functionality
- */
-static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
-{
- atomic_long_add(delta, (atomic_long_t *)&sem->count);
-}
-
-/*
- * downgrade write lock to read lock
- */
-static inline void __downgrade_write(struct rw_semaphore *sem)
-{
- long tmp;
-
- tmp = atomic_long_add_return(-RWSEM_WAITING_BIAS,
- (atomic_long_t *)&sem->count);
- if (tmp < 0)
- rwsem_downgrade_wake(sem);
-}
-
-/*
- * implement exchange and add functionality
- */
-static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
-{
- return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
-}
-
-#endif /* __KERNEL__ */
-#endif /* _ASM_POWERPC_RWSEM_H */
--
1.7.3
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
^ permalink raw reply related
* Re: [PATCH 6/6] 44x/currituck: Add support for the new IBM currituck platform
From: David Gibson @ 2011-11-30 6:31 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: LinuxPPC-dev
In-Reply-To: <1322634022.21641.61.camel@pasglop>
On Wed, Nov 30, 2011 at 05:20:22PM +1100, Benjamin Herrenschmidt wrote:
> On Wed, 2011-11-30 at 16:24 +1100, Tony Breeds wrote:
>
> > + cpu@1 {
> > + device_type = "cpu";
> > + model = "PowerPC,476";
> > + reg = <1>;
> > + clock-frequency = <1600000000>; // 1.6 GHz
> > + timebase-frequency = <100000000>; // 100Mhz
> > + i-cache-line-size = <32>;
> > + d-cache-line-size = <32>;
> > + i-cache-size = <32768>;
> > + d-cache-size = <32768>;
> > + dcr-controller;
> > + dcr-access-method = "native";
> > + status = "disabled";
>
> disabled ? really ?
This is ePAPR. All non-boot CPUs are supposed to have status =
"disabled" to indicate that they won't be available until explicitly
enabled via the enable-method.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 6/6] 44x/currituck: Add support for the new IBM currituck platform
From: Benjamin Herrenschmidt @ 2011-11-30 6:20 UTC (permalink / raw)
To: Tony Breeds; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-7-git-send-email-tony@bakeyournoodle.com>
On Wed, 2011-11-30 at 16:24 +1100, Tony Breeds wrote:
> + cpu@1 {
> + device_type = "cpu";
> + model = "PowerPC,476";
> + reg = <1>;
> + clock-frequency = <1600000000>; // 1.6 GHz
> + timebase-frequency = <100000000>; // 100Mhz
> + i-cache-line-size = <32>;
> + d-cache-line-size = <32>;
> + i-cache-size = <32768>;
> + d-cache-size = <32768>;
> + dcr-controller;
> + dcr-access-method = "native";
> + status = "disabled";
disabled ? really ?
> + enable-method = "spin-table";
> + cpu-release-addr = <0x0 0x01f00000>;
> + };
> + };
> +
> + memory {
> + device_type = "memory";
> + reg = <0x0 0x0 0x0 0x0>; // filled in by zImage
> + };
> +
> + MPIC: interrupt-controller {
> + compatible = "chrp,open-pic";
> + interrupt-controller;
> + dcr-reg = <0xffc00000 0x00040000>;
> + #address-cells = <0>;
> + #size-cells = <0>;
> + #interrupt-cells = <2>;
> +
> + };
> +
> + plb {
> + compatible = "ibm,plb-4xx", "ibm,plb4"; /* Could be PLB6, doesn't matter */
Then make it plb6 and add it to the probe list. Might have to whack it's
configuration registers one day etc...
> + #address-cells = <2>;
> + #size-cells = <2>;
> + ranges;
> + clock-frequency = <200000000>; // 200Mhz
> +
> + POB0: opb {
> + compatible = "ibm,opb-4xx", "ibm,opb";
> + #address-cells = <1>;
> + #size-cells = <1>;
> + /* Wish there was a nicer way of specifying a full
> + * 32-bit range
> + *
> + * XXX: 1 TB address space, do we really care past
> + * 4 GB and should we expand cell width?
> + */
For OPB probably not :-)
.../...
> +#define DBG(fmt...)
> +
> +BSS_STACK(4096);
> +
> +#define MAX_RANKS 0x4
> +#define DDR3_MR0CF 0x80010011U
> +
> +static unsigned long long ibm_currituck_memsize;
> +static void ibm_currituck_detect_memsize(void)
> +{
> + u32 reg;
> + unsigned i;
> +
> + ibm_currituck_memsize = 0;
> + DBG("%s: initial memsize=0x%016llx\r\n", __func__,
> + ibm_currituck_memsize);
That doesn't seem like a very useful pair of statements or useful debug
message....
Any reason why you aren't returning what you detect rather than using a
global ?
> + for(i = 0; i < MAX_RANKS; i++){
> + reg = mfdcrx(DDR3_MR0CF + i);
> + printf("%s: reg=0x%08x\r\n", __func__, reg);
All that debug is pretty gross, keep it if you wish but make it a bit
neater and/or wrap it in DBG
> + if (reg & 0x01) {
if (!(reg & 1))
continue;
avoids too much indent
> + reg &= 0x0000f000;
> + reg >>= 12;
> + DBG("%s: reg=0x%08x, mem=0x%016llx\r\n",
> + __func__, reg, (0x800000ULL << reg));
Similar comment about making the debug output neater
> + ibm_currituck_memsize += (0x800000ULL << reg);
> + DBG("%s: memsize=0x%016llx\r\n", __func__, ibm_currituck_memsize);
> + }
> + }
> +
> + DBG("\r\n\r\n");
> +}
> +
> +static void ibm_currituck_fixups(void)
> +{
> + int i;
> + void *devp = finddevice("/");
> + u32 dma_ranges[7];
> +
> + dt_fixup_memory(0x0ULL, ibm_currituck_memsize);
Ok, I see why the global... I'd still prefer if the detect function just
returned the value and the caller whacks the global.
> + while ((devp = find_node_by_devtype(devp, "pci"))) {
> + if (getprop(devp, "dma-ranges", &dma_ranges[0], sizeof(dma_ranges)) < 0) {
Can't you replace &dma_ranges[0] with just dma_ranges ?
> + printf("%s: Failed to get dma-ranges\r\n", __func__);
> + continue;
> + }
> +
> + dma_ranges[5] = ibm_currituck_memsize >> 32;
> + dma_ranges[6] = ibm_currituck_memsize & 0xffffffffUL;
> +
> + setprop(devp, "dma-ranges", &dma_ranges[0], sizeof(dma_ranges));
Ditto.
> + DBG("%s: Setting DMA-ranges to <0x%x", __func__, dma_ranges[0]);
> + for (i = 1; i < 7; i++)
> + DBG(" 0x%x", dma_ranges[i]);
> + DBG(">\n\r");
Do you really need that added debug ? Once you've displayed the memory
size and tested that code once it doesn't look like you really care much
anymore
> + }
> +}
> +
> +#define SPRN_PIR 0x11E /* Processor Indentification Register */
That should go elsewhere along with the other SPR definitions.
> +void platform_init(void)
> +{
> + /* Cap the zImage to 512MB */
Any reason ? If yes, please document it a bit more.
> + unsigned long end_of_ram = 0x20000000;
> + unsigned long avail_ram = end_of_ram - (unsigned long)_end;
> + u32 pir_reg;
> + int node, size;
> + const u32 *timebase;
> +
> + simple_alloc_init(_end, avail_ram, 128, 64);
> + platform_ops.fixups = ibm_currituck_fixups;
> + platform_ops.exit = ibm44x_dbcr_reset;
> + pir_reg = mfspr(SPRN_PIR);
> +
> + /* Make sure FDT blob is sane */
> + if (fdt_check_header(_dtb_start) != 0)
> + fatal("Invalid device tree blob\n");
> +
> + node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
> + "cpu", sizeof("cpu"));
> + if (!node)
> + fatal("Cannot find cpu node\n");
The above will return -a- CPU node... you have several and you don't
know which one. You should probably iterate accross all of them.
> + /* FIXME: Check this works */
> + timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
> + if (timebase && (size == 4))
> + timebase_period_ns = 1000000000 / *timebase;
> +
> + fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
> + fdt_init(_dtb_start);
> +
> + serial_console_init();
> +
> + ibm_currituck_detect_memsize();
> +}
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index 559da19..aa38de6 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -951,6 +951,7 @@
> #define PVR_403GCX 0x00201400
> #define PVR_405GP 0x40110000
> #define PVR_476 0x11a52000
> +#define PVR_476CURRITUCK 0x7ff50000
My understanding is that the currituck was the platform, not the chip,
and that the chip was called something like 476FPE, am I wrong ?
> #define PVR_STB03XXX 0x40310000
> #define PVR_NP405H 0x41410000
> #define PVR_NP405L 0x41610000
> diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
> index edae5bb..02e0749 100644
> --- a/arch/powerpc/kernel/cputable.c
> +++ b/arch/powerpc/kernel/cputable.c
> @@ -1830,6 +1830,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
> .machine_check = machine_check_47x,
> .platform = "ppc470",
> },
> + { /* 476 core Currituck */
> + .pvr_mask = 0xffff0000,
> + .pvr_value = 0x7ff50000,
> + .cpu_name = "476",
> + .cpu_features = CPU_FTRS_47X | CPU_FTR_476_DD2,
> + .cpu_user_features = COMMON_USER_BOOKE |
> + PPC_FEATURE_HAS_FPU,
> + .mmu_features = MMU_FTR_TYPE_47x |
> + MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
> + .icache_bsize = 32,
> + .dcache_bsize = 128,
> + .machine_check = machine_check_47x,
> + .platform = "ppc470",
> + },
Same comment.
> { /* 476 iss */
> .pvr_mask = 0xffff0000,
> .pvr_value = 0x00050000,
> diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
> index b725dab..3aca1e2 100644
> --- a/arch/powerpc/kernel/head_44x.S
> +++ b/arch/powerpc/kernel/head_44x.S
> @@ -732,6 +732,8 @@ _GLOBAL(init_cpu_state)
> /* We use the PVR to differenciate 44x cores from 476 */
> mfspr r3,SPRN_PVR
> srwi r3,r3,16
> + cmplwi cr0,r3,PVR_476CURRITUCK@h
> + beq head_start_47x
So at some point, they gave us the magic foo to do with the PVR to
identify any 476... I'll try to dig that out of my email archives.
> cmplwi cr0,r3,PVR_476@h
> beq head_start_47x
> cmplwi cr0,r3,PVR_476_ISS@h
> diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
> index 762322c..245d121 100644
> --- a/arch/powerpc/platforms/44x/Kconfig
> +++ b/arch/powerpc/platforms/44x/Kconfig
> @@ -186,6 +186,16 @@ config ISS4xx
> help
> This option enables support for the IBM ISS simulation environment
>
> +config CURRITUCK
> + bool "IBM Currituck (476fpe) Support"
> + depends on PPC_47x
> + default n
> + select SWIOTLB
> + select PPC_FPU
> + select PPC4xx_PCI_EXPRESS
> + help
> + This option enables support for the IBM Currituck (476fpe) evaluation board
> +
>
> config ICON
> bool "Icon"
> depends on 44x
> diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
> index 553db60..5cd2725 100644
> --- a/arch/powerpc/platforms/44x/Makefile
> +++ b/arch/powerpc/platforms/44x/Makefile
> @@ -10,3 +10,4 @@ obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
> obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
> obj-$(CONFIG_ISS4xx) += iss4xx.o
> obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
> +obj-$(CONFIG_PPC_47x) += ppc47x.o
> diff --git a/arch/powerpc/platforms/44x/ppc47x.c b/arch/powerpc/platforms/44x/ppc47x.c
> new file mode 100644
> index 0000000..a4989b1
> --- /dev/null
> +++ b/arch/powerpc/platforms/44x/ppc47x.c
Call the file currituck.c
> @@ -0,0 +1,198 @@
> +/*
> + * Currituck board specific routines
> + *
> + * Copyright © 2011 Tony Breeds IBM Corporation
> + *
> + * Based on earlier code:
> + * Matt Porter <mporter@kernel.crashing.org>
> + * Copyright 2002-2005 MontaVista Software Inc.
> + *
> + * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
> + * Copyright (c) 2003-2005 Zultys Technologies
> + *
> + * Rewritten and ported to the merged powerpc tree:
> + * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
> + * Copyright © 2011 David Kliekamp IBM Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms of the GNU General Public License as published by the
> + * Free Software Foundation; either version 2 of the License, or (at your
> + * option) any later version.
> + */
> +
> +#include <linux/init.h>
> +#include <linux/memblock.h>
> +#include <linux/of_platform.h>
> +#include <linux/rtc.h>
> +
> +#include <asm/machdep.h>
> +#include <asm/prom.h>
> +#include <asm/udbg.h>
> +#include <asm/time.h>
> +#include <asm/uic.h>
> +#include <asm/ppc4xx.h>
> +#include <asm/mpic.h>
> +#include <asm/mmu.h>
> +
> +#include <linux/pci.h>
> +
> +static __initdata struct of_device_id ppc47x_of_bus[] = {
> + { .compatible = "ibm,plb4", },
> + { .compatible = "ibm,plb6", },
> + { .compatible = "ibm,opb", },
> + { .compatible = "ibm,ebc", },
> + {},
> +};
> +
> +static void __devinit quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
> +{
> + pci_write_config_dword(dev, 0xe0, 0x0114231f);
> + pci_write_config_dword(dev, 0xe4, 0x00006c40);
> +}
Pleae document better what you are doing here and also test
that you are indeed on the right platform so you don't end up
whacking bits on USB controllers on other platforms that happen
to be compiled in the same binary.
> +DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
> +
> +static int __init ppc47x_device_probe(void)
> +{
> + of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
> +
> + return 0;
> +}
> +machine_device_initcall(ppc47x, ppc47x_device_probe);
> +
> +/* We can have either UICs or MPICs */
> +static void __init ppc47x_init_irq(void)
> +{
> + struct device_node *np;
> +
> + /* Find top level interrupt controller */
> + for_each_node_with_property(np, "interrupt-controller") {
> + if (of_get_property(np, "interrupts", NULL) == NULL)
> + break;
> + }
> + if (np == NULL)
> + panic("Can't find top level interrupt controller");
> +
> + /* Check type and do appropriate initialization */
> + if (of_device_is_compatible(np, "chrp,open-pic")) {
> + /* The MPIC driver will get everything it needs from the
> + * device-tree, just pass 0 to all arguments
> + */
> + struct mpic *mpic =
> + mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, " MPIC ");
> + BUG_ON(mpic == NULL);
> + mpic_init(mpic);
> + ppc_md.get_irq = mpic_get_irq;
> + } else
> + panic("Unrecognized top level interrupt controller");
> +}
Ok, I'll have to fixup that vs. Kyle patches but the good thing is that
it will make things even simpler.
> +#ifdef CONFIG_SMP
> +static void __cpuinit smp_ppc47x_setup_cpu(int cpu)
> +{
> + mpic_setup_this_cpu();
> +}
> +
> +static int __cpuinit smp_ppc47x_kick_cpu(int cpu)
> +{
> + struct device_node *cpunode = of_get_cpu_node(cpu, NULL);
> + const u64 *spin_table_addr_prop;
> + u32 *spin_table;
> + extern void start_secondary_47x(void);
> +
> + BUG_ON(cpunode == NULL);
> +
> + /* Assume spin table. We could test for the enable-method in
> + * the device-tree but currently there's little point as it's
> + * our only supported method
> + */
> + spin_table_addr_prop =
> + of_get_property(cpunode, "cpu-release-addr", NULL);
> +
> + if (spin_table_addr_prop == NULL) {
> + pr_err("CPU%d: Can't start, missing cpu-release-addr !\n",
> + cpu);
> + return 1;
> + }
> +
> + /* Assume it's mapped as part of the linear mapping. This is a bit
> + * fishy but will work fine for now
> + *
> + * XXX: Is there any reason to assume differently?
> + */
> + spin_table = (u32 *)__va(*spin_table_addr_prop);
> + pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table);
> +
> + spin_table[3] = cpu;
> + smp_wmb();
> + spin_table[1] = __pa(start_secondary_47x);
> + mb();
> +
> + return 0;
> +}
Now pretty much everything in this platform file is generic I believe.
We could move it all to ppc44x_simple.c. The only things that are not
are the USB quirk and the interrupt fixup.
The USB quirk which should have a compatible test for the platform to
make sure we don't run it on something else. For such a simple quirk, I
think it's fine ot have it in ppc44x_simple.c or in drivers/pci/quirk.c
For the interrupt fixup, we can probably address it entirely in the
device-tree, though that means exposing a bunch of on-board bridges
which is only midly annoying.
Anyways, we can discuss that (or maybe an even better option)
tomorrow :-)
> +static struct smp_ops_t ppc47x_smp_ops = {
> + .probe = smp_mpic_probe,
> + .message_pass = smp_mpic_message_pass,
> + .setup_cpu = smp_ppc47x_setup_cpu,
> + .kick_cpu = smp_ppc47x_kick_cpu,
> + .give_timebase = smp_generic_give_timebase,
> + .take_timebase = smp_generic_take_timebase,
> +};
> +
> +static void __init ppc47x_smp_init(void)
> +{
> + if (mmu_has_feature(MMU_FTR_TYPE_47x))
> + smp_ops = &ppc47x_smp_ops;
> +}
> +
> +#else /* CONFIG_SMP */
> +static void __init ppc47x_smp_init(void) { }
> +#endif /* CONFIG_SMP */
> +
> +static void __init ppc47x_setup_arch(void)
> +{
> +
> + /* No need to check the DMA config as we /know/ our windows are all of
> + * RAM. Lets hope that doesn't change */
> +#ifdef CONFIG_SWIOTLB
> + if (memblock_end_of_DRAM() > 0xffffffff) {
> + ppc_swiotlb_enable = 1;
> + set_pci_dma_ops(&swiotlb_dma_ops);
> + ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
> + }
> +#endif
> + ppc47x_smp_init();
> +}
> +
> +/*
> + * Called very early, MMU is off, device-tree isn't unflattened
> + */
> +static int __init ppc47x_probe(void)
> +{
> + unsigned long root = of_get_flat_dt_root();
> +
> + if (!of_flat_dt_is_compatible(root, "ibm,476"))
> + return 0;
> + return 1;
> +}
> +
> +static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
> +{
> + if (dev->vendor == 0x1033 && (dev->device == 0x0035 ||
> + dev->device == 0x00e0)) {
> + dev->irq = irq_create_mapping(NULL, 47);
> + pr_info("%s: Mapping irq 47 %d\n", __func__, dev->irq);
> + }
> +}
> +
> +define_machine(ppc47x) {
> + .name = "PowerPC 47x",
> + .probe = ppc47x_probe,
> + .progress = udbg_progress,
> + .init_IRQ = ppc47x_init_irq,
> + .setup_arch = ppc47x_setup_arch,
> + .pci_irq_fixup = ppc47x_pci_irq_fixup,
> + .restart = ppc4xx_reset_system,
> + .calibrate_decr = generic_calibrate_decr,
> +};
> diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
> index d766068..49b711b 100644
> --- a/arch/powerpc/sysdev/ppc4xx_pci.c
> +++ b/arch/powerpc/sysdev/ppc4xx_pci.c
> @@ -1290,6 +1290,52 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
>
> #endif /* CONFIG_40x */
>
> +#ifdef CONFIG_CURRITUCK
Again, you are mixing the SoC with the board here. afaik, currituck is
the board, not the SoC.
> +static int __init ppc_currituck_pciex_core_init(struct device_node *np)
> +{
> + return 4;
> +}
> +
> +static void __init ppc_currituck_pciex_check_link(struct ppc4xx_pciex_port *port)
> +{
> + u32 timeout_ms = 20;
> + u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT);
> + void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000,
> + 0x1000);
> +
> + printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
> +
> + if (mbase == NULL) {
> + printk(KERN_WARNING "PCIE%d: failed to get cfg space\n",
> + port->index);
> + return;
> + }
> +
> + while (timeout_ms--) {
> + val = in_le32(mbase + PECFG_TLDLP);
> +
> + if ((val & mask) == mask)
> + break;
> + msleep(10);
> + }
> +
> + if (val & PECFG_TLDLP_PRESENT) {
> + printk(KERN_INFO "PCIE%d: link is up !\n", port->index);
> + port->link = 1;
> + } else
> + printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index);
> +
> + iounmap(mbase);
> + return;
> +}
> +
> +static struct ppc4xx_pciex_hwops ppc_currituck_pcie_hwops __initdata =
> +{
> + .core_init = ppc_currituck_pciex_core_init,
> + .check_link = ppc_currituck_pciex_check_link,
> +};
> +#endif /* CONFIG_CURRITUCK */
> +
> /* Check that the core has been initied and if not, do it */
> static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
> {
> @@ -1315,6 +1361,10 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
> if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
> ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
> #endif
> +#ifdef CONFIG_CURRITUCK
> + if (of_device_is_compatible(np, "ibm,plb-pciex-currituck"))
> + ppc4xx_pciex_hwops = &ppc_currituck_pcie_hwops;
> +#endif
> if (ppc4xx_pciex_hwops == NULL) {
> printk(KERN_WARNING "PCIE: unknown host type %s\n",
> np->full_name);
> @@ -1623,6 +1673,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
> dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
> sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
> | DCRO_PEGPL_OMRxMSKL_VAL);
> + else if (of_device_is_compatible(port->node, "ibm,plb-pciex-currituck"))
> + dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
> + sa | DCRO_PEGPL_CURRITUCK_OMR1MSKL_UOT
> + | DCRO_PEGPL_OMRxMSKL_VAL);
> else
> dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
> sa | DCRO_PEGPL_OMR1MSKL_UOT
> @@ -1747,7 +1801,8 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
> if (res->flags & IORESOURCE_PREFETCH)
> sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
>
> - if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
> + if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
> + of_device_is_compatible(port->node, "ibm,plb-pciex-currituck"))
> sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
>
> out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
> diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
> index 32ce763..81f60d9 100644
> --- a/arch/powerpc/sysdev/ppc4xx_pci.h
> +++ b/arch/powerpc/sysdev/ppc4xx_pci.h
> @@ -476,6 +476,13 @@
> #define DCRO_PEGPL_OMR1MSKL_UOT 0x00000002
> #define DCRO_PEGPL_OMR3MSKL_IO 0x00000002
>
> +/* Currituck - 476 FPE */
> +#define PCCFG_LCPA 0x270
> +#define PECFG_TLDLP 0x3F8
> +#define PECFG_TLDLP_LNKUP 0x00000008
> +#define PECFG_TLDLP_PRESENT 0x00000010
> +#define DCRO_PEGPL_CURRITUCK_OMR1MSKL_UOT 0x00000004
> +
> /* SDR Bit Mappings */
> #define PESDRx_RCSSET_HLDPLB 0x10000000
> #define PESDRx_RCSSET_RSTGU 0x01000000
Cheers,
Ben.
^ permalink raw reply
* [PATCH] powerpc/pci: Make pci_read_irq_line() static
From: Benjamin Herrenschmidt @ 2011-11-30 6:16 UTC (permalink / raw)
To: linuxppc-dev
It's only used inside the same file where it's defined. There's
also no point exporting it anymore.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/pci.h | 2 --
arch/powerpc/kernel/pci-common.c | 3 +--
2 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index 49c3de5..1c92013 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -184,8 +184,6 @@ extern void of_scan_pci_bridge(struct pci_dev *dev);
extern void of_scan_bus(struct device_node *node, struct pci_bus *bus);
extern void of_rescan_bus(struct device_node *node, struct pci_bus *bus);
-extern int pci_read_irq_line(struct pci_dev *dev);
-
struct file;
extern pgprot_t pci_phys_mem_access_prot(struct file *file,
unsigned long pfn,
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 9bffc02..fa4a573 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -214,7 +214,7 @@ char __devinit *pcibios_setup(char *str)
* If the interrupt is used, then gets the interrupt line from the
* openfirmware and sets it in the pci_dev and pci_config line.
*/
-int pci_read_irq_line(struct pci_dev *pci_dev)
+static int pci_read_irq_line(struct pci_dev *pci_dev)
{
struct of_irq oirq;
unsigned int virq;
@@ -283,7 +283,6 @@ int pci_read_irq_line(struct pci_dev *pci_dev)
return 0;
}
-EXPORT_SYMBOL(pci_read_irq_line);
/*
* Platform support for /proc/bus/pci/X/Y mmap()s,
--
1.7.7.2
^ permalink raw reply related
* Re: [PATCH 4/6] powerpc/boot: Add extended precision shifts to the boot wrapper.
From: Benjamin Herrenschmidt @ 2011-11-30 5:48 UTC (permalink / raw)
To: Tony Breeds; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-5-git-send-email-tony@bakeyournoodle.com>
On Wed, 2011-11-30 at 16:23 +1100, Tony Breeds wrote:
> Code copied from arch/powerpc/kernel/misc_32.S
>
> Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
> ---
> arch/powerpc/boot/div64.S | 52 +++++++++++++++++++++++++++++++++++++++++++++
> 1 files changed, 52 insertions(+), 0 deletions(-)
Should we just link with libgcc ? :-)
Cheers,
Ben.
> diff --git a/arch/powerpc/boot/div64.S b/arch/powerpc/boot/div64.S
> index d271ab5..bbcb8a4 100644
> --- a/arch/powerpc/boot/div64.S
> +++ b/arch/powerpc/boot/div64.S
> @@ -57,3 +57,55 @@ __div64_32:
> stw r8,4(r3)
> mr r3,r6 # return the remainder in r3
> blr
> +
> +/*
> + * Extended precision shifts.
> + *
> + * Updated to be valid for shift counts from 0 to 63 inclusive.
> + * -- Gabriel
> + *
> + * R3/R4 has 64 bit value
> + * R5 has shift count
> + * result in R3/R4
> + *
> + * ashrdi3: arithmetic right shift (sign propagation)
> + * lshrdi3: logical right shift
> + * ashldi3: left shift
> + */
> + .globl __ashrdi3
> +__ashrdi3:
> + subfic r6,r5,32
> + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
> + addi r7,r5,32 # could be xori, or addi with -32
> + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
> + rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
> + sraw r7,r3,r7 # t2 = MSW >> (count-32)
> + or r4,r4,r6 # LSW |= t1
> + slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
> + sraw r3,r3,r5 # MSW = MSW >> count
> + or r4,r4,r7 # LSW |= t2
> + blr
> +
> + .globl __ashldi3
> +__ashldi3:
> + subfic r6,r5,32
> + slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
> + addi r7,r5,32 # could be xori, or addi with -32
> + srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
> + slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
> + or r3,r3,r6 # MSW |= t1
> + slw r4,r4,r5 # LSW = LSW << count
> + or r3,r3,r7 # MSW |= t2
> + blr
> +
> + .globl __lshrdi3
> +__lshrdi3:
> + subfic r6,r5,32
> + srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
> + addi r7,r5,32 # could be xori, or addi with -32
> + slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
> + srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
> + or r4,r4,r6 # LSW |= t1
> + srw r3,r3,r5 # MSW = MSW >> count
> + or r4,r4,r7 # LSW |= t2
> + blr
^ permalink raw reply
* Re: [PATCH 1/6] 44x/pci: Continue pci setup even if there is no sdr-base in the device-tree
From: Benjamin Herrenschmidt @ 2011-11-30 5:46 UTC (permalink / raw)
To: Tony Breeds; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-2-git-send-email-tony@bakeyournoodle.com>
On Wed, 2011-11-30 at 16:23 +1100, Tony Breeds wrote:
> Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
> ---
> arch/powerpc/sysdev/ppc4xx_pci.c | 6 +++---
> 1 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
> index 16f5eba..d3fa380 100644
> --- a/arch/powerpc/sysdev/ppc4xx_pci.c
> +++ b/arch/powerpc/sysdev/ppc4xx_pci.c
> @@ -1974,11 +1974,11 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
> port->node = of_node_get(np);
> pval = of_get_property(np, "sdr-base", NULL);
> if (pval == NULL) {
> - printk(KERN_ERR "PCIE: missing sdr-base for %s\n",
> + printk(KERN_INFO "PCIE: missing sdr-base for %s\n",
> np->full_name);
If you don't expect an sdr-base as part of the normal operations of that
bridge, don't bring a message that makes me think something is wrong :-)
Just changing the severity isn't enough. you should just remove the
message and later on, print/warn/error out if you decide you actually
need an sdr-base (such as in the backend).
Cheers,
Ben.
> - return;
> + } else {
> + port->sdr_base = *pval;
> }
> - port->sdr_base = *pval;
>
> /* Check if device_type property is set to "pci" or "pci-endpoint".
> * Resulting from this setup this PCIe port will be configured
^ permalink raw reply
* Kernel support for the Freescale P2020-MSC8156 AdvancedMC Reference Design
From: Daniel Ng2 @ 2011-11-30 5:34 UTC (permalink / raw)
To: linuxppc-dev
Hi,
Does anyone know of any kernel support for the Freescale P2020-MSC8156 AMC
board?-
http://freescale.com.hk/webapp/sps/site/prod_summary.jsp?code=P2020-MSC8156AMCRD
I am looking for platform-specific files ie. the ones that go in
arch/powerpc/platforms/85xx and DTS files if possible...
Cheers,
Daniel
--
View this message in context: http://old.nabble.com/Kernel-support-for-the-Freescale-P2020-MSC8156-AdvancedMC-Reference-Design-tp32883132p32883132.html
Sent from the linuxppc-dev mailing list archive at Nabble.com.
^ permalink raw reply
* [PATCH 6/6] 44x/currituck: Add support for the new IBM currituck platform
From: Tony Breeds @ 2011-11-30 5:24 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
Based on original work by David 'Shaggy' Kliekamp.
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/boot/Makefile | 5 +-
arch/powerpc/boot/dts/currituck.dts | 240 ++++++++++++++++++++++++++
arch/powerpc/boot/treeboot-currituck.c | 129 ++++++++++++++
arch/powerpc/boot/wrapper | 3 +
arch/powerpc/configs/44x/currituck_defconfig | 110 ++++++++++++
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/kernel/cputable.c | 14 ++
arch/powerpc/kernel/head_44x.S | 2 +
arch/powerpc/platforms/44x/Kconfig | 10 +
arch/powerpc/platforms/44x/Makefile | 1 +
arch/powerpc/platforms/44x/ppc47x.c | 198 +++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.c | 57 ++++++-
arch/powerpc/sysdev/ppc4xx_pci.h | 7 +
13 files changed, 775 insertions(+), 2 deletions(-)
create mode 100644 arch/powerpc/boot/dts/currituck.dts
create mode 100644 arch/powerpc/boot/treeboot-currituck.c
create mode 100644 arch/powerpc/configs/44x/currituck_defconfig
create mode 100644 arch/powerpc/platforms/44x/ppc47x.c
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 72ee8c1..ff0057f 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -45,6 +45,7 @@ $(obj)/cuboot-katmai.o: BOOTCFLAGS += -mcpu=405
$(obj)/cuboot-acadia.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-walnut.o: BOOTCFLAGS += -mcpu=405
$(obj)/treeboot-iss4xx.o: BOOTCFLAGS += -mcpu=405
+$(obj)/treeboot-currituck.o: BOOTCFLAGS += -mcpu=405
$(obj)/virtex405-head.o: BOOTAFLAGS += -mcpu=405
@@ -79,7 +80,8 @@ src-plat := of.c cuboot-52xx.c cuboot-824x.c cuboot-83xx.c cuboot-85xx.c holly.c
cuboot-warp.c cuboot-85xx-cpm2.c cuboot-yosemite.c simpleboot.c \
virtex405-head.S virtex.c redboot-83xx.c cuboot-sam440ep.c \
cuboot-acadia.c cuboot-amigaone.c cuboot-kilauea.c \
- gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c
+ gamecube-head.S gamecube.c wii-head.S wii.c treeboot-iss4xx.c \
+ treeboot-currituck.c
src-boot := $(src-wlib) $(src-plat) empty.c
src-boot := $(addprefix $(obj)/, $(src-boot))
@@ -212,6 +214,7 @@ image-$(CONFIG_WARP) += cuImage.warp
image-$(CONFIG_YOSEMITE) += cuImage.yosemite
image-$(CONFIG_ISS4xx) += treeImage.iss4xx \
treeImage.iss4xx-mpic
+image-$(CONFIG_CURRITUCK) += treeImage.currituck
# Board ports in arch/powerpc/platform/8xx/Kconfig
image-$(CONFIG_MPC86XADS) += cuImage.mpc866ads
diff --git a/arch/powerpc/boot/dts/currituck.dts b/arch/powerpc/boot/dts/currituck.dts
new file mode 100644
index 0000000..7a021a8
--- /dev/null
+++ b/arch/powerpc/boot/dts/currituck.dts
@@ -0,0 +1,240 @@
+/*
+ * Device Tree Source for IBM Embedded PPC 476 Platform
+ *
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * 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.
+ */
+
+/dts-v1/;
+
+/memreserve/ 0x01f00000 0x00100000; // spin table
+
+/ {
+ #address-cells = <2>;
+ #size-cells = <2>;
+ model = "ibm,currituck";
+ compatible = "ibm,currituck", "ibm,476";
+ dcr-parent = <&{/cpus/cpu@0}>;
+
+ aliases {
+ serial0 = &UART0;
+ };
+
+ cpus {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ cpu@0 {
+ device_type = "cpu";
+ model = "PowerPC,476";
+ reg = <0>;
+ clock-frequency = <1600000000>; // 1.6 GHz
+ timebase-frequency = <100000000>; // 100Mhz
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
+ dcr-controller;
+ dcr-access-method = "native";
+ status = "ok";
+ };
+ cpu@1 {
+ device_type = "cpu";
+ model = "PowerPC,476";
+ reg = <1>;
+ clock-frequency = <1600000000>; // 1.6 GHz
+ timebase-frequency = <100000000>; // 100Mhz
+ i-cache-line-size = <32>;
+ d-cache-line-size = <32>;
+ i-cache-size = <32768>;
+ d-cache-size = <32768>;
+ dcr-controller;
+ dcr-access-method = "native";
+ status = "disabled";
+ enable-method = "spin-table";
+ cpu-release-addr = <0x0 0x01f00000>;
+ };
+ };
+
+ memory {
+ device_type = "memory";
+ reg = <0x0 0x0 0x0 0x0>; // filled in by zImage
+ };
+
+ MPIC: interrupt-controller {
+ compatible = "chrp,open-pic";
+ interrupt-controller;
+ dcr-reg = <0xffc00000 0x00040000>;
+ #address-cells = <0>;
+ #size-cells = <0>;
+ #interrupt-cells = <2>;
+
+ };
+
+ plb {
+ compatible = "ibm,plb-4xx", "ibm,plb4"; /* Could be PLB6, doesn't matter */
+ #address-cells = <2>;
+ #size-cells = <2>;
+ ranges;
+ clock-frequency = <200000000>; // 200Mhz
+
+ POB0: opb {
+ compatible = "ibm,opb-4xx", "ibm,opb";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ /* Wish there was a nicer way of specifying a full
+ * 32-bit range
+ *
+ * XXX: 1 TB address space, do we really care past
+ * 4 GB and should we expand cell width?
+ */
+ ranges = <0x00000000 0x00000200 0x00000000 0x80000000
+ 0x80000000 0x00000200 0x80000000 0x80000000>;
+ clock-frequency = <100000000>;
+
+ UART0: serial@10000000 {
+ device_type = "serial";
+ compatible = "ns16750", "ns16550";
+ reg = <0x10000000 0x00000008>;
+ virtual-reg = <0xe1000000>;
+ clock-frequency = <1851851>; // PCIe refclk/MCGC0_CTL[UART]
+ current-speed = <115200>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <34 2>;
+ };
+
+ IIC0: i2c@00000000 {
+ compatible = "ibm,iic-currituck", "ibm,iic";
+ reg = <0x0 0x00000014>;
+ interrupt-parent = <&MPIC>;
+ interrupts = <79 2>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ rtc@68 {
+ compatible = "stm,m41t80", "m41st85";
+ reg = <0x68>;
+ };
+ };
+ };
+
+ PCIE0: pciex@10100000000 { // 4xGBIF1
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-currituck", "ibm,plb-pciex";
+ primary;
+ port = <0x0>; /* port number */
+ reg = <0x00000101 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000100 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0x80 0x20>;
+
+// pci_space < pci_addr > < cpu_addr > < size >
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000110 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x00000140 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 46 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 47 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 48 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 49 0x2 /* int D */>;
+ };
+
+ PCIE1: pciex@30100000000 { // 4xGBIF0
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-currituck", "ibm,plb-pciex";
+ primary;
+ port = <0x1>; /* port number */
+ reg = <0x00000301 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000300 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0x60 0x20>;
+
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000310 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x00000340 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 38 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 39 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 40 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 41 0x2 /* int D */>;
+ };
+
+ PCIE2: pciex@38100000000 { // 2xGBIF0
+ device_type = "pci";
+ #interrupt-cells = <1>;
+ #size-cells = <2>;
+ #address-cells = <3>;
+ compatible = "ibm,plb-pciex-currituck", "ibm,plb-pciex";
+ primary;
+ port = <0x2>; /* port number */
+ reg = <0x00000381 0x00000000 0x0 0x10000000 /* Config space access */
+ 0x00000380 0x00000000 0x0 0x00001000>; /* UTL Registers space access */
+ dcr-reg = <0xA0 0x20>;
+
+ ranges = <0x02000000 0x00000000 0x80000000 0x00000390 0x80000000 0x0 0x80000000
+ 0x01000000 0x0 0x0 0x000003C0 0x0 0x0 0x00010000>;
+
+ /* Inbound starting at 0 to memsize filled in by zImage */
+ dma-ranges = <0x42000000 0x0 0x0 0x0 0x0 0x0 0x0>;
+
+ /* This drives busses 0 to 0xf */
+ bus-range = <0x0 0xf>;
+
+ /* Legacy interrupts (note the weird polarity, the bridge seems
+ * to invert PCIe legacy interrupts).
+ * We are de-swizzling here because the numbers are actually for
+ * port of the root complex virtual P2P bridge. But I want
+ * to avoid putting a node for it in the tree, so the numbers
+ * below are basically de-swizzled numbers.
+ * The real slot is on idsel 0, so the swizzling is 1:1
+ */
+ interrupt-map-mask = <0x0 0x0 0x0 0x7>;
+ interrupt-map = <
+ 0x0 0x0 0x0 0x1 &MPIC 54 0x2 /* int A */
+ 0x0 0x0 0x0 0x2 &MPIC 55 0x2 /* int B */
+ 0x0 0x0 0x0 0x3 &MPIC 56 0x2 /* int C */
+ 0x0 0x0 0x0 0x4 &MPIC 57 0x2 /* int D */>;
+ };
+
+ };
+
+ chosen {
+ linux,stdout-path = &UART0;
+ };
+};
diff --git a/arch/powerpc/boot/treeboot-currituck.c b/arch/powerpc/boot/treeboot-currituck.c
new file mode 100644
index 0000000..aaf9dbf
--- /dev/null
+++ b/arch/powerpc/boot/treeboot-currituck.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * Based on earlier code:
+ * Copyright (C) Paul Mackerras 1997.
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003, 2004 Zultys Technologies
+ *
+ * Copyright 2007 David Gibson, IBM Corporation.
+ * Copyright 2010 Ben. Herrenschmidt, IBM Corporation.
+ * Copyright © 2011 David Kleikamp IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#include <stdarg.h>
+#include <stddef.h>
+#include "types.h"
+#include "elf.h"
+#include "string.h"
+#include "stdio.h"
+#include "page.h"
+#include "ops.h"
+#include "reg.h"
+#include "io.h"
+#include "dcr.h"
+#include "4xx.h"
+#include "44x.h"
+#include "libfdt.h"
+
+#define DBG(fmt...)
+
+BSS_STACK(4096);
+
+#define MAX_RANKS 0x4
+#define DDR3_MR0CF 0x80010011U
+
+static unsigned long long ibm_currituck_memsize;
+static void ibm_currituck_detect_memsize(void)
+{
+ u32 reg;
+ unsigned i;
+
+ ibm_currituck_memsize = 0;
+ DBG("%s: initial memsize=0x%016llx\r\n", __func__,
+ ibm_currituck_memsize);
+
+ for(i = 0; i < MAX_RANKS; i++){
+ reg = mfdcrx(DDR3_MR0CF + i);
+ printf("%s: reg=0x%08x\r\n", __func__, reg);
+ if (reg & 0x01) {
+ reg &= 0x0000f000;
+ reg >>= 12;
+ DBG("%s: reg=0x%08x, mem=0x%016llx\r\n",
+ __func__, reg, (0x800000ULL << reg));
+ ibm_currituck_memsize += (0x800000ULL << reg);
+ DBG("%s: memsize=0x%016llx\r\n", __func__, ibm_currituck_memsize);
+ }
+ }
+
+ DBG("\r\n\r\n");
+}
+
+static void ibm_currituck_fixups(void)
+{
+ int i;
+ void *devp = finddevice("/");
+ u32 dma_ranges[7];
+
+ dt_fixup_memory(0x0ULL, ibm_currituck_memsize);
+
+ while ((devp = find_node_by_devtype(devp, "pci"))) {
+ if (getprop(devp, "dma-ranges", &dma_ranges[0], sizeof(dma_ranges)) < 0) {
+ printf("%s: Failed to get dma-ranges\r\n", __func__);
+ continue;
+ }
+
+ dma_ranges[5] = ibm_currituck_memsize >> 32;
+ dma_ranges[6] = ibm_currituck_memsize & 0xffffffffUL;
+
+ setprop(devp, "dma-ranges", &dma_ranges[0], sizeof(dma_ranges));
+ DBG("%s: Setting DMA-ranges to <0x%x", __func__, dma_ranges[0]);
+ for (i = 1; i < 7; i++)
+ DBG(" 0x%x", dma_ranges[i]);
+ DBG(">\n\r");
+ }
+}
+
+#define SPRN_PIR 0x11E /* Processor Indentification Register */
+void platform_init(void)
+{
+ /* Cap the zImage to 512MB */
+ unsigned long end_of_ram = 0x20000000;
+ unsigned long avail_ram = end_of_ram - (unsigned long)_end;
+ u32 pir_reg;
+ int node, size;
+ const u32 *timebase;
+
+ simple_alloc_init(_end, avail_ram, 128, 64);
+ platform_ops.fixups = ibm_currituck_fixups;
+ platform_ops.exit = ibm44x_dbcr_reset;
+ pir_reg = mfspr(SPRN_PIR);
+
+ /* Make sure FDT blob is sane */
+ if (fdt_check_header(_dtb_start) != 0)
+ fatal("Invalid device tree blob\n");
+
+ node = fdt_node_offset_by_prop_value(_dtb_start, -1, "device_type",
+ "cpu", sizeof("cpu"));
+ if (!node)
+ fatal("Cannot find cpu node\n");
+ /* FIXME: Check this works */
+ timebase = fdt_getprop(_dtb_start, node, "timebase-frequency", &size);
+ if (timebase && (size == 4))
+ timebase_period_ns = 1000000000 / *timebase;
+
+ fdt_set_boot_cpuid_phys(_dtb_start, pir_reg);
+ fdt_init(_dtb_start);
+
+ serial_console_init();
+
+ ibm_currituck_detect_memsize();
+}
diff --git a/arch/powerpc/boot/wrapper b/arch/powerpc/boot/wrapper
index c74531a..87f4950 100755
--- a/arch/powerpc/boot/wrapper
+++ b/arch/powerpc/boot/wrapper
@@ -244,6 +244,9 @@ gamecube|wii)
link_address='0x600000'
platformo="$object/$platform-head.o $object/$platform.o"
;;
+treeboot-currituck)
+ link_address='0x1000000'
+ ;;
treeboot-iss4xx-mpic)
platformo="$object/treeboot-iss4xx.o"
;;
diff --git a/arch/powerpc/configs/44x/currituck_defconfig b/arch/powerpc/configs/44x/currituck_defconfig
new file mode 100644
index 0000000..4192322
--- /dev/null
+++ b/arch/powerpc/configs/44x/currituck_defconfig
@@ -0,0 +1,110 @@
+CONFIG_44x=y
+CONFIG_SMP=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EXPERT=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_PPC_47x=y
+# CONFIG_EBONY is not set
+CONFIG_CURRITUCK=y
+CONFIG_HIGHMEM=y
+CONFIG_HZ_100=y
+CONFIG_MATH_EMULATION=y
+CONFIG_IRQ_ALL_CPUS=y
+CONFIG_CMDLINE_BOOL=y
+CONFIG_CMDLINE=""
+# CONFIG_SUSPEND is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
+# CONFIG_INET_XFRM_MODE_TUNNEL is not set
+# CONFIG_INET_XFRM_MODE_BEET is not set
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
+CONFIG_DEVTMPFS_MOUNT=y
+CONFIG_CONNECTOR=y
+CONFIG_MTD=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_JEDECPROBE=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_PROC_DEVICETREE=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=35000
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+CONFIG_SATA_SIL24=y
+# CONFIG_ATA_SFF is not set
+CONFIG_NETDEVICES=y
+CONFIG_E1000E=y
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_OF_PLATFORM=y
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+CONFIG_I2C_IBM_IIC=y
+# CONFIG_HWMON is not set
+CONFIG_THERMAL=y
+CONFIG_USB=y
+CONFIG_USB_DEBUG=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_M41T80=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+CONFIG_PROC_KCORE=y
+CONFIG_TMPFS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_NFS_V3_ACL=y
+CONFIG_NFS_V4=y
+CONFIG_NLS_DEFAULT="n"
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_INFO=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_XMON=y
+CONFIG_XMON_DEFAULT=y
+CONFIG_PPC_EARLY_DEBUG=y
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSLOW=0x10000000
+CONFIG_PPC_EARLY_DEBUG_44x_PHYSHIGH=0x200
+CONFIG_CRYPTO=y
+CONFIG_CRYPTO_CBC=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_PCBC=y
+CONFIG_CRYPTO_MD5=y
+CONFIG_CRYPTO_DES=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 559da19..aa38de6 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -951,6 +951,7 @@
#define PVR_403GCX 0x00201400
#define PVR_405GP 0x40110000
#define PVR_476 0x11a52000
+#define PVR_476CURRITUCK 0x7ff50000
#define PVR_STB03XXX 0x40310000
#define PVR_NP405H 0x41410000
#define PVR_NP405L 0x41610000
diff --git a/arch/powerpc/kernel/cputable.c b/arch/powerpc/kernel/cputable.c
index edae5bb..02e0749 100644
--- a/arch/powerpc/kernel/cputable.c
+++ b/arch/powerpc/kernel/cputable.c
@@ -1830,6 +1830,20 @@ static struct cpu_spec __initdata cpu_specs[] = {
.machine_check = machine_check_47x,
.platform = "ppc470",
},
+ { /* 476 core Currituck */
+ .pvr_mask = 0xffff0000,
+ .pvr_value = 0x7ff50000,
+ .cpu_name = "476",
+ .cpu_features = CPU_FTRS_47X | CPU_FTR_476_DD2,
+ .cpu_user_features = COMMON_USER_BOOKE |
+ PPC_FEATURE_HAS_FPU,
+ .mmu_features = MMU_FTR_TYPE_47x |
+ MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
+ .icache_bsize = 32,
+ .dcache_bsize = 128,
+ .machine_check = machine_check_47x,
+ .platform = "ppc470",
+ },
{ /* 476 iss */
.pvr_mask = 0xffff0000,
.pvr_value = 0x00050000,
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index b725dab..3aca1e2 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -732,6 +732,8 @@ _GLOBAL(init_cpu_state)
/* We use the PVR to differenciate 44x cores from 476 */
mfspr r3,SPRN_PVR
srwi r3,r3,16
+ cmplwi cr0,r3,PVR_476CURRITUCK@h
+ beq head_start_47x
cmplwi cr0,r3,PVR_476@h
beq head_start_47x
cmplwi cr0,r3,PVR_476_ISS@h
diff --git a/arch/powerpc/platforms/44x/Kconfig b/arch/powerpc/platforms/44x/Kconfig
index 762322c..245d121 100644
--- a/arch/powerpc/platforms/44x/Kconfig
+++ b/arch/powerpc/platforms/44x/Kconfig
@@ -186,6 +186,16 @@ config ISS4xx
help
This option enables support for the IBM ISS simulation environment
+config CURRITUCK
+ bool "IBM Currituck (476fpe) Support"
+ depends on PPC_47x
+ default n
+ select SWIOTLB
+ select PPC_FPU
+ select PPC4xx_PCI_EXPRESS
+ help
+ This option enables support for the IBM Currituck (476fpe) evaluation board
+
config ICON
bool "Icon"
depends on 44x
diff --git a/arch/powerpc/platforms/44x/Makefile b/arch/powerpc/platforms/44x/Makefile
index 553db60..5cd2725 100644
--- a/arch/powerpc/platforms/44x/Makefile
+++ b/arch/powerpc/platforms/44x/Makefile
@@ -10,3 +10,4 @@ obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
obj-$(CONFIG_ISS4xx) += iss4xx.o
obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
+obj-$(CONFIG_PPC_47x) += ppc47x.o
diff --git a/arch/powerpc/platforms/44x/ppc47x.c b/arch/powerpc/platforms/44x/ppc47x.c
new file mode 100644
index 0000000..a4989b1
--- /dev/null
+++ b/arch/powerpc/platforms/44x/ppc47x.c
@@ -0,0 +1,198 @@
+/*
+ * Currituck board specific routines
+ *
+ * Copyright © 2011 Tony Breeds IBM Corporation
+ *
+ * Based on earlier code:
+ * Matt Porter <mporter@kernel.crashing.org>
+ * Copyright 2002-2005 MontaVista Software Inc.
+ *
+ * Eugene Surovegin <eugene.surovegin@zultys.com> or <ebs@ebshome.net>
+ * Copyright (c) 2003-2005 Zultys Technologies
+ *
+ * Rewritten and ported to the merged powerpc tree:
+ * Copyright 2007 David Gibson <dwg@au1.ibm.com>, IBM Corporation.
+ * Copyright © 2011 David Kliekamp IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/memblock.h>
+#include <linux/of_platform.h>
+#include <linux/rtc.h>
+
+#include <asm/machdep.h>
+#include <asm/prom.h>
+#include <asm/udbg.h>
+#include <asm/time.h>
+#include <asm/uic.h>
+#include <asm/ppc4xx.h>
+#include <asm/mpic.h>
+#include <asm/mmu.h>
+
+#include <linux/pci.h>
+
+static __initdata struct of_device_id ppc47x_of_bus[] = {
+ { .compatible = "ibm,plb4", },
+ { .compatible = "ibm,plb6", },
+ { .compatible = "ibm,opb", },
+ { .compatible = "ibm,ebc", },
+ {},
+};
+
+static void __devinit quirk_ppc_currituck_usb_fixup(struct pci_dev *dev)
+{
+ pci_write_config_dword(dev, 0xe0, 0x0114231f);
+ pci_write_config_dword(dev, 0xe4, 0x00006c40);
+}
+DECLARE_PCI_FIXUP_HEADER(0x1033, 0x0035, quirk_ppc_currituck_usb_fixup);
+
+static int __init ppc47x_device_probe(void)
+{
+ of_platform_bus_probe(NULL, ppc47x_of_bus, NULL);
+
+ return 0;
+}
+machine_device_initcall(ppc47x, ppc47x_device_probe);
+
+/* We can have either UICs or MPICs */
+static void __init ppc47x_init_irq(void)
+{
+ struct device_node *np;
+
+ /* Find top level interrupt controller */
+ for_each_node_with_property(np, "interrupt-controller") {
+ if (of_get_property(np, "interrupts", NULL) == NULL)
+ break;
+ }
+ if (np == NULL)
+ panic("Can't find top level interrupt controller");
+
+ /* Check type and do appropriate initialization */
+ if (of_device_is_compatible(np, "chrp,open-pic")) {
+ /* The MPIC driver will get everything it needs from the
+ * device-tree, just pass 0 to all arguments
+ */
+ struct mpic *mpic =
+ mpic_alloc(np, 0, MPIC_PRIMARY, 0, 0, " MPIC ");
+ BUG_ON(mpic == NULL);
+ mpic_init(mpic);
+ ppc_md.get_irq = mpic_get_irq;
+ } else
+ panic("Unrecognized top level interrupt controller");
+}
+
+#ifdef CONFIG_SMP
+static void __cpuinit smp_ppc47x_setup_cpu(int cpu)
+{
+ mpic_setup_this_cpu();
+}
+
+static int __cpuinit smp_ppc47x_kick_cpu(int cpu)
+{
+ struct device_node *cpunode = of_get_cpu_node(cpu, NULL);
+ const u64 *spin_table_addr_prop;
+ u32 *spin_table;
+ extern void start_secondary_47x(void);
+
+ BUG_ON(cpunode == NULL);
+
+ /* Assume spin table. We could test for the enable-method in
+ * the device-tree but currently there's little point as it's
+ * our only supported method
+ */
+ spin_table_addr_prop =
+ of_get_property(cpunode, "cpu-release-addr", NULL);
+
+ if (spin_table_addr_prop == NULL) {
+ pr_err("CPU%d: Can't start, missing cpu-release-addr !\n",
+ cpu);
+ return 1;
+ }
+
+ /* Assume it's mapped as part of the linear mapping. This is a bit
+ * fishy but will work fine for now
+ *
+ * XXX: Is there any reason to assume differently?
+ */
+ spin_table = (u32 *)__va(*spin_table_addr_prop);
+ pr_debug("CPU%d: Spin table mapped at %p\n", cpu, spin_table);
+
+ spin_table[3] = cpu;
+ smp_wmb();
+ spin_table[1] = __pa(start_secondary_47x);
+ mb();
+
+ return 0;
+}
+
+static struct smp_ops_t ppc47x_smp_ops = {
+ .probe = smp_mpic_probe,
+ .message_pass = smp_mpic_message_pass,
+ .setup_cpu = smp_ppc47x_setup_cpu,
+ .kick_cpu = smp_ppc47x_kick_cpu,
+ .give_timebase = smp_generic_give_timebase,
+ .take_timebase = smp_generic_take_timebase,
+};
+
+static void __init ppc47x_smp_init(void)
+{
+ if (mmu_has_feature(MMU_FTR_TYPE_47x))
+ smp_ops = &ppc47x_smp_ops;
+}
+
+#else /* CONFIG_SMP */
+static void __init ppc47x_smp_init(void) { }
+#endif /* CONFIG_SMP */
+
+static void __init ppc47x_setup_arch(void)
+{
+
+ /* No need to check the DMA config as we /know/ our windows are all of
+ * RAM. Lets hope that doesn't change */
+#ifdef CONFIG_SWIOTLB
+ if (memblock_end_of_DRAM() > 0xffffffff) {
+ ppc_swiotlb_enable = 1;
+ set_pci_dma_ops(&swiotlb_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
+ }
+#endif
+ ppc47x_smp_init();
+}
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init ppc47x_probe(void)
+{
+ unsigned long root = of_get_flat_dt_root();
+
+ if (!of_flat_dt_is_compatible(root, "ibm,476"))
+ return 0;
+
+ return 1;
+}
+
+static void ppc47x_pci_irq_fixup(struct pci_dev *dev)
+{
+ if (dev->vendor == 0x1033 && (dev->device == 0x0035 ||
+ dev->device == 0x00e0)) {
+ dev->irq = irq_create_mapping(NULL, 47);
+ pr_info("%s: Mapping irq 47 %d\n", __func__, dev->irq);
+ }
+}
+
+define_machine(ppc47x) {
+ .name = "PowerPC 47x",
+ .probe = ppc47x_probe,
+ .progress = udbg_progress,
+ .init_IRQ = ppc47x_init_irq,
+ .setup_arch = ppc47x_setup_arch,
+ .pci_irq_fixup = ppc47x_pci_irq_fixup,
+ .restart = ppc4xx_reset_system,
+ .calibrate_decr = generic_calibrate_decr,
+};
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index d766068..49b711b 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1290,6 +1290,52 @@ static struct ppc4xx_pciex_hwops ppc405ex_pcie_hwops __initdata =
#endif /* CONFIG_40x */
+#ifdef CONFIG_CURRITUCK
+static int __init ppc_currituck_pciex_core_init(struct device_node *np)
+{
+ return 4;
+}
+
+static void __init ppc_currituck_pciex_check_link(struct ppc4xx_pciex_port *port)
+{
+ u32 timeout_ms = 20;
+ u32 val = 0, mask = (PECFG_TLDLP_LNKUP|PECFG_TLDLP_PRESENT);
+ void __iomem *mbase = ioremap(port->cfg_space.start + 0x10000000,
+ 0x1000);
+
+ printk(KERN_INFO "PCIE%d: Checking link...\n", port->index);
+
+ if (mbase == NULL) {
+ printk(KERN_WARNING "PCIE%d: failed to get cfg space\n",
+ port->index);
+ return;
+ }
+
+ while (timeout_ms--) {
+ val = in_le32(mbase + PECFG_TLDLP);
+
+ if ((val & mask) == mask)
+ break;
+ msleep(10);
+ }
+
+ if (val & PECFG_TLDLP_PRESENT) {
+ printk(KERN_INFO "PCIE%d: link is up !\n", port->index);
+ port->link = 1;
+ } else
+ printk(KERN_WARNING "PCIE%d: Link up failed\n", port->index);
+
+ iounmap(mbase);
+ return;
+}
+
+static struct ppc4xx_pciex_hwops ppc_currituck_pcie_hwops __initdata =
+{
+ .core_init = ppc_currituck_pciex_core_init,
+ .check_link = ppc_currituck_pciex_check_link,
+};
+#endif /* CONFIG_CURRITUCK */
+
/* Check that the core has been initied and if not, do it */
static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
{
@@ -1315,6 +1361,10 @@ static int __init ppc4xx_pciex_check_core_init(struct device_node *np)
if (of_device_is_compatible(np, "ibm,plb-pciex-405ex"))
ppc4xx_pciex_hwops = &ppc405ex_pcie_hwops;
#endif
+#ifdef CONFIG_CURRITUCK
+ if (of_device_is_compatible(np, "ibm,plb-pciex-currituck"))
+ ppc4xx_pciex_hwops = &ppc_currituck_pcie_hwops;
+#endif
if (ppc4xx_pciex_hwops == NULL) {
printk(KERN_WARNING "PCIE: unknown host type %s\n",
np->full_name);
@@ -1623,6 +1673,10 @@ static int __init ppc4xx_setup_one_pciex_POM(struct ppc4xx_pciex_port *port,
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_460SX_OMR1MSKL_UOT
| DCRO_PEGPL_OMRxMSKL_VAL);
+ else if (of_device_is_compatible(port->node, "ibm,plb-pciex-currituck"))
+ dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
+ sa | DCRO_PEGPL_CURRITUCK_OMR1MSKL_UOT
+ | DCRO_PEGPL_OMRxMSKL_VAL);
else
dcr_write(port->dcrs, DCRO_PEGPL_OMR1MSKL,
sa | DCRO_PEGPL_OMR1MSKL_UOT
@@ -1747,7 +1801,8 @@ static void __init ppc4xx_configure_pciex_PIMs(struct ppc4xx_pciex_port *port,
if (res->flags & IORESOURCE_PREFETCH)
sa |= PCI_BASE_ADDRESS_MEM_PREFETCH;
- if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx"))
+ if (of_device_is_compatible(port->node, "ibm,plb-pciex-460sx") ||
+ of_device_is_compatible(port->node, "ibm,plb-pciex-currituck"))
sa |= PCI_BASE_ADDRESS_MEM_TYPE_64;
out_le32(mbase + PECFG_BAR0HMPA, RES_TO_U32_HIGH(sa));
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.h b/arch/powerpc/sysdev/ppc4xx_pci.h
index 32ce763..81f60d9 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.h
+++ b/arch/powerpc/sysdev/ppc4xx_pci.h
@@ -476,6 +476,13 @@
#define DCRO_PEGPL_OMR1MSKL_UOT 0x00000002
#define DCRO_PEGPL_OMR3MSKL_IO 0x00000002
+/* Currituck - 476 FPE */
+#define PCCFG_LCPA 0x270
+#define PECFG_TLDLP 0x3F8
+#define PECFG_TLDLP_LNKUP 0x00000008
+#define PECFG_TLDLP_PRESENT 0x00000010
+#define DCRO_PEGPL_CURRITUCK_OMR1MSKL_UOT 0x00000004
+
/* SDR Bit Mappings */
#define PESDRx_RCSSET_HLDPLB 0x10000000
#define PESDRx_RCSSET_RSTGU 0x01000000
--
1.7.6.4
^ permalink raw reply related
* [PATCH 5/6] powerpc/boot: Add mfdcrx
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/boot/dcr.h | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/dcr.h b/arch/powerpc/boot/dcr.h
index 645a7c9..51b5893 100644
--- a/arch/powerpc/boot/dcr.h
+++ b/arch/powerpc/boot/dcr.h
@@ -9,6 +9,12 @@
})
#define mtdcr(rn, val) \
asm volatile("mtdcr %0,%1" : : "i"(rn), "r"(val))
+#define mfdcrx(rn) \
+ ({ \
+ unsigned long rval; \
+ asm volatile("mfdcrx %0,%1" : "=r"(rval) : "g"(rn)); \
+ rval; \
+ })
/* 440GP/440GX SDRAM controller DCRs */
#define DCRN_SDRAM0_CFGADDR 0x010
--
1.7.6.4
^ permalink raw reply related
* [PATCH 4/6] powerpc/boot: Add extended precision shifts to the boot wrapper.
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
Code copied from arch/powerpc/kernel/misc_32.S
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/boot/div64.S | 52 +++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 52 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/boot/div64.S b/arch/powerpc/boot/div64.S
index d271ab5..bbcb8a4 100644
--- a/arch/powerpc/boot/div64.S
+++ b/arch/powerpc/boot/div64.S
@@ -57,3 +57,55 @@ __div64_32:
stw r8,4(r3)
mr r3,r6 # return the remainder in r3
blr
+
+/*
+ * Extended precision shifts.
+ *
+ * Updated to be valid for shift counts from 0 to 63 inclusive.
+ * -- Gabriel
+ *
+ * R3/R4 has 64 bit value
+ * R5 has shift count
+ * result in R3/R4
+ *
+ * ashrdi3: arithmetic right shift (sign propagation)
+ * lshrdi3: logical right shift
+ * ashldi3: left shift
+ */
+ .globl __ashrdi3
+__ashrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ rlwinm r8,r7,0,32 # t3 = (count < 32) ? 32 : 0
+ sraw r7,r3,r7 # t2 = MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ slw r7,r7,r8 # t2 = (count < 32) ? 0 : t2
+ sraw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
+
+ .globl __ashldi3
+__ashldi3:
+ subfic r6,r5,32
+ slw r3,r3,r5 # MSW = count > 31 ? 0 : MSW << count
+ addi r7,r5,32 # could be xori, or addi with -32
+ srw r6,r4,r6 # t1 = count > 31 ? 0 : LSW >> (32-count)
+ slw r7,r4,r7 # t2 = count < 32 ? 0 : LSW << (count-32)
+ or r3,r3,r6 # MSW |= t1
+ slw r4,r4,r5 # LSW = LSW << count
+ or r3,r3,r7 # MSW |= t2
+ blr
+
+ .globl __lshrdi3
+__lshrdi3:
+ subfic r6,r5,32
+ srw r4,r4,r5 # LSW = count > 31 ? 0 : LSW >> count
+ addi r7,r5,32 # could be xori, or addi with -32
+ slw r6,r3,r6 # t1 = count > 31 ? 0 : MSW << (32-count)
+ srw r7,r3,r7 # t2 = count < 32 ? 0 : MSW >> (count-32)
+ or r4,r4,r6 # LSW |= t1
+ srw r3,r3,r5 # MSW = MSW >> count
+ or r4,r4,r7 # LSW |= t2
+ blr
--
1.7.6.4
^ permalink raw reply related
* [PATCH 3/6] 44x: Removing dead CONFIG_PPC47x
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: Christoph Egger, LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
From: Christoph Egger <siccegge@cs.fau.de>
CONFIG_PPC47x doesn't exist in Kconfig, therefore removing all
references for it from the source code.
Signed-off-by: Christoph Egger <siccegge@cs.fau.de>
---
arch/powerpc/mm/44x_mmu.c | 4 ----
1 files changed, 0 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index f60e006..5d4e3ff 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -78,11 +78,7 @@ static void __init ppc44x_pin_tlb(unsigned int virt, unsigned int phys)
"tlbwe %1,%3,%5\n"
"tlbwe %0,%3,%6\n"
:
-#ifdef CONFIG_PPC47x
- : "r" (PPC47x_TLB2_S_RWX),
-#else
: "r" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G),
-#endif
"r" (phys),
"r" (virt | PPC44x_TLB_VALID | PPC44x_TLB_256M),
"r" (entry),
--
1.7.6.4
^ permalink raw reply related
* [PATCH 2/6] 44x/pci: Setup the dma_window properties for each pci_controller
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
Needed if you want to use swiotlb, harmless otherwise.
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/sysdev/ppc4xx_pci.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index d3fa380..d766068 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -185,9 +185,15 @@ static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
out:
dma_offset_set = 1;
pci_dram_offset = res->start;
+ hose->dma_window_base_cur = res->start;
+ hose->dma_window_size = resource_size(res);
printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n",
pci_dram_offset);
+ printk(KERN_INFO "4xx PCI DMA window base to 0x%016llx\n",
+ (unsigned long long)hose->dma_window_base_cur);
+ printk(KERN_INFO "DMA window size 0x%016llx\n",
+ (unsigned long long)hose->dma_window_size);
return 0;
}
--
1.7.6.4
^ permalink raw reply related
* [PATCH 1/6] 44x/pci: Continue pci setup even if there is no sdr-base in the device-tree
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
In-Reply-To: <1322630640-13708-1-git-send-email-tony@bakeyournoodle.com>
Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
---
arch/powerpc/sysdev/ppc4xx_pci.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/sysdev/ppc4xx_pci.c b/arch/powerpc/sysdev/ppc4xx_pci.c
index 16f5eba..d3fa380 100644
--- a/arch/powerpc/sysdev/ppc4xx_pci.c
+++ b/arch/powerpc/sysdev/ppc4xx_pci.c
@@ -1974,11 +1974,11 @@ static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
port->node = of_node_get(np);
pval = of_get_property(np, "sdr-base", NULL);
if (pval == NULL) {
- printk(KERN_ERR "PCIE: missing sdr-base for %s\n",
+ printk(KERN_INFO "PCIE: missing sdr-base for %s\n",
np->full_name);
- return;
+ } else {
+ port->sdr_base = *pval;
}
- port->sdr_base = *pval;
/* Check if device_type property is set to "pci" or "pci-endpoint".
* Resulting from this setup this PCIe port will be configured
--
1.7.6.4
^ permalink raw reply related
* Add support for the currituck 476 platform from IBM
From: Tony Breeds @ 2011-11-30 5:23 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Josh Boyer; +Cc: LinuxPPC-dev
Patches 1 and 2
Modify the 44x PCI code to work with currituck.
Patch 3
Is an old patch by Christoph Egger that fell through the cracks somehow.
Patches 4 and 5
Modify the bootwrapper to handle currituck
Patch 6
The platform itself.
arch/powerpc/boot/Makefile | 5 +-
arch/powerpc/boot/dcr.h | 6 +
arch/powerpc/boot/div64.S | 52 ++++++
arch/powerpc/boot/dts/currituck.dts | 240 ++++++++++++++++++++++++++
arch/powerpc/boot/treeboot-currituck.c | 129 ++++++++++++++
arch/powerpc/boot/wrapper | 3 +
arch/powerpc/configs/44x/currituck_defconfig | 110 ++++++++++++
arch/powerpc/include/asm/reg.h | 1 +
arch/powerpc/kernel/cputable.c | 14 ++
arch/powerpc/kernel/head_44x.S | 2 +
arch/powerpc/mm/44x_mmu.c | 4 -
arch/powerpc/platforms/44x/Kconfig | 10 +
arch/powerpc/platforms/44x/Makefile | 1 +
arch/powerpc/platforms/44x/ppc47x.c | 198 +++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.c | 69 +++++++-
arch/powerpc/sysdev/ppc4xx_pci.h | 7 +
16 files changed, 842 insertions(+), 9 deletions(-)
^ permalink raw reply
* Re: [linux-pm] [RFC PATCH v2 4/4] cpuidle: (POWER) Handle power_save=off
From: Benjamin Herrenschmidt @ 2011-11-30 4:52 UTC (permalink / raw)
To: Deepthi Dharwar; +Cc: linuxppc-dev, linux-pm, linux-kernel, linux-pm
In-Reply-To: <4ED58614.9090204@linux.vnet.ibm.com>
On Wed, 2011-11-30 at 06:55 +0530, Deepthi Dharwar wrote:
> I was trying to add a return value for power_save for all arch/powepc
> idle functions but a few of them directly call *.S routines, as they
> are asm.
>
> What would be a good way to change the return value for asm
> routines ?
> Do we make a change in asm only, put the return value in r3 or write a
> wrapper function which would call these asm routines and return an
> int ?
No, add li r3,0 at the end, but beware that their return point might not
be ovbvious since we often return from an interrupt which modifies the
return address ... Let me know if there's some you can't figure out and
I'll help you.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 00/10] powerpc/mpic: General cleanup patch series
From: Benjamin Herrenschmidt @ 2011-11-30 4:40 UTC (permalink / raw)
To: Kyle Moffett; +Cc: linuxppc-dev
In-Reply-To: <1322593117-29938-1-git-send-email-Kyle.D.Moffett@boeing.com>
On Tue, 2011-11-29 at 13:58 -0500, Kyle Moffett wrote:
> Hello,
>
> As BenH requested, this is the version-2 repost of the PowerPC MPIC
> cleanup patch series.
>
> All of the review comments have been addressed, and I have performed
> build and boot testing on our HWW-1U-1A hardware with these patches
> applied (plus a few independent board-support patches).
>
> Unfortunately, this has a potentially very broad impact across a wide
> variety of hardware that I don't have the ability to test with, so
> any additional testing will be highly appreciated. Ben has indicated
> that he plans to put it into his testing tree soon, so hopefully any
> such issues will get ironed out quickly.
Ok, clashes with whatever I already have in -next, so I did a manual
merge in my -test branch, please double check I haven't done any
mistake. (This test branch also contains Becky current patch series).
So -test is out there for you guys to hammer on, I'll do some tests
myself in the next couple of days, and I expect to merge all of that
into -next (assuming there are no big issues) some time next week.
BTW. Reminder to all: -test is a rebase-friendly branch, so pull -f and
do NOT base any work on top of it if you aren't ready to deal with your
origin changing completely from underneath you.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 3/3] powerpc/powernv: Workaround OFW issues in prom_init.c
From: Benjamin Herrenschmidt @ 2011-11-30 4:22 UTC (permalink / raw)
To: linuxppc-dev
Open Firmware on OPAL machines seems to have issues if we close
stdin and/or we try to print things after calling "quiesce" so
we avoid doing both.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/prom_init.c | 14 ++++++++++----
1 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index cc58486..6d2987b 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2969,9 +2969,11 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
/*
* in case stdin is USB and still active on IBM machines...
* Unfortunately quiesce crashes on some powermacs if we have
- * closed stdin already (in particular the powerbook 101).
+ * closed stdin already (in particular the powerbook 101). It
+ * appears that the OPAL version of OFW doesn't like it either.
*/
- if (RELOC(of_platform) != PLATFORM_POWERMAC)
+ if (RELOC(of_platform) != PLATFORM_POWERMAC &&
+ RELOC(of_platform) != PLATFORM_OPAL)
prom_close_stdin();
/*
@@ -2987,8 +2989,12 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
* is common to us and kexec
*/
hdr = RELOC(dt_header_start);
- prom_printf("returning from prom_init\n");
- prom_debug("->dt_header_start=0x%x\n", hdr);
+
+ /* Don't print anything after quiesce under OPAL, it crashes OFW */
+ if (RELOC(of_platform) != PLATFORM_OPAL) {
+ prom_printf("returning from prom_init\n");
+ prom_debug("->dt_header_start=0x%x\n", hdr);
+ }
#ifdef CONFIG_PPC32
reloc_got2(-offset);
--
1.7.7.2
^ permalink raw reply related
* [PATCH 2/3] powerpc/powernv: Display diag data on p7ioc EEH errors
From: Benjamin Herrenschmidt @ 2011-11-30 4:22 UTC (permalink / raw)
To: linuxppc-dev
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/powernv/pci-ioda.c | 25 ++++---
arch/powerpc/platforms/powernv/pci-p5ioc2.c | 1 +
arch/powerpc/platforms/powernv/pci.c | 117 ++++++++++++++++++++++++--
arch/powerpc/platforms/powernv/pci.h | 16 ++++
4 files changed, 140 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 425c2b2..f31162c 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -9,7 +9,7 @@
* 2 of the License, or (at your option) any later version.
*/
-#define DEBUG
+#undef DEBUG
#include <linux/kernel.h>
#include <linux/pci.h>
@@ -467,14 +467,13 @@ static void __devinit pnv_ioda_update_resources(struct pci_bus *bus)
struct pci_bus *cbus;
struct pci_dev *cdev;
unsigned int i;
- u16 cmd;
- /* Clear all device enables */
- list_for_each_entry(cdev, &bus->devices, bus_list) {
- pci_read_config_word(cdev, PCI_COMMAND, &cmd);
- cmd &= ~(PCI_COMMAND_IO|PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER);
- pci_write_config_word(cdev, PCI_COMMAND, cmd);
- }
+ /* We used to clear all device enables here. However it looks like
+ * clearing MEM enable causes Obsidian (IPR SCS) to go bonkers,
+ * and shoot fatal errors to the PHB which in turns fences itself
+ * and we can't recover from that ... yet. So for now, let's leave
+ * the enables as-is and hope for the best.
+ */
/* Check if bus resources fit in our IO or M32 range */
for (i = 0; bus->self && (i < 2); i++) {
@@ -618,7 +617,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
struct pci_dn *pdn = pnv_ioda_get_pdn(parent);
if (pdn && pdn->pe_number != IODA_INVALID_PE) {
rc = opal_pci_set_peltv(phb->opal_id, pdn->pe_number,
- pe->pe_number, 1);
+ pe->pe_number, OPAL_ADD_PE_TO_DOMAIN);
/* XXX What to do in case of error ? */
}
parent = parent->bus->self;
@@ -638,7 +637,7 @@ static int __devinit pnv_ioda_configure_pe(struct pnv_phb *phb,
pe->mve_number = -1;
} else {
rc = opal_pci_set_mve_enable(phb->opal_id,
- pe->mve_number, 1);
+ pe->mve_number, OPAL_ENABLE_MVE);
if (rc) {
pe_err(pe, "OPAL error %ld enabling MVE %d\n",
rc, pe->mve_number);
@@ -1187,6 +1186,12 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
phb->opal_id = phb_id;
phb->type = PNV_PHB_IODA1;
+ /* Detect specific models for error handling */
+ if (of_device_is_compatible(np, "ibm,p7ioc-pciex"))
+ phb->model = PNV_PHB_MODEL_P7IOC;
+ else
+ phb->model = PNV_PHB_MODEL_UNKNOWN;
+
/* We parse "ranges" now since we need to deduce the register base
* from the IO base
*/
diff --git a/arch/powerpc/platforms/powernv/pci-p5ioc2.c b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
index 4c80f7c..2649677 100644
--- a/arch/powerpc/platforms/powernv/pci-p5ioc2.c
+++ b/arch/powerpc/platforms/powernv/pci-p5ioc2.c
@@ -137,6 +137,7 @@ static void __init pnv_pci_init_p5ioc2_phb(struct device_node *np,
phb->hose->private_data = phb;
phb->opal_id = phb_id;
phb->type = PNV_PHB_P5IOC2;
+ phb->model = PNV_PHB_MODEL_P5IOC2;
phb->regs = of_iomap(np, 0);
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index c0ed379..68e7e2c 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -144,6 +144,112 @@ static void pnv_teardown_msi_irqs(struct pci_dev *pdev)
}
#endif /* CONFIG_PCI_MSI */
+static void pnv_pci_dump_p7ioc_diag_data(struct pnv_phb *phb)
+{
+ struct OpalIoP7IOCPhbErrorData *data = &phb->diag.p7ioc;
+ int i;
+
+ pr_info("PHB %d diagnostic data:\n", phb->hose->global_number);
+
+ pr_info(" brdgCtl = 0x%08x\n", data->brdgCtl);
+
+ pr_info(" portStatusReg = 0x%08x\n", data->portStatusReg);
+ pr_info(" rootCmplxStatus = 0x%08x\n", data->rootCmplxStatus);
+ pr_info(" busAgentStatus = 0x%08x\n", data->busAgentStatus);
+
+ pr_info(" deviceStatus = 0x%08x\n", data->deviceStatus);
+ pr_info(" slotStatus = 0x%08x\n", data->slotStatus);
+ pr_info(" linkStatus = 0x%08x\n", data->linkStatus);
+ pr_info(" devCmdStatus = 0x%08x\n", data->devCmdStatus);
+ pr_info(" devSecStatus = 0x%08x\n", data->devSecStatus);
+
+ pr_info(" rootErrorStatus = 0x%08x\n", data->rootErrorStatus);
+ pr_info(" uncorrErrorStatus = 0x%08x\n", data->uncorrErrorStatus);
+ pr_info(" corrErrorStatus = 0x%08x\n", data->corrErrorStatus);
+ pr_info(" tlpHdr1 = 0x%08x\n", data->tlpHdr1);
+ pr_info(" tlpHdr2 = 0x%08x\n", data->tlpHdr2);
+ pr_info(" tlpHdr3 = 0x%08x\n", data->tlpHdr3);
+ pr_info(" tlpHdr4 = 0x%08x\n", data->tlpHdr4);
+ pr_info(" sourceId = 0x%08x\n", data->sourceId);
+
+ pr_info(" errorClass = 0x%016llx\n", data->errorClass);
+ pr_info(" correlator = 0x%016llx\n", data->correlator);
+
+ pr_info(" p7iocPlssr = 0x%016llx\n", data->p7iocPlssr);
+ pr_info(" p7iocCsr = 0x%016llx\n", data->p7iocCsr);
+ pr_info(" lemFir = 0x%016llx\n", data->lemFir);
+ pr_info(" lemErrorMask = 0x%016llx\n", data->lemErrorMask);
+ pr_info(" lemWOF = 0x%016llx\n", data->lemWOF);
+ pr_info(" phbErrorStatus = 0x%016llx\n", data->phbErrorStatus);
+ pr_info(" phbFirstErrorStatus = 0x%016llx\n", data->phbFirstErrorStatus);
+ pr_info(" phbErrorLog0 = 0x%016llx\n", data->phbErrorLog0);
+ pr_info(" phbErrorLog1 = 0x%016llx\n", data->phbErrorLog1);
+ pr_info(" mmioErrorStatus = 0x%016llx\n", data->mmioErrorStatus);
+ pr_info(" mmioFirstErrorStatus = 0x%016llx\n", data->mmioFirstErrorStatus);
+ pr_info(" mmioErrorLog0 = 0x%016llx\n", data->mmioErrorLog0);
+ pr_info(" mmioErrorLog1 = 0x%016llx\n", data->mmioErrorLog1);
+ pr_info(" dma0ErrorStatus = 0x%016llx\n", data->dma0ErrorStatus);
+ pr_info(" dma0FirstErrorStatus = 0x%016llx\n", data->dma0FirstErrorStatus);
+ pr_info(" dma0ErrorLog0 = 0x%016llx\n", data->dma0ErrorLog0);
+ pr_info(" dma0ErrorLog1 = 0x%016llx\n", data->dma0ErrorLog1);
+ pr_info(" dma1ErrorStatus = 0x%016llx\n", data->dma1ErrorStatus);
+ pr_info(" dma1FirstErrorStatus = 0x%016llx\n", data->dma1FirstErrorStatus);
+ pr_info(" dma1ErrorLog0 = 0x%016llx\n", data->dma1ErrorLog0);
+ pr_info(" dma1ErrorLog1 = 0x%016llx\n", data->dma1ErrorLog1);
+
+ for (i = 0; i < OPAL_P7IOC_NUM_PEST_REGS; i++) {
+ if ((data->pestA[i] >> 63) == 0 &&
+ (data->pestB[i] >> 63) == 0)
+ continue;
+ pr_info(" PE[%3d] PESTA = 0x%016llx\n", i, data->pestA[i]);
+ pr_info(" PESTB = 0x%016llx\n", data->pestB[i]);
+ }
+}
+
+static void pnv_pci_dump_phb_diag_data(struct pnv_phb *phb)
+{
+ switch(phb->model) {
+ case PNV_PHB_MODEL_P7IOC:
+ pnv_pci_dump_p7ioc_diag_data(phb);
+ break;
+ default:
+ pr_warning("PCI %d: Can't decode this PHB diag data\n",
+ phb->hose->global_number);
+ }
+}
+
+static void pnv_pci_handle_eeh_config(struct pnv_phb *phb, u32 pe_no)
+{
+ unsigned long flags, rc;
+ int has_diag;
+
+ spin_lock_irqsave(&phb->lock, flags);
+
+ rc = opal_pci_get_phb_diag_data(phb->opal_id, phb->diag.blob, PNV_PCI_DIAG_BUF_SIZE);
+ has_diag = (rc == OPAL_SUCCESS);
+
+ rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
+ OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
+ if (rc) {
+ pr_warning("PCI %d: Failed to clear EEH freeze state"
+ " for PE#%d, err %ld\n",
+ phb->hose->global_number, pe_no, rc);
+
+ /* For now, let's only display the diag buffer when we fail to clear
+ * the EEH status. We'll do more sensible things later when we have
+ * proper EEH support. We need to make sure we don't pollute ourselves
+ * with the normal errors generated when probing empty slots
+ */
+ if (has_diag)
+ pnv_pci_dump_phb_diag_data(phb);
+ else
+ pr_warning("PCI %d: No diag data available\n",
+ phb->hose->global_number);
+ }
+
+ spin_unlock_irqrestore(&phb->lock, flags);
+}
+
static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
u32 bdfn)
{
@@ -165,15 +271,8 @@ static void pnv_pci_config_check_eeh(struct pnv_phb *phb, struct pci_bus *bus,
}
cfg_dbg(" -> EEH check, bdfn=%04x PE%d fstate=%x\n",
bdfn, pe_no, fstate);
- if (fstate != 0) {
- rc = opal_pci_eeh_freeze_clear(phb->opal_id, pe_no,
- OPAL_EEH_ACTION_CLEAR_FREEZE_ALL);
- if (rc) {
- pr_warning("PCI %d: Failed to clear EEH freeze state"
- " for PE#%d, err %lld\n",
- phb->hose->global_number, pe_no, rc);
- }
- }
+ if (fstate != 0)
+ pnv_pci_handle_eeh_config(phb, pe_no);
}
static int pnv_pci_read_config(struct pci_bus *bus,
diff --git a/arch/powerpc/platforms/powernv/pci.h b/arch/powerpc/platforms/powernv/pci.h
index 28ae4ca..8bc4796 100644
--- a/arch/powerpc/platforms/powernv/pci.h
+++ b/arch/powerpc/platforms/powernv/pci.h
@@ -9,6 +9,15 @@ enum pnv_phb_type {
PNV_PHB_IODA2,
};
+/* Precise PHB model for error management */
+enum pnv_phb_model {
+ PNV_PHB_MODEL_UNKNOWN,
+ PNV_PHB_MODEL_P5IOC2,
+ PNV_PHB_MODEL_P7IOC,
+};
+
+#define PNV_PCI_DIAG_BUF_SIZE 4096
+
/* Data associated with a PE, including IOMMU tracking etc.. */
struct pnv_ioda_pe {
/* A PE can be associated with a single device or an
@@ -56,6 +65,7 @@ struct pnv_ioda_pe {
struct pnv_phb {
struct pci_controller *hose;
enum pnv_phb_type type;
+ enum pnv_phb_model model;
u64 opal_id;
void __iomem *regs;
spinlock_t lock;
@@ -118,6 +128,12 @@ struct pnv_phb {
struct list_head pe_list;
} ioda;
};
+
+ /* PHB status structure */
+ union {
+ unsigned char blob[PNV_PCI_DIAG_BUF_SIZE];
+ struct OpalIoP7IOCPhbErrorData p7ioc;
+ } diag;
};
extern struct pci_ops pnv_pci_ops;
--
1.7.7.2
^ permalink raw reply related
* [PATCH 1/3] powerpc/powernv: Update OPAL interfaces
From: Benjamin Herrenschmidt @ 2011-11-30 4:22 UTC (permalink / raw)
To: linuxppc-dev
This adds some more interfaces for OPAL v2
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/opal.h | 131 +++++++++++++++++++++++-
arch/powerpc/platforms/powernv/opal-wrappers.S | 8 ++
arch/powerpc/platforms/powernv/pci-ioda.c | 4 +-
3 files changed, 137 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 2893e8f..a4b28f1 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -109,6 +109,14 @@ extern int opal_enter_rtas(struct rtas_args *args,
#define OPAL_PCI_MAP_PE_DMA_WINDOW 44
#define OPAL_PCI_MAP_PE_DMA_WINDOW_REAL 45
#define OPAL_PCI_RESET 49
+#define OPAL_PCI_GET_HUB_DIAG_DATA 50
+#define OPAL_PCI_GET_PHB_DIAG_DATA 51
+#define OPAL_PCI_FENCE_PHB 52
+#define OPAL_PCI_REINIT 53
+#define OPAL_PCI_MASK_PE_ERROR 54
+#define OPAL_SET_SLOT_LED_STATUS 55
+#define OPAL_GET_EPOW_STATUS 56
+#define OPAL_SET_SYSTEM_ATTENTION_LED 57
#ifndef __ASSEMBLY__
@@ -169,7 +177,11 @@ enum OpalPendingState {
OPAL_EVENT_NVRAM = 0x2,
OPAL_EVENT_RTC = 0x4,
OPAL_EVENT_CONSOLE_OUTPUT = 0x8,
- OPAL_EVENT_CONSOLE_INPUT = 0x10
+ OPAL_EVENT_CONSOLE_INPUT = 0x10,
+ OPAL_EVENT_ERROR_LOG_AVAIL = 0x20,
+ OPAL_EVENT_ERROR_LOG = 0x40,
+ OPAL_EVENT_EPOW = 0x80,
+ OPAL_EVENT_LED_STATUS = 0x100
};
/* Machine check related definitions */
@@ -258,13 +270,49 @@ enum OpalPeAction {
OPAL_MAP_PE = 1
};
+enum OpalPeltvAction {
+ OPAL_REMOVE_PE_FROM_DOMAIN = 0,
+ OPAL_ADD_PE_TO_DOMAIN = 1
+};
+
+enum OpalMveEnableAction {
+ OPAL_DISABLE_MVE = 0,
+ OPAL_ENABLE_MVE = 1
+};
+
enum OpalPciResetAndReinitScope {
OPAL_PHB_COMPLETE = 1, OPAL_PCI_LINK = 2, OPAL_PHB_ERROR = 3,
OPAL_PCI_HOT_RESET = 4, OPAL_PCI_FUNDAMENTAL_RESET = 5,
- OPAL_PCI_IODA_RESET = 6,
+ OPAL_PCI_IODA_TABLE_RESET = 6,
+};
+
+enum OpalPciResetState {
+ OPAL_DEASSERT_RESET = 0,
+ OPAL_ASSERT_RESET = 1
};
-enum OpalPciResetState { OPAL_DEASSERT_RESET = 0, OPAL_ASSERT_RESET = 1 };
+enum OpalPciMaskAction {
+ OPAL_UNMASK_ERROR_TYPE = 0,
+ OPAL_MASK_ERROR_TYPE = 1
+};
+
+enum OpalSlotLedType {
+ OPAL_SLOT_LED_ID_TYPE = 0,
+ OPAL_SLOT_LED_FAULT_TYPE = 1
+};
+
+enum OpalLedAction {
+ OPAL_TURN_OFF_LED = 0,
+ OPAL_TURN_ON_LED = 1,
+ OPAL_QUERY_LED_STATE_AFTER_BUSY = 2
+};
+
+enum OpalEpowStatus {
+ OPAL_EPOW_NONE = 0,
+ OPAL_EPOW_UPS = 1,
+ OPAL_EPOW_OVER_AMBIENT_TEMP = 2,
+ OPAL_EPOW_OVER_INTERNAL_TEMP = 3
+};
struct opal_machine_check_event {
enum OpalMCE_Version version:8; /* 0x00 */
@@ -314,8 +362,74 @@ struct opal_machine_check_event {
} u;
};
+/**
+ * This structure defines the overlay which will be used to store PHB error
+ * data upon request.
+ */
+enum {
+ OPAL_P7IOC_NUM_PEST_REGS = 128,
+};
+
+struct OpalIoP7IOCPhbErrorData {
+ uint32_t brdgCtl;
+
+ // P7IOC utl regs
+ uint32_t portStatusReg;
+ uint32_t rootCmplxStatus;
+ uint32_t busAgentStatus;
+
+ // P7IOC cfg regs
+ uint32_t deviceStatus;
+ uint32_t slotStatus;
+ uint32_t linkStatus;
+ uint32_t devCmdStatus;
+ uint32_t devSecStatus;
+
+ // cfg AER regs
+ uint32_t rootErrorStatus;
+ uint32_t uncorrErrorStatus;
+ uint32_t corrErrorStatus;
+ uint32_t tlpHdr1;
+ uint32_t tlpHdr2;
+ uint32_t tlpHdr3;
+ uint32_t tlpHdr4;
+ uint32_t sourceId;
+
+ uint32_t rsv3;
+
+ // Record data about the call to allocate a buffer.
+ uint64_t errorClass;
+ uint64_t correlator;
+
+ //P7IOC MMIO Error Regs
+ uint64_t p7iocPlssr; // n120
+ uint64_t p7iocCsr; // n110
+ uint64_t lemFir; // nC00
+ uint64_t lemErrorMask; // nC18
+ uint64_t lemWOF; // nC40
+ uint64_t phbErrorStatus; // nC80
+ uint64_t phbFirstErrorStatus; // nC88
+ uint64_t phbErrorLog0; // nCC0
+ uint64_t phbErrorLog1; // nCC8
+ uint64_t mmioErrorStatus; // nD00
+ uint64_t mmioFirstErrorStatus; // nD08
+ uint64_t mmioErrorLog0; // nD40
+ uint64_t mmioErrorLog1; // nD48
+ uint64_t dma0ErrorStatus; // nD80
+ uint64_t dma0FirstErrorStatus; // nD88
+ uint64_t dma0ErrorLog0; // nDC0
+ uint64_t dma0ErrorLog1; // nDC8
+ uint64_t dma1ErrorStatus; // nE00
+ uint64_t dma1FirstErrorStatus; // nE08
+ uint64_t dma1ErrorLog0; // nE40
+ uint64_t dma1ErrorLog1; // nE48
+ uint64_t pestA[OPAL_P7IOC_NUM_PEST_REGS];
+ uint64_t pestB[OPAL_P7IOC_NUM_PEST_REGS];
+};
+
typedef struct oppanel_line {
- /* XXX */
+ const char * line;
+ uint64_t line_len;
} oppanel_line_t;
/* API functions */
@@ -413,6 +527,15 @@ int64_t opal_pci_map_pe_dma_window_real(uint64_t phb_id, uint16_t pe_number,
uint64_t pci_mem_size);
int64_t opal_pci_reset(uint64_t phb_id, uint8_t reset_scope, uint8_t assert_state);
+int64_t opal_pci_get_hub_diag_data(uint64_t hub_id, void *diag_buffer, uint64_t diag_buffer_len);
+int64_t opal_pci_get_phb_diag_data(uint64_t phb_id, void *diag_buffer, uint64_t diag_buffer_len);
+int64_t opal_pci_fence_phb(uint64_t phb_id);
+int64_t opal_pci_reinit(uint64_t phb_id, uint8_t reinit_scope);
+int64_t opal_pci_mask_pe_error(uint64_t phb_id, uint16_t pe_number, uint8_t error_type, uint8_t mask_action);
+int64_t opal_set_slot_led_status(uint64_t phb_id, uint64_t slot_id, uint8_t led_type, uint8_t led_action);
+int64_t opal_get_epow_status(uint64_t *status);
+int64_t opal_set_system_attention_led(uint8_t led_action);
+
/* Internal functions */
extern int early_init_dt_scan_opal(unsigned long node, const char *uname, int depth, void *data);
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index 4a3f46d..3bb07e5 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -99,3 +99,11 @@ OPAL_CALL(opal_write_oppanel, OPAL_WRITE_OPPANEL);
OPAL_CALL(opal_pci_map_pe_dma_window, OPAL_PCI_MAP_PE_DMA_WINDOW);
OPAL_CALL(opal_pci_map_pe_dma_window_real, OPAL_PCI_MAP_PE_DMA_WINDOW_REAL);
OPAL_CALL(opal_pci_reset, OPAL_PCI_RESET);
+OPAL_CALL(opal_pci_get_hub_diag_data, OPAL_PCI_GET_HUB_DIAG_DATA);
+OPAL_CALL(opal_pci_get_phb_diag_data, OPAL_PCI_GET_PHB_DIAG_DATA);
+OPAL_CALL(opal_pci_fence_phb, OPAL_PCI_FENCE_PHB);
+OPAL_CALL(opal_pci_reinit, OPAL_PCI_REINIT);
+OPAL_CALL(opal_pci_mask_pe_error, OPAL_PCI_MASK_PE_ERROR);
+OPAL_CALL(opal_set_slot_led_status, OPAL_SET_SLOT_LED_STATUS);
+OPAL_CALL(opal_get_epow_status, OPAL_GET_EPOW_STATUS);
+OPAL_CALL(opal_set_system_attention_led, OPAL_SET_SYSTEM_ATTENTION_LED);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index cf89f30..425c2b2 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -1294,9 +1294,9 @@ void __init pnv_pci_init_ioda1_phb(struct device_node *np)
pci_add_flags(PCI_REASSIGN_ALL_RSRC);
/* Reset IODA tables to a clean state */
- rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_RESET, OPAL_ASSERT_RESET);
+ rc = opal_pci_reset(phb_id, OPAL_PCI_IODA_TABLE_RESET, OPAL_ASSERT_RESET);
if (rc)
- pr_warning(" OPAL Error %ld performing IODA reset !\n", rc);
+ pr_warning(" OPAL Error %ld performing IODA table reset !\n", rc);
opal_pci_set_pe(phb_id, 0, 0, 7, 1, 1 , OPAL_MAP_PE);
}
--
1.7.7.2
^ permalink raw reply related
* Re: [BUG?]3.0-rc4+ftrace+kprobe: set kprobe at instruction 'stwu' lead to system crash/freeze
From: Benjamin Herrenschmidt @ 2011-11-30 4:19 UTC (permalink / raw)
To: tiejun.chen
Cc: Jim Keniston, Anton Blanchard, linux-kernel, Steven Rostedt,
Yong Zhang, paulus, yrl.pp-manager.tt, Masami Hiramatsu,
linuxppc-dev
In-Reply-To: <4E0D9B5E.3010901@windriver.com>
On Fri, 2011-07-01 at 18:03 +0800, tiejun.chen wrote:
>
> Here emulate_step() is called to emulate 'stwu'. Actually this is equivalent to
> 1> update pr_regs->gpr[1] = mem(old r1 + (-A))
> 2> 'stw <old r1>, mem<(old r1 + (-A)) >
>
> You should notice the stack based on new r1 would be covered with mem<old r1
> +(-A)>. So after this, the kernel exit from post_krpobe, something would be
> broken. This should depend on sizeof(-A).
>
> For kprobe show_interrupts, you can see pregs->nip is re-written violently so
> kernel issued.
>
> But sometimes we may only re-write some violate registers the kernel still
> alive. And so this is just why the kernel works well for some kprobed point
> after you change some kernel options/toolchains.
>
> If I'm correct its difficult to kprobe these stwu sp operation since the
> sizeof(-A) is undermined for the kernel. So we have to implement in-depend
> interrupt stack like PPC64.
So I've spent a lot of time trying to find a better way to fix that bug
and I think I might have finally found one :-)
- When you try to emulate stwcx on the kernel stack (and only there),
don't actually perform the store. Set a TIF flag instead to indicate
special processing in the exception return path and store the address to
update somewhere either in a free slot of the stack frame itself of
somewhere in the thread struct (the former would be easier). You may as
well do some sanity checking on the value while at it to catch errors
early.
- In the exception return code, we already test for various TIF flags
(*** see comment below, it's even buggy today for preempt ***), so we
add a test for that flag and go to do_work.
- At the end of do_work, we check for this TIF flag. If it's not set or
any other flag is set, move on as usual. However, if it's the only flag
still set:
- Copy the exception frame we're about to unwind to just -below- the
new r1 value we want to write to. Then perform the write, and change
r1 to point to that copy of the frame.
- Branch to restore: which will unwind everything from that copy of
the frame, and eventually set r1 to GPR(1) in the copy which contains
the new value of r1.
This is the less intrusive approach and should work just fine, it's also
more robust than anything I've been able to think of and the approach
would work for 32 and 64-bit similarily.
(***) Above comment about a bug: If you look at entry_64.S version of
ret_from_except_lite you'll notice that in the !preempt case, after
we've checked MSR_PR we test for any TIF flag in _TIF_USER_WORK_MASK to
decide whether to go to do_work or not. However, in the preempt case, we
do a convoluted trick to test SIGPENDING only if PR was set and always
test NEED_RESCHED ... but we forget to test any other bit of
_TIF_USER_WORK_MASK !!! So that means that with preempt, we completely
fail to test for things like single step, syscall tracing, etc...
I think this should be fixed at the same time, by simplifying the code
by doing:
- Test PR. If set, go to test_work_user, else continue (or the other
way around and call it test_work_kernel)
- In test_work_user, always test for _TIF_USER_WORK_MASK to decide to
go to do_work, maybe call it do_user_work
- In test_work_kernel, test for _TIF_KERNEL_WORK_MASK which is set to
our new flag along with NEED_RESCHED if preempt is enabled and branch to
do_kernel_work.
do_user_work is basically the same as today's user_work
do_kernel_work is basically the same as today preempt block with added
code to handle the new flag as described above.
Is anybody volunteering for fixing that ? I don't have the bandwidth
right now, but if nobody shows up I suppose I'll have to eventually deal
with it myself :-)
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 2/8] powerpc/ps3: Fix hcall lv1_net_stop_rx_dma
From: Geoff Levand @ 2011-11-30 1:50 UTC (permalink / raw)
To: David S. Miller; +Cc: cbe-oss-dev, linuxppc-dev
In-Reply-To: <a4ecc1a889c6773a8ef6fd52ba0f49a705cac6d3.1322615824.git.geoff@infradead.org>
Hi Dave,
Unfortunately, your address got cut off for this patch.
I think Ben can merge this one through his powerpc tree since it is just
a trivial change to the ps3 gelic net driver.
Please consider.
-Geoff
On Wed, 2011-11-30 at 01:38 +0000, Geoff Levand wrote:
> The lv1_net_stop_tx_dma and net_stop_rx_dma hcalls take 2, not 3 input
> arguments. Adjust the lv1 hcall table and all calls.
>
> Signed-off-by: Geoff Levand <geoff@infradead.org>
> ---
> arch/powerpc/include/asm/lv1call.h | 4 ++--
> drivers/net/ethernet/toshiba/ps3_gelic_net.c | 4 ++--
> 2 files changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/lv1call.h b/arch/powerpc/include/asm/lv1call.h
> index f77c708..807d895 100644
> --- a/arch/powerpc/include/asm/lv1call.h
> +++ b/arch/powerpc/include/asm/lv1call.h
> @@ -294,9 +294,9 @@ LV1_CALL(unmap_device_dma_region, 4, 0, 177 )
> LV1_CALL(net_add_multicast_address, 4, 0, 185 )
> LV1_CALL(net_remove_multicast_address, 4, 0, 186 )
> LV1_CALL(net_start_tx_dma, 4, 0, 187 )
> -LV1_CALL(net_stop_tx_dma, 3, 0, 188 )
> +LV1_CALL(net_stop_tx_dma, 2, 0, 188 )
> LV1_CALL(net_start_rx_dma, 4, 0, 189 )
> -LV1_CALL(net_stop_rx_dma, 3, 0, 190 )
> +LV1_CALL(net_stop_rx_dma, 2, 0, 190 )
> LV1_CALL(net_set_interrupt_status_indicator, 4, 0, 191 )
> LV1_CALL(net_set_interrupt_mask, 4, 0, 193 )
> LV1_CALL(net_control, 6, 2, 194 )
> diff --git a/drivers/net/ethernet/toshiba/ps3_gelic_net.c b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> index 7bf1e20..5ee82a7 100644
> --- a/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> +++ b/drivers/net/ethernet/toshiba/ps3_gelic_net.c
> @@ -640,7 +640,7 @@ static inline void gelic_card_disable_rxdmac(struct gelic_card *card)
> int status;
>
> /* this hvc blocks until the DMA in progress really stopped */
> - status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card), 0);
> + status = lv1_net_stop_rx_dma(bus_id(card), dev_id(card));
> if (status)
> dev_err(ctodev(card),
> "lv1_net_stop_rx_dma failed, %d\n", status);
> @@ -658,7 +658,7 @@ static inline void gelic_card_disable_txdmac(struct gelic_card *card)
> int status;
>
> /* this hvc blocks until the DMA in progress really stopped */
> - status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card), 0);
> + status = lv1_net_stop_tx_dma(bus_id(card), dev_id(card));
> if (status)
> dev_err(ctodev(card),
> "lv1_net_stop_tx_dma failed, status=%d\n", status);
^ permalink raw reply
* Re: [PATCH v2] Integrated Flash Controller support
From: Kumar Gala @ 2011-11-30 1:47 UTC (permalink / raw)
To: Scott Wood
Cc: Artem.Bityutskiy, Li Yang-R58472, dedekind1,
linuxppc-dev@lists.ozlabs.org list, b35362@freescale.com>,
linux-kernel@vger.kernel.org Kernel, linux-mtd, Andrew Morton,
David Woodhouse
In-Reply-To: <4ED5531C.6030104@freescale.com>
On Nov 29, 2011, at 3:48 PM, Scott Wood wrote:
> On 11/29/2011 03:40 PM, Artem Bityutskiy wrote:
>> On Thu, 2011-11-24 at 08:24 -0600, Kumar Gala wrote:
>>> On Nov 22, 2011, at 9:41 PM, Kumar Gala wrote:
>>>=20
>>>>=20
>>>> On Oct 31, 2011, at 4:38 AM, <b35362@freescale.com> =
<b35362@freescale.com> wrote:
>>>>=20
>>>>> From: Liu Shuo <b35362@freescale.com>
>>>>>=20
>>>>> Integrated Flash Controller supports various flashes like NOR, =
NAND
>>>>> and other devices using NOR, NAND and GPCM Machine available on =
it.
>>>>> IFC supports four chip selects.
>>>>>=20
>>>>> Signed-off-by: Dipen Dudhat <Dipen.Dudhat@freescale.com>
>>>>> Signed-off-by: Scott Wood <scottwood@freescale.com>
>>>>> Signed-off-by: Li Yang <leoli@freescale.com>
>>>>> Signed-off-by: Liu Shuo <b35362@freescale.com>
>>>>> ---
>>>>> arch/powerpc/Kconfig | 4 +
>>>>> arch/powerpc/include/asm/fsl_ifc.h | 834 =
++++++++++++++++++++++++++++++++++++
>>>>> arch/powerpc/sysdev/Makefile | 1 +
>>>>> arch/powerpc/sysdev/fsl_ifc.c | 322 ++++++++++++++
>>>>> 4 files changed, 1161 insertions(+), 0 deletions(-)
>>>>> create mode 100644 arch/powerpc/include/asm/fsl_ifc.h
>>>>> create mode 100644 arch/powerpc/sysdev/fsl_ifc.c
>>>>=20
>>>> Guys,
>>>>=20
>>>> How are we handling this patchset since it touches =
drivers/mtd/nand?
>>=20
>> I do not see it touching MTD from the diffstat above. I am a little =
bit
>> confused why a flash controller is added to
>> arch/powerpc/sysdev/fsl_ifc.c ?
>=20
> It's really a bus controller, with NOR, NAND, and general-purpose =
modes
> settable per chipselect. The actual NAND driver goes in
> drivers/mtd/nand, and is apparently in a separate patch (probably due =
to
> separate maintenance domains).
>=20
> It's the same situation as arch/powerpc/sysdev/fsl_lbc.c versus
> drivers/mtd/nand/fsl_elbc_nand.c and drivers/mtd/nand/fsl_upm.c.
>=20
> -Scott
As Scott said, I was more asking about the 2nd patch in the sequence =
which did touch MTD. Since that one is dependent on this patch, =
wondering how we wanted to handle them.
- k
^ 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