2010-11-20 14:27:21

by Hans Ulli Kroll

[permalink] [raw]
Subject: [PATCH] ARM: Gemini: Add support for PCI Bus

Add support for PCI Bus on Gemini Devices SL3516

Signed-off-by: Hans Ulli Kroll <[email protected]>
---
arch/arm/Kconfig | 1 +
arch/arm/mach-gemini/Makefile | 2 +
arch/arm/mach-gemini/include/mach/hardware.h | 8 +
arch/arm/mach-gemini/include/mach/irqs.h | 7 +-
arch/arm/mach-gemini/mm.c | 5 +
arch/arm/mach-gemini/pci.c | 319 ++++++++++++++++++++++++++
6 files changed, 340 insertions(+), 2 deletions(-)
create mode 100644 arch/arm/mach-gemini/pci.c

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a19a526..5d4b398 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -307,6 +307,7 @@ config ARCH_GEMINI
select CPU_FA526
select ARCH_REQUIRE_GPIOLIB
select ARCH_USES_GETTIMEOFFSET
+ select PCI
help
Support for the Cortina Systems Gemini family SoCs

diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile
index c5b24b9..c263f48 100644
--- a/arch/arm/mach-gemini/Makefile
+++ b/arch/arm/mach-gemini/Makefile
@@ -6,6 +6,8 @@

obj-y := irq.o mm.o time.o devices.o gpio.o

+obj-$(CONFIG_PCI) += pci.o
+
# Board-specific support
obj-$(CONFIG_MACH_NAS4220B) += board-nas4220b.o
obj-$(CONFIG_MACH_RUT100) += board-rut1xx.o
diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
index 213a4fc..38c530f 100644
--- a/arch/arm/mach-gemini/include/mach/hardware.h
+++ b/arch/arm/mach-gemini/include/mach/hardware.h
@@ -71,4 +71,12 @@
*/
#define IO_ADDRESS(x) ((((x) & 0xFFF00000) >> 4) | ((x) & 0x000FFFFF) | 0xF0000000)

+/*
+ * PCI subsystem macros
+ */
+#define PCIBIOS_MIN_IO 0x00000100
+#define PCIBIOS_MIN_MEM 0x00000000
+
+#define pcibios_assign_all_busses() 1
+
#endif
diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h
index 06bc47e..c737673 100644
--- a/arch/arm/mach-gemini/include/mach/irqs.h
+++ b/arch/arm/mach-gemini/include/mach/irqs.h
@@ -43,11 +43,14 @@

#define NORMAL_IRQ_NUM 32

-#define GPIO_IRQ_BASE NORMAL_IRQ_NUM
+#define PCI_IRQ_BASE NORMAL_IRQ_NUM
+#define PCI_IRQ_NUM 4
+
+#define GPIO_IRQ_BASE (NORMAL_IRQ_NUM + PCI_IRQ_NUM)
#define GPIO_IRQ_NUM (3 * 32)

#define ARCH_TIMER_IRQ IRQ_TIMER2

-#define NR_IRQS (NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
+#define NR_IRQS (NORMAL_IRQ_NUM + PCI_IRQ_NUM + GPIO_IRQ_NUM)

#endif /* __MACH_IRQS_H__ */
diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
index 5194824..2bf20b2 100644
--- a/arch/arm/mach-gemini/mm.c
+++ b/arch/arm/mach-gemini/mm.c
@@ -59,6 +59,11 @@ static struct map_desc gemini_io_desc[] __initdata = {
.length = SZ_512K,
.type = MT_DEVICE,
}, {
+ .virtual = IO_ADDRESS(GEMINI_PCI_IO_BASE),
+ .pfn = __phys_to_pfn(GEMINI_PCI_IO_BASE),
+ .length = SZ_512K,
+ .type = MT_DEVICE,
+ }, {
.virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
.pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
.length = SZ_512K,
diff --git a/arch/arm/mach-gemini/pci.c b/arch/arm/mach-gemini/pci.c
new file mode 100644
index 0000000..1064b05
--- /dev/null
+++ b/arch/arm/mach-gemini/pci.c
@@ -0,0 +1,319 @@
+/*
+ * Support for Gemini PCI Controller
+ *
+ * Copyright (C) 2009 Janos Laube <[email protected]>
+ * Copyright (C) 2009 Paulius Zaleckas <[email protected]>
+ *
+ * based on SL2312 PCI controller code
+ * Storlink (C) 2003
+ *
+ * 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/kernel.h>
+#include <linux/pci.h>
+#include <linux/irq.h>
+
+#include <asm/mach/pci.h>
+#include <asm/gpio.h>
+
+#include <mach/irqs.h>
+
+#define GEMINI_PCI_IOSIZE_1M 0x0000
+
+#define GEMINI_PCI_PMC 0x40
+#define GEMINI_PCI_PMCSR 0x44
+#define GEMINI_PCI_CTRL1 0x48
+#define GEMINI_PCI_CTRL2 0x4C
+#define GEMINI_PCI_MEM1_BASE_SIZE 0x50
+#define GEMINI_PCI_MEM2_BASE_SIZE 0x54
+#define GEMINI_PCI_MEM3_BASE_SIZE 0x58
+
+#define PCI_CTRL2_INTSTS_OFFSET 28
+#define PCI_CTRL2_INTMASK_OFFSET 22
+
+#define GEMINI_PCI_DMA_MASK 0xFFF00000
+#define GEMINI_PCI_DMA_MEM1_BASE 0x00000000
+#define GEMINI_PCI_DMA_MEM2_BASE 0x00000000
+#define GEMINI_PCI_DMA_MEM3_BASE 0x00000000
+#define GEMINI_PCI_DMA_MEM1_SIZE 7
+#define GEMINI_PCI_DMA_MEM2_SIZE 6
+#define GEMINI_PCI_DMA_MEM3_SIZE 6
+
+#define PCI_CONF_ENABLE (1 << 31)
+#define PCI_CONF_WHERE(r) ((r) & 0xFC)
+#define PCI_CONF_BUS(b) (((b) & 0xFF) << 16)
+#define PCI_CONF_DEVICE(d) (((d) & 0x1F) << 11)
+#define PCI_CONF_FUNCTION(f) (((f) & 0x07) << 8)
+
+#define PCI_IOSIZE_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE))
+#define PCI_PROT_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x04)
+#define PCI_CTRL_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x08)
+#define PCI_SOFTRST_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x10)
+#define PCI_CONFIG_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x28)
+#define PCI_DATA_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x2C)
+
+
+static DEFINE_SPINLOCK(gemini_pci_lock);
+
+static struct resource gemini_pci_resource_io = {
+ .name = "PCI I/O Space",
+ .start = IO_ADDRESS(GEMINI_PCI_IO_BASE),
+ .end = IO_ADDRESS(GEMINI_PCI_IO_BASE) + SZ_1M - 1,
+ .flags = IORESOURCE_IO,
+};
+
+static struct resource gemini_pci_resource_mem = {
+ .name = "PCI Memory Space",
+ .start = GEMINI_PCI_MEM_BASE,
+ .end = GEMINI_PCI_MEM_BASE + SZ_128M - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static int gemini_pci_read_config(struct pci_bus *bus, unsigned int fn,
+ int config, int size, u32 *value)
+{
+ unsigned long irq_flags;
+
+ spin_lock_irqsave(&gemini_pci_lock, irq_flags);
+
+ __raw_writel(PCI_CONF_BUS(bus->number) |
+ PCI_CONF_DEVICE(PCI_SLOT(fn)) |
+ PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
+ PCI_CONF_WHERE(config) |
+ PCI_CONF_ENABLE,
+ PCI_CONFIG_REG);
+
+ *value = __raw_readl(PCI_DATA_REG);
+
+ if (size == 1)
+ *value = (*value >> (8 * (config & 3))) & 0xFF;
+ else if (size == 2)
+ *value = (*value >> (8 * (config & 3))) & 0xFFFF;
+
+ spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
+
+ dev_dbg(&bus->dev,
+ "[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
+ PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int gemini_pci_write_config(struct pci_bus *bus, unsigned int fn,
+ int config, int size, u32 value)
+{
+ unsigned long irq_flags = 0;
+ int ret = PCIBIOS_SUCCESSFUL;
+
+ dev_dbg(&bus->dev,
+ "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
+ PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
+
+ spin_lock_irqsave(&gemini_pci_lock, irq_flags);
+
+ __raw_writel(PCI_CONF_BUS(bus->number) |
+ PCI_CONF_DEVICE(PCI_SLOT(fn)) |
+ PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
+ PCI_CONF_WHERE(config) |
+ PCI_CONF_ENABLE,
+ PCI_CONFIG_REG);
+
+ switch (size) {
+ case 4:
+ __raw_writel(value, PCI_DATA_REG);
+ break;
+ case 2:
+ __raw_writew(value, PCI_DATA_REG + (config & 3));
+ break;
+ case 1:
+ __raw_writeb(value, PCI_DATA_REG + (config & 3));
+ break;
+ default:
+ ret = PCIBIOS_BAD_REGISTER_NUMBER;
+ }
+
+ spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
+
+ return ret;
+}
+
+static struct pci_ops gemini_pci_ops = {
+ .read = gemini_pci_read_config,
+ .write = gemini_pci_write_config,
+};
+
+static int __init gemini_pci_request_resources(struct pci_sys_data *sys)
+{
+ if (request_resource(&ioport_resource, &gemini_pci_resource_io))
+ goto bad_resources;
+ if (request_resource(&iomem_resource, &gemini_pci_resource_mem))
+ goto bad_resources;
+
+ sys->resource[0] = &gemini_pci_resource_io;
+ sys->resource[1] = &gemini_pci_resource_mem;
+ sys->resource[2] = 0;
+
+ return 0;
+
+bad_resources:
+ pr_err("Gemini PCI: request_resource() failed. "
+ "Abort PCI bus enumeration.\n");
+ return -1;
+}
+
+static int __init gemini_pci_setup(int nr, struct pci_sys_data *sys)
+{
+ unsigned int cmd;
+
+ if ((nr > 0) || gemini_pci_request_resources(sys))
+ return 0;
+
+ /* setup I/O space to 1MB size */
+ __raw_writel(GEMINI_PCI_IOSIZE_1M, PCI_IOSIZE_REG);
+
+ /* setup hostbridge */
+ cmd = __raw_readl(PCI_CTRL_REG);
+ cmd |= PCI_COMMAND_IO;
+ cmd |= PCI_COMMAND_MEMORY;
+ cmd |= PCI_COMMAND_MASTER;
+ __raw_writel(cmd, PCI_CTRL_REG);
+
+ return 1;
+}
+
+static struct pci_bus __init *gemini_pci_scan_bus(int nr,
+ struct pci_sys_data *sys)
+{
+ unsigned int reg = 0;
+ struct pci_bus *bus = 0;
+
+ bus = pci_scan_bus(nr, &gemini_pci_ops, sys);
+ if (bus) {
+ dev_dbg(&bus->dev, "setting up PCI DMA\n");
+ reg = (GEMINI_PCI_DMA_MEM1_BASE & GEMINI_PCI_DMA_MASK)
+ | (GEMINI_PCI_DMA_MEM1_SIZE << 16);
+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM1_BASE_SIZE,
+ 4, reg);
+ reg = (GEMINI_PCI_DMA_MEM2_BASE & GEMINI_PCI_DMA_MASK)
+ | (GEMINI_PCI_DMA_MEM2_SIZE << 16);
+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM2_BASE_SIZE,
+ 4, reg);
+ reg = (GEMINI_PCI_DMA_MEM3_BASE & GEMINI_PCI_DMA_MASK)
+ | (GEMINI_PCI_DMA_MEM3_SIZE << 16);
+ gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM3_BASE_SIZE,
+ 4, reg);
+ }
+
+ return bus;
+}
+
+/* Should work with all boards based on original Storlink EVB */
+static int __init gemini_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (slot < 9 || slot > 12)
+ return -1;
+
+ return PCI_IRQ_BASE + (((slot - 9) + (pin - 1)) & 0x3);
+}
+
+static struct hw_pci gemini_hw_pci __initdata = {
+ .nr_controllers = 1,
+ .setup = gemini_pci_setup,
+ .scan = gemini_pci_scan_bus,
+ .swizzle = pci_std_swizzle,
+ .map_irq = gemini_pci_map_irq,
+};
+
+/* we need this for muxed PCI interrupts handling */
+static struct pci_bus bogus_pci_bus;
+
+static void gemini_pci_ack_irq(unsigned int irq)
+{
+ unsigned int reg;
+
+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
+ reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
+ reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTSTS_OFFSET);
+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
+}
+
+static void gemini_pci_mask_irq(unsigned int irq)
+{
+ unsigned int reg;
+
+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
+ reg &= ~((0xF << PCI_CTRL2_INTSTS_OFFSET)
+ | (1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET)));
+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
+}
+
+static void gemini_pci_unmask_irq(unsigned int irq)
+{
+ unsigned int reg;
+
+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
+ reg &= ~(0xF << PCI_CTRL2_INTSTS_OFFSET);
+ reg |= 1 << (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET);
+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
+}
+
+static void gemini_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+ unsigned int pci_irq_no, irq_stat, reg, i;
+
+ gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, &reg);
+ irq_stat = reg >> PCI_CTRL2_INTSTS_OFFSET;
+
+ for (i = 0; i < 4; i++) {
+
+ if ((irq_stat & (1 << i)) == 0)
+ continue;
+
+ pci_irq_no = PCI_IRQ_BASE + i;
+
+ BUG_ON(!(irq_desc[pci_irq_no].handle_irq));
+ irq_desc[pci_irq_no].handle_irq(pci_irq_no,
+ &irq_desc[pci_irq_no]);
+ }
+}
+
+static struct irq_chip gemini_pci_irq_chip = {
+ .name = "PCI",
+ .ack = gemini_pci_ack_irq,
+ .mask = gemini_pci_mask_irq,
+ .unmask = gemini_pci_unmask_irq,
+};
+
+static int __init gemini_pci_init(void)
+{
+ int i;
+
+ for (i = 72; i <= 95; i++)
+ gpio_request(i, "PCI");
+
+ /* initialize our bogus bus */
+ dev_set_name(&bogus_pci_bus.dev, "PCI IRQ handler");
+ bogus_pci_bus.number = 0;
+
+ /* mask and clear all interrupts */
+ gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2 + 2, 2,
+ 0xF000);
+
+ for (i = PCI_IRQ_BASE; i < PCI_IRQ_BASE + 4; i++) {
+ set_irq_chip(i, &gemini_pci_irq_chip);
+ set_irq_handler(i, handle_level_irq);
+ set_irq_flags(i, IRQF_VALID);
+ }
+
+ set_irq_chained_handler(IRQ_PCI, gemini_pci_irq_handler);
+
+ pci_common_init(&gemini_hw_pci);
+
+ return 0;
+}
+
+subsys_initcall(gemini_pci_init);
--
1.7.3.2


2010-11-20 19:30:16

by Paulius Zaleckas

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On 11/20/2010 04:27 PM, Hans Ulli Kroll wrote:
> Add support for PCI Bus on Gemini Devices SL3516
>
> Signed-off-by: Hans Ulli Kroll<[email protected]>
> ---
> arch/arm/Kconfig | 1 +
> arch/arm/mach-gemini/Makefile | 2 +
> arch/arm/mach-gemini/include/mach/hardware.h | 8 +
> arch/arm/mach-gemini/include/mach/irqs.h | 7 +-
> arch/arm/mach-gemini/mm.c | 5 +
> arch/arm/mach-gemini/pci.c | 319 ++++++++++++++++++++++++++
> 6 files changed, 340 insertions(+), 2 deletions(-)
> create mode 100644 arch/arm/mach-gemini/pci.c
>
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index a19a526..5d4b398 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -307,6 +307,7 @@ config ARCH_GEMINI
> select CPU_FA526
> select ARCH_REQUIRE_GPIOLIB
> select ARCH_USES_GETTIMEOFFSET
> + select PCI
> help
> Support for the Cortina Systems Gemini family SoCs
>
> diff --git a/arch/arm/mach-gemini/Makefile b/arch/arm/mach-gemini/Makefile
> index c5b24b9..c263f48 100644
> --- a/arch/arm/mach-gemini/Makefile
> +++ b/arch/arm/mach-gemini/Makefile
> @@ -6,6 +6,8 @@
>
> obj-y := irq.o mm.o time.o devices.o gpio.o
>
> +obj-$(CONFIG_PCI) += pci.o
> +
> # Board-specific support
> obj-$(CONFIG_MACH_NAS4220B) += board-nas4220b.o
> obj-$(CONFIG_MACH_RUT100) += board-rut1xx.o
> diff --git a/arch/arm/mach-gemini/include/mach/hardware.h b/arch/arm/mach-gemini/include/mach/hardware.h
> index 213a4fc..38c530f 100644
> --- a/arch/arm/mach-gemini/include/mach/hardware.h
> +++ b/arch/arm/mach-gemini/include/mach/hardware.h
> @@ -71,4 +71,12 @@
> */
> #define IO_ADDRESS(x) ((((x)& 0xFFF00000)>> 4) | ((x)& 0x000FFFFF) | 0xF0000000)
>
> +/*
> + * PCI subsystem macros
> + */
> +#define PCIBIOS_MIN_IO 0x00000100
> +#define PCIBIOS_MIN_MEM 0x00000000
> +
> +#define pcibios_assign_all_busses() 1
> +
> #endif
> diff --git a/arch/arm/mach-gemini/include/mach/irqs.h b/arch/arm/mach-gemini/include/mach/irqs.h
> index 06bc47e..c737673 100644
> --- a/arch/arm/mach-gemini/include/mach/irqs.h
> +++ b/arch/arm/mach-gemini/include/mach/irqs.h
> @@ -43,11 +43,14 @@
>
> #define NORMAL_IRQ_NUM 32
>
> -#define GPIO_IRQ_BASE NORMAL_IRQ_NUM
> +#define PCI_IRQ_BASE NORMAL_IRQ_NUM
> +#define PCI_IRQ_NUM 4
> +
> +#define GPIO_IRQ_BASE (NORMAL_IRQ_NUM + PCI_IRQ_NUM)
> #define GPIO_IRQ_NUM (3 * 32)
>
> #define ARCH_TIMER_IRQ IRQ_TIMER2
>
> -#define NR_IRQS (NORMAL_IRQ_NUM + GPIO_IRQ_NUM)
> +#define NR_IRQS (NORMAL_IRQ_NUM + PCI_IRQ_NUM + GPIO_IRQ_NUM)
>
> #endif /* __MACH_IRQS_H__ */
> diff --git a/arch/arm/mach-gemini/mm.c b/arch/arm/mach-gemini/mm.c
> index 5194824..2bf20b2 100644
> --- a/arch/arm/mach-gemini/mm.c
> +++ b/arch/arm/mach-gemini/mm.c
> @@ -59,6 +59,11 @@ static struct map_desc gemini_io_desc[] __initdata = {
> .length = SZ_512K,
> .type = MT_DEVICE,
> }, {
> + .virtual = IO_ADDRESS(GEMINI_PCI_IO_BASE),
> + .pfn = __phys_to_pfn(GEMINI_PCI_IO_BASE),
> + .length = SZ_512K,
> + .type = MT_DEVICE,
> + }, {
> .virtual = IO_ADDRESS(GEMINI_FLASH_CTRL_BASE),
> .pfn = __phys_to_pfn(GEMINI_FLASH_CTRL_BASE),
> .length = SZ_512K,
> diff --git a/arch/arm/mach-gemini/pci.c b/arch/arm/mach-gemini/pci.c
> new file mode 100644
> index 0000000..1064b05
> --- /dev/null
> +++ b/arch/arm/mach-gemini/pci.c
> @@ -0,0 +1,319 @@
> +/*
> + * Support for Gemini PCI Controller
> + *
> + * Copyright (C) 2009 Janos Laube<[email protected]>
> + * Copyright (C) 2009 Paulius Zaleckas<[email protected]>

Please update my e-mail. This one is long gone...

> + *
> + * based on SL2312 PCI controller code
> + * Storlink (C) 2003
> + *
> + * 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/kernel.h>
> +#include<linux/pci.h>
> +#include<linux/irq.h>
> +
> +#include<asm/mach/pci.h>
> +#include<asm/gpio.h>
> +
> +#include<mach/irqs.h>
> +
> +#define GEMINI_PCI_IOSIZE_1M 0x0000
> +
> +#define GEMINI_PCI_PMC 0x40
> +#define GEMINI_PCI_PMCSR 0x44
> +#define GEMINI_PCI_CTRL1 0x48
> +#define GEMINI_PCI_CTRL2 0x4C
> +#define GEMINI_PCI_MEM1_BASE_SIZE 0x50
> +#define GEMINI_PCI_MEM2_BASE_SIZE 0x54
> +#define GEMINI_PCI_MEM3_BASE_SIZE 0x58
> +
> +#define PCI_CTRL2_INTSTS_OFFSET 28
> +#define PCI_CTRL2_INTMASK_OFFSET 22
> +
> +#define GEMINI_PCI_DMA_MASK 0xFFF00000
> +#define GEMINI_PCI_DMA_MEM1_BASE 0x00000000
> +#define GEMINI_PCI_DMA_MEM2_BASE 0x00000000
> +#define GEMINI_PCI_DMA_MEM3_BASE 0x00000000
> +#define GEMINI_PCI_DMA_MEM1_SIZE 7
> +#define GEMINI_PCI_DMA_MEM2_SIZE 6
> +#define GEMINI_PCI_DMA_MEM3_SIZE 6
> +
> +#define PCI_CONF_ENABLE (1<< 31)
> +#define PCI_CONF_WHERE(r) ((r)& 0xFC)
> +#define PCI_CONF_BUS(b) (((b)& 0xFF)<< 16)
> +#define PCI_CONF_DEVICE(d) (((d)& 0x1F)<< 11)
> +#define PCI_CONF_FUNCTION(f) (((f)& 0x07)<< 8)
> +
> +#define PCI_IOSIZE_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE))
> +#define PCI_PROT_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x04)
> +#define PCI_CTRL_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x08)
> +#define PCI_SOFTRST_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x10)
> +#define PCI_CONFIG_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x28)
> +#define PCI_DATA_REG (IO_ADDRESS(GEMINI_PCI_IO_BASE) + 0x2C)
> +
> +
> +static DEFINE_SPINLOCK(gemini_pci_lock);
> +
> +static struct resource gemini_pci_resource_io = {
> + .name = "PCI I/O Space",
> + .start = IO_ADDRESS(GEMINI_PCI_IO_BASE),
> + .end = IO_ADDRESS(GEMINI_PCI_IO_BASE) + SZ_1M - 1,
> + .flags = IORESOURCE_IO,
> +};
> +
> +static struct resource gemini_pci_resource_mem = {
> + .name = "PCI Memory Space",
> + .start = GEMINI_PCI_MEM_BASE,
> + .end = GEMINI_PCI_MEM_BASE + SZ_128M - 1,
> + .flags = IORESOURCE_MEM,
> +};
> +
> +static int gemini_pci_read_config(struct pci_bus *bus, unsigned int fn,
> + int config, int size, u32 *value)
> +{
> + unsigned long irq_flags;
> +
> + spin_lock_irqsave(&gemini_pci_lock, irq_flags);
> +
> + __raw_writel(PCI_CONF_BUS(bus->number) |
> + PCI_CONF_DEVICE(PCI_SLOT(fn)) |
> + PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
> + PCI_CONF_WHERE(config) |
> + PCI_CONF_ENABLE,
> + PCI_CONFIG_REG);
> +
> + *value = __raw_readl(PCI_DATA_REG);
> +
> + if (size == 1)
> + *value = (*value>> (8 * (config& 3)))& 0xFF;
> + else if (size == 2)
> + *value = (*value>> (8 * (config& 3)))& 0xFFFF;
> +
> + spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
> +
> + dev_dbg(&bus->dev,
> + "[read] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
> + PCI_SLOT(fn), PCI_FUNC(fn), config, size, *value);
> +
> + return PCIBIOS_SUCCESSFUL;
> +}
> +
> +static int gemini_pci_write_config(struct pci_bus *bus, unsigned int fn,
> + int config, int size, u32 value)
> +{
> + unsigned long irq_flags = 0;
> + int ret = PCIBIOS_SUCCESSFUL;
> +
> + dev_dbg(&bus->dev,
> + "[write] slt: %.2d, fnc: %d, cnf: 0x%.2X, val (%d bytes): 0x%.8X\n",
> + PCI_SLOT(fn), PCI_FUNC(fn), config, size, value);
> +
> + spin_lock_irqsave(&gemini_pci_lock, irq_flags);
> +
> + __raw_writel(PCI_CONF_BUS(bus->number) |
> + PCI_CONF_DEVICE(PCI_SLOT(fn)) |
> + PCI_CONF_FUNCTION(PCI_FUNC(fn)) |
> + PCI_CONF_WHERE(config) |
> + PCI_CONF_ENABLE,
> + PCI_CONFIG_REG);
> +
> + switch (size) {
> + case 4:
> + __raw_writel(value, PCI_DATA_REG);
> + break;
> + case 2:
> + __raw_writew(value, PCI_DATA_REG + (config& 3));
> + break;
> + case 1:
> + __raw_writeb(value, PCI_DATA_REG + (config& 3));
> + break;
> + default:
> + ret = PCIBIOS_BAD_REGISTER_NUMBER;
> + }
> +
> + spin_unlock_irqrestore(&gemini_pci_lock, irq_flags);
> +
> + return ret;
> +}
> +
> +static struct pci_ops gemini_pci_ops = {
> + .read = gemini_pci_read_config,
> + .write = gemini_pci_write_config,
> +};
> +
> +static int __init gemini_pci_request_resources(struct pci_sys_data *sys)
> +{
> + if (request_resource(&ioport_resource,&gemini_pci_resource_io))
> + goto bad_resources;
> + if (request_resource(&iomem_resource,&gemini_pci_resource_mem))
> + goto bad_resources;
> +
> + sys->resource[0] =&gemini_pci_resource_io;
> + sys->resource[1] =&gemini_pci_resource_mem;
> + sys->resource[2] = 0;
> +
> + return 0;
> +
> +bad_resources:
> + pr_err("Gemini PCI: request_resource() failed. "
> + "Abort PCI bus enumeration.\n");
> + return -1;
> +}
> +
> +static int __init gemini_pci_setup(int nr, struct pci_sys_data *sys)
> +{
> + unsigned int cmd;
> +
> + if ((nr> 0) || gemini_pci_request_resources(sys))
> + return 0;
> +
> + /* setup I/O space to 1MB size */
> + __raw_writel(GEMINI_PCI_IOSIZE_1M, PCI_IOSIZE_REG);
> +
> + /* setup hostbridge */
> + cmd = __raw_readl(PCI_CTRL_REG);
> + cmd |= PCI_COMMAND_IO;
> + cmd |= PCI_COMMAND_MEMORY;
> + cmd |= PCI_COMMAND_MASTER;
> + __raw_writel(cmd, PCI_CTRL_REG);
> +
> + return 1;
> +}
> +
> +static struct pci_bus __init *gemini_pci_scan_bus(int nr,
> + struct pci_sys_data *sys)
> +{
> + unsigned int reg = 0;
> + struct pci_bus *bus = 0;
> +
> + bus = pci_scan_bus(nr,&gemini_pci_ops, sys);
> + if (bus) {
> + dev_dbg(&bus->dev, "setting up PCI DMA\n");
> + reg = (GEMINI_PCI_DMA_MEM1_BASE& GEMINI_PCI_DMA_MASK)
> + | (GEMINI_PCI_DMA_MEM1_SIZE<< 16);
> + gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM1_BASE_SIZE,
> + 4, reg);
> + reg = (GEMINI_PCI_DMA_MEM2_BASE& GEMINI_PCI_DMA_MASK)
> + | (GEMINI_PCI_DMA_MEM2_SIZE<< 16);
> + gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM2_BASE_SIZE,
> + 4, reg);
> + reg = (GEMINI_PCI_DMA_MEM3_BASE& GEMINI_PCI_DMA_MASK)
> + | (GEMINI_PCI_DMA_MEM3_SIZE<< 16);
> + gemini_pci_write_config(bus, 0, GEMINI_PCI_MEM3_BASE_SIZE,
> + 4, reg);
> + }
> +
> + return bus;
> +}
> +
> +/* Should work with all boards based on original Storlink EVB */
> +static int __init gemini_pci_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
> +{
> + if (slot< 9 || slot> 12)
> + return -1;
> +
> + return PCI_IRQ_BASE + (((slot - 9) + (pin - 1))& 0x3);
> +}
> +
> +static struct hw_pci gemini_hw_pci __initdata = {
> + .nr_controllers = 1,
> + .setup = gemini_pci_setup,
> + .scan = gemini_pci_scan_bus,
> + .swizzle = pci_std_swizzle,
> + .map_irq = gemini_pci_map_irq,
> +};
> +
> +/* we need this for muxed PCI interrupts handling */
> +static struct pci_bus bogus_pci_bus;
> +
> +static void gemini_pci_ack_irq(unsigned int irq)
> +{
> + unsigned int reg;
> +
> + gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4,&reg);
> + reg&= ~(0xF<< PCI_CTRL2_INTSTS_OFFSET);
> + reg |= 1<< (irq - PCI_IRQ_BASE + PCI_CTRL2_INTSTS_OFFSET);
> + gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
> +}
> +
> +static void gemini_pci_mask_irq(unsigned int irq)
> +{
> + unsigned int reg;
> +
> + gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4,&reg);
> + reg&= ~((0xF<< PCI_CTRL2_INTSTS_OFFSET)
> + | (1<< (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET)));
> + gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
> +}
> +
> +static void gemini_pci_unmask_irq(unsigned int irq)
> +{
> + unsigned int reg;
> +
> + gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4,&reg);
> + reg&= ~(0xF<< PCI_CTRL2_INTSTS_OFFSET);
> + reg |= 1<< (irq - PCI_IRQ_BASE + PCI_CTRL2_INTMASK_OFFSET);
> + gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4, reg);
> +}
> +
> +static void gemini_pci_irq_handler(unsigned int irq, struct irq_desc *desc)
> +{
> + unsigned int pci_irq_no, irq_stat, reg, i;
> +
> + gemini_pci_read_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2, 4,&reg);
> + irq_stat = reg>> PCI_CTRL2_INTSTS_OFFSET;
> +
> + for (i = 0; i< 4; i++) {
> +
> + if ((irq_stat& (1<< i)) == 0)
> + continue;
> +
> + pci_irq_no = PCI_IRQ_BASE + i;
> +
> + BUG_ON(!(irq_desc[pci_irq_no].handle_irq));
> + irq_desc[pci_irq_no].handle_irq(pci_irq_no,
> + &irq_desc[pci_irq_no]);
> + }
> +}
> +
> +static struct irq_chip gemini_pci_irq_chip = {
> + .name = "PCI",
> + .ack = gemini_pci_ack_irq,
> + .mask = gemini_pci_mask_irq,
> + .unmask = gemini_pci_unmask_irq,
> +};
> +
> +static int __init gemini_pci_init(void)
> +{
> + int i;
> +
> + for (i = 72; i<= 95; i++)
> + gpio_request(i, "PCI");
> +
> + /* initialize our bogus bus */
> + dev_set_name(&bogus_pci_bus.dev, "PCI IRQ handler");
> + bogus_pci_bus.number = 0;
> +
> + /* mask and clear all interrupts */
> + gemini_pci_write_config(&bogus_pci_bus, 0, GEMINI_PCI_CTRL2 + 2, 2,
> + 0xF000);
> +
> + for (i = PCI_IRQ_BASE; i< PCI_IRQ_BASE + 4; i++) {
> + set_irq_chip(i,&gemini_pci_irq_chip);
> + set_irq_handler(i, handle_level_irq);
> + set_irq_flags(i, IRQF_VALID);
> + }
> +
> + set_irq_chained_handler(IRQ_PCI, gemini_pci_irq_handler);
> +
> + pci_common_init(&gemini_hw_pci);
> +
> + return 0;
> +}
> +
> +subsys_initcall(gemini_pci_init);

2010-11-26 11:18:25

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Sat, Nov 20, 2010 at 09:30:07PM +0200, Paulius Zaleckas wrote:
>> +#include<linux/kernel.h>
>> +#include<linux/pci.h>
>> +#include<linux/irq.h>
>> +
>> +#include<asm/mach/pci.h>
>> +#include<asm/gpio.h>

linux/gpio.h, not asm/gpio.h please.

2010-11-26 11:57:05

by Michał Mirosław

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

2010/11/20 Hans Ulli Kroll <[email protected]>:
> Add support for PCI Bus on Gemini Devices SL3516
>
> Signed-off-by: Hans Ulli Kroll <[email protected]>
> ---
[...]
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index a19a526..5d4b398 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -307,6 +307,7 @@ config ARCH_GEMINI
> ? ? ? ?select CPU_FA526
> ? ? ? ?select ARCH_REQUIRE_GPIOLIB
> ? ? ? ?select ARCH_USES_GETTIMEOFFSET
> + ? ? ? select PCI
> ? ? ? ?help
> ? ? ? ? ?Support for the Cortina Systems Gemini family SoCs
>
[...]

I think it's better to add ARCH_GEMINI to CONFIG_PCI dependencies.
AFAIK IB-4220B NAS does not use PCI and doesn't need all that code.
Board support entries could select PCI if the board is useless without
it.

Best Regards,
Micha? Miros?aw

2010-11-27 12:24:43

by Hans Ulli Kroll

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus



On Fri, 26 Nov 2010, Micha? Miros?aw wrote:

> 2010/11/20 Hans Ulli Kroll <[email protected]>:
> > Add support for PCI Bus on Gemini Devices SL3516
> >
> > Signed-off-by: Hans Ulli Kroll <[email protected]>
> > ---
> [...]
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index a19a526..5d4b398 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -307,6 +307,7 @@ config ARCH_GEMINI
> > ? ? ? ?select CPU_FA526
> > ? ? ? ?select ARCH_REQUIRE_GPIOLIB
> > ? ? ? ?select ARCH_USES_GETTIMEOFFSET
> > + ? ? ? select PCI
> > ? ? ? ?help
> > ? ? ? ? ?Support for the Cortina Systems Gemini family SoCs
> >
> [...]
>
> I think it's better to add ARCH_GEMINI to CONFIG_PCI dependencies.
> AFAIK IB-4220B NAS does not use PCI and doesn't need all that code.
> Board support entries could select PCI if the board is useless without
> it.
>

I know this, I have some.

There are many boards with PCI i.e WBD 222.
Other ARM devices uses the same select inside ARCH_*
I don't want to pollute drivers/pci/Kconfig.

Ulli

2010-11-27 13:01:27

by Michał Mirosław

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

W dniu 27 listopada 2010 13:16 u?ytkownik Hans Ulli Kroll
<[email protected]> napisa?:
> On Fri, 26 Nov 2010, Micha? Miros?aw wrote:
>> 2010/11/20 Hans Ulli Kroll <[email protected]>:
>> > Add support for PCI Bus on Gemini Devices SL3516
>> >
>> > Signed-off-by: Hans Ulli Kroll <[email protected]>
>> > ---
>> [...]
>> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
>> > index a19a526..5d4b398 100644
>> > --- a/arch/arm/Kconfig
>> > +++ b/arch/arm/Kconfig
>> > @@ -307,6 +307,7 @@ config ARCH_GEMINI
>> > ? ? ? ?select CPU_FA526
>> > ? ? ? ?select ARCH_REQUIRE_GPIOLIB
>> > ? ? ? ?select ARCH_USES_GETTIMEOFFSET
>> > + ? ? ? select PCI
>> > ? ? ? ?help
>> > ? ? ? ? ?Support for the Cortina Systems Gemini family SoCs
>> >
>> [...]
>> I think it's better to add ARCH_GEMINI to CONFIG_PCI dependencies.
>> AFAIK IB-4220B NAS does not use PCI and doesn't need all that code.
>> Board support entries could select PCI if the board is useless without
>> it.
> I know this, I have some.
>
> There are many boards with PCI i.e WBD 222.
> Other ARM devices uses the same select inside ARCH_*
> I don't want to pollute drivers/pci/Kconfig.

I meant 'config PCI' entry in arch/arm/Kconfig, see following diff.

Best Regards,
Micha? Miros?aw

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index db524e7..74ea522 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1164,7 +1164,7 @@ config ISA_DMA_API
bool

config PCI
- bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+ bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||
ARCH_GEMINI
help
Find out whether you have a PCI motherboard. PCI is the name of a
bus system, i.e. the way the CPU talks to the other stuff inside

2010-11-27 15:39:45

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Saturday 27 November 2010 14:01:20 Micha? Miros?aw wrote:
> diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> index db524e7..74ea522 100644
> --- a/arch/arm/Kconfig
> +++ b/arch/arm/Kconfig
> @@ -1164,7 +1164,7 @@ config ISA_DMA_API
> bool
>
> config PCI
> - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||
> ARCH_GEMINI
> help
> Find out whether you have a PCI motherboard. PCI is the name of a
> bus system, i.e. the way the CPU talks to the other stuff inside
>

This approach really does not scale as we add more boards to the list.

Better make a new CONFIG_HAVE_PCI option that you can select from the
individual boards, and make that the only dependency that CONFIG_PCI has.

Arnd

2010-11-29 08:13:11

by Hans Ulli Kroll

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus



On Sat, 27 Nov 2010, Arnd Bergmann wrote:

> On Saturday 27 November 2010 14:01:20 Micha? Miros?aw wrote:
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index db524e7..74ea522 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -1164,7 +1164,7 @@ config ISA_DMA_API
> > bool
> >
> > config PCI
> > - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> > + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||
> > ARCH_GEMINI
> > help
> > Find out whether you have a PCI motherboard. PCI is the name of a
> > bus system, i.e. the way the CPU talks to the other stuff inside
> >
>
> This approach really does not scale as we add more boards to the list.
>
> Better make a new CONFIG_HAVE_PCI option that you can select from the
> individual boards, and make that the only dependency that CONFIG_PCI has.
>
> Arnd
>
Good idea.
I write a patch for this.

Ulli

2010-11-29 14:22:29

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Sat, Nov 27, 2010 at 04:39:21PM +0100, Arnd Bergmann wrote:
> On Saturday 27 November 2010 14:01:20 Michał Mirosław wrote:
> > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > index db524e7..74ea522 100644
> > --- a/arch/arm/Kconfig
> > +++ b/arch/arm/Kconfig
> > @@ -1164,7 +1164,7 @@ config ISA_DMA_API
> > bool
> >
> > config PCI
> > - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> > + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||
> > ARCH_GEMINI
> > help
> > Find out whether you have a PCI motherboard. PCI is the name of a
> > bus system, i.e. the way the CPU talks to the other stuff inside
> >
>
> This approach really does not scale as we add more boards to the list.
>
> Better make a new CONFIG_HAVE_PCI option that you can select from the
> individual boards, and make that the only dependency that CONFIG_PCI has.

Be careful. There are two things going on here:

1. those which PCI support is configurable
2. those which always have PCI support

Making PCI "depend on HAVE_PCI" is wrong, and will throw up lots of
Kconfig warnings, as those platforms which always have PCI support
won't select HAVE_PCI - and making them do so such that "PCI support"
gets offered to them - with the only possible value being 'Y' is
silly.

So, rather than HAVE_PCI, it should be MIGHT_HAVE_PCI, and that
symbol needs to control whether the "PCI support" prompt is offered
to the user, not whether PCI is available or not.

2010-11-29 14:50:47

by Hans Ulli Kroll

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus



On Mon, 29 Nov 2010, Russell King - ARM Linux wrote:

> On Sat, Nov 27, 2010 at 04:39:21PM +0100, Arnd Bergmann wrote:
> > On Saturday 27 November 2010 14:01:20 Michał Mirosław wrote:
> > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
> > > index db524e7..74ea522 100644
> > > --- a/arch/arm/Kconfig
> > > +++ b/arch/arm/Kconfig
> > > @@ -1164,7 +1164,7 @@ config ISA_DMA_API
> > > bool
> > >
> > > config PCI
> > > - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> > > + bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX ||
> > > ARCH_GEMINI
> > > help
> > > Find out whether you have a PCI motherboard. PCI is the name of a
> > > bus system, i.e. the way the CPU talks to the other stuff inside
> > >
> >
> > This approach really does not scale as we add more boards to the list.
> >
> > Better make a new CONFIG_HAVE_PCI option that you can select from the
> > individual boards, and make that the only dependency that CONFIG_PCI has.
>
> Be careful. There are two things going on here:
>
> 1. those which PCI support is configurable
> 2. those which always have PCI support
>
> Making PCI "depend on HAVE_PCI" is wrong, and will throw up lots of
> Kconfig warnings, as those platforms which always have PCI support
> won't select HAVE_PCI - and making them do so such that "PCI support"
> gets offered to them - with the only possible value being 'Y' is
> silly.
>
> So, rather than HAVE_PCI, it should be MIGHT_HAVE_PCI, and that
> symbol needs to control whether the "PCI support" prompt is offered
> to the user, not whether PCI is available or not.
>

Here's my idea

bool "PIC support" if MIGHT_HAVE_PCI

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a19a526..614cf2f 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -34,6 +34,9 @@ config ARM
config HAVE_PWM
bool

+config MIGHT_HAVE_PCI
+ bool
+
config SYS_SUPPORTS_APM_EMULATION
bool

@@ -298,6 +301,7 @@ config ARCH_CNS3XXX
select CPU_V6
select GENERIC_CLOCKEVENTS
select ARM_GIC
+ select MIGHT_HAVE_PCI
select PCI_DOMAINS if PCI
help
Support for Cavium Networks CNS3XXX platform.
@@ -433,6 +437,7 @@ config ARCH_IXP4XX
select CPU_XSCALE
select GENERIC_GPIO
select GENERIC_CLOCKEVENTS
+ select MIGHT_HAVE_PCI
select DMABOUNCE if PCI
help
Support for Intel's IXP4XX (XScale) family of processors.
@@ -1164,7 +1169,7 @@ config ISA_DMA_API
bool

config PCI
- bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
+ bool "PCI support" if MIGHT_HAVE_PCI
help
Find out whether you have a PCI motherboard. PCI is the name of
a
bus system, i.e. the way the CPU talks to the other stuff inside
diff --git a/arch/arm/mach-cns3xxx/Kconfig b/arch/arm/mach-cns3xxx/Kconfig
index 9ebfcc4..29b13f2 100644
--- a/arch/arm/mach-cns3xxx/Kconfig
+++ b/arch/arm/mach-cns3xxx/Kconfig
@@ -3,6 +3,7 @@ menu "CNS3XXX platform type"

config MACH_CNS3420VB
bool "Support for CNS3420 Validation Board"
+ select MIGHT_HAVE_PCI
help
Include support for the Cavium Networks CNS3420 MPCore Platform
Baseboard.
diff --git a/arch/arm/mach-integrator/Kconfig
b/arch/arm/mach-integrator/Kconfig
index 27db275..769b0f1 100644
--- a/arch/arm/mach-integrator/Kconfig
+++ b/arch/arm/mach-integrator/Kconfig
@@ -4,6 +4,7 @@ menu "Integrator Options"

config ARCH_INTEGRATOR_AP
bool "Support Integrator/AP and Integrator/PP2 platforms"
+ select MIGHT_HAVE_PCI
help
Include support for the ARM(R) Integrator/AP and
Integrator/PP2 platforms.
diff --git a/arch/arm/mach-ks8695/Kconfig b/arch/arm/mach-ks8695/Kconfig
index fe0c82e..f5c39a8 100644
--- a/arch/arm/mach-ks8695/Kconfig
+++ b/arch/arm/mach-ks8695/Kconfig
@@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"

config MACH_KS8695
+++ b/arch/arm/mach-versatile/Kconfig
@@ -4,6 +4,7 @@ menu "Versatile platform type"
config ARCH_VERSATILE_PB
bool "Support Versatile/PB platform"
select CPU_ARM926T
+ select HAVE_PCI
default y
help
Include support for the ARM(R) Versatile/PB platform.bool
"KS8695 development board"
+ select MIGHT_HAVE_PCI
help
Say 'Y' here if you want your kernel to run on the original
Kendin-Micrel KS8695 development board.
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index dd235ec..716a2e1 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -94,6 +94,7 @@ config MACH_ARMCORE
select PXA27x
select IWMMXT
select PXA25x
+ select MIGHT_HAVE_PCI

config MACH_EM_X270
bool "CompuLab EM-x270 platform"
diff --git a/arch/arm/mach-versatile/Kconfig
b/arch/arm/mach-versatile/Kconfig
index c781f30..3f7b5e9 100644
--- a/arch/arm/mach-versatile/Kconfig
+++ b/arch/arm/mach-versatile/Kconfig
@@ -4,6 +4,7 @@ menu "Versatile platform type"
config ARCH_VERSATILE_PB
bool "Support Versatile/PB platform"
select CPU_ARM926T
+ select MIGHT_HAVE_PCI
default y
help
Include support for the ARM(R) Versatile/PB platform.


IF OK I send is a a patch on the list

Ulli

2010-11-29 15:50:47

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Monday 29 November 2010, Russell King - ARM Linux wrote:
> On Sat, Nov 27, 2010 at 04:39:21PM +0100, Arnd Bergmann wrote:
> > On Saturday 27 November 2010 14:01:20 Michał Mirosław wrote:
>
> Be careful. There are two things going on here:
>
> 1. those which PCI support is configurable
> 2. those which always have PCI support
>
> Making PCI "depend on HAVE_PCI" is wrong, and will throw up lots of
> Kconfig warnings, as those platforms which always have PCI support
> won't select HAVE_PCI - and making them do so such that "PCI support"
> gets offered to them - with the only possible value being 'Y' is
> silly.

We definitely need to be careful with combinations of select and
depends. The obvious danger is enabling two boards, one of which
requires PCI while the other one cannot deal with CONFIG_PCI=y.
As we get to more multiplatform builds, we have to eventually
solve this, along with the problem that certain PCI implementations
are currently mutually exclusive.

What behaviour do you want to see in a multiplatform build where
one board is known to have PCI, one may have it and a third
one cannot have PCI? Should it be enabled, disabled or
user-selected.

> So, rather than HAVE_PCI, it should be MIGHT_HAVE_PCI, and that
> symbol needs to control whether the "PCI support" prompt is offered
> to the user, not whether PCI is available or not.

Most architectures make PCI optional even though it is a bit silly
to disable it like on x86. There are a lot of other useful configuration
options that end up always enabled in practice.

The easiest way would be to always select HAVE_PCI (or MIGHT_HAVE_PCI
if you prefer the term) and make the default CONFIG_PCI default to
yes.

Or you could go fancy and have both HAVE_PCI and MIGHT_HAVE_PCI, with
each platform selecting at most one of the two and this

config PCI
bool "PCI support"
depends on MIGHT_HAVE_PCI && !HAVE_PCI
default HAVE_PCI

This way it will be silently turned on if one of the machines requires
PCI, but stay visible if the machines might want to disable PCI.

Arnd

2010-11-29 15:58:19

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Monday 29 November 2010, Hans Ulli Kroll wrote:
> @@ -1164,7 +1169,7 @@ config ISA_DMA_API
> bool
>
> config PCI
> - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> + bool "PCI support" if MIGHT_HAVE_PCI
> help
> Find out whether you have a PCI motherboard. PCI is the name of
> a
> bus system, i.e. the way the CPU talks to the other stuff inside

This does not solve the problem that Russell mentioned: existing platforms
select PCI unconditionally, e.g. Iop13XX, some IXP, Orion, Shark
and more. At the very least, these would need to also select MIGHT_HAVE_PCI
to avoid the warning.

> index fe0c82e..f5c39a8 100644
> --- a/arch/arm/mach-ks8695/Kconfig
> +++ b/arch/arm/mach-ks8695/Kconfig
> @@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
>
> config MACH_KS8695
> +++ b/arch/arm/mach-versatile/Kconfig
> @@ -4,6 +4,7 @@ menu "Versatile platform type"
> config ARCH_VERSATILE_PB
> bool "Support Versatile/PB platform"
> select CPU_ARM926T
> + select HAVE_PCI
> default y
> help
> Include support for the ARM(R) Versatile/PB platform.bool

Typo: you certainly meant MIGHT_HAVE_PCI here.

We still need to agree on what it should be doing, but otherwise this
is what I had in mind.

Arnd

2010-11-30 15:39:07

by Hans Ulli Kroll

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus



On Mon, 29 Nov 2010, Arnd Bergmann wrote:

> On Monday 29 November 2010, Hans Ulli Kroll wrote:
> > @@ -1164,7 +1169,7 @@ config ISA_DMA_API
> > bool
> >
> > config PCI
> > - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> > + bool "PCI support" if MIGHT_HAVE_PCI
> > help
> > Find out whether you have a PCI motherboard. PCI is the name of
> > a
> > bus system, i.e. the way the CPU talks to the other stuff inside
>
> This does not solve the problem that Russell mentioned: existing platforms
> select PCI unconditionally, e.g. Iop13XX, some IXP, Orion, Shark
> and more. At the very least, these would need to also select MIGHT_HAVE_PCI
> to avoid the warning.
>

so
select MIGHT_HAVE_PCI
in conjunction of
select PCI
on other almost platforms

> > index fe0c82e..f5c39a8 100644
> > --- a/arch/arm/mach-ks8695/Kconfig
> > +++ b/arch/arm/mach-ks8695/Kconfig
> > @@ -4,6 +4,7 @@ menu "Kendin/Micrel KS8695 Implementations"
> >
> > config MACH_KS8695
> > +++ b/arch/arm/mach-versatile/Kconfig
> > @@ -4,6 +4,7 @@ menu "Versatile platform type"
> > config ARCH_VERSATILE_PB
> > bool "Support Versatile/PB platform"
> > select CPU_ARM926T
> > + select HAVE_PCI
> > default y
> > help
> > Include support for the ARM(R) Versatile/PB platform.bool
>
> Typo: you certainly meant MIGHT_HAVE_PCI here.
>

Damn, I missed this.
HAVE_PCI was my first approach to do this.

> We still need to agree on what it should be doing, but otherwise this
> is what I had in mind.
>
> Arnd
>

2010-11-30 16:06:34

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Mon, Nov 29, 2010 at 04:57:53PM +0100, Arnd Bergmann wrote:
> On Monday 29 November 2010, Hans Ulli Kroll wrote:
> > @@ -1164,7 +1169,7 @@ config ISA_DMA_API
> > bool
> >
> > config PCI
> > - bool "PCI support" if ARCH_INTEGRATOR_AP || ARCH_VERSATILE_PB ||
> > ARCH_IXP4XX || ARCH_KS8695 || MACH_ARMCORE || ARCH_CNS3XXX
> > + bool "PCI support" if MIGHT_HAVE_PCI
> > help
> > Find out whether you have a PCI motherboard. PCI is the name of
> > a
> > bus system, i.e. the way the CPU talks to the other stuff inside
>
> This does not solve the problem that Russell mentioned: existing platforms
> select PCI unconditionally, e.g. Iop13XX, some IXP, Orion, Shark
> and more. At the very least, these would need to also select MIGHT_HAVE_PCI
> to avoid the warning.

No, the above is correct. What I was talking about was the difference
between these:

config PCI
bool "PCI support" if MIGHT_HAVE_PCI

and

config PCI
bool "PCI support"
depends on MIGHT_HAVE_PCI

In the first instance, PCI itself does not depend on MIGHT_HAVE_PCI.
MIGHT_HAVE_PCI controls whether the user is offered the "PCI support"
option.

In the second instance, PCI depends on MIGHT_HAVE_PCI, which must be
set to 'y' to offer the option _and_ also if PCI is selected.

We want the first behaviour. Platforms which must have PCI support can
continue to select PCI as they currently do, and leave the MIGHT_HAVE_PCI
option alone.

Platforms which may optionally have PCI support should select
MIGHT_HAVE_PCI instead.

2010-11-30 16:19:16

by Arnd Bergmann

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus

On Tuesday 30 November 2010, Russell King - ARM Linux wrote:
> No, the above is correct. What I was talking about was the difference
> between these:
>
> config PCI
> bool "PCI support" if MIGHT_HAVE_PCI
>
> and
>
> config PCI
> bool "PCI support"
> depends on MIGHT_HAVE_PCI
>
> In the first instance, PCI itself does not depend on MIGHT_HAVE_PCI.
> MIGHT_HAVE_PCI controls whether the user is offered the "PCI support"
> option.
>
> In the second instance, PCI depends on MIGHT_HAVE_PCI, which must be
> set to 'y' to offer the option and also if PCI is selected.

Right, I misread the patch as doing the wrong thing, thanks for
clearing that up.

> We want the first behaviour. Platforms which must have PCI support can
> continue to select PCI as they currently do, and leave the MIGHT_HAVE_PCI
> option alone.
>
> Platforms which may optionally have PCI support should select
> MIGHT_HAVE_PCI instead.

Yes, that sounds good.

Arnd

2010-12-01 15:05:21

by Hans Ulli Kroll

[permalink] [raw]
Subject: Re: [PATCH] ARM: Gemini: Add support for PCI Bus



On Tue, 30 Nov 2010, Arnd Bergmann wrote:

> On Tuesday 30 November 2010, Russell King - ARM Linux wrote:
> > No, the above is correct. What I was talking about was the difference
> > between these:
> >
> > config PCI
> > bool "PCI support" if MIGHT_HAVE_PCI
> >
> > and
> >
> > config PCI
> > bool "PCI support"
> > depends on MIGHT_HAVE_PCI
> >
> > In the first instance, PCI itself does not depend on MIGHT_HAVE_PCI.
> > MIGHT_HAVE_PCI controls whether the user is offered the "PCI support"
> > option.
> >
> > In the second instance, PCI depends on MIGHT_HAVE_PCI, which must be
> > set to 'y' to offer the option and also if PCI is selected.
>
> Right, I misread the patch as doing the wrong thing, thanks for
> clearing that up.
>
> > We want the first behaviour. Platforms which must have PCI support can
> > continue to select PCI as they currently do, and leave the MIGHT_HAVE_PCI
> > option alone.
> >
> > Platforms which may optionally have PCI support should select
> > MIGHT_HAVE_PCI instead.
>
> Yes, that sounds good.
>
> Arnd
>

OK.
I prepare some patch.

Ulli