From e2dbdc436b46250c8682ea57151a7afb45f271e1 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:21 +0100 Subject: MIPS: ath79: separate common PCI code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The 'pcibios_map_irq' and 'pcibios_plat_dev_init' are common functions and only instance one of them can be present in a single kernel. Currently these functions can be built only if the CONFIG_SOC_AR724X option is selected. However the ath79 platform contain support for the AR71XX SoCs,. The AR71XX SoCs have a differnet PCI controller, and those will require a different code. Move the common PCI code into a separeate file in order to be able to use that with other SoCs as well. Signed-off-by: Gabor Juhos Acked-by: René Bolldorf Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3485/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ath724x.c | 34 ---------------------------------- 1 file changed, 34 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c index a4dd24a4130b..1e810be22d26 100644 --- a/arch/mips/pci/pci-ath724x.c +++ b/arch/mips/pci/pci-ath724x.c @@ -9,7 +9,6 @@ */ #include -#include #define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) #define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) @@ -19,8 +18,6 @@ #define ATH724X_PCI_MEM_SIZE 0x08000000 static DEFINE_SPINLOCK(ath724x_pci_lock); -static struct ath724x_pci_data *pci_data; -static int pci_data_size; static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) @@ -133,37 +130,6 @@ static struct pci_controller ath724x_pci_controller = { .mem_resource = &ath724x_mem_resource, }; -void ath724x_pci_add_data(struct ath724x_pci_data *data, int size) -{ - pci_data = data; - pci_data_size = size; -} - -int __init pcibios_map_irq(const struct pci_dev *dev, uint8_t slot, uint8_t pin) -{ - unsigned int devfn = dev->devfn; - int irq = -1; - - if (devfn > pci_data_size - 1) - return irq; - - irq = pci_data[devfn].irq; - - return irq; -} - -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - unsigned int devfn = dev->devfn; - - if (devfn > pci_data_size - 1) - return PCIBIOS_DEVICE_NOT_FOUND; - - dev->dev.platform_data = pci_data[devfn].pdata; - - return PCIBIOS_SUCCESSFUL; -} - static int __init ath724x_pcibios_init(void) { register_pci_controller(&ath724x_pci_controller); -- cgit v1.2.3 From 659243ccaf296ae122c159d4c573f93561e1b8d6 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:23 +0100 Subject: MIPS: ath79: make ath724x_pcibios_init visible for external code MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: René Bolldorf Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3487/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-ath79/pci.h | 20 ++++++++++++++++++++ arch/mips/pci/pci-ath724x.c | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) create mode 100644 arch/mips/include/asm/mach-ath79/pci.h (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h new file mode 100644 index 000000000000..e0c4b53590f4 --- /dev/null +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -0,0 +1,20 @@ +/* + * Atheros 724x PCI support + * + * Copyright (C) 2011 René Bolldorf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#ifndef __ASM_MACH_ATH79_PCI_H +#define __ASM_MACH_ATH79_PCI_H + +#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) +int ath724x_pcibios_init(void); +#else +static inline int ath724x_pcibios_init(void) { return 0; } +#endif + +#endif /* __ASM_MACH_ATH79_PCI_H */ diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c index 1e810be22d26..be01b7f8d840 100644 --- a/arch/mips/pci/pci-ath724x.c +++ b/arch/mips/pci/pci-ath724x.c @@ -9,6 +9,7 @@ */ #include +#include #define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) #define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) @@ -130,7 +131,7 @@ static struct pci_controller ath724x_pci_controller = { .mem_resource = &ath724x_mem_resource, }; -static int __init ath724x_pcibios_init(void) +int __init ath724x_pcibios_init(void) { register_pci_controller(&ath724x_pci_controller); -- cgit v1.2.3 From 6335aef59c55f50e6d8017a28c0ee985b533ea29 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:24 +0100 Subject: MIPS: ath79: add a common PCI registration function The current code unconditionally registers the AR724X specific PCI controller, even if the kernel is running on a different SoC. Add a common function for PCI controller registration, and only register the AR724X PCI controller if the kernel is running on an AR724X SoC. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3488/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/mach-ubnt-xm.c | 1 + arch/mips/ath79/pci.c | 10 ++++++++++ arch/mips/ath79/pci.h | 6 ++++++ arch/mips/pci/pci-ath724x.c | 2 -- 4 files changed, 17 insertions(+), 2 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c index a0435003b2e7..edbc093bf665 100644 --- a/arch/mips/ath79/mach-ubnt-xm.c +++ b/arch/mips/ath79/mach-ubnt-xm.c @@ -111,6 +111,7 @@ static void __init ubnt_xm_init(void) ath724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data)); #endif /* CONFIG_PCI */ + ath79_register_pci(); } MIPS_MACHINE(ATH79_MACH_UBNT_XM, diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index 49574284b755..855a69dcc86e 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -9,6 +9,8 @@ */ #include +#include +#include #include "pci.h" static struct ath724x_pci_data *pci_data; @@ -44,3 +46,11 @@ int pcibios_plat_dev_init(struct pci_dev *dev) return PCIBIOS_SUCCESSFUL; } + +int __init ath79_register_pci(void) +{ + if (soc_is_ar724x()) + return ath724x_pcibios_init(); + + return -ENODEV; +} diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h index 454885fa30c3..787fac2c08f0 100644 --- a/arch/mips/ath79/pci.h +++ b/arch/mips/ath79/pci.h @@ -18,4 +18,10 @@ struct ath724x_pci_data { void ath724x_pci_add_data(struct ath724x_pci_data *data, int size); +#ifdef CONFIG_PCI +int ath79_register_pci(void); +#else +static inline int ath79_register_pci(void) { return 0; } +#endif + #endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */ diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c index be01b7f8d840..ebefc165fae6 100644 --- a/arch/mips/pci/pci-ath724x.c +++ b/arch/mips/pci/pci-ath724x.c @@ -137,5 +137,3 @@ int __init ath724x_pcibios_init(void) return PCIBIOS_SUCCESSFUL; } - -arch_initcall(ath724x_pcibios_init); -- cgit v1.2.3 From 692183ef12c4ba9dcdc9a54065ca92072cd79493 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:25 +0100 Subject: MIPS: ath79: rename pci-ath724x.c to make it reflect the real SoC name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabor Juhos Acked-by: René Bolldorf Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3489/ Signed-off-by: Ralf Baechle --- arch/mips/pci/Makefile | 2 +- arch/mips/pci/pci-ar724x.c | 139 ++++++++++++++++++++++++++++++++++++++++++++ arch/mips/pci/pci-ath724x.c | 139 -------------------------------------------- 3 files changed, 140 insertions(+), 140 deletions(-) create mode 100644 arch/mips/pci/pci-ar724x.c delete mode 100644 arch/mips/pci/pci-ath724x.c (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c3ac4b086eb2..172277cb8291 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -19,7 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ ops-bcm63xx.o obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o -obj-$(CONFIG_SOC_AR724X) += pci-ath724x.o +obj-$(CONFIG_SOC_AR724X) += pci-ar724x.o # # These are still pretty much in the old state, watch, go blind. diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c new file mode 100644 index 000000000000..ebefc165fae6 --- /dev/null +++ b/arch/mips/pci/pci-ar724x.c @@ -0,0 +1,139 @@ +/* + * Atheros 724x PCI support + * + * Copyright (C) 2011 René Bolldorf + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include + +#define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) +#define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) + +#define ATH724X_PCI_DEV_BASE 0x14000000 +#define ATH724X_PCI_MEM_BASE 0x10000000 +#define ATH724X_PCI_MEM_SIZE 0x08000000 + +static DEFINE_SPINLOCK(ath724x_pci_lock); + +static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t *value) +{ + unsigned long flags, addr, tval, mask; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&ath724x_pci_lock, flags); + + switch (size) { + case 1: + addr = where & ~3; + mask = 0xff000000 >> ((where % 4) * 8); + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = tval & ~mask; + *value = (tval >> ((4 - (where % 4))*8)); + break; + case 2: + addr = where & ~3; + mask = 0xffff0000 >> ((where % 4)*8); + tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = tval & ~mask; + *value = (tval >> ((4 - (where % 4))*8)); + break; + case 4: + *value = reg_read(ATH724X_PCI_DEV_BASE + where); + break; + default: + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, uint32_t value) +{ + unsigned long flags, tval, addr, mask; + + if (devfn) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (where & (size - 1)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + spin_lock_irqsave(&ath724x_pci_lock, flags); + + switch (size) { + case 1: + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + mask = 0xff000000 >> ((where % 4)*8); + tval = reg_read(addr); + tval = tval & ~mask; + tval |= (value << ((4 - (where % 4))*8)) & mask; + reg_write(addr, tval); + break; + case 2: + addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + mask = 0xffff0000 >> ((where % 4)*8); + tval = reg_read(addr); + tval = tval & ~mask; + tval |= (value << ((4 - (where % 4))*8)) & mask; + reg_write(addr, tval); + break; + case 4: + reg_write((ATH724X_PCI_DEV_BASE + where), value); + break; + default: + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_BAD_REGISTER_NUMBER; + } + + spin_unlock_irqrestore(&ath724x_pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops ath724x_pci_ops = { + .read = ath724x_pci_read, + .write = ath724x_pci_write, +}; + +static struct resource ath724x_io_resource = { + .name = "PCI IO space", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO, +}; + +static struct resource ath724x_mem_resource = { + .name = "PCI memory space", + .start = ATH724X_PCI_MEM_BASE, + .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct pci_controller ath724x_pci_controller = { + .pci_ops = &ath724x_pci_ops, + .io_resource = &ath724x_io_resource, + .mem_resource = &ath724x_mem_resource, +}; + +int __init ath724x_pcibios_init(void) +{ + register_pci_controller(&ath724x_pci_controller); + + return PCIBIOS_SUCCESSFUL; +} diff --git a/arch/mips/pci/pci-ath724x.c b/arch/mips/pci/pci-ath724x.c deleted file mode 100644 index ebefc165fae6..000000000000 --- a/arch/mips/pci/pci-ath724x.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Atheros 724x PCI support - * - * Copyright (C) 2011 René Bolldorf - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -#include -#include - -#define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) -#define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) - -#define ATH724X_PCI_DEV_BASE 0x14000000 -#define ATH724X_PCI_MEM_BASE 0x10000000 -#define ATH724X_PCI_MEM_SIZE 0x08000000 - -static DEFINE_SPINLOCK(ath724x_pci_lock); - -static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t *value) -{ - unsigned long flags, addr, tval, mask; - - if (devfn) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - spin_lock_irqsave(&ath724x_pci_lock, flags); - - switch (size) { - case 1: - addr = where & ~3; - mask = 0xff000000 >> ((where % 4) * 8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); - break; - case 2: - addr = where & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); - break; - case 4: - *value = reg_read(ATH724X_PCI_DEV_BASE + where); - break; - default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, uint32_t value) -{ - unsigned long flags, tval, addr, mask; - - if (devfn) - return PCIBIOS_DEVICE_NOT_FOUND; - - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - spin_lock_irqsave(&ath724x_pci_lock, flags); - - switch (size) { - case 1: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; - mask = 0xff000000 >> ((where % 4)*8); - tval = reg_read(addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); - break; - case 2: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); - break; - case 4: - reg_write((ATH724X_PCI_DEV_BASE + where), value); - break; - default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_BAD_REGISTER_NUMBER; - } - - spin_unlock_irqrestore(&ath724x_pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -static struct pci_ops ath724x_pci_ops = { - .read = ath724x_pci_read, - .write = ath724x_pci_write, -}; - -static struct resource ath724x_io_resource = { - .name = "PCI IO space", - .start = 0, - .end = 0, - .flags = IORESOURCE_IO, -}; - -static struct resource ath724x_mem_resource = { - .name = "PCI memory space", - .start = ATH724X_PCI_MEM_BASE, - .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM, -}; - -static struct pci_controller ath724x_pci_controller = { - .pci_ops = &ath724x_pci_ops, - .io_resource = &ath724x_io_resource, - .mem_resource = &ath724x_mem_resource, -}; - -int __init ath724x_pcibios_init(void) -{ - register_pci_controller(&ath724x_pci_controller); - - return PCIBIOS_SUCCESSFUL; -} -- cgit v1.2.3 From d624bd3cf7835612b25b9ec8db4002624c2dbb32 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:26 +0100 Subject: MIPS: ath79: replace ath724x to ar724x MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the 'ath724x' to 'ar724x' in function, variable and structure names to reflect the name of the real SoC. Signed-off-by: Gabor Juhos Acked-by: René Bolldorf Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3490/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/mach-ubnt-xm.c | 4 +-- arch/mips/ath79/pci.c | 6 ++-- arch/mips/ath79/pci.h | 10 +++--- arch/mips/include/asm/mach-ath79/pci.h | 4 +-- arch/mips/pci/pci-ar724x.c | 62 +++++++++++++++++----------------- 5 files changed, 43 insertions(+), 43 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/mach-ubnt-xm.c b/arch/mips/ath79/mach-ubnt-xm.c index edbc093bf665..3266ee063bd6 100644 --- a/arch/mips/ath79/mach-ubnt-xm.c +++ b/arch/mips/ath79/mach-ubnt-xm.c @@ -84,7 +84,7 @@ static struct ath79_spi_platform_data ubnt_xm_spi_data = { #ifdef CONFIG_PCI static struct ath9k_platform_data ubnt_xm_eeprom_data; -static struct ath724x_pci_data ubnt_xm_pci_data[] = { +static struct ar724x_pci_data ubnt_xm_pci_data[] = { { .irq = UBNT_XM_PCI_IRQ, .pdata = &ubnt_xm_eeprom_data, @@ -108,7 +108,7 @@ static void __init ubnt_xm_init(void) memcpy(ubnt_xm_eeprom_data.eeprom_data, UBNT_XM_EEPROM_ADDR, sizeof(ubnt_xm_eeprom_data.eeprom_data)); - ath724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data)); + ar724x_pci_add_data(ubnt_xm_pci_data, ARRAY_SIZE(ubnt_xm_pci_data)); #endif /* CONFIG_PCI */ ath79_register_pci(); diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index 855a69dcc86e..72281fb5360f 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -13,10 +13,10 @@ #include #include "pci.h" -static struct ath724x_pci_data *pci_data; +static struct ar724x_pci_data *pci_data; static int pci_data_size; -void ath724x_pci_add_data(struct ath724x_pci_data *data, int size) +void ar724x_pci_add_data(struct ar724x_pci_data *data, int size) { pci_data = data; pci_data_size = size; @@ -50,7 +50,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) int __init ath79_register_pci(void) { if (soc_is_ar724x()) - return ath724x_pcibios_init(); + return ar724x_pcibios_init(); return -ENODEV; } diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h index 787fac2c08f0..e0601c4a7fc6 100644 --- a/arch/mips/ath79/pci.h +++ b/arch/mips/ath79/pci.h @@ -8,15 +8,15 @@ * by the Free Software Foundation. */ -#ifndef __ASM_MACH_ATH79_PCI_ATH724X_H -#define __ASM_MACH_ATH79_PCI_ATH724X_H +#ifndef _ATH79_PCI_H +#define _ATH79_PCI_H -struct ath724x_pci_data { +struct ar724x_pci_data { int irq; void *pdata; }; -void ath724x_pci_add_data(struct ath724x_pci_data *data, int size); +void ar724x_pci_add_data(struct ar724x_pci_data *data, int size); #ifdef CONFIG_PCI int ath79_register_pci(void); @@ -24,4 +24,4 @@ int ath79_register_pci(void); static inline int ath79_register_pci(void) { return 0; } #endif -#endif /* __ASM_MACH_ATH79_PCI_ATH724X_H */ +#endif /* _ATH79_PCI_H */ diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h index e0c4b53590f4..6d7a837e6055 100644 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -12,9 +12,9 @@ #define __ASM_MACH_ATH79_PCI_H #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) -int ath724x_pcibios_init(void); +int ar724x_pcibios_init(void); #else -static inline int ath724x_pcibios_init(void) { return 0; } +static inline int ar724x_pcibios_init(void) { return 0; } #endif #endif /* __ASM_MACH_ATH79_PCI_H */ diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index ebefc165fae6..772d12c5fc9e 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -14,13 +14,13 @@ #define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) #define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) -#define ATH724X_PCI_DEV_BASE 0x14000000 -#define ATH724X_PCI_MEM_BASE 0x10000000 -#define ATH724X_PCI_MEM_SIZE 0x08000000 +#define AR724X_PCI_DEV_BASE 0x14000000 +#define AR724X_PCI_MEM_BASE 0x10000000 +#define AR724X_PCI_MEM_SIZE 0x08000000 -static DEFINE_SPINLOCK(ath724x_pci_lock); +static DEFINE_SPINLOCK(ar724x_pci_lock); -static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, +static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) { unsigned long flags, addr, tval, mask; @@ -31,38 +31,38 @@ static int ath724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, if (where & (size - 1)) return PCIBIOS_BAD_REGISTER_NUMBER; - spin_lock_irqsave(&ath724x_pci_lock, flags); + spin_lock_irqsave(&ar724x_pci_lock, flags); switch (size) { case 1: addr = where & ~3; mask = 0xff000000 >> ((where % 4) * 8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = reg_read(AR724X_PCI_DEV_BASE + addr); tval = tval & ~mask; *value = (tval >> ((4 - (where % 4))*8)); break; case 2: addr = where & ~3; mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(ATH724X_PCI_DEV_BASE + addr); + tval = reg_read(AR724X_PCI_DEV_BASE + addr); tval = tval & ~mask; *value = (tval >> ((4 - (where % 4))*8)); break; case 4: - *value = reg_read(ATH724X_PCI_DEV_BASE + where); + *value = reg_read(AR724X_PCI_DEV_BASE + where); break; default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); + spin_unlock_irqrestore(&ar724x_pci_lock, flags); return PCIBIOS_BAD_REGISTER_NUMBER; } - spin_unlock_irqrestore(&ath724x_pci_lock, flags); + spin_unlock_irqrestore(&ar724x_pci_lock, flags); return PCIBIOS_SUCCESSFUL; } -static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, +static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t value) { unsigned long flags, tval, addr, mask; @@ -73,11 +73,11 @@ static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, if (where & (size - 1)) return PCIBIOS_BAD_REGISTER_NUMBER; - spin_lock_irqsave(&ath724x_pci_lock, flags); + spin_lock_irqsave(&ar724x_pci_lock, flags); switch (size) { case 1: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + addr = (AR724X_PCI_DEV_BASE + where) & ~3; mask = 0xff000000 >> ((where % 4)*8); tval = reg_read(addr); tval = tval & ~mask; @@ -85,7 +85,7 @@ static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, reg_write(addr, tval); break; case 2: - addr = (ATH724X_PCI_DEV_BASE + where) & ~3; + addr = (AR724X_PCI_DEV_BASE + where) & ~3; mask = 0xffff0000 >> ((where % 4)*8); tval = reg_read(addr); tval = tval & ~mask; @@ -93,47 +93,47 @@ static int ath724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, reg_write(addr, tval); break; case 4: - reg_write((ATH724X_PCI_DEV_BASE + where), value); + reg_write((AR724X_PCI_DEV_BASE + where), value); break; default: - spin_unlock_irqrestore(&ath724x_pci_lock, flags); + spin_unlock_irqrestore(&ar724x_pci_lock, flags); return PCIBIOS_BAD_REGISTER_NUMBER; } - spin_unlock_irqrestore(&ath724x_pci_lock, flags); + spin_unlock_irqrestore(&ar724x_pci_lock, flags); return PCIBIOS_SUCCESSFUL; } -static struct pci_ops ath724x_pci_ops = { - .read = ath724x_pci_read, - .write = ath724x_pci_write, +static struct pci_ops ar724x_pci_ops = { + .read = ar724x_pci_read, + .write = ar724x_pci_write, }; -static struct resource ath724x_io_resource = { +static struct resource ar724x_io_resource = { .name = "PCI IO space", .start = 0, .end = 0, .flags = IORESOURCE_IO, }; -static struct resource ath724x_mem_resource = { +static struct resource ar724x_mem_resource = { .name = "PCI memory space", - .start = ATH724X_PCI_MEM_BASE, - .end = ATH724X_PCI_MEM_BASE + ATH724X_PCI_MEM_SIZE - 1, + .start = AR724X_PCI_MEM_BASE, + .end = AR724X_PCI_MEM_BASE + AR724X_PCI_MEM_SIZE - 1, .flags = IORESOURCE_MEM, }; -static struct pci_controller ath724x_pci_controller = { - .pci_ops = &ath724x_pci_ops, - .io_resource = &ath724x_io_resource, - .mem_resource = &ath724x_mem_resource, +static struct pci_controller ar724x_pci_controller = { + .pci_ops = &ar724x_pci_ops, + .io_resource = &ar724x_io_resource, + .mem_resource = &ar724x_mem_resource, }; -int __init ath724x_pcibios_init(void) +int __init ar724x_pcibios_init(void) { - register_pci_controller(&ath724x_pci_controller); + register_pci_controller(&ar724x_pci_controller); return PCIBIOS_SUCCESSFUL; } -- cgit v1.2.3 From c198441a3f3007752c551a32d5c426f48ae8712d Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:29:27 +0100 Subject: MIPS: ath79: use io-accessor macros in pci-ar724x.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gabor Juhos Acked-by: René Bolldorf Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3491/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ar724x.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 772d12c5fc9e..22f5e5bc4dfe 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -11,19 +11,19 @@ #include #include -#define reg_read(_phys) (*(unsigned int *) KSEG1ADDR(_phys)) -#define reg_write(_phys, _val) ((*(unsigned int *) KSEG1ADDR(_phys)) = (_val)) - -#define AR724X_PCI_DEV_BASE 0x14000000 +#define AR724X_PCI_CFG_BASE 0x14000000 +#define AR724X_PCI_CFG_SIZE 0x1000 #define AR724X_PCI_MEM_BASE 0x10000000 #define AR724X_PCI_MEM_SIZE 0x08000000 static DEFINE_SPINLOCK(ar724x_pci_lock); +static void __iomem *ar724x_pci_devcfg_base; static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) { unsigned long flags, addr, tval, mask; + void __iomem *base; if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -31,25 +31,27 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, if (where & (size - 1)) return PCIBIOS_BAD_REGISTER_NUMBER; + base = ar724x_pci_devcfg_base; + spin_lock_irqsave(&ar724x_pci_lock, flags); switch (size) { case 1: addr = where & ~3; mask = 0xff000000 >> ((where % 4) * 8); - tval = reg_read(AR724X_PCI_DEV_BASE + addr); + tval = __raw_readl(base + addr); tval = tval & ~mask; *value = (tval >> ((4 - (where % 4))*8)); break; case 2: addr = where & ~3; mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(AR724X_PCI_DEV_BASE + addr); + tval = __raw_readl(base + addr); tval = tval & ~mask; *value = (tval >> ((4 - (where % 4))*8)); break; case 4: - *value = reg_read(AR724X_PCI_DEV_BASE + where); + *value = __raw_readl(base + where); break; default: spin_unlock_irqrestore(&ar724x_pci_lock, flags); @@ -66,6 +68,7 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t value) { unsigned long flags, tval, addr, mask; + void __iomem *base; if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -73,27 +76,29 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, if (where & (size - 1)) return PCIBIOS_BAD_REGISTER_NUMBER; + base = ar724x_pci_devcfg_base; + spin_lock_irqsave(&ar724x_pci_lock, flags); switch (size) { case 1: - addr = (AR724X_PCI_DEV_BASE + where) & ~3; + addr = where & ~3; mask = 0xff000000 >> ((where % 4)*8); - tval = reg_read(addr); + tval = __raw_readl(base + addr); tval = tval & ~mask; tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); + __raw_writel(tval, base + addr); break; case 2: - addr = (AR724X_PCI_DEV_BASE + where) & ~3; + addr = where & ~3; mask = 0xffff0000 >> ((where % 4)*8); - tval = reg_read(addr); + tval = __raw_readl(base + addr); tval = tval & ~mask; tval |= (value << ((4 - (where % 4))*8)) & mask; - reg_write(addr, tval); + __raw_writel(tval, base + addr); break; case 4: - reg_write((AR724X_PCI_DEV_BASE + where), value); + __raw_writel(value, (base + where)); break; default: spin_unlock_irqrestore(&ar724x_pci_lock, flags); @@ -133,6 +138,11 @@ static struct pci_controller ar724x_pci_controller = { int __init ar724x_pcibios_init(void) { + ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, + AR724X_PCI_CFG_SIZE); + if (ar724x_pci_devcfg_base == NULL) + return -ENOMEM; + register_pci_controller(&ar724x_pci_controller); return PCIBIOS_SUCCESSFUL; -- cgit v1.2.3 From ffdce4668234a113e767edd27aa1331903959106 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:03 +0100 Subject: MIPS: ath79: remove superfluous alignment checks from pci-ar724x.c The alignment of the 'where' parameters are checked in the core PCI code already. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3492/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ar724x.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 22f5e5bc4dfe..342bf4ab8960 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -28,9 +28,6 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - base = ar724x_pci_devcfg_base; spin_lock_irqsave(&ar724x_pci_lock, flags); @@ -73,9 +70,6 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; - if (where & (size - 1)) - return PCIBIOS_BAD_REGISTER_NUMBER; - base = ar724x_pci_devcfg_base; spin_lock_irqsave(&ar724x_pci_lock, flags); -- cgit v1.2.3 From 64adb6bb62bee11ad04c2f9c3c797799e329c351 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:04 +0100 Subject: MIPS: ath79: fix broken ar724x_pci_{read,write} functions The current ar724x_pci_{read,write} functions are broken. Due to that, pci_read_config_byte returns with bogus values, and pci_write_config_{byte,word} unconditionally clears the accessed PCI configuration registers instead of changing the value of them. The patch fixes the broken functions, thus the PCI configuration space can be accessed correctly. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3493/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ar724x.c | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 342bf4ab8960..bb4f2162d4e4 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -22,8 +22,9 @@ static void __iomem *ar724x_pci_devcfg_base; static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) { - unsigned long flags, addr, tval, mask; + unsigned long flags; void __iomem *base; + u32 data; if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -31,24 +32,22 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, base = ar724x_pci_devcfg_base; spin_lock_irqsave(&ar724x_pci_lock, flags); + data = __raw_readl(base + (where & ~3)); switch (size) { case 1: - addr = where & ~3; - mask = 0xff000000 >> ((where % 4) * 8); - tval = __raw_readl(base + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); + if (where & 1) + data >>= 8; + if (where & 2) + data >>= 16; + data &= 0xff; break; case 2: - addr = where & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = __raw_readl(base + addr); - tval = tval & ~mask; - *value = (tval >> ((4 - (where % 4))*8)); + if (where & 2) + data >>= 16; + data &= 0xffff; break; case 4: - *value = __raw_readl(base + where); break; default: spin_unlock_irqrestore(&ar724x_pci_lock, flags); @@ -57,6 +56,7 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, } spin_unlock_irqrestore(&ar724x_pci_lock, flags); + *value = data; return PCIBIOS_SUCCESSFUL; } @@ -64,8 +64,10 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t value) { - unsigned long flags, tval, addr, mask; + unsigned long flags; void __iomem *base; + u32 data; + int s; if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; @@ -73,26 +75,21 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, base = ar724x_pci_devcfg_base; spin_lock_irqsave(&ar724x_pci_lock, flags); + data = __raw_readl(base + (where & ~3)); switch (size) { case 1: - addr = where & ~3; - mask = 0xff000000 >> ((where % 4)*8); - tval = __raw_readl(base + addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - __raw_writel(tval, base + addr); + s = ((where & 3) * 8); + data &= ~(0xff << s); + data |= ((value & 0xff) << s); break; case 2: - addr = where & ~3; - mask = 0xffff0000 >> ((where % 4)*8); - tval = __raw_readl(base + addr); - tval = tval & ~mask; - tval |= (value << ((4 - (where % 4))*8)) & mask; - __raw_writel(tval, base + addr); + s = ((where & 2) * 8); + data &= ~(0xffff << s); + data |= ((value & 0xffff) << s); break; case 4: - __raw_writel(value, (base + where)); + data = value; break; default: spin_unlock_irqrestore(&ar724x_pci_lock, flags); @@ -100,6 +97,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, return PCIBIOS_BAD_REGISTER_NUMBER; } + __raw_writel(data, base + (where & ~3)); + /* flush write */ + __raw_readl(base + (where & ~3)); spin_unlock_irqrestore(&ar724x_pci_lock, flags); return PCIBIOS_SUCCESSFUL; -- cgit v1.2.3 From 6015a856f16ccf33e9f83643d04c2e15be2384eb Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:05 +0100 Subject: MIPS: ath79: add a workaround for a PCI controller bug in AR7240 SoCs The PCI controller of the AR724X SoCs has a hardware bag. If the BAR0 register of the PCI device is set to the proper base address, the memory address space of the device is not accessible. When the device driver tries to access the memory address space of the PCI device, it leads to data bus error, similiar to this: Data bus error, epc == 801f69a0, ra == 801f698c Oops[#1]: Cpu 0 $ 0 : 00000000 00000061 deadbeef 000000ff $ 4 : 00000000 000000ff 00000014 00000000 $ 8 : ff000000 fffffffc 00000000 00000000 $12 : 000001f5 00000006 00000000 6e637920 $16 : 81ca4000 81ca0260 81ca4000 804d70f0 $20 : fffffff4 0000002b 803ad4c4 00000000 $24 : 00000003 00000000 $28 : 81c20000 81c21c60 00000000 801f698c Hi : 00000000 Lo : 00000000 epc : 801f69a0 ath9k_hw_init+0xd0/0xa70 Not tainted ra : 801f698c ath9k_hw_init+0xbc/0xa70 Status: 1000c103 KERNEL EXL IE Cause : 1080001c PrId : 00019374 (MIPS 24Kc) Modules linked in: Process swapper (pid: 1, threadinfo=81c20000, task=81c18000, tls=00000000) Stack : 00000000 00000000 00000000 00000000 81c21c78 81ca0260 00000000 804d70f0 81ca0260 81c21cc0 81ca0e80 81ca0260 81ca4000 804d70f0 fffffff4 0000002b 803ad4c4 00000000 00000000 801e3ae8 81c9d080 81ca0e80 b0000000 800b9b9c 00000008 81c9d000 8031aeb0 802d38a0 00000000 81c14c00 81c14c60 00000000 81ca0e80 81ca0260 b0000000 801f08a4 81c9c820 81c21d48 81c9c820 80144320 ... Call Trace: [<801f69a0>] ath9k_hw_init+0xd0/0xa70 [<801e3ae8>] ath9k_init_device+0x174/0x680 [<801f08a4>] ath_pci_probe+0x27c/0x380 [<8019e490>] pci_device_probe+0x74/0x9c [<801bfadc>] driver_probe_device+0x9c/0x1b4 [<801bfcb0>] __driver_attach+0xbc/0xc4 [<801bea0c>] bus_for_each_dev+0x5c/0x98 [<801bf394>] bus_add_driver+0x1d0/0x2a4 [<801c0364>] driver_register+0x8c/0x16c [<8019e72c>] __pci_register_driver+0x4c/0xe4 [<803d3d40>] ath9k_init+0x3c/0x88 [<80060930>] do_one_initcall+0x3c/0x1cc [<803c297c>] kernel_init+0xa4/0x138 [<80063c04>] kernel_thread_helper+0x10/0x18 Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3494/ Signed-off-by: Ralf Baechle --- arch/mips/pci/pci-ar724x.c | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index bb4f2162d4e4..07b7e3071735 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -9,6 +9,7 @@ */ #include +#include #include #define AR724X_PCI_CFG_BASE 0x14000000 @@ -16,9 +17,14 @@ #define AR724X_PCI_MEM_BASE 0x10000000 #define AR724X_PCI_MEM_SIZE 0x08000000 +#define AR7240_BAR0_WAR_VALUE 0xffff + static DEFINE_SPINLOCK(ar724x_pci_lock); static void __iomem *ar724x_pci_devcfg_base; +static u32 ar724x_pci_bar0_value; +static bool ar724x_pci_bar0_is_cached; + static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, uint32_t *value) { @@ -56,7 +62,14 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, } spin_unlock_irqrestore(&ar724x_pci_lock, flags); - *value = data; + + if (where == PCI_BASE_ADDRESS_0 && size == 4 && + ar724x_pci_bar0_is_cached) { + /* use the cached value */ + *value = ar724x_pci_bar0_value; + } else { + *value = data; + } return PCIBIOS_SUCCESSFUL; } @@ -72,6 +85,27 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, if (devfn) return PCIBIOS_DEVICE_NOT_FOUND; + if (soc_is_ar7240() && where == PCI_BASE_ADDRESS_0 && size == 4) { + if (value != 0xffffffff) { + /* + * WAR for a hw issue. If the BAR0 register of the + * device is set to the proper base address, the + * memory space of the device is not accessible. + * + * Cache the intended value so it can be read back, + * and write a SoC specific constant value to the + * BAR0 register in order to make the device memory + * accessible. + */ + ar724x_pci_bar0_is_cached = true; + ar724x_pci_bar0_value = value; + + value = AR7240_BAR0_WAR_VALUE; + } else { + ar724x_pci_bar0_is_cached = false; + } + } + base = ar724x_pci_devcfg_base; spin_lock_irqsave(&ar724x_pci_lock, flags); -- cgit v1.2.3 From 4c07c7dfa0f3575dc3276c544349fbf181381167 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:07 +0100 Subject: MIPS: ath79: add PCI IRQ handling code for AR724X SoCs The PCI Host Controller of the AR724x SoC has a built-in IRQ controller. The current code does not supports that, so the IRQ lines wired to this controller are not usable. This leads to failed 'request_irq' calls: ath9k 0000:00:00.0: request_irq failed ath9k: probe of 0000:00:00.0 failed with error -89 This patch adds support for the IRQ controller in order to make PCI IRQs work. Signed-off-by: Gabor Juhos Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3496/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/pci.c | 3 +- arch/mips/include/asm/mach-ath79/pci.h | 4 +- arch/mips/pci/pci-ar724x.c | 118 ++++++++++++++++++++++++++++++++- 3 files changed, 120 insertions(+), 5 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index 72281fb5360f..14f981c295d2 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -10,6 +10,7 @@ #include #include +#include #include #include "pci.h" @@ -50,7 +51,7 @@ int pcibios_plat_dev_init(struct pci_dev *dev) int __init ath79_register_pci(void) { if (soc_is_ar724x()) - return ar724x_pcibios_init(); + return ar724x_pcibios_init(ATH79_CPU_IRQ_IP2); return -ENODEV; } diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h index 6d7a837e6055..2eb01815d54e 100644 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -12,9 +12,9 @@ #define __ASM_MACH_ATH79_PCI_H #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) -int ar724x_pcibios_init(void); +int ar724x_pcibios_init(int irq); #else -static inline int ar724x_pcibios_init(void) { return 0; } +static inline int ar724x_pcibios_init(int irq) { return 0; } #endif #endif /* __ASM_MACH_ATH79_PCI_H */ diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 07b7e3071735..04f433a823da 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -8,19 +8,32 @@ * by the Free Software Foundation. */ +#include #include #include +#include #include #define AR724X_PCI_CFG_BASE 0x14000000 #define AR724X_PCI_CFG_SIZE 0x1000 +#define AR724X_PCI_CTRL_BASE (AR71XX_APB_BASE + 0x000f0000) +#define AR724X_PCI_CTRL_SIZE 0x100 + #define AR724X_PCI_MEM_BASE 0x10000000 #define AR724X_PCI_MEM_SIZE 0x08000000 +#define AR724X_PCI_REG_INT_STATUS 0x4c +#define AR724X_PCI_REG_INT_MASK 0x50 + +#define AR724X_PCI_INT_DEV0 BIT(14) + +#define AR724X_PCI_IRQ_COUNT 1 + #define AR7240_BAR0_WAR_VALUE 0xffff static DEFINE_SPINLOCK(ar724x_pci_lock); static void __iomem *ar724x_pci_devcfg_base; +static void __iomem *ar724x_pci_ctrl_base; static u32 ar724x_pci_bar0_value; static bool ar724x_pci_bar0_is_cached; @@ -164,14 +177,115 @@ static struct pci_controller ar724x_pci_controller = { .mem_resource = &ar724x_mem_resource, }; -int __init ar724x_pcibios_init(void) +static void ar724x_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + void __iomem *base; + u32 pending; + + base = ar724x_pci_ctrl_base; + + pending = __raw_readl(base + AR724X_PCI_REG_INT_STATUS) & + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + + if (pending & AR724X_PCI_INT_DEV0) + generic_handle_irq(ATH79_PCI_IRQ(0)); + + else + spurious_interrupt(); +} + +static void ar724x_pci_irq_unmask(struct irq_data *d) +{ + void __iomem *base; + u32 t; + + base = ar724x_pci_ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t | AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_MASK); + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + } +} + +static void ar724x_pci_irq_mask(struct irq_data *d) +{ + void __iomem *base; + u32 t; + + base = ar724x_pci_ctrl_base; + + switch (d->irq) { + case ATH79_PCI_IRQ(0): + t = __raw_readl(base + AR724X_PCI_REG_INT_MASK); + __raw_writel(t & ~AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_MASK); + + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_MASK); + + t = __raw_readl(base + AR724X_PCI_REG_INT_STATUS); + __raw_writel(t | AR724X_PCI_INT_DEV0, + base + AR724X_PCI_REG_INT_STATUS); + + /* flush write */ + __raw_readl(base + AR724X_PCI_REG_INT_STATUS); + } +} + +static struct irq_chip ar724x_pci_irq_chip = { + .name = "AR724X PCI ", + .irq_mask = ar724x_pci_irq_mask, + .irq_unmask = ar724x_pci_irq_unmask, + .irq_mask_ack = ar724x_pci_irq_mask, +}; + +static void __init ar724x_pci_irq_init(int irq) +{ + void __iomem *base; + int i; + + base = ar724x_pci_ctrl_base; + + __raw_writel(0, base + AR724X_PCI_REG_INT_MASK); + __raw_writel(0, base + AR724X_PCI_REG_INT_STATUS); + + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR724X_PCI_IRQ_COUNT); + + for (i = ATH79_PCI_IRQ_BASE; + i < ATH79_PCI_IRQ_BASE + AR724X_PCI_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &ar724x_pci_irq_chip, + handle_level_irq); + + irq_set_chained_handler(irq, ar724x_pci_irq_handler); +} + +int __init ar724x_pcibios_init(int irq) { + int ret; + + ret = -ENOMEM; + ar724x_pci_devcfg_base = ioremap(AR724X_PCI_CFG_BASE, AR724X_PCI_CFG_SIZE); if (ar724x_pci_devcfg_base == NULL) - return -ENOMEM; + goto err; + ar724x_pci_ctrl_base = ioremap(AR724X_PCI_CTRL_BASE, + AR724X_PCI_CTRL_SIZE); + if (ar724x_pci_ctrl_base == NULL) + goto err_unmap_devcfg; + + ar724x_pci_irq_init(irq); register_pci_controller(&ar724x_pci_controller); return PCIBIOS_SUCCESSFUL; + +err_unmap_devcfg: + iounmap(ar724x_pci_devcfg_base); +err: + return ret; } -- cgit v1.2.3 From f8365ec4e1b945f70a86e9514dd67ba5f9f2915b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:10 +0100 Subject: MIPS: ath79: add support for the PCI host controller of the AR71XX SoCs The Atheros AR71XX SoCs have a built-in PCI Host Controller. This patch adds a driver for that, and modifies the relevant files in order to allow to register the PCI controller from board specific setup. Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3498/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/Kconfig | 1 + arch/mips/include/asm/mach-ath79/pci.h | 6 + arch/mips/pci/Makefile | 1 + arch/mips/pci/pci-ar71xx.c | 375 +++++++++++++++++++++++++++++++++ 4 files changed, 383 insertions(+) create mode 100644 arch/mips/pci/pci-ar71xx.c (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index e0fae8f4442b..bc6edada38ac 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -52,6 +52,7 @@ endmenu config SOC_AR71XX select USB_ARCH_HAS_EHCI select USB_ARCH_HAS_OHCI + select HW_HAS_PCI def_bool n config SOC_AR724X diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h index 2eb01815d54e..b12b0870b7ed 100644 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -11,6 +11,12 @@ #ifndef __ASM_MACH_ATH79_PCI_H #define __ASM_MACH_ATH79_PCI_H +#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR71XX) +int ar71xx_pcibios_init(void); +#else +static inline int ar71xx_pcibios_init(void) { return 0; } +#endif + #if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) int ar724x_pcibios_init(int irq); #else diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index 172277cb8291..b1c0a1c88991 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_BCM47XX) += pci-bcm47xx.o obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ ops-bcm63xx.o obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o +obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o obj-$(CONFIG_SOC_AR724X) += pci-ar724x.o # diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c new file mode 100644 index 000000000000..1552522b8718 --- /dev/null +++ b/arch/mips/pci/pci-ar71xx.c @@ -0,0 +1,375 @@ +/* + * Atheros AR71xx PCI host controller driver + * + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define AR71XX_PCI_MEM_BASE 0x10000000 +#define AR71XX_PCI_MEM_SIZE 0x08000000 + +#define AR71XX_PCI_WIN0_OFFS 0x10000000 +#define AR71XX_PCI_WIN1_OFFS 0x11000000 +#define AR71XX_PCI_WIN2_OFFS 0x12000000 +#define AR71XX_PCI_WIN3_OFFS 0x13000000 +#define AR71XX_PCI_WIN4_OFFS 0x14000000 +#define AR71XX_PCI_WIN5_OFFS 0x15000000 +#define AR71XX_PCI_WIN6_OFFS 0x16000000 +#define AR71XX_PCI_WIN7_OFFS 0x07000000 + +#define AR71XX_PCI_CFG_BASE \ + (AR71XX_PCI_MEM_BASE + AR71XX_PCI_WIN7_OFFS + 0x10000) +#define AR71XX_PCI_CFG_SIZE 0x100 + +#define AR71XX_PCI_REG_CRP_AD_CBE 0x00 +#define AR71XX_PCI_REG_CRP_WRDATA 0x04 +#define AR71XX_PCI_REG_CRP_RDDATA 0x08 +#define AR71XX_PCI_REG_CFG_AD 0x0c +#define AR71XX_PCI_REG_CFG_CBE 0x10 +#define AR71XX_PCI_REG_CFG_WRDATA 0x14 +#define AR71XX_PCI_REG_CFG_RDDATA 0x18 +#define AR71XX_PCI_REG_PCI_ERR 0x1c +#define AR71XX_PCI_REG_PCI_ERR_ADDR 0x20 +#define AR71XX_PCI_REG_AHB_ERR 0x24 +#define AR71XX_PCI_REG_AHB_ERR_ADDR 0x28 + +#define AR71XX_PCI_CRP_CMD_WRITE 0x00010000 +#define AR71XX_PCI_CRP_CMD_READ 0x00000000 +#define AR71XX_PCI_CFG_CMD_READ 0x0000000a +#define AR71XX_PCI_CFG_CMD_WRITE 0x0000000b + +#define AR71XX_PCI_INT_CORE BIT(4) +#define AR71XX_PCI_INT_DEV2 BIT(2) +#define AR71XX_PCI_INT_DEV1 BIT(1) +#define AR71XX_PCI_INT_DEV0 BIT(0) + +#define AR71XX_PCI_IRQ_COUNT 5 + +static DEFINE_SPINLOCK(ar71xx_pci_lock); +static void __iomem *ar71xx_pcicfg_base; + +/* Byte lane enable bits */ +static const u8 ar71xx_pci_ble_table[4][4] = { + {0x0, 0xf, 0xf, 0xf}, + {0xe, 0xd, 0xb, 0x7}, + {0xc, 0xf, 0x3, 0xf}, + {0xf, 0xf, 0xf, 0xf}, +}; + +static const u32 ar71xx_pci_read_mask[8] = { + 0, 0xff, 0xffff, 0, 0xffffffff, 0, 0, 0 +}; + +static inline u32 ar71xx_pci_get_ble(int where, int size, int local) +{ + u32 t; + + t = ar71xx_pci_ble_table[size & 3][where & 3]; + BUG_ON(t == 0xf); + t <<= (local) ? 20 : 4; + + return t; +} + +static inline u32 ar71xx_pci_bus_addr(struct pci_bus *bus, unsigned int devfn, + int where) +{ + u32 ret; + + if (!bus->number) { + /* type 0 */ + ret = (1 << PCI_SLOT(devfn)) | (PCI_FUNC(devfn) << 8) | + (where & ~3); + } else { + /* type 1 */ + ret = (bus->number << 16) | (PCI_SLOT(devfn) << 11) | + (PCI_FUNC(devfn) << 8) | (where & ~3) | 1; + } + + return ret; +} + +static int ar71xx_pci_check_error(int quiet) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 pci_err; + u32 ahb_err; + + pci_err = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR) & 3; + if (pci_err) { + if (!quiet) { + u32 addr; + + addr = __raw_readl(base + AR71XX_PCI_REG_PCI_ERR_ADDR); + pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", + "PCI", pci_err, addr); + } + + /* clear PCI error status */ + __raw_writel(pci_err, base + AR71XX_PCI_REG_PCI_ERR); + } + + ahb_err = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR) & 1; + if (ahb_err) { + if (!quiet) { + u32 addr; + + addr = __raw_readl(base + AR71XX_PCI_REG_AHB_ERR_ADDR); + pr_crit("ar71xx: %s bus error %d at addr 0x%x\n", + "AHB", ahb_err, addr); + } + + /* clear AHB error status */ + __raw_writel(ahb_err, base + AR71XX_PCI_REG_AHB_ERR); + } + + return !!(ahb_err | pci_err); +} + +static inline void ar71xx_pci_local_write(int where, int size, u32 value) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 ad_cbe; + + value = value << (8 * (where & 3)); + + ad_cbe = AR71XX_PCI_CRP_CMD_WRITE | (where & ~3); + ad_cbe |= ar71xx_pci_get_ble(where, size, 1); + + __raw_writel(ad_cbe, base + AR71XX_PCI_REG_CRP_AD_CBE); + __raw_writel(value, base + AR71XX_PCI_REG_CRP_WRDATA); +} + +static inline int ar71xx_pci_set_cfgaddr(struct pci_bus *bus, + unsigned int devfn, + int where, int size, u32 cmd) +{ + void __iomem *base = ar71xx_pcicfg_base; + u32 addr; + + addr = ar71xx_pci_bus_addr(bus, devfn, where); + + __raw_writel(addr, base + AR71XX_PCI_REG_CFG_AD); + __raw_writel(cmd | ar71xx_pci_get_ble(where, size, 0), + base + AR71XX_PCI_REG_CFG_CBE); + + return ar71xx_pci_check_error(1); +} + +static int ar71xx_pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + void __iomem *base = ar71xx_pcicfg_base; + unsigned long flags; + u32 data; + int err; + int ret; + + ret = PCIBIOS_SUCCESSFUL; + data = ~0; + + spin_lock_irqsave(&ar71xx_pci_lock, flags); + + err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, + AR71XX_PCI_CFG_CMD_READ); + if (err) + ret = PCIBIOS_DEVICE_NOT_FOUND; + else + data = __raw_readl(base + AR71XX_PCI_REG_CFG_RDDATA); + + spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + + *value = (data >> (8 * (where & 3))) & ar71xx_pci_read_mask[size & 7]; + + return ret; +} + +static int ar71xx_pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + void __iomem *base = ar71xx_pcicfg_base; + unsigned long flags; + int err; + int ret; + + value = value << (8 * (where & 3)); + ret = PCIBIOS_SUCCESSFUL; + + spin_lock_irqsave(&ar71xx_pci_lock, flags); + + err = ar71xx_pci_set_cfgaddr(bus, devfn, where, size, + AR71XX_PCI_CFG_CMD_WRITE); + if (err) + ret = PCIBIOS_DEVICE_NOT_FOUND; + else + __raw_writel(value, base + AR71XX_PCI_REG_CFG_WRDATA); + + spin_unlock_irqrestore(&ar71xx_pci_lock, flags); + + return ret; +} + +static struct pci_ops ar71xx_pci_ops = { + .read = ar71xx_pci_read_config, + .write = ar71xx_pci_write_config, +}; + +static struct resource ar71xx_pci_io_resource = { + .name = "PCI IO space", + .start = 0, + .end = 0, + .flags = IORESOURCE_IO, +}; + +static struct resource ar71xx_pci_mem_resource = { + .name = "PCI memory space", + .start = AR71XX_PCI_MEM_BASE, + .end = AR71XX_PCI_MEM_BASE + AR71XX_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +static struct pci_controller ar71xx_pci_controller = { + .pci_ops = &ar71xx_pci_ops, + .mem_resource = &ar71xx_pci_mem_resource, + .io_resource = &ar71xx_pci_io_resource, +}; + +static void ar71xx_pci_irq_handler(unsigned int irq, struct irq_desc *desc) +{ + void __iomem *base = ath79_reset_base; + u32 pending; + + pending = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_STATUS) & + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + if (pending & AR71XX_PCI_INT_DEV0) + generic_handle_irq(ATH79_PCI_IRQ(0)); + + else if (pending & AR71XX_PCI_INT_DEV1) + generic_handle_irq(ATH79_PCI_IRQ(1)); + + else if (pending & AR71XX_PCI_INT_DEV2) + generic_handle_irq(ATH79_PCI_IRQ(2)); + + else if (pending & AR71XX_PCI_INT_CORE) + generic_handle_irq(ATH79_PCI_IRQ(4)); + + else + spurious_interrupt(); +} + +static void ar71xx_pci_irq_unmask(struct irq_data *d) +{ + unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + void __iomem *base = ath79_reset_base; + u32 t; + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + /* flush write */ + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +} + +static void ar71xx_pci_irq_mask(struct irq_data *d) +{ + unsigned int irq = d->irq - ATH79_PCI_IRQ_BASE; + void __iomem *base = ath79_reset_base; + u32 t; + + t = __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_PCI_INT_ENABLE); + + /* flush write */ + __raw_readl(base + AR71XX_RESET_REG_PCI_INT_ENABLE); +} + +static struct irq_chip ar71xx_pci_irq_chip = { + .name = "AR71XX PCI", + .irq_mask = ar71xx_pci_irq_mask, + .irq_unmask = ar71xx_pci_irq_unmask, + .irq_mask_ack = ar71xx_pci_irq_mask, +}; + +static __init void ar71xx_pci_irq_init(void) +{ + void __iomem *base = ath79_reset_base; + int i; + + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_ENABLE); + __raw_writel(0, base + AR71XX_RESET_REG_PCI_INT_STATUS); + + BUILD_BUG_ON(ATH79_PCI_IRQ_COUNT < AR71XX_PCI_IRQ_COUNT); + + for (i = ATH79_PCI_IRQ_BASE; + i < ATH79_PCI_IRQ_BASE + AR71XX_PCI_IRQ_COUNT; i++) + irq_set_chip_and_handler(i, &ar71xx_pci_irq_chip, + handle_level_irq); + + irq_set_chained_handler(ATH79_CPU_IRQ_IP2, ar71xx_pci_irq_handler); +} + +static __init void ar71xx_pci_reset(void) +{ + void __iomem *ddr_base = ath79_ddr_base; + + ath79_device_reset_set(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); + mdelay(100); + + ath79_device_reset_clear(AR71XX_RESET_PCI_BUS | AR71XX_RESET_PCI_CORE); + mdelay(100); + + __raw_writel(AR71XX_PCI_WIN0_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN0); + __raw_writel(AR71XX_PCI_WIN1_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN1); + __raw_writel(AR71XX_PCI_WIN2_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN2); + __raw_writel(AR71XX_PCI_WIN3_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN3); + __raw_writel(AR71XX_PCI_WIN4_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN4); + __raw_writel(AR71XX_PCI_WIN5_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN5); + __raw_writel(AR71XX_PCI_WIN6_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN6); + __raw_writel(AR71XX_PCI_WIN7_OFFS, ddr_base + AR71XX_DDR_REG_PCI_WIN7); + + mdelay(100); +} + +__init int ar71xx_pcibios_init(void) +{ + u32 t; + + ar71xx_pcicfg_base = ioremap(AR71XX_PCI_CFG_BASE, AR71XX_PCI_CFG_SIZE); + if (ar71xx_pcicfg_base == NULL) + return -ENOMEM; + + ar71xx_pci_reset(); + + /* setup COMMAND register */ + t = PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE + | PCI_COMMAND_PARITY | PCI_COMMAND_SERR | PCI_COMMAND_FAST_BACK; + ar71xx_pci_local_write(PCI_COMMAND, 4, t); + + /* clear bus errors */ + ar71xx_pci_check_error(1); + + ar71xx_pci_irq_init(); + + register_pci_controller(&ar71xx_pci_controller); + + return 0; +} -- cgit v1.2.3 From e9b62e8ef9d71ed977797529fc0dfc352448d50b Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:36:14 +0100 Subject: MIPS: ath79: update copyright headers of PCI related files Add copyright records according to the recent changes in the PCI code. Also fix up the descriptions. Signed-off-by: Gabor Juhos Signed-off-by: Imre Kaloz Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3503/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/pci.c | 4 ++++ arch/mips/ath79/pci.h | 4 +++- arch/mips/include/asm/mach-ath79/pci.h | 4 +++- arch/mips/pci/pci-ar724x.c | 3 ++- 4 files changed, 12 insertions(+), 3 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/pci.c b/arch/mips/ath79/pci.c index 253a382f63b2..bc40070e45c9 100644 --- a/arch/mips/ath79/pci.c +++ b/arch/mips/ath79/pci.c @@ -2,6 +2,10 @@ * Atheros AR71XX/AR724X specific PCI setup code * * Copyright (C) 2011 René Bolldorf + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz + * + * Parts of this file are based on Atheros' 2.6.15 BSP * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published diff --git a/arch/mips/ath79/pci.h b/arch/mips/ath79/pci.h index 5ebed2104ed0..51c6625dcc6d 100644 --- a/arch/mips/ath79/pci.h +++ b/arch/mips/ath79/pci.h @@ -1,7 +1,9 @@ /* - * Atheros 724x PCI support + * Atheros AR71XX/AR724X PCI support * * Copyright (C) 2011 René Bolldorf + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h index b12b0870b7ed..4f2222de6064 100644 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -1,7 +1,9 @@ /* - * Atheros 724x PCI support + * Atheros AR71XX/AR724X PCI support * * Copyright (C) 2011 René Bolldorf + * Copyright (C) 2008-2011 Gabor Juhos + * Copyright (C) 2008 Imre Kaloz * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c index 04f433a823da..414a7459858d 100644 --- a/arch/mips/pci/pci-ar724x.c +++ b/arch/mips/pci/pci-ar724x.c @@ -1,7 +1,8 @@ /* - * Atheros 724x PCI support + * Atheros AR724X PCI host controller driver * * Copyright (C) 2011 René Bolldorf + * Copyright (C) 2009-2011 Gabor Juhos * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published -- cgit v1.2.3 From 67644c547fef2739f49c80e5eb1ace82f3e916e2 Mon Sep 17 00:00:00 2001 From: Gabor Juhos Date: Wed, 14 Mar 2012 10:45:29 +0100 Subject: MIPS: ath79: add PCI_AR724X Kconfig symbol The AR724X specific PCI code can be used for the AR934X SoCs, however it can be selected only if SOC_AR724X is set. Introduce a new Kconfig symbol in order to be able to use the code for AR934X as well. Signed-off-by: Gabor Juhos Acked-by: Luis R. Rodriguez Cc: linux-mips@linux-mips.org Cc: mcgrof@infradead.org Patchwork: https://patchwork.linux-mips.org/patch/3514/ Signed-off-by: Ralf Baechle --- arch/mips/ath79/Kconfig | 4 ++++ arch/mips/include/asm/mach-ath79/pci.h | 2 +- arch/mips/pci/Makefile | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) (limited to 'arch/mips/pci') diff --git a/arch/mips/ath79/Kconfig b/arch/mips/ath79/Kconfig index 5fa3d7b2b716..123cc3773b49 100644 --- a/arch/mips/ath79/Kconfig +++ b/arch/mips/ath79/Kconfig @@ -59,6 +59,7 @@ config SOC_AR724X select USB_ARCH_HAS_EHCI select USB_ARCH_HAS_OHCI select HW_HAS_PCI + select PCI_AR724X if PCI def_bool n config SOC_AR913X @@ -73,6 +74,9 @@ config SOC_AR934X select USB_ARCH_HAS_EHCI def_bool n +config PCI_AR724X + def_bool n + config ATH79_DEV_GPIO_BUTTONS def_bool n diff --git a/arch/mips/include/asm/mach-ath79/pci.h b/arch/mips/include/asm/mach-ath79/pci.h index 4f2222de6064..7868f7fa028f 100644 --- a/arch/mips/include/asm/mach-ath79/pci.h +++ b/arch/mips/include/asm/mach-ath79/pci.h @@ -19,7 +19,7 @@ int ar71xx_pcibios_init(void); static inline int ar71xx_pcibios_init(void) { return 0; } #endif -#if defined(CONFIG_PCI) && defined(CONFIG_SOC_AR724X) +#if defined(CONFIG_PCI_AR724X) int ar724x_pcibios_init(int irq); #else static inline int ar724x_pcibios_init(int irq) { return 0; } diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index b1c0a1c88991..43c5138a8498 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -20,7 +20,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \ ops-bcm63xx.o obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o -obj-$(CONFIG_SOC_AR724X) += pci-ar724x.o +obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o # # These are still pretty much in the old state, watch, go blind. -- cgit v1.2.3 From a48cf37ac8a77ddd2370be3c9af411c622ebc425 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 4 May 2012 10:50:13 +0200 Subject: MIPS: pci: parse memory ranges from devicetree Implement pci_load_of_ranges on MIPS. Due to lack of test hardware only 32bit bus width is supported. This function is based on pci_process_bridge_OF_ranges from powerpc. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3729/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/pci.h | 6 +++++ arch/mips/pci/pci.c | 55 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/pci.h b/arch/mips/include/asm/pci.h index fcd4060f6421..90bf3b3fce19 100644 --- a/arch/mips/include/asm/pci.h +++ b/arch/mips/include/asm/pci.h @@ -17,6 +17,7 @@ */ #include +#include /* * Each pci channel is a top-level PCI bus seem by CPU. A machine with @@ -26,6 +27,7 @@ struct pci_controller { struct pci_controller *next; struct pci_bus *bus; + struct device_node *of_node; struct pci_ops *pci_ops; struct resource *mem_resource; @@ -142,4 +144,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel) extern char * (*pcibios_plat_setup)(char *str); +/* this function parses memory ranges from a device node */ +extern void __devinit pci_load_of_ranges(struct pci_controller *hose, + struct device_node *node); + #endif /* _ASM_PCI_H */ diff --git a/arch/mips/pci/pci.c b/arch/mips/pci/pci.c index 0514866fa925..271e8c4a54c7 100644 --- a/arch/mips/pci/pci.c +++ b/arch/mips/pci/pci.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -114,9 +115,63 @@ static void __devinit pcibios_scanbus(struct pci_controller *hose) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } + bus->dev.of_node = hose->of_node; } } +#ifdef CONFIG_OF +void __devinit pci_load_of_ranges(struct pci_controller *hose, + struct device_node *node) +{ + const __be32 *ranges; + int rlen; + int pna = of_n_addr_cells(node); + int np = pna + 5; + + pr_info("PCI host bridge %s ranges:\n", node->full_name); + ranges = of_get_property(node, "ranges", &rlen); + if (ranges == NULL) + return; + hose->of_node = node; + + while ((rlen -= np * 4) >= 0) { + u32 pci_space; + struct resource *res = NULL; + u64 addr, size; + + pci_space = be32_to_cpup(&ranges[0]); + addr = of_translate_address(node, ranges + 3); + size = of_read_number(ranges + pna + 3, 2); + ranges += np; + switch ((pci_space >> 24) & 0x3) { + case 1: /* PCI IO space */ + pr_info(" IO 0x%016llx..0x%016llx\n", + addr, addr + size - 1); + hose->io_map_base = + (unsigned long)ioremap(addr, size); + res = hose->io_resource; + res->flags = IORESOURCE_IO; + break; + case 2: /* PCI Memory space */ + case 3: /* PCI 64 bits Memory space */ + pr_info(" MEM 0x%016llx..0x%016llx\n", + addr, addr + size - 1); + res = hose->mem_resource; + res->flags = IORESOURCE_MEM; + break; + } + if (res != NULL) { + res->start = addr; + res->name = node->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + } +} +#endif + static DEFINE_MUTEX(pci_scan_mutex); void __devinit register_pci_controller(struct pci_controller *hose) -- cgit v1.2.3 From bd51db7f3bf2ba23ff55f6d5fdcec04c74df13e4 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 11 May 2012 18:45:25 +0200 Subject: MIPS: lantiq: drop ltq_gpio_request() and gpio_to_irq() As part of the conversion to OF we also implement pinctrl drivers. Previously we used ltq_gpio_request() to set pinmuxing. This is now obselete and we can hence drop the function. Additionally we remove gpio_to_irq() from the gpio driver and move it to a header file. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3801/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/mach-lantiq/gpio.h | 16 ++++++++ .../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 2 - arch/mips/lantiq/xway/gpio.c | 12 ------ arch/mips/lantiq/xway/gpio_stp.c | 5 --- arch/mips/pci/pci-lantiq.c | 44 +--------------------- 5 files changed, 17 insertions(+), 62 deletions(-) create mode 100644 arch/mips/include/asm/mach-lantiq/gpio.h (limited to 'arch/mips/pci') diff --git a/arch/mips/include/asm/mach-lantiq/gpio.h b/arch/mips/include/asm/mach-lantiq/gpio.h new file mode 100644 index 000000000000..f79505b43609 --- /dev/null +++ b/arch/mips/include/asm/mach-lantiq/gpio.h @@ -0,0 +1,16 @@ +#ifndef __ASM_MIPS_MACH_LANTIQ_GPIO_H +#define __ASM_MIPS_MACH_LANTIQ_GPIO_H + +static inline int gpio_to_irq(unsigned int gpio) +{ + return -1; +} + +#define gpio_get_value __gpio_get_value +#define gpio_set_value __gpio_set_value + +#define gpio_cansleep __gpio_cansleep + +#include + +#endif diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h index 15eb4dc6ec03..150c7bef5a14 100644 --- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h +++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h @@ -153,8 +153,6 @@ #define LTQ_MPS_CHIPID ((u32 *)(LTQ_MPS_BASE_ADDR + 0x0344)) /* request a non-gpio and set the PIO config */ -extern int ltq_gpio_request(unsigned int pin, unsigned int alt0, - unsigned int alt1, unsigned int dir, const char *name); extern void ltq_pmu_enable(unsigned int module); extern void ltq_pmu_disable(unsigned int module); diff --git a/arch/mips/lantiq/xway/gpio.c b/arch/mips/lantiq/xway/gpio.c index d2fa98f3c78d..a8b2edc80855 100644 --- a/arch/mips/lantiq/xway/gpio.c +++ b/arch/mips/lantiq/xway/gpio.c @@ -36,18 +36,6 @@ struct ltq_gpio { static struct ltq_gpio ltq_gpio_port[MAX_PORTS]; -int gpio_to_irq(unsigned int gpio) -{ - return -EINVAL; -} -EXPORT_SYMBOL(gpio_to_irq); - -int irq_to_gpio(unsigned int gpio) -{ - return -EINVAL; -} -EXPORT_SYMBOL(irq_to_gpio); - int ltq_gpio_request(unsigned int pin, unsigned int alt0, unsigned int alt1, unsigned int dir, const char *name) { diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c index ff9991cddeaa..d674f1be237d 100644 --- a/arch/mips/lantiq/xway/gpio_stp.c +++ b/arch/mips/lantiq/xway/gpio_stp.c @@ -78,11 +78,6 @@ static struct gpio_chip ltq_stp_chip = { static int ltq_stp_hw_init(void) { - /* the 3 pins used to control the external stp */ - ltq_gpio_request(4, 1, 0, 1, "stp-st"); - ltq_gpio_request(5, 1, 0, 1, "stp-d"); - ltq_gpio_request(6, 1, 0, 1, "stp-sh"); - /* sane defaults */ ltq_stp_w32(0, LTQ_STP_AR); ltq_stp_w32(0, LTQ_STP_CPU0); diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 030c77e7926e..4d8c49beeda4 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -68,32 +68,6 @@ #define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_mapped_cfg + (y)) #define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_mapped_cfg + (x)) -struct ltq_pci_gpio_map { - int pin; - int alt0; - int alt1; - int dir; - char *name; -}; - -/* the pci core can make use of the following gpios */ -static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = { - { 0, 1, 0, 0, "pci-exin0" }, - { 1, 1, 0, 0, "pci-exin1" }, - { 2, 1, 0, 0, "pci-exin2" }, - { 39, 1, 0, 0, "pci-exin3" }, - { 10, 1, 0, 0, "pci-exin4" }, - { 9, 1, 0, 0, "pci-exin5" }, - { 30, 1, 0, 1, "pci-gnt1" }, - { 23, 1, 0, 1, "pci-gnt2" }, - { 19, 1, 0, 1, "pci-gnt3" }, - { 38, 1, 0, 1, "pci-gnt4" }, - { 29, 1, 0, 0, "pci-req1" }, - { 31, 1, 0, 0, "pci-req2" }, - { 3, 1, 0, 0, "pci-req3" }, - { 37, 1, 0, 0, "pci-req4" }, -}; - __iomem void *ltq_pci_mapped_cfg; static __iomem void *ltq_pci_membase; @@ -151,22 +125,6 @@ static u32 ltq_calc_bar11mask(void) return bar11mask; } -static void ltq_pci_setup_gpio(int gpio) -{ - int i; - for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) { - if (gpio & (1 << i)) { - ltq_gpio_request(ltq_pci_gpio_map[i].pin, - ltq_pci_gpio_map[i].alt0, - ltq_pci_gpio_map[i].alt1, - ltq_pci_gpio_map[i].dir, - ltq_pci_gpio_map[i].name); - } - } - ltq_gpio_request(21, 0, 0, 1, "pci-reset"); - ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK; -} - static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) { u32 temp_buffer; @@ -192,7 +150,7 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) } /* setup pci clock and gpis used by pci */ - ltq_pci_setup_gpio(conf->gpio); + gpio_request(21, "pci-reset"); /* enable auto-switching between PCI and EBU */ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); -- cgit v1.2.3 From 57c8cb8f242988b8048a7058cd1edde025c6f232 Mon Sep 17 00:00:00 2001 From: John Crispin Date: Fri, 11 May 2012 18:47:30 +0200 Subject: MIPS: pci: convert lantiq driver to OF Implement support for OF inside the lantiq PCI driver. The patch also splits pcibios_plat_dev_init and pcibios_map_irq out into their own file to accomodate coexistance with the upcoming pcie driver. Signed-off-by: John Crispin Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/3806/ Signed-off-by: Ralf Baechle --- arch/mips/lantiq/Kconfig | 5 +- arch/mips/pci/Makefile | 3 +- arch/mips/pci/fixup-lantiq.c | 40 ++++++++++ arch/mips/pci/pci-lantiq.c | 177 +++++++++++++++++++++---------------------- 4 files changed, 131 insertions(+), 94 deletions(-) create mode 100644 arch/mips/pci/fixup-lantiq.c (limited to 'arch/mips/pci') diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig index 9485fe54752b..7389098fd983 100644 --- a/arch/mips/lantiq/Kconfig +++ b/arch/mips/lantiq/Kconfig @@ -18,7 +18,6 @@ config SOC_XWAY select HW_HAS_PCI endchoice - choice prompt "Devicetree" @@ -27,4 +26,8 @@ config DT_EASY50712 depends on SOC_XWAY endchoice +config PCI_LANTIQ + bool "PCI Support" + depends on SOC_XWAY && PCI + endif diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile index c3ac4b086eb2..499a019c2c5f 100644 --- a/arch/mips/pci/Makefile +++ b/arch/mips/pci/Makefile @@ -41,7 +41,8 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o -obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o +obj-$(CONFIG_LANTIQ) += fixup-lantiq.o +obj-$(CONFIG_PCI_LANTIQ) += pci-lantiq.o ops-lantiq.o obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o diff --git a/arch/mips/pci/fixup-lantiq.c b/arch/mips/pci/fixup-lantiq.c new file mode 100644 index 000000000000..6c829df28dc7 --- /dev/null +++ b/arch/mips/pci/fixup-lantiq.c @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published + * by the Free Software Foundation. + * + * Copyright (C) 2012 John Crispin + */ + +#include +#include + +int (*ltq_pci_plat_arch_init)(struct pci_dev *dev) = NULL; +int (*ltq_pci_plat_dev_init)(struct pci_dev *dev) = NULL; + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + if (ltq_pci_plat_arch_init) + return ltq_pci_plat_arch_init(dev); + + if (ltq_pci_plat_dev_init) + return ltq_pci_plat_dev_init(dev); + + return 0; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + struct of_irq dev_irq; + int irq; + + if (of_irq_map_pci(dev, &dev_irq)) { + dev_err(&dev->dev, "trying to map irq for unknown slot:%d pin:%d\n", + slot, pin); + return 0; + } + irq = irq_create_of_mapping(dev_irq.controller, dev_irq.specifier, + dev_irq.size); + dev_info(&dev->dev, "SLOT:%d PIN:%d IRQ:%d\n", slot, pin, irq); + return irq; +} diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c index 4d8c49beeda4..ea453532a33c 100644 --- a/arch/mips/pci/pci-lantiq.c +++ b/arch/mips/pci/pci-lantiq.c @@ -13,8 +13,12 @@ #include #include #include -#include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -22,17 +26,9 @@ #include #include -#include #include "pci-lantiq.h" -#define LTQ_PCI_CFG_BASE 0x17000000 -#define LTQ_PCI_CFG_SIZE 0x00008000 -#define LTQ_PCI_MEM_BASE 0x18000000 -#define LTQ_PCI_MEM_SIZE 0x02000000 -#define LTQ_PCI_IO_BASE 0x1AE00000 -#define LTQ_PCI_IO_SIZE 0x00200000 - #define PCI_CR_FCI_ADDR_MAP0 0x00C0 #define PCI_CR_FCI_ADDR_MAP1 0x00C4 #define PCI_CR_FCI_ADDR_MAP2 0x00C8 @@ -71,50 +67,24 @@ __iomem void *ltq_pci_mapped_cfg; static __iomem void *ltq_pci_membase; -int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL; - -/* Since the PCI REQ pins can be reused for other functionality, make it - possible to exclude those from interpretation by the PCI controller */ -static int ltq_pci_req_mask = 0xf; - -static int *ltq_pci_irq_map; - -struct pci_ops ltq_pci_ops = { +static int reset_gpio; +static struct clk *clk_pci, *clk_external; +static struct resource pci_io_resource; +static struct resource pci_mem_resource; +static struct pci_ops pci_ops = { .read = ltq_pci_read_config_dword, .write = ltq_pci_write_config_dword }; -static struct resource pci_io_resource = { - .name = "pci io space", - .start = LTQ_PCI_IO_BASE, - .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1, - .flags = IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - .name = "pci memory space", - .start = LTQ_PCI_MEM_BASE, - .end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1, - .flags = IORESOURCE_MEM -}; - -static struct pci_controller ltq_pci_controller = { - .pci_ops = <q_pci_ops, +static struct pci_controller pci_controller = { + .pci_ops = &pci_ops, .mem_resource = &pci_mem_resource, .mem_offset = 0x00000000UL, .io_resource = &pci_io_resource, .io_offset = 0x00000000UL, }; -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - if (ltqpci_plat_dev_init) - return ltqpci_plat_dev_init(dev); - - return 0; -} - -static u32 ltq_calc_bar11mask(void) +static inline u32 ltq_calc_bar11mask(void) { u32 mem, bar11mask; @@ -125,32 +95,42 @@ static u32 ltq_calc_bar11mask(void) return bar11mask; } -static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) +static int __devinit ltq_pci_startup(struct platform_device *pdev) { + struct device_node *node = pdev->dev.of_node; + const __be32 *req_mask, *bus_clk; u32 temp_buffer; - /* set clock to 33Mhz */ - if (ltq_is_ar9()) { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR); - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR); - } else { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR); - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR); + /* get our clocks */ + clk_pci = clk_get(&pdev->dev, NULL); + if (IS_ERR(clk_pci)) { + dev_err(&pdev->dev, "failed to get pci clock\n"); + return PTR_ERR(clk_pci); } - /* external or internal clock ? */ - if (conf->clock) { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16), - LTQ_CGU_IFCCR); - ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR); - } else { - ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16), - LTQ_CGU_IFCCR); - ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR); + clk_external = clk_get(&pdev->dev, "external"); + if (IS_ERR(clk_external)) { + clk_put(clk_pci); + dev_err(&pdev->dev, "failed to get external pci clock\n"); + return PTR_ERR(clk_external); } - /* setup pci clock and gpis used by pci */ - gpio_request(21, "pci-reset"); + /* read the bus speed that we want */ + bus_clk = of_get_property(node, "lantiq,bus-clock", NULL); + if (bus_clk) + clk_set_rate(clk_pci, *bus_clk); + + /* and enable the clocks */ + clk_enable(clk_pci); + if (of_find_property(node, "lantiq,external-clock", NULL)) + clk_enable(clk_external); + else + clk_disable(clk_external); + + /* setup reset gpio used by pci */ + reset_gpio = of_get_named_gpio(node, "gpio-reset", 0); + if (reset_gpio > 0) + devm_gpio_request(&pdev->dev, reset_gpio, "pci-reset"); /* enable auto-switching between PCI and EBU */ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL); @@ -163,7 +143,12 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) /* enable external 2 PCI masters */ temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB); - temp_buffer &= (~(ltq_pci_req_mask << 16)); + /* setup the request mask */ + req_mask = of_get_property(node, "req-mask", NULL); + if (req_mask) + temp_buffer &= ~((*req_mask & 0xf) << 16); + else + temp_buffer &= ~0xf0000; /* enable internal arbiter */ temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); /* enable internal PCI master reqest */ @@ -207,47 +192,55 @@ static int __devinit ltq_pci_startup(struct ltq_pci_data *conf) ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN); /* toggle reset pin */ - __gpio_set_value(21, 0); - wmb(); - mdelay(1); - __gpio_set_value(21, 1); - return 0; -} - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - if (ltq_pci_irq_map[slot]) - return ltq_pci_irq_map[slot]; - printk(KERN_ERR "lq_pci: trying to map irq for unknown slot %d\n", - slot); - + if (reset_gpio > 0) { + __gpio_set_value(reset_gpio, 0); + wmb(); + mdelay(1); + __gpio_set_value(reset_gpio, 1); + } return 0; } static int __devinit ltq_pci_probe(struct platform_device *pdev) { - struct ltq_pci_data *ltq_pci_data = - (struct ltq_pci_data *) pdev->dev.platform_data; + struct resource *res_cfg, *res_bridge; pci_clear_flags(PCI_PROBE_ONLY); - ltq_pci_irq_map = ltq_pci_data->irq; - ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE); - ltq_pci_mapped_cfg = - ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE); - ltq_pci_controller.io_map_base = - (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1); - ltq_pci_startup(ltq_pci_data); - register_pci_controller(<q_pci_controller); + res_cfg = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res_bridge = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res_cfg || !res_bridge) { + dev_err(&pdev->dev, "missing memory reources\n"); + return -EINVAL; + } + + ltq_pci_membase = devm_request_and_ioremap(&pdev->dev, res_bridge); + ltq_pci_mapped_cfg = devm_request_and_ioremap(&pdev->dev, res_cfg); + + if (!ltq_pci_membase || !ltq_pci_mapped_cfg) { + dev_err(&pdev->dev, "failed to remap resources\n"); + return -ENOMEM; + } + + ltq_pci_startup(pdev); + + pci_load_of_ranges(&pci_controller, pdev->dev.of_node); + register_pci_controller(&pci_controller); return 0; } -static struct platform_driver -ltq_pci_driver = { +static const struct of_device_id ltq_pci_match[] = { + { .compatible = "lantiq,pci-xway" }, + {}, +}; +MODULE_DEVICE_TABLE(of, ltq_pci_match); + +static struct platform_driver ltq_pci_driver = { .probe = ltq_pci_probe, .driver = { - .name = "ltq_pci", + .name = "pci-xway", .owner = THIS_MODULE, + .of_match_table = ltq_pci_match, }, }; @@ -255,7 +248,7 @@ int __init pcibios_init(void) { int ret = platform_driver_register(<q_pci_driver); if (ret) - printk(KERN_INFO "ltq_pci: Error registering platfom driver!"); + pr_info("pci-xway: Error registering platform driver!"); return ret; } -- cgit v1.2.3