* [PATCH] ARM: NUC900: Add PCI driver support for NUC960
@ 2011-11-12 16:04 Wan ZongShun
2011-11-12 23:14 ` Russell King - ARM Linux
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
0 siblings, 2 replies; 6+ messages in thread
From: Wan ZongShun @ 2011-11-12 16:04 UTC (permalink / raw)
To: linux-arm-kernel
Add pci driver support for Nuvoton arm nuc960.
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
---
arch/arm/mach-w90x900/Kconfig | 1 +
arch/arm/mach-w90x900/Makefile | 3 +
arch/arm/mach-w90x900/include/mach/map.h | 4 +
arch/arm/mach-w90x900/include/mach/regs-pci.h | 37 ++++
arch/arm/mach-w90x900/nuc960.c | 2 +
arch/arm/mach-w90x900/pci.c | 231
+++++++++++++++++++++++++
6 files changed, 278 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-w90x900/include/mach/regs-pci.h
create mode 100644 arch/arm/mach-w90x900/pci.c
diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig
index 69bab32..17be262 100644
--- a/arch/arm/mach-w90x900/Kconfig
+++ b/arch/arm/mach-w90x900/Kconfig
@@ -41,6 +41,7 @@ menu "NUC960 Machines"
config MACH_W90N960EVB
bool "Nuvoton NUC960 Evaluation Board"
select CPU_NUC960
+ select PCI
help
Say Y here if you are using the Nuvoton NUC960EVB
diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile
index 828c032..0c35800 100644
--- a/arch/arm/mach-w90x900/Makefile
+++ b/arch/arm/mach-w90x900/Makefile
@@ -17,3 +17,6 @@ obj-$(CONFIG_CPU_NUC960) += nuc960.o
obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o
obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o
obj-$(CONFIG_MACH_W90N960EVB) += mach-nuc960evb.o
+
+# Add pci support for nuc960, nuc920
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/arm/mach-w90x900/include/mach/map.h
b/arch/arm/mach-w90x900/include/mach/map.h
index 1a20953..69f6c73 100644
--- a/arch/arm/mach-w90x900/include/mach/map.h
+++ b/arch/arm/mach-w90x900/include/mach/map.h
@@ -154,4 +154,8 @@
#define W90X900_PA_EMC (0xB0003000)
#define W90X900_SZ_EMC SZ_4K
+/* PCI interface controller */
+#define W90X900_VA_PCI W90X900_ADDR(0x00002000)
+#define W90X900_PA_PCI (0xB0002000)
+#define W90X900_SZ_PCI SZ_4K
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-pci.h
b/arch/arm/mach-w90x900/include/mach/regs-pci.h
new file mode 100644
index 0000000..d1975eb
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/regs-pci.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-pci.h
+ *
+ * Copyright (c) 2011 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_PCI_H
+#define __ASM_ARCH_REGS_PCI_H
+
+#define PCI_BA W90X900_VA_PCI /* PCI Control */
+/* PCI Control Registers */
+#define REG_PCICTR (PCI_BA + 0x000)
+#define REG_PCISTR (PCI_BA + 0x004)
+#define REG_PCILATIMER (PCI_BA + 0x008)
+#define REG_PCIINTEN (PCI_BA + 0x010)
+#define REG_PCIINT (PCI_BA + 0x014)
+#define REG_CFGADDR (PCI_BA + 0x020)
+#define REG_CFGDATA (PCI_BA + 0x024)
+#define REG_PCIARB (PCI_BA + 0x04C)
+#define REG_PCIBIST (PCI_BA + 0x050)
+
+#define NUC900_PCI_IO_BASE 0xE0000000
+#define NUC900_PCI_IO_END 0xE000FFFF
+#define NUC900_PCI_IO_SIZE 0x10000
+
+#define NUC900_PCI_MEM_BASE 0xC0000000
+#define NUC900_PCI_MEM_END 0xDFFFEFFFF
+#define NUC900_PCI_MEM_SIZE 0x20000000
+
+#endif /* ___ASM_ARCH_REGS_PCI_H */
diff --git a/arch/arm/mach-w90x900/nuc960.c b/arch/arm/mach-w90x900/nuc960.c
index 8851a3a..0212964 100644
--- a/arch/arm/mach-w90x900/nuc960.c
+++ b/arch/arm/mach-w90x900/nuc960.c
@@ -19,6 +19,7 @@
#include <asm/mach/map.h>
#include <mach/hardware.h>
#include "cpu.h"
+#include "clock.h"
/* define specific CPU platform device */
@@ -30,6 +31,7 @@ static struct platform_device *nuc960_dev[] __initdata = {
/* define specific CPU platform io map */
static struct map_desc nuc960evb_iodesc[] __initdata = {
+ IODESC_ENT(PCI),
};
/*Init NUC960 evb io*/
diff --git a/arch/arm/mach-w90x900/pci.c b/arch/arm/mach-w90x900/pci.c
new file mode 100644
index 0000000..493515e
--- /dev/null
+++ b/arch/arm/mach-w90x900/pci.c
@@ -0,0 +1,231 @@
+/*
+ * linux/arch/arm/mach-w90x900/pci.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+
+#include <mach/regs-pci.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gcr.h>
+
+#define EXTAL15M (0x03 << 2)
+#define CK33DIV5 (0x05 << 4)
+#define RESET_VAL1 0x20C0
+#define RESET_VAL2 0x20CF
+
+static int nuc900_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int *val)
+{
+ unsigned int v;
+
+ __raw_writel(devfn * 0x100 + (where & 0xfffffffc), REG_CFGADDR);
+ v = __raw_readl(REG_CFGDATA);
+ switch (size) {
+ case 1:
+ *val = (v >> ((where % 4) * 8)) & 0xff;
+ break;
+ case 2:
+ *val = (v >> ((where % 4) * 8)) & 0xffff;
+ break;
+ default:
+ *val = v;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int nuc900_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int val)
+{
+ unsigned int v;
+
+ __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
+
+ v = __raw_readl(REG_CFGDATA);
+
+ __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
+
+ switch (size) {
+ case 1:
+ v &= ~(0xff << (where % 4) * 8);
+ v |= (val << (where % 4) * 8);
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ case 2:
+ v &= ~(0xffff << (where % 4) * 8);
+ v |= (val << (where % 4) * 8);
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ case 4:
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nuc900_ops = {
+ .read = nuc900_read_config,
+ .write = nuc900_write_config,
+};
+
+static struct resource pci_io = {
+ .name = "NUC900 PCI IO",
+ .start = NUC900_PCI_IO_BASE,
+ .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_mem = {
+ .name = "nuc900 PCI Memory",
+ .start = NUC900_PCI_MEM_BASE,
+ .end = NUC900_PCI_MEM_BASE + NUC900_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static int __init pci_nuc900_setup_resources(struct resource **resource)
+{
+ int ret = 0;
+
+ ret = request_resource(&iomem_resource, &pci_io);
+ if (ret) {
+ printk(KERN_ERR "PCI: unable to allocate I/O "
+ "memory region (%d)\n", ret);
+ goto out;
+ }
+ ret = request_resource(&iomem_resource, &pci_mem);
+ if (ret) {
+ printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
+ "memory region (%d)\n", ret);
+ goto release_io_mem;
+ }
+
+ /*
+ * bus->resource[0] is the IO resource for this bus
+ * bus->resource[1] is the mem resource for this bus
+ * bus->resource[2] is the prefetch mem resource for this bus
+ */
+ resource[0] = &pci_io;
+ resource[1] = &pci_mem;
+ resource[2] = NULL;
+
+ goto out;
+
+ release_io_mem:
+ release_resource(&pci_io);
+ out:
+ return ret;
+}
+int __init pci_nuc900_setup(int nr, struct pci_sys_data *sys)
+{
+ int ret = 0;
+
+ if (nr == 0) {
+ sys->mem_offset = 0;
+ sys->io_offset = 0;
+ ret = pci_nuc900_setup_resources(sys->resource);
+ if (ret) {
+ printk(KERN_ERR "pci_versatile_setup:\
+ resources... oops?\n");
+ goto out;
+ }
+ } else {
+ printk(KERN_ERR "pci_versatile_setup:\
+ resources... nr == 0??\n");
+ goto out;
+ }
+ ret = 1;
+out:
+ return ret;
+}
+
+struct pci_bus *pci_nuc900_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_nuc900_ops, sys);
+}
+
+void __init pci_nuc900_preinit(void)
+{
+ /* CK33 from PLL0 */
+ __raw_writel(__raw_readl(REG_CLKSEL) & ~EXTAL15M, REG_CLKSEL);
+ /* PCI CLOCK = 200/6 = 33Mhz */
+ __raw_writel(((__raw_readl(REG_CLKDIV) &
+ (~(0xf<<4))) | CK33DIV5), REG_CLKDIV);
+
+ /* enable PCI clock */
+ __raw_writel(__raw_readl(REG_CLKEN) | 0x4, REG_CLKEN);
+
+ __raw_writel(RESET_VAL1, REG_PCICTR);
+
+ mdelay(100);
+
+ __raw_writel(RESET_VAL2, REG_PCICTR);
+
+ mdelay(200);
+}
+
+static inline int bridge_swizzle(int pin, unsigned int slot)
+{
+ return (pin + slot) & 3;
+}
+
+/*
+ * This routine handles multiple bridges.
+ */
+static u8 __init nuc900_swizzle(struct pci_dev *dev, u8 *pinp)
+{
+ int pin = *pinp;
+
+ if (pin == 0)
+ pin = 1;
+
+ pin -= 1;
+ while (dev->bus->self) {
+ pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
+ /*
+ * move up the chain of bridges, swizzling as we go.
+ */
+ dev = dev->bus->self;
+ }
+ *pinp = pin + 1;
+
+ return PCI_SLOT(dev->devfn);
+}
+
+static struct hw_pci nuc900_pci __initdata = {
+ .swizzle = nuc900_swizzle,
+ .setup = pci_nuc900_setup,
+ .nr_controllers = 1,
+ .scan = pci_nuc900_scan_bus,
+ .preinit = pci_nuc900_preinit,
+};
+
+static int __init nuc900_pci_init(void)
+{
+ pci_common_init(&nuc900_pci);
+ return 0;
+}
+
+subsys_initcall(nuc900_pci_init);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH] ARM: NUC900: Add PCI driver support for NUC960
2011-11-12 16:04 [PATCH] ARM: NUC900: Add PCI driver support for NUC960 Wan ZongShun
@ 2011-11-12 23:14 ` Russell King - ARM Linux
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
1 sibling, 0 replies; 6+ messages in thread
From: Russell King - ARM Linux @ 2011-11-12 23:14 UTC (permalink / raw)
To: linux-arm-kernel
On Sun, Nov 13, 2011 at 12:04:12AM +0800, Wan ZongShun wrote:
> +#define NUC900_PCI_IO_BASE 0xE0000000
> +#define NUC900_PCI_IO_END 0xE000FFFF
> +#define NUC900_PCI_IO_SIZE 0x10000
...
> +static struct resource pci_io = {
> + .name = "NUC900 PCI IO",
> + .start = NUC900_PCI_IO_BASE,
> + .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
> + .flags = IORESOURCE_IO,
> +};
...
> +static int __init pci_nuc900_setup_resources(struct resource **resource)
> +{
> + int ret = 0;
> +
> + ret = request_resource(&iomem_resource, &pci_io);
> + if (ret) {
> + printk(KERN_ERR "PCI: unable to allocate I/O "
> + "memory region (%d)\n", ret);
> + goto out;
> + }
You must not cross-register IO resources into MMIO resources. The
resource manager doesn't work like that. If you have an IO space which
is part of the MMIO space (which is true on all ARMs) then you should
register a MMIO resource reserving (iow, with IORESOURCE_BUSY, or
using request_mem_region()) to ensure that the region is properly
reserved in the MMIO space.
The IO resource stands entirely separately and is part of the
&ioport_resource tree.
> + ret = request_resource(&iomem_resource, &pci_mem);
> + if (ret) {
> + printk(KERN_ERR "PCI: unable to allocate non-prefetchable "
> + "memory region (%d)\n", ret);
> + goto release_io_mem;
> + }
> +
> + /*
> + * bus->resource[0] is the IO resource for this bus
> + * bus->resource[1] is the mem resource for this bus
> + * bus->resource[2] is the prefetch mem resource for this bus
> + */
> + resource[0] = &pci_io;
This seems wrong. IO space generally is 16-bit, not 32-bit, and
resource 0 is expected to be registered against the ioport_resource
or be the ioport_resource itself if it covers all 16-bit.
Moreover, if you have an IO space which is part of the MMIO space, it
is expected that your __io macro in mach/io.h appropriately translates
an inb(0) access to the start of your IO space emulation.
> + resource[1] = &pci_mem;
> + resource[2] = NULL;
> +
> + goto out;
> +
> + release_io_mem:
> + release_resource(&pci_io);
> + out:
> + return ret;
> +}
Missing blank line.
> +int __init pci_nuc900_setup(int nr, struct pci_sys_data *sys)
> +{
> + int ret = 0;
> +
> + if (nr == 0) {
> + sys->mem_offset = 0;
> + sys->io_offset = 0;
> + ret = pci_nuc900_setup_resources(sys->resource);
> + if (ret) {
> + printk(KERN_ERR "pci_versatile_setup:\
> + resources... oops?\n");
Don't continue strings with '\'. Plus this isn't versatile. Also try
printing the error code, which can aid debugging.
Try this instead:
pr_err("%s: failed to setup resources: %d\n",
__func__, ret);
> + goto out;
> + }
> + } else {
> + printk(KERN_ERR "pci_versatile_setup:\
> + resources... nr == 0??\n");
> + goto out;
> + }
> + ret = 1;
> +out:
> + return ret;
> +}
> +
> +struct pci_bus *pci_nuc900_scan_bus(int nr, struct pci_sys_data *sys)
> +{
> + return pci_scan_bus(sys->busnr, &pci_nuc900_ops, sys);
> +}
> +
> +void __init pci_nuc900_preinit(void)
> +{
> + /* CK33 from PLL0 */
> + __raw_writel(__raw_readl(REG_CLKSEL) & ~EXTAL15M, REG_CLKSEL);
> + /* PCI CLOCK = 200/6 = 33Mhz */
> + __raw_writel(((__raw_readl(REG_CLKDIV) &
> + (~(0xf<<4))) | CK33DIV5), REG_CLKDIV);
> +
> + /* enable PCI clock */
> + __raw_writel(__raw_readl(REG_CLKEN) | 0x4, REG_CLKEN);
> +
> + __raw_writel(RESET_VAL1, REG_PCICTR);
> +
> + mdelay(100);
> +
> + __raw_writel(RESET_VAL2, REG_PCICTR);
> +
> + mdelay(200);
> +}
> +
> +static inline int bridge_swizzle(int pin, unsigned int slot)
> +{
> + return (pin + slot) & 3;
> +}
> +
> +/*
> + * This routine handles multiple bridges.
> + */
> +static u8 __init nuc900_swizzle(struct pci_dev *dev, u8 *pinp)
> +{
> + int pin = *pinp;
> +
> + if (pin == 0)
> + pin = 1;
pin should never be zero - are you seeing such cases?
> +
> + pin -= 1;
> + while (dev->bus->self) {
> + pin = bridge_swizzle(pin, PCI_SLOT(dev->devfn));
> + /*
> + * move up the chain of bridges, swizzling as we go.
> + */
> + dev = dev->bus->self;
> + }
> + *pinp = pin + 1;
> +
> + return PCI_SLOT(dev->devfn);
> +}
Is there a reason the standard swizzle (pci_common_swizzle) doesn't work
for you?
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH V2] ARM: NUC900: Add PCI driver support for NUC960
2011-11-12 16:04 [PATCH] ARM: NUC900: Add PCI driver support for NUC960 Wan ZongShun
2011-11-12 23:14 ` Russell King - ARM Linux
@ 2011-11-14 7:13 ` Wan ZongShun
2011-11-14 11:44 ` Marek Vasut
` (2 more replies)
1 sibling, 3 replies; 6+ messages in thread
From: Wan ZongShun @ 2011-11-14 7:13 UTC (permalink / raw)
To: linux-arm-kernel
Modify PCI driver for nuc960 per Russell's comments as following:
(1)Use the common PCI swizzle API.
(2)Use the pr_err insteading of prink.
(3)Request the IO resource in ioport_resource tree.
Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
---
arch/arm/mach-w90x900/Kconfig | 1 +
arch/arm/mach-w90x900/Makefile | 3 +
arch/arm/mach-w90x900/include/mach/map.h | 4 +
arch/arm/mach-w90x900/include/mach/regs-pci.h | 37 +++++
arch/arm/mach-w90x900/nuc960.c | 2 +
arch/arm/mach-w90x900/pci.c | 195
+++++++++++++++++++++++++
6 files changed, 242 insertions(+), 0 deletions(-)
create mode 100644 arch/arm/mach-w90x900/include/mach/regs-pci.h
create mode 100644 arch/arm/mach-w90x900/pci.c
diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig
index 69bab32..17be262 100644
--- a/arch/arm/mach-w90x900/Kconfig
+++ b/arch/arm/mach-w90x900/Kconfig
@@ -41,6 +41,7 @@ menu "NUC960 Machines"
config MACH_W90N960EVB
bool "Nuvoton NUC960 Evaluation Board"
select CPU_NUC960
+ select PCI
help
Say Y here if you are using the Nuvoton NUC960EVB
diff --git a/arch/arm/mach-w90x900/Makefile b/arch/arm/mach-w90x900/Makefile
index 828c032..0c35800 100644
--- a/arch/arm/mach-w90x900/Makefile
+++ b/arch/arm/mach-w90x900/Makefile
@@ -17,3 +17,6 @@ obj-$(CONFIG_CPU_NUC960) += nuc960.o
obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o
obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o
obj-$(CONFIG_MACH_W90N960EVB) += mach-nuc960evb.o
+
+# Add pci support for nuc960, nuc920
+obj-$(CONFIG_PCI) += pci.o
diff --git a/arch/arm/mach-w90x900/include/mach/map.h
b/arch/arm/mach-w90x900/include/mach/map.h
index 1a20953..69f6c73 100644
--- a/arch/arm/mach-w90x900/include/mach/map.h
+++ b/arch/arm/mach-w90x900/include/mach/map.h
@@ -154,4 +154,8 @@
#define W90X900_PA_EMC (0xB0003000)
#define W90X900_SZ_EMC SZ_4K
+/* PCI interface controller */
+#define W90X900_VA_PCI W90X900_ADDR(0x00002000)
+#define W90X900_PA_PCI (0xB0002000)
+#define W90X900_SZ_PCI SZ_4K
#endif /* __ASM_ARCH_MAP_H */
diff --git a/arch/arm/mach-w90x900/include/mach/regs-pci.h
b/arch/arm/mach-w90x900/include/mach/regs-pci.h
new file mode 100644
index 0000000..d1975eb
--- /dev/null
+++ b/arch/arm/mach-w90x900/include/mach/regs-pci.h
@@ -0,0 +1,37 @@
+/*
+ * arch/arm/mach-w90x900/include/mach/regs-pci.h
+ *
+ * Copyright (c) 2011 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#ifndef __ASM_ARCH_REGS_PCI_H
+#define __ASM_ARCH_REGS_PCI_H
+
+#define PCI_BA W90X900_VA_PCI /* PCI Control */
+/* PCI Control Registers */
+#define REG_PCICTR (PCI_BA + 0x000)
+#define REG_PCISTR (PCI_BA + 0x004)
+#define REG_PCILATIMER (PCI_BA + 0x008)
+#define REG_PCIINTEN (PCI_BA + 0x010)
+#define REG_PCIINT (PCI_BA + 0x014)
+#define REG_CFGADDR (PCI_BA + 0x020)
+#define REG_CFGDATA (PCI_BA + 0x024)
+#define REG_PCIARB (PCI_BA + 0x04C)
+#define REG_PCIBIST (PCI_BA + 0x050)
+
+#define NUC900_PCI_IO_BASE 0xE0000000
+#define NUC900_PCI_IO_END 0xE000FFFF
+#define NUC900_PCI_IO_SIZE 0x10000
+
+#define NUC900_PCI_MEM_BASE 0xC0000000
+#define NUC900_PCI_MEM_END 0xDFFFEFFFF
+#define NUC900_PCI_MEM_SIZE 0x20000000
+
+#endif /* ___ASM_ARCH_REGS_PCI_H */
diff --git a/arch/arm/mach-w90x900/nuc960.c b/arch/arm/mach-w90x900/nuc960.c
index 8851a3a..0212964 100644
--- a/arch/arm/mach-w90x900/nuc960.c
+++ b/arch/arm/mach-w90x900/nuc960.c
@@ -19,6 +19,7 @@
#include <asm/mach/map.h>
#include <mach/hardware.h>
#include "cpu.h"
+#include "clock.h"
/* define specific CPU platform device */
@@ -30,6 +31,7 @@ static struct platform_device *nuc960_dev[] __initdata = {
/* define specific CPU platform io map */
static struct map_desc nuc960evb_iodesc[] __initdata = {
+ IODESC_ENT(PCI),
};
/*Init NUC960 evb io*/
diff --git a/arch/arm/mach-w90x900/pci.c b/arch/arm/mach-w90x900/pci.c
new file mode 100644
index 0000000..74095b0
--- /dev/null
+++ b/arch/arm/mach-w90x900/pci.c
@@ -0,0 +1,195 @@
+/*
+ * linux/arch/arm/mach-w90x900/pci.c
+ *
+ * Copyright (c) 2008 Nuvoton technology corporation.
+ *
+ * Wan ZongShun <mcuos.com@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation;version 2 of the License.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+
+#include <mach/hardware.h>
+#include <asm/irq.h>
+#include <asm/system.h>
+#include <asm/mach/pci.h>
+
+#include <mach/regs-pci.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-gcr.h>
+
+#define EXTAL15M (0x03 << 2)
+#define CK33DIV5 (0x05 << 4)
+#define RESET_VAL1 0x20C0
+#define RESET_VAL2 0x20CF
+
+static int nuc900_read_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int *val)
+{
+ unsigned int v;
+
+ __raw_writel(devfn * 0x100 + (where & 0xfffffffc), REG_CFGADDR);
+ v = __raw_readl(REG_CFGDATA);
+ switch (size) {
+ case 1:
+ *val = (v >> ((where % 4) * 8)) & 0xff;
+ break;
+ case 2:
+ *val = (v >> ((where % 4) * 8)) & 0xffff;
+ break;
+ default:
+ *val = v;
+ break;
+ }
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+
+static int nuc900_write_config(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, unsigned int val)
+{
+ unsigned int v;
+
+ __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
+
+ v = __raw_readl(REG_CFGDATA);
+
+ __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
+
+ switch (size) {
+ case 1:
+ v &= ~(0xff << (where % 4) * 8);
+ v |= (val << (where % 4) * 8);
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ case 2:
+ v &= ~(0xffff << (where % 4) * 8);
+ v |= (val << (where % 4) * 8);
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ case 4:
+ __raw_writel(val, REG_CFGDATA);
+ break;
+ }
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static struct pci_ops pci_nuc900_ops = {
+ .read = nuc900_read_config,
+ .write = nuc900_write_config,
+};
+
+static struct resource pci_io = {
+ .name = "NUC900 PCI IO",
+ .start = NUC900_PCI_IO_BASE,
+ .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource pci_mem = {
+ .name = "nuc900 PCI Memory",
+ .start = NUC900_PCI_MEM_BASE,
+ .end = NUC900_PCI_MEM_BASE + NUC900_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static int __init pci_nuc900_setup_resources(struct resource **resource)
+{
+ int ret = 0;
+
+ ret = request_resource(&ioport_resource, &pci_io);
+ if (ret) {
+ pr_err("%s: failed to request resources: %d\n", __func__, ret);
+ goto out;
+ }
+ ret = request_resource(&iomem_resource, &pci_mem);
+ if (ret) {
+ pr_err("%s: failed to request resources: %d\n", __func__, ret);
+ goto release_io_mem;
+ }
+
+ /*
+ * bus->resource[0] is the IO resource for this bus
+ * bus->resource[1] is the mem resource for this bus
+ * bus->resource[2] is the prefetch mem resource for this bus
+ */
+ resource[0] = &pci_io;
+ resource[1] = &pci_mem;
+ resource[2] = NULL;
+
+ goto out;
+
+ release_io_mem:
+ release_resource(&pci_io);
+ out:
+ return ret;
+}
+
+int __init pci_nuc900_setup(int nr, struct pci_sys_data *sys)
+{
+ int ret = 0;
+
+ if (nr > 0)
+ return 0;
+
+ sys->mem_offset = 0;
+ sys->io_offset = 0;
+ ret = pci_nuc900_setup_resources(sys->resource);
+ if (ret)
+ pr_err("%s: failed to setup resources: %d\n", __func__, ret);
+
+ return !ret;
+}
+
+struct pci_bus *pci_nuc900_scan_bus(int nr, struct pci_sys_data *sys)
+{
+ return pci_scan_bus(sys->busnr, &pci_nuc900_ops, sys);
+}
+
+void __init pci_nuc900_preinit(void)
+{
+ /* CK33 from PLL0 */
+ __raw_writel(__raw_readl(REG_CLKSEL) & ~EXTAL15M, REG_CLKSEL);
+ /* PCI CLOCK = 200/6 = 33Mhz */
+ __raw_writel(((__raw_readl(REG_CLKDIV) &
+ (~(0xf<<4))) | CK33DIV5), REG_CLKDIV);
+
+ /* enable PCI clock */
+ __raw_writel(__raw_readl(REG_CLKEN) | 0x4, REG_CLKEN);
+
+ __raw_writel(RESET_VAL1, REG_PCICTR);
+
+ mdelay(100);
+
+ __raw_writel(RESET_VAL2, REG_PCICTR);
+
+ mdelay(200);
+}
+
+static struct hw_pci nuc900_pci __initdata = {
+ .swizzle = pci_std_swizzle,
+ .setup = pci_nuc900_setup,
+ .nr_controllers = 1,
+ .scan = pci_nuc900_scan_bus,
+ .preinit = pci_nuc900_preinit,
+};
+
+static int __init nuc900_pci_init(void)
+{
+ pci_common_init(&nuc900_pci);
+ return 0;
+}
+
+subsys_initcall(nuc900_pci_init);
--
1.7.0.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH V2] ARM: NUC900: Add PCI driver support for NUC960
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
@ 2011-11-14 11:44 ` Marek Vasut
2011-11-15 17:30 ` Russell King - ARM Linux
2011-11-15 20:54 ` Arnd Bergmann
2 siblings, 0 replies; 6+ messages in thread
From: Marek Vasut @ 2011-11-14 11:44 UTC (permalink / raw)
To: linux-arm-kernel
> Modify PCI driver for nuc960 per Russell's comments as following:
> (1)Use the common PCI swizzle API.
> (2)Use the pr_err insteading of prink.
> (3)Request the IO resource in ioport_resource tree.
>
> Signed-off-by: Wan ZongShun <mcuos.com@gmail.com>
>
> ---
> arch/arm/mach-w90x900/Kconfig | 1 +
> arch/arm/mach-w90x900/Makefile | 3 +
> arch/arm/mach-w90x900/include/mach/map.h | 4 +
> arch/arm/mach-w90x900/include/mach/regs-pci.h | 37 +++++
> arch/arm/mach-w90x900/nuc960.c | 2 +
> arch/arm/mach-w90x900/pci.c | 195
> +++++++++++++++++++++++++
> 6 files changed, 242 insertions(+), 0 deletions(-)
> create mode 100644 arch/arm/mach-w90x900/include/mach/regs-pci.h
> create mode 100644 arch/arm/mach-w90x900/pci.c
>
> diff --git a/arch/arm/mach-w90x900/Kconfig b/arch/arm/mach-w90x900/Kconfig
> index 69bab32..17be262 100644
> --- a/arch/arm/mach-w90x900/Kconfig
> +++ b/arch/arm/mach-w90x900/Kconfig
> @@ -41,6 +41,7 @@ menu "NUC960 Machines"
> config MACH_W90N960EVB
> bool "Nuvoton NUC960 Evaluation Board"
> select CPU_NUC960
> + select PCI
> help
> Say Y here if you are using the Nuvoton NUC960EVB
>
> diff --git a/arch/arm/mach-w90x900/Makefile
> b/arch/arm/mach-w90x900/Makefile index 828c032..0c35800 100644
> --- a/arch/arm/mach-w90x900/Makefile
> +++ b/arch/arm/mach-w90x900/Makefile
> @@ -17,3 +17,6 @@ obj-$(CONFIG_CPU_NUC960) += nuc960.o
> obj-$(CONFIG_MACH_W90P910EVB) += mach-nuc910evb.o
> obj-$(CONFIG_MACH_W90P950EVB) += mach-nuc950evb.o
> obj-$(CONFIG_MACH_W90N960EVB) += mach-nuc960evb.o
> +
> +# Add pci support for nuc960, nuc920
> +obj-$(CONFIG_PCI) += pci.o
> diff --git a/arch/arm/mach-w90x900/include/mach/map.h
> b/arch/arm/mach-w90x900/include/mach/map.h
> index 1a20953..69f6c73 100644
> --- a/arch/arm/mach-w90x900/include/mach/map.h
> +++ b/arch/arm/mach-w90x900/include/mach/map.h
> @@ -154,4 +154,8 @@
> #define W90X900_PA_EMC (0xB0003000)
> #define W90X900_SZ_EMC SZ_4K
>
> +/* PCI interface controller */
> +#define W90X900_VA_PCI W90X900_ADDR(0x00002000)
> +#define W90X900_PA_PCI (0xB0002000)
> +#define W90X900_SZ_PCI SZ_4K
> #endif /* __ASM_ARCH_MAP_H */
> diff --git a/arch/arm/mach-w90x900/include/mach/regs-pci.h
> b/arch/arm/mach-w90x900/include/mach/regs-pci.h
> new file mode 100644
> index 0000000..d1975eb
> --- /dev/null
> +++ b/arch/arm/mach-w90x900/include/mach/regs-pci.h
> @@ -0,0 +1,37 @@
> +/*
> + * arch/arm/mach-w90x900/include/mach/regs-pci.h
> + *
> + * Copyright (c) 2011 Nuvoton technology corporation.
> + *
> + * Wan ZongShun <mcuos.com@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation;version 2 of the License.
> + *
> + */
> +
> +#ifndef __ASM_ARCH_REGS_PCI_H
> +#define __ASM_ARCH_REGS_PCI_H
> +
> +#define PCI_BA W90X900_VA_PCI /* PCI Control */
> +/* PCI Control Registers */
> +#define REG_PCICTR (PCI_BA + 0x000)
> +#define REG_PCISTR (PCI_BA + 0x004)
> +#define REG_PCILATIMER (PCI_BA + 0x008)
> +#define REG_PCIINTEN (PCI_BA + 0x010)
> +#define REG_PCIINT (PCI_BA + 0x014)
> +#define REG_CFGADDR (PCI_BA + 0x020)
> +#define REG_CFGDATA (PCI_BA + 0x024)
> +#define REG_PCIARB (PCI_BA + 0x04C)
> +#define REG_PCIBIST (PCI_BA + 0x050)
> +
> +#define NUC900_PCI_IO_BASE 0xE0000000
> +#define NUC900_PCI_IO_END 0xE000FFFF
> +#define NUC900_PCI_IO_SIZE 0x10000
> +
> +#define NUC900_PCI_MEM_BASE 0xC0000000
> +#define NUC900_PCI_MEM_END 0xDFFFEFFFF
> +#define NUC900_PCI_MEM_SIZE 0x20000000
> +
> +#endif /* ___ASM_ARCH_REGS_PCI_H */
> diff --git a/arch/arm/mach-w90x900/nuc960.c
> b/arch/arm/mach-w90x900/nuc960.c index 8851a3a..0212964 100644
> --- a/arch/arm/mach-w90x900/nuc960.c
> +++ b/arch/arm/mach-w90x900/nuc960.c
> @@ -19,6 +19,7 @@
> #include <asm/mach/map.h>
> #include <mach/hardware.h>
> #include "cpu.h"
> +#include "clock.h"
>
> /* define specific CPU platform device */
>
> @@ -30,6 +31,7 @@ static struct platform_device *nuc960_dev[] __initdata =
> { /* define specific CPU platform io map */
>
> static struct map_desc nuc960evb_iodesc[] __initdata = {
> + IODESC_ENT(PCI),
> };
>
> /*Init NUC960 evb io*/
> diff --git a/arch/arm/mach-w90x900/pci.c b/arch/arm/mach-w90x900/pci.c
> new file mode 100644
> index 0000000..74095b0
> --- /dev/null
> +++ b/arch/arm/mach-w90x900/pci.c
> @@ -0,0 +1,195 @@
> +/*
> + * linux/arch/arm/mach-w90x900/pci.c
> + *
> + * Copyright (c) 2008 Nuvoton technology corporation.
> + *
> + * Wan ZongShun <mcuos.com@gmail.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation;version 2 of the License.
> + *
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/pci.h>
> +#include <linux/ioport.h>
> +#include <linux/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/init.h>
> +#include <linux/io.h>
> +#include <linux/delay.h>
> +
> +#include <mach/hardware.h>
> +#include <asm/irq.h>
> +#include <asm/system.h>
> +#include <asm/mach/pci.h>
> +
> +#include <mach/regs-pci.h>
> +#include <mach/regs-clock.h>
> +#include <mach/regs-gcr.h>
> +
> +#define EXTAL15M (0x03 << 2)
> +#define CK33DIV5 (0x05 << 4)
> +#define RESET_VAL1 0x20C0
> +#define RESET_VAL2 0x20CF
> +
> +static int nuc900_read_config(struct pci_bus *bus, unsigned int devfn,
> + int where, int size, unsigned int *val)
> +{
> + unsigned int v;
> +
> + __raw_writel(devfn * 0x100 + (where & 0xfffffffc), REG_CFGADDR);
> + v = __raw_readl(REG_CFGDATA);
> + switch (size) {
> + case 1:
> + *val = (v >> ((where % 4) * 8)) & 0xff;
> + break;
> + case 2:
> + *val = (v >> ((where % 4) * 8)) & 0xffff;
> + break;
> + default:
case 4 ? Default case should error out.
> + *val = v;
> + break;
> + }
> +
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +
> +static int nuc900_write_config(struct pci_bus *bus, unsigned int devfn,
> + int where, int size, unsigned int val)
> +{
> + unsigned int v;
> +
> + __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
> +
> + v = __raw_readl(REG_CFGDATA);
> +
> + __raw_writel(devfn * 0x100 + where, REG_CFGADDR);
> +
> + switch (size) {
> + case 1:
> + v &= ~(0xff << (where % 4) * 8);
> + v |= (val << (where % 4) * 8);
> + __raw_writel(val, REG_CFGDATA);
> + break;
> + case 2:
> + v &= ~(0xffff << (where % 4) * 8);
> + v |= (val << (where % 4) * 8);
> + __raw_writel(val, REG_CFGDATA);
> + break;
> + case 4:
> + __raw_writel(val, REG_CFGDATA);
> + break;
> + }
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static struct pci_ops pci_nuc900_ops = {
> + .read = nuc900_read_config,
> + .write = nuc900_write_config,
> +};
> +
> +static struct resource pci_io = {
> + .name = "NUC900 PCI IO",
> + .start = NUC900_PCI_IO_BASE,
> + .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
> + .flags = IORESOURCE_IO,
> +};
> +
> +static struct resource pci_mem = {
> + .name = "nuc900 PCI Memory",
> + .start = NUC900_PCI_MEM_BASE,
> + .end = NUC900_PCI_MEM_BASE + NUC900_PCI_MEM_SIZE - 1,
> + .flags = IORESOURCE_MEM,
> +};
> +
> +static int __init pci_nuc900_setup_resources(struct resource **resource)
> +{
> + int ret = 0;
> +
> + ret = request_resource(&ioport_resource, &pci_io);
> + if (ret) {
> + pr_err("%s: failed to request resources: %d\n", __func__, ret);
> + goto out;
> + }
newline
> + ret = request_resource(&iomem_resource, &pci_mem);
> + if (ret) {
> + pr_err("%s: failed to request resources: %d\n", __func__, ret);
> + goto release_io_mem;
> + }
> +
> + /*
> + * bus->resource[0] is the IO resource for this bus
> + * bus->resource[1] is the mem resource for this bus
> + * bus->resource[2] is the prefetch mem resource for this bus
> + */
> + resource[0] = &pci_io;
> + resource[1] = &pci_mem;
> + resource[2] = NULL;
> +
> + goto out;
> +
> + release_io_mem:
> + release_resource(&pci_io);
> + out:
> + return ret;
> +}
> +
> +int __init pci_nuc900_setup(int nr, struct pci_sys_data *sys)
> +{
> + int ret = 0;
> +
> + if (nr > 0)
> + return 0;
pr_err() missing in this if ?
> +
> + sys->mem_offset = 0;
> + sys->io_offset = 0;
> + ret = pci_nuc900_setup_resources(sys->resource);
> + if (ret)
> + pr_err("%s: failed to setup resources: %d\n", __func__, ret);
> +
> + return !ret;
> +}
> +
> +struct pci_bus *pci_nuc900_scan_bus(int nr, struct pci_sys_data *sys)
> +{
> + return pci_scan_bus(sys->busnr, &pci_nuc900_ops, sys);
> +}
> +
> +void __init pci_nuc900_preinit(void)
> +{
> + /* CK33 from PLL0 */
> + __raw_writel(__raw_readl(REG_CLKSEL) & ~EXTAL15M, REG_CLKSEL);
> + /* PCI CLOCK = 200/6 = 33Mhz */
> + __raw_writel(((__raw_readl(REG_CLKDIV) &
> + (~(0xf<<4))) | CK33DIV5), REG_CLKDIV);
> +
> + /* enable PCI clock */
> + __raw_writel(__raw_readl(REG_CLKEN) | 0x4, REG_CLKEN);
What's this magic 0x4?
> +
> + __raw_writel(RESET_VAL1, REG_PCICTR);
> +
> + mdelay(100);
> +
> + __raw_writel(RESET_VAL2, REG_PCICTR);
> +
> + mdelay(200);
> +}
> +
> +static struct hw_pci nuc900_pci __initdata = {
> + .swizzle = pci_std_swizzle,
> + .setup = pci_nuc900_setup,
> + .nr_controllers = 1,
> + .scan = pci_nuc900_scan_bus,
> + .preinit = pci_nuc900_preinit,
> +};
> +
> +static int __init nuc900_pci_init(void)
> +{
> + pci_common_init(&nuc900_pci);
> + return 0;
> +}
> +
> +subsys_initcall(nuc900_pci_init);
Reviewed-by: Marek Vasut <marek.vasut@gmail.com>
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH V2] ARM: NUC900: Add PCI driver support for NUC960
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
2011-11-14 11:44 ` Marek Vasut
@ 2011-11-15 17:30 ` Russell King - ARM Linux
2011-11-15 20:54 ` Arnd Bergmann
2 siblings, 0 replies; 6+ messages in thread
From: Russell King - ARM Linux @ 2011-11-15 17:30 UTC (permalink / raw)
To: linux-arm-kernel
On Mon, Nov 14, 2011 at 03:13:31PM +0800, Wan ZongShun wrote:
> +#define NUC900_PCI_MEM_BASE 0xC0000000
> +#define NUC900_PCI_MEM_END 0xDFFFEFFFF
> +#define NUC900_PCI_MEM_SIZE 0x20000000
NUC900_PCI_MEM_END has more than 32 bits.
> +#define NUC900_PCI_IO_BASE 0xE0000000
> +#define NUC900_PCI_IO_END 0xE000FFFF
> +#define NUC900_PCI_IO_SIZE 0x10000
...
> +static struct resource pci_io = {
> + .name = "NUC900 PCI IO",
> + .start = NUC900_PCI_IO_BASE,
> + .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
> + .flags = IORESOURCE_IO,
> +};
...
> +static int __init pci_nuc900_setup_resources(struct resource **resource)
> +{
> + int ret = 0;
> +
> + ret = request_resource(&ioport_resource, &pci_io);
> + if (ret) {
> + pr_err("%s: failed to request resources: %d\n", __func__, ret);
> + goto out;
> + }
...
> + /*
> + * bus->resource[0] is the IO resource for this bus
> + * bus->resource[1] is the mem resource for this bus
> + * bus->resource[2] is the prefetch mem resource for this bus
> + */
> + resource[0] = &pci_io;
> + resource[1] = &pci_mem;
> + resource[2] = NULL;
This is better, but still not correct.
1. in mach/io.h:
-#define IO_SPACE_LIMIT 0xffffffff
+#define IO_SPACE_LIMIT 0xffff
-#define __io(a) __typesafe_io(a)
+#define __io(a) ((void __iomem __force *)(a) + VA_OF_IO_SPACE)
where VA_OF_IO_SPACE is correctly named and typed.
2. set resource[0] = &ioport_resource and get rid of pci_io entirely.
3. if (!request_mem_region(PA_OF_IO_SPACE, 64K, "PCI IO emulation space"))
pr_warn("Unable to request PCI IO space\n");
in your pre-init function.
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH V2] ARM: NUC900: Add PCI driver support for NUC960
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
2011-11-14 11:44 ` Marek Vasut
2011-11-15 17:30 ` Russell King - ARM Linux
@ 2011-11-15 20:54 ` Arnd Bergmann
2 siblings, 0 replies; 6+ messages in thread
From: Arnd Bergmann @ 2011-11-15 20:54 UTC (permalink / raw)
To: linux-arm-kernel
On Monday 14 November 2011, Wan ZongShun wrote:
> diff --git a/arch/arm/mach-w90x900/include/mach/regs-pci.h
> b/arch/arm/mach-w90x900/include/mach/regs-pci.h
> new file mode 100644
> index 0000000..d1975eb
> --- /dev/null
> +++ b/arch/arm/mach-w90x900/include/mach/regs-pci.h
> @@ -0,0 +1,37 @@
> +#define PCI_BA W90X900_VA_PCI /* PCI Control */
> +/* PCI Control Registers */
> +#define REG_PCICTR (PCI_BA + 0x000)
> +#define REG_PCISTR (PCI_BA + 0x004)
> +#define REG_PCILATIMER (PCI_BA + 0x008)
> +#define REG_PCIINTEN (PCI_BA + 0x010)
> +#define REG_PCIINT (PCI_BA + 0x014)
> +#define REG_CFGADDR (PCI_BA + 0x020)
> +#define REG_CFGDATA (PCI_BA + 0x024)
> +#define REG_PCIARB (PCI_BA + 0x04C)
> +#define REG_PCIBIST (PCI_BA + 0x050)
These should not be used outside of your pci.c file, so just move the
definitions there.
> +#define NUC900_PCI_IO_BASE 0xE0000000
> +#define NUC900_PCI_IO_END 0xE000FFFF
> +#define NUC900_PCI_IO_SIZE 0x10000
Whereas these should probably go in your mach/map.h file and follow the
naming conventions used there, e.g.
#define W90X900_VA_PCI_IO W90X900_ADDR(0xsomewhere)
#define W90X900_PA_PCI_IO 0xE0000000
#define W90X900_SZ_PCI_IO 0x10000
so you can map the I/O window along with the other static mappings.
This goes along with changing your __io() definition to
#define __io(a) (((a) & IO_SPACE_LIMIT) + W90X900_VA_PCI_IO)
> +#define NUC900_PCI_MEM_BASE 0xC0000000
> +#define NUC900_PCI_MEM_END 0xDFFFEFFFF
> +#define NUC900_PCI_MEM_SIZE 0x20000000
This probably fits there, too, so you can remove the pci header file.
> diff --git a/arch/arm/mach-w90x900/nuc960.c b/arch/arm/mach-w90x900/nuc960.c
> index 8851a3a..0212964 100644
> --- a/arch/arm/mach-w90x900/nuc960.c
> +++ b/arch/arm/mach-w90x900/nuc960.c
> @@ -19,6 +19,7 @@
> #include <asm/mach/map.h>
> #include <mach/hardware.h>
> #include "cpu.h"
> +#include "clock.h"
>
> /* define specific CPU platform device */
>
> @@ -30,6 +31,7 @@ static struct platform_device *nuc960_dev[] __initdata = {
> /* define specific CPU platform io map */
>
> static struct map_desc nuc960evb_iodesc[] __initdata = {
> + IODESC_ENT(PCI),
> };
It seems that you don't currently map the I/O window, which is a bug
and means that you cannot use any card with PIO resources.
> +static int nuc900_read_config(struct pci_bus *bus, unsigned int devfn,
> + int where, int size, unsigned int *val)
> +{
> + unsigned int v;
> +
> + __raw_writel(devfn * 0x100 + (where & 0xfffffffc), REG_CFGADDR);
> + v = __raw_readl(REG_CFGDATA);
> + switch (size) {
Please use writel_relaxed/readl_relaxed instead of the __raw versions
for new code.
> +static struct pci_ops pci_nuc900_ops = {
> + .read = nuc900_read_config,
> + .write = nuc900_write_config,
> +};
> +
> +static struct resource pci_io = {
> + .name = "NUC900 PCI IO",
> + .start = NUC900_PCI_IO_BASE,
> + .end = NUC900_PCI_IO_BASE + NUC900_PCI_IO_SIZE - 1,
> + .flags = IORESOURCE_IO,
> +};
As Russell mentioned, the I/O space window itself is not an IORESOURCE_IO
resource. Just register it using request_mem_region, or at least make
it IORESOURCE_MEM and register it to iomem_resource.
> + __raw_writel(RESET_VAL1, REG_PCICTR);
> +
> + mdelay(100);
> +
> + __raw_writel(RESET_VAL2, REG_PCICTR);
> +
> + mdelay(200);
> +}
Using mdelay is rather rude, especially in code that is actually allowed to
sleep. Better use msleep here, or (even better) find a way to detect from
the hardware if you have waited long enough, using a small msleep to back
off while waiting.
Not specific to your driver, I'm wondering whether we should start moving
pci host drivers to some new directory under drivers/pci/, similar to what
we do in other subsystems. Unfortunately, pci host drivers are rather
architecture specific right now, so we might have to clean that up first:
If we move a PCI host driver to an arch independent place, it should
really work on anything that has the same hardware interface.
Arnd
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2011-11-15 20:54 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-12 16:04 [PATCH] ARM: NUC900: Add PCI driver support for NUC960 Wan ZongShun
2011-11-12 23:14 ` Russell King - ARM Linux
2011-11-14 7:13 ` [PATCH V2] " Wan ZongShun
2011-11-14 11:44 ` Marek Vasut
2011-11-15 17:30 ` Russell King - ARM Linux
2011-11-15 20:54 ` Arnd Bergmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).