From 541ff27cfb26939cf1b98b73fa5aeea0d8432082 Mon Sep 17 00:00:00 2001 From: matteo Date: Sun, 11 May 2008 19:43:00 +0000 Subject: atheros: USB support git-svn-id: svn://svn.openwrt.org/openwrt/trunk@11113 3c298f89-4303-0410-b956-a3cf2f4a3e73 --- target/linux/atheros/Makefile | 4 +- target/linux/atheros/config-2.6.25 | 26 ++- .../linux/atheros/files/arch/mips/atheros/Kconfig | 20 +- .../files/arch/mips/atheros/ar5315/Makefile | 1 + .../atheros/files/arch/mips/atheros/ar5315/irq.c | 28 +++ .../atheros/files/arch/mips/atheros/ar5315/pci.c | 253 +++++++++++++++++++++ .../include/asm-mips/mach-atheros/dma-coherence.h | 4 - 7 files changed, 323 insertions(+), 13 deletions(-) create mode 100644 target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c (limited to 'target/linux/atheros') diff --git a/target/linux/atheros/Makefile b/target/linux/atheros/Makefile index ab301ba509..6a88fc5a05 100644 --- a/target/linux/atheros/Makefile +++ b/target/linux/atheros/Makefile @@ -9,9 +9,9 @@ include $(TOPDIR)/rules.mk ARCH:=mips BOARD:=atheros BOARDNAME:=Atheros 231x/5312 -FEATURES:=squashfs jffs2 +FEATURES:=squashfs jffs2 pci usb -LINUX_VERSION:=2.6.23.16 +LINUX_VERSION:=2.6.25.1 include $(INCLUDE_DIR)/target.mk diff --git a/target/linux/atheros/config-2.6.25 b/target/linux/atheros/config-2.6.25 index 4b978403bc..2408411f5e 100644 --- a/target/linux/atheros/config-2.6.25 +++ b/target/linux/atheros/config-2.6.25 @@ -10,8 +10,11 @@ CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_ATHEROS=y CONFIG_ATHEROS_AR5312=y CONFIG_ATHEROS_AR5315=y +CONFIG_ATHEROS_AR5315_PCI=y # CONFIG_ATM is not set +# CONFIG_ATMEL is not set CONFIG_BASE_SMALL=0 +# CONFIG_BCM43XX is not set # CONFIG_BCM47XX is not set CONFIG_BITREVERSE=y # CONFIG_BROADCOM_PHY is not set @@ -52,6 +55,7 @@ CONFIG_CRYPTO_AEAD=m CONFIG_CRYPTO_AUTHENC=m CONFIG_CRYPTO_GF128MUL=m CONFIG_CSRC_R4K=y +CONFIG_DEVPORT=y # CONFIG_DM9000 is not set CONFIG_DMA_NEED_PCI_MAP_STATE=y CONFIG_DMA_NONCOHERENT=y @@ -71,7 +75,9 @@ CONFIG_HAVE_IDE=y # CONFIG_HAVE_KPROBES is not set # CONFIG_HAVE_KRETPROBES is not set CONFIG_HAVE_OPROFILE=y +# CONFIG_HERMES is not set # CONFIG_HOSTAP is not set +CONFIG_HW_HAS_PCI=y CONFIG_HW_RANDOM=y # CONFIG_I2C is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set @@ -80,8 +86,9 @@ CONFIG_HW_RANDOM=y # CONFIG_IBM_NEW_EMAC_ZMII is not set CONFIG_ICPLUS_PHY=y # CONFIG_IDE is not set -# CONFIG_IEEE80211 is not set CONFIG_INITRAMFS_SOURCE="" +# CONFIG_IPW2100 is not set +# CONFIG_IPW2200 is not set CONFIG_IRQ_CPU=y # CONFIG_LEDS_ALIX is not set # CONFIG_LEDS_GPIO is not set @@ -94,6 +101,7 @@ CONFIG_LZO_DECOMPRESS=m # CONFIG_MACH_VR41XX is not set # CONFIG_MDIO_BITBANG is not set # CONFIG_MEMSTICK is not set +CONFIG_MII=m CONFIG_MIPS=y # CONFIG_MIPS_ATLAS is not set # CONFIG_MIPS_COBALT is not set @@ -143,12 +151,14 @@ CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_ONENAND is not set # CONFIG_MTD_OTP is not set CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PCI is not set # CONFIG_MTD_PHRAM is not set CONFIG_MTD_PHYSMAP=y CONFIG_MTD_PHYSMAP_BANKWIDTH=0 CONFIG_MTD_PHYSMAP_LEN=0x0 CONFIG_MTD_PHYSMAP_START=0x0 # CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set # CONFIG_MTD_RAM is not set CONFIG_MTD_REDBOOT_DIRECTORY_BLOCK=-3 CONFIG_MTD_REDBOOT_PARTS=y @@ -156,17 +166,23 @@ CONFIG_MTD_REDBOOT_PARTS_READONLY=y # CONFIG_MTD_ROM is not set # CONFIG_MTD_SLRAM is not set CONFIG_MTD_SPIFLASH=y +# CONFIG_NET_PCI is not set +# CONFIG_NET_VENDOR_3COM is not set CONFIG_NEW_GPIO=y # CONFIG_NO_IOPORT is not set # CONFIG_PAGE_SIZE_16KB is not set CONFIG_PAGE_SIZE_4KB=y # CONFIG_PAGE_SIZE_64KB is not set # CONFIG_PAGE_SIZE_8KB is not set +CONFIG_PCI=y +# CONFIG_PCIPCWATCHDOG is not set +CONFIG_PCI_DOMAINS=y CONFIG_PHYLIB=y # CONFIG_PMC_MSP is not set # CONFIG_PMC_YOSEMITE is not set # CONFIG_PNX8550_JBS is not set # CONFIG_PNX8550_STB810 is not set +# CONFIG_PRISM54 is not set # CONFIG_QSEMI_PHY is not set # CONFIG_REALTEK_PHY is not set # CONFIG_RTC is not set @@ -206,9 +222,11 @@ CONFIG_TICK_ONESHOT=y # CONFIG_TOSHIBA_RBTX4927 is not set # CONFIG_TOSHIBA_RBTX4938 is not set CONFIG_TRAD_SIGNALS=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set +CONFIG_USB=m +# CONFIG_USBPCWATCHDOG is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set +# CONFIG_USB_UHCI_HCD is not set # CONFIG_VGASTATE is not set CONFIG_VIDEO_V4L2_COMMON=m CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/atheros/files/arch/mips/atheros/Kconfig b/target/linux/atheros/files/arch/mips/atheros/Kconfig index 2170fd710b..953f0cb5b1 100644 --- a/target/linux/atheros/files/arch/mips/atheros/Kconfig +++ b/target/linux/atheros/files/arch/mips/atheros/Kconfig @@ -1,4 +1,3 @@ - config ATHEROS_AR5312 bool "Atheros 5312/2312+ support" depends on ATHEROS @@ -7,7 +6,22 @@ config ATHEROS_AR5312 config ATHEROS_AR5315 bool "Atheros 5315/2315+ support" depends on ATHEROS + select DMA_NONCOHERENT + select CEVT_R4K + select CSRC_R4K + select IRQ_CPU + select SYS_HAS_CPU_MIPS32_R1 + select SYS_SUPPORTS_32BIT_KERNEL + select SYS_SUPPORTS_BIG_ENDIAN + select GENERIC_GPIO default y - - +config ATHEROS_AR5315_PCI + bool "PCI support" + select HW_HAS_PCI + select PCI + select USB_ARCH_HAS_HCD + select USB_ARCH_HAS_OHCI + select USB_ARCH_HAS_EHCI + depends on ATHEROS_AR5315 + default n diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/Makefile b/target/linux/atheros/files/arch/mips/atheros/ar5315/Makefile index 6c50d9931d..9b900113ff 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5315/Makefile +++ b/target/linux/atheros/files/arch/mips/atheros/ar5315/Makefile @@ -9,3 +9,4 @@ # obj-y := board.o irq.o +obj-$(CONFIG_ATHEROS_AR5315_PCI) += pci.o diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c b/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c index 69cb362a00..581b1a4a10 100644 --- a/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c +++ b/target/linux/atheros/files/arch/mips/atheros/ar5315/irq.c @@ -60,6 +60,10 @@ asmlinkage void ar5315_irq_dispatch(void) do_IRQ(AR5315_IRQ_WLAN0_INTRS); else if (pending & CAUSEF_IP4) do_IRQ(AR5315_IRQ_ENET0_INTRS); +#ifdef CONFIG_PCI + else if (pending & CAUSEF_IP5) + ar5315_pci_irq(AR5315_IRQ_LCBUS_PCI); +#endif else if (pending & CAUSEF_IP2) { unsigned int ar531x_misc_intrs = sysRegRead(AR5315_ISR) & sysRegRead(AR5315_IMR); @@ -81,6 +85,30 @@ asmlinkage void ar5315_irq_dispatch(void) do_IRQ(AR531X_IRQ_CPU_CLOCK); } +#ifdef CONFIG_PCI +static inline void pci_abort_irq(void) +{ + sysRegWrite(AR5315_PCI_INT_STATUS, AR5315_PCI_ABORT_INT); + (void)sysRegRead(AR5315_PCI_INT_STATUS); /* flush write to hardware */ +} + +static inline void pci_ack_irq(void) +{ + sysRegWrite(AR5315_PCI_INT_STATUS, AR5315_PCI_EXT_INT); + (void)sysRegRead(AR5315_PCI_INT_STATUS); /* flush write to hardware */ +} + +void ar5315_pci_irq(int irq) +{ + if (sysRegRead(AR5315_PCI_INT_STATUS) == AR5315_PCI_ABORT_INT) + pci_abort_irq(); + else { + do_IRQ(irq); + pci_ack_irq(); + } +} +#endif + static void ar5315_gpio_intr_enable(unsigned int irq) { u32 gpio, mask; diff --git a/target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c b/target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c new file mode 100644 index 0000000000..0213b34719 --- /dev/null +++ b/target/linux/atheros/files/arch/mips/atheros/ar5315/pci.c @@ -0,0 +1,253 @@ +/* + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ar531x.h" + +#define AR531X_MEM_BASE 0x80800000UL +#define AR531X_MEM_SIZE 0x00ffffffUL +#define AR531X_IO_SIZE 0x00007fffUL + +#define IDSEL_SHIFT 13 + +static spinlock_t ar531x_pci_lock = SPIN_LOCK_UNLOCKED; +static u32 cfgaddr; + +static int config_access(int busno, int dev, int func, int where, int size, u32 ptr, int write) +{ + u32 address; /* Address to read from */ + u32 reg; + unsigned long flags; + int ret = -1; + + if ((busno != 0) || (dev > 3) || (func > 2)) + return ret; + + spin_lock_irqsave(&ar531x_pci_lock, flags); + + /* Select Configuration access */ + reg = sysRegRead(AR5315_PCI_MISC_CONFIG); + reg |= AR5315_PCIMISC_CFG_SEL; + sysRegWrite(AR5315_PCI_MISC_CONFIG, reg); + (void)sysRegRead(AR5315_PCI_MISC_CONFIG); + + address = (u32)cfgaddr + (1 << (IDSEL_SHIFT + dev)) + (func << 8) + where; + + if (size == 1) + address ^= 0x3; + else if (size == 2) + address ^= 0x2; + + if (write) { + if (size == 1) + ret = put_dbe(ptr, (u8 *) address); + else if (size == 2) + ret = put_dbe(ptr, (u16 *) address); + else if (size == 4) + ret = put_dbe(ptr, (u32 *) address); + } else { + if (size == 1) + ret = get_dbe(*((u32 *)ptr), (u8 *) address); + else if (size == 2) + ret = get_dbe(*((u32 *)ptr), (u16 *) address); + else if (size == 4) + ret = get_dbe(*((u32 *)ptr), (u32 *) address); + } + + /* Select Memory access */ + reg = sysRegRead(AR5315_PCI_MISC_CONFIG); + reg &= ~AR5315_PCIMISC_CFG_SEL; + sysRegWrite(AR5315_PCI_MISC_CONFIG, reg); + (void)sysRegRead(AR5315_PCI_MISC_CONFIG); + + spin_unlock_irqrestore(&ar531x_pci_lock, flags); + + if (ret) { + *((u32 *)ptr) = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return PCIBIOS_SUCCESSFUL; +} + +static int ar531x_pci_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * value) +{ + return config_access(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, (u32) value, 0); +} + +static int ar531x_pci_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) +{ + return config_access(bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), where, size, value, 1); +} + +struct pci_ops ar531x_pci_ops = { + .read = ar531x_pci_read, + .write = ar531x_pci_write, +}; + +static struct resource ar531x_mem_resource = { + .name = "AR531x PCI MEM", + .start = AR531X_MEM_BASE, + .end = AR531X_MEM_BASE + AR531X_MEM_SIZE - AR531X_IO_SIZE - 1, + .flags = IORESOURCE_MEM, +}; + +static struct resource ar531x_io_resource = { + .name = "AR531x PCI I/O", + .start = 0, + .end = AR531X_IO_SIZE, + .flags = IORESOURCE_IO, +}; + +struct pci_controller ar531x_pci_controller = { + .pci_ops = &ar531x_pci_ops, + .mem_resource = &ar531x_mem_resource, + .io_resource = &ar531x_io_resource, +}; + +int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + return AR5315_IRQ_LCBUS_PCI; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + u32 reg; + + pci_write_config_byte(dev, PCI_INTERRUPT_LINE, 5); + pci_write_config_word(dev, 0x40, 0); + + /* Clear any pending Abort or external Interrupts + * and enable interrupt processing */ + reg = sysRegRead(AR5315_PCI_INTEN_REG); + reg &= ~AR5315_PCI_INT_ENABLE; + sysRegWrite(AR5315_PCI_INTEN_REG, reg); + + reg = sysRegRead(AR5315_PCI_INT_STATUS); + reg |= (AR5315_PCI_ABORT_INT | AR5315_PCI_EXT_INT); + sysRegWrite(AR5315_PCI_INT_STATUS, reg); + + reg = sysRegRead(AR5315_PCI_INT_MASK); + reg |= (AR5315_PCI_EXT_INT | AR5315_PCI_ABORT_INT); + sysRegWrite(AR5315_PCI_INT_MASK, reg); + + reg = sysRegRead(AR5315_PCI_INTEN_REG); + reg |= AR5315_PCI_INT_ENABLE; + sysRegWrite(AR5315_PCI_INTEN_REG, reg); + + return 0; +} + +static void ar5315_pci_fixup(struct pci_dev *dev) +{ + struct pci_bus *bus = dev->bus; + + if ((PCI_SLOT(dev->devfn) != 3) || (PCI_FUNC(dev->devfn) != 0) || (bus->number != 0)) + return; + +#define _DEV bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn) + printk("PCI: fixing up device %d,%d,%d\n", _DEV); + /* fix up mbars */ + config_access(_DEV, PCI_BASE_ADDRESS_0, 4, HOST_PCI_MBAR0, 1); + config_access(_DEV, PCI_BASE_ADDRESS_1, 4, HOST_PCI_MBAR1, 1); + config_access(_DEV, PCI_BASE_ADDRESS_2, 4, HOST_PCI_MBAR2, 1); + config_access(_DEV, PCI_COMMAND, 4, + PCI_COMMAND_MEMORY|PCI_COMMAND_MASTER|PCI_COMMAND_SPECIAL| + PCI_COMMAND_INVALIDATE|PCI_COMMAND_PARITY|PCI_COMMAND_SERR| + PCI_COMMAND_FAST_BACK, 1); +#undef _DEV +} +DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, ar5315_pci_fixup); + +int __init ar5315_pci_init(void) +{ + u32 reg; + + printk("AR531x PCI init... "); + + cfgaddr = (u32) ioremap_nocache(0x80000000, 1*1024*1024); /* Remap PCI config space */ + set_io_port_base((unsigned long) ioremap_nocache(AR531X_MEM_BASE + AR531X_IO_SIZE - 1, AR531X_IO_SIZE)); /* PCI I/O space */ + + reg = sysRegRead(AR5315_RESET); + sysRegWrite(AR5315_RESET, reg | AR5315_RESET_PCIDMA); + + udelay(10*1000); + + sysRegWrite(AR5315_RESET, reg & ~AR5315_RESET_PCIDMA); + sysRegRead(AR5315_RESET); /* read after */ + + udelay(10*1000); + + reg = sysRegRead(AR5315_ENDIAN_CTL); + reg |= AR5315_CONFIG_PCIAHB | AR5315_CONFIG_PCIAHB_BRIDGE; + + sysRegWrite(AR5315_ENDIAN_CTL, reg); + + reg = sysRegRead(AR5315_PCICLK); + reg = 4; + sysRegWrite(AR5315_PCICLK, reg); + + reg = sysRegRead(AR5315_AHB_ARB_CTL); + reg |= (ARB_PCI); + sysRegWrite(AR5315_AHB_ARB_CTL, reg); + + reg = sysRegRead(AR5315_IF_CTL); + reg &= ~(IF_PCI_CLK_MASK | IF_MASK); + reg |= (IF_PCI | IF_PCI_HOST | IF_PCI_INTR | (IF_PCI_CLK_OUTPUT_CLK << IF_PCI_CLK_SHIFT)); + + sysRegWrite(AR5315_IF_CTL, reg); + + /* Reset the PCI bus by setting bits 5-4 in PCI_MCFG */ + reg = sysRegRead(AR5315_PCI_MISC_CONFIG); + reg &= ~(AR5315_PCIMISC_RST_MODE); + reg |= AR5315_PCIRST_LOW; + sysRegWrite(AR5315_PCI_MISC_CONFIG, reg); + + /* wait for 100 ms */ + udelay(100*1000); + + /* Bring the PCI out of reset */ + reg = sysRegRead(AR5315_PCI_MISC_CONFIG); + reg &= ~(AR5315_PCIMISC_RST_MODE); + reg |= (AR5315_PCIRST_HIGH | AR5315_PCICACHE_DIS | 0x8); + sysRegWrite(AR5315_PCI_MISC_CONFIG, reg); + + sysRegWrite(AR5315_PCI_UNCACHE_CFG, + 0x1E | /* 1GB uncached */ + (1 << 5) | /* Enable uncached */ + (0x2 << 30) /* Base: 0x80000000 */ + ); + (void)sysRegRead(AR5315_PCI_UNCACHE_CFG); /* flush */ + + udelay(500*1000); + + register_pci_controller(&ar531x_pci_controller); + + printk("done\n"); + return 0; +} + +arch_initcall(ar5315_pci_init); diff --git a/target/linux/atheros/files/include/asm-mips/mach-atheros/dma-coherence.h b/target/linux/atheros/files/include/asm-mips/mach-atheros/dma-coherence.h index 34e5a85070..fe53556881 100644 --- a/target/linux/atheros/files/include/asm-mips/mach-atheros/dma-coherence.h +++ b/target/linux/atheros/files/include/asm-mips/mach-atheros/dma-coherence.h @@ -10,11 +10,7 @@ #ifndef __ASM_MACH_GENERIC_DMA_COHERENCE_H #define __ASM_MACH_GENERIC_DMA_COHERENCE_H -#if 0 #define PCI_DMA_OFFSET 0x20000000 -#else -#define PCI_DMA_OFFSET 0x00000000 -#endif struct device; -- cgit v1.2.3