From: Florian Fainelli Date: Sat, 10 Jan 2015 18:08:53 +0000 (+0000) Subject: adm5120: move files to files-3.8 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=c119814b2bf25bc89a5cbfb3eb791ad7461d0c38;p=librecmc%2Flibrecmc.git adm5120: move files to files-3.8 In preparation for adding new kernel support Signed-off-by: Florian Fainelli SVN-Revision: 43914 --- diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/Kconfig b/target/linux/adm5120/files-3.8/arch/mips/adm5120/Kconfig new file mode 100644 index 0000000000..be35a8f72e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/Kconfig @@ -0,0 +1,197 @@ +if ADM5120 + +menu "ADM5120 Board selection" + +config ADM5120_MACH_CAS_771 + bool "Cellvision CAS-771/771W support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_CELLVISION + default y + +config ADM5120_MACH_NFS_101 + bool "Cellvision NFS-101U/101WU support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_CELLVISION + default y + +config ADM5120_MACH_NP27G + bool "Compex NP27G support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_COMPEX + default y + +config ADM5120_MACH_NP28G + bool "Compex NP28G support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_COMPEX + default y + +config ADM5120_MACH_WP54 + bool "Compex WP54 family support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_COMPEX + default y + +config ADM5120_MACH_EB_214A + bool "EB-214A support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_GENERIC + default y + +config ADM5120_MACH_BR_6104K + bool "Edimax BR-6104K support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_OEM_EDIMAX + default y + +config ADM5120_MACH_BR_6104KP + bool "Edimax BR-6104KP support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_OEM_EDIMAX + default y + +config ADM5120_MACH_BR_61X4WG + bool "Edimax BR-6104WG/6114WG support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_EDIMAX + default y + +config ADM5120_MACH_EASY5120_RT + bool "Infineon EASY 5120-RT Reference Board support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_INFINEON + default y + +config ADM5120_MACH_EASY5120_WVOIP + bool "Infineon EASY 5120-WVoIP Reference Board support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_INFINEON + default y + +config ADM5120_MACH_EASY5120P_ATA + bool "Infineon EASY 5120P-ATA Reference Board support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_OEM_INFINEON + default y + +config ADM5120_MACH_EASY83000 + bool "Infineon EASY 83000 Reference Board support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_OEM_INFINEON + default y + +config ADM5120_MACH_RB_11X + bool "MikroTik RouterBOARD 111/112 support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_RB_133 + bool "MikroTik RouterBOARD 133 support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_RB_133C + bool "MikroTik RouterBOARD 133C support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_RB_150 + bool "MikroTik RouterBOARD 150 support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_RB_153 + bool "MikroTik RouterBOARD 153 support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_RB_192 + bool "MikroTik RouterBOARD 192 support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MIKROTIK + default y + +config ADM5120_MACH_PMUGW + bool "Motorola Powerline MU Gateway" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_MOTOROLA + default y + +config ADM5120_MACH_5GXI + bool "OSBRiDGE 5GXi/5XLi support" + depends on CPU_LITTLE_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_OSBRIDGE + default y + +config ADM5120_MACH_P_334WT + bool "ZyXEL Prestige 334WT" + depends on CPU_BIG_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_ZYXEL + default y + +config ADM5120_MACH_P_335 + bool "ZyXEL Prestige 335/335WT" + depends on CPU_BIG_ENDIAN + select ADM5120_SOC_BGA + select ADM5120_OEM_ZYXEL + default y + +endmenu + +config ADM5120_SOC_BGA + select HW_HAS_PCI + def_bool n + +config ADM5120_OEM_CELLVISION + def_bool n + +config ADM5120_OEM_COMPEX + def_bool n + +config ADM5120_OEM_EDIMAX + def_bool n + +config ADM5120_OEM_GENERIC + def_bool n + +config ADM5120_OEM_INFINEON + def_bool n + +config ADM5120_OEM_MIKROTIK + def_bool n + +config ADM5120_OEM_MOTOROLA + def_bool n + +config ADM5120_OEM_OSBRIDGE + def_bool n + +config ADM5120_OEM_ZYXEL + def_bool n + +config ARM_AMBA + def_bool y + +endif diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/Platform b/target/linux/adm5120/files-3.8/arch/mips/adm5120/Platform new file mode 100644 index 0000000000..0c9edf218b --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/Platform @@ -0,0 +1,19 @@ +# +# Infineon/ADMtek ADM5120 +# + +platform-$(CONFIG_ADM5120) += adm5120/common/ + +platform-$(CONFIG_ADM5120_OEM_CELLVISION) += adm5120/cellvision/ +platform-$(CONFIG_ADM5120_OEM_COMPEX) += adm5120/compex/ +platform-$(CONFIG_ADM5120_OEM_EDIMAX) += adm5120/edimax/ +platform-$(CONFIG_ADM5120_OEM_GENERIC) += adm5120/generic/ +platform-$(CONFIG_ADM5120_OEM_INFINEON) += adm5120/infineon/ +platform-$(CONFIG_ADM5120_OEM_MIKROTIK) += adm5120/mikrotik/ +platform-$(CONFIG_ADM5120_OEM_MOTOROLA) += adm5120/motorola/ +platform-$(CONFIG_ADM5120_OEM_OSBRIDGE) += adm5120/osbridge/ +platform-$(CONFIG_ADM5120_OEM_ZYXEL) += adm5120/zyxel/ + +cflags-$(CONFIG_ADM5120) += -I$(srctree)/arch/mips/include/asm/mach-adm5120 +libs-$(CONFIG_ADM5120) += arch/mips/adm5120/prom/ +load-$(CONFIG_ADM5120) += 0xffffffff80001000 diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/Makefile new file mode 100644 index 0000000000..a949fc9f61 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/Makefile @@ -0,0 +1,4 @@ +obj-y += cellvision.o + +obj-$(CONFIG_ADM5120_MACH_CAS_771) += cas-771.o +obj-$(CONFIG_ADM5120_MACH_NFS_101) += nfs-101.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cas-771.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cas-771.c new file mode 100644 index 0000000000..5033e02469 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cas-771.c @@ -0,0 +1,37 @@ +/* + * Cellvision/SparkLAN CAS-771/771W support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "cellvision.h" + +static struct adm5120_pci_irq cas771_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), + PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI1), + PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2) +}; + +static struct gpio_led cas771_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN0, "cam_flash", NULL), + /* GPIO PIN3 is the reset */ + GPIO_LED_STD(ADM5120_GPIO_PIN6, "access", NULL), + GPIO_LED_STD(ADM5120_GPIO_P0L1, "status", NULL), + GPIO_LED_STD(ADM5120_GPIO_P0L2, "diag", NULL), +}; + +static void __init cas771_setup(void) +{ + cas7xx_setup(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(cas771_gpio_leds), + cas771_gpio_leds); + adm5120_pci_set_irq_map(ARRAY_SIZE(cas771_pci_irqs), cas771_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_CAS771, "CAS-771", "Cellvision CAS-771/771W", + cas771_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.c new file mode 100644 index 0000000000..a7cedf03bc --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.c @@ -0,0 +1,147 @@ +/* + * Cellvision/SparkLAN boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "cellvision.h" + +#include + +#define CELLVISION_GPIO_FLASH_A20 ADM5120_GPIO_PIN5 +#define CELLVISION_GPIO_DEV_MASK (1 << CELLVISION_GPIO_FLASH_A20) + +#define CELLVISION_CONFIG_OFFSET 0x8000 +#define CELLVISION_CONFIG_SIZE 0x1000 + +static struct mtd_partition cas6xx_partitions[] = { + { + .name = "admboot", + .offset = 0, + .size = 32*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "nvfs1", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, + } , { + .name = "nvfs2", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct mtd_partition cas7xx_partitions[] = { + { + .name = "admboot", + .offset = 0, + .size = 32*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "nvfs", + .offset = MTDPART_OFS_APPEND, + .size = 128*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static void switch_bank_gpio5(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(CELLVISION_GPIO_FLASH_A20, 0); + break; + case 1: + gpio_set_value(CELLVISION_GPIO_FLASH_A20, 1); + break; + } +} + +static void __init cellvision_flash_setup(void) +{ + /* setup flash A20 line */ + gpio_request(CELLVISION_GPIO_FLASH_A20, NULL); + gpio_direction_output(CELLVISION_GPIO_FLASH_A20, 0); + + adm5120_flash0_data.switch_bank = switch_bank_gpio5; + adm5120_add_device_flash(0); +} + +void __init cellvision_mac_setup(void) +{ + u8 mac_base[6]; + int err; + + err = admboot_get_mac_base(CELLVISION_CONFIG_OFFSET, + CELLVISION_CONFIG_SIZE, mac_base); + + if ((err) || !is_valid_ether_addr(mac_base)) + random_ether_addr(mac_base); + + adm5120_setup_eth_macs(mac_base); +} + +void __init cas6xx_flash_setup(void) +{ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas6xx_partitions); + adm5120_flash0_data.parts = cas6xx_partitions; + + cellvision_flash_setup(); +} + +void __init cas7xx_flash_setup(void) +{ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas7xx_partitions); + adm5120_flash0_data.parts = cas7xx_partitions; + + cellvision_flash_setup(); +} + +void __init cas6xx_setup(void) +{ + cas6xx_flash_setup(); + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + adm5120_add_device_switch(1, NULL); +} + +MIPS_MACHINE(MACH_ADM5120_CAS630, "CAS-630", "Cellvision CAS-630/630W", + cas6xx_setup); +MIPS_MACHINE(MACH_ADM5120_CAS670, "CAS-670", "Cellvision CAS-670/670W", + cas6xx_setup); + +void __init cas7xx_setup(void) +{ + cas7xx_flash_setup(); + cellvision_mac_setup(); + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + adm5120_add_device_switch(1, NULL); +} + +MIPS_MACHINE(MACH_ADM5120_CAS700, "CAS-700", "Cellvision CAS-700/700W", + cas7xx_setup); +MIPS_MACHINE(MACH_ADM5120_CAS790, "CAS-790", "Cellvision CAS-790", + cas7xx_setup); +MIPS_MACHINE(MACH_ADM5120_CAS861, "CAS-861", "Cellvision CAS-861/861W", + cas7xx_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.h new file mode 100644 index 0000000000..2b55ebf761 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/cellvision.h @@ -0,0 +1,28 @@ +/* + * Cellvision/SparkLAN boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +extern void cellvision_mac_setup(void) __init; + +extern void cas6xx_flash_setup(void) __init; +extern void cas7xx_flash_setup(void) __init; +extern void cas6xx_setup(void) __init; +extern void cas7xx_setup(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/nfs-101.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/nfs-101.c new file mode 100644 index 0000000000..7d214c0909 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/cellvision/nfs-101.c @@ -0,0 +1,47 @@ +/* + * Cellvision/SparkLAN NFS-101U/WU support + * + * Copyright (C) 2007-2009 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 + * by the Free Software Foundation. + * + */ + +#include "cellvision.h" + +static struct adm5120_pci_irq nfs101_pci_irqs[] __initdata = { + /* miniPCI slot */ + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), + + /* ALi USB controller */ + PCIIRQ(3, 0, 2, ADM5120_IRQ_PCI2), + PCIIRQ(3, 3, 1, ADM5120_IRQ_PCI1), + + /* NEC USB controller */ + PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI1), + PCIIRQ(3, 1, 2, ADM5120_IRQ_PCI2), + PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2), +}; + +static u8 nfs101_vlans[6] __initdata = { + /* FIXME: not tested */ + 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init nfs101_setup(void) +{ + cas6xx_flash_setup(); + cellvision_mac_setup(); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + adm5120_add_device_switch(1, nfs101_vlans); + + adm5120_pci_set_irq_map(ARRAY_SIZE(nfs101_pci_irqs), + nfs101_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_NFS101U, "NFS-101U", "Cellvision NFS-101U/101WU", + nfs101_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/Makefile new file mode 100644 index 0000000000..8d302c5931 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/Makefile @@ -0,0 +1,8 @@ +# +# Makefile for the Infineon/ADMtek ADM5120 SoC specific parts of the kernel +# + +obj-y := adm5120.o setup.o prom.o irq.o memory.o clock.o \ + gpio.o platform.o + +obj-$(CONFIG_EARLY_PRINTK) += early-printk.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/adm5120.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/adm5120.c new file mode 100644 index 0000000000..28388342c6 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/adm5120.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include + +unsigned int adm5120_product_code; +unsigned int adm5120_revision; +unsigned int adm5120_package; +unsigned int adm5120_nand_boot; +unsigned long adm5120_speed; + +/* + * CPU settings detection + */ +#define CODE_GET_PC(c) ((c) & CODE_PC_MASK) +#define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK) +#define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK) +#define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK) +#define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0) + +void adm5120_ndelay(u32 ns) +{ + u32 t; + + SW_WRITE_REG(SWITCH_REG_TIMER, TIMER_PERIOD_DEFAULT); + SW_WRITE_REG(SWITCH_REG_TIMER_INT, (TIMER_INT_TOS | TIMER_INT_TOM)); + + t = (ns+640) / 640; + t &= TIMER_PERIOD_MASK; + SW_WRITE_REG(SWITCH_REG_TIMER, t | TIMER_TE); + + /* wait until the timer expires */ + do { + t = SW_READ_REG(SWITCH_REG_TIMER_INT); + } while ((t & TIMER_INT_TOS) == 0); + + /* leave the timer disabled */ + SW_WRITE_REG(SWITCH_REG_TIMER, TIMER_PERIOD_DEFAULT); + SW_WRITE_REG(SWITCH_REG_TIMER_INT, (TIMER_INT_TOS | TIMER_INT_TOM)); +} + +void __init adm5120_soc_init(void) +{ + u32 code; + u32 clks; + + code = SW_READ_REG(SWITCH_REG_CODE); + + adm5120_product_code = CODE_GET_PC(code); + adm5120_revision = CODE_GET_REV(code); + adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ? + ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP; + adm5120_nand_boot = CODE_GET_NAB(code); + + clks = CODE_GET_CLKS(code); + adm5120_speed = ADM5120_SPEED_175; + if (clks & 1) + adm5120_speed += 25000000; + if (clks & 2) + adm5120_speed += 50000000; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/clock.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/clock.c new file mode 100644 index 0000000000..52ae64c419 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/clock.c @@ -0,0 +1,65 @@ +/* + * ADM5120 minimal CLK API implementation + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was based on the CLK API implementation in: + * arch/mips/tx4938/toshiba_rbtx4938/setup.c + * Copyright (C) 2000-2001 Toshiba Corporation + * 2003-2005 (c) MontaVista Software, Inc. + * + * 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 + +struct clk { + unsigned long rate; +}; + +static struct clk uart_clk = { + .rate = ADM5120_UART_CLOCK +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + const char *name = dev_name(dev); + + if (!strcmp(name, "apb:uart0") || !strcmp(name, "apb:uart1")) + return &uart_clk; + + return ERR_PTR(-ENOENT); +} +EXPORT_SYMBOL(clk_get); + +int clk_enable(struct clk *clk) +{ + return 0; +} +EXPORT_SYMBOL(clk_enable); + +void clk_disable(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_disable); + +unsigned long clk_get_rate(struct clk *clk) +{ + return clk->rate; +} +EXPORT_SYMBOL(clk_get_rate); + +void clk_put(struct clk *clk) +{ +} +EXPORT_SYMBOL(clk_put); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/early-printk.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/early-printk.c new file mode 100644 index 0000000000..d900712639 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/early-printk.c @@ -0,0 +1,31 @@ +/* + * ADM5120 specific early printk support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include + +#include +#include +#include + +#define UART_READ(r) \ + __raw_readl((void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) +#define UART_WRITE(r, v) \ + __raw_writel((v), (void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) + +void __init prom_putchar(char ch) +{ + while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0) + ; + UART_WRITE(UART_REG_DATA, ch); + while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0) + ; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/gpio.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/gpio.c new file mode 100644 index 0000000000..e60ed7ad01 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/gpio.c @@ -0,0 +1,330 @@ +/* + * ADM5120 generic GPIO API support via GPIOLIB + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r) + +struct gpio1_desc { + void __iomem *reg; /* register address */ + u8 iv_shift; /* shift amount for input bit */ + u8 mode_shift; /* shift amount for mode bits */ +}; + +#define GPIO1_DESC(p, l) { \ + .reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \ + .iv_shift = LED0_IV_SHIFT + (l), \ + .mode_shift = (l) * 4 \ + } + +static struct gpio1_desc gpio1_table[15] = { + GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2), + GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2), + GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2), + GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2), + GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2) +}; + +static u32 gpio_conf2; + +int adm5120_gpio_to_irq(unsigned gpio) +{ + int ret; + + switch (gpio) { + case ADM5120_GPIO_PIN2: + ret = ADM5120_IRQ_GPIO2; + break; + case ADM5120_GPIO_PIN4: + ret = ADM5120_IRQ_GPIO4; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL(adm5120_gpio_to_irq); + +int adm5120_irq_to_gpio(unsigned irq) +{ + int ret; + + switch (irq) { + case ADM5120_IRQ_GPIO2: + ret = ADM5120_GPIO_PIN2; + break; + case ADM5120_IRQ_GPIO4: + ret = ADM5120_GPIO_PIN4; + break; + default: + ret = -EINVAL; + break; + } + + return ret; +} +EXPORT_SYMBOL(adm5120_irq_to_gpio); + +/* + * Helpers for GPIO lines in GPIO_CONF0 register + */ +#define PIN_IM(p) ((1 << GPIO_CONF0_IM_SHIFT) << p) +#define PIN_IV(p) ((1 << GPIO_CONF0_IV_SHIFT) << p) +#define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p) +#define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p) + +int __adm5120_gpio0_get_value(unsigned offset) +{ + void __iomem **reg; + u32 t; + + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + if ((t & PIN_IM(offset)) != 0) + t &= PIN_IV(offset); + else + t &= PIN_OV(offset); + + return (t) ? 1 : 0; +} +EXPORT_SYMBOL(__adm5120_gpio0_get_value); + +void __adm5120_gpio0_set_value(unsigned offset, int value) +{ + void __iomem **reg; + u32 t; + + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + if (value == 0) + t &= ~(PIN_OV(offset)); + else + t |= PIN_OV(offset); + + __raw_writel(t, reg); +} +EXPORT_SYMBOL(__adm5120_gpio0_set_value); + +static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __adm5120_gpio0_get_value(offset); +} + +static void adm5120_gpio0_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio0_set_value(offset, value); +} + +static int adm5120_gpio0_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + void __iomem **reg; + u32 t; + + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + t &= ~(PIN_OE(offset)); + t |= PIN_IM(offset); + __raw_writel(t, reg); + + return 0; +} + +static int adm5120_gpio0_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + void __iomem **reg; + u32 t; + + reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); + + t = __raw_readl(reg); + t &= ~(PIN_IM(offset) | PIN_OV(offset)); + t |= PIN_OE(offset); + + if (value) + t |= PIN_OV(offset); + + __raw_writel(t, reg); + + return 0; +} + +static struct gpio_chip adm5120_gpio0_chip = { + .label = "adm5120 gpio0", + .get = adm5120_gpio0_get_value, + .set = adm5120_gpio0_set_value, + .direction_input = adm5120_gpio0_direction_input, + .direction_output = adm5120_gpio0_direction_output, + .base = ADM5120_GPIO_PIN0, + .ngpio = ADM5120_GPIO_PIN7 - ADM5120_GPIO_PIN0 + 1, +}; + +int __adm5120_gpio1_get_value(unsigned offset) +{ + void __iomem **reg; + u32 t, m; + + reg = gpio1_table[offset].reg; + + t = __raw_readl(reg); + m = (t >> gpio1_table[offset].mode_shift) & LED_MODE_MASK; + if (m == LED_MODE_INPUT) + return (t >> gpio1_table[offset].iv_shift) & 1; + + if (m == LED_MODE_OUT_LOW) + return 0; + + return 1; +} +EXPORT_SYMBOL(__adm5120_gpio1_get_value); + +void __adm5120_gpio1_set_value(unsigned offset, int value) +{ + void __iomem **reg; + u32 t, s; + + reg = gpio1_table[offset].reg; + s = gpio1_table[offset].mode_shift; + + t = __raw_readl(reg); + t &= ~(LED_MODE_MASK << s); + + switch (value) { + case ADM5120_GPIO_LOW: + t |= (LED_MODE_OUT_LOW << s); + break; + case ADM5120_GPIO_FLASH: + case ADM5120_GPIO_LINK: + case ADM5120_GPIO_SPEED: + case ADM5120_GPIO_DUPLEX: + case ADM5120_GPIO_ACT: + case ADM5120_GPIO_COLL: + case ADM5120_GPIO_LINK_ACT: + case ADM5120_GPIO_DUPLEX_COLL: + case ADM5120_GPIO_10M_ACT: + case ADM5120_GPIO_100M_ACT: + t |= ((value & LED_MODE_MASK) << s); + break; + default: + t |= (LED_MODE_OUT_HIGH << s); + break; + } + + __raw_writel(t, reg); +} +EXPORT_SYMBOL(__adm5120_gpio1_set_value); + +static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset) +{ + return __adm5120_gpio1_get_value(offset); +} + +static void adm5120_gpio1_set_value(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio1_set_value(offset, value); +} + +static int adm5120_gpio1_direction_input(struct gpio_chip *chip, + unsigned offset) +{ + void __iomem **reg; + u32 t; + + reg = gpio1_table[offset].reg; + t = __raw_readl(reg); + t &= ~(LED_MODE_MASK << gpio1_table[offset].mode_shift); + __raw_writel(t, reg); + + return 0; +} + +static int adm5120_gpio1_direction_output(struct gpio_chip *chip, + unsigned offset, int value) +{ + __adm5120_gpio1_set_value(offset, value); + return 0; +} + +static struct gpio_chip adm5120_gpio1_chip = { + .label = "adm5120 gpio1", + .get = adm5120_gpio1_get_value, + .set = adm5120_gpio1_set_value, + .direction_input = adm5120_gpio1_direction_input, + .direction_output = adm5120_gpio1_direction_output, + .base = ADM5120_GPIO_P0L0, + .ngpio = ADM5120_GPIO_P4L2 - ADM5120_GPIO_P0L0 + 1, +}; + +void __init adm5120_gpio_csx0_enable(void) +{ + gpio_conf2 |= GPIO_CONF2_CSX0; + SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); + + gpio_request(ADM5120_GPIO_PIN1, "CSX0"); +} + +void __init adm5120_gpio_csx1_enable(void) +{ + gpio_conf2 |= GPIO_CONF2_CSX1; + SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); + + gpio_request(ADM5120_GPIO_PIN3, "CSX1"); +} + +void __init adm5120_gpio_ew_enable(void) +{ + gpio_conf2 |= GPIO_CONF2_EW; + SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); + + gpio_request(ADM5120_GPIO_PIN0, "EW"); +} + +void __init adm5120_gpio_init(void) +{ + int err; + + SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); + + if (adm5120_package_pqfp()) { + gpiochip_reserve(ADM5120_GPIO_PIN4, 4); + adm5120_gpio0_chip.ngpio = 4; + } + + err = gpiochip_add(&adm5120_gpio0_chip); + if (err) + panic("cannot add ADM5120 GPIO0 chip, error=%d", err); + + err = gpiochip_add(&adm5120_gpio1_chip); + if (err) + panic("cannot add ADM5120 GPIO1 chip, error=%d", err); + +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/irq.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/irq.c new file mode 100644 index 0000000000..a26e65176e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/irq.c @@ -0,0 +1,171 @@ +/* + * ADM5120 specific interrupt handlers + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +static void adm5120_intc_irq_unmask(struct irq_data *d); +static void adm5120_intc_irq_mask(struct irq_data *d); +static int adm5120_intc_irq_set_type(struct irq_data *d, unsigned int flow_type); + +static inline void intc_write_reg(unsigned int reg, u32 val) +{ + void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE); + + __raw_writel(val, base + reg); +} + +static inline u32 intc_read_reg(unsigned int reg) +{ + void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE); + + return __raw_readl(base + reg); +} + +static struct irq_chip adm5120_intc_irq_chip = { + .name = "INTC", + .irq_unmask = adm5120_intc_irq_unmask, + .irq_mask = adm5120_intc_irq_mask, + .irq_mask_ack = adm5120_intc_irq_mask, + .irq_set_type = adm5120_intc_irq_set_type +}; + +static struct irqaction adm5120_intc_irq_action = { + .handler = no_action, + .name = "cascade [INTC]" +}; + +static void adm5120_intc_irq_unmask(struct irq_data *d) +{ + intc_write_reg(INTC_REG_IRQ_ENABLE, 1 << (d->irq - ADM5120_INTC_IRQ_BASE)); +} + +static void adm5120_intc_irq_mask(struct irq_data *d) +{ + intc_write_reg(INTC_REG_IRQ_DISABLE, 1 << (d->irq - ADM5120_INTC_IRQ_BASE)); +} + +static int adm5120_intc_irq_set_type(struct irq_data *d, unsigned int flow_type) +{ + unsigned int irq = d->irq; + unsigned int sense; + unsigned long mode; + int err = 0; + + sense = flow_type & (IRQ_TYPE_SENSE_MASK); + switch (sense) { + case IRQ_TYPE_NONE: + case IRQ_TYPE_LEVEL_HIGH: + break; + case IRQ_TYPE_LEVEL_LOW: + switch (irq) { + case ADM5120_IRQ_GPIO2: + case ADM5120_IRQ_GPIO4: + break; + default: + err = -EINVAL; + break; + } + break; + default: + err = -EINVAL; + break; + } + + if (err) + return err; + + switch (irq) { + case ADM5120_IRQ_GPIO2: + case ADM5120_IRQ_GPIO4: + mode = intc_read_reg(INTC_REG_INT_MODE); + if (sense == IRQ_TYPE_LEVEL_LOW) + mode |= (1 << (irq - ADM5120_INTC_IRQ_BASE)); + else + mode &= ~(1 << (irq - ADM5120_INTC_IRQ_BASE)); + + intc_write_reg(INTC_REG_INT_MODE, mode); + break; + } + + return 0; +} + +static void adm5120_intc_irq_dispatch(void) +{ + unsigned long status; + int irq; + + status = intc_read_reg(INTC_REG_IRQ_STATUS) & INTC_INT_ALL; + if (status) { + irq = ADM5120_INTC_IRQ_BASE + fls(status) - 1; + do_IRQ(irq); + } else + spurious_interrupt(); +} + +asmlinkage void plat_irq_dispatch(void) +{ + unsigned long pending; + + pending = read_c0_status() & read_c0_cause() & ST0_IM; + + if (pending & STATUSF_IP7) + do_IRQ(ADM5120_IRQ_COUNTER); + else if (pending & STATUSF_IP2) + adm5120_intc_irq_dispatch(); + else + spurious_interrupt(); +} + +#define INTC_IRQ_STATUS (IRQ_LEVEL | IRQ_TYPE_LEVEL_HIGH | IRQ_DISABLED) +static void __init adm5120_intc_irq_init(void) +{ + int i; + + /* disable all interrupts */ + intc_write_reg(INTC_REG_IRQ_DISABLE, INTC_INT_ALL); + + /* setup all interrupts to generate IRQ instead of FIQ */ + intc_write_reg(INTC_REG_INT_MODE, 0); + + /* set active level for all external interrupts to HIGH */ + intc_write_reg(INTC_REG_INT_LEVEL, 0); + + /* disable usage of the TEST_SOURCE register */ + intc_write_reg(INTC_REG_IRQ_SOURCE_SELECT, 0); + + for (i = ADM5120_INTC_IRQ_BASE; + i <= ADM5120_INTC_IRQ_BASE + INTC_IRQ_LAST; + i++) { + irq_set_chip_and_handler(i, &adm5120_intc_irq_chip, + handle_level_irq); + } + + setup_irq(ADM5120_IRQ_INTC, &adm5120_intc_irq_action); +} + +void __init arch_init_irq(void) +{ + mips_cpu_irq_init(); + adm5120_intc_irq_init(); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/memory.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/memory.c new file mode 100644 index 0000000000..d07266fa38 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/memory.c @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#ifdef DEBUG +# define mem_dbg(f, a...) printk(KERN_INFO "mem_detect: " f, ## a) +#else +# define mem_dbg(f, a...) +#endif + +unsigned long adm5120_memsize; + +#define MEM_READL(a) __raw_readl((void __iomem *)(a)) +#define MEM_WRITEL(a, v) __raw_writel((v), (void __iomem *)(a)) + +static int __init mem_check_pattern(u8 *addr, unsigned long offs) +{ + u32 *p1 = (u32 *)addr; + u32 *p2 = (u32 *)(addr+offs); + u32 t, u, v; + + /* save original value */ + t = MEM_READL(p1); + + u = MEM_READL(p2); + if (t != u) + return 0; + + v = 0x55555555; + if (u == v) + v = 0xAAAAAAAA; + + mem_dbg("write 0x%08X to 0x%08lX\n", v, (unsigned long)p1); + + MEM_WRITEL(p1, v); + adm5120_ndelay(1000); + u = MEM_READL(p2); + + mem_dbg("pattern at 0x%08lX is 0x%08X\n", (unsigned long)p2, u); + + /* restore original value */ + MEM_WRITEL(p1, t); + + return (v == u); +} + +static void __init adm5120_detect_memsize(void) +{ + u32 memctrl; + u32 size, maxsize; + u8 *p; + + memctrl = SW_READ_REG(SWITCH_REG_MEMCTRL); + switch (memctrl & MEMCTRL_SDRS_MASK) { + case MEMCTRL_SDRS_4M: + maxsize = 4 << 20; + break; + case MEMCTRL_SDRS_8M: + maxsize = 8 << 20; + break; + case MEMCTRL_SDRS_16M: + maxsize = 16 << 20; + break; + default: + maxsize = 64 << 20; + break; + } + + mem_dbg("checking for %uMB chip in 1st bank\n", maxsize >> 20); + + /* detect size of the 1st SDRAM bank */ + p = (u8 *)KSEG1ADDR(0); + for (size = 2<<20; size <= (maxsize >> 1); size <<= 1) { + if (mem_check_pattern(p, size)) { + /* mirrored address */ + mem_dbg("mirrored data found at offset 0x%08X\n", size); + break; + } + } + + mem_dbg("chip size in 1st bank is %uMB\n", size >> 20); + adm5120_memsize = size; + + if (size != maxsize) + /* 2nd bank is not supported */ + goto out; + + if ((memctrl & MEMCTRL_SDR1_ENABLE) == 0) + /* 2nd bank is disabled */ + goto out; + + /* + * some bootloaders enable 2nd bank, even if the 2nd SDRAM chip + * are missing. + */ + mem_dbg("check presence of 2nd bank\n"); + + p = (u8 *)KSEG1ADDR(maxsize+size-4); + if (mem_check_pattern(p, 0)) + adm5120_memsize += size; + + if (maxsize != size) { + /* adjusting MECTRL register */ + memctrl &= ~(MEMCTRL_SDRS_MASK); + switch (size>>20) { + case 4: + memctrl |= MEMCTRL_SDRS_4M; + break; + case 8: + memctrl |= MEMCTRL_SDRS_8M; + break; + case 16: + memctrl |= MEMCTRL_SDRS_16M; + break; + default: + memctrl |= MEMCTRL_SDRS_64M; + break; + } + SW_WRITE_REG(SWITCH_REG_MEMCTRL, memctrl); + } + +out: + mem_dbg("%dx%uMB memory found\n", (adm5120_memsize == size) ? 1 : 2 , + size>>20); +} + +void __init adm5120_mem_init(void) +{ + adm5120_detect_memsize(); + add_memory_region(0, adm5120_memsize, BOOT_MEM_RAM); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/platform.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/platform.c new file mode 100644 index 0000000000..bdbfbcbae5 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/platform.c @@ -0,0 +1,375 @@ +/* + * ADM5120 generic platform devices + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#if 1 +/* + * TODO:remove global adm5120_eth* variables when the switch driver will be + * converted into a real platform driver + */ +unsigned int adm5120_eth_num_ports = 6; +EXPORT_SYMBOL_GPL(adm5120_eth_num_ports); + +unsigned char adm5120_eth_macs[6][6] = { + {'\00', 'A', 'D', 'M', '\x51', '\x20' }, + {'\00', 'A', 'D', 'M', '\x51', '\x21' }, + {'\00', 'A', 'D', 'M', '\x51', '\x22' }, + {'\00', 'A', 'D', 'M', '\x51', '\x23' }, + {'\00', 'A', 'D', 'M', '\x51', '\x24' }, + {'\00', 'A', 'D', 'M', '\x51', '\x25' } +}; +EXPORT_SYMBOL_GPL(adm5120_eth_macs); + +unsigned char adm5120_eth_vlans[6] = { + 0x41, 0x42, 0x44, 0x48, 0x50, 0x60 +}; +EXPORT_SYMBOL_GPL(adm5120_eth_vlans); +#endif + +void __init adm5120_setup_eth_macs(u8 *mac_base) +{ + u32 t; + int i, j; + + t = ((u32) mac_base[3] << 16) | ((u32) mac_base[4] << 8) + | ((u32) mac_base[5]); + + for (i = 0; i < ARRAY_SIZE(adm5120_eth_macs); i++) { + for (j = 0; j < 3; j++) + adm5120_eth_macs[i][j] = mac_base[j]; + + adm5120_eth_macs[i][3] = (t >> 16) & 0xff; + adm5120_eth_macs[i][4] = (t >> 8) & 0xff; + adm5120_eth_macs[i][5] = t & 0xff; + + t++; + } +} + +/* + * Built-in ethernet switch + */ +struct resource adm5120_switch_resources[] = { + [0] = { + .start = ADM5120_SWITCH_BASE, + .end = ADM5120_SWITCH_BASE+ADM5120_SWITCH_SIZE-1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = ADM5120_IRQ_SWITCH, + .end = ADM5120_IRQ_SWITCH, + .flags = IORESOURCE_IRQ, + }, +}; + +struct adm5120_switch_platform_data adm5120_switch_data; +struct platform_device adm5120_switch_device = { + .name = "adm5120-switch", + .id = -1, + .num_resources = ARRAY_SIZE(adm5120_switch_resources), + .resource = adm5120_switch_resources, + .dev.platform_data = &adm5120_switch_data, +}; + +void __init adm5120_add_device_switch(unsigned num_ports, u8 *vlan_map) +{ + if (num_ports > 0) + adm5120_eth_num_ports = num_ports; + + if (vlan_map) + memcpy(adm5120_eth_vlans, vlan_map, sizeof(adm5120_eth_vlans)); + + platform_device_register(&adm5120_switch_device); +} + +/* + * USB Host Controller + */ +struct resource adm5120_hcd_resources[] = { + [0] = { + .start = ADM5120_USBC_BASE, + .end = ADM5120_USBC_BASE+ADM5120_USBC_SIZE-1, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = ADM5120_IRQ_USBC, + .end = ADM5120_IRQ_USBC, + .flags = IORESOURCE_IRQ, + }, +}; + +static u64 adm5120_hcd_dma_mask = DMA_BIT_MASK(24); +struct platform_device adm5120_hcd_device = { + .name = "adm5120-hcd", + .id = -1, + .num_resources = ARRAY_SIZE(adm5120_hcd_resources), + .resource = adm5120_hcd_resources, + .dev = { + .dma_mask = &adm5120_hcd_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(24), + } +}; + +void __init adm5120_add_device_usb(void) +{ + platform_device_register(&adm5120_hcd_device); +} + +/* + * NOR flash devices + */ +struct adm5120_flash_platform_data adm5120_flash0_data; +struct platform_device adm5120_flash0_device = { + .name = "adm5120-flash", + .id = 0, + .dev.platform_data = &adm5120_flash0_data, +}; + +struct adm5120_flash_platform_data adm5120_flash1_data; +struct platform_device adm5120_flash1_device = { + .name = "adm5120-flash", + .id = 1, + .dev.platform_data = &adm5120_flash1_data, +}; + +void __init adm5120_add_device_flash(unsigned id) +{ + struct platform_device *pdev; + + switch (id) { + case 0: + pdev = &adm5120_flash0_device; + break; + case 1: + pdev = &adm5120_flash1_device; + break; + default: + pdev = NULL; + break; + } + + if (pdev) + platform_device_register(pdev); +} + +/* + * built-in UARTs + */ +static void adm5120_uart_set_mctrl(struct amba_device *dev, void __iomem *base, + unsigned int mctrl) +{ +} + +struct amba_pl010_data adm5120_uart0_data = { + .set_mctrl = adm5120_uart_set_mctrl +}; + +struct amba_device adm5120_uart0_device = { + .dev = { + .init_name = "apb:uart0", + .platform_data = &adm5120_uart0_data, + }, + .res = { + .start = ADM5120_UART0_BASE, + .end = ADM5120_UART0_BASE + ADM5120_UART_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = { ADM5120_IRQ_UART0, 0 }, + .periphid = 0x0041010, +}; + +struct amba_pl010_data adm5120_uart1_data = { + .set_mctrl = adm5120_uart_set_mctrl +}; + +struct amba_device adm5120_uart1_device = { + .dev = { + .init_name = "apb:uart1", + .platform_data = &adm5120_uart1_data, + }, + .res = { + .start = ADM5120_UART1_BASE, + .end = ADM5120_UART1_BASE + ADM5120_UART_SIZE - 1, + .flags = IORESOURCE_MEM, + }, + .irq = { ADM5120_IRQ_UART1, 0 }, + .periphid = 0x0041010, +}; + +void __init adm5120_add_device_uart(unsigned id) +{ + struct amba_device *dev; + + switch (id) { + case 0: + dev = &adm5120_uart0_device; + break; + case 1: + dev = &adm5120_uart1_device; + break; + default: + dev = NULL; + break; + } + + if (dev) + amba_device_register(dev, &iomem_resource); +} + +/* + * GPIO buttons + */ +void __init adm5120_register_gpio_buttons(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_keys_button *buttons) +{ + struct platform_device *pdev; + struct gpio_keys_platform_data pdata; + struct gpio_keys_button *p; + int err; + + p = kmemdup(buttons, nbuttons * sizeof(*p), GFP_KERNEL); + if (!p) + return; + + pdev = platform_device_alloc("gpio-keys-polled", id); + if (!pdev) + goto err_free_buttons; + + memset(&pdata, 0, sizeof(pdata)); + pdata.poll_interval = poll_interval; + pdata.nbuttons = nbuttons; + pdata.buttons = p; + + err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); + if (err) + goto err_put_pdev; + + err = platform_device_add(pdev); + if (err) + goto err_put_pdev; + + return; + +err_put_pdev: + platform_device_put(pdev); + +err_free_buttons: + kfree(p); +} + +/* + * GPIO LEDS + */ +struct gpio_led_platform_data adm5120_gpio_leds_data; +struct platform_device adm5120_gpio_leds_device = { + .name = "leds-gpio", + .id = -1, + .dev.platform_data = &adm5120_gpio_leds_data, +}; + +void __init adm5120_add_device_gpio_leds(unsigned num_leds, + struct gpio_led *leds) +{ + struct gpio_led *p; + + p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memcpy(p, leds, num_leds * sizeof(*p)); + adm5120_gpio_leds_data.num_leds = num_leds; + adm5120_gpio_leds_data.leds = p; + + platform_device_register(&adm5120_gpio_leds_device); +} + +/* + * NAND flash + */ +struct resource adm5120_nand_resources[] = { + [0] = { + .start = ADM5120_NAND_BASE, + .end = ADM5120_NAND_BASE + ADM5120_NAND_SIZE-1, + .flags = IORESOURCE_MEM, + }, +}; + +static int adm5120_nand_ready(struct mtd_info *mtd) +{ + return ((adm5120_nand_get_status() & ADM5120_NAND_STATUS_READY) != 0); +} + +static void adm5120_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + if (ctrl & NAND_CTRL_CHANGE) { + adm5120_nand_set_cle(ctrl & NAND_CLE); + adm5120_nand_set_ale(ctrl & NAND_ALE); + adm5120_nand_set_cen(ctrl & NAND_NCE); + } + + if (cmd != NAND_CMD_NONE) + NAND_WRITE_REG(NAND_REG_DATA, cmd); +} + +void __init adm5120_add_device_nand(struct platform_nand_data *pdata) +{ + struct platform_device *pdev; + int err; + + pdev = platform_device_alloc("gen_nand", -1); + if (!pdev) + goto err_out; + + err = platform_device_add_resources(pdev, adm5120_nand_resources, + ARRAY_SIZE(adm5120_nand_resources)); + if (err) + goto err_put; + + err = platform_device_add_data(pdev, pdata, sizeof(*pdata)); + if (err) + goto err_put; + + pdata = pdev->dev.platform_data; + pdata->ctrl.dev_ready = adm5120_nand_ready; + pdata->ctrl.cmd_ctrl = adm5120_nand_cmd_ctrl; + + err = platform_device_add(pdev); + if (err) + goto err_put; + + return; + +err_put: + platform_device_put(pdev); +err_out: + return; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/prom.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/prom.c new file mode 100644 index 0000000000..5c52ea27e2 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/prom.c @@ -0,0 +1,264 @@ +/* + * ADM5120 specific prom routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include +#include + +unsigned int adm5120_prom_type = ADM5120_PROM_GENERIC; + +struct board_desc { + unsigned long mach_type; + char *name; +}; + +#define DEFBOARD(n, mt) { .mach_type = (mt), .name = (n)} +static struct board_desc common_boards[] __initdata = { + /* Cellvision/SparkLAN boards */ + DEFBOARD("CAS-630", MACH_ADM5120_CAS630), + DEFBOARD("CAS-670", MACH_ADM5120_CAS670), + DEFBOARD("CAS-700", MACH_ADM5120_CAS700), + DEFBOARD("CAS-771", MACH_ADM5120_CAS771), + DEFBOARD("CAS-790", MACH_ADM5120_CAS790), + DEFBOARD("CAS-861", MACH_ADM5120_CAS861), + DEFBOARD("NFS-101U", MACH_ADM5120_NFS101U), + /* Compex boards */ + DEFBOARD("WP54G-WRT", MACH_ADM5120_WP54G_WRT), + /* Edimax boards */ + DEFBOARD("BR-6104K", MACH_ADM5120_BR6104K), + DEFBOARD("BR-6104KP", MACH_ADM5120_BR6104KP), + DEFBOARD("BR-6104WG", MACH_ADM5120_BR61X4WG), + DEFBOARD("BR-6114WG", MACH_ADM5120_BR61X4WG), + /* Infineon boards */ + DEFBOARD("EASY 5120P-ATA", MACH_ADM5120_EASY5120PATA), + DEFBOARD("EASY 5120-RT", MACH_ADM5120_EASY5120RT), + DEFBOARD("EASY 5120-WVoIP", MACH_ADM5120_EASY5120WVOIP), + DEFBOARD("EASY 83000", MACH_ADM5120_EASY83000), + /* Mikrotik RouterBOARDs */ + DEFBOARD("111", MACH_ADM5120_RB_11X), + DEFBOARD("112", MACH_ADM5120_RB_11X), + DEFBOARD("133", MACH_ADM5120_RB_133), + DEFBOARD("133C", MACH_ADM5120_RB_133C), + DEFBOARD("133C3", MACH_ADM5120_RB_133C), + DEFBOARD("150", MACH_ADM5120_RB_153), /* it's intentional */ + DEFBOARD("153", MACH_ADM5120_RB_153), + DEFBOARD("192", MACH_ADM5120_RB_192), + DEFBOARD("miniROUTER", MACH_ADM5120_RB_150), + /* OSBRiDGE boards */ + DEFBOARD("OSBRiDGE 5GXi", MACH_ADM5120_5GXI), + /* Motorola boards */ + DEFBOARD("Powerline MU Gateway", MACH_ADM5120_PMUGW), + /* Generic EB-214A */ + DEFBOARD("ADM5120", MACH_ADM5120_EB_214A), +}; + +static unsigned long __init find_machtype_byname(char *name) +{ + unsigned long ret; + int i; + + ret = MACH_ADM5120_GENERIC; + if (name == NULL) + goto out; + + if (*name == '\0') + goto out; + + for (i = 0; i < ARRAY_SIZE(common_boards); i++) { + if (strcmp(common_boards[i].name, name) == 0) { + ret = common_boards[i].mach_type; + break; + } + } + +out: + return ret; +} + +static unsigned long __init detect_machtype_routerboot(void) +{ + char *name; + + name = routerboot_get_boardname(); + return find_machtype_byname(name); +} + +static unsigned long __init detect_machtype_generic(void) +{ + char *name; + + name = generic_prom_getenv("board_name"); + return find_machtype_byname(name); +} + +unsigned long __init detect_machtype_cfe(void) +{ + char *name; + + name = cfe_getenv("BOARD_NAME"); + return find_machtype_byname(name); +} + +static struct { + unsigned long mach_type; + u16 vendor_id; + u16 board_id; +} zynos_boards[] __initdata = { +#define ZYNOS_BOARD(vi, bi, mt) \ + {.vendor_id = (vi), .board_id = (bi), .mach_type = (mt)} + +#define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt) +#define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt) +#define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt) + ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100), + ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U), + ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W), + ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH), + ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD), + ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT), + ZYXEL_BOARD(ZYNOS_BOARD_P334WT_ALT, MACH_ADM5120_P334WT), + ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335), + ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS), + ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U) +}; + +static unsigned long __init detect_machtype_bootbase(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(zynos_boards); i++) { + if (zynos_boards[i].vendor_id == bootbase_info.vendor_id && + zynos_boards[i].board_id == bootbase_info.board_id) { + return zynos_boards[i].mach_type; + break; + } + } + + printk(KERN_WARNING "Unknown ZyXEL model (%u)\n", + bootbase_info.board_id); + return MACH_ADM5120_GENERIC; +} + +static struct { + unsigned long mach_type; + u16 vid; + u16 did; + u16 svid; + u16 sdid; +} mylo_boards[] __initdata = { +#define MYLO_BOARD(v, d, sv, sd, mt) \ + {.vid = (v), .did = (d), .svid = (sv), .sdid = (sd), .mach_type = (mt)} +#define COMPEX_BOARD(d, mt) \ + MYLO_BOARD(VENID_COMPEX, (d), VENID_COMPEX, (d), (mt)) + + COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G), + COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G), + COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS), + COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54), + COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C), + COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54), + COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WP54), + COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WP54), +}; + +static unsigned long __init detect_machtype_myloader(void) +{ + unsigned long ret; + int i; + + ret = MACH_ADM5120_GENERIC; + for (i = 0; i < ARRAY_SIZE(mylo_boards); i++) { + if (mylo_boards[i].vid == myloader_info.vid && + mylo_boards[i].did == myloader_info.did && + mylo_boards[i].svid == myloader_info.svid && + mylo_boards[i].sdid == myloader_info.sdid) { + ret = mylo_boards[i].mach_type; + break; + } + } + + return ret; +} + +static void __init prom_detect_machtype(void) +{ + if (bootbase_present()) { + adm5120_prom_type = ADM5120_PROM_BOOTBASE; + mips_machtype = detect_machtype_bootbase(); + return; + } + + if (cfe_present()) { + adm5120_prom_type = ADM5120_PROM_CFE; + mips_machtype = detect_machtype_cfe(); + return; + } + + if (myloader_present()) { + adm5120_prom_type = ADM5120_PROM_MYLOADER; + mips_machtype = detect_machtype_myloader(); + return; + } + + if (routerboot_present()) { + adm5120_prom_type = ADM5120_PROM_ROUTERBOOT; + mips_machtype = detect_machtype_routerboot(); + return; + } + + if (generic_prom_present()) { + adm5120_prom_type = ADM5120_PROM_GENERIC; + mips_machtype = detect_machtype_generic(); + return; + } + + mips_machtype = MACH_ADM5120_GENERIC; +} + +#ifdef CONFIG_IMAGE_CMDLINE_HACK +extern char __image_cmdline[]; + +static void __init prom_init_cmdline(void) +{ + char *cmd; + + /* init command line, register a default kernel command line */ + cmd = __image_cmdline; + if (strlen(cmd) > 0) + strlcpy(arcs_cmdline, cmd, sizeof(arcs_cmdline)); + +} +#else +static inline void prom_init_cmdline(void) {} +#endif /* CONFIG_IMAGE_CMDLINE_HACK */ + +void __init prom_init(void) +{ + prom_detect_machtype(); + prom_init_cmdline(); +} + +void __init prom_free_prom_memory(void) +{ + /* We do not have to prom memory to free */ +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/setup.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/setup.c new file mode 100644 index 0000000000..c4be845170 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/common/setup.c @@ -0,0 +1,128 @@ +/* + * ADM5120 specific setup + * + * Copyright (C) 2007-2009 Gabor Juhos + * + * This code was based on the ADM5120 specific port of the Linux 2.6.10 kernel + * done by Jeroen Vreeken + * Copyright (C) 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * Jeroen's code was based on the Linux 2.4.xx source codes found in various + * tarballs released by Edimax for it's ADM5120 based devices + * Copyright (C) ADMtek Incorporated + * + * 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 +#include +#include +#include + +#define ADM5120_SYS_TYPE_LEN 64 + +unsigned char adm5120_sys_type[ADM5120_SYS_TYPE_LEN]; +void (*adm5120_board_reset)(void); + +static char *prom_names[ADM5120_PROM_LAST+1] __initdata = { + [ADM5120_PROM_GENERIC] = "Generic", + [ADM5120_PROM_CFE] = "CFE", + [ADM5120_PROM_UBOOT] = "U-Boot", + [ADM5120_PROM_MYLOADER] = "MyLoader", + [ADM5120_PROM_ROUTERBOOT] = "RouterBOOT", + [ADM5120_PROM_BOOTBASE] = "Bootbase" +}; + +static void __init adm5120_report(void) +{ + printk(KERN_INFO "SoC : %s\n", adm5120_sys_type); + printk(KERN_INFO "Bootdev : %s flash\n", + adm5120_nand_boot ? "NAND" : "NOR"); + printk(KERN_INFO "Prom : %s\n", prom_names[adm5120_prom_type]); +} + +const char *get_system_type(void) +{ + return adm5120_sys_type; +} + +static void adm5120_restart(char *command) +{ + /* TODO: stop switch before reset */ + + if (adm5120_board_reset) + adm5120_board_reset(); + + SW_WRITE_REG(SWITCH_REG_SOFT_RESET, 1); +} + +static void adm5120_halt(void) +{ + local_irq_disable(); + + while (1) { + if (cpu_wait) + cpu_wait(); + } +} + +void __init plat_time_init(void) +{ + mips_hpt_frequency = adm5120_speed / 2; +} + +void __init plat_mem_setup(void) +{ + adm5120_soc_init(); + adm5120_mem_init(); + + sprintf(adm5120_sys_type, "ADM%04X%s rev %u, running at %lu.%03lu MHz", + adm5120_product_code, + adm5120_package_bga() ? "" : "P", + adm5120_revision, + (adm5120_speed / 1000000), (adm5120_speed / 1000) % 1000); + + adm5120_report(); + + _machine_restart = adm5120_restart; + _machine_halt = adm5120_halt; + pm_power_off = adm5120_halt; + + set_io_port_base(KSEG1); +} + +static int __init adm5120_board_setup(void) +{ + adm5120_gpio_init(); + + mips_machine_setup(); + + return 0; +} +arch_initcall(adm5120_board_setup); + +static void __init adm5120_generic_board_setup(void) +{ + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_flash(0); + adm5120_add_device_switch(6, NULL); +} + +MIPS_MACHINE(MACH_ADM5120_GENERIC, "Generic", "Generic ADM5120 board", + adm5120_generic_board_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/Makefile new file mode 100644 index 0000000000..8c66c171e7 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/Makefile @@ -0,0 +1,5 @@ +obj-y += compex.o + +obj-$(CONFIG_ADM5120_MACH_NP27G) += np27g.o +obj-$(CONFIG_ADM5120_MACH_NP28G) += np28g.o +obj-$(CONFIG_ADM5120_MACH_WP54) += wp54.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.c new file mode 100644 index 0000000000..814acfb0cf --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.c @@ -0,0 +1,60 @@ +/* + * Compex boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "compex.h" + +#include + +static void switch_bank_gpio5(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(ADM5120_GPIO_PIN5, 0); + break; + case 1: + gpio_set_value(ADM5120_GPIO_PIN5, 1); + break; + } +} + +void __init compex_mac_setup(void) +{ + if (myloader_present()) { + int i; + + for (i = 0; i < 6; i++) { + if (is_valid_ether_addr(myloader_info.macs[i])) + memcpy(adm5120_eth_macs[i], + myloader_info.macs[i], ETH_ALEN); + else + random_ether_addr(adm5120_eth_macs[i]); + } + } else { + u8 mac[ETH_ALEN]; + + random_ether_addr(mac); + adm5120_setup_eth_macs(mac); + } +} + +void __init compex_generic_setup(void) +{ + gpio_request(ADM5120_GPIO_PIN5, NULL); /* for flash A20 line */ + gpio_direction_output(ADM5120_GPIO_PIN5, 0); + + adm5120_flash0_data.switch_bank = switch_bank_gpio5; + adm5120_add_device_flash(0); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + compex_mac_setup(); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.h new file mode 100644 index 0000000000..124e676971 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/compex.h @@ -0,0 +1,23 @@ +/* + * Compex boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +extern void compex_generic_setup(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np27g.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np27g.c new file mode 100644 index 0000000000..82da46d1c7 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np27g.c @@ -0,0 +1,28 @@ +/* + * Compex NP27G board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "compex.h" + +static u8 np27g_vlans[6] __initdata = { + /* FIXME: untested */ + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 +}; + +static void __init np27g_setup(void) +{ + compex_generic_setup(); + adm5120_add_device_switch(5, np27g_vlans); + adm5120_add_device_usb(); + + /* TODO: add PCI IRQ map */ +} + +MIPS_MACHINE(MACH_ADM5120_NP27G, "NP27G", "Compex NetPassage 27G", np27g_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np28g.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np28g.c new file mode 100644 index 0000000000..a541439998 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/np28g.c @@ -0,0 +1,63 @@ +/* + * Compex NP28G board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "compex.h" + +static struct adm5120_pci_irq np28g_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), + PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI0), + PCIIRQ(3, 1, 2, ADM5120_IRQ_PCI1), + PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2) +}; + +static struct gpio_led np28g_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN2, "diag", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN3, "power", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN6, "wan_cond", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN7, "wifi", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L2, "usb1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L2, "usb2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L2, "usb3", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L2, "usb4", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), +}; + +static u8 np28g_vlans[6] __initdata = { + 0x50, 0x42, 0x44, 0x48, 0x00, 0x00 +}; + +static void np28g_reset(void) +{ + gpio_set_value(ADM5120_GPIO_PIN4, 0); +} + +static void __init np28g_setup(void) +{ + compex_generic_setup(); + + /* setup reset line */ + gpio_request(ADM5120_GPIO_PIN4, NULL); + gpio_direction_output(ADM5120_GPIO_PIN4, 1); + adm5120_board_reset = np28g_reset; + + adm5120_add_device_switch(4, np28g_vlans); + adm5120_add_device_usb(); + + adm5120_add_device_gpio_leds(ARRAY_SIZE(np28g_gpio_leds), + np28g_gpio_leds); + + adm5120_pci_set_irq_map(ARRAY_SIZE(np28g_pci_irqs), np28g_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_NP28G, "NP28G", "Compex NetPassage 28G", np28g_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/wp54.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/wp54.c new file mode 100644 index 0000000000..8aa35c555a --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/compex/wp54.c @@ -0,0 +1,95 @@ +/* + * Compex WP54 board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "compex.h" + +#define WP54_KEYS_POLL_INTERVAL 20 +#define WP54_KEYS_DEBOUNCE_INTERVAL (3 * WP54_KEYS_POLL_INTERVAL) + +static struct mtd_partition wp54g_wrt_partitions[] = { + { + .name = "cfe", + .offset = 0, + .size = 0x050000, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "trx", + .offset = MTDPART_OFS_APPEND, + .size = 0x3A0000, + } , { + .name = "nvram", + .offset = MTDPART_OFS_APPEND, + .size = 0x010000, + } +}; + +static struct adm5120_pci_irq wp54_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static struct gpio_keys_button wp54_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = WP54_KEYS_DEBOUNCE_INTERVAL, + .gpio = ADM5120_GPIO_PIN4, + } +}; + +static struct gpio_led wp54_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN2, "diag", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN6, "wlan", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN7, "wan", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan2", NULL), +}; + +static u8 wp54_vlans[6] __initdata = { + 0x41, 0x42, 0x00, 0x00, 0x00, 0x00 +}; + +static void wp54_reset(void) +{ + gpio_set_value(ADM5120_GPIO_PIN3, 0); +} + +static void __init wp54_setup(void) +{ + compex_generic_setup(); + + /* setup reset line */ + gpio_request(ADM5120_GPIO_PIN3, NULL); + gpio_direction_output(ADM5120_GPIO_PIN3, 1); + adm5120_board_reset = wp54_reset; + + adm5120_add_device_switch(2, wp54_vlans); + adm5120_register_gpio_buttons(-1, WP54_KEYS_POLL_INTERVAL, + ARRAY_SIZE(wp54_gpio_buttons), + wp54_gpio_buttons); + adm5120_add_device_gpio_leds(ARRAY_SIZE(wp54_gpio_leds), + wp54_gpio_leds); + + adm5120_pci_set_irq_map(ARRAY_SIZE(wp54_pci_irqs), wp54_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_WP54, "WP54", "Compex WP54 family", wp54_setup); + +static void __init wp54_wrt_setup(void) +{ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(wp54g_wrt_partitions); + adm5120_flash0_data.parts = wp54g_wrt_partitions; + + wp54_setup(); +} + +MIPS_MACHINE(MACH_ADM5120_WP54G_WRT, "WP54G-WRT", "Compex WP54G-WRT", + wp54_wrt_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/Makefile new file mode 100644 index 0000000000..1286ed4c1e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/Makefile @@ -0,0 +1,5 @@ +obj-y := br-61xx.o + +obj-$(CONFIG_ADM5120_MACH_BR_6104K) += br-6104k.o +obj-$(CONFIG_ADM5120_MACH_BR_6104KP) += br-6104kp.o +obj-$(CONFIG_ADM5120_MACH_BR_61X4WG) += br-61x4wg.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104k.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104k.c new file mode 100644 index 0000000000..8b2b445506 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104k.c @@ -0,0 +1,36 @@ +/* + * Edimax BR-6104K board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "br-61xx.h" + +static struct gpio_led br6104k_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), +}; + +static void __init br6104k_setup(void) +{ + br61xx_generic_setup(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(br6104k_gpio_leds), + br6104k_gpio_leds); +} + +MIPS_MACHINE(MACH_ADM5120_BR6104K, "BR-6104K", "Edimax BR-6104K", + br6104k_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104kp.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104kp.c new file mode 100644 index 0000000000..034575d6b2 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-6104kp.c @@ -0,0 +1,39 @@ +/* + * Edimax BR-6104KP board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "br-61xx.h" + +static struct gpio_led br6104kp_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN3, "usb1", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN1, "usb2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), +}; + +static void __init br6104kp_setup(void) +{ + br61xx_generic_setup(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(br6104kp_gpio_leds), + br6104kp_gpio_leds); + adm5120_add_device_usb(); +} + +MIPS_MACHINE(MACH_ADM5120_BR6104KP, "BR-6104KP", "Edimax BR-6104KP", + br6104kp_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61x4wg.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61x4wg.c new file mode 100644 index 0000000000..5d57507101 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61x4wg.c @@ -0,0 +1,43 @@ +/* + * Edimax BR-6104Wg/6114WG board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "br-61xx.h" + +static struct adm5120_pci_irq br61x4wg_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static struct gpio_led br61x4wg_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), + GPIO_LED_STD(ADM5120_GPIO_PIN5, "wlan", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), +}; + +static void __init br61x4wg_setup(void) +{ + br61xx_generic_setup(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(br61x4wg_gpio_leds), + br61x4wg_gpio_leds); + adm5120_pci_set_irq_map(ARRAY_SIZE(br61x4wg_pci_irqs), + br61x4wg_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_BR61X4WG, "BR-6104WG", "Edimax BR-6104WG/6114WG", + br61x4wg_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.c new file mode 100644 index 0000000000..62a1cee384 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.c @@ -0,0 +1,84 @@ +/* + * Edimax BR-61xx support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "br-61xx.h" + +#include + +#define BR61XX_CONFIG_OFFSET 0x8000 +#define BR61XX_CONFIG_SIZE 0x1000 + +#define BR61XX_KEYS_POLL_INTERVAL 20 +#define BR61XX_KEYS_DEBOUNCE_INTERVAL (3 * BR61XX_KEYS_POLL_INTERVAL) + +static struct mtd_partition br61xx_partitions[] = { + { + .name = "admboot", + .offset = 0, + .size = 32*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct gpio_keys_button br61xx_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = BR61XX_KEYS_DEBOUNCE_INTERVAL, + .gpio = ADM5120_GPIO_PIN2, + } +}; + +static u8 br61xx_vlans[6] __initdata = { + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 +}; + +static void __init br61xx_mac_setup(void) +{ + u8 mac_base[6]; + int err; + + err = admboot_get_mac_base(BR61XX_CONFIG_OFFSET, + BR61XX_CONFIG_SIZE, mac_base); + + if ((err) || !is_valid_ether_addr(mac_base)) + random_ether_addr(mac_base); + + adm5120_setup_eth_macs(mac_base); +} + +void __init br61xx_generic_setup(void) +{ + + adm5120_flash0_data.nr_parts = ARRAY_SIZE(br61xx_partitions); + adm5120_flash0_data.parts = br61xx_partitions; + adm5120_add_device_flash(0); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_switch(5, br61xx_vlans); + + adm5120_register_gpio_buttons(-1, BR61XX_KEYS_POLL_INTERVAL, + ARRAY_SIZE(br61xx_gpio_buttons), + br61xx_gpio_buttons); + + br61xx_mac_setup(); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.h new file mode 100644 index 0000000000..c4a9eced56 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/edimax/br-61xx.h @@ -0,0 +1,23 @@ +/* + * Edimax BR-61xx board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include + +extern void __init br61xx_generic_setup(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/Makefile new file mode 100644 index 0000000000..0c032e3a52 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ADM5120_MACH_EB_214A) += eb-214a.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/eb-214a.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/eb-214a.c new file mode 100644 index 0000000000..cf491a1efc --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/generic/eb-214a.c @@ -0,0 +1,120 @@ +/* + * EB-214A board support + * + * Copyright (C) 2007-2008 Gabor Juhos + * Copyright (C) 2010 Cezary Jackiewicz + * + * 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 +#include + + +#define EB214A_CONFIG_OFFSET 0x4000 + +#define EB214A_KEYS_POLL_INTERVAL 20 +#define EB214A_KEYS_DEBOUNCE_INTERVAL (3 * EB214A_KEYS_POLL_INTERVAL) + +static struct mtd_partition eb214a_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 32*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "config", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct adm5120_pci_irq eb214a_pci_irqs[] __initdata = { + PCIIRQ(4, 0, 1, ADM5120_IRQ_PCI0), + PCIIRQ(4, 1, 2, ADM5120_IRQ_PCI0), + PCIIRQ(4, 2, 3, ADM5120_IRQ_PCI0), +}; + +static struct gpio_led eb214a_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN7, "power", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "usb1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "usb2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L2, "usb3", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "usb4", NULL), +}; + +static struct gpio_keys_button eb214a_gpio_buttons[] __initdata = { + { + .desc = "reset", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = EB214A_KEYS_DEBOUNCE_INTERVAL, + .gpio = ADM5120_GPIO_PIN1, + } +}; + +static u8 eb214a_vlans[6] __initdata = { + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 +}; + +static void __init eb214a_mac_setup(void) +{ + u8 mac_base[6]; + u8 *cfg; + int i; + + cfg = (u8 *) KSEG1ADDR(ADM5120_SRAM0_BASE + EB214A_CONFIG_OFFSET); + for (i = 0; i < 6; i++) + mac_base[i] = cfg[i]; + + if (!is_valid_ether_addr(mac_base)) + random_ether_addr(mac_base); + + adm5120_setup_eth_macs(mac_base); +} + +static void __init eb214a_setup(void) +{ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(eb214a_partitions); + adm5120_flash0_data.parts = eb214a_partitions; + adm5120_add_device_flash(0); + + adm5120_add_device_uart(0); + /* adm5120_add_device_uart(1); */ + + adm5120_add_device_switch(5, eb214a_vlans); + + eb214a_mac_setup(); + + adm5120_register_gpio_buttons(-1, EB214A_KEYS_POLL_INTERVAL, + ARRAY_SIZE(eb214a_gpio_buttons), + eb214a_gpio_buttons); + + adm5120_add_device_gpio_leds(ARRAY_SIZE(eb214a_gpio_leds), + eb214a_gpio_leds); + + adm5120_pci_set_irq_map(ARRAY_SIZE(eb214a_pci_irqs), + eb214a_pci_irqs); + /* adm5120_add_device_usb(); */ +} + +MIPS_MACHINE(MACH_ADM5120_EB_214A, "EB-214A", "Generic EB-214A", eb214a_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/Makefile new file mode 100644 index 0000000000..49453cba9a --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/Makefile @@ -0,0 +1,6 @@ +obj-y += infineon.o + +obj-$(CONFIG_ADM5120_MACH_EASY5120_RT) += easy5120-rt.o +obj-$(CONFIG_ADM5120_MACH_EASY5120_WVOIP) += easy5120-wvoip.o +obj-$(CONFIG_ADM5120_MACH_EASY5120P_ATA) += easy5120p-ata.o +obj-$(CONFIG_ADM5120_MACH_EASY83000) += easy83000.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-rt.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-rt.c new file mode 100644 index 0000000000..31eaee7721 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-rt.c @@ -0,0 +1,48 @@ +/* + * Infineon EASY 5120-RT Reference Board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "infineon.h" + +static struct gpio_led easy5120_rt_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN6, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan0_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan0_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), +}; + +static struct adm5120_pci_irq easy5120_rt_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static u8 easy5120_rt_vlans[6] __initdata = { + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 +}; + +static void __init easy5120_rt_setup(void) +{ + easy_setup_bga(); + + adm5120_add_device_switch(5, easy5120_rt_vlans); + adm5120_add_device_usb(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(easy5120_rt_gpio_leds), + easy5120_rt_gpio_leds); + adm5120_pci_set_irq_map(ARRAY_SIZE(easy5120_rt_pci_irqs), + easy5120_rt_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_EASY5120RT, "EASY5120-RT", + "Infineon EASY 5120-RT Reference Board", easy5120_rt_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-wvoip.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-wvoip.c new file mode 100644 index 0000000000..0bf404cc26 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120-wvoip.c @@ -0,0 +1,24 @@ +/* + * Infineon EASY 5120-WVoIP Reference Board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "infineon.h" + +static void __init easy5120wvoip_setup(void) +{ + easy_setup_bga(); + adm5120_add_device_switch(6, NULL); + + /* TODO: add VINETIC2 device */ + /* TODO: setup PCI IRQ map */ +} + +MIPS_MACHINE(MACH_ADM5120_EASY5120WVOIP, "EASY5120WVoIP", + "Infineon EASY 5120-WVoIP Reference Board", easy5120wvoip_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120p-ata.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120p-ata.c new file mode 100644 index 0000000000..fafe0238bd --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy5120p-ata.c @@ -0,0 +1,22 @@ +/* + * Infineon EASY 5120P-ATA Reference Board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "infineon.h" + +static void __init easy5120pata_setup(void) +{ + easy_setup_pqfp(); + + adm5120_add_device_switch(6, NULL); +} + +MIPS_MACHINE(MACH_ADM5120_EASY5120PATA, "EASY5120P-ATA", + "Infineon EASY 5120P-ATA Reference Board", easy5120pata_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy83000.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy83000.c new file mode 100644 index 0000000000..051b852749 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/easy83000.c @@ -0,0 +1,23 @@ +/* + * Infineon EASY 83000 Reference Board support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "infineon.h" + +static void __init easy83000_setup(void) +{ + easy_setup_pqfp(); + adm5120_add_device_switch(6, NULL); + + /* TODO: add VINAX device */ +} + +MIPS_MACHINE(MACH_ADM5120_EASY83000, "EASY8300", + "Infineon EASY 83000 Reference Board", easy83000_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.c new file mode 100644 index 0000000000..5c441da90e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.c @@ -0,0 +1,108 @@ +/* + * Infineon Reference Boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "infineon.h" + +#include + +#define EASY_CONFIG_OFFSET 0x10000 +#define EASY_CONFIG_SIZE 0x1000 + +static struct mtd_partition easy_partitions[] = { + { + .name = "admboot", + .offset = 0, + .size = 64*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "boardcfg", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static __init void easy_setup_mac(void) +{ + u8 mac_base[6]; + int err; + + err = admboot_get_mac_base(EASY_CONFIG_OFFSET, + EASY_CONFIG_SIZE, mac_base); + + if ((err) || !is_valid_ether_addr(mac_base)) + random_ether_addr(mac_base); + + adm5120_setup_eth_macs(mac_base); +} + +static void switch_bank_gpio3(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(ADM5120_GPIO_PIN3, 0); + break; + case 1: + gpio_set_value(ADM5120_GPIO_PIN3, 1); + break; + } +} + +void __init easy_setup_pqfp(void) +{ + /* setup flash A20 line */ + gpio_request(ADM5120_GPIO_PIN3, NULL); + gpio_direction_output(ADM5120_GPIO_PIN3, 0); + adm5120_flash0_data.switch_bank = switch_bank_gpio3; + + adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); + adm5120_flash0_data.parts = easy_partitions; + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_flash(0); + + easy_setup_mac(); +} + +static void switch_bank_gpio5(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(ADM5120_GPIO_PIN5, 0); + break; + case 1: + gpio_set_value(ADM5120_GPIO_PIN5, 1); + break; + } +} + +void __init easy_setup_bga(void) +{ + /* setup flash A20 line */ + gpio_request(ADM5120_GPIO_PIN5, NULL); + gpio_direction_output(ADM5120_GPIO_PIN5, 0); + adm5120_flash0_data.switch_bank = switch_bank_gpio5; + + adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); + adm5120_flash0_data.parts = easy_partitions; + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_flash(0); + + easy_setup_mac(); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.h new file mode 100644 index 0000000000..a5f28b4fec --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/infineon/infineon.h @@ -0,0 +1,25 @@ +/* + * Infineon Reference Boards + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +extern void easy_setup_pqfp(void) __init; +extern void easy_setup_bga(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/Makefile new file mode 100644 index 0000000000..34ea0a3d88 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/Makefile @@ -0,0 +1,8 @@ +obj-y += rb-1xx.o + +obj-${CONFIG_ADM5120_MACH_RB_11X} += rb-11x.o +obj-${CONFIG_ADM5120_MACH_RB_133} += rb-133.o +obj-${CONFIG_ADM5120_MACH_RB_133C} += rb-133c.o +obj-${CONFIG_ADM5120_MACH_RB_150} += rb-150.o +obj-${CONFIG_ADM5120_MACH_RB_153} += rb-153.o +obj-${CONFIG_ADM5120_MACH_RB_192} += rb-192.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-11x.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-11x.c new file mode 100644 index 0000000000..fd768d8ef0 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-11x.c @@ -0,0 +1,35 @@ +/* + * Mikrotik RouterBOARD 111/112 support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +static struct gpio_led rb11x_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN3, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan_lnkact", NULL), +}; + +static u8 rb11x_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init rb11x_setup(void) +{ + rb1xx_generic_setup(); + rb1xx_add_device_nand(); + + adm5120_add_device_switch(1, rb11x_vlans); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb11x_gpio_leds), + rb11x_gpio_leds); +} + +MIPS_MACHINE(MACH_ADM5120_RB_11X, "11x", "Mikrotik RouterBOARD 111/112", + rb11x_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133.c new file mode 100644 index 0000000000..23c57820c3 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133.c @@ -0,0 +1,40 @@ +/* + * Mikrotik RouterBOARD 133 support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +static struct gpio_led rb133_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN6, "power", NULL), + GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan1_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan2_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan2_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan3_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan3_lnkact", NULL), +}; + +static u8 rb133_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init rb133_setup(void) +{ + rb1xx_generic_setup(); + rb1xx_add_device_nand(); + + adm5120_add_device_switch(3, rb133_vlans); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133_gpio_leds), + rb133_gpio_leds); +} + +MIPS_MACHINE(MACH_ADM5120_RB_133, "133", "Mikrotik RouterBOARD 133", + rb133_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133c.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133c.c new file mode 100644 index 0000000000..25bab70c00 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-133c.c @@ -0,0 +1,36 @@ +/* + * Mikrotik RouterBOARD 133C support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +static struct gpio_led rb133c_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN6, "power", NULL), + GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan1_lnkact", NULL), +}; + +static u8 rb133c_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init rb133c_setup(void) +{ + rb1xx_generic_setup(); + rb1xx_add_device_nand(); + + adm5120_add_device_switch(1, rb133c_vlans); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133c_gpio_leds), + rb133c_gpio_leds); +} + +MIPS_MACHINE(MACH_ADM5120_RB_133C, "133C", "Mikrotik RouterBOARD 133C", + rb133c_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-150.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-150.c new file mode 100644 index 0000000000..96a8c1b87b --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-150.c @@ -0,0 +1,131 @@ +/* + * Mikrotik RouterBOARD 150 support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +#define RB150_NAND_BASE 0x1FC80000 +#define RB150_NAND_SIZE 1 + +#define RB150_GPIO_NAND_READY ADM5120_GPIO_PIN0 +#define RB150_GPIO_NAND_NCE ADM5120_GPIO_PIN1 +#define RB150_GPIO_NAND_CLE ADM5120_GPIO_P2L2 +#define RB150_GPIO_NAND_ALE ADM5120_GPIO_P3L2 +#define RB150_GPIO_RESET_BUTTON ADM5120_GPIO_PIN1 /* FIXME */ + +#define RB150_NAND_DELAY 100 + +#define RB150_NAND_WRITE(v) \ + writeb((v), (void __iomem *)KSEG1ADDR(RB150_NAND_BASE)) + +static struct resource rb150_nand_resources[] __initdata = { + [0] = { + .start = RB150_NAND_BASE, + .end = RB150_NAND_BASE + RB150_NAND_SIZE-1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct gpio_led rb150_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_P0L2, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan1_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan5_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan5_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan4_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan4_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_led2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan2_led1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan2_led2", NULL), +}; + +static u8 rb150_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static int rb150_nand_dev_ready(struct mtd_info *mtd) +{ + return gpio_get_value(RB150_GPIO_NAND_READY); +} + +static void rb150_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, + unsigned int ctrl) +{ + if (ctrl & NAND_CTRL_CHANGE) { + gpio_set_value(RB150_GPIO_NAND_CLE, (ctrl & NAND_CLE) ? 1 : 0); + gpio_set_value(RB150_GPIO_NAND_ALE, (ctrl & NAND_ALE) ? 1 : 0); + gpio_set_value(RB150_GPIO_NAND_NCE, (ctrl & NAND_NCE) ? 0 : 1); + } + + udelay(RB150_NAND_DELAY); + + if (cmd != NAND_CMD_NONE) + RB150_NAND_WRITE(cmd); +} + +static void __init rb150_add_device_nand(void) +{ + struct platform_device *pdev; + int err; + + /* setup GPIO pins for NAND flash chip */ + gpio_request(RB150_GPIO_NAND_READY, "nand-ready"); + gpio_direction_input(RB150_GPIO_NAND_READY); + gpio_request(RB150_GPIO_NAND_NCE, "nand-nce"); + gpio_direction_output(RB150_GPIO_NAND_NCE, 1); + gpio_request(RB150_GPIO_NAND_CLE, "nand-cle"); + gpio_direction_output(RB150_GPIO_NAND_CLE, 0); + gpio_request(RB150_GPIO_NAND_ALE, "nand-ale"); + gpio_direction_output(RB150_GPIO_NAND_ALE, 0); + + pdev = platform_device_alloc("gen_nand", -1); + if (!pdev) + goto err_out; + + err = platform_device_add_resources(pdev, rb150_nand_resources, + ARRAY_SIZE(rb150_nand_resources)); + if (err) + goto err_put; + + + rb1xx_nand_data.ctrl.cmd_ctrl = rb150_nand_cmd_ctrl; + rb1xx_nand_data.ctrl.dev_ready = rb150_nand_dev_ready; + + err = platform_device_add_data(pdev, &rb1xx_nand_data, + sizeof(rb1xx_nand_data)); + if (err) + goto err_put; + + err = platform_device_add(pdev); + if (err) + goto err_put; + + return; + +err_put: + platform_device_put(pdev); +err_out: + return; +} + +static void __init rb150_setup(void) +{ + rb1xx_gpio_buttons[0].gpio = RB150_GPIO_RESET_BUTTON; + rb1xx_generic_setup(); + rb150_add_device_nand(); + + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb150_gpio_leds), + rb150_gpio_leds); + adm5120_add_device_switch(5, rb150_vlans); +} + +MIPS_MACHINE(MACH_ADM5120_RB_150, "miniROUTER", "Mikrotik RouterBOARD 150", + rb150_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-153.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-153.c new file mode 100644 index 0000000000..8456684951 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-153.c @@ -0,0 +1,70 @@ +/* + * Mikrotik RouterBOARD 153 support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +static struct resource rb153_cf_resources[] __initdata = { + { + .name = "cf_membase", + .start = ADM5120_EXTIO1_BASE, + .end = ADM5120_EXTIO1_BASE + ADM5120_EXTIO1_SIZE-1 , + .flags = IORESOURCE_MEM + }, { + .name = "cf_irq", + .start = ADM5120_IRQ_GPIO4, + .end = ADM5120_IRQ_GPIO4, + .flags = IORESOURCE_IRQ + } +}; + +static struct gpio_led rb153_gpio_leds[] __initdata = { + GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan1_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan5_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan5_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan4_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan4_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan2_speed", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan2_lnkact", NULL), +}; + +static u8 rb153_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init rb153_add_device_cf(void) +{ + /* enable CSX1:INTX1 on GPIO[3:4] for the CF slot */ + adm5120_gpio_csx1_enable(); + + /* enable the wait state pin GPIO[0] for external I/O control */ + adm5120_gpio_ew_enable(); + + platform_device_register_simple("pata-rb153-cf", -1, + rb153_cf_resources, ARRAY_SIZE(rb153_cf_resources)); +} + +static void __init rb153_setup(void) +{ + rb1xx_generic_setup(); + rb1xx_add_device_nand(); + rb153_add_device_cf(); + + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb153_gpio_leds), + rb153_gpio_leds); + adm5120_add_device_switch(5, rb153_vlans); +} + +MIPS_MACHINE(MACH_ADM5120_RB_153, "150", "Mikrotik RouterBOARD 153", + rb153_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-192.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-192.c new file mode 100644 index 0000000000..9049421397 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-192.c @@ -0,0 +1,27 @@ +/* + * Mikrotik RouterBOARD 192 support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "rb-1xx.h" + +static u8 rb192_vlans[6] __initdata = { + 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init rb192_setup(void) +{ + rb1xx_generic_setup(); + rb1xx_add_device_nand(); + + adm5120_add_device_switch(6, rb192_vlans); +} + +MIPS_MACHINE(MACH_ADM5120_RB_192, "192", "Mikrotik RouterBOARD 192", + rb192_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.c new file mode 100644 index 0000000000..8961115c7e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.c @@ -0,0 +1,149 @@ +/* + * Mikrotik RouterBOARD 1xx series support + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * NAND initialization code was based on a driver for Linux 2.6.19+ which + * was derived from the driver for Linux 2.4.xx published by Mikrotik for + * their RouterBoard 1xx and 5xx series boards. + * Copyright (C) 2007 David Goodenough + * Copyright (C) 2007 Florian Fainelli + * + * 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 "rb-1xx.h" + +#define RB1XX_NAND_CHIP_DELAY 25 + +#define RB1XX_KEYS_POLL_INTERVAL 20 +#define RB1XX_KEYS_DEBOUNCE_INTERVAL (3 * RB1XX_KEYS_POLL_INTERVAL) + +static struct adm5120_pci_irq rb1xx_pci_irqs[] __initdata = { + PCIIRQ(1, 0, 1, ADM5120_IRQ_PCI0), + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI1), + PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI2) +}; + +static struct mtd_partition rb1xx_nor_parts[] = { + { + .name = "booter", + .offset = 0, + .size = 64*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct mtd_partition rb1xx_nand_parts[] = { + { + .name = "kernel", + .offset = 0, + .size = 4 * 1024 * 1024, + } , { + .name = "rootfs", + .offset = MTDPART_OFS_NXTBLK, + .size = MTDPART_SIZ_FULL + } +}; + +/* + * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader + * will not be able to find the kernel that we load. So set the oobinfo + * when creating the partitions + */ +static struct nand_ecclayout rb1xx_nand_ecclayout = { + .eccbytes = 6, + .eccpos = { 8, 9, 10, 13, 14, 15 }, + .oobavail = 9, + .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } +}; + +/*--------------------------------------------------------------------------*/ + +static int rb1xx_nand_fixup(struct mtd_info *mtd) +{ + struct nand_chip *chip = mtd->priv; + + if (mtd->writesize == 512) + chip->ecc.layout = &rb1xx_nand_ecclayout; + + return 0; +} + +struct platform_nand_data rb1xx_nand_data __initdata = { + .chip = { + .nr_chips = 1, + .nr_partitions = ARRAY_SIZE(rb1xx_nand_parts), + .partitions = rb1xx_nand_parts, + .chip_delay = RB1XX_NAND_CHIP_DELAY, + .chip_fixup = rb1xx_nand_fixup, + }, +}; + +struct gpio_keys_button rb1xx_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = KEY_RESTART, + .debounce_interval = RB1XX_KEYS_DEBOUNCE_INTERVAL, + .gpio = ADM5120_GPIO_PIN7, + } +}; + +static void __init rb1xx_mac_setup(void) +{ + if (rb_hs.mac_base != NULL && is_valid_ether_addr(rb_hs.mac_base)) { + adm5120_setup_eth_macs(rb_hs.mac_base); + } else { + u8 mac[ETH_ALEN]; + + random_ether_addr(mac); + adm5120_setup_eth_macs(mac); + } +} + +void __init rb1xx_add_device_flash(void) +{ + /* setup data for flash0 device */ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(rb1xx_nor_parts); + adm5120_flash0_data.parts = rb1xx_nor_parts; + adm5120_flash0_data.window_size = 128*1024; + + adm5120_add_device_flash(0); +} + +void __init rb1xx_add_device_nand(void) +{ + /* enable NAND flash interface */ + adm5120_nand_enable(); + + /* initialize NAND chip */ + adm5120_nand_set_spn(1); + adm5120_nand_set_wpn(0); + + adm5120_add_device_nand(&rb1xx_nand_data); +} + +void __init rb1xx_generic_setup(void) +{ + if (adm5120_package_bga()) + adm5120_pci_set_irq_map(ARRAY_SIZE(rb1xx_pci_irqs), + rb1xx_pci_irqs); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_register_gpio_buttons(-1, RB1XX_KEYS_POLL_INTERVAL, + ARRAY_SIZE(rb1xx_gpio_buttons), + rb1xx_gpio_buttons); + + rb1xx_add_device_flash(); + rb1xx_mac_setup(); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.h new file mode 100644 index 0000000000..05e68bd0a8 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/mikrotik/rb-1xx.h @@ -0,0 +1,33 @@ +/* + * Mikrotik RouterBOARD 1xx series support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include + +extern struct platform_nand_data rb1xx_nand_data __initdata; +extern struct gpio_keys_button rb1xx_gpio_buttons[] __initdata; + +extern void rb1xx_add_device_flash(void) __init; +extern void rb1xx_add_device_nand(void) __init; +extern void rb1xx_generic_setup(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/Makefile new file mode 100644 index 0000000000..239d5a0880 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ADM5120_MACH_PMUGW) += pmugw.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/pmugw.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/pmugw.c new file mode 100644 index 0000000000..369892fd13 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/motorola/pmugw.c @@ -0,0 +1,96 @@ +/* + * Motorola Powerline MU Gateway board + * + * Copyright (C) 2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +#define PMUGW_CONFIG_OFFSET 0x10000 +#define PMUGW_CONFIG_SIZE 0x1000 + +static struct mtd_partition pmugw_partitions[] = { + { + .name = "admboot", + .offset = 0, + .size = 64*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "boardcfg", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static u8 pmugw_vlans[6] __initdata = { + 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 +}; + +static __init void pmugw_setup_mac(void) +{ + u8 mac_base[6]; + int err; + + err = admboot_get_mac_base(PMUGW_CONFIG_OFFSET, + PMUGW_CONFIG_SIZE, mac_base); + + if ((err) || !is_valid_ether_addr(mac_base)) + random_ether_addr(mac_base); + + adm5120_setup_eth_macs(mac_base); +} + +static void switch_bank_gpio5(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(ADM5120_GPIO_PIN5, 0); + break; + case 1: + gpio_set_value(ADM5120_GPIO_PIN5, 1); + break; + } +} + +void __init pmugw_setup(void) +{ + /* setup flash A20 line */ + gpio_request(ADM5120_GPIO_PIN5, NULL); + gpio_direction_output(ADM5120_GPIO_PIN5, 0); + adm5120_flash0_data.switch_bank = switch_bank_gpio5; + + adm5120_flash0_data.nr_parts = ARRAY_SIZE(pmugw_partitions); + adm5120_flash0_data.parts = pmugw_partitions; + + adm5120_add_device_uart(1); /* ttyAM0 */ + adm5120_add_device_uart(0); /* ttyAM1 */ + + adm5120_add_device_flash(0); + + pmugw_setup_mac(); + adm5120_add_device_switch(5, pmugw_vlans); +} + +MIPS_MACHINE(MACH_ADM5120_PMUGW, "PMUGW", "Motorola Powerline MU Gateway", + pmugw_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/5gxi.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/5gxi.c new file mode 100644 index 0000000000..a5c2c3653e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/5gxi.c @@ -0,0 +1,71 @@ +/* + * OSBRiDGE 5GXi/5XLi board support + * + * Copyright (C) 2009 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 + * by the Free Software Foundation. + * + */ +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +static struct mtd_partition osbridge_5gxi_partitions[] = { + { + .name = "bootloader", + .offset = 0, + .size = 64*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "boardcfg", + .offset = 64*1024, + .size = 64*1024, + } , { + .name = "firmware", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct gpio_led osbridge_5gxi_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN6, "5gxi:green:user", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "5gxi:yellow:lan", NULL), +}; + +static struct adm5120_pci_irq osbridge_5gxi_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static u8 osbridge_5gxi_vlans[6] __initdata = { + 0x41, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static void __init osbridge_5gxi_setup(void) +{ + adm5120_flash0_data.nr_parts = ARRAY_SIZE(osbridge_5gxi_partitions); + adm5120_flash0_data.parts = osbridge_5gxi_partitions; + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_flash(0); + + adm5120_add_device_switch(1, osbridge_5gxi_vlans); + adm5120_add_device_gpio_leds(ARRAY_SIZE(osbridge_5gxi_gpio_leds), + osbridge_5gxi_gpio_leds); + adm5120_pci_set_irq_map(ARRAY_SIZE(osbridge_5gxi_pci_irqs), + osbridge_5gxi_pci_irqs); +} + +MIPS_MACHINE(MACH_ADM5120_5GXI, "5GXi", "OSBRiDGE 5GXi/5XLi board", + osbridge_5gxi_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/Makefile new file mode 100644 index 0000000000..34946c5e58 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/osbridge/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_ADM5120_MACH_5GXI) += 5gxi.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/Makefile new file mode 100644 index 0000000000..650be40779 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/Makefile @@ -0,0 +1,10 @@ +# +# Makefile for the ADMtek ADM5120 SoC specific parts of the kernel +# + +lib-y += admboot.o +lib-y += bootbase.o +lib-y += cfe.o +lib-y += generic.o +lib-y += myloader.o +lib-y += routerboot.o diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/admboot.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/admboot.c new file mode 100644 index 0000000000..b655390c16 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/admboot.c @@ -0,0 +1,55 @@ +/* + * ADMBoot specific prom routines + * + * Copyright (C) 2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include "prom_read.h" + +#define ADMBOOT_MAGIC_MAC_BASE 0x636D676D /* 'mgmc' */ +#define ADMBOOT_MAGIC_MAC_BASE_BR6104XX 0x31305348 /* 'HS01' */ + +int __init admboot_get_mac_base(u32 offset, u32 len, u8 *mac) +{ + u8 *cfg; + int i; + + cfg = (u8 *) KSEG1ADDR(ADM5120_SRAM0_BASE + offset); + for (i = 0; i < len; i += 4) { + u32 magic; + + magic = prom_read_le32(cfg + i); + if (magic == ADMBOOT_MAGIC_MAC_BASE) { + int j; + + for (j = 0; j < 6; j++) + mac[j] = cfg[i + 4 + j]; + + return 0; + } + if (magic == ADMBOOT_MAGIC_MAC_BASE_BR6104XX) { + int j; + + for (j = 0; j < 6; j++) + mac[j] = cfg[i + 7 + j]; + + return 0; + } + } + + return -ENXIO; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/bootbase.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/bootbase.c new file mode 100644 index 0000000000..063281e3f7 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/bootbase.c @@ -0,0 +1,119 @@ +/* + * ZyXEL's Bootbase specific prom routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "prom_read.h" + +#define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90) +#define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000) +#define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE) +#define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024)) + +static int bootbase_found; +static struct zynos_board_info *board_info; + +struct bootbase_info bootbase_info; + +static inline int bootbase_dbgarea_present(u8 *data) +{ + u32 t; + + t = prom_read_be32(data+5); + if (t != ZYNOS_MAGIC_DBGAREA1) + return 0; + + t = prom_read_be32(data+9); + if (t != ZYNOS_MAGIC_DBGAREA2) + return 0; + + return 1; +} + +static inline u32 bootbase_get_bootext_addr(void) +{ + return prom_read_be32(&board_info->bootext_addr); +} + +static inline void bootbase_get_mac(u8 *mac) +{ + int i; + + for (i = 0; i < 6; i++) + mac[i] = board_info->mac[i]; +} + +static inline u16 bootbase_get_vendor_id(void) +{ +#define CHECK_VENDOR(n) (strnicmp(board_info->vendor, (n), strlen(n)) == 0) + unsigned char vendor[ZYNOS_NAME_LEN]; + int i; + + for (i = 0; i < ZYNOS_NAME_LEN; i++) + vendor[i] = board_info->vendor[i]; + + if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL) + return ZYNOS_VENDOR_ID_ZYXEL; + + if CHECK_VENDOR(ZYNOS_VENDOR_DLINK) + return ZYNOS_VENDOR_ID_DLINK; + + if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT) + return ZYNOS_VENDOR_ID_LUCENT; + + if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR) + return ZYNOS_VENDOR_ID_NETGEAR; + + return ZYNOS_VENDOR_ID_OTHER; +} + +static inline u16 bootbase_get_board_id(void) +{ + return prom_read_be16(&board_info->board_id); +} + +int __init bootbase_present(void) +{ + u32 t; + + if (bootbase_found) + goto out; + + /* check presence of the dbgarea */ + if (bootbase_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0) + goto out; + + board_info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR); + + /* check for a valid BootExt address */ + t = bootbase_get_bootext_addr(); + if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX)) + goto out; + + bootbase_info.vendor_id = bootbase_get_vendor_id(); + bootbase_info.board_id = bootbase_get_board_id(); + bootbase_get_mac(bootbase_info.mac); + + bootbase_found = 1; + +out: + return bootbase_found; +} + diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/cfe.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/cfe.c new file mode 100644 index 0000000000..5a343cd7e4 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/cfe.c @@ -0,0 +1,69 @@ +/* + * Broadcom's CFE specific prom routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include + +#include +#include + +#include +#include "prom_read.h" + +/* + * CFE based boards + */ +#define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE +from other bootloaders */ + +static int cfe_found; + +static u32 cfe_handle; +static u32 cfe_entry; +static u32 cfe_seal; + +int __init cfe_present(void) +{ + /* + * This method only works, when we are booted directly from the CFE. + */ + u32 a1 = (u32) fw_arg1; + + if (cfe_found) + return 1; + + cfe_handle = (u32) fw_arg0; + cfe_entry = (u32) fw_arg2; + cfe_seal = (u32) fw_arg3; + + /* Check for CFE by finding the CFE magic number */ + if (cfe_seal != CFE_EPTSEAL) + return 0; + + /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 */ + if (a1 != 0) + return 0; + + /* The cfe_handle, and the cfe_entry must be kernel mode addresses */ + if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0)) + return 0; + + cfe_found = 1; + return 1; +} + +char *cfe_getenv(char *envname) +{ + if (cfe_found == 0) + return NULL; + + return NULL; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/generic.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/generic.c new file mode 100644 index 0000000000..4d4caa8476 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/generic.c @@ -0,0 +1,47 @@ +/* + * Generic PROM routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include + +#include + +#include + +static int *_prom_argc; +static char **_prom_argv; +static char **_prom_envp; + +char *generic_prom_getenv(char *envname) +{ + char **env; + char *ret; + + ret = NULL; + for (env = _prom_envp; *env != NULL; env++) { + if (strcmp(envname, *env++) == 0) { + ret = *env; + break; + } + } + + return ret; +} + +int generic_prom_present(void) +{ + _prom_argc = (int *)fw_arg0; + _prom_argv = (char **)fw_arg1; + _prom_envp = (char **)fw_arg2; + + return 1; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/myloader.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/myloader.c new file mode 100644 index 0000000000..5357db511b --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/myloader.c @@ -0,0 +1,68 @@ +/* + * Compex's MyLoader specific prom routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include "prom_read.h" + +#define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000) +#define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800) +#define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000) + +static int myloader_found; + +struct myloader_info myloader_info; + +int __init myloader_present(void) +{ + struct mylo_system_params *sysp; + struct mylo_board_params *boardp; + struct mylo_partition_table *parts; + int i; + + if (myloader_found) + goto out; + + sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR); + boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR); + parts = (struct mylo_partition_table *)(PART_TABLE_ADDR); + + /* Check for some magic numbers */ + if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) || + (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) || + (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS)) + goto out; + + myloader_info.vid = le32_to_cpu(sysp->vid); + myloader_info.did = le32_to_cpu(sysp->did); + myloader_info.svid = le32_to_cpu(sysp->svid); + myloader_info.sdid = le32_to_cpu(sysp->sdid); + + for (i = 0; i < MYLO_ETHADDR_COUNT; i++) { + int j; + for (j = 0; j < 6; j++) + myloader_info.macs[i][j] = boardp->addr[i].mac[j]; + } + + myloader_found = 1; + +out: + return myloader_found; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/prom_read.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/prom_read.h new file mode 100644 index 0000000000..1a6ea110ce --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/prom_read.h @@ -0,0 +1,50 @@ +/* + * Generic prom definitions + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _ADM5120_PROM_H_ +#define _ADM5120_PROM_H_ + +/* + * Helper routines + */ +static inline u16 prom_read_le16(void *buf) +{ + u8 *p = buf; + + return ((u16)p[0] + ((u16)p[1] << 8)); +} + +static inline u32 prom_read_le32(void *buf) +{ + u8 *p = buf; + + return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) + + ((u32)p[3] << 24)); +} + +static inline u16 prom_read_be16(void *buf) +{ + u8 *p = buf; + + return (((u16)p[0] << 8) + (u16)p[1]); +} + +static inline u32 prom_read_be32(void *buf) +{ + u8 *p = buf; + + return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) + + ((u32)p[3])); +} + +#endif /* _ADM5120_PROM_H_ */ + + diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/routerboot.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/routerboot.c new file mode 100644 index 0000000000..d9a06d968e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/prom/routerboot.c @@ -0,0 +1,121 @@ +/* + * Mikrotik's RouterBOOT specific prom routines + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include "prom_read.h" + +struct rb_hard_settings rb_hs; +static int rb_found; + +static int __init routerboot_load_hs(u8 *buf, u16 buflen) +{ + u16 id, len; + + memset(&rb_hs, 0, sizeof(rb_hs)); + + if (buflen < 4) + return -1; + + if (prom_read_le32(buf) != RB_MAGIC_HARD) + return -1; + + /* skip magic value */ + buf += 4; + buflen -= 4; + + while (buflen > 2) { + id = prom_read_le16(buf); + buf += 2; + buflen -= 2; + if (id == RB_ID_TERMINATOR || buflen < 2) + break; + + len = prom_read_le16(buf); + buf += 2; + buflen -= 2; + + if (buflen < len) + break; + + switch (id) { + case RB_ID_BIOS_VERSION: + rb_hs.bios_ver = (char *)buf; + break; + case RB_ID_BOARD_NAME: + rb_hs.name = (char *)buf; + break; + case RB_ID_MEMORY_SIZE: + rb_hs.mem_size = prom_read_le32(buf); + break; + case RB_ID_MAC_ADDRESS_COUNT: + rb_hs.mac_count = prom_read_le32(buf); + break; + case RB_ID_MAC_ADDRESS_PACK: + if ((len / RB_MAC_SIZE) > 0) + rb_hs.mac_base = buf; + break; + } + + buf += len; + buflen -= len; + + } + + return 0; +} + +#define RB_BS_OFFS 0x14 +#define RB_OFFS_MAX (128*1024) + +int __init routerboot_present(void) +{ + struct rb_bios_settings *bs; + u8 *base; + u32 off, len; + + if (rb_found) + goto out; + + base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE); + bs = (struct rb_bios_settings *)(base + RB_BS_OFFS); + + off = prom_read_le32(&bs->hs_offs); + len = prom_read_le32(&bs->hs_size); + if (off > RB_OFFS_MAX) + goto out; + + if (routerboot_load_hs(base+off, len) != 0) + goto out; + + rb_found = 1; + +out: + return rb_found; +} + +char *routerboot_get_boardname(void) +{ + if (rb_found == 0) + return NULL; + + return rb_hs.name; +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/Makefile b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/Makefile new file mode 100644 index 0000000000..e8325a1b1f --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/Makefile @@ -0,0 +1,4 @@ +obj-y += p-33x.o + +obj-${CONFIG_ADM5120_MACH_P_334WT} += p-334wt.o +obj-${CONFIG_ADM5120_MACH_P_335} += p-335.o \ No newline at end of file diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-334wt.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-334wt.c new file mode 100644 index 0000000000..6cc9aee857 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-334wt.c @@ -0,0 +1,34 @@ +/* + * ZyXEL Prestige P-334WT support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "p-33x.h" + +static struct gpio_led p334wt_gpio_leds[] __initdata = { + GPIO_LED_INV(ADM5120_GPIO_PIN2, "power", NULL), + GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan1", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan3", NULL), + GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan4", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), + GPIO_LED_INV(ADM5120_GPIO_P4L2, "wlan", NULL), + GPIO_LED_INV(ADM5120_GPIO_P2L2, "otist", NULL), + GPIO_LED_INV(ADM5120_GPIO_P1L2, "hidden", NULL), +}; + +static void __init p334wt_setup(void) +{ + p33x_generic_setup(); + adm5120_add_device_gpio_leds(ARRAY_SIZE(p334wt_gpio_leds), + p334wt_gpio_leds); +} + +MIPS_MACHINE(MACH_ADM5120_P334WT, "P-334WT", "ZyXEL Prestige 334WT", + p334wt_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-335.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-335.c new file mode 100644 index 0000000000..6ac2b09158 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-335.c @@ -0,0 +1,21 @@ +/* + * ZyXEL Prestige P-335/335WT support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "p-33x.h" + +static void __init p335_setup(void) +{ + p33x_generic_setup(); + adm5120_add_device_usb(); +} + +MIPS_MACHINE(MACH_ADM5120_P335, "P-335", "ZyXEL Prestige 335/335WT", + p335_setup); diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.c b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.c new file mode 100644 index 0000000000..2626cf9eec --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.c @@ -0,0 +1,85 @@ +/* + * ZyXEL Prestige P-33x boards support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include "p-33x.h" + +#include + +#define P33X_GPIO_FLASH_A20 ADM5120_GPIO_PIN5 +static struct mtd_partition p33x_partitions[] = { + { + .name = "bootbase", + .offset = 0, + .size = 16*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "rom", + .offset = MTDPART_OFS_APPEND, + .size = 16*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "bootext1", + .offset = MTDPART_OFS_APPEND, + .size = 32*1024, + } , { + .name = "bootext2", + .offset = MTDPART_OFS_APPEND, + .size = 64*1024, + } , { + .name = "trx", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } , { + .name = "firmware", + .offset = 32*1024, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct adm5120_pci_irq p33x_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static u8 p33x_vlans[6] __initdata = { + /* FIXME: untested */ + 0x50, 0x48, 0x44, 0x42, 0x41, 0x00 +}; + +static void switch_bank_gpio5(unsigned bank) +{ + switch (bank) { + case 0: + gpio_set_value(P33X_GPIO_FLASH_A20, 0); + break; + case 1: + gpio_set_value(P33X_GPIO_FLASH_A20, 1); + break; + } +} + +void __init p33x_generic_setup(void) +{ + /* setup data for flash0 device */ + gpio_request(P33X_GPIO_FLASH_A20, NULL); /* for flash A20 line */ + gpio_direction_output(P33X_GPIO_FLASH_A20, 0); + adm5120_flash0_data.switch_bank = switch_bank_gpio5; + adm5120_flash0_data.nr_parts = ARRAY_SIZE(p33x_partitions); + adm5120_flash0_data.parts = p33x_partitions; + adm5120_add_device_flash(0); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_setup_eth_macs(bootbase_info.mac); + adm5120_add_device_switch(6, p33x_vlans); + + adm5120_pci_set_irq_map(ARRAY_SIZE(p33x_pci_irqs), p33x_pci_irqs); +} diff --git a/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.h b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.h new file mode 100644 index 0000000000..8a7340cb5e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/adm5120/zyxel/p-33x.h @@ -0,0 +1,22 @@ +/* + * ZyXEL Prestige P-33x boards support + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include + +#include + +#include +#include + +extern void p33x_generic_setup(void) __init; diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_defs.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_defs.h new file mode 100644 index 0000000000..bf220ff4d6 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_defs.h @@ -0,0 +1,53 @@ +/* + * ADM5120 SoC definitions + * + * This file defines some constants specific to the ADM5120 SoC + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ +#ifndef _ASM_MIPS_MACH_ADM5120_DEFS_H +#define _ASM_MIPS_MACH_ADM5120_DEFS_H + +#define ADM5120_SDRAM0_BASE 0x00000000 +#define ADM5120_SDRAM1_BASE 0x01000000 +#define ADM5120_SRAM1_BASE 0x10000000 +#define ADM5120_EXTIO0_BASE 0x10C00000 +#define ADM5120_EXTIO0_SIZE 0x00200000 +#define ADM5120_EXTIO1_BASE 0x10E00000 +#define ADM5120_EXTIO1_SIZE 0x00200000 +#define ADM5120_MPMC_BASE 0x11000000 +#define ADM5120_MPMC_SIZE 0x00200000 +#define ADM5120_USBC_BASE 0x11200000 +#define ADM5120_USBC_SIZE 0x00200000 +#define ADM5120_PCIMEM_BASE 0x11400000 +#define ADM5120_PCIMEM_SIZE 0x00100000 +#define ADM5120_PCIIO_BASE 0x11500000 +#define ADM5120_PCIIO_SIZE 0x000FFFF0 +#define ADM5120_PCICFG_ADDR 0x115FFFF0 +#define ADM5120_PCICFG_DATA 0x115FFFF8 +#define ADM5120_PCICFG_SIZE 0x00000010 +#define ADM5120_SWITCH_BASE 0x12000000 +#define ADM5120_SWITCH_SIZE 0x00200000 +#define ADM5120_INTC_BASE 0x12200000 +#define ADM5120_INTC_SIZE 0x00200000 +#define ADM5120_UART0_BASE 0x12600000 +#define ADM5120_UART1_BASE 0x12800000 +#define ADM5120_UART_SIZE 0x00200000 +#define ADM5120_SRAM0_BASE 0x1FC00000 + +#define ADM5120_NAND_BASE ADM5120_SRAM1_BASE +#define ADM5120_NAND_SIZE 0xB + +#define ADM5120_CLK_175 175000000 +#define ADM5120_CLK_200 200000000 +#define ADM5120_CLK_225 225000000 +#define ADM5120_CLK_250 250000000 + +#define ADM5120_UART_CLOCK 62500000 + +#endif /* _ASM_MIPS_MACH_ADM5120_DEFS_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_info.h new file mode 100644 index 0000000000..1d34d80ee6 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_info.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2007-2009 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MACH_ADM5120_INFO_H +#define _MACH_ADM5120_INFO_H + +#include + +extern unsigned int adm5120_prom_type; +#define ADM5120_PROM_GENERIC 0 +#define ADM5120_PROM_CFE 1 +#define ADM5120_PROM_MYLOADER 2 +#define ADM5120_PROM_ROUTERBOOT 3 +#define ADM5120_PROM_BOOTBASE 4 +#define ADM5120_PROM_UBOOT 5 +#define ADM5120_PROM_LAST 5 + +extern unsigned int adm5120_product_code; +extern unsigned int adm5120_revision; +extern unsigned int adm5120_nand_boot; + +extern unsigned long adm5120_speed; +#define ADM5120_SPEED_175 175000000 +#define ADM5120_SPEED_200 200000000 +#define ADM5120_SPEED_225 225000000 +#define ADM5120_SPEED_250 250000000 + +extern unsigned int adm5120_package; +#define ADM5120_PACKAGE_PQFP 0 +#define ADM5120_PACKAGE_BGA 1 + +extern unsigned long adm5120_memsize; + +enum { + MACH_ADM5120_GENERIC = 0, /* Generic board */ + MACH_ADM5120_5GXI, /* OSBRiDGE 5GXi/5XLi */ + MACH_ADM5120_BR6104K, /* Edimax BR-6104K */ + MACH_ADM5120_BR6104KP, /* Edimax BR-6104KP */ + MACH_ADM5120_BR61X4WG, /* Edimax BR-6104Wg/BR-6114WG */ + MACH_ADM5120_CAS630, /* Cellvision CAS-630/630W */ + MACH_ADM5120_CAS670, /* Cellvision CAS-670/670W */ + MACH_ADM5120_CAS700, /* Cellvision CAS-700/700W */ + MACH_ADM5120_CAS771, /* Cellvision CAS-771/771W */ + MACH_ADM5120_CAS790, /* Cellvision CAS-790 */ + MACH_ADM5120_CAS861, /* Cellvision CAS-861/861W */ + MACH_ADM5120_EASY5120PATA, /* Infineon EASY 5120P-ATA */ + MACH_ADM5120_EASY5120RT, /* Infineon EASY 5120-RT */ + MACH_ADM5120_EASY5120WVOIP, /* Infineon EASY 5120-WVoIP */ + MACH_ADM5120_EASY83000, /* Infineon EASY-83000 */ + MACH_ADM5120_ES2108, /* ZyXEL Ethernet Switch 2108 */ + MACH_ADM5120_ES2108F, /* ZyXEL Ethernet Switch 2108-F */ + MACH_ADM5120_ES2108G, /* ZyXEL Ethernet Switch 2108-G */ + MACH_ADM5120_ES2108LC, /* ZyXEL Ethernet Switch 2108-LC */ + MACH_ADM5120_ES2108PWR, /* ZyXEL Ethernet Switch 2108-PWR */ + MACH_ADM5120_ES2024A, /* ZyXEL Ethernet Switch 2024A */ + MACH_ADM5120_ES2024PWR, /* ZyXEL Ethernet Switch 2024PWR */ + MACH_ADM5120_HS100, /* ZyXEL HomeSafe 100/100W */ + MACH_ADM5120_NFS101U, /* Cellvision NFS-101U/101WU */ + MACH_ADM5120_NFS202U, /* Cellvision NFS-202U/202WU */ + MACH_ADM5120_NP28G, /* Compex NP28G */ + MACH_ADM5120_NP28GHS, /* Compex NP28G HotSpot */ + MACH_ADM5120_NP27G, /* Compex NP27G */ + MACH_ADM5120_RB_11X, /* Mikrotik RouterBOARD 111/112 */ + MACH_ADM5120_RB_133, /* Mikrotik RouterBOARD 133 */ + MACH_ADM5120_RB_133C, /* Mikrotik RouterBOARD 133c */ + MACH_ADM5120_RB_150, /* Mikrotik RouterBOARD 150 */ + MACH_ADM5120_RB_153, /* Mikrotik RouterBOARD 153 */ + MACH_ADM5120_RB_192, /* Mikrotik RouterBOARD 192 */ + MACH_ADM5120_P334U, /* ZyXEL Prestige 334U */ + MACH_ADM5120_P334W, /* ZyXEL Prestige 334W */ + MACH_ADM5120_P334WH, /* ZyXEL Prestige 334WH */ + MACH_ADM5120_P334WHD, /* ZyXEL Prestige 334WHD */ + MACH_ADM5120_P334WT, /* ZyXEL Prestige 334WT */ + MACH_ADM5120_P335, /* ZyXEL Prestige 335/335WT */ + MACH_ADM5120_P335PLUS, /* ZyXEL Prestige 335Plus */ + MACH_ADM5120_P335U, /* ZyXEL Prestige 335U */ + MACH_ADM5120_PMUGW, /* Motorola Powerline MU Gateway */ + MACH_ADM5120_WP54, /* Compex WP54G/WP54AG/WPP54G/WPP54AG */ + MACH_ADM5120_WP54G_WRT, /* Compex WP54G-WRT */ + MACH_ADM5120_WP54Gv1C, /* Compex WP54G version 1C */ + MACH_ADM5120_EB_214A, /* Generic EB-214A */ +}; + +/* + * TODO:remove adm5120_eth* variables when the switch driver will be + * converted into a real platform driver + */ +extern unsigned int adm5120_eth_num_ports; +extern unsigned char adm5120_eth_macs[6][6]; +extern unsigned char adm5120_eth_vlans[6]; + +extern void adm5120_soc_init(void) __init; +extern void adm5120_mem_init(void) __init; +extern void adm5120_ndelay(u32 ns); + +extern void (*adm5120_board_reset)(void); + +extern void adm5120_gpio_init(void) __init; +extern void adm5120_gpio_csx0_enable(void) __init; +extern void adm5120_gpio_csx1_enable(void) __init; +extern void adm5120_gpio_ew_enable(void) __init; + +static inline int adm5120_package_pqfp(void) +{ + return (adm5120_package == ADM5120_PACKAGE_PQFP); +} + +static inline int adm5120_package_bga(void) +{ + return (adm5120_package == ADM5120_PACKAGE_BGA); +} + +static inline int adm5120_has_pci(void) +{ + return (adm5120_package == ADM5120_PACKAGE_BGA); +} + +static inline int adm5120_has_gmii(void) +{ + return (adm5120_package == ADM5120_PACKAGE_BGA); +} + +#endif /* _MACH_ADM5120_INFO_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_intc.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_intc.h new file mode 100644 index 0000000000..70dd6bbe85 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_intc.h @@ -0,0 +1,63 @@ +/* + * ADM5120 interrupt controller definitions + * + * This header file defines the hardware registers of the ADM5120 SoC + * built-in interrupt controller. + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MACH_ADM5120_INTC_H +#define _MACH_ADM5120_INTC_H + +/* + * INTC register offsets + */ +#define INTC_REG_IRQ_STATUS 0x00 /* Interrupt status after masking */ +#define INTC_REG_IRQ_RAW_STATUS 0x04 /* Interrupt status before masking */ +#define INTC_REG_IRQ_ENABLE 0x08 /* Used to enable the interrupt sources */ +#define INTC_REG_IRQ_ENABLE_CLEAR 0x0C /* Used to disable the interrupt sources */ +#define INTC_REG_IRQ_DISABLE INTC_REG_IRQ_ENABLE_CLEAR +#define INTC_REG_INT_MODE 0x14 /* The interrupt mode of the sources */ +#define INTC_REG_FIQ_STATUS 0x18 /* FIQ status */ +#define INTC_REG_IRQ_TEST_SOURCE 0x1C +#define INTC_REG_IRQ_SOURCE_SELECT 0x20 +#define INTC_REG_INT_LEVEL 0x24 + +/* + * INTC IRQ numbers + */ +#define INTC_IRQ_TIMER 0 /* built in timer */ +#define INTC_IRQ_UART0 1 /* built-in UART0 */ +#define INTC_IRQ_UART1 2 /* built-in UART1 */ +#define INTC_IRQ_USBC 3 /* USB Host Controller */ +#define INTC_IRQ_GPIO2 4 /* GPIO line 2 */ +#define INTC_IRQ_GPIO4 5 /* GPIO line 4 */ +#define INTC_IRQ_PCI0 6 /* PCI slot 2 */ +#define INTC_IRQ_PCI1 7 /* PCI slot 3 */ +#define INTC_IRQ_PCI2 8 /* PCI slot 4 */ +#define INTC_IRQ_SWITCH 9 /* built-in ethernet switch */ +#define INTC_IRQ_LAST INTC_IRQ_SWITCH +#define INTC_IRQ_COUNT 10 + +/* + * INTC register bits + */ +#define INTC_INT_TIMER (1 << INTC_IRQ_TIMER) +#define INTC_INT_UART0 (1 << INTC_IRQ_UART0) +#define INTC_INT_UART1 (1 << INTC_IRQ_UART1) +#define INTC_INT_USBC (1 << INTC_IRQ_USBC) +#define INTC_INT_INTX0 (1 << INTC_IRQ_INTX0) +#define INTC_INT_INTX1 (1 << INTC_IRQ_INTX1) +#define INTC_INT_PCI0 (1 << INTC_IRQ_PCI0) +#define INTC_INT_PCI1 (1 << INTC_IRQ_PCI1) +#define INTC_INT_PCI2 (1 << INTC_IRQ_PCI2) +#define INTC_INT_SWITCH (1 << INTC_IRQ_SWITCH) +#define INTC_INT_ALL ((1 << INTC_IRQ_COUNT) - 1) + +#endif /* _MACH_ADM5120_INTC_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h new file mode 100644 index 0000000000..c4e9591fb8 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h @@ -0,0 +1,92 @@ +/* + * ADM5120 MPMC (Multiport Memory Controller) register definitions + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MACH_ADM5120_MPMC_H +#define _MACH_ADM5120_MPMC_H + +#define MPMC_READ_REG(r) __raw_readl( \ + (void __iomem *)KSEG1ADDR(ADM5120_MPMC_BASE) + MPMC_REG_ ## r) +#define MPMC_WRITE_REG(r, v) __raw_writel((v), \ + (void __iomem *)KSEG1ADDR(ADM5120_MPMC_BASE) + MPMC_REG_ ## r) + +#define MPMC_REG_CTRL 0x0000 +#define MPMC_REG_STATUS 0x0004 +#define MPMC_REG_CONF 0x0008 +#define MPMC_REG_DC 0x0020 +#define MPMC_REG_DR 0x0024 +#define MPMC_REG_DRP 0x0030 + +#define MPMC_REG_DC0 0x0100 +#define MPMC_REG_DRC0 0x0104 +#define MPMC_REG_DC1 0x0120 +#define MPMC_REG_DRC1 0x0124 +#define MPMC_REG_DC2 0x0140 +#define MPMC_REG_DRC2 0x0144 +#define MPMC_REG_DC3 0x0160 +#define MPMC_REG_DRC3 0x0164 +#define MPMC_REG_SC0 0x0200 /* for F_CS1_N */ +#define MPMC_REG_SC1 0x0220 /* for F_CS0_N */ +#define MPMC_REG_SC2 0x0240 +#define MPMC_REG_WEN2 0x0244 +#define MPMC_REG_OEN2 0x0248 +#define MPMC_REG_RD2 0x024C +#define MPMC_REG_PG2 0x0250 +#define MPMC_REG_WR2 0x0254 +#define MPMC_REG_TN2 0x0258 +#define MPMC_REG_SC3 0x0260 + +/* Control register bits */ +#define MPMC_CTRL_AM (1 << 1) /* Address Mirror */ +#define MPMC_CTRL_LPM (1 << 2) /* Low Power Mode */ +#define MPMC_CTRL_DWB (1 << 3) /* Drain Write Buffers */ + +/* Status register bits */ +#define MPMC_STATUS_BUSY (1 << 0) /* Busy */ +#define MPMC_STATUS_WBS (1 << 1) /* Write Buffer Status */ +#define MPMC_STATUS_SRA (1 << 2) /* Self-Refresh Acknowledge*/ + +/* Dynamic Control register bits */ +#define MPMC_DC_CE (1 << 0) +#define MPMC_DC_DMC (1 << 1) +#define MPMC_DC_SRR (1 << 2) +#define MPMC_DC_SI_SHIFT 7 +#define MPMC_DC_SI_MASK (3 << 7) +#define MPMC_DC_SI_NORMAL (0 << 7) +#define MPMC_DC_SI_MODE (1 << 7) +#define MPMC_DC_SI_PALL (2 << 7) +#define MPMC_DC_SI_NOP (3 << 7) + +#define SRAM_REG_CONF 0x00 +#define SRAM_REG_WWE 0x04 +#define SRAM_REG_WOE 0x08 +#define SRAM_REG_WRD 0x0C +#define SRAM_REG_WPG 0x10 +#define SRAM_REG_WWR 0x14 +#define SRAM_REG_WTR 0x18 + +/* Dynamic Configuration register bits */ +#define DC_BE (1 << 19) /* buffer enable */ +#define DC_RW_SHIFT 28 /* shift for number of rows */ +#define DC_RW_MASK 0x03 +#define DC_NB_SHIFT 26 /* shift for number of banks */ +#define DC_NB_MASK 0x01 +#define DC_CW_SHIFT 22 /* shift for number of columns */ +#define DC_CW_MASK 0x07 +#define DC_DW_SHIFT 7 /* shift for device width */ +#define DC_DW_MASK 0x03 + +/* Static Configuration register bits */ +#define SC_MW_MASK 0x03 /* memory width mask */ +#define SC_MW_8 0x00 /* 8 bit memory width */ +#define SC_MW_16 0x01 /* 16 bit memory width */ +#define SC_MW_32 0x02 /* 32 bit memory width */ + +#endif /* _MACH_ADM5120_MPMC_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_nand.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_nand.h new file mode 100644 index 0000000000..1e2f3bd15d --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_nand.h @@ -0,0 +1,89 @@ +/* + * ADM5120 NAND interface definitions + * + * This header file defines the hardware registers of the ADM5120 SoC + * built-in NAND interface. + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * NAND interface routines was based on a driver for Linux 2.6.19+ which + * was derived from the driver for Linux 2.4.xx published by Mikrotik for + * their RouterBoard 1xx and 5xx series boards. + * Copyright (C) 2007 David Goodenough + * Copyright (C) 2007 Florian Fainelli + * + * 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 _MACH_ADM5120_NAND_H +#define _MACH_ADM5120_NAND_H + +#include +#include + +#include +#include + +/* NAND control registers */ +#define NAND_REG_DATA 0x0 /* data register */ +#define NAND_REG_SET_CEn 0x1 /* CE# low */ +#define NAND_REG_CLR_CEn 0x2 /* CE# high */ +#define NAND_REG_CLR_CLE 0x3 /* CLE low */ +#define NAND_REG_SET_CLE 0x4 /* CLE high */ +#define NAND_REG_CLR_ALE 0x5 /* ALE low */ +#define NAND_REG_SET_ALE 0x6 /* ALE high */ +#define NAND_REG_SET_SPn 0x7 /* SP# low (use spare area) */ +#define NAND_REG_CLR_SPn 0x8 /* SP# high (do not use spare area) */ +#define NAND_REG_SET_WPn 0x9 /* WP# low */ +#define NAND_REG_CLR_WPn 0xA /* WP# high */ +#define NAND_REG_STATUS 0xB /* Status register */ + +#define ADM5120_NAND_STATUS_READY 0x80 + +#define NAND_READ_REG(r) \ + readb((void __iomem *)KSEG1ADDR(ADM5120_NAND_BASE) + (r)) +#define NAND_WRITE_REG(r, v) \ + writeb((v), (void __iomem *)KSEG1ADDR(ADM5120_NAND_BASE) + (r)) + +/*-------------------------------------------------------------------------*/ + +static inline void adm5120_nand_enable(void) +{ + SW_WRITE_REG(SWITCH_REG_BW_CNTL1, BW_CNTL1_NAND_ENABLE); + SW_WRITE_REG(SWITCH_REG_BOOT_DONE, 1); +} + +static inline void adm5120_nand_set_wpn(unsigned int set) +{ + NAND_WRITE_REG((set) ? NAND_REG_SET_WPn : NAND_REG_CLR_WPn, 1); +} + +static inline void adm5120_nand_set_spn(unsigned int set) +{ + NAND_WRITE_REG((set) ? NAND_REG_SET_SPn : NAND_REG_CLR_SPn, 1); +} + +static inline void adm5120_nand_set_cle(unsigned int set) +{ + NAND_WRITE_REG((set) ? NAND_REG_SET_CLE : NAND_REG_CLR_CLE, 1); +} + +static inline void adm5120_nand_set_ale(unsigned int set) +{ + NAND_WRITE_REG((set) ? NAND_REG_SET_ALE : NAND_REG_CLR_ALE, 1); +} + +static inline void adm5120_nand_set_cen(unsigned int set) +{ + NAND_WRITE_REG((set) ? NAND_REG_SET_CEn : NAND_REG_CLR_CEn, 1); +} + +static inline u8 adm5120_nand_get_status(void) +{ + return NAND_READ_REG(NAND_REG_STATUS); +} + +#endif /* _MACH_ADM5120_NAND_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_platform.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_platform.h new file mode 100644 index 0000000000..ed73b53297 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_platform.h @@ -0,0 +1,87 @@ +/* + * ADM5120 specific platform definitions + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _ASM_MIPS_MACH_ADM5120_PLATFORM_H +#define _ASM_MIPS_MACH_ADM5120_PLATFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct adm5120_flash_platform_data { + void (*set_vpp)(struct map_info *, int); + void (*switch_bank)(unsigned); + u32 window_size; + unsigned int nr_parts; + struct mtd_partition *parts; +}; + +struct adm5120_switch_platform_data { + /* TODO: not yet implemented */ +}; + +struct adm5120_pci_irq { + u8 slot; + u8 func; + u8 pin; + unsigned irq; +}; + +#define PCIIRQ(s, f, p, i) {.slot = (s), .func = (f), .pin = (p), .irq = (i)} + +#ifdef CONFIG_PCI +extern void adm5120_pci_set_irq_map(unsigned int nr_irqs, + struct adm5120_pci_irq *map) __init; +#else +static inline void adm5120_pci_set_irq_map(unsigned int nr_irqs, + struct adm5120_pci_irq *map) +{ +} +#endif + +extern void adm5120_setup_eth_macs(u8 *mac_base) __init; + +extern struct adm5120_flash_platform_data adm5120_flash0_data; +extern struct adm5120_flash_platform_data adm5120_flash1_data; + +extern void adm5120_add_device_flash(unsigned id) __init; +extern void adm5120_add_device_usb(void) __init; +extern void adm5120_add_device_uart(unsigned id) __init; +extern void adm5120_add_device_nand(struct platform_nand_data *pdata) __init; +extern void adm5120_add_device_switch(unsigned num_ports, u8 *vlan_map) __init; +extern void adm5120_register_gpio_buttons(int id, + unsigned poll_interval, + unsigned nbuttons, + struct gpio_keys_button *buttons); + +#define GPIO_LED_DEF(g, n, t, a) { \ + .name = (n), \ + .default_trigger = (t), \ + .gpio = (g), \ + .active_low = (a) \ +} + +#define GPIO_LED_STD(g, n, t) GPIO_LED_DEF((g), (n), (t), 0) +#define GPIO_LED_INV(g, n, t) GPIO_LED_DEF((g), (n), (t), 1) + +extern void adm5120_add_device_gpio_leds(unsigned num_leds, + struct gpio_led *leds) __init; + +#endif /* _ASM_MIPS_MACH_ADM5120_PLATFORM_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_switch.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_switch.h new file mode 100644 index 0000000000..91adc5bae9 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_switch.h @@ -0,0 +1,300 @@ +/* + * ADM5120 ethernet switch definitions + * + * This header file defines the hardware registers of the ADM5120 SoC + * built-in Ethernet switch. + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MACH_ADM5120_SWITCH_H +#define _MACH_ADM5120_SWITCH_H + +#ifndef BIT +# define BIT(at) (1 << (at)) +#endif +#define BITMASK(len) (BIT(len)-1) + +#define SW_READ_REG(r) __raw_readl( \ + (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE) + r) +#define SW_WRITE_REG(r, v) __raw_writel((v), \ + (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE) + r) + +/* Switch register offsets */ +#define SWITCH_REG_CODE 0x0000 +#define SWITCH_REG_SOFT_RESET 0x0004 /* Soft Reset */ +#define SWITCH_REG_BOOT_DONE 0x0008 /* Boot Done */ +#define SWITCH_REG_SW_RESET 0x000C /* Switch Reset */ +#define SWITCH_REG_PHY_STATUS 0x0014 /* PHY Status */ +#define SWITCH_REG_MEMCTRL 0x001C /* Memory Control */ +#define SWITCH_REG_CPUP_CONF 0x0024 /* CPU Port Configuration */ +#define SWITCH_REG_PORT_CONF0 0x0028 /* Port Configuration 0 */ +#define SWITCH_REG_PORT_CONF1 0x002C /* Port Configuration 1 */ +#define SWITCH_REG_PORT_CONF2 0x0030 /* Port Configuration 2 */ +#define SWITCH_REG_VLAN_G1 0x0040 /* VLAN group 1 */ +#define SWITCH_REG_VLAN_G2 0x0044 /* VLAN group 2 */ +#define SWITCH_REG_SEND_TRIG 0x0048 /* Send Trigger */ +#define SWITCH_REG_MAC_WT0 0x0058 /* MAC Write Address 0 */ +#define SWITCH_REG_MAC_WT1 0x005C /* MAC Write Address 1 */ +#define SWITCH_REG_BW_CNTL0 0x0060 /* Bandwidth Control 0 */ +#define SWITCH_REG_BW_CNTL1 0x0064 /* Bandwidth Control 1 */ +#define SWITCH_REG_PHY_CNTL0 0x0068 /* PHY Control 0 */ +#define SWITCH_REG_PHY_CNTL1 0x006C /* PHY Control 1 */ +#define SWITCH_REG_PORT_TH 0x0078 /* Port Threshold */ +#define SWITCH_REG_PHY_CNTL2 0x007C /* PHY Control 2 */ +#define SWITCH_REG_PHY_CNTL3 0x0080 /* PHY Control 3 */ +#define SWITCH_REG_PRI_CNTL 0x0084 /* Priority Control */ +#define SWITCH_REG_PHY_CNTL4 0x00A0 /* PHY Control 4 */ +#define SWITCH_REG_EMPTY_CNT 0x00A4 /* Empty Count */ +#define SWITCH_REG_PORT_CNTLS 0x00A8 /* Port Control Select */ +#define SWITCH_REG_PORT_CNTL 0x00AC /* Port Control */ +#define SWITCH_REG_INT_STATUS 0x00B0 /* Interrupt Status */ +#define SWITCH_REG_INT_MASK 0x00B4 /* Interrupt Mask */ +#define SWITCH_REG_GPIO_CONF0 0x00B8 /* GPIO Configuration 0 */ +#define SWITCH_REG_GPIO_CONF2 0x00BC /* GPIO Configuration 1 */ +#define SWITCH_REG_WDOG0 0x00C0 /* Watchdog 0 */ +#define SWITCH_REG_WDOG1 0x00C4 /* Watchdog 1 */ + +#define SWITCH_REG_SHDA 0x00D0 /* Send High Descriptors Address */ +#define SWITCH_REG_SLDA 0x00D4 /* Send Low Descriptors Address */ +#define SWITCH_REG_RHDA 0x00D8 /* Receive High Descriptor Address */ +#define SWITCH_REG_RLDA 0x00DC /* Receive Low Descriptor Address */ +#define SWITCH_REG_SHWA 0x00E0 /* Send High Working Address */ +#define SWITCH_REG_SLWA 0x00E4 /* Send Low Working Address */ +#define SWITCH_REG_RHWA 0x00E8 /* Receive High Working Address */ +#define SWITCH_REG_RLWA 0x00EC /* Receive Low Working Address */ + +#define SWITCH_REG_TIMER_INT 0x00F0 /* Timer */ +#define SWITCH_REG_TIMER 0x00F4 /* Timer Interrupt */ + +#define SWITCH_REG_PORT0_LED 0x0100 +#define SWITCH_REG_PORT1_LED 0x0104 +#define SWITCH_REG_PORT2_LED 0x0108 +#define SWITCH_REG_PORT3_LED 0x010C +#define SWITCH_REG_PORT4_LED 0x0110 + +/* CODE register bits */ +#define CODE_PC_MASK BITMASK(16) /* Product Code */ +#define CODE_REV_SHIFT 16 +#define CODE_REV_MASK BITMASK(4) /* Product Revision */ +#define CODE_CLKS_SHIFT 20 +#define CODE_CLKS_MASK BITMASK(2) /* Clock Speed */ +#define CODE_CLKS_175 0 /* 175 MHz */ +#define CODE_CLKS_200 1 /* 200 MHz */ +#define CODE_CLKS_225 2 /* 225 MHz */ +#define CODE_CLKS_250 3 /* 250 MHz */ +#define CODE_NAB BIT(24) /* NAND boot */ +#define CODE_PK_MASK BITMASK(1) /* Package type */ +#define CODE_PK_SHIFT 29 +#define CODE_PK_BGA 0 /* BGA package */ +#define CODE_PK_PQFP 1 /* PQFP package */ + +/* MEMCTRL register bits */ +#define MEMCTRL_SDRS_MASK BITMASK(3) /* SDRAM bank size */ +#define MEMCTRL_SDRS_4M 0x01 +#define MEMCTRL_SDRS_8M 0x02 +#define MEMCTRL_SDRS_16M 0x03 +#define MEMCTRL_SDRS_64M 0x04 +#define MEMCTRL_SDRS_128M 0x05 +#define MEMCTRL_SDR1_ENABLE BIT(5) /* enable SDRAM bank 1 */ + +#define MEMCTRL_SRS0_SHIFT 8 /* shift for SRAM0 size */ +#define MEMCTRL_SRS1_SHIFT 16 /* shift for SRAM1 size */ +#define MEMCTRL_SRS_MASK BITMASK(3) /* SRAM size mask */ +#define MEMCTRL_SRS_DISABLED 0x00 /* Disabled */ +#define MEMCTRL_SRS_512K 0x01 /* 512KB*/ +#define MEMCTRL_SRS_1M 0x02 /* 1MB */ +#define MEMCTRL_SRS_2M 0x03 /* 2MB */ +#define MEMCTRL_SRS_4M 0x04 /* 4MB */ + +/* Port bits used in various registers */ +#define SWITCH_PORT_PHY0 BIT(0) +#define SWITCH_PORT_PHY1 BIT(1) +#define SWITCH_PORT_PHY2 BIT(2) +#define SWITCH_PORT_PHY3 BIT(3) +#define SWITCH_PORT_PHY4 BIT(4) +#define SWITCH_PORT_MII BIT(5) +#define SWITCH_PORT_CPU BIT(6) + +/* Port bit shorthands */ +#define SWITCH_PORTS_PHY 0x1F /* phy ports */ +#define SWITCH_PORTS_NOCPU 0x3F /* physical ports */ +#define SWITCH_PORTS_ALL 0x7F /* all ports */ + +/* CPUP_CONF register bits */ +#define CPUP_CONF_DCPUP BIT(0) /* Disable CPU port */ +#define CPUP_CONF_CRCP BIT(1) /* CRC padding from CPU */ +#define CPUP_CONF_BTM BIT(2) /* Bridge Testing Mode */ +#define CPUP_CONF_DUNP_SHIFT 9 /* Disable Unknown Packets for portX */ +#define CPUP_CONF_DMCP_SHIFT 16 /* Disable Mcast Packets form portX */ +#define CPUP_CONF_DBCP_SHIFT 24 /* Disable Bcast Packets form portX */ + +/* PORT_CONF0 register bits */ +#define PORT_CONF0_DP_SHIFT 0 /* Disable Port */ +#define PORT_CONF0_EMCP_SHIFT 8 /* Enable All MC Packets */ +#define PORT_CONF0_BP_SHIFT 16 /* Enable Back Pressure */ + +/* PORT_CONF1 register bits */ +#define PORT_CONF1_DISL_SHIFT 0 /* Disable Learning */ +#define PORT_CONF1_BS_SHIFT 6 /* Blocking State */ +#define PORT_CONF1_BM_SHIFT 12 /* Blocking Mode */ + +/* SEND_TRIG register bits */ +#define SEND_TRIG_STL BIT(0) /* Send Trigger Low */ +#define SEND_TRIG_STH BIT(1) /* Send Trigger High */ + +/* MAC_WT0 register bits */ +#define MAC_WT0_MAWC BIT(0) /* MAC address write command */ +#define MAC_WT0_MWD_SHIFT 1 +#define MAC_WT0_MWD BIT(1) /* MAC write done */ +#define MAC_WT0_WFB BIT(2) /* Write Filter Bit */ +#define MAC_WT0_WVN_SHIFT 3 /* Write Vlan Number shift */ +#define MAC_WT0_WVE BIT(6) /* Write VLAN enable */ +#define MAC_WT0_WPMN_SHIFT 7 +#define MAC_WT0_WAF_SHIFT 13 /* Write Age Field shift */ +#define MAC_WT0_WAF_EMPTY 0 +#define MAC_WT0_WAF_STATIC 7 /* age: static */ +#define MAC_WT0_MAC0_SHIFT 16 +#define MAC_WT0_MAC1_SHIFT 24 + +/* MAC_WT1 register bits */ +#define MAC_WT1_MAC2_SHIFT 0 +#define MAC_WT1_MAC3_SHIFT 8 +#define MAC_WT1_MAC4_SHIFT 16 +#define MAC_WT1_MAC5_SHIFT 24 + +/* BW_CNTL0/BW_CNTL1 register bits */ +#define BW_CNTL_DISABLE 0x00 +#define BW_CNTL_64K 0x01 +#define BW_CNTL_128K 0x02 +#define BW_CNTL_256K 0x03 +#define BW_CNTL_512K 0x04 +#define BW_CNTL_1M 0x05 +#define BW_CNTL_4M 0x06 +#define BW_CNTL_10M 0x07 + +#define P4TBC_SHIFT 0 +#define P4RBC_SHIFT 4 +#define P5TBC_SHIFT 8 +#define P5RBC_SHIFT 12 + +#define BW_CNTL1_NAND_ENABLE 0x100 + +/* PHY_CNTL0 register bits */ +#define PHY_CNTL0_PHYA_MASK BITMASK(5) +#define PHY_CNTL0_PHYR_MASK BITMASK(5) +#define PHY_CNTL0_PHYR_SHIFT 8 +#define PHY_CNTL0_WC BIT(13) /* Write Command */ +#define PHY_CNTL0_RC BIT(14) /* Read Command */ +#define PHY_CNTL0_WTD_MASK BIT(16) /* Read Command */ +#define PHY_CNTL0_WTD_SHIFT 16 + +/* PHY_CNTL1 register bits */ +#define PHY_CNTL1_WOD BIT(0) /* Write Operation Done */ +#define PHY_CNTL1_ROD BIT(1) /* Read Operation Done */ +#define PHY_CNTL1_RD_MASK BITMASK(16) +#define PHY_CNTL1_RD_SHIFT 16 + +/* PHY_CNTL2 register bits */ +#define PHY_CNTL2_ANE_SHIFT 0 /* Auto Negotiation Enable */ +#define PHY_CNTL2_SC_SHIFT 5 /* Speed Control */ +#define PHY_CNTL2_DC_SHIFT 10 /* Duplex Control */ +#define PHY_CNTL2_FNCV_SHIFT 15 /* Recommended FC Value */ +#define PHY_CNTL2_PHYR_SHIFT 20 /* PHY reset */ +#define PHY_CNTL2_AMDIX_SHIFT 25 /* Auto MDIX enable */ +/* PHY_CNTL2_RMAE is bad in datasheet */ +#define PHY_CNTL2_RMAE BIT(31) /* Recommended MCC Average enable */ + +/* PHY_CNTL3 register bits */ +#define PHY_CNTL3_RNT BIT(10) /* Recommend Normal Threshold */ + +/* PORT_TH register bits */ +#define PORT_TH_PPT_MASK BITMASK(8) /* Per Port Threshold */ +#define PORT_TH_CPUT_SHIFT 8 /* CPU Port Buffer Threshold */ +#define PORT_TH_CPUT_MASK BITMASK(8) +#define PORT_TH_CPUHT_SHIFT 16 /* CPU Hold Threshold */ +#define PORT_TH_CPUHT_MASK BITMASK(8) +#define PORT_TH_CPURT_SHIFT 24 /* CPU Release Threshold */ +#define PORT_TH_CPURT_MASK BITMASK(8) + +/* EMPTY_CNT register bits */ +#define EMPTY_CNT_EBGB_MASK BITMASK(9) /* Empty Blocks in the Global Buffer */ + +/* GPIO_CONF0 register bits */ +#define GPIO_CONF0_MASK BITMASK(8) +#define GPIO_CONF0_IM_SHIFT 0 +#define GPIO_CONF0_IV_SHIFT 8 +#define GPIO_CONF0_OE_SHIFT 16 +#define GPIO_CONF0_OV_SHIFT 24 +#define GPIO_CONF0_IM_MASK (0xFF << GPIO_CONF0_IM_SHIFT) +#define GPIO_CONF0_IV_MASK (0xFF << GPIO_CONF0_IV_SHIFT) +#define GPIO_CONF0_OE_MASK (0xFF << GPIO_CONF0_OE_SHIFT) +#define GPIO_CONF0_OV_MASK (0xFF << GPIO_CONF0_OV_SHIFT) + +/* GPIO_CONF2 register bits */ +#define GPIO_CONF2_CSX0 BIT(4) /* enable CSX0:INTX0 on GPIO 1:2 */ +#define GPIO_CONF2_CSX1 BIT(5) /* enable CSX1:INTX1 on GPIO 3:4 */ +#define GPIO_CONF2_EW BIT(6) /* enable wait state pin for CSX0/1 */ + +/* INT_STATUS/INT_MASK register bits */ +#define SWITCH_INT_SHD BIT(0) /* Send High Done */ +#define SWITCH_INT_SLD BIT(1) /* Send Low Done */ +#define SWITCH_INT_RHD BIT(2) /* Receive High Done */ +#define SWITCH_INT_RLD BIT(3) /* Receive Low Done */ +#define SWITCH_INT_HDF BIT(4) /* High Descriptor Full */ +#define SWITCH_INT_LDF BIT(5) /* Low Descriptor Full */ +#define SWITCH_INT_P0QF BIT(6) /* Port0 Queue Full */ +#define SWITCH_INT_P1QF BIT(7) /* Port1 Queue Full */ +#define SWITCH_INT_P2QF BIT(8) /* Port2 Queue Full */ +#define SWITCH_INT_P3QF BIT(9) /* Port3 Queue Full */ +#define SWITCH_INT_P4QF BIT(10) /* Port4 Queue Full */ +#define SWITCH_INT_P5QF BIT(11) /* Port5 Queue Full */ +#define SWITCH_INT_CPQF BIT(13) /* CPU Queue Full */ +#define SWITCH_INT_GQF BIT(14) /* Global Queue Full */ +#define SWITCH_INT_MD BIT(15) /* Must Drop */ +#define SWITCH_INT_BCS BIT(16) /* BC Storm */ +#define SWITCH_INT_PSC BIT(18) /* Port Status Change */ +#define SWITCH_INT_ID BIT(19) /* Intruder Detected */ +#define SWITCH_INT_W0TE BIT(20) /* Watchdog 0 Timer Expired */ +#define SWITCH_INT_W1TE BIT(21) /* Watchdog 1 Timer Expired */ +#define SWITCH_INT_RDE BIT(22) /* Receive Descriptor Error */ +#define SWITCH_INT_SDE BIT(23) /* Send Descriptor Error */ +#define SWITCH_INT_CPUH BIT(24) /* CPU Hold */ + +/* TIMER_INT register bits */ +#define TIMER_INT_TOS BIT(0) /* time-out status */ +#define TIMER_INT_TOM BIT(16) /* mask time-out interrupt */ + +/* TIMER register bits */ +#define TIMER_PERIOD_MASK BITMASK(16) /* mask for timer period */ +#define TIMER_PERIOD_DEFAULT 0xFFFF /* default timer period */ +#define TIMER_TE BIT(16) /* timer enable bit */ + +/* PORTx_LED register bits */ +#define LED_MODE_MASK BITMASK(4) +#define LED_MODE_INPUT 0 +#define LED_MODE_FLASH 1 +#define LED_MODE_OUT_HIGH 2 +#define LED_MODE_OUT_LOW 3 +#define LED_MODE_LINK 4 +#define LED_MODE_SPEED 5 +#define LED_MODE_DUPLEX 6 +#define LED_MODE_ACT 7 +#define LED_MODE_COLL 8 +#define LED_MODE_LINK_ACT 9 +#define LED_MODE_DUPLEX_COLL 10 +#define LED_MODE_10M_ACT 11 +#define LED_MODE_100M_ACT 12 +#define LED0_MODE_SHIFT 0 /* LED0 mode shift */ +#define LED1_MODE_SHIFT 4 /* LED1 mode shift */ +#define LED2_MODE_SHIFT 8 /* LED2 mode shift */ +#define LED0_IV_SHIFT 12 /* LED0 input value shift */ +#define LED1_IV_SHIFT 13 /* LED1 input value shift */ +#define LED2_IV_SHIFT 14 /* LED2 input value shift */ + +#endif /* _MACH_ADM5120_SWITCH_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_uart.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_uart.h new file mode 100644 index 0000000000..81d3067da3 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/adm5120_uart.h @@ -0,0 +1,64 @@ +/* + * ADM5120 UART definitions + * + * This header file defines the hardware registers of the ADM5120 SoC + * built-in UARTs. + * + * Copyright (C) 2007 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MACH_ADM5120_UART_H +#define _MACH_ADM5120_UART_H + +#define UART_BAUDDIV(clk, baud) ((clk/(16 * (baud)))-1) + +#define UART_REG_DATA 0x00 +#define UART_REG_RSR 0x04 +#define UART_REG_ECR UART_REG_RSR +#define UART_REG_LCRH 0x08 +#define UART_REG_LCRM 0x0C +#define UART_REG_LCRL 0x10 +#define UART_REG_CTRL 0x14 +#define UART_REG_FLAG 0x18 + +/* Receive Status Register bits */ +#define UART_RSR_FE (1 << 0) +#define UART_RSR_PE (1 << 1) +#define UART_RSR_BE (1 << 2) +#define UART_RSR_OE (1 << 3) +#define UART_RSR_ERR (UART_RSR_FE | UART_RSR_PE | UART_RSR_BE) + +#define UART_ECR_ALL 0xFF + +/* Line Control High register bits */ +#define UART_LCRH_BRK (1 << 0) /* send break */ +#define UART_LCRH_PEN (1 << 1) /* parity enable */ +#define UART_LCRH_EPS (1 << 2) /* even parity select */ +#define UART_LCRH_STP1 (0 << 3) /* one stop bits select */ +#define UART_LCRH_STP2 (1 << 3) /* two stop bits select */ +#define UART_LCRH_FEN (1 << 4) /* FIFO enable */ + +#define UART_LCRH_WLEN5 (0 << 5) +#define UART_LCRH_WLEN6 (1 << 5) +#define UART_LCRH_WLEN7 (2 << 5) +#define UART_LCRH_WLEN8 (3 << 5) + +/* Control register bits */ +#define UART_CTRL_EN (1 << 0) + +/* Flag register bits */ +#define UART_FLAG_CTS (1 << 0) +#define UART_FLAG_DSR (1 << 1) +#define UART_FLAG_DCD (1 << 2) +#define UART_FLAG_BUSY (1 << 3) +#define UART_FLAG_RXFE (1 << 4) +#define UART_FLAG_TXFF (1 << 5) +#define UART_FLAG_RXFF (1 << 6) +#define UART_FLAG_TXFE (1 << 7) + +#endif /* _MACH_ADM5120_UART_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/asm/sizes.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/asm/sizes.h new file mode 100644 index 0000000000..503843db15 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/asm/sizes.h @@ -0,0 +1,56 @@ +/* + * 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 + */ +/* DO NOT EDIT!! - this file automatically generated + * from .s file by awk -f s2h.awk + */ +/* Size definitions + * Copyright (C) ARM Limited 1998. All rights reserved. + */ + +#ifndef __sizes_h +#define __sizes_h 1 + +/* handy sizes */ +#define SZ_16 0x00000010 +#define SZ_256 0x00000100 +#define SZ_512 0x00000200 + +#define SZ_1K 0x00000400 +#define SZ_4K 0x00001000 +#define SZ_8K 0x00002000 +#define SZ_16K 0x00004000 +#define SZ_64K 0x00010000 +#define SZ_128K 0x00020000 +#define SZ_256K 0x00040000 +#define SZ_512K 0x00080000 + +#define SZ_1M 0x00100000 +#define SZ_2M 0x00200000 +#define SZ_4M 0x00400000 +#define SZ_8M 0x00800000 +#define SZ_16M 0x01000000 +#define SZ_32M 0x02000000 +#define SZ_64M 0x04000000 +#define SZ_128M 0x08000000 +#define SZ_256M 0x10000000 +#define SZ_512M 0x20000000 + +#define SZ_1G 0x40000000 +#define SZ_2G 0x80000000 + +#endif + +/* END */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h new file mode 100644 index 0000000000..c6310cc6e6 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h @@ -0,0 +1,71 @@ +/* + * ADM5120 specific CPU feature overrides + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: include/asm-mips/cpu-features.h + * Copyright (C) 2003, 2004 Ralf Baechle + * Copyright (C) 2004 Maciej W. Rozycki + * + * 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_ADM5120_CPU_FEATURE_OVERRIDES_H +#define __ASM_MACH_ADM5120_CPU_FEATURE_OVERRIDES_H + +/* + * The ADM5120 SOC has a built-in MIPS 4Kc core. + */ +#define cpu_has_tlb 1 +#define cpu_has_4kex 1 +#define cpu_has_3k_cache 0 +#define cpu_has_4k_cache 1 +#define cpu_has_tx39_cache 0 +#define cpu_has_sb1_cache 0 +#define cpu_has_fpu 0 +#define cpu_has_32fpr 0 +#define cpu_has_counter 1 +#define cpu_has_watch 1 +#define cpu_has_divec 1 +/* #define cpu_has_vce ? */ +/* #define cpu_has_cache_cdex_p ? */ +/* #define cpu_has_cache_cdex_s ? */ +#define cpu_has_prefetch 1 +/* #define cpu_has_mcheck ? */ +#define cpu_has_ejtag 1 +#define cpu_has_llsc 1 + +#define cpu_has_mips16 0 +#define cpu_has_mdmx 0 +#define cpu_has_mips3d 0 +#define cpu_has_smartmips 0 + +/* #define cpu_has_vtag_icache ? */ +/* #define cpu_has_dc_aliases ? */ +/* #define cpu_has_ic_fills_f_dc ? */ +/* #define cpu_has_pindexed_dcache ? */ + +/* #define cpu_icache_snoops_remote_store ? */ + +#define cpu_has_mips32r1 1 +#define cpu_has_mips32r2 0 +#define cpu_has_mips64r1 0 +#define cpu_has_mips64r2 0 + +#define cpu_has_dsp 0 +#define cpu_has_mipsmt 0 + +/* #define cpu_has_nofpuex ? */ +#define cpu_has_64bits 0 +#define cpu_has_64bit_zero_reg 0 +#define cpu_has_64bit_gp_regs 0 +#define cpu_has_64bit_addresses 0 + +/* #define cpu_has_inclusive_pcaches ? */ + +#define cpu_dcache_line_size() 16 +#define cpu_icache_line_size() 16 + +#endif /* __ASM_MACH_ADM5120_CPU_FEATURE_OVERRIDES_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/gpio.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/gpio.h new file mode 100644 index 0000000000..7ba7efca1f --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/gpio.h @@ -0,0 +1,115 @@ +/* + * ADM5120 GPIO wrappers for arch-neutral GPIO calls + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _ASM_MIPS_MACH_ADM5120_GPIO_H +#define _ASM_MIPS_MACH_ADM5120_GPIO_H + +#define ARCH_NR_GPIOS 64 + +#include + +#include + +#define ADM5120_GPIO_PIN0 0 +#define ADM5120_GPIO_PIN1 1 +#define ADM5120_GPIO_PIN2 2 +#define ADM5120_GPIO_PIN3 3 +#define ADM5120_GPIO_PIN4 4 +#define ADM5120_GPIO_PIN5 5 +#define ADM5120_GPIO_PIN6 6 +#define ADM5120_GPIO_PIN7 7 +#define ADM5120_GPIO_P0L0 8 +#define ADM5120_GPIO_P0L1 9 +#define ADM5120_GPIO_P0L2 10 +#define ADM5120_GPIO_P1L0 11 +#define ADM5120_GPIO_P1L1 12 +#define ADM5120_GPIO_P1L2 13 +#define ADM5120_GPIO_P2L0 14 +#define ADM5120_GPIO_P2L1 15 +#define ADM5120_GPIO_P2L2 16 +#define ADM5120_GPIO_P3L0 17 +#define ADM5120_GPIO_P3L1 18 +#define ADM5120_GPIO_P3L2 19 +#define ADM5120_GPIO_P4L0 20 +#define ADM5120_GPIO_P4L1 21 +#define ADM5120_GPIO_P4L2 22 +#define ADM5120_GPIO_MAX 22 +#define ADM5120_GPIO_COUNT ADM5120_GPIO_MAX+1 + +#define ADM5120_GPIO_LOW 0 +#define ADM5120_GPIO_HIGH 1 + +#define ADM5120_GPIO_SWITCH 0x10 +#define ADM5120_GPIO_FLASH (ADM5120_GPIO_SWITCH | LED_MODE_FLASH) +#define ADM5120_GPIO_LINK (ADM5120_GPIO_SWITCH | LED_MODE_LINK) +#define ADM5120_GPIO_SPEED (ADM5120_GPIO_SWITCH | LED_MODE_SPEED) +#define ADM5120_GPIO_DUPLEX (ADM5120_GPIO_SWITCH | LED_MODE_DUPLEX) +#define ADM5120_GPIO_ACT (ADM5120_GPIO_SWITCH | LED_MODE_ACT) +#define ADM5120_GPIO_COLL (ADM5120_GPIO_SWITCH | LED_MODE_COLL) +#define ADM5120_GPIO_LINK_ACT (ADM5120_GPIO_SWITCH | LED_MODE_LINK_ACT) +#define ADM5120_GPIO_DUPLEX_COLL (ADM5120_GPIO_SWITCH | LED_MODE_DUPLEX_COLL) +#define ADM5120_GPIO_10M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_10M_ACT) +#define ADM5120_GPIO_100M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_100M_ACT) + +extern int __adm5120_gpio0_get_value(unsigned gpio); +extern void __adm5120_gpio0_set_value(unsigned gpio, int value); +extern int __adm5120_gpio1_get_value(unsigned gpio); +extern void __adm5120_gpio1_set_value(unsigned gpio, int value); +extern int adm5120_gpio_to_irq(unsigned gpio); +extern int adm5120_irq_to_gpio(unsigned irq); + +static inline int gpio_get_value(unsigned gpio) +{ + int ret; + + switch (gpio) { + case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: + ret = __adm5120_gpio0_get_value(gpio); + break; + case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: + ret = __adm5120_gpio1_get_value(gpio - ADM5120_GPIO_P0L0); + break; + default: + ret = __gpio_get_value(gpio); + break; + } + + return ret; +} + +static inline void gpio_set_value(unsigned gpio, int value) +{ + switch (gpio) { + case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: + __adm5120_gpio0_set_value(gpio, value); + break; + case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: + __adm5120_gpio1_set_value(gpio - ADM5120_GPIO_P0L0, value); + break; + default: + __gpio_set_value(gpio, value); + break; + } +} + +static inline int gpio_to_irq(unsigned gpio) +{ + return adm5120_gpio_to_irq(gpio); +} + +static inline int irq_to_gpio(unsigned irq) +{ + return adm5120_irq_to_gpio(irq); +} + +#define gpio_cansleep __gpio_cansleep + +#endif /* _ASM_MIPS_MACH_ADM5120_GPIO_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/irq.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/irq.h new file mode 100644 index 0000000000..b0350c8b83 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/irq.h @@ -0,0 +1,43 @@ +/* + * ADM5120 specific IRQ numbers + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ +#ifndef _ASM_MIPS_MACH_ADM5120_IRQ_H +#define _ASM_MIPS_MACH_ADM5120_IRQ_H + +#define MIPS_CPU_IRQ_BASE 0 +#define NR_IRQS 24 + +#include_next + +#include + +#define NO_IRQ (-1) + +#define MIPS_CPU_IRQ_COUNT 8 +#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x)) + +#define ADM5120_INTC_IRQ_BASE (MIPS_CPU_IRQ_BASE + MIPS_CPU_IRQ_COUNT) +#define ADM5120_INTC_IRQ(x) (ADM5120_INTC_IRQ_BASE + (x)) + +#define ADM5120_IRQ_INTC MIPS_CPU_IRQ(2) +#define ADM5120_IRQ_COUNTER MIPS_CPU_IRQ(7) + +#define ADM5120_IRQ_TIMER ADM5120_INTC_IRQ(INTC_IRQ_TIMER) +#define ADM5120_IRQ_UART0 ADM5120_INTC_IRQ(INTC_IRQ_UART0) +#define ADM5120_IRQ_UART1 ADM5120_INTC_IRQ(INTC_IRQ_UART1) +#define ADM5120_IRQ_USBC ADM5120_INTC_IRQ(INTC_IRQ_USBC) +#define ADM5120_IRQ_GPIO2 ADM5120_INTC_IRQ(INTC_IRQ_GPIO2) +#define ADM5120_IRQ_GPIO4 ADM5120_INTC_IRQ(INTC_IRQ_GPIO4) +#define ADM5120_IRQ_PCI0 ADM5120_INTC_IRQ(INTC_IRQ_PCI0) +#define ADM5120_IRQ_PCI1 ADM5120_INTC_IRQ(INTC_IRQ_PCI1) +#define ADM5120_IRQ_PCI2 ADM5120_INTC_IRQ(INTC_IRQ_PCI2) +#define ADM5120_IRQ_SWITCH ADM5120_INTC_IRQ(INTC_IRQ_SWITCH) + +#endif /* _ASM_MIPS_MACH_ADM5120_IRQ_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/admboot.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/admboot.h new file mode 100644 index 0000000000..fa42bf7148 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/admboot.h @@ -0,0 +1,17 @@ +/* + * ADMBoot specific definitions + * + * Copyright (C) 2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _ADMBOOT_H +#define _ADMBOOT_H + +extern int admboot_get_mac_base(u32 offset, u32 len, u8 *mac) __init; + +#endif /* _ADMBOOT_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/cfe.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/cfe.h new file mode 100644 index 0000000000..0cb3eee70e --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/cfe.h @@ -0,0 +1,18 @@ +/* + * Broadcom's CFE definitions + * + * Copyright (C) 2006-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _PROM_CFE_H_ +#define _PROM_CFE_H_ + +extern int cfe_present(void) __init; +extern char *cfe_getenv(char *); + +#endif /*_PROM_CFE_H_*/ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/generic.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/generic.h new file mode 100644 index 0000000000..778df24677 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/generic.h @@ -0,0 +1,18 @@ +/* + * Generic prom definitions + * + * Copyright (C) 2006-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _PROM_GENERIC_H_ +#define _PROM_GENERIC_H_ + +extern int generic_prom_present(void) __init; +extern char *generic_prom_getenv(char *); + +#endif /*_PROM_GENERIC_H_*/ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/myloader.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/myloader.h new file mode 100644 index 0000000000..ea8db81ed3 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/myloader.h @@ -0,0 +1,179 @@ +/* + * Compex's MyLoader specific definitions + * + * Copyright (C) 2006-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _MYLOADER_H_ +#define _MYLOADER_H_ + +/* + * Firmware file format: + * + *
+ * [] + * ... + * [] + * + * [] + * ... + * [] + * + * + */ + +/* Myloader specific magic numbers */ +#define MYLO_MAGIC_FIRMWARE 0x4C594D00 +#define MYLO_MAGIC_20021103 0x20021103 +#define MYLO_MAGIC_20021107 0x20021107 + +#define MYLO_MAGIC_SYS_PARAMS MYLO_MAGIC_20021107 +#define MYLO_MAGIC_PARTITIONS MYLO_MAGIC_20021103 +#define MYLO_MAGIC_BOARD_PARAMS MYLO_MAGIC_20021103 + +/* + * Addresses of the data structures provided by MyLoader + */ +#define MYLO_MIPS_SYS_PARAMS 0x80000800 /* System Parameters */ +#define MYLO_MIPS_BOARD_PARAMS 0x80000A00 /* Board Parameters */ +#define MYLO_MIPS_PARTITIONS 0x80000C00 /* Partition Table */ +#define MYLO_MIPS_BOOT_PARAMS 0x80000E00 /* Boot Parameters */ + +/* Vendor ID's (seems to be same as the PCI vendor ID's) */ +#define VENID_COMPEX 0x11F6 + +/* Devices based on the ADM5120 */ +#define DEVID_COMPEX_NP27G 0x0078 +#define DEVID_COMPEX_NP28G 0x044C +#define DEVID_COMPEX_NP28GHS 0x044E +#define DEVID_COMPEX_WP54Gv1C 0x0514 +#define DEVID_COMPEX_WP54G 0x0515 +#define DEVID_COMPEX_WP54AG 0x0546 +#define DEVID_COMPEX_WPP54AG 0x0550 +#define DEVID_COMPEX_WPP54G 0x0555 + +/* Devices based on the IXP422 */ +#define DEVID_COMPEX_WP18 0x047E +#define DEVID_COMPEX_NP18A 0x0489 + +/* Other devices */ +#define DEVID_COMPEX_NP26G8M 0x03E8 +#define DEVID_COMPEX_NP26G16M 0x03E9 + +struct mylo_fw_header { + uint32_t magic; /* must be MYLO_MAGIC_FIRMWARE */ + uint32_t crc; /* CRC of the whole firmware */ + uint32_t res0; /* unknown/unused */ + uint32_t res1; /* unknown/unused */ + uint16_t vid; /* vendor ID */ + uint16_t did; /* device ID */ + uint16_t svid; /* sub vendor ID */ + uint16_t sdid; /* sub device ID */ + uint32_t rev; /* device revision */ + uint32_t fwhi; /* FIXME: firmware version high? */ + uint32_t fwlo; /* FIXME: firmware version low? */ + uint32_t flags; /* firmware flags */ +}; + +#define FW_FLAG_BOARD_PARAMS_WP 0x01 /* board parameters are write protected */ +#define FW_FLAG_BOOT_SECTOR_WE 0x02 /* enable of write boot sectors (below 64K) */ + +struct mylo_fw_blockdesc { + uint32_t type; /* block type */ + uint32_t addr; /* relative address to flash start */ + uint32_t dlen; /* size of block data in bytes */ + uint32_t blen; /* total size of block in bytes */ +}; + +#define FW_DESC_TYPE_UNUSED 0 +#define FW_DESC_TYPE_USED 1 + +struct mylo_partition { + uint16_t flags; /* partition flags */ + uint16_t type; /* type of the partition */ + uint32_t addr; /* relative address of the partition from the + flash start */ + uint32_t size; /* size of the partition in bytes */ + uint32_t param; /* if this is the active partition, the + MyLoader load code to this address */ +}; + +#define PARTITION_FLAG_ACTIVE 0x8000 /* this is the active partition, + * MyLoader loads firmware from here */ +#define PARTITION_FLAG_ISRAM 0x2000 /* FIXME: this is a RAM partition? */ +#define PARTIIION_FLAG_RAMLOAD 0x1000 /* FIXME: load this partition into the RAM? */ +#define PARTITION_FLAG_PRELOAD 0x0800 /* the partition data preloaded to RAM + * before decompression */ +#define PARTITION_FLAG_HAVEHDR 0x0002 /* the partition data have a header */ + +#define PARTITION_TYPE_FREE 0 +#define PARTITION_TYPE_USED 1 + +#define MYLO_MAX_PARTITIONS 8 /* maximum number of partitions in the + partition table */ + +struct mylo_partition_table { + uint32_t magic; /* must be MYLO_MAGIC_PARTITIONS */ + uint32_t res0; /* unknown/unused */ + uint32_t res1; /* unknown/unused */ + uint32_t res2; /* unknown/unused */ + struct mylo_partition partitions[MYLO_MAX_PARTITIONS]; +}; + +struct mylo_partition_header { + uint32_t len; /* length of the partition data */ + uint32_t crc; /* CRC value of the partition data */ +}; + +struct mylo_system_params { + uint32_t magic; /* must be MYLO_MAGIC_SYS_PARAMS */ + uint32_t res0; + uint32_t res1; + uint32_t mylo_ver; + uint16_t vid; /* Vendor ID */ + uint16_t did; /* Device ID */ + uint16_t svid; /* Sub Vendor ID */ + uint16_t sdid; /* Sub Device ID */ + uint32_t rev; /* device revision */ + uint32_t fwhi; + uint32_t fwlo; + uint32_t tftp_addr; + uint32_t prog_start; + uint32_t flash_size; /* Size of boot FLASH in bytes */ + uint32_t dram_size; /* Size of onboard RAM in bytes */ +}; + + +struct mylo_eth_addr { + uint8_t mac[6]; + uint8_t csum[2]; +}; + +#define MYLO_ETHADDR_COUNT 8 /* maximum number of ethernet address + in the board parameters */ + +struct mylo_board_params { + uint32_t magic; /* must be MYLO_MAGIC_BOARD_PARAMS */ + uint32_t res0; + uint32_t res1; + uint32_t res2; + struct mylo_eth_addr addr[MYLO_ETHADDR_COUNT]; +}; + +struct myloader_info { + u32 vid; + u32 did; + u32 svid; + u32 sdid; + uint8_t macs[MYLO_ETHADDR_COUNT][6]; +}; + +extern struct myloader_info myloader_info; +extern int myloader_present(void) __init; + +#endif /* _MYLOADER_H_*/ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/routerboot.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/routerboot.h new file mode 100644 index 0000000000..91ac05a630 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/routerboot.h @@ -0,0 +1,36 @@ +/* + * Mikrotik's RouterBOOT definitions + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _PROM_ROUTERBOOT_H_ +#define _PROM_ROUTERBOOT_H_ + +struct rb_bios_settings { + u32 hs_offs; /* hard settings offset */ + u32 hs_size; /* hard settings size */ + u32 fw_offs; /* firmware offset */ + u32 ss_offs; /* soft settings offset */ + u32 ss_size; /* soft settings size */ +}; + +struct rb_hard_settings { + char *name; /* board name */ + char *bios_ver; /* BIOS version */ + u32 mem_size; /* memory size in bytes */ + u32 mac_count; /* number of mac addresses */ + u8 *mac_base; /* mac address base */ +}; + +extern int routerboot_present(void) __init; +extern char *routerboot_get_boardname(void); + +extern struct rb_hard_settings rb_hs; + +#endif /* _PROM_ROUTERBOOT_H_ */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/zynos.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/zynos.h new file mode 100644 index 0000000000..d1e3e5b941 --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/prom/zynos.h @@ -0,0 +1,86 @@ +/* + * ZyNOS (ZyXEL's Networking OS) definitions + * + * Copyright (C) 2007-2008 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 + * by the Free Software Foundation. + * + */ + +#ifndef _ZYNOS_H +#define _ZYNOS_H + +#define ZYNOS_NAME_LEN 32 +#define ZYNOS_FEAT_BYTES 22 +#define ZYNOS_MAC_LEN 6 + +struct zynos_board_info { + unsigned char vendor[ZYNOS_NAME_LEN]; + unsigned char product[ZYNOS_NAME_LEN]; + u32 bootext_addr; + u32 res0; + u16 board_id; + u8 res1[6]; + u8 feat_other[ZYNOS_FEAT_BYTES]; + u8 feat_main; + u8 res2; + u8 mac[ZYNOS_MAC_LEN]; + u8 country; + u8 dbgflag; +} __attribute__ ((packed)); + +/* + * Vendor IDs + */ +#define ZYNOS_VENDOR_ID_ZYXEL 0 +#define ZYNOS_VENDOR_ID_NETGEAR 1 +#define ZYNOS_VENDOR_ID_DLINK 2 +#define ZYNOS_VENDOR_ID_OTHER 3 +#define ZYNOS_VENDOR_ID_LUCENT 4 + +/* + * Vendor names + */ +#define ZYNOS_VENDOR_DLINK "D-Link" +#define ZYNOS_VENDOR_LUCENT "LUCENT" +#define ZYNOS_VENDOR_NETGEAR "NetGear" +#define ZYNOS_VENDOR_ZYXEL "ZyXEL" + +/* + * Board IDs (big-endian) + */ +#define ZYNOS_BOARD_ES2108 0x00F2 /* Ethernet Switch 2108 */ +#define ZYNOS_BOARD_ES2108F 0x01AF /* Ethernet Switch 2108-F */ +#define ZYNOS_BOARD_ES2108G 0x00F3 /* Ethernet Switch 2108-G */ +#define ZYNOS_BOARD_ES2108LC 0x00FC /* Ethernet Switch 2108-LC */ +#define ZYNOS_BOARD_ES2108PWR 0x00F4 /* Ethernet Switch 2108PWR */ +#define ZYNOS_BOARD_HS100 0x9FF1 /* HomeSafe 100/100W */ +#define ZYNOS_BOARD_P334 0x9FF5 /* Prestige 334 */ +#define ZYNOS_BOARD_P334U 0x9FDD /* Prestige 334U */ +#define ZYNOS_BOARD_P334W 0x9FF3 /* Prestige 334W */ +#define ZYNOS_BOARD_P334WH 0x00E0 /* Prestige 334WH */ +#define ZYNOS_BOARD_P334WHD 0x00E1 /* Prestige 334WHD */ +#define ZYNOS_BOARD_P334WT 0x9FEF /* Prestige 334WT */ +#define ZYNOS_BOARD_P334WT_ALT 0x9F02 /* Prestige 334WT alternative*/ +#define ZYNOS_BOARD_P335 0x9FED /* Prestige 335/335WT */ +#define ZYNOS_BOARD_P335PLUS 0x0025 /* Prestige 335Plus */ +#define ZYNOS_BOARD_P335U 0x9FDC /* Prestige 335U */ + +/* + * Some magic numbers (big-endian) + */ +#define ZYNOS_MAGIC_DBGAREA1 0x48646267 /* "Hdbg" */ +#define ZYNOS_MAGIC_DBGAREA2 0x61726561 /* "area" */ + +struct bootbase_info { + u16 vendor_id; + u16 board_id; + u8 mac[6]; +}; + +extern struct bootbase_info bootbase_info; +extern int bootbase_present(void) __init; + +#endif /* _ZYNOS_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/war.h b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/war.h new file mode 100644 index 0000000000..87c35f375b --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/include/asm/mach-adm5120/war.h @@ -0,0 +1,25 @@ +/* + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + * + * Copyright (C) 2002, 2004, 2007 by Ralf Baechle + */ +#ifndef __ASM_MIPS_MACH_ADM5120_WAR_H +#define __ASM_MIPS_MACH_ADM5120_WAR_H + +#define R4600_V1_INDEX_ICACHEOP_WAR 0 +#define R4600_V1_HIT_CACHEOP_WAR 0 +#define R4600_V2_HIT_CACHEOP_WAR 0 +#define R5432_CP0_INTERRUPT_WAR 0 +#define BCM1250_M3_WAR 0 +#define SIBYTE_1956_WAR 0 +#define MIPS4K_ICACHE_REFILL_WAR 0 +#define MIPS_CACHE_SYNC_WAR 0 +#define TX49XX_ICACHE_INDEX_INV_WAR 0 +#define RM9000_CDEX_SMP_WAR 0 +#define ICACHE_REFILLS_WORKAROUND_WAR 0 +#define R10000_LLSC_WAR 0 +#define MIPS34K_MISSED_ITLB_WAR 0 + +#endif /* __ASM_MIPS_MACH_ADM5120_WAR_H */ diff --git a/target/linux/adm5120/files-3.8/arch/mips/pci/pci-adm5120.c b/target/linux/adm5120/files-3.8/arch/mips/pci/pci-adm5120.c new file mode 100644 index 0000000000..f8d359806a --- /dev/null +++ b/target/linux/adm5120/files-3.8/arch/mips/pci/pci-adm5120.c @@ -0,0 +1,277 @@ +/* + * ADM5120 PCI Host Controller driver + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This code was based on the ADM5120 specific port of the Linux 2.6.10 kernel + * done by Jeroen Vreeken + * Copyright (C) 2005 Jeroen Vreeken (pe1rxq@amsat.org) + * + * Jeroen's code was based on the Linux 2.4.xx source codes found in various + * tarballs released by Edimax for it's ADM5120 based devices + * Copyright (C) ADMtek Incorporated + * + * 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 + +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(f, a...) printk(KERN_DEBUG f, ## a) +#else +#define DBG(f, a...) do {} while (0) +#endif + +#define PCI_ENABLE 0x80000000 + +/* -------------------------------------------------------------------------*/ + +static unsigned int adm5120_pci_nr_irqs __initdata; +static struct adm5120_pci_irq *adm5120_pci_irq_map __initdata; + +static DEFINE_SPINLOCK(pci_lock); + +/* -------------------------------------------------------------------------*/ + +static inline void write_cfgaddr(u32 addr) +{ + __raw_writel((addr | PCI_ENABLE), + (void __iomem *)(KSEG1ADDR(ADM5120_PCICFG_ADDR))); +} + +static inline void write_cfgdata(u32 data) +{ + __raw_writel(data, (void __iomem *)KSEG1ADDR(ADM5120_PCICFG_DATA)); +} + +static inline u32 read_cfgdata(void) +{ + return __raw_readl((void __iomem *)KSEG1ADDR(ADM5120_PCICFG_DATA)); +} + +static inline u32 mkaddr(struct pci_bus *bus, unsigned int devfn, int where) +{ + return ((bus->number & 0xFF) << 16) | ((devfn & 0xFF) << 8) | \ + (where & 0xFC); +} + +/* -------------------------------------------------------------------------*/ + +static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 *val) +{ + unsigned long flags; + u32 data; + + spin_lock_irqsave(&pci_lock, flags); + + write_cfgaddr(mkaddr(bus, devfn, where)); + data = read_cfgdata(); + + DBG("PCI: cfg_read %02u.%02u.%01u/%02X:%01d, cfg:0x%08X", + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), + where, size, data); + + switch (size) { + case 1: + if (where & 1) + data >>= 8; + if (where & 2) + data >>= 16; + data &= 0xFF; + break; + case 2: + if (where & 2) + data >>= 16; + data &= 0xFFFF; + break; + } + + *val = data; + DBG(", 0x%08X returned\n", data); + + spin_unlock_irqrestore(&pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, + int size, u32 val) +{ + unsigned long flags; + u32 data; + int s; + + spin_lock_irqsave(&pci_lock, flags); + + write_cfgaddr(mkaddr(bus, devfn, where)); + data = read_cfgdata(); + + DBG("PCI: cfg_write %02u.%02u.%01u/%02X:%01d, cfg:0x%08X", + bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), + where, size, data); + + switch (size) { + case 1: + s = ((where & 3) << 3); + data &= ~(0xFF << s); + data |= ((val & 0xFF) << s); + break; + case 2: + s = ((where & 2) << 4); + data &= ~(0xFFFF << s); + data |= ((val & 0xFFFF) << s); + break; + case 4: + data = val; + break; + } + + write_cfgdata(data); + DBG(", 0x%08X written\n", data); + + spin_unlock_irqrestore(&pci_lock, flags); + + return PCIBIOS_SUCCESSFUL; +} + +struct pci_ops adm5120_pci_ops = { + .read = pci_config_read, + .write = pci_config_write, +}; + +/* -------------------------------------------------------------------------*/ + +static void adm5120_pci_fixup(struct pci_dev *dev) +{ + if (dev->devfn != 0) + return; + + /* setup COMMAND register */ + pci_write_config_word(dev, PCI_COMMAND, + (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER)); + + /* setup CACHE_LINE_SIZE register */ + pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4); + + /* setup BARS */ + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0); + pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); +} + +DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_ADM5120, + adm5120_pci_fixup); + +/* -------------------------------------------------------------------------*/ + +void __init adm5120_pci_set_irq_map(unsigned int nr_irqs, + struct adm5120_pci_irq *map) +{ + adm5120_pci_nr_irqs = nr_irqs; + adm5120_pci_irq_map = map; +} + +int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +{ + int irq = -1; + int i; + + if ((!adm5120_pci_nr_irqs) || (!adm5120_pci_irq_map)) { + printk(KERN_ALERT "PCI: pci_irq_map is not initialized\n"); + goto out; + } + + if (slot < 1 || slot > 4) { + printk(KERN_ALERT "PCI: slot number %u is not supported\n", + slot); + goto out; + } + + for (i = 0; i < adm5120_pci_nr_irqs; i++) { + if ((adm5120_pci_irq_map[i].slot == slot) + && (adm5120_pci_irq_map[i].func == PCI_FUNC(dev->devfn)) + && (adm5120_pci_irq_map[i].pin == pin)) { + irq = adm5120_pci_irq_map[i].irq; + break; + } + } + + if (irq < 0) { + printk(KERN_ALERT "PCI: no irq found for %s pin:%u\n", + pci_name((struct pci_dev *)dev), pin); + } else { + printk(KERN_INFO "PCI: mapping irq for %s pin:%u, irq:%d\n", + pci_name((struct pci_dev *)dev), pin, irq); + } + +out: + return irq; +} + +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + +/* -------------------------------------------------------------------------*/ + +static struct resource pci_io_resource = { + .name = "ADM5120 PCI I/O", + .start = ADM5120_PCIIO_BASE, + .end = ADM5120_PCICFG_ADDR-1, + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = { + .name = "ADM5120 PCI MEM", + .start = ADM5120_PCIMEM_BASE, + .end = ADM5120_PCIIO_BASE-1, + .flags = IORESOURCE_MEM +}; + +static struct pci_controller adm5120_controller = { + .pci_ops = &adm5120_pci_ops, + .io_resource = &pci_io_resource, + .mem_resource = &pci_mem_resource, +}; + +static int __init adm5120_pci_setup(void) +{ + if (adm5120_package_pqfp()) { + printk(KERN_INFO "PCI: not available on ADM5120P\n"); + return -1; + } + + /* Avoid ISA compat ranges. */ + PCIBIOS_MIN_IO = 0x00000000; + PCIBIOS_MIN_MEM = 0x00000000; + + /* Set I/O resource limits. */ + ioport_resource.end = 0x1fffffff; + iomem_resource.end = 0xffffffff; + + register_pci_controller(&adm5120_controller); + return 0; +} + +arch_initcall(adm5120_pci_setup); diff --git a/target/linux/adm5120/files-3.8/drivers/ata/pata_rb153_cf.c b/target/linux/adm5120/files-3.8/drivers/ata/pata_rb153_cf.c new file mode 100644 index 0000000000..92a4d1390d --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/ata/pata_rb153_cf.c @@ -0,0 +1,267 @@ +/* + * A low-level PATA driver to handle a Compact Flash connected on the + * Mikrotik's RouterBoard 153 board. + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was based on: drivers/ata/pata_ixp4xx_cf.c + * Copyright (C) 2006-07 Tower Technologies + * Author: Alessandro Zummo + * + * Also was based on the driver for Linux 2.4.xx published by Mikrotik for + * their RouterBoard 1xx and 5xx series devices. The original Mikrotik code + * seems not to have a license. + * + * 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 + +#define DRV_NAME "pata-rb153-cf" +#define DRV_VERSION "0.5.0" +#define DRV_DESC "PATA driver for RouterBOARD 153 Compact Flash" + +#define RB153_CF_MAXPORTS 1 +#define RB153_CF_IO_DELAY 100 + +#define RB153_CF_REG_CMD 0x0800 +#define RB153_CF_REG_CTRL 0x080E +#define RB153_CF_REG_DATA 0x0C00 + +struct rb153_cf_info { + void __iomem *iobase; + unsigned int gpio_line; + int frozen; + unsigned int irq; +}; + +static inline void rb153_pata_finish_io(struct ata_port *ap) +{ + struct rb153_cf_info *info = ap->host->private_data; + + /* FIXME: Keep previous delay. If this is merely a fence then + * ata_sff_sync might be sufficient. */ + ata_sff_dma_pause(ap); + ndelay(RB153_CF_IO_DELAY); + + irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); +} + +static void rb153_pata_exec_command(struct ata_port *ap, + const struct ata_taskfile *tf) +{ + writeb(tf->command, ap->ioaddr.command_addr); + rb153_pata_finish_io(ap); +} + +static unsigned int rb153_pata_data_xfer(struct ata_device *adev, + unsigned char *buf, + unsigned int buflen, + int write_data) +{ + void __iomem *ioaddr = adev->link->ap->ioaddr.data_addr; + unsigned int t; + + t = buflen; + if (write_data) { + for (; t > 0; t--, buf++) + writeb(*buf, ioaddr); + } else { + for (; t > 0; t--, buf++) + *buf = readb(ioaddr); + } + + rb153_pata_finish_io(adev->link->ap); + return buflen; +} + +static void rb153_pata_freeze(struct ata_port *ap) +{ + struct rb153_cf_info *info = ap->host->private_data; + + info->frozen = 1; +} + +static void rb153_pata_thaw(struct ata_port *ap) +{ + struct rb153_cf_info *info = ap->host->private_data; + + info->frozen = 0; +} + +static irqreturn_t rb153_pata_irq_handler(int irq, void *dev_instance) +{ + struct ata_host *ah = dev_instance; + struct rb153_cf_info *info = ah->private_data; + + if (gpio_get_value(info->gpio_line)) { + irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); + if (!info->frozen) + ata_sff_interrupt(irq, dev_instance); + } else { + irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); + } + + return IRQ_HANDLED; +} + +static struct ata_port_operations rb153_pata_port_ops = { + .inherits = &ata_sff_port_ops, + .sff_exec_command = rb153_pata_exec_command, + .sff_data_xfer = rb153_pata_data_xfer, + .freeze = rb153_pata_freeze, + .thaw = rb153_pata_thaw, +}; + +static struct scsi_host_template rb153_pata_sht = { + ATA_PIO_SHT(DRV_NAME), +}; + +static void rb153_pata_setup_port(struct ata_host *ah) +{ + struct rb153_cf_info *info = ah->private_data; + struct ata_port *ap; + + ap = ah->ports[0]; + + ap->ops = &rb153_pata_port_ops; + ap->pio_mask = 0x1f; /* PIO4 */ + + ap->ioaddr.cmd_addr = info->iobase + RB153_CF_REG_CMD; + ap->ioaddr.ctl_addr = info->iobase + RB153_CF_REG_CTRL; + ap->ioaddr.altstatus_addr = info->iobase + RB153_CF_REG_CTRL; + + ata_sff_std_ports(&ap->ioaddr); + + ap->ioaddr.data_addr = info->iobase + RB153_CF_REG_DATA; +} + +static int rb153_pata_driver_probe(struct platform_device *pdev) +{ + unsigned int irq; + int gpio; + struct resource *res; + struct ata_host *ah; + struct rb153_cf_info *info; + int ret; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "no IOMEM resource found\n"); + return -EINVAL; + } + + irq = platform_get_irq(pdev, 0); + if (irq <= 0) { + dev_err(&pdev->dev, "no IRQ resource found\n"); + return -ENOENT; + } + + gpio = irq_to_gpio(irq); + if (gpio < 0) { + dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq); + return -ENOENT; + } + + ret = gpio_request(gpio, DRV_NAME); + if (ret) { + dev_err(&pdev->dev, "GPIO request failed\n"); + return ret; + } + + ah = ata_host_alloc(&pdev->dev, RB153_CF_MAXPORTS); + if (!ah) + return -ENOMEM; + + platform_set_drvdata(pdev, ah); + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + ah->private_data = info; + info->gpio_line = gpio; + info->irq = irq; + + info->iobase = devm_ioremap_nocache(&pdev->dev, res->start, + res->end - res->start + 1); + if (!info->iobase) + return -ENOMEM; + + ret = gpio_direction_input(gpio); + if (ret) { + dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n", + ret); + goto err_free_gpio; + } + + rb153_pata_setup_port(ah); + + ret = ata_host_activate(ah, irq, rb153_pata_irq_handler, + IRQF_TRIGGER_LOW, &rb153_pata_sht); + if (ret) + goto err_free_gpio; + + return 0; + +err_free_gpio: + gpio_free(gpio); + + return ret; +} + +static int rb153_pata_driver_remove(struct platform_device *pdev) +{ + struct ata_host *ah = platform_get_drvdata(pdev); + struct rb153_cf_info *info = ah->private_data; + + ata_host_detach(ah); + gpio_free(info->gpio_line); + + return 0; +} + +static struct platform_driver rb153_pata_platform_driver = { + .probe = rb153_pata_driver_probe, + .remove = rb153_pata_driver_remove, + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, +}; + +/* ------------------------------------------------------------------------ */ + +#define DRV_INFO DRV_DESC " version " DRV_VERSION + +static int __init rb153_pata_module_init(void) +{ + printk(KERN_INFO DRV_INFO "\n"); + + return platform_driver_register(&rb153_pata_platform_driver); +} + +static void __exit rb153_pata_module_exit(void) +{ + platform_driver_unregister(&rb153_pata_platform_driver); +} + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); +MODULE_LICENSE("GPL v2"); + +module_init(rb153_pata_module_init); +module_exit(rb153_pata_module_exit); diff --git a/target/linux/adm5120/files-3.8/drivers/leds/ledtrig-adm5120-switch.c b/target/linux/adm5120/files-3.8/drivers/leds/ledtrig-adm5120-switch.c new file mode 100644 index 0000000000..23a54a0b9a --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/leds/ledtrig-adm5120-switch.c @@ -0,0 +1,149 @@ +/* + * LED ADM5120 Switch Port State Trigger + * + * Copyright (C) 2007 Bernhard Held + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was based on: drivers/leds/ledtrig-timer.c + * Copyright 2005-2006 Openedhand Ltd. + * Author: Richard Purdie + * + * 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 "leds.h" + +#define DRV_NAME "port_state" +#define DRV_DESC "LED ADM5120 Switch Port State Trigger" + +struct port_state { + char *name; + unsigned int value; +}; + +#define PORT_STATE(n, v) {.name = (n), .value = (v)} + +static struct port_state port_states[] = { + PORT_STATE("off", LED_OFF), + PORT_STATE("on", LED_FULL), + PORT_STATE("flash", ADM5120_GPIO_FLASH), + PORT_STATE("link", ADM5120_GPIO_LINK), + PORT_STATE("speed", ADM5120_GPIO_SPEED), + PORT_STATE("duplex", ADM5120_GPIO_DUPLEX), + PORT_STATE("act", ADM5120_GPIO_ACT), + PORT_STATE("coll", ADM5120_GPIO_COLL), + PORT_STATE("link_act", ADM5120_GPIO_LINK_ACT), + PORT_STATE("duplex_coll", ADM5120_GPIO_DUPLEX_COLL), + PORT_STATE("10M_act", ADM5120_GPIO_10M_ACT), + PORT_STATE("100M_act", ADM5120_GPIO_100M_ACT), +}; + +static ssize_t led_port_state_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + struct port_state *state = led_cdev->trigger_data; + int len = 0; + int i; + + *buf = '\0'; + for (i = 0; i < ARRAY_SIZE(port_states); i++) { + if (&port_states[i] == state) + len += sprintf(buf+len, "[%s] ", port_states[i].name); + else + len += sprintf(buf+len, "%s ", port_states[i].name); + } + len += sprintf(buf+len, "\n"); + + return len; +} + +static ssize_t led_port_state_store(struct device *dev, + struct device_attribute *attr, const char *buf, size_t size) +{ + struct led_classdev *led_cdev = dev_get_drvdata(dev); + size_t len; + int i; + + for (i = 0; i < ARRAY_SIZE(port_states); i++) { + len = strlen(port_states[i].name); + if (strncmp(port_states[i].name, buf, len) != 0) + continue; + + if (buf[len] != '\0' && buf[len] != '\n') + continue; + + led_cdev->trigger_data = &port_states[i]; + led_set_brightness(led_cdev, port_states[i].value); + return size; + } + + return -EINVAL; +} + +static DEVICE_ATTR(port_state, 0644, led_port_state_show, + led_port_state_store); + +static void adm5120_switch_trig_activate(struct led_classdev *led_cdev) +{ + struct port_state *state = port_states; + int rc; + + led_cdev->trigger_data = state; + + rc = device_create_file(led_cdev->dev, &dev_attr_port_state); + if (rc) + goto err; + + led_set_brightness(led_cdev, state->value); + + return; +err: + led_cdev->trigger_data = NULL; +} + +static void adm5120_switch_trig_deactivate(struct led_classdev *led_cdev) +{ + struct port_state *state = led_cdev->trigger_data; + + if (!state) + return; + + device_remove_file(led_cdev->dev, &dev_attr_port_state); + +} + +static struct led_trigger adm5120_switch_led_trigger = { + .name = DRV_NAME, + .activate = adm5120_switch_trig_activate, + .deactivate = adm5120_switch_trig_deactivate, +}; + +static int __init adm5120_switch_trig_init(void) +{ + led_trigger_register(&adm5120_switch_led_trigger); + return 0; +} + +static void __exit adm5120_switch_trig_exit(void) +{ + led_trigger_unregister(&adm5120_switch_led_trigger); +} + +module_init(adm5120_switch_trig_init); +module_exit(adm5120_switch_trig_exit); + +MODULE_AUTHOR("Bernhard Held , " + "Gabor Juhos "); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files-3.8/drivers/mtd/maps/adm5120-flash.c b/target/linux/adm5120/files-3.8/drivers/mtd/maps/adm5120-flash.c new file mode 100644 index 0000000000..f6a86f4897 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/mtd/maps/adm5120-flash.c @@ -0,0 +1,482 @@ +/* + * Platform driver for NOR flash devices on ADM5120 based boards + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/mtd/map/physmap.c + * Copyright (C) 2003 MontaVista Software Inc. + * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net + * + * 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 +#include + +#include +#include +#include +#include + +#define DRV_NAME "adm5120-flash" +#define DRV_DESC "ADM5120 flash MAP driver" +#define MAX_PARSED_PARTS 8 + +#ifdef ADM5120_FLASH_DEBUG +#define MAP_DBG(m, f, a...) printk(KERN_INFO "%s: " f, (m->name) , ## a) +#else +#define MAP_DBG(m, f, a...) do {} while (0) +#endif +#define MAP_ERR(m, f, a...) printk(KERN_ERR "%s: " f, (m->name) , ## a) +#define MAP_INFO(m, f, a...) printk(KERN_INFO "%s: " f, (m->name) , ## a) + +struct adm5120_map_info { + struct map_info map; + void (*switch_bank)(unsigned); + unsigned long window_size; +}; + +struct adm5120_flash_info { + struct mtd_info *mtd; + struct resource *res; + struct platform_device *dev; + struct adm5120_map_info amap; +}; + +struct flash_desc { + u32 phys; + u32 srs_shift; +}; + +/* + * Globals + */ +static DEFINE_SPINLOCK(adm5120_flash_spin); +#define FLASH_LOCK() spin_lock(&adm5120_flash_spin) +#define FLASH_UNLOCK() spin_unlock(&adm5120_flash_spin) + +static u32 flash_bankwidths[4] = { 1, 2, 4, 0 }; + +static u32 flash_sizes[8] = { + 0, 512*1024, 1024*1024, 2*1024*1024, + 4*1024*1024, 0, 0, 0 +}; + +static struct flash_desc flash_descs[2] = { + { + .phys = ADM5120_SRAM0_BASE, + .srs_shift = MEMCTRL_SRS0_SHIFT, + }, { + .phys = ADM5120_SRAM1_BASE, + .srs_shift = MEMCTRL_SRS1_SHIFT, + } +}; + +static const char const *probe_types[] = { + "cfi_probe", + "jedec_probe", + "map_rom", + NULL +}; + +static const char const *parse_types[] = { + "cmdlinepart", +#ifdef CONFIG_MTD_REDBOOT_PARTS + "RedBoot", +#endif +#ifdef CONFIG_MTD_MYLOADER_PARTS + "MyLoader", +#endif + NULL, +}; + +#define BANK_SIZE (2<<20) +#define BANK_SIZE_MAX (4<<20) +#define BANK_OFFS_MASK (BANK_SIZE-1) +#define BANK_START_MASK (~BANK_OFFS_MASK) + +static inline struct adm5120_map_info *map_to_amap(struct map_info *map) +{ + return (struct adm5120_map_info *)map; +} + +static void adm5120_flash_switchbank(struct map_info *map, + unsigned long ofs) +{ + struct adm5120_map_info *amap = map_to_amap(map); + unsigned bank; + + if (amap->switch_bank == NULL) + return; + + bank = (ofs & BANK_START_MASK) >> 21; + if (bank > 1) + BUG(); + + MAP_DBG(map, "switching to bank %u, ofs=%lX\n", bank, ofs); + amap->switch_bank(bank); +} + +static map_word adm5120_flash_read(struct map_info *map, unsigned long ofs) +{ + struct adm5120_map_info *amap = map_to_amap(map); + map_word ret; + + MAP_DBG(map, "reading from ofs %lX\n", ofs); + + if (ofs >= amap->window_size) + return map_word_ff(map); + + FLASH_LOCK(); + adm5120_flash_switchbank(map, ofs); + ret = inline_map_read(map, (ofs & (amap->window_size-1))); + FLASH_UNLOCK(); + + return ret; +} + +static void adm5120_flash_write(struct map_info *map, const map_word datum, + unsigned long ofs) +{ + struct adm5120_map_info *amap = map_to_amap(map); + + MAP_DBG(map, "writing to ofs %lX\n", ofs); + + if (ofs > amap->window_size) + return; + + FLASH_LOCK(); + adm5120_flash_switchbank(map, ofs); + inline_map_write(map, datum, (ofs & (amap->window_size-1))); + FLASH_UNLOCK(); +} + +static void adm5120_flash_copy_from(struct map_info *map, void *to, + unsigned long from, ssize_t len) +{ + struct adm5120_map_info *amap = map_to_amap(map); + char *p; + ssize_t t; + + MAP_DBG(map, "copy_from, to=%lX, from=%lX, len=%lX\n", + (unsigned long)to, from, (unsigned long)len); + + if (from > amap->window_size) + return; + + p = (char *)to; + while (len > 0) { + t = len; + if ((from < BANK_SIZE) && ((from+len) > BANK_SIZE)) + t = BANK_SIZE-from; + + FLASH_LOCK(); + MAP_DBG(map, "copying %lu byte(s) from %lX to %lX\n", + (unsigned long)t, (from & (amap->window_size-1)), + (unsigned long)p); + adm5120_flash_switchbank(map, from); + inline_map_copy_from(map, p, (from & (amap->window_size-1)), t); + FLASH_UNLOCK(); + p += t; + from += t; + len -= t; + } +} + +static int adm5120_flash_initres(struct adm5120_flash_info *info) +{ + struct map_info *map = &info->amap.map; + int err = 0; + + info->res = request_mem_region(map->phys, info->amap.window_size, + map->name); + if (info->res == NULL) { + MAP_ERR(map, "could not reserve memory region\n"); + err = -ENOMEM; + goto out; + } + + map->virt = ioremap_nocache(map->phys, info->amap.window_size); + if (map->virt == NULL) { + MAP_ERR(map, "failed to ioremap flash region\n"); + err = -ENOMEM; + goto out; + } + +out: + return err; +} + +static int adm5120_flash_initinfo(struct adm5120_flash_info *info, + struct platform_device *dev) +{ + struct map_info *map = &info->amap.map; + struct adm5120_flash_platform_data *pdata = dev->dev.platform_data; + struct flash_desc *fdesc; + u32 t = 0; + + map->name = dev_name(&dev->dev); + + if (dev->id > 1) { + MAP_ERR(map, "invalid flash id\n"); + goto err_out; + } + + fdesc = &flash_descs[dev->id]; + + if (pdata) + info->amap.window_size = pdata->window_size; + + if (info->amap.window_size == 0) { + /* get memory window size */ + t = SW_READ_REG(SWITCH_REG_MEMCTRL) >> fdesc->srs_shift; + t &= MEMCTRL_SRS_MASK; + info->amap.window_size = flash_sizes[t]; + } + + if (info->amap.window_size == 0) { + MAP_ERR(map, "unable to determine window size\n"); + goto err_out; + } + + /* get flash bus width */ + switch (dev->id) { + case 0: + t = MPMC_READ_REG(SC1) & SC_MW_MASK; + break; + case 1: + t = MPMC_READ_REG(SC0) & SC_MW_MASK; + break; + } + map->bankwidth = flash_bankwidths[t]; + if (map->bankwidth == 0) { + MAP_ERR(map, "invalid bus width detected\n"); + goto err_out; + } + + map->phys = fdesc->phys; + map->size = BANK_SIZE_MAX; + + simple_map_init(map); + map->read = adm5120_flash_read; + map->write = adm5120_flash_write; + map->copy_from = adm5120_flash_copy_from; + + if (pdata) { + map->set_vpp = pdata->set_vpp; + info->amap.switch_bank = pdata->switch_bank; + } + + info->dev = dev; + + MAP_INFO(map, "probing at 0x%lX, size:%ldKiB, width:%d bits\n", + (unsigned long)map->phys, + (unsigned long)info->amap.window_size >> 10, + map->bankwidth*8); + + return 0; + +err_out: + return -ENODEV; +} + +static void adm5120_flash_initbanks(struct adm5120_flash_info *info) +{ + struct map_info *map = &info->amap.map; + + if (info->mtd->size <= BANK_SIZE) + /* no bank switching needed */ + return; + + if (info->amap.switch_bank) { + info->amap.window_size = info->mtd->size; + return; + } + + MAP_ERR(map, "reduce visibility from %ldKiB to %ldKiB\n", + (unsigned long)map->size >> 10, + (unsigned long)info->mtd->size >> 10); + + info->mtd->size = info->amap.window_size; +} + +static int adm5120_flash_remove(struct platform_device *dev) +{ + struct adm5120_flash_info *info; + + info = platform_get_drvdata(dev); + if (info == NULL) + return 0; + + platform_set_drvdata(dev, NULL); + + if (info->mtd != NULL) { + mtd_device_unregister(info->mtd); + map_destroy(info->mtd); + } + + if (info->amap.map.virt != NULL) + iounmap(info->amap.map.virt); + + if (info->res != NULL) { + release_resource(info->res); + kfree(info->res); + } + + return 0; +} + +static int adm5120_flash_probe(struct platform_device *dev) +{ + struct adm5120_flash_platform_data *pdata; + struct adm5120_flash_info *info; + struct map_info *map; + const char **probe_type; + int err; + + pdata = dev->dev.platform_data; + if (!pdata) { + dev_err(&dev->dev, "no platform data\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (info == NULL) { + err = -ENOMEM; + goto err_out; + } + + platform_set_drvdata(dev, info); + + err = adm5120_flash_initinfo(info, dev); + if (err) + goto err_out; + + err = adm5120_flash_initres(info); + if (err) + goto err_out; + + map = &info->amap.map; + for (probe_type = probe_types; info->mtd == NULL && *probe_type != NULL; + probe_type++) + info->mtd = do_map_probe(*probe_type, map); + + if (info->mtd == NULL) { + MAP_ERR(map, "map_probe failed\n"); + err = -ENXIO; + goto err_out; + } + + adm5120_flash_initbanks(info); + + if (info->mtd->size < info->amap.window_size) { + /* readjust resources */ + iounmap(map->virt); + release_resource(info->res); + kfree(info->res); + + info->amap.window_size = info->mtd->size; + map->size = info->mtd->size; + MAP_INFO(map, "reducing map size to %ldKiB\n", + (unsigned long)map->size >> 10); + err = adm5120_flash_initres(info); + if (err) + goto err_out; + } + + MAP_INFO(map, "found at 0x%lX, size:%ldKiB, width:%d bits\n", + (unsigned long)map->phys, (unsigned long)info->mtd->size >> 10, + map->bankwidth*8); + + info->mtd->owner = THIS_MODULE; + + err = mtd_device_parse_register(info->mtd, parse_types, 0, + pdata->parts, pdata->nr_parts); + if (err) + goto err_out; + + return 0; + +err_out: + adm5120_flash_remove(dev); + return err; +} + +#ifdef CONFIG_PM +static int adm5120_flash_suspend(struct platform_device *dev, + pm_message_t state) +{ + struct adm5120_flash_info *info = platform_get_drvdata(dev); + int ret = 0; + + if (info) + ret = info->mtd->suspend(info->mtd); + + return ret; +} + +static int adm5120_flash_resume(struct platform_device *dev) +{ + struct adm5120_flash_info *info = platform_get_drvdata(dev); + + if (info) + info->mtd->resume(info->mtd); + + return 0; +} + +static void adm5120_flash_shutdown(struct platform_device *dev) +{ + struct adm5120_flash_info *info = platform_get_drvdata(dev); + + if (info && info->mtd->suspend(info->mtd) == 0) + info->mtd->resume(info->mtd); +} +#endif + +static struct platform_driver adm5120_flash_driver = { + .probe = adm5120_flash_probe, + .remove = adm5120_flash_remove, +#ifdef CONFIG_PM + .suspend = adm5120_flash_suspend, + .resume = adm5120_flash_resume, + .shutdown = adm5120_flash_shutdown, +#endif + .driver = { + .name = DRV_NAME, + }, +}; + +static int __init adm5120_flash_init(void) +{ + int err; + + err = platform_driver_register(&adm5120_flash_driver); + + return err; +} + +static void __exit adm5120_flash_exit(void) +{ + platform_driver_unregister(&adm5120_flash_driver); +} + +module_init(adm5120_flash_init); +module_exit(adm5120_flash_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION(DRV_DESC); diff --git a/target/linux/adm5120/files-3.8/drivers/mtd/trxsplit.c b/target/linux/adm5120/files-3.8/drivers/mtd/trxsplit.c new file mode 100644 index 0000000000..76cbdc7494 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/mtd/trxsplit.c @@ -0,0 +1,216 @@ +/* + * Copyright (C) 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 + * by the Free Software Foundation. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#define PFX "trxsplit: " + +#define TRX_MAGIC 0x30524448 /* "HDR0" */ +#define TRX_VERSION 1 +#define TRX_MAX_LEN 0x3A0000 +#define TRX_NO_HEADER 0x1 /* do not write TRX header */ +#define TRX_GZ_FILES 0x2 /* contains individual gzip files */ +#define TRX_MAX_OFFSET 3 +#define TRX_MIN_KERNEL_SIZE (256 * 1024) + +struct trx_header { + u32 magic; /* "HDR0" */ + u32 len; /* Length of file including header */ + u32 crc32; /* 32-bit CRC from flag_version to end of file */ + u32 flag_version; /* 0:15 flags, 16:31 version */ + u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions */ +}; + +#define TRX_ALIGN 0x1000 + +static int trx_nr_parts; +static unsigned long trx_offset; +static struct mtd_info *trx_mtd; +static struct mtd_partition trx_parts[TRX_MAX_OFFSET]; +static struct trx_header trx_hdr; + +static int trxsplit_refresh_partitions(struct mtd_info *mtd); + +static int trxsplit_checktrx(struct mtd_info *mtd, unsigned long offset) +{ + size_t retlen; + int err; + + err = mtd_read(mtd, offset, sizeof(trx_hdr), &retlen, (void *)&trx_hdr); + if (err) { + printk(KERN_ALERT PFX "unable to read from '%s'\n", mtd->name); + goto err_out; + } + + if (retlen != sizeof(trx_hdr)) { + printk(KERN_ALERT PFX "reading failed on '%s'\n", mtd->name); + goto err_out; + } + + trx_hdr.magic = le32_to_cpu(trx_hdr.magic); + trx_hdr.len = le32_to_cpu(trx_hdr.len); + trx_hdr.crc32 = le32_to_cpu(trx_hdr.crc32); + trx_hdr.flag_version = le32_to_cpu(trx_hdr.flag_version); + trx_hdr.offsets[0] = le32_to_cpu(trx_hdr.offsets[0]); + trx_hdr.offsets[1] = le32_to_cpu(trx_hdr.offsets[1]); + trx_hdr.offsets[2] = le32_to_cpu(trx_hdr.offsets[2]); + + /* sanity checks */ + if (trx_hdr.magic != TRX_MAGIC) + goto err_out; + + if (trx_hdr.len > mtd->size - offset) + goto err_out; + + /* TODO: add crc32 checking too? */ + + return 0; + +err_out: + return -1; +} + +static void trxsplit_findtrx(struct mtd_info *mtd) +{ + unsigned long offset; + int err; + + printk(KERN_INFO PFX "searching TRX header in '%s'\n", mtd->name); + + err = 0; + for (offset = 0; offset < mtd->size; offset += TRX_ALIGN) { + err = trxsplit_checktrx(mtd, offset); + if (err == 0) + break; + } + + if (err) + return; + + printk(KERN_INFO PFX "TRX header found at 0x%lX\n", offset); + + trx_mtd = mtd; + trx_offset = offset; +} + +static void trxsplit_create_partitions(struct mtd_info *mtd) +{ + struct mtd_partition *part = trx_parts; + int err; + int i; + + for (i = 0; i < TRX_MAX_OFFSET; i++) { + part = &trx_parts[i]; + if (trx_hdr.offsets[i] == 0) + continue; + part->offset = trx_offset + trx_hdr.offsets[i]; + trx_nr_parts++; + } + + for (i = 0; i < trx_nr_parts-1; i++) + trx_parts[i].size = trx_parts[i+1].offset - trx_parts[i].offset; + + trx_parts[i].size = mtd->size - trx_parts[i].offset; + + i = 0; + part = &trx_parts[i]; + if (part->size < TRX_MIN_KERNEL_SIZE) { + part->name = "loader"; + i++; + } + + part = &trx_parts[i]; + part->name = "kernel"; + i++; + + part = &trx_parts[i]; + part->name = "rootfs"; + + err = mtd_device_register(mtd, trx_parts, trx_nr_parts); + if (err) { + printk(KERN_ALERT PFX "adding TRX partitions failed\n"); + return; + } + + mtd->refresh_device = trxsplit_refresh_partitions; +} + +static int trxsplit_refresh_partitions(struct mtd_info *mtd) +{ + printk(KERN_INFO PFX "refreshing TRX partitions in '%s' (%d,%d)\n", + mtd->name, MTD_BLOCK_MAJOR, mtd->index); + + /* remove old partitions */ + mtd_device_unregister(mtd); + + trxsplit_findtrx(mtd); + if (!trx_mtd) + goto err; + + trxsplit_create_partitions(trx_mtd); + return 1; + +err: + return 0; +} + +static void __init trxsplit_add_mtd(struct mtd_info *mtd) +{ + if (mtd->type != MTD_NORFLASH) { + printk(KERN_INFO PFX "'%s' is not a NOR flash, skipped\n", + mtd->name); + return; + } + + if (!trx_mtd) + trxsplit_findtrx(mtd); +} + +static void __init trxsplit_remove_mtd(struct mtd_info *mtd) +{ + /* nothing to do */ +} + +static struct mtd_notifier trxsplit_notifier __initdata = { + .add = trxsplit_add_mtd, + .remove = trxsplit_remove_mtd, +}; + +static void __init trxsplit_scan(void) +{ + register_mtd_user(&trxsplit_notifier); + unregister_mtd_user(&trxsplit_notifier); +} + +static int __init trxsplit_init(void) +{ + trxsplit_scan(); + + if (trx_mtd) { + printk(KERN_INFO PFX "creating TRX partitions in '%s' " + "(%d,%d)\n", trx_mtd->name, MTD_BLOCK_MAJOR, + trx_mtd->index); + trxsplit_create_partitions(trx_mtd); + } + + return 0; +} + +late_initcall(trxsplit_init); diff --git a/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.c b/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.c new file mode 100644 index 0000000000..7fbabb00e4 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.c @@ -0,0 +1,1219 @@ +/* + * ADM5120 built-in ethernet switch driver + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This code was based on a driver for Linux 2.6.xx by Jeroen Vreeken. + * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005 + * NAPI extension for the Jeroen's driver + * Copyright Thomas Langer (Thomas.Langer@infineon.com), 2007 + * Copyright Friedrich Beckmann (Friedrich.Beckmann@infineon.com), 2007 + * Inspiration for the Jeroen's driver came from the ADMtek 2.4 driver. + * Copyright ADMtek Inc. + * + * 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 +#include +#include + +#include + +#include +#include +#include + +#include "adm5120sw.h" +#include + +#define DRV_NAME "adm5120-switch" +#define DRV_DESC "ADM5120 built-in ethernet switch driver" +#define DRV_VERSION "0.1.1" + +#define CONFIG_ADM5120_SWITCH_NAPI 1 +#undef CONFIG_ADM5120_SWITCH_DEBUG + +/* ------------------------------------------------------------------------ */ + +#ifdef CONFIG_ADM5120_SWITCH_DEBUG +#define SW_DBG(f, a...) printk(KERN_DEBUG "%s: " f, DRV_NAME , ## a) +#else +#define SW_DBG(f, a...) do {} while (0) +#endif +#define SW_ERR(f, a...) printk(KERN_ERR "%s: " f, DRV_NAME , ## a) +#define SW_INFO(f, a...) printk(KERN_INFO "%s: " f, DRV_NAME , ## a) + +#define SWITCH_NUM_PORTS 6 +#define ETH_CSUM_LEN 4 + +#define RX_MAX_PKTLEN 1550 +#define RX_RING_SIZE 64 + +#define TX_RING_SIZE 32 +#define TX_QUEUE_LEN 28 /* Limit ring entries actually used. */ +#define TX_TIMEOUT (HZ * 400) + +#define RX_DESCS_SIZE (RX_RING_SIZE * sizeof(struct dma_desc *)) +#define RX_SKBS_SIZE (RX_RING_SIZE * sizeof(struct sk_buff *)) +#define TX_DESCS_SIZE (TX_RING_SIZE * sizeof(struct dma_desc *)) +#define TX_SKBS_SIZE (TX_RING_SIZE * sizeof(struct sk_buff *)) + +#define SKB_ALLOC_LEN (RX_MAX_PKTLEN + 32) +#define SKB_RESERVE_LEN (NET_IP_ALIGN + NET_SKB_PAD) + +#define SWITCH_INTS_HIGH (SWITCH_INT_SHD | SWITCH_INT_RHD | SWITCH_INT_HDF) +#define SWITCH_INTS_LOW (SWITCH_INT_SLD | SWITCH_INT_RLD | SWITCH_INT_LDF) +#define SWITCH_INTS_ERR (SWITCH_INT_RDE | SWITCH_INT_SDE | SWITCH_INT_CPUH) +#define SWITCH_INTS_Q (SWITCH_INT_P0QF | SWITCH_INT_P1QF | SWITCH_INT_P2QF | \ + SWITCH_INT_P3QF | SWITCH_INT_P4QF | SWITCH_INT_P5QF | \ + SWITCH_INT_CPQF | SWITCH_INT_GQF) + +#define SWITCH_INTS_ALL (SWITCH_INTS_HIGH | SWITCH_INTS_LOW | \ + SWITCH_INTS_ERR | SWITCH_INTS_Q | \ + SWITCH_INT_MD | SWITCH_INT_PSC) + +#define SWITCH_INTS_USED (SWITCH_INTS_LOW | SWITCH_INT_PSC) +#define SWITCH_INTS_POLL (SWITCH_INT_RLD | SWITCH_INT_LDF | SWITCH_INT_SLD) + +/* ------------------------------------------------------------------------ */ + +struct adm5120_if_priv { + struct net_device *dev; + + unsigned int vlan_no; + unsigned int port_mask; + +#ifdef CONFIG_ADM5120_SWITCH_NAPI + struct napi_struct napi; +#endif +}; + +struct dma_desc { + __u32 buf1; +#define DESC_OWN (1UL << 31) /* Owned by the switch */ +#define DESC_EOR (1UL << 28) /* End of Ring */ +#define DESC_ADDR_MASK 0x1FFFFFF +#define DESC_ADDR(x) ((__u32)(x) & DESC_ADDR_MASK) + __u32 buf2; +#define DESC_BUF2_EN (1UL << 31) /* Buffer 2 enable */ + __u32 buflen; + __u32 misc; +/* definitions for tx/rx descriptors */ +#define DESC_PKTLEN_SHIFT 16 +#define DESC_PKTLEN_MASK 0x7FF +/* tx descriptor specific part */ +#define DESC_CSUM (1UL << 31) /* Append checksum */ +#define DESC_DSTPORT_SHIFT 8 +#define DESC_DSTPORT_MASK 0x3F +#define DESC_VLAN_MASK 0x3F +/* rx descriptor specific part */ +#define DESC_SRCPORT_SHIFT 12 +#define DESC_SRCPORT_MASK 0x7 +#define DESC_DA_MASK 0x3 +#define DESC_DA_SHIFT 4 +#define DESC_IPCSUM_FAIL (1UL << 3) /* IP checksum fail */ +#define DESC_VLAN_TAG (1UL << 2) /* VLAN tag present */ +#define DESC_TYPE_MASK 0x3 /* mask for Packet type */ +#define DESC_TYPE_IP 0x0 /* IP packet */ +#define DESC_TYPE_PPPoE 0x1 /* PPPoE packet */ +} __attribute__ ((aligned(16))); + +/* ------------------------------------------------------------------------ */ + +static int adm5120_nrdevs; + +static struct net_device *adm5120_devs[SWITCH_NUM_PORTS]; +/* Lookup table port -> device */ +static struct net_device *adm5120_port[SWITCH_NUM_PORTS]; + +static struct dma_desc *txl_descs; +static struct dma_desc *rxl_descs; + +static dma_addr_t txl_descs_dma; +static dma_addr_t rxl_descs_dma; + +static struct sk_buff **txl_skbuff; +static struct sk_buff **rxl_skbuff; + +static unsigned int cur_rxl, dirty_rxl; /* producer/consumer ring indices */ +static unsigned int cur_txl, dirty_txl; + +static unsigned int sw_used; + +static DEFINE_SPINLOCK(tx_lock); + +/* ------------------------------------------------------------------------ */ + +static inline u32 sw_read_reg(u32 reg) +{ + return __raw_readl((void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); +} + +static inline void sw_write_reg(u32 reg, u32 val) +{ + __raw_writel(val, (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); +} + +static inline void sw_int_mask(u32 mask) +{ + u32 t; + + t = sw_read_reg(SWITCH_REG_INT_MASK); + t |= mask; + sw_write_reg(SWITCH_REG_INT_MASK, t); +} + +static inline void sw_int_unmask(u32 mask) +{ + u32 t; + + t = sw_read_reg(SWITCH_REG_INT_MASK); + t &= ~mask; + sw_write_reg(SWITCH_REG_INT_MASK, t); +} + +static inline void sw_int_ack(u32 mask) +{ + sw_write_reg(SWITCH_REG_INT_STATUS, mask); +} + +static inline u32 sw_int_status(void) +{ + u32 t; + + t = sw_read_reg(SWITCH_REG_INT_STATUS); + t &= ~sw_read_reg(SWITCH_REG_INT_MASK); + return t; +} + +static inline u32 desc_get_srcport(struct dma_desc *desc) +{ + return (desc->misc >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK; +} + +static inline u32 desc_get_pktlen(struct dma_desc *desc) +{ + return (desc->misc >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK; +} + +static inline int desc_ipcsum_fail(struct dma_desc *desc) +{ + return ((desc->misc & DESC_IPCSUM_FAIL) != 0); +} + +/* ------------------------------------------------------------------------ */ + +#ifdef CONFIG_ADM5120_SWITCH_DEBUG +static void sw_dump_desc(char *label, struct dma_desc *desc, int tx) +{ + u32 t; + + SW_DBG("%s %s desc/%p\n", label, tx ? "tx" : "rx", desc); + + t = desc->buf1; + SW_DBG(" buf1 %08X addr=%08X; len=%08X %s%s\n", t, + t & DESC_ADDR_MASK, + desc->buflen, + (t & DESC_OWN) ? "SWITCH" : "CPU", + (t & DESC_EOR) ? " RE" : ""); + + t = desc->buf2; + SW_DBG(" buf2 %08X addr=%08X%s\n", desc->buf2, + t & DESC_ADDR_MASK, + (t & DESC_BUF2_EN) ? " EN" : ""); + + t = desc->misc; + if (tx) + SW_DBG(" misc %08X%s pktlen=%04X ports=%02X vlan=%02X\n", t, + (t & DESC_CSUM) ? " CSUM" : "", + (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, + (t >> DESC_DSTPORT_SHIFT) & DESC_DSTPORT_MASK, + t & DESC_VLAN_MASK); + else + SW_DBG(" misc %08X pktlen=%04X port=%d DA=%d%s%s type=%d\n", + t, + (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, + (t >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK, + (t >> DESC_DA_SHIFT) & DESC_DA_MASK, + (t & DESC_IPCSUM_FAIL) ? " IPCF" : "", + (t & DESC_VLAN_TAG) ? " VLAN" : "", + (t & DESC_TYPE_MASK)); +} + +static void sw_dump_intr_mask(char *label, u32 mask) +{ + SW_DBG("%s %08X%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + label, mask, + (mask & SWITCH_INT_SHD) ? " SHD" : "", + (mask & SWITCH_INT_SLD) ? " SLD" : "", + (mask & SWITCH_INT_RHD) ? " RHD" : "", + (mask & SWITCH_INT_RLD) ? " RLD" : "", + (mask & SWITCH_INT_HDF) ? " HDF" : "", + (mask & SWITCH_INT_LDF) ? " LDF" : "", + (mask & SWITCH_INT_P0QF) ? " P0QF" : "", + (mask & SWITCH_INT_P1QF) ? " P1QF" : "", + (mask & SWITCH_INT_P2QF) ? " P2QF" : "", + (mask & SWITCH_INT_P3QF) ? " P3QF" : "", + (mask & SWITCH_INT_P4QF) ? " P4QF" : "", + (mask & SWITCH_INT_CPQF) ? " CPQF" : "", + (mask & SWITCH_INT_GQF) ? " GQF" : "", + (mask & SWITCH_INT_MD) ? " MD" : "", + (mask & SWITCH_INT_BCS) ? " BCS" : "", + (mask & SWITCH_INT_PSC) ? " PSC" : "", + (mask & SWITCH_INT_ID) ? " ID" : "", + (mask & SWITCH_INT_W0TE) ? " W0TE" : "", + (mask & SWITCH_INT_W1TE) ? " W1TE" : "", + (mask & SWITCH_INT_RDE) ? " RDE" : "", + (mask & SWITCH_INT_SDE) ? " SDE" : "", + (mask & SWITCH_INT_CPUH) ? " CPUH" : ""); +} + +static void sw_dump_regs(void) +{ + u32 t; + + t = sw_read_reg(SWITCH_REG_PHY_STATUS); + SW_DBG("phy_status: %08X\n", t); + + t = sw_read_reg(SWITCH_REG_CPUP_CONF); + SW_DBG("cpup_conf: %08X%s%s%s\n", t, + (t & CPUP_CONF_DCPUP) ? " DCPUP" : "", + (t & CPUP_CONF_CRCP) ? " CRCP" : "", + (t & CPUP_CONF_BTM) ? " BTM" : ""); + + t = sw_read_reg(SWITCH_REG_PORT_CONF0); + SW_DBG("port_conf0: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PORT_CONF1); + SW_DBG("port_conf1: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PORT_CONF2); + SW_DBG("port_conf2: %08X\n", t); + + t = sw_read_reg(SWITCH_REG_VLAN_G1); + SW_DBG("vlan g1: %08X\n", t); + t = sw_read_reg(SWITCH_REG_VLAN_G2); + SW_DBG("vlan g2: %08X\n", t); + + t = sw_read_reg(SWITCH_REG_BW_CNTL0); + SW_DBG("bw_cntl0: %08X\n", t); + t = sw_read_reg(SWITCH_REG_BW_CNTL1); + SW_DBG("bw_cntl1: %08X\n", t); + + t = sw_read_reg(SWITCH_REG_PHY_CNTL0); + SW_DBG("phy_cntl0: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PHY_CNTL1); + SW_DBG("phy_cntl1: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PHY_CNTL2); + SW_DBG("phy_cntl2: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PHY_CNTL3); + SW_DBG("phy_cntl3: %08X\n", t); + t = sw_read_reg(SWITCH_REG_PHY_CNTL4); + SW_DBG("phy_cntl4: %08X\n", t); + + t = sw_read_reg(SWITCH_REG_INT_STATUS); + sw_dump_intr_mask("int_status: ", t); + + t = sw_read_reg(SWITCH_REG_INT_MASK); + sw_dump_intr_mask("int_mask: ", t); + + t = sw_read_reg(SWITCH_REG_SHDA); + SW_DBG("shda: %08X\n", t); + t = sw_read_reg(SWITCH_REG_SLDA); + SW_DBG("slda: %08X\n", t); + t = sw_read_reg(SWITCH_REG_RHDA); + SW_DBG("rhda: %08X\n", t); + t = sw_read_reg(SWITCH_REG_RLDA); + SW_DBG("rlda: %08X\n", t); +} +#else +static inline void sw_dump_desc(char *label, struct dma_desc *desc, int tx) {} +static void sw_dump_intr_mask(char *label, u32 mask) {} +static inline void sw_dump_regs(void) {} +#endif /* CONFIG_ADM5120_SWITCH_DEBUG */ + +/* ------------------------------------------------------------------------ */ + +static inline void adm5120_rx_dma_update(struct dma_desc *desc, + struct sk_buff *skb, int end) +{ + desc->misc = 0; + desc->buf2 = 0; + desc->buflen = RX_MAX_PKTLEN; + desc->buf1 = DESC_ADDR(skb->data) | + DESC_OWN | (end ? DESC_EOR : 0); +} + +static void adm5120_switch_rx_refill(void) +{ + unsigned int entry; + + for (; cur_rxl - dirty_rxl > 0; dirty_rxl++) { + struct dma_desc *desc; + struct sk_buff *skb; + + entry = dirty_rxl % RX_RING_SIZE; + desc = &rxl_descs[entry]; + + skb = rxl_skbuff[entry]; + if (skb == NULL) { + skb = alloc_skb(SKB_ALLOC_LEN, GFP_ATOMIC); + if (skb) { + skb_reserve(skb, SKB_RESERVE_LEN); + rxl_skbuff[entry] = skb; + } else { + SW_ERR("no memory for skb\n"); + desc->buflen = 0; + desc->buf2 = 0; + desc->misc = 0; + desc->buf1 = (desc->buf1 & DESC_EOR) | DESC_OWN; + break; + } + } + + desc->buf2 = 0; + desc->buflen = RX_MAX_PKTLEN; + desc->misc = 0; + desc->buf1 = (desc->buf1 & DESC_EOR) | DESC_OWN | + DESC_ADDR(skb->data); + } +} + +static int adm5120_switch_rx(int limit) +{ + unsigned int done = 0; + + SW_DBG("rx start, limit=%d, cur_rxl=%u, dirty_rxl=%u\n", + limit, cur_rxl, dirty_rxl); + + while (done < limit) { + int entry = cur_rxl % RX_RING_SIZE; + struct dma_desc *desc = &rxl_descs[entry]; + struct net_device *rdev; + unsigned int port; + + if (desc->buf1 & DESC_OWN) + break; + + if (dirty_rxl + RX_RING_SIZE == cur_rxl) + break; + + port = desc_get_srcport(desc); + rdev = adm5120_port[port]; + + SW_DBG("rx descriptor %u, desc=%p, skb=%p\n", entry, desc, + rxl_skbuff[entry]); + + if ((rdev) && netif_running(rdev)) { + struct sk_buff *skb = rxl_skbuff[entry]; + int pktlen; + + pktlen = desc_get_pktlen(desc); + pktlen -= ETH_CSUM_LEN; + + if ((pktlen == 0) || desc_ipcsum_fail(desc)) { + rdev->stats.rx_errors++; + if (pktlen == 0) + rdev->stats.rx_length_errors++; + if (desc_ipcsum_fail(desc)) + rdev->stats.rx_crc_errors++; + SW_DBG("rx error, recycling skb %u\n", entry); + } else { + skb_put(skb, pktlen); + + skb->dev = rdev; + skb->protocol = eth_type_trans(skb, rdev); + skb->ip_summed = CHECKSUM_UNNECESSARY; + + dma_cache_wback_inv((unsigned long)skb->data, + skb->len); + +#ifdef CONFIG_ADM5120_SWITCH_NAPI + netif_receive_skb(skb); +#else + netif_rx(skb); +#endif + + rdev->last_rx = jiffies; + rdev->stats.rx_packets++; + rdev->stats.rx_bytes += pktlen; + + rxl_skbuff[entry] = NULL; + done++; + } + } else { + SW_DBG("no rx device, recycling skb %u\n", entry); + } + + cur_rxl++; + if (cur_rxl - dirty_rxl > RX_RING_SIZE / 4) + adm5120_switch_rx_refill(); + } + + adm5120_switch_rx_refill(); + + SW_DBG("rx finished, cur_rxl=%u, dirty_rxl=%u, processed %d\n", + cur_rxl, dirty_rxl, done); + + return done; +} + +static void adm5120_switch_tx(void) +{ + unsigned int entry; + + spin_lock(&tx_lock); + entry = dirty_txl % TX_RING_SIZE; + while (dirty_txl != cur_txl) { + struct dma_desc *desc = &txl_descs[entry]; + struct sk_buff *skb = txl_skbuff[entry]; + + if (desc->buf1 & DESC_OWN) + break; + + if (netif_running(skb->dev)) { + skb->dev->stats.tx_bytes += skb->len; + skb->dev->stats.tx_packets++; + } + + dev_kfree_skb_irq(skb); + txl_skbuff[entry] = NULL; + entry = (++dirty_txl) % TX_RING_SIZE; + } + + if ((cur_txl - dirty_txl) < TX_QUEUE_LEN - 4) { + int i; + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + if (!adm5120_devs[i]) + continue; + netif_wake_queue(adm5120_devs[i]); + } + } + spin_unlock(&tx_lock); +} + +#ifdef CONFIG_ADM5120_SWITCH_NAPI +static int adm5120_if_poll(struct napi_struct *napi, int limit) +{ + struct adm5120_if_priv *priv = container_of(napi, + struct adm5120_if_priv, napi); + struct net_device *dev __maybe_unused = priv->dev; + int done; + u32 status; + + sw_int_ack(SWITCH_INTS_POLL); + + SW_DBG("%s: processing TX ring\n", dev->name); + adm5120_switch_tx(); + + SW_DBG("%s: processing RX ring\n", dev->name); + done = adm5120_switch_rx(limit); + + status = sw_int_status() & SWITCH_INTS_POLL; + if ((done < limit) && (!status)) { + SW_DBG("disable polling mode for %s\n", dev->name); + napi_complete(napi); + sw_int_unmask(SWITCH_INTS_POLL); + return 0; + } + + SW_DBG("%s still in polling mode, done=%d, status=%x\n", + dev->name, done, status); + return 1; +} +#endif /* CONFIG_ADM5120_SWITCH_NAPI */ + + +static irqreturn_t adm5120_switch_irq(int irq, void *dev_id) +{ + u32 status; + + status = sw_int_status(); + status &= SWITCH_INTS_ALL; + if (!status) + return IRQ_NONE; + +#ifdef CONFIG_ADM5120_SWITCH_NAPI + sw_int_ack(status & ~SWITCH_INTS_POLL); + + if (status & SWITCH_INTS_POLL) { + struct net_device *dev = dev_id; + struct adm5120_if_priv *priv = netdev_priv(dev); + + sw_dump_intr_mask("poll ints", status); + SW_DBG("enable polling mode for %s\n", dev->name); + sw_int_mask(SWITCH_INTS_POLL); + napi_schedule(&priv->napi); + } +#else + sw_int_ack(status); + + if (status & (SWITCH_INT_RLD | SWITCH_INT_LDF)) + adm5120_switch_rx(RX_RING_SIZE); + + if (status & SWITCH_INT_SLD) + adm5120_switch_tx(); +#endif + + return IRQ_HANDLED; +} + +static void adm5120_set_bw(char *matrix) +{ + unsigned long val; + + /* Port 0 to 3 are set using the bandwidth control 0 register */ + val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); + sw_write_reg(SWITCH_REG_BW_CNTL0, val); + + /* Port 4 and 5 are set using the bandwidth control 1 register */ + val = matrix[4]; + if (matrix[5] == 1) + sw_write_reg(SWITCH_REG_BW_CNTL1, val | 0x80000000); + else + sw_write_reg(SWITCH_REG_BW_CNTL1, val & ~0x8000000); + + SW_DBG("D: ctl0 0x%ux, ctl1 0x%ux\n", sw_read_reg(SWITCH_REG_BW_CNTL0), + sw_read_reg(SWITCH_REG_BW_CNTL1)); +} + +static void adm5120_switch_tx_ring_reset(struct dma_desc *desc, + struct sk_buff **skbl, int num) +{ + memset(desc, 0, num * sizeof(*desc)); + desc[num-1].buf1 |= DESC_EOR; + memset(skbl, 0, sizeof(struct skb *) * num); + + cur_txl = 0; + dirty_txl = 0; +} + +static void adm5120_switch_rx_ring_reset(struct dma_desc *desc, + struct sk_buff **skbl, int num) +{ + int i; + + memset(desc, 0, num * sizeof(*desc)); + for (i = 0; i < num; i++) { + skbl[i] = dev_alloc_skb(SKB_ALLOC_LEN); + if (!skbl[i]) { + i = num; + break; + } + skb_reserve(skbl[i], SKB_RESERVE_LEN); + adm5120_rx_dma_update(&desc[i], skbl[i], (num - 1 == i)); + } + + cur_rxl = 0; + dirty_rxl = 0; +} + +static int adm5120_switch_tx_ring_alloc(void) +{ + int err; + + txl_descs = dma_alloc_coherent(NULL, TX_DESCS_SIZE, &txl_descs_dma, + GFP_ATOMIC); + if (!txl_descs) { + err = -ENOMEM; + goto err; + } + + txl_skbuff = kzalloc(TX_SKBS_SIZE, GFP_KERNEL); + if (!txl_skbuff) { + err = -ENOMEM; + goto err; + } + + return 0; + +err: + return err; +} + +static void adm5120_switch_tx_ring_free(void) +{ + int i; + + if (txl_skbuff) { + for (i = 0; i < TX_RING_SIZE; i++) + if (txl_skbuff[i]) + kfree_skb(txl_skbuff[i]); + kfree(txl_skbuff); + } + + if (txl_descs) + dma_free_coherent(NULL, TX_DESCS_SIZE, txl_descs, + txl_descs_dma); +} + +static int adm5120_switch_rx_ring_alloc(void) +{ + int err; + int i; + + /* init RX ring */ + rxl_descs = dma_alloc_coherent(NULL, RX_DESCS_SIZE, &rxl_descs_dma, + GFP_ATOMIC); + if (!rxl_descs) { + err = -ENOMEM; + goto err; + } + + rxl_skbuff = kzalloc(RX_SKBS_SIZE, GFP_KERNEL); + if (!rxl_skbuff) { + err = -ENOMEM; + goto err; + } + + for (i = 0; i < RX_RING_SIZE; i++) { + struct sk_buff *skb; + skb = alloc_skb(SKB_ALLOC_LEN, GFP_ATOMIC); + if (!skb) { + err = -ENOMEM; + goto err; + } + rxl_skbuff[i] = skb; + skb_reserve(skb, SKB_RESERVE_LEN); + } + + return 0; + +err: + return err; +} + +static void adm5120_switch_rx_ring_free(void) +{ + int i; + + if (rxl_skbuff) { + for (i = 0; i < RX_RING_SIZE; i++) + if (rxl_skbuff[i]) + kfree_skb(rxl_skbuff[i]); + kfree(rxl_skbuff); + } + + if (rxl_descs) + dma_free_coherent(NULL, RX_DESCS_SIZE, rxl_descs, + rxl_descs_dma); +} + +static void adm5120_write_mac(struct net_device *dev) +{ + struct adm5120_if_priv *priv = netdev_priv(dev); + unsigned char *mac = dev->dev_addr; + u32 t; + + t = mac[2] | (mac[3] << MAC_WT1_MAC3_SHIFT) | + (mac[4] << MAC_WT1_MAC4_SHIFT) | (mac[5] << MAC_WT1_MAC5_SHIFT); + sw_write_reg(SWITCH_REG_MAC_WT1, t); + + t = (mac[0] << MAC_WT0_MAC0_SHIFT) | (mac[1] << MAC_WT0_MAC1_SHIFT) | + MAC_WT0_MAWC | MAC_WT0_WVE | (priv->vlan_no<<3); + + sw_write_reg(SWITCH_REG_MAC_WT0, t); + + while (!(sw_read_reg(SWITCH_REG_MAC_WT0) & MAC_WT0_MWD)) + ; +} + +static void adm5120_set_vlan(char *matrix) +{ + unsigned long val; + int vlan_port, port; + + val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); + sw_write_reg(SWITCH_REG_VLAN_G1, val); + val = matrix[4] + (matrix[5]<<8); + sw_write_reg(SWITCH_REG_VLAN_G2, val); + + /* Now set/update the port vs. device lookup table */ + for (port = 0; port < SWITCH_NUM_PORTS; port++) { + for (vlan_port = 0; vlan_port < SWITCH_NUM_PORTS && !(matrix[vlan_port] & (0x00000001 << port)); vlan_port++) + ; + if (vlan_port < SWITCH_NUM_PORTS) + adm5120_port[port] = adm5120_devs[vlan_port]; + else + adm5120_port[port] = NULL; + } +} + +static void adm5120_switch_set_vlan_mac(unsigned int vlan, unsigned char *mac) +{ + u32 t; + + t = mac[2] | (mac[3] << MAC_WT1_MAC3_SHIFT) + | (mac[4] << MAC_WT1_MAC4_SHIFT) + | (mac[5] << MAC_WT1_MAC5_SHIFT); + sw_write_reg(SWITCH_REG_MAC_WT1, t); + + t = (mac[0] << MAC_WT0_MAC0_SHIFT) | (mac[1] << MAC_WT0_MAC1_SHIFT) | + MAC_WT0_MAWC | MAC_WT0_WVE | (vlan << MAC_WT0_WVN_SHIFT) | + (MAC_WT0_WAF_STATIC << MAC_WT0_WAF_SHIFT); + sw_write_reg(SWITCH_REG_MAC_WT0, t); + + do { + t = sw_read_reg(SWITCH_REG_MAC_WT0); + } while ((t & MAC_WT0_MWD) == 0); +} + +static void adm5120_switch_set_vlan_ports(unsigned int vlan, u32 ports) +{ + unsigned int reg; + u32 t; + + if (vlan < 4) + reg = SWITCH_REG_VLAN_G1; + else { + vlan -= 4; + reg = SWITCH_REG_VLAN_G2; + } + + t = sw_read_reg(reg); + t &= ~(0xFF << (vlan*8)); + t |= (ports << (vlan*8)); + sw_write_reg(reg, t); +} + +/* ------------------------------------------------------------------------ */ + +#ifdef CONFIG_ADM5120_SWITCH_NAPI +static inline void adm5120_if_napi_enable(struct net_device *dev) +{ + struct adm5120_if_priv *priv = netdev_priv(dev); + napi_enable(&priv->napi); +} + +static inline void adm5120_if_napi_disable(struct net_device *dev) +{ + struct adm5120_if_priv *priv = netdev_priv(dev); + napi_disable(&priv->napi); +} +#else +static inline void adm5120_if_napi_enable(struct net_device *dev) {} +static inline void adm5120_if_napi_disable(struct net_device *dev) {} +#endif /* CONFIG_ADM5120_SWITCH_NAPI */ + +static int adm5120_if_open(struct net_device *dev) +{ + u32 t; + int err; + int i; + + adm5120_if_napi_enable(dev); + + err = request_irq(dev->irq, adm5120_switch_irq, IRQF_SHARED, + dev->name, dev); + if (err) { + SW_ERR("unable to get irq for %s\n", dev->name); + goto err; + } + + if (!sw_used++) + /* enable interrupts on first open */ + sw_int_unmask(SWITCH_INTS_USED); + + /* enable (additional) port */ + t = sw_read_reg(SWITCH_REG_PORT_CONF0); + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + if (dev == adm5120_devs[i]) + t &= ~adm5120_eth_vlans[i]; + } + sw_write_reg(SWITCH_REG_PORT_CONF0, t); + + netif_start_queue(dev); + + return 0; + +err: + adm5120_if_napi_disable(dev); + return err; +} + +static int adm5120_if_stop(struct net_device *dev) +{ + u32 t; + int i; + + netif_stop_queue(dev); + adm5120_if_napi_disable(dev); + + /* disable port if not assigned to other devices */ + t = sw_read_reg(SWITCH_REG_PORT_CONF0); + t |= SWITCH_PORTS_NOCPU; + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + if ((dev != adm5120_devs[i]) && netif_running(adm5120_devs[i])) + t &= ~adm5120_eth_vlans[i]; + } + sw_write_reg(SWITCH_REG_PORT_CONF0, t); + + if (!--sw_used) + sw_int_mask(SWITCH_INTS_USED); + + free_irq(dev->irq, dev); + + return 0; +} + +static int adm5120_if_hard_start_xmit(struct sk_buff *skb, + struct net_device *dev) +{ + struct dma_desc *desc; + struct adm5120_if_priv *priv = netdev_priv(dev); + unsigned int entry; + unsigned long data; + int i; + + /* lock switch irq */ + spin_lock_irq(&tx_lock); + + /* calculate the next TX descriptor entry. */ + entry = cur_txl % TX_RING_SIZE; + + desc = &txl_descs[entry]; + if (desc->buf1 & DESC_OWN) { + /* We want to write a packet but the TX queue is still + * occupied by the DMA. We are faster than the DMA... */ + SW_DBG("%s unable to transmit, packet dopped\n", dev->name); + dev_kfree_skb(skb); + dev->stats.tx_dropped++; + return 0; + } + + txl_skbuff[entry] = skb; + data = (desc->buf1 & DESC_EOR); + data |= DESC_ADDR(skb->data); + + desc->misc = + ((skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len) << DESC_PKTLEN_SHIFT) | + (0x1 << priv->vlan_no); + + desc->buflen = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; + + desc->buf1 = data | DESC_OWN; + sw_write_reg(SWITCH_REG_SEND_TRIG, SEND_TRIG_STL); + + cur_txl++; + if (cur_txl == dirty_txl + TX_QUEUE_LEN) { + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + if (!adm5120_devs[i]) + continue; + netif_stop_queue(adm5120_devs[i]); + } + } + + dev->trans_start = jiffies; + + spin_unlock_irq(&tx_lock); + + return 0; +} + +static void adm5120_if_tx_timeout(struct net_device *dev) +{ + SW_INFO("TX timeout on %s\n", dev->name); +} + +static void adm5120_if_set_rx_mode(struct net_device *dev) +{ + struct adm5120_if_priv *priv = netdev_priv(dev); + u32 ports; + u32 t; + + ports = adm5120_eth_vlans[priv->vlan_no] & SWITCH_PORTS_NOCPU; + + t = sw_read_reg(SWITCH_REG_CPUP_CONF); + if (dev->flags & IFF_PROMISC) + /* enable unknown packets */ + t &= ~(ports << CPUP_CONF_DUNP_SHIFT); + else + /* disable unknown packets */ + t |= (ports << CPUP_CONF_DUNP_SHIFT); + + if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || + netdev_mc_count(dev)) + /* enable multicast packets */ + t &= ~(ports << CPUP_CONF_DMCP_SHIFT); + else + /* disable multicast packets */ + t |= (ports << CPUP_CONF_DMCP_SHIFT); + + /* If there is any port configured to be in promiscuous mode, then the */ + /* Bridge Test Mode has to be activated. This will result in */ + /* transporting also packets learned in another VLAN to be forwarded */ + /* to the CPU. */ + /* The difficult scenario is when we want to build a bridge on the CPU.*/ + /* Assume we have port0 and the CPU port in VLAN0 and port1 and the */ + /* CPU port in VLAN1. Now we build a bridge on the CPU between */ + /* VLAN0 and VLAN1. Both ports of the VLANs are set in promisc mode. */ + /* Now assume a packet with ethernet source address 99 enters port 0 */ + /* It will be forwarded to the CPU because it is unknown. Then the */ + /* bridge in the CPU will send it to VLAN1 and it goes out at port 1. */ + /* When now a packet with ethernet destination address 99 comes in at */ + /* port 1 in VLAN1, then the switch has learned that this address is */ + /* located at port 0 in VLAN0. Therefore the switch will drop */ + /* this packet. In order to avoid this and to send the packet still */ + /* to the CPU, the Bridge Test Mode has to be activated. */ + + /* Check if there is any vlan in promisc mode. */ + if (~t & (SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT)) + t |= CPUP_CONF_BTM; /* Enable Bridge Testing Mode */ + else + t &= ~CPUP_CONF_BTM; /* Disable Bridge Testing Mode */ + + sw_write_reg(SWITCH_REG_CPUP_CONF, t); + +} + +static int adm5120_if_set_mac_address(struct net_device *dev, void *p) +{ + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; + + adm5120_write_mac(dev); + return 0; +} + +static int adm5120_if_do_ioctl(struct net_device *dev, struct ifreq *rq, + int cmd) +{ + int err; + struct adm5120_sw_info info; + struct adm5120_if_priv *priv = netdev_priv(dev); + + switch (cmd) { + case SIOCGADMINFO: + info.magic = 0x5120; + info.ports = adm5120_nrdevs; + info.vlan = priv->vlan_no; + err = copy_to_user(rq->ifr_data, &info, sizeof(info)); + if (err) + return -EFAULT; + break; + case SIOCSMATRIX: + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + err = copy_from_user(adm5120_eth_vlans, rq->ifr_data, + sizeof(adm5120_eth_vlans)); + if (err) + return -EFAULT; + adm5120_set_vlan(adm5120_eth_vlans); + break; + case SIOCGMATRIX: + err = copy_to_user(rq->ifr_data, adm5120_eth_vlans, + sizeof(adm5120_eth_vlans)); + if (err) + return -EFAULT; + break; + default: + return -EOPNOTSUPP; + } + return 0; +} + +static const struct net_device_ops adm5120sw_netdev_ops = { + .ndo_open = adm5120_if_open, + .ndo_stop = adm5120_if_stop, + .ndo_start_xmit = adm5120_if_hard_start_xmit, + .ndo_set_rx_mode = adm5120_if_set_rx_mode, + .ndo_do_ioctl = adm5120_if_do_ioctl, + .ndo_tx_timeout = adm5120_if_tx_timeout, + .ndo_validate_addr = eth_validate_addr, + .ndo_change_mtu = eth_change_mtu, + .ndo_set_mac_address = adm5120_if_set_mac_address, +}; + +static struct net_device *adm5120_if_alloc(void) +{ + struct net_device *dev; + struct adm5120_if_priv *priv; + + dev = alloc_etherdev(sizeof(*priv)); + if (!dev) + return NULL; + + priv = netdev_priv(dev); + priv->dev = dev; + + dev->irq = ADM5120_IRQ_SWITCH; + dev->netdev_ops = &adm5120sw_netdev_ops; + dev->watchdog_timeo = TX_TIMEOUT; + +#ifdef CONFIG_ADM5120_SWITCH_NAPI + netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64); +#endif + + return dev; +} + +/* ------------------------------------------------------------------------ */ + +static void adm5120_switch_cleanup(void) +{ + int i; + + /* disable interrupts */ + sw_int_mask(SWITCH_INTS_ALL); + + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + struct net_device *dev = adm5120_devs[i]; + if (dev) { + unregister_netdev(dev); + free_netdev(dev); + } + } + + adm5120_switch_tx_ring_free(); + adm5120_switch_rx_ring_free(); +} + +static int adm5120_switch_probe(struct platform_device *pdev) +{ + u32 t; + int i, err; + + adm5120_nrdevs = adm5120_eth_num_ports; + + t = CPUP_CONF_DCPUP | CPUP_CONF_CRCP | + SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT | + SWITCH_PORTS_NOCPU << CPUP_CONF_DMCP_SHIFT ; + sw_write_reg(SWITCH_REG_CPUP_CONF, t); + + t = (SWITCH_PORTS_NOCPU << PORT_CONF0_EMCP_SHIFT) | + (SWITCH_PORTS_NOCPU << PORT_CONF0_BP_SHIFT) | + (SWITCH_PORTS_NOCPU); + sw_write_reg(SWITCH_REG_PORT_CONF0, t); + + /* setup ports to Autoneg/100M/Full duplex/Auto MDIX */ + t = SWITCH_PORTS_PHY | + (SWITCH_PORTS_PHY << PHY_CNTL2_SC_SHIFT) | + (SWITCH_PORTS_PHY << PHY_CNTL2_DC_SHIFT) | + (SWITCH_PORTS_PHY << PHY_CNTL2_PHYR_SHIFT) | + (SWITCH_PORTS_PHY << PHY_CNTL2_AMDIX_SHIFT) | + PHY_CNTL2_RMAE; + sw_write_reg(SWITCH_REG_PHY_CNTL2, t); + + t = sw_read_reg(SWITCH_REG_PHY_CNTL3); + t |= PHY_CNTL3_RNT; + sw_write_reg(SWITCH_REG_PHY_CNTL3, t); + + /* Force all the packets from all ports are low priority */ + sw_write_reg(SWITCH_REG_PRI_CNTL, 0); + + sw_int_mask(SWITCH_INTS_ALL); + sw_int_ack(SWITCH_INTS_ALL); + + err = adm5120_switch_rx_ring_alloc(); + if (err) + goto err; + + err = adm5120_switch_tx_ring_alloc(); + if (err) + goto err; + + adm5120_switch_tx_ring_reset(txl_descs, txl_skbuff, TX_RING_SIZE); + adm5120_switch_rx_ring_reset(rxl_descs, rxl_skbuff, RX_RING_SIZE); + + sw_write_reg(SWITCH_REG_SHDA, 0); + sw_write_reg(SWITCH_REG_SLDA, KSEG1ADDR(txl_descs)); + sw_write_reg(SWITCH_REG_RHDA, 0); + sw_write_reg(SWITCH_REG_RLDA, KSEG1ADDR(rxl_descs)); + + for (i = 0; i < SWITCH_NUM_PORTS; i++) { + struct net_device *dev; + struct adm5120_if_priv *priv; + + dev = adm5120_if_alloc(); + if (!dev) { + err = -ENOMEM; + goto err; + } + + adm5120_devs[i] = dev; + priv = netdev_priv(dev); + + priv->vlan_no = i; + priv->port_mask = adm5120_eth_vlans[i]; + + memcpy(dev->dev_addr, adm5120_eth_macs[i], 6); + adm5120_write_mac(dev); + + err = register_netdev(dev); + if (err) { + SW_INFO("%s register failed, error=%d\n", + dev->name, err); + goto err; + } + } + + /* setup vlan/port mapping after devs are filled up */ + adm5120_set_vlan(adm5120_eth_vlans); + + /* enable CPU port */ + t = sw_read_reg(SWITCH_REG_CPUP_CONF); + t &= ~CPUP_CONF_DCPUP; + sw_write_reg(SWITCH_REG_CPUP_CONF, t); + + return 0; + +err: + adm5120_switch_cleanup(); + + SW_ERR("init failed\n"); + return err; +} + +static int adm5120_switch_remove(struct platform_device *pdev) +{ + adm5120_switch_cleanup(); + return 0; +} + +static struct platform_driver adm5120_switch_driver = { + .probe = adm5120_switch_probe, + .remove = adm5120_switch_remove, + .driver = { + .name = DRV_NAME, + }, +}; + +/* -------------------------------------------------------------------------- */ + +static int __init adm5120_switch_mod_init(void) +{ + int err; + + pr_info(DRV_DESC " version " DRV_VERSION "\n"); + err = platform_driver_register(&adm5120_switch_driver); + + return err; +} + +static void __exit adm5120_switch_mod_exit(void) +{ + platform_driver_unregister(&adm5120_switch_driver); +} + +module_init(adm5120_switch_mod_init); +module_exit(adm5120_switch_mod_exit); + +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION(DRV_DESC); +MODULE_VERSION(DRV_VERSION); diff --git a/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.h b/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.h new file mode 100644 index 0000000000..fa9e503359 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/net/adm5120sw.h @@ -0,0 +1,23 @@ +/* + * Defines for ADM5120 built in ethernet switch driver + * + * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005 + * + * Values come from ADM5120 datasheet and original ADMtek 2.4 driver, + * Copyright ADMtek Inc. + */ + +#ifndef _INCLUDE_ADM5120SW_H_ +#define _INCLUDE_ADM5120SW_H_ + +#define SIOCSMATRIX SIOCDEVPRIVATE +#define SIOCGMATRIX (SIOCDEVPRIVATE + 1) +#define SIOCGADMINFO (SIOCDEVPRIVATE + 2) + +struct adm5120_sw_info { + u16 magic; + u16 ports; + u16 vlan; +}; + +#endif /* _INCLUDE_ADM5120SW_H_ */ diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-dbg.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-dbg.c new file mode 100644 index 0000000000..2d5dc2a5a7 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-dbg.c @@ -0,0 +1,836 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-dbg.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * 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. + * + */ + +/*-------------------------------------------------------------------------*/ + +static inline char *ed_typestring(int ed_type) +{ + switch (ed_type) { + case PIPE_CONTROL: + return "ctrl"; + case PIPE_BULK: + return "bulk"; + case PIPE_INTERRUPT: + return "intr"; + case PIPE_ISOCHRONOUS: + return "isoc"; + } + return "(bad ed_type)"; +} + +static inline char *ed_statestring(int state) +{ + switch (state) { + case ED_IDLE: + return "IDLE"; + case ED_UNLINK: + return "UNLINK"; + case ED_OPER: + return "OPER"; + } + return "?STATE"; +} + +static inline char *pipestring(int pipe) +{ + return ed_typestring(usb_pipetype(pipe)); +} + +static inline char *td_pidstring(u32 info) +{ + switch (info & TD_DP) { + case TD_DP_SETUP: + return "SETUP"; + case TD_DP_IN: + return "IN"; + case TD_DP_OUT: + return "OUT"; + } + return "?PID"; +} + +static inline char *td_togglestring(u32 info) +{ + switch (info & TD_T) { + case TD_T_DATA0: + return "DATA0"; + case TD_T_DATA1: + return "DATA1"; + case TD_T_CARRY: + return "CARRY"; + } + return "?TOGGLE"; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header + */ +static void __attribute__((unused)) +urb_print(struct admhcd *ahcd, struct urb *urb, char *str, int small, int status) +{ + unsigned int pipe = urb->pipe; + + if (!urb->dev || !urb->dev->bus) { + admhc_dbg(ahcd, "%s URB: no dev", str); + return; + } + +#ifndef ADMHC_VERBOSE_DEBUG + if (status != 0) +#endif + admhc_dbg(ahcd, "URB-%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d " + "stat=%d\n", + str, + urb, + usb_pipedevice(pipe), + usb_pipeendpoint(pipe), + usb_pipeout(pipe) ? "out" : "in", + pipestring(pipe), + urb->transfer_flags, + urb->actual_length, + urb->transfer_buffer_length, + status); + +#ifdef ADMHC_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol(pipe)) { + admhc_dbg(ahcd, "setup(8):"); + for (i = 0; i < 8 ; i++) + printk(KERN_INFO" %02x", ((__u8 *)urb->setup_packet)[i]); + printk(KERN_INFO "\n"); + } + if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { + admhc_dbg(ahcd, "data(%d/%d):", + urb->actual_length, + urb->transfer_buffer_length); + len = usb_pipeout(pipe) ? + urb->transfer_buffer_length : urb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printk(KERN_INFO " %02x", ((__u8 *)urb->transfer_buffer)[i]); + printk(KERN_INFO "%s stat:%d\n", i < len ? "..." : "", status); + } + } +#endif /* ADMHC_VERBOSE_DEBUG */ +} + +#define admhc_dbg_sw(ahcd, next, size, format, arg...) \ + do { \ + if (next) { \ + unsigned s_len; \ + s_len = scnprintf(*next, *size, format, ## arg); \ + *size -= s_len; *next += s_len; \ + } else \ + admhc_dbg(ahcd, format, ## arg); \ + } while (0); + + +static void admhc_dump_intr_mask(struct admhcd *ahcd, char *label, u32 mask, + char **next, unsigned *size) +{ + admhc_dbg_sw(ahcd, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", + label, + mask, + (mask & ADMHC_INTR_INTA) ? " INTA" : "", + (mask & ADMHC_INTR_FATI) ? " FATI" : "", + (mask & ADMHC_INTR_SWI) ? " SWI" : "", + (mask & ADMHC_INTR_TDC) ? " TDC" : "", + (mask & ADMHC_INTR_FNO) ? " FNO" : "", + (mask & ADMHC_INTR_SO) ? " SO" : "", + (mask & ADMHC_INTR_INSM) ? " INSM" : "", + (mask & ADMHC_INTR_BABI) ? " BABI" : "", + (mask & ADMHC_INTR_7) ? " !7!" : "", + (mask & ADMHC_INTR_6) ? " !6!" : "", + (mask & ADMHC_INTR_RESI) ? " RESI" : "", + (mask & ADMHC_INTR_SOFI) ? " SOFI" : "" + ); +} + +static void maybe_print_eds(struct admhcd *ahcd, char *label, u32 value, + char **next, unsigned *size) +{ + if (value) + admhc_dbg_sw(ahcd, next, size, "%s %08x\n", label, value); +} + +static char *buss2string(int state) +{ + switch (state) { + case ADMHC_BUSS_RESET: + return "reset"; + case ADMHC_BUSS_RESUME: + return "resume"; + case ADMHC_BUSS_OPER: + return "operational"; + case ADMHC_BUSS_SUSPEND: + return "suspend"; + } + return "?state"; +} + +static void +admhc_dump_status(struct admhcd *ahcd, char **next, unsigned *size) +{ + struct admhcd_regs __iomem *regs = ahcd->regs; + u32 temp; + + temp = admhc_readl(ahcd, ®s->gencontrol); + admhc_dbg_sw(ahcd, next, size, + "gencontrol 0x%08x%s%s%s%s\n", + temp, + (temp & ADMHC_CTRL_UHFE) ? " UHFE" : "", + (temp & ADMHC_CTRL_SIR) ? " SIR" : "", + (temp & ADMHC_CTRL_DMAA) ? " DMAA" : "", + (temp & ADMHC_CTRL_SR) ? " SR" : "" + ); + + temp = admhc_readl(ahcd, ®s->host_control); + admhc_dbg_sw(ahcd, next, size, + "host_control 0x%08x BUSS=%s%s\n", + temp, + buss2string(temp & ADMHC_HC_BUSS), + (temp & ADMHC_HC_DMAE) ? " DMAE" : "" + ); + + admhc_dump_intr_mask(ahcd, "int_status", + admhc_readl(ahcd, ®s->int_status), + next, size); + admhc_dump_intr_mask(ahcd, "int_enable", + admhc_readl(ahcd, ®s->int_enable), + next, size); + + maybe_print_eds(ahcd, "hosthead", + admhc_readl(ahcd, ®s->hosthead), next, size); +} + +#define dbg_port_sw(hc, num, value, next, size) \ + admhc_dbg_sw(hc, next, size, \ + "portstatus [%d] " \ + "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ + num, temp, \ + (temp & ADMHC_PS_PRSC) ? " PRSC" : "", \ + (temp & ADMHC_PS_OCIC) ? " OCIC" : "", \ + (temp & ADMHC_PS_PSSC) ? " PSSC" : "", \ + (temp & ADMHC_PS_PESC) ? " PESC" : "", \ + (temp & ADMHC_PS_CSC) ? " CSC" : "", \ + \ + (temp & ADMHC_PS_LSDA) ? " LSDA" : "", \ + (temp & ADMHC_PS_PPS) ? " PPS" : "", \ + (temp & ADMHC_PS_PRS) ? " PRS" : "", \ + (temp & ADMHC_PS_POCI) ? " POCI" : "", \ + (temp & ADMHC_PS_PSS) ? " PSS" : "", \ + \ + (temp & ADMHC_PS_PES) ? " PES" : "", \ + (temp & ADMHC_PS_CCS) ? " CCS" : "" \ + ); + + +static void +admhc_dump_roothub( + struct admhcd *ahcd, + int verbose, + char **next, + unsigned *size) +{ + u32 temp, i; + + temp = admhc_read_rhdesc(ahcd); + if (temp == ~(u32)0) + return; + + if (verbose) { + admhc_dbg_sw(ahcd, next, size, + "rhdesc %08x%s%s%s%s%s%s PPCM=%02x%s%s%s%s NUMP=%d(%d)\n", + temp, + (temp & ADMHC_RH_CRWE) ? " CRWE" : "", + (temp & ADMHC_RH_OCIC) ? " OCIC" : "", + (temp & ADMHC_RH_LPSC) ? " LPSC" : "", + (temp & ADMHC_RH_LPSC) ? " DRWE" : "", + (temp & ADMHC_RH_LPSC) ? " OCI" : "", + (temp & ADMHC_RH_LPSC) ? " LPS" : "", + ((temp & ADMHC_RH_PPCM) >> 16), + (temp & ADMHC_RH_NOCP) ? " NOCP" : "", + (temp & ADMHC_RH_OCPM) ? " OCPM" : "", + (temp & ADMHC_RH_NPS) ? " NPS" : "", + (temp & ADMHC_RH_PSM) ? " PSM" : "", + (temp & ADMHC_RH_NUMP), ahcd->num_ports + ); + } + + for (i = 0; i < ahcd->num_ports; i++) { + temp = admhc_read_portstatus(ahcd, i); + dbg_port_sw(ahcd, i, temp, next, size); + } +} + +static void admhc_dump(struct admhcd *ahcd, int verbose) +{ + admhc_dbg(ahcd, "ADMHC ahcd state\n"); + + /* dumps some of the state we know about */ + admhc_dump_status(ahcd, NULL, NULL); + admhc_dbg(ahcd, "current frame #%04x\n", + admhc_frame_no(ahcd)); + + admhc_dump_roothub(ahcd, verbose, NULL, NULL); +} + +static const char data0[] = "DATA0"; +static const char data1[] = "DATA1"; + +static void admhc_dump_td(const struct admhcd *ahcd, const char *label, + const struct td *td) +{ + u32 tmp; + + admhc_dbg(ahcd, "%s td %p; urb %p index %d; hwNextTD %08x\n", + label, td, + td->urb, td->index, + hc32_to_cpup(ahcd, &td->hwNextTD)); + + tmp = hc32_to_cpup(ahcd, &td->hwINFO); + admhc_dbg(ahcd, " status %08x%s CC=%x EC=%d %s %s ISI=%x FN=%x\n", + tmp, + (tmp & TD_OWN) ? " OWN" : "", + TD_CC_GET(tmp), + TD_EC_GET(tmp), + td_togglestring(tmp), + td_pidstring(tmp), + TD_ISI_GET(tmp), + TD_FN_GET(tmp)); + + tmp = hc32_to_cpup(ahcd, &td->hwCBL); + admhc_dbg(ahcd, " dbp %08x; cbl %08x; LEN=%d%s\n", + hc32_to_cpup(ahcd, &td->hwDBP), + tmp, + TD_BL_GET(tmp), + (tmp & TD_IE) ? " IE" : ""); +} + +/* caller MUST own hcd spinlock if verbose is set! */ +static void __attribute__((unused)) +admhc_dump_ed(const struct admhcd *ahcd, const char *label, + const struct ed *ed, int verbose) +{ + u32 tmp = hc32_to_cpu(ahcd, ed->hwINFO); + + admhc_dbg(ahcd, "%s ed %p %s type %s; next ed %08x\n", + label, + ed, ed_statestring(ed->state), ed_typestring(ed->type), + hc32_to_cpup(ahcd, &ed->hwNextED)); + + admhc_dbg(ahcd, " info %08x MAX=%d%s%s%s%s EP=%d DEV=%d\n", tmp, + ED_MPS_GET(tmp), + (tmp & ED_ISO) ? " ISO" : "", + (tmp & ED_SKIP) ? " SKIP" : "", + (tmp & ED_SPEED_FULL) ? " FULL" : " LOW", + (tmp & ED_INT) ? " INT" : "", + ED_EN_GET(tmp), + ED_FA_GET(tmp)); + + tmp = hc32_to_cpup(ahcd, &ed->hwHeadP); + admhc_dbg(ahcd, " tds: head %08x tail %08x %s%s%s\n", + tmp & TD_MASK, + hc32_to_cpup(ahcd, &ed->hwTailP), + (tmp & ED_C) ? data1 : data0, + (tmp & ED_H) ? " HALT" : "", + verbose ? " td list follows" : " (not listing)"); + + if (verbose) { + struct list_head *tmp; + + /* use ed->td_list because HC concurrently modifies + * hwNextTD as it accumulates ed_donelist. + */ + list_for_each(tmp, &ed->td_list) { + struct td *td; + td = list_entry(tmp, struct td, td_list); + admhc_dump_td(ahcd, " ->", td); + } + } +} + +#else /* ifdef DEBUG */ + +static inline void urb_print(struct admhcd *ahcd, struct urb * urb, char * str, + int small, int status) {} +static inline void admhc_dump_ed(const struct admhcd *ahcd, const char *label, + const struct ed *ed, int verbose) {} +static inline void admhc_dump_td(const struct admhcd *ahcd, const char *label, + const struct td *td) {} +static inline void admhc_dump(struct admhcd *ahcd, int verbose) {} + +#undef ADMHC_VERBOSE_DEBUG + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------*/ + +#ifdef STUB_DEBUG_FILES + +static inline void create_debug_files(struct admhcd *bus) { } +static inline void remove_debug_files(struct admhcd *bus) { } + +#else + +static int debug_async_open(struct inode *, struct file *); +static int debug_periodic_open(struct inode *, struct file *); +static int debug_registers_open(struct inode *, struct file *); +static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); +static int debug_close(struct inode *, struct file *); + +static const struct file_operations debug_async_fops = { + .owner = THIS_MODULE, + .open = debug_async_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_periodic_fops = { + .owner = THIS_MODULE, + .open = debug_periodic_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; +static const struct file_operations debug_registers_fops = { + .owner = THIS_MODULE, + .open = debug_registers_open, + .read = debug_output, + .release = debug_close, + .llseek = default_llseek, +}; + +static struct dentry *admhc_debug_root; + +struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ + struct admhcd *ahcd; + struct mutex mutex; /* protect filling of buffer */ + size_t count; /* number of characters filled into buffer */ + char *page; +}; + +static ssize_t +show_list(struct admhcd *ahcd, char *buf, size_t count, struct ed *ed) +{ + unsigned temp; + unsigned size = count; + + if (!ed) + return 0; + + /* dump a snapshot of the bulk or control schedule */ + while (ed) { + u32 info = hc32_to_cpu(ahcd, ed->hwINFO); + u32 headp = hc32_to_cpu(ahcd, ed->hwHeadP); + u32 tailp = hc32_to_cpu(ahcd, ed->hwTailP); + struct list_head *entry; + struct td *td; + + temp = scnprintf(buf, size, + "ed/%p %s %s %cs dev%d ep%d %s%smax %d %08x%s%s %s" + " h:%08x t:%08x", + ed, + ed_statestring(ed->state), + ed_typestring(ed->type), + (info & ED_SPEED_FULL) ? 'f' : 'l', + info & ED_FA_MASK, + (info >> ED_EN_SHIFT) & ED_EN_MASK, + (info & ED_INT) ? "INT " : "", + (info & ED_ISO) ? "ISO " : "", + (info >> ED_MPS_SHIFT) & ED_MPS_MASK , + info, + (info & ED_SKIP) ? " S" : "", + (headp & ED_H) ? " H" : "", + (headp & ED_C) ? data1 : data0, + headp & ED_MASK, tailp); + size -= temp; + buf += temp; + + list_for_each(entry, &ed->td_list) { + u32 dbp, cbl; + + td = list_entry(entry, struct td, td_list); + info = hc32_to_cpup(ahcd, &td->hwINFO); + dbp = hc32_to_cpup(ahcd, &td->hwDBP); + cbl = hc32_to_cpup(ahcd, &td->hwCBL); + + temp = scnprintf(buf, size, + "\n\ttd/%p %s %d %s%scc=%x urb %p (%08x,%08x)", + td, + td_pidstring(info), + TD_BL_GET(cbl), + (info & TD_OWN) ? "" : "DONE ", + (cbl & TD_IE) ? "IE " : "", + TD_CC_GET(info), td->urb, info, cbl); + size -= temp; + buf += temp; + } + + temp = scnprintf(buf, size, "\n"); + size -= temp; + buf += temp; + + ed = ed->ed_next; + } + + return count - size; +} + +static ssize_t fill_async_buffer(struct debug_buffer *buf) +{ + struct admhcd *ahcd; + size_t temp; + unsigned long flags; + + ahcd = buf->ahcd; + + spin_lock_irqsave(&ahcd->lock, flags); + temp = show_list(ahcd, buf->page, PAGE_SIZE, ahcd->ed_head); + spin_unlock_irqrestore(&ahcd->lock, flags); + + return temp; +} + + +#define DBG_SCHED_LIMIT 64 + +static ssize_t fill_periodic_buffer(struct debug_buffer *buf) +{ + struct admhcd *ahcd; + struct ed **seen, *ed; + unsigned long flags; + unsigned temp, size, seen_count; + char *next; + unsigned i; + + seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC); + if (!seen) + return 0; + seen_count = 0; + + ahcd = buf->ahcd; + next = buf->page; + size = PAGE_SIZE; + + temp = scnprintf(next, size, "size = %d\n", NUM_INTS); + size -= temp; + next += temp; + + /* dump a snapshot of the periodic schedule (and load) */ + spin_lock_irqsave(&ahcd->lock, flags); + for (i = 0; i < NUM_INTS; i++) { + ed = ahcd->periodic[i]; + if (!ed) + continue; + + temp = scnprintf(next, size, "%2d [%3d]:", i, ahcd->load[i]); + size -= temp; + next += temp; + + do { + temp = scnprintf(next, size, " ed%d/%p", + ed->interval, ed); + size -= temp; + next += temp; + for (temp = 0; temp < seen_count; temp++) { + if (seen[temp] == ed) + break; + } + + /* show more info the first time around */ + if (temp == seen_count) { + u32 info = hc32_to_cpu(ahcd, ed->hwINFO); + struct list_head *entry; + unsigned qlen = 0; + + /* qlen measured here in TDs, not urbs */ + list_for_each(entry, &ed->td_list) + qlen++; + temp = scnprintf(next, size, + " (%cs dev%d ep%d%s qlen %u" + " max %d %08x%s%s)", + (info & ED_SPEED_FULL) ? 'f' : 'l', + ED_FA_GET(info), + ED_EN_GET(info), + (info & ED_ISO) ? "iso" : "int", + qlen, + ED_MPS_GET(info), + info, + (info & ED_SKIP) ? " K" : "", + (ed->hwHeadP & + cpu_to_hc32(ahcd, ED_H)) ? + " H" : ""); + size -= temp; + next += temp; + + if (seen_count < DBG_SCHED_LIMIT) + seen[seen_count++] = ed; + + ed = ed->ed_next; + + } else { + /* we've seen it and what's after */ + temp = 0; + ed = NULL; + } + + } while (ed); + + temp = scnprintf(next, size, "\n"); + size -= temp; + next += temp; + } + spin_unlock_irqrestore(&ahcd->lock, flags); + kfree(seen); + + return PAGE_SIZE - size; +} + + +#undef DBG_SCHED_LIMIT + +static ssize_t fill_registers_buffer(struct debug_buffer *buf) +{ + struct usb_hcd *hcd; + struct admhcd *ahcd; + struct admhcd_regs __iomem *regs; + unsigned long flags; + unsigned temp, size; + char *next; + u32 rdata; + + ahcd = buf->ahcd; + hcd = admhc_to_hcd(ahcd); + regs = ahcd->regs; + next = buf->page; + size = PAGE_SIZE; + + spin_lock_irqsave(&ahcd->lock, flags); + + /* dump driver info, then registers in spec order */ + + admhc_dbg_sw(ahcd, &next, &size, + "bus %s, device %s\n" + "%s\n" + "%s\n", + hcd->self.controller->bus->name, + dev_name(hcd->self.controller), + hcd->product_desc, + hcd_name); + + if (!HCD_HW_ACCESSIBLE(hcd)) { + size -= scnprintf(next, size, + "SUSPENDED (no register access)\n"); + goto done; + } + + admhc_dump_status(ahcd, &next, &size); + + /* other registers mostly affect frame timings */ + rdata = admhc_readl(ahcd, ®s->fminterval); + temp = scnprintf(next, size, + "fmintvl 0x%08x %sFSLDP=0x%04x FI=0x%04x\n", + rdata, (rdata & ADMHC_SFI_FIT) ? "FIT " : "", + (rdata >> ADMHC_SFI_FSLDP_SHIFT) & ADMHC_SFI_FSLDP_MASK, + rdata & ADMHC_SFI_FI_MASK); + size -= temp; + next += temp; + + rdata = admhc_readl(ahcd, ®s->fmnumber); + temp = scnprintf(next, size, "fmnumber 0x%08x %sFR=0x%04x FN=%04x\n", + rdata, (rdata & ADMHC_SFN_FRT) ? "FRT " : "", + (rdata >> ADMHC_SFN_FR_SHIFT) & ADMHC_SFN_FR_MASK, + rdata & ADMHC_SFN_FN_MASK); + size -= temp; + next += temp; + + /* TODO: use predefined bitmask */ + rdata = admhc_readl(ahcd, ®s->lsthresh); + temp = scnprintf(next, size, "lsthresh 0x%04x\n", + rdata & 0x3fff); + size -= temp; + next += temp; + + temp = scnprintf(next, size, "hub poll timer: %s\n", + admhcd_to_hcd(ahcd)->poll_rh ? "ON" : "OFF"); + size -= temp; + next += temp; + + /* roothub */ + admhc_dump_roothub(ahcd, 1, &next, &size); + +done: + spin_unlock_irqrestore(&ahcd->lock, flags); + return PAGE_SIZE - size; +} + + +static struct debug_buffer *alloc_buffer(struct admhcd *ahcd, + ssize_t (*fill_func)(struct debug_buffer *)) +{ + struct debug_buffer *buf; + + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + + if (buf) { + buf->ahcd = ahcd; + buf->fill_func = fill_func; + mutex_init(&buf->mutex); + } + + return buf; +} + +static int fill_buffer(struct debug_buffer *buf) +{ + int ret = 0; + + if (!buf->page) + buf->page = (char *)get_zeroed_page(GFP_KERNEL); + + if (!buf->page) { + ret = -ENOMEM; + goto out; + } + + ret = buf->fill_func(buf); + + if (ret >= 0) { + buf->count = ret; + ret = 0; + } + +out: + return ret; +} + +static ssize_t debug_output(struct file *file, char __user *user_buf, + size_t len, loff_t *offset) +{ + struct debug_buffer *buf = file->private_data; + int ret = 0; + + mutex_lock(&buf->mutex); + if (buf->count == 0) { + ret = fill_buffer(buf); + if (ret != 0) { + mutex_unlock(&buf->mutex); + goto out; + } + } + mutex_unlock(&buf->mutex); + + ret = simple_read_from_buffer(user_buf, len, offset, + buf->page, buf->count); + +out: + return ret; +} + +static int debug_close(struct inode *inode, struct file *file) +{ + struct debug_buffer *buf = file->private_data; + + if (buf) { + if (buf->page) + free_page((unsigned long)buf->page); + kfree(buf); + } + + return 0; +} + +static int debug_async_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static int debug_periodic_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, + fill_periodic_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static int debug_registers_open(struct inode *inode, struct file *file) +{ + file->private_data = alloc_buffer(inode->i_private, + fill_registers_buffer); + + return file->private_data ? 0 : -ENOMEM; +} + +static inline void create_debug_files(struct admhcd *ahcd) +{ + struct usb_bus *bus = &admhcd_to_hcd(ahcd)->self; + + ahcd->debug_dir = debugfs_create_dir(bus->bus_name, admhc_debug_root); + if (!ahcd->debug_dir) + goto dir_error; + + ahcd->debug_async = debugfs_create_file("async", S_IRUGO, + ahcd->debug_dir, ahcd, + &debug_async_fops); + if (!ahcd->debug_async) + goto async_error; + + ahcd->debug_periodic = debugfs_create_file("periodic", S_IRUGO, + ahcd->debug_dir, ahcd, + &debug_periodic_fops); + if (!ahcd->debug_periodic) + goto periodic_error; + + ahcd->debug_registers = debugfs_create_file("registers", S_IRUGO, + ahcd->debug_dir, ahcd, + &debug_registers_fops); + if (!ahcd->debug_registers) + goto registers_error; + + admhc_dbg(ahcd, "created debug files\n"); + return; + +registers_error: + debugfs_remove(ahcd->debug_periodic); +periodic_error: + debugfs_remove(ahcd->debug_async); +async_error: + debugfs_remove(ahcd->debug_dir); +dir_error: + ahcd->debug_periodic = NULL; + ahcd->debug_async = NULL; + ahcd->debug_dir = NULL; +} + +static inline void remove_debug_files(struct admhcd *ahcd) +{ + debugfs_remove(ahcd->debug_registers); + debugfs_remove(ahcd->debug_periodic); + debugfs_remove(ahcd->debug_async); + debugfs_remove(ahcd->debug_dir); +} + +#endif + +/*-------------------------------------------------------------------------*/ diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-drv.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-drv.c new file mode 100644 index 0000000000..798fd22081 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-drv.c @@ -0,0 +1,228 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-au1xxx.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * (C) Copyright 2002 Hewlett-Packard Company + * + * Written by Christopher Hoover + * Based on fragments of previous driver by Russell King et al. + * + * Modified for LH7A404 from ahcd-sa1111.c + * by Durgesh Pattamatta + * Modified for AMD Alchemy Au1xxx + * by Matt Porter + * + * 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 + +#ifdef DEBUG +#define HCD_DBG(f, a...) printk(KERN_DEBUG "%s: " f, hcd_name, ## a) +#else +#define HCD_DBG(f, a...) do {} while (0) +#endif +#define HCD_ERR(f, a...) printk(KERN_ERR "%s: " f, hcd_name, ## a) +#define HCD_INFO(f, a...) printk(KERN_INFO "%s: " f, hcd_name, ## a) + +/*-------------------------------------------------------------------------*/ + +static int admhc_adm5120_probe(const struct hc_driver *driver, + struct platform_device *dev) +{ + int retval; + struct usb_hcd *hcd; + int irq; + struct resource *regs; + + /* sanity checks */ + regs = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (!regs) { + HCD_DBG("no IOMEM resource found\n"); + return -ENODEV; + } + + irq = platform_get_irq(dev, 0); + if (irq < 0) { + HCD_DBG("no IRQ resource found\n"); + return -ENODEV; + } + + hcd = usb_create_hcd(driver, &dev->dev, "ADM5120"); + if (!hcd) + return -ENOMEM; + + hcd->rsrc_start = regs->start; + hcd->rsrc_len = regs->end - regs->start + 1; + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + HCD_DBG("request_mem_region failed\n"); + retval = -EBUSY; + goto err_dev; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + HCD_DBG("ioremap failed\n"); + retval = -ENOMEM; + goto err_mem; + } + + admhc_hcd_init(hcd_to_admhcd(hcd)); + + retval = usb_add_hcd(hcd, irq, 0); + if (retval) + goto err_io; + + return 0; + +err_io: + iounmap(hcd->regs); +err_mem: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_dev: + usb_put_hcd(hcd); + return retval; +} + + +/* may be called without controller electrically present */ +/* may be called with controller, bus, and devices active */ + +static void admhc_adm5120_remove(struct usb_hcd *hcd, + struct platform_device *dev) +{ + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); +} + +static int admhc_adm5120_start(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + int ret; + + ret = admhc_init(ahcd); + if (ret < 0) { + HCD_ERR("unable to init %s\n", hcd->self.bus_name); + goto err; + } + + ret = admhc_run(ahcd); + if (ret < 0) { + HCD_ERR("unable to run %s\n", hcd->self.bus_name); + goto err_stop; + } + + return 0; + +err_stop: + admhc_stop(hcd); +err: + return ret; +} + +static const struct hc_driver adm5120_hc_driver = { + .description = hcd_name, + .product_desc = "ADM5120 built-in USB 1.1 Host Controller", + .hcd_priv_size = sizeof(struct admhcd), + + /* + * generic hardware linkage + */ + .irq = admhc_irq, + .flags = HCD_USB11 | HCD_MEMORY, + + /* + * basic lifecycle operations + */ + .start = admhc_adm5120_start, + .stop = admhc_stop, + .shutdown = admhc_shutdown, + + /* + * managing i/o requests and associated device resources + */ + .urb_enqueue = admhc_urb_enqueue, + .urb_dequeue = admhc_urb_dequeue, + .endpoint_disable = admhc_endpoint_disable, + + /* + * scheduling support + */ + .get_frame_number = admhc_get_frame_number, + + /* + * root hub support + */ + .hub_status_data = admhc_hub_status_data, + .hub_control = admhc_hub_control, +#ifdef CONFIG_PM + .bus_suspend = admhc_bus_suspend, + .bus_resume = admhc_bus_resume, +#endif + .start_port_reset = admhc_start_port_reset, +}; + +static int usb_hcd_adm5120_probe(struct platform_device *pdev) +{ + int ret; + + ret = admhc_adm5120_probe(&adm5120_hc_driver, pdev); + + return ret; +} + +static int usb_hcd_adm5120_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + admhc_adm5120_remove(hcd, pdev); + + return 0; +} + +#ifdef CONFIG_PM +/* TODO */ +static int usb_hcd_adm5120_suspend(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + + return 0; +} + +static int usb_hcd_adm5120_resume(struct platform_device *dev) +{ + struct usb_hcd *hcd = platform_get_drvdata(dev); + + return 0; +} +#else +#define usb_hcd_adm5120_suspend NULL +#define usb_hcd_adm5120_resume NULL +#endif /* CONFIG_PM */ + +static struct platform_driver usb_hcd_adm5120_driver = { + .probe = usb_hcd_adm5120_probe, + .remove = usb_hcd_adm5120_remove, + .shutdown = usb_hcd_platform_shutdown, + .suspend = usb_hcd_adm5120_suspend, + .resume = usb_hcd_adm5120_resume, + .driver = { + .name = "adm5120-hcd", + .owner = THIS_MODULE, + }, +}; + diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hcd.c new file mode 100644 index 0000000000..f721ec1ff8 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hcd.c @@ -0,0 +1,843 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-hcd.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2004 David Brownell + * + * [ Initialisation is based on Linus' ] + * [ uhci code and gregs ahcd fragments ] + * [ (C) Copyright 1999 Linus Torvalds ] + * [ (C) Copyright 1999 Gregory P. Smith] + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define DRIVER_VERSION "0.27.0" +#define DRIVER_AUTHOR "Gabor Juhos " +#define DRIVER_DESC "ADMtek USB 1.1 Host Controller Driver" + +/*-------------------------------------------------------------------------*/ + +#undef ADMHC_VERBOSE_DEBUG /* not always helpful */ + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR + +#define ADMHC_INTR_INIT \ + (ADMHC_INTR_MIE | ADMHC_INTR_INSM | ADMHC_INTR_FATI \ + | ADMHC_INTR_RESI | ADMHC_INTR_TDC | ADMHC_INTR_BABI) + +/*-------------------------------------------------------------------------*/ + +static const char hcd_name[] = "admhc-hcd"; + +#define STATECHANGE_DELAY msecs_to_jiffies(300) + +#include "adm5120.h" + +static void admhc_dump(struct admhcd *ahcd, int verbose); +static int admhc_init(struct admhcd *ahcd); +static void admhc_stop(struct usb_hcd *hcd); + +#include "adm5120-dbg.c" +#include "adm5120-mem.c" +#include "adm5120-pm.c" +#include "adm5120-hub.c" +#include "adm5120-q.c" + +/*-------------------------------------------------------------------------*/ + +/* + * queue up an urb for anything except the root hub + */ +static int admhc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, + gfp_t mem_flags) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + struct ed *ed; + struct urb_priv *urb_priv; + unsigned int pipe = urb->pipe; + int td_cnt = 0; + unsigned long flags; + int ret = 0; + +#ifdef ADMHC_VERBOSE_DEBUG + spin_lock_irqsave(&ahcd->lock, flags); + urb_print(ahcd, urb, "ENQEUE", usb_pipein(pipe), -EINPROGRESS); + spin_unlock_irqrestore(&ahcd->lock, flags); +#endif + + /* every endpoint has an ed, locate and maybe (re)initialize it */ + ed = ed_get(ahcd, urb->ep, urb->dev, pipe, urb->interval); + if (!ed) + return -ENOMEM; + + /* for the private part of the URB we need the number of TDs */ + switch (ed->type) { + case PIPE_CONTROL: + if (urb->transfer_buffer_length > TD_DATALEN_MAX) + /* td_submit_urb() doesn't yet handle these */ + return -EMSGSIZE; + + /* 1 TD for setup, 1 for ACK, plus ... */ + td_cnt = 2; + /* FALLTHROUGH */ + case PIPE_BULK: + /* one TD for every 4096 Bytes (can be up to 8K) */ + td_cnt += urb->transfer_buffer_length / TD_DATALEN_MAX; + /* ... and for any remaining bytes ... */ + if ((urb->transfer_buffer_length % TD_DATALEN_MAX) != 0) + td_cnt++; + /* ... and maybe a zero length packet to wrap it up */ + if (td_cnt == 0) + td_cnt++; + else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 + && (urb->transfer_buffer_length + % usb_maxpacket(urb->dev, pipe, + usb_pipeout(pipe))) == 0) + td_cnt++; + break; + case PIPE_INTERRUPT: + /* + * for Interrupt IN/OUT transactions, each ED contains + * only 1 TD. + * TODO: check transfer_buffer_length? + */ + td_cnt = 1; + break; + case PIPE_ISOCHRONOUS: + /* number of packets from URB */ + td_cnt = urb->number_of_packets; + break; + } + + urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags); + if (!urb_priv) + return -ENOMEM; + + urb_priv->ed = ed; + + spin_lock_irqsave(&ahcd->lock, flags); + /* don't submit to a dead HC */ + if (!HCD_HW_ACCESSIBLE(hcd)) { + ret = -ENODEV; + goto fail; + } + if (!HC_IS_RUNNING(hcd->state)) { + ret = -ENODEV; + goto fail; + } + + ret = usb_hcd_link_urb_to_ep(hcd, urb); + if (ret) + goto fail; + + /* schedule the ed if needed */ + if (ed->state == ED_IDLE) { + ret = ed_schedule(ahcd, ed); + if (ret < 0) { + usb_hcd_unlink_urb_from_ep(hcd, urb); + goto fail; + } + if (ed->type == PIPE_ISOCHRONOUS) { + u16 frame = admhc_frame_no(ahcd); + + /* delay a few frames before the first TD */ + frame += max_t (u16, 8, ed->interval); + frame &= ~(ed->interval - 1); + frame |= ed->branch; + urb->start_frame = frame; + + /* yes, only URB_ISO_ASAP is supported, and + * urb->start_frame is never used as input. + */ + } + } else if (ed->type == PIPE_ISOCHRONOUS) + urb->start_frame = ed->last_iso + ed->interval; + + /* fill the TDs and link them to the ed; and + * enable that part of the schedule, if needed + * and update count of queued periodic urbs + */ + urb->hcpriv = urb_priv; + td_submit_urb(ahcd, urb); + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1); +#endif + +fail: + if (ret) + urb_priv_free(ahcd, urb_priv); + + spin_unlock_irqrestore(&ahcd->lock, flags); + return ret; +} + +/* + * decouple the URB from the HC queues (TDs, urb_priv); + * reporting is always done + * asynchronously, and we might be dealing with an urb that's + * partially transferred, or an ED with other urbs being unlinked. + */ +static int admhc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, + int status) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + unsigned long flags; + int ret; + + spin_lock_irqsave(&ahcd->lock, flags); + +#ifdef ADMHC_VERBOSE_DEBUG + urb_print(ahcd, urb, "DEQUEUE", 1, status); +#endif + ret = usb_hcd_check_unlink_urb(hcd, urb, status); + if (ret) { + /* Do nothing */ + ; + } else if (HC_IS_RUNNING(hcd->state)) { + struct urb_priv *urb_priv; + + /* Unless an IRQ completed the unlink while it was being + * handed to us, flag it for unlink and giveback, and force + * some upcoming INTR_SF to call finish_unlinks() + */ + urb_priv = urb->hcpriv; + if (urb_priv) { + if (urb_priv->ed->state == ED_OPER) + start_ed_unlink(ahcd, urb_priv->ed); + } + } else { + /* + * with HC dead, we won't respect hc queue pointers + * any more ... just clean up every urb's memory. + */ + if (urb->hcpriv) + finish_urb(ahcd, urb, status); + } + spin_unlock_irqrestore(&ahcd->lock, flags); + + return ret; +} + +/*-------------------------------------------------------------------------*/ + +/* frees config/altsetting state for endpoints, + * including ED memory, dummy TD, and bulk/intr data toggle + */ + +static void admhc_endpoint_disable(struct usb_hcd *hcd, + struct usb_host_endpoint *ep) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + unsigned long flags; + struct ed *ed = ep->hcpriv; + unsigned limit = 1000; + + /* ASSERT: any requests/urbs are being unlinked */ + /* ASSERT: nobody can be submitting urbs for this any more */ + + if (!ed) + return; + +#ifdef ADMHC_VERBOSE_DEBUG + spin_lock_irqsave(&ahcd->lock, flags); + admhc_dump_ed(ahcd, "EP-DISABLE", ed, 1); + spin_unlock_irqrestore(&ahcd->lock, flags); +#endif + +rescan: + spin_lock_irqsave(&ahcd->lock, flags); + + if (!HC_IS_RUNNING(hcd->state)) { +sanitize: + ed->state = ED_IDLE; + finish_unlinks(ahcd, 0); + } + + switch (ed->state) { + case ED_UNLINK: /* wait for hw to finish? */ + /* major IRQ delivery trouble loses INTR_SOFI too... */ + if (limit-- == 0) { + admhc_warn(ahcd, "IRQ INTR_SOFI lossage\n"); + goto sanitize; + } + spin_unlock_irqrestore(&ahcd->lock, flags); + schedule_timeout_uninterruptible(1); + goto rescan; + case ED_IDLE: /* fully unlinked */ + if (list_empty(&ed->td_list)) { + td_free(ahcd, ed->dummy); + ed_free(ahcd, ed); + break; + } + /* else FALL THROUGH */ + default: + /* caller was supposed to have unlinked any requests; + * that's not our job. can't recover; must leak ed. + */ + admhc_err(ahcd, "leak ed %p (#%02x) state %d%s\n", + ed, ep->desc.bEndpointAddress, ed->state, + list_empty(&ed->td_list) ? "" : " (has tds)"); + td_free(ahcd, ed->dummy); + break; + } + + ep->hcpriv = NULL; + + spin_unlock_irqrestore(&ahcd->lock, flags); +} + +static int admhc_get_frame_number(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + + return admhc_frame_no(ahcd); +} + +static void admhc_usb_reset(struct admhcd *ahcd) +{ +#if 0 + ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); + ahcd->hc_control &= OHCI_CTRL_RWC; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->regs->control); +#else + /* FIXME */ + ahcd->host_control = ADMHC_BUSS_RESET; + admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); +#endif +} + +/* admhc_shutdown forcibly disables IRQs and DMA, helping kexec and + * other cases where the next software may expect clean state from the + * "firmware". this is bus-neutral, unlike shutdown() methods. + */ +static void +admhc_shutdown(struct usb_hcd *hcd) +{ + struct admhcd *ahcd; + + ahcd = hcd_to_admhcd(hcd); + admhc_intr_disable(ahcd, ADMHC_INTR_MIE); + admhc_dma_disable(ahcd); + admhc_usb_reset(ahcd); + /* flush the writes */ + admhc_writel_flush(ahcd); +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +static void admhc_eds_cleanup(struct admhcd *ahcd) +{ + if (ahcd->ed_tails[PIPE_INTERRUPT]) { + ed_free(ahcd, ahcd->ed_tails[PIPE_INTERRUPT]); + ahcd->ed_tails[PIPE_INTERRUPT] = NULL; + } + + if (ahcd->ed_tails[PIPE_ISOCHRONOUS]) { + ed_free(ahcd, ahcd->ed_tails[PIPE_ISOCHRONOUS]); + ahcd->ed_tails[PIPE_ISOCHRONOUS] = NULL; + } + + if (ahcd->ed_tails[PIPE_CONTROL]) { + ed_free(ahcd, ahcd->ed_tails[PIPE_CONTROL]); + ahcd->ed_tails[PIPE_CONTROL] = NULL; + } + + if (ahcd->ed_tails[PIPE_BULK]) { + ed_free(ahcd, ahcd->ed_tails[PIPE_BULK]); + ahcd->ed_tails[PIPE_BULK] = NULL; + } + + ahcd->ed_head = NULL; +} + +#define ED_DUMMY_INFO (ED_SPEED_FULL | ED_SKIP) + +static int admhc_eds_init(struct admhcd *ahcd) +{ + struct ed *ed; + + ed = ed_create(ahcd, PIPE_INTERRUPT, ED_DUMMY_INFO); + if (!ed) + goto err; + + ahcd->ed_tails[PIPE_INTERRUPT] = ed; + + ed = ed_create(ahcd, PIPE_ISOCHRONOUS, ED_DUMMY_INFO); + if (!ed) + goto err; + + ahcd->ed_tails[PIPE_ISOCHRONOUS] = ed; + ed->ed_prev = ahcd->ed_tails[PIPE_INTERRUPT]; + ahcd->ed_tails[PIPE_INTERRUPT]->ed_next = ed; + ahcd->ed_tails[PIPE_INTERRUPT]->hwNextED = cpu_to_hc32(ahcd, ed->dma); + + ed = ed_create(ahcd, PIPE_CONTROL, ED_DUMMY_INFO); + if (!ed) + goto err; + + ahcd->ed_tails[PIPE_CONTROL] = ed; + ed->ed_prev = ahcd->ed_tails[PIPE_ISOCHRONOUS]; + ahcd->ed_tails[PIPE_ISOCHRONOUS]->ed_next = ed; + ahcd->ed_tails[PIPE_ISOCHRONOUS]->hwNextED = cpu_to_hc32(ahcd, ed->dma); + + ed = ed_create(ahcd, PIPE_BULK, ED_DUMMY_INFO); + if (!ed) + goto err; + + ahcd->ed_tails[PIPE_BULK] = ed; + ed->ed_prev = ahcd->ed_tails[PIPE_CONTROL]; + ahcd->ed_tails[PIPE_CONTROL]->ed_next = ed; + ahcd->ed_tails[PIPE_CONTROL]->hwNextED = cpu_to_hc32(ahcd, ed->dma); + + ahcd->ed_head = ahcd->ed_tails[PIPE_INTERRUPT]; + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "ed intr", ahcd->ed_tails[PIPE_INTERRUPT], 1); + admhc_dump_ed(ahcd, "ed isoc", ahcd->ed_tails[PIPE_ISOCHRONOUS], 1); + admhc_dump_ed(ahcd, "ed ctrl", ahcd->ed_tails[PIPE_CONTROL], 1); + admhc_dump_ed(ahcd, "ed bulk", ahcd->ed_tails[PIPE_BULK], 1); +#endif + + return 0; + +err: + admhc_eds_cleanup(ahcd); + return -ENOMEM; +} + +/* init memory, and kick BIOS/SMM off */ + +static int admhc_init(struct admhcd *ahcd) +{ + struct usb_hcd *hcd = admhcd_to_hcd(ahcd); + int ret; + + admhc_disable(ahcd); + ahcd->regs = hcd->regs; + + /* Disable HC interrupts */ + admhc_intr_disable(ahcd, ADMHC_INTR_MIE); + + /* Read the number of ports unless overridden */ + if (ahcd->num_ports == 0) + ahcd->num_ports = admhc_read_rhdesc(ahcd) & ADMHC_RH_NUMP; + + ret = admhc_mem_init(ahcd); + if (ret) + goto err; + + /* init dummy endpoints */ + ret = admhc_eds_init(ahcd); + if (ret) + goto err; + + create_debug_files(ahcd); + + return 0; + +err: + admhc_stop(hcd); + return ret; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * resets USB and controller + * enable interrupts + */ +static int admhc_run(struct admhcd *ahcd) +{ + u32 val; + int first = ahcd->fminterval == 0; + struct usb_hcd *hcd = admhcd_to_hcd(ahcd); + + admhc_disable(ahcd); + + /* boot firmware should have set this up (5.1.1.3.1) */ + if (first) { + val = admhc_readl(ahcd, &ahcd->regs->fminterval); + ahcd->fminterval = val & ADMHC_SFI_FI_MASK; + if (ahcd->fminterval != FI) + admhc_dbg(ahcd, "fminterval delta %d\n", + ahcd->fminterval - FI); + ahcd->fminterval |= + (FSLDP(ahcd->fminterval) << ADMHC_SFI_FSLDP_SHIFT); + /* also: power/overcurrent flags in rhdesc */ + } + +#if 0 /* TODO: not applicable */ + /* Reset USB nearly "by the book". RemoteWakeupConnected has + * to be checked in case boot firmware (BIOS/SMM/...) has set up + * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). + * If the bus glue detected wakeup capability then it should + * already be enabled; if so we'll just enable it again. + */ + if ((ahcd->hc_control & OHCI_CTRL_RWC) != 0) + device_set_wakeup_capable(hcd->self.controller, 1); +#endif + + switch (ahcd->host_control & ADMHC_HC_BUSS) { + case ADMHC_BUSS_OPER: + val = 0; + break; + case ADMHC_BUSS_SUSPEND: + /* FALLTHROUGH ? */ + case ADMHC_BUSS_RESUME: + ahcd->host_control = ADMHC_BUSS_RESUME; + val = 10 /* msec wait */; + break; + /* case ADMHC_BUSS_RESET: */ + default: + ahcd->host_control = ADMHC_BUSS_RESET; + val = 50 /* msec wait */; + break; + } + admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); + + /* flush the writes */ + admhc_writel_flush(ahcd); + + msleep(val); + val = admhc_read_rhdesc(ahcd); + if (!(val & ADMHC_RH_NPS)) { + /* power down each port */ + for (val = 0; val < ahcd->num_ports; val++) + admhc_write_portstatus(ahcd, val, ADMHC_PS_CPP); + } + /* flush those writes */ + admhc_writel_flush(ahcd); + + /* 2msec timelimit here means no irqs/preempt */ + spin_lock_irq(&ahcd->lock); + + admhc_writel(ahcd, ADMHC_CTRL_SR, &ahcd->regs->gencontrol); + val = 30; /* ... allow extra time */ + while ((admhc_readl(ahcd, &ahcd->regs->gencontrol) & ADMHC_CTRL_SR) != 0) { + if (--val == 0) { + spin_unlock_irq(&ahcd->lock); + admhc_err(ahcd, "USB HC reset timed out!\n"); + return -1; + } + udelay(1); + } + + /* enable HOST mode, before access any host specific register */ + admhc_writel(ahcd, ADMHC_CTRL_UHFE, &ahcd->regs->gencontrol); + + /* Tell the controller where the descriptor list is */ + admhc_writel(ahcd, (u32)ahcd->ed_head->dma, &ahcd->regs->hosthead); + + periodic_reinit(ahcd); + + /* use rhsc irqs after khubd is fully initialized */ + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + hcd->uses_new_polling = 1; + +#if 0 + /* wake on ConnectStatusChange, matching external hubs */ + admhc_writel(ahcd, RH_HS_DRWE, &ahcd->regs->roothub.status); +#else + /* FIXME roothub_write_status (ahcd, ADMHC_RH_DRWE); */ +#endif + + /* Choose the interrupts we care about now, others later on demand */ + admhc_intr_ack(ahcd, ~0); + admhc_intr_enable(ahcd, ADMHC_INTR_INIT); + + admhc_writel(ahcd, ADMHC_RH_NPS | ADMHC_RH_LPSC, &ahcd->regs->rhdesc); + + /* flush those writes */ + admhc_writel_flush(ahcd); + + /* start controller operations */ + ahcd->host_control = ADMHC_BUSS_OPER; + admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); + + val = 20; + while ((admhc_readl(ahcd, &ahcd->regs->host_control) + & ADMHC_HC_BUSS) != ADMHC_BUSS_OPER) { + if (--val == 0) { + spin_unlock_irq(&ahcd->lock); + admhc_err(ahcd, "unable to setup operational mode!\n"); + return -1; + } + mdelay(1); + } + + hcd->state = HC_STATE_RUNNING; + + ahcd->next_statechange = jiffies + STATECHANGE_DELAY; + +#if 0 + /* FIXME: enabling DMA is always failed here for an unknown reason */ + admhc_dma_enable(ahcd); + + val = 200; + while ((admhc_readl(ahcd, &ahcd->regs->host_control) + & ADMHC_HC_DMAE) != ADMHC_HC_DMAE) { + if (--val == 0) { + spin_unlock_irq(&ahcd->lock); + admhc_err(ahcd, "unable to enable DMA!\n"); + admhc_dump(ahcd, 1); + return -1; + } + mdelay(1); + } + +#endif + + spin_unlock_irq(&ahcd->lock); + + mdelay(ADMHC_POTPGT); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static irqreturn_t admhc_irq(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + struct admhcd_regs __iomem *regs = ahcd->regs; + u32 ints; + + ints = admhc_readl(ahcd, ®s->int_status); + if ((ints & ADMHC_INTR_INTA) == 0) { + /* no unmasked interrupt status is set */ + return IRQ_NONE; + } + + ints &= admhc_readl(ahcd, ®s->int_enable); + + if (ints & ADMHC_INTR_FATI) { + /* e.g. due to PCI Master/Target Abort */ + admhc_disable(ahcd); + admhc_err(ahcd, "Fatal Error, controller disabled\n"); + admhc_dump(ahcd, 1); + admhc_usb_reset(ahcd); + } + + if (ints & ADMHC_INTR_BABI) { + admhc_intr_disable(ahcd, ADMHC_INTR_BABI); + admhc_intr_ack(ahcd, ADMHC_INTR_BABI); + admhc_err(ahcd, "Babble Detected\n"); + } + + if (ints & ADMHC_INTR_INSM) { + admhc_vdbg(ahcd, "Root Hub Status Change\n"); + ahcd->next_statechange = jiffies + STATECHANGE_DELAY; + admhc_intr_ack(ahcd, ADMHC_INTR_RESI | ADMHC_INTR_INSM); + + /* NOTE: Vendors didn't always make the same implementation + * choices for RHSC. Many followed the spec; RHSC triggers + * on an edge, like setting and maybe clearing a port status + * change bit. With others it's level-triggered, active + * until khubd clears all the port status change bits. We'll + * always disable it here and rely on polling until khubd + * re-enables it. + */ + admhc_intr_disable(ahcd, ADMHC_INTR_INSM); + usb_hcd_poll_rh_status(hcd); + } else if (ints & ADMHC_INTR_RESI) { + /* For connect and disconnect events, we expect the controller + * to turn on RHSC along with RD. But for remote wakeup events + * this might not happen. + */ + admhc_vdbg(ahcd, "Resume Detect\n"); + admhc_intr_ack(ahcd, ADMHC_INTR_RESI); + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + if (ahcd->autostop) { + spin_lock(&ahcd->lock); + admhc_rh_resume(ahcd); + spin_unlock(&ahcd->lock); + } else + usb_hcd_resume_root_hub(hcd); + } + + if (ints & ADMHC_INTR_TDC) { + admhc_vdbg(ahcd, "Transfer Descriptor Complete\n"); + admhc_intr_ack(ahcd, ADMHC_INTR_TDC); + if (HC_IS_RUNNING(hcd->state)) + admhc_intr_disable(ahcd, ADMHC_INTR_TDC); + spin_lock(&ahcd->lock); + admhc_td_complete(ahcd); + spin_unlock(&ahcd->lock); + if (HC_IS_RUNNING(hcd->state)) + admhc_intr_enable(ahcd, ADMHC_INTR_TDC); + } + + if (ints & ADMHC_INTR_SO) { + /* could track INTR_SO to reduce available PCI/... bandwidth */ + admhc_vdbg(ahcd, "Schedule Overrun\n"); + } + +#if 1 + spin_lock(&ahcd->lock); + if (ahcd->ed_rm_list) + finish_unlinks(ahcd, admhc_frame_no(ahcd)); + + if ((ints & ADMHC_INTR_SOFI) != 0 && !ahcd->ed_rm_list + && HC_IS_RUNNING(hcd->state)) + admhc_intr_disable(ahcd, ADMHC_INTR_SOFI); + spin_unlock(&ahcd->lock); +#else + if (ints & ADMHC_INTR_SOFI) { + admhc_vdbg(ahcd, "Start Of Frame\n"); + spin_lock(&ahcd->lock); + + /* handle any pending ED removes */ + finish_unlinks(ahcd, admhc_frameno(ahcd)); + + /* leaving INTR_SOFI enabled when there's still unlinking + * to be done in the (next frame). + */ + if ((ahcd->ed_rm_list == NULL) || + HC_IS_RUNNING(hcd->state) == 0) + /* + * disable INTR_SOFI if there are no unlinking to be + * done (in the next frame) + */ + admhc_intr_disable(ahcd, ADMHC_INTR_SOFI); + + spin_unlock(&ahcd->lock); + } +#endif + + if (HC_IS_RUNNING(hcd->state)) { + admhc_intr_ack(ahcd, ints); + admhc_intr_enable(ahcd, ADMHC_INTR_MIE); + admhc_writel_flush(ahcd); + } + + return IRQ_HANDLED; +} + +/*-------------------------------------------------------------------------*/ + +static void admhc_stop(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + + admhc_dump(ahcd, 1); + + flush_scheduled_work(); + + admhc_usb_reset(ahcd); + admhc_intr_disable(ahcd, ADMHC_INTR_MIE); + + free_irq(hcd->irq, hcd); + hcd->irq = -1; + + remove_debug_files(ahcd); + admhc_eds_cleanup(ahcd); + admhc_mem_cleanup(ahcd); +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_ADM5120 +#include "adm5120-drv.c" +#define PLATFORM_DRIVER usb_hcd_adm5120_driver +#endif + +#if !defined(PLATFORM_DRIVER) +#error "missing bus glue for admhc-hcd" +#endif + +#define DRIVER_INFO DRIVER_DESC " version " DRIVER_VERSION + +static int __init admhc_hcd_mod_init(void) +{ + int ret = 0; + + if (usb_disabled()) + return -ENODEV; + + pr_info("%s: " DRIVER_INFO "\n", hcd_name); + pr_info("%s: block sizes: ed %Zd td %Zd\n", hcd_name, + sizeof(struct ed), sizeof(struct td)); + set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + +#ifdef DEBUG + admhc_debug_root = debugfs_create_dir("admhc", usb_debug_root); + if (!admhc_debug_root) { + ret = -ENOENT; + goto error_debug; + } +#endif + +#ifdef PLATFORM_DRIVER + ret = platform_driver_register(&PLATFORM_DRIVER); + if (ret < 0) + goto error_platform; +#endif + + return ret; + +#ifdef PLATFORM_DRIVER + platform_driver_unregister(&PLATFORM_DRIVER); +error_platform: +#endif + +#ifdef DEBUG + debugfs_remove(admhc_debug_root); + admhc_debug_root = NULL; +error_debug: +#endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); + return ret; +} +module_init(admhc_hcd_mod_init); + +static void __exit admhc_hcd_mod_exit(void) +{ + platform_driver_unregister(&PLATFORM_DRIVER); +#ifdef DEBUG + debugfs_remove(admhc_debug_root); +#endif + clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); +} +module_exit(admhc_hcd_mod_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_INFO); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hub.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hub.c new file mode 100644 index 0000000000..8cabaf902d --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-hub.c @@ -0,0 +1,430 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-hub.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2004 David Brownell + * + * 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. + * + */ + +/*-------------------------------------------------------------------------*/ + +/* + * ADM5120 Root Hub ... the nonsharable stuff + */ + +#define dbg_port(hc, label, num, value) \ + admhc_dbg(hc, \ + "%s port%d " \ + "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ + label, num, value, \ + (value & ADMHC_PS_PRSC) ? " PRSC" : "", \ + (value & ADMHC_PS_OCIC) ? " OCIC" : "", \ + (value & ADMHC_PS_PSSC) ? " PSSC" : "", \ + (value & ADMHC_PS_PESC) ? " PESC" : "", \ + (value & ADMHC_PS_CSC) ? " CSC" : "", \ + \ + (value & ADMHC_PS_LSDA) ? " LSDA" : "", \ + (value & ADMHC_PS_PPS) ? " PPS" : "", \ + (value & ADMHC_PS_PRS) ? " PRS" : "", \ + (value & ADMHC_PS_POCI) ? " POCI" : "", \ + (value & ADMHC_PS_PSS) ? " PSS" : "", \ + \ + (value & ADMHC_PS_PES) ? " PES" : "", \ + (value & ADMHC_PS_CCS) ? " CCS" : "" \ + ); + +#define dbg_port_write(hc, label, num, value) \ + admhc_dbg(hc, \ + "%s port%d " \ + "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ + label, num, value, \ + (value & ADMHC_PS_PRSC) ? " PRSC" : "", \ + (value & ADMHC_PS_OCIC) ? " OCIC" : "", \ + (value & ADMHC_PS_PSSC) ? " PSSC" : "", \ + (value & ADMHC_PS_PESC) ? " PESC" : "", \ + (value & ADMHC_PS_CSC) ? " CSC" : "", \ + \ + (value & ADMHC_PS_CPP) ? " CPP" : "", \ + (value & ADMHC_PS_SPP) ? " SPP" : "", \ + (value & ADMHC_PS_SPR) ? " SPR" : "", \ + (value & ADMHC_PS_CPS) ? " CPS" : "", \ + (value & ADMHC_PS_SPS) ? " SPS" : "", \ + \ + (value & ADMHC_PS_SPE) ? " SPE" : "", \ + (value & ADMHC_PS_CPE) ? " CPE" : "" \ + ); + +/*-------------------------------------------------------------------------*/ + +/* build "status change" packet (one or two bytes) from HC registers */ + +static int +admhc_hub_status_data(struct usb_hcd *hcd, char *buf) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + int i, changed = 0, length = 1; + int any_connected = 0; + unsigned long flags; + u32 status; + + spin_lock_irqsave(&ahcd->lock, flags); + if (!HCD_HW_ACCESSIBLE(hcd)) + goto done; + + /* init status */ + status = admhc_read_rhdesc(ahcd); + if (status & (ADMHC_RH_LPSC | ADMHC_RH_OCIC)) + buf[0] = changed = 1; + else + buf[0] = 0; + if (ahcd->num_ports > 7) { + buf[1] = 0; + length++; + } + + /* look at each port */ + for (i = 0; i < ahcd->num_ports; i++) { + status = admhc_read_portstatus(ahcd, i); + + /* can't autostop if ports are connected */ + any_connected |= (status & ADMHC_PS_CCS); + + if (status & (ADMHC_PS_CSC | ADMHC_PS_PESC | ADMHC_PS_PSSC + | ADMHC_PS_OCIC | ADMHC_PS_PRSC)) { + changed = 1; + if (i < 7) + buf[0] |= 1 << (i + 1); + else + buf[1] |= 1 << (i - 7); + } + } + + if (admhc_root_hub_state_changes(ahcd, changed, + any_connected)) + set_bit(HCD_FLAG_POLL_RH, &hcd->flags); + else + clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); + +done: + spin_unlock_irqrestore(&ahcd->lock, flags); + + return changed ? length : 0; +} + +/*-------------------------------------------------------------------------*/ + +static int admhc_get_hub_descriptor(struct admhcd *ahcd, char *buf) +{ + struct usb_hub_descriptor *desc = (struct usb_hub_descriptor *)buf; + u32 rh = admhc_read_rhdesc(ahcd); + u16 temp; + + desc->bDescriptorType = USB_DT_HUB; /* Hub-descriptor */ + desc->bPwrOn2PwrGood = ADMHC_POTPGT/2; /* use default value */ + desc->bHubContrCurrent = 0x00; /* 0mA */ + + desc->bNbrPorts = ahcd->num_ports; + temp = 1 + (ahcd->num_ports / 8); + desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp; + + /* FIXME */ + temp = 0; + if (rh & ADMHC_RH_NPS) /* no power switching? */ + temp |= 0x0002; + if (rh & ADMHC_RH_PSM) /* per-port power switching? */ + temp |= 0x0001; + if (rh & ADMHC_RH_NOCP) /* no overcurrent reporting? */ + temp |= 0x0010; + else if (rh & ADMHC_RH_OCPM) /* per-port overcurrent reporting? */ + temp |= 0x0008; + desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ahcd, temp); + + /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + desc->u.hs.DeviceRemovable[0] = 0; + desc->u.hs.DeviceRemovable[0] = ~0; + + return 0; +} + +static int admhc_get_hub_status(struct admhcd *ahcd, char *buf) +{ + struct usb_hub_status *hs = (struct usb_hub_status *)buf; + u32 t = admhc_read_rhdesc(ahcd); + u16 status, change; + + status = 0; + status |= (t & ADMHC_RH_LPS) ? HUB_STATUS_LOCAL_POWER : 0; + status |= (t & ADMHC_RH_OCI) ? HUB_STATUS_OVERCURRENT : 0; + + change = 0; + change |= (t & ADMHC_RH_LPSC) ? HUB_CHANGE_LOCAL_POWER : 0; + change |= (t & ADMHC_RH_OCIC) ? HUB_CHANGE_OVERCURRENT : 0; + + hs->wHubStatus = (__force __u16)cpu_to_hc16(ahcd, status); + hs->wHubChange = (__force __u16)cpu_to_hc16(ahcd, change); + + return 0; +} + +static int admhc_get_port_status(struct admhcd *ahcd, unsigned port, char *buf) +{ + struct usb_port_status *ps = (struct usb_port_status *)buf; + u32 t = admhc_read_portstatus(ahcd, port); + u16 status, change; + + status = 0; + status |= (t & ADMHC_PS_CCS) ? USB_PORT_STAT_CONNECTION : 0; + status |= (t & ADMHC_PS_PES) ? USB_PORT_STAT_ENABLE : 0; + status |= (t & ADMHC_PS_PSS) ? USB_PORT_STAT_SUSPEND : 0; + status |= (t & ADMHC_PS_POCI) ? USB_PORT_STAT_OVERCURRENT : 0; + status |= (t & ADMHC_PS_PRS) ? USB_PORT_STAT_RESET : 0; + status |= (t & ADMHC_PS_PPS) ? USB_PORT_STAT_POWER : 0; + status |= (t & ADMHC_PS_LSDA) ? USB_PORT_STAT_LOW_SPEED : 0; + + change = 0; + change |= (t & ADMHC_PS_CSC) ? USB_PORT_STAT_C_CONNECTION : 0; + change |= (t & ADMHC_PS_PESC) ? USB_PORT_STAT_C_ENABLE : 0; + change |= (t & ADMHC_PS_PSSC) ? USB_PORT_STAT_C_SUSPEND : 0; + change |= (t & ADMHC_PS_OCIC) ? USB_PORT_STAT_C_OVERCURRENT : 0; + change |= (t & ADMHC_PS_PRSC) ? USB_PORT_STAT_C_RESET : 0; + + ps->wPortStatus = (__force __u16)cpu_to_hc16(ahcd, status); + ps->wPortChange = (__force __u16)cpu_to_hc16(ahcd, change); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef CONFIG_USB_OTG + +static int admhc_start_port_reset(struct usb_hcd *hcd, unsigned port) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + u32 status; + + if (!port) + return -EINVAL; + port--; + + /* start port reset before HNP protocol times out */ + status = admhc_read_portstatus(ahcd, port); + if (!(status & ADMHC_PS_CCS)) + return -ENODEV; + + /* khubd will finish the reset later */ + admhc_write_portstatus(ahcd, port, ADMHC_PS_PRS); + return 0; +} + +static void start_hnp(struct admhcd *ahcd); + +#else + +#define admhc_start_port_reset NULL + +#endif + +/*-------------------------------------------------------------------------*/ + + +/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling, + * not necessarily continuous ... to guard against resume signaling. + * The short timeout is safe for non-root hubs, and is backward-compatible + * with earlier Linux hosts. + */ +#ifdef CONFIG_USB_SUSPEND +#define PORT_RESET_MSEC 50 +#else +#define PORT_RESET_MSEC 10 +#endif + +/* this timer value might be vendor-specific ... */ +#define PORT_RESET_HW_MSEC 10 + +/* wrap-aware logic morphed from */ +#define tick_before(t1, t2) ((s16)(((s16)(t1)) - ((s16)(t2))) < 0) + +/* called from some task, normally khubd */ +static inline int admhc_port_reset(struct admhcd *ahcd, unsigned port) +{ + u32 t; + + admhc_vdbg(ahcd, "reset port%d\n", port); + t = admhc_read_portstatus(ahcd, port); + if (!(t & ADMHC_PS_CCS)) + return -ENODEV; + + admhc_write_portstatus(ahcd, port, ADMHC_PS_SPR); + mdelay(10); + admhc_write_portstatus(ahcd, port, (ADMHC_PS_SPE | ADMHC_PS_CSC)); + mdelay(100); + + return 0; +} + +static inline int admhc_port_enable(struct admhcd *ahcd, unsigned port) +{ + u32 t; + + admhc_vdbg(ahcd, "enable port%d\n", port); + t = admhc_read_portstatus(ahcd, port); + if (!(t & ADMHC_PS_CCS)) + return -ENODEV; + + admhc_write_portstatus(ahcd, port, ADMHC_PS_SPE); + + return 0; +} + +static inline int admhc_port_disable(struct admhcd *ahcd, unsigned port) +{ + u32 t; + + admhc_vdbg(ahcd, "disable port%d\n", port); + t = admhc_read_portstatus(ahcd, port); + if (!(t & ADMHC_PS_CCS)) + return -ENODEV; + + admhc_write_portstatus(ahcd, port, ADMHC_PS_CPE); + + return 0; +} + +static inline int admhc_port_write(struct admhcd *ahcd, unsigned port, + u32 val) +{ +#ifdef ADMHC_VERBOSE_DEBUG + dbg_port_write(ahcd, "write", port, val); +#endif + admhc_write_portstatus(ahcd, port, val); + + return 0; +} + +static int admhc_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, + u16 wIndex, char *buf, u16 wLength) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + int ports = ahcd->num_ports; + int ret = 0; + + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) + return -ESHUTDOWN; + + switch (typeReq) { + case ClearHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: +#if 0 /* FIXME */ + admhc_writel(ahcd, ADMHC_RH_OCIC, + &ahcd->regs->roothub.status); +#endif + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case ClearPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + ret = admhc_port_disable(ahcd, wIndex); + break; + case USB_PORT_FEAT_SUSPEND: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CPS); + break; + case USB_PORT_FEAT_POWER: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CPP); + break; + case USB_PORT_FEAT_C_CONNECTION: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CSC); + break; + case USB_PORT_FEAT_C_ENABLE: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PESC); + break; + case USB_PORT_FEAT_C_SUSPEND: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PSSC); + break; + case USB_PORT_FEAT_C_OVER_CURRENT: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_OCIC); + break; + case USB_PORT_FEAT_C_RESET: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PRSC); + break; + default: + goto error; + } + break; + case GetHubDescriptor: + ret = admhc_get_hub_descriptor(ahcd, buf); + break; + case GetHubStatus: + ret = admhc_get_hub_status(ahcd, buf); + break; + case GetPortStatus: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + + ret = admhc_get_port_status(ahcd, wIndex, buf); + break; + case SetHubFeature: + switch (wValue) { + case C_HUB_OVER_CURRENT: + /* FIXME: this can be cleared, yes? */ + case C_HUB_LOCAL_POWER: + break; + default: + goto error; + } + break; + case SetPortFeature: + if (!wIndex || wIndex > ports) + goto error; + wIndex--; + + switch (wValue) { + case USB_PORT_FEAT_ENABLE: + ret = admhc_port_enable(ahcd, wIndex); + break; + case USB_PORT_FEAT_RESET: + ret = admhc_port_reset(ahcd, wIndex); + break; + case USB_PORT_FEAT_SUSPEND: +#ifdef CONFIG_USB_OTG + if (hcd->self.otg_port == (wIndex + 1) + && hcd->self.b_hnp_enable) + start_hnp(ahcd); + else +#endif + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_SPS); + break; + case USB_PORT_FEAT_POWER: + ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_SPP); + break; + default: + goto error; + } + break; + + default: +error: + /* "protocol stall" on error */ + ret = -EPIPE; + } + + return ret; +} + diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-mem.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-mem.c new file mode 100644 index 0000000000..79fff70e2d --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-mem.c @@ -0,0 +1,202 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-mem.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * 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. + * + */ + +/*-------------------------------------------------------------------------*/ + +/* + * OHCI deals with three types of memory: + * - data used only by the HCD ... kmalloc is fine + * - async and periodic schedules, shared by HC and HCD ... these + * need to use dma_pool or dma_alloc_coherent + * - driver buffers, read/written by HC ... the hcd glue or the + * device driver provides us with dma addresses + * + * There's also "register" data, which is memory mapped. + * No memory seen by this driver (or any HCD) may be paged out. + */ + +/*-------------------------------------------------------------------------*/ + +static void admhc_hcd_init(struct admhcd *ahcd) +{ + ahcd->next_statechange = jiffies; + spin_lock_init(&ahcd->lock); + INIT_LIST_HEAD(&ahcd->pending); +} + +/*-------------------------------------------------------------------------*/ + +static int admhc_mem_init(struct admhcd *ahcd) +{ + ahcd->td_cache = dma_pool_create("admhc_td", + admhcd_to_hcd(ahcd)->self.controller, + sizeof(struct td), + TD_ALIGN, /* byte alignment */ + 0 /* no page-crossing issues */ + ); + if (!ahcd->td_cache) + goto err; + + ahcd->ed_cache = dma_pool_create("admhc_ed", + admhcd_to_hcd(ahcd)->self.controller, + sizeof(struct ed), + ED_ALIGN, /* byte alignment */ + 0 /* no page-crossing issues */ + ); + if (!ahcd->ed_cache) + goto err_td_cache; + + return 0; + +err_td_cache: + dma_pool_destroy(ahcd->td_cache); + ahcd->td_cache = NULL; +err: + return -ENOMEM; +} + +static void admhc_mem_cleanup(struct admhcd *ahcd) +{ + if (ahcd->td_cache) { + dma_pool_destroy(ahcd->td_cache); + ahcd->td_cache = NULL; + } + + if (ahcd->ed_cache) { + dma_pool_destroy(ahcd->ed_cache); + ahcd->ed_cache = NULL; + } +} + +/*-------------------------------------------------------------------------*/ + +/* ahcd "done list" processing needs this mapping */ +static inline struct td *dma_to_td(struct admhcd *ahcd, dma_addr_t td_dma) +{ + struct td *td; + + td_dma &= TD_MASK; + td = ahcd->td_hash[TD_HASH_FUNC(td_dma)]; + while (td && td->td_dma != td_dma) + td = td->td_hash; + + return td; +} + +/* TDs ... */ +static struct td *td_alloc(struct admhcd *ahcd, gfp_t mem_flags) +{ + dma_addr_t dma; + struct td *td; + + td = dma_pool_alloc(ahcd->td_cache, mem_flags, &dma); + if (!td) + return NULL; + + /* in case ahcd fetches it, make it look dead */ + memset(td, 0, sizeof *td); + td->hwNextTD = cpu_to_hc32(ahcd, dma); + td->td_dma = dma; + /* hashed in td_fill */ + + return td; +} + +static void td_free(struct admhcd *ahcd, struct td *td) +{ + struct td **prev = &ahcd->td_hash[TD_HASH_FUNC(td->td_dma)]; + + while (*prev && *prev != td) + prev = &(*prev)->td_hash; + if (*prev) + *prev = td->td_hash; +#if 0 + /* TODO: remove */ + else if ((td->hwINFO & cpu_to_hc32(ahcd, TD_DONE)) != 0) + admhc_dbg(ahcd, "no hash for td %p\n", td); +#else + else if ((td->flags & TD_FLAG_DONE) != 0) + admhc_dbg(ahcd, "no hash for td %p\n", td); +#endif + dma_pool_free(ahcd->td_cache, td, td->td_dma); +} + +/*-------------------------------------------------------------------------*/ + +/* EDs ... */ +static struct ed *ed_alloc(struct admhcd *ahcd, gfp_t mem_flags) +{ + dma_addr_t dma; + struct ed *ed; + + ed = dma_pool_alloc(ahcd->ed_cache, mem_flags, &dma); + if (!ed) + return NULL; + + memset(ed, 0, sizeof(*ed)); + ed->dma = dma; + + INIT_LIST_HEAD(&ed->td_list); + INIT_LIST_HEAD(&ed->urb_list); + + return ed; +} + +static void ed_free(struct admhcd *ahcd, struct ed *ed) +{ + dma_pool_free(ahcd->ed_cache, ed, ed->dma); +} + +/*-------------------------------------------------------------------------*/ + +/* URB priv ... */ +static void urb_priv_free(struct admhcd *ahcd, struct urb_priv *urb_priv) +{ + int i; + + for (i = 0; i < urb_priv->td_cnt; i++) + if (urb_priv->td[i]) + td_free(ahcd, urb_priv->td[i]); + + list_del(&urb_priv->pending); + kfree(urb_priv); +} + +static struct urb_priv *urb_priv_alloc(struct admhcd *ahcd, int num_tds, + gfp_t mem_flags) +{ + struct urb_priv *priv; + + /* allocate the private part of the URB */ + priv = kzalloc(sizeof(*priv) + sizeof(struct td) * num_tds, mem_flags); + if (!priv) + goto err; + + /* allocate the TDs (deferring hash chain updates) */ + for (priv->td_cnt = 0; priv->td_cnt < num_tds; priv->td_cnt++) { + priv->td[priv->td_cnt] = td_alloc(ahcd, mem_flags); + if (priv->td[priv->td_cnt] == NULL) + goto err_free; + } + + INIT_LIST_HEAD(&priv->pending); + + return priv; + +err_free: + urb_priv_free(ahcd, priv); +err: + return NULL; +} diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-pm.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-pm.c new file mode 100644 index 0000000000..7d7fc2438f --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-pm.c @@ -0,0 +1,449 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from fragments of the OHCI driver. + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2004 David Brownell + * + * 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. + * + */ + +#define OHCI_SCHED_ENABLES \ + (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) + +#ifdef CONFIG_PM +static int admhc_restart(struct admhcd *ahcd); + +static int admhc_rh_suspend(struct admhcd *ahcd, int autostop) +__releases(ahcd->lock) +__acquires(ahcd->lock) +{ + int status = 0; + + ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); + switch (ahcd->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_RESUME: + admhc_dbg(ahcd, "resume/suspend?\n"); + ahcd->hc_control &= ~OHCI_CTRL_HCFS; + ahcd->hc_control |= OHCI_USB_RESET; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); + (void) admhc_readl(ahcd, &ahcd->regs->control); + /* FALL THROUGH */ + case OHCI_USB_RESET: + status = -EBUSY; + admhc_dbg(ahcd, "needs reinit!\n"); + goto done; + case OHCI_USB_SUSPEND: + if (!ahcd->autostop) { + admhc_dbg(ahcd, "already suspended\n"); + goto done; + } + } + admhc_dbg(ahcd, "%s root hub\n", + autostop ? "auto-stop" : "suspend"); + + /* First stop any processing */ + if (!autostop && (ahcd->hc_control & OHCI_SCHED_ENABLES)) { + ahcd->hc_control &= ~OHCI_SCHED_ENABLES; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); + ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); + admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->intrstatus); + + /* sched disables take effect on the next frame, + * then the last WDH could take 6+ msec + */ + admhc_dbg(ahcd, "stopping schedules ...\n"); + ahcd->autostop = 0; + spin_unlock_irq (&ahcd->lock); + msleep (8); + spin_lock_irq(&ahcd->lock); + } + dl_done_list (ahcd); + finish_unlinks (ahcd, admhc_frame_no(ahcd)); + + /* maybe resume can wake root hub */ + if (device_may_wakeup(&admhcd_to_hcd(ahcd)->self.root_hub->dev) || + autostop) + ahcd->hc_control |= OHCI_CTRL_RWE; + else { + admhc_writel(ahcd, OHCI_INTR_RHSC, &ahcd->regs->intrdisable); + ahcd->hc_control &= ~OHCI_CTRL_RWE; + } + + /* Suspend hub ... this is the "global (to this bus) suspend" mode, + * which doesn't imply ports will first be individually suspended. + */ + ahcd->hc_control &= ~OHCI_CTRL_HCFS; + ahcd->hc_control |= OHCI_USB_SUSPEND; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); + (void) admhc_readl(ahcd, &ahcd->regs->control); + + /* no resumes until devices finish suspending */ + if (!autostop) { + ahcd->next_statechange = jiffies + msecs_to_jiffies (5); + ahcd->autostop = 0; + } + +done: + return status; +} + +static inline struct ed *find_head(struct ed *ed) +{ + /* for bulk and control lists */ + while (ed->ed_prev) + ed = ed->ed_prev; + return ed; +} + +/* caller has locked the root hub */ +static int admhc_rh_resume(struct admhcd *ahcd) +__releases(ahcd->lock) +__acquires(ahcd->lock) +{ + struct usb_hcd *hcd = admhcd_to_hcd (ahcd); + u32 temp, enables; + int status = -EINPROGRESS; + int autostopped = ahcd->autostop; + + ahcd->autostop = 0; + ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); + + if (ahcd->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { + /* this can happen after resuming a swsusp snapshot */ + if (hcd->state == HC_STATE_RESUMING) { + admhc_dbg(ahcd, "BIOS/SMM active, control %03x\n", + ahcd->hc_control); + status = -EBUSY; + /* this happens when pmcore resumes HC then root */ + } else { + admhc_dbg(ahcd, "duplicate resume\n"); + status = 0; + } + } else switch (ahcd->hc_control & OHCI_CTRL_HCFS) { + case OHCI_USB_SUSPEND: + ahcd->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); + ahcd->hc_control |= OHCI_USB_RESUME; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); + (void) admhc_readl(ahcd, &ahcd->regs->control); + admhc_dbg(ahcd, "%s root hub\n", + autostopped ? "auto-start" : "resume"); + break; + case OHCI_USB_RESUME: + /* HCFS changes sometime after INTR_RD */ + admhc_dbg(ahcd, "%swakeup root hub\n", + autostopped ? "auto-" : ""); + break; + case OHCI_USB_OPER: + /* this can happen after resuming a swsusp snapshot */ + admhc_dbg(ahcd, "snapshot resume? reinit\n"); + status = -EBUSY; + break; + default: /* RESET, we lost power */ + admhc_dbg(ahcd, "lost power\n"); + status = -EBUSY; + } + if (status == -EBUSY) { + if (!autostopped) { + spin_unlock_irq (&ahcd->lock); + (void) ahcd_init (ahcd); + status = admhc_restart (ahcd); + spin_lock_irq(&ahcd->lock); + } + return status; + } + if (status != -EINPROGRESS) + return status; + if (autostopped) + goto skip_resume; + spin_unlock_irq (&ahcd->lock); + + /* Some controllers (lucent erratum) need extra-long delays */ + msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); + + temp = admhc_readl(ahcd, &ahcd->regs->control); + temp &= OHCI_CTRL_HCFS; + if (temp != OHCI_USB_RESUME) { + admhc_err (ahcd, "controller won't resume\n"); + spin_lock_irq(&ahcd->lock); + return -EBUSY; + } + + /* disable old schedule state, reinit from scratch */ + admhc_writel(ahcd, 0, &ahcd->regs->ed_controlhead); + admhc_writel(ahcd, 0, &ahcd->regs->ed_controlcurrent); + admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkhead); + admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkcurrent); + admhc_writel(ahcd, 0, &ahcd->regs->ed_periodcurrent); + admhc_writel(ahcd, (u32) ahcd->hcca_dma, &ahcd->ahcd->regs->hcca); + + /* Sometimes PCI D3 suspend trashes frame timings ... */ + periodic_reinit(ahcd); + + /* the following code is executed with ahcd->lock held and + * irqs disabled if and only if autostopped is true + */ + +skip_resume: + /* interrupts might have been disabled */ + admhc_writel(ahcd, OHCI_INTR_INIT, &ahcd->regs->int_enable); + if (ahcd->ed_rm_list) + admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->int_enable); + + /* Then re-enable operations */ + admhc_writel(ahcd, OHCI_USB_OPER, &ahcd->regs->control); + (void) admhc_readl(ahcd, &ahcd->regs->control); + if (!autostopped) + msleep (3); + + temp = ahcd->hc_control; + temp &= OHCI_CTRL_RWC; + temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER; + ahcd->hc_control = temp; + admhc_writel(ahcd, temp, &ahcd->regs->control); + (void) admhc_readl(ahcd, &ahcd->regs->control); + + /* TRSMRCY */ + if (!autostopped) { + msleep (10); + spin_lock_irq(&ahcd->lock); + } + /* now ahcd->lock is always held and irqs are always disabled */ + + /* keep it alive for more than ~5x suspend + resume costs */ + ahcd->next_statechange = jiffies + STATECHANGE_DELAY; + + /* maybe turn schedules back on */ + enables = 0; + temp = 0; + if (!ahcd->ed_rm_list) { + if (ahcd->ed_controltail) { + admhc_writel(ahcd, + find_head (ahcd->ed_controltail)->dma, + &ahcd->regs->ed_controlhead); + enables |= OHCI_CTRL_CLE; + temp |= OHCI_CLF; + } + if (ahcd->ed_bulktail) { + admhc_writel(ahcd, find_head (ahcd->ed_bulktail)->dma, + &ahcd->regs->ed_bulkhead); + enables |= OHCI_CTRL_BLE; + temp |= OHCI_BLF; + } + } + if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs) + enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE; + if (enables) { + admhc_dbg(ahcd, "restarting schedules ... %08x\n", enables); + ahcd->hc_control |= enables; + admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); + if (temp) + admhc_writel(ahcd, temp, &ahcd->regs->cmdstatus); + (void) admhc_readl(ahcd, &ahcd->regs->control); + } + + return 0; +} + +static int admhc_bus_suspend(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + int rc; + + spin_lock_irq(&ahcd->lock); + + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) + rc = -ESHUTDOWN; + else + rc = admhc_rh_suspend(ahcd, 0); + spin_unlock_irq(&ahcd->lock); + return rc; +} + +static int admhc_bus_resume(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + int rc; + + if (time_before(jiffies, ahcd->next_statechange)) + msleep(5); + + spin_lock_irq(&ahcd->lock); + + if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) + rc = -ESHUTDOWN; + else + rc = admhc_rh_resume(ahcd); + spin_unlock_irq(&ahcd->lock); + + /* poll until we know a device is connected or we autostop */ + if (rc == 0) + usb_hcd_poll_rh_status(hcd); + return rc; +} + +/* Carry out polling-, autostop-, and autoresume-related state changes */ +static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed, + int any_connected) +{ + int poll_rh = 1; + + switch (ahcd->hc_control & OHCI_CTRL_HCFS) { + + case OHCI_USB_OPER: + /* keep on polling until we know a device is connected + * and RHSC is enabled */ + if (!ahcd->autostop) { + if (any_connected || + !device_may_wakeup(&admhcd_to_hcd(ahcd) + ->self.root_hub->dev)) { + if (admhc_readl(ahcd, &ahcd->regs->int_enable) & + OHCI_INTR_RHSC) + poll_rh = 0; + } else { + ahcd->autostop = 1; + ahcd->next_statechange = jiffies + HZ; + } + + /* if no devices have been attached for one second, autostop */ + } else { + if (changed || any_connected) { + ahcd->autostop = 0; + ahcd->next_statechange = jiffies + + STATECHANGE_DELAY; + } else if (time_after_eq(jiffies, + ahcd->next_statechange) + && !ahcd->ed_rm_list + && !(ahcd->hc_control & + OHCI_SCHED_ENABLES)) { + ahcd_rh_suspend(ahcd, 1); + } + } + break; + + /* if there is a port change, autostart or ask to be resumed */ + case OHCI_USB_SUSPEND: + case OHCI_USB_RESUME: + if (changed) { + if (ahcd->autostop) + admhc_rh_resume(ahcd); + else + usb_hcd_resume_root_hub(admhcd_to_hcd(ahcd)); + } else { + /* everything is idle, no need for polling */ + poll_rh = 0; + } + break; + } + return poll_rh; +} + +/*-------------------------------------------------------------------------*/ + +/* must not be called from interrupt context */ +static int admhc_restart(struct admhcd *ahcd) +{ + int temp; + int i; + struct urb_priv *priv; + + /* mark any devices gone, so they do nothing till khubd disconnects. + * recycle any "live" eds/tds (and urbs) right away. + * later, khubd disconnect processing will recycle the other state, + * (either as disconnect/reconnect, or maybe someday as a reset). + */ + spin_lock_irq(&ahcd->lock); + admhc_disable(ahcd); + usb_root_hub_lost_power(admhcd_to_hcd(ahcd)->self.root_hub); + if (!list_empty(&ahcd->pending)) + admhc_dbg(ahcd, "abort schedule...\n"); + list_for_each_entry(priv, &ahcd->pending, pending) { + struct urb *urb = priv->td[0]->urb; + struct ed *ed = priv->ed; + + switch (ed->state) { + case ED_OPER: + ed->state = ED_UNLINK; + ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE); + ed_deschedule (ahcd, ed); + + ed->ed_next = ahcd->ed_rm_list; + ed->ed_prev = NULL; + ahcd->ed_rm_list = ed; + /* FALLTHROUGH */ + case ED_UNLINK: + break; + default: + admhc_dbg(ahcd, "bogus ed %p state %d\n", + ed, ed->state); + } + + if (!urb->unlinked) + urb->unlinked = -ESHUTDOWN; + } + finish_unlinks(ahcd, 0); + spin_unlock_irq(&ahcd->lock); + + /* paranoia, in case that didn't work: */ + + /* empty the interrupt branches */ + for (i = 0; i < NUM_INTS; i++) ahcd->load[i] = 0; + for (i = 0; i < NUM_INTS; i++) ahcd->hcca->int_table[i] = 0; + + /* no EDs to remove */ + ahcd->ed_rm_list = NULL; + + /* empty control and bulk lists */ + ahcd->ed_controltail = NULL; + ahcd->ed_bulktail = NULL; + + if ((temp = admhc_run(ahcd)) < 0) { + admhc_err(ahcd, "can't restart, %d\n", temp); + return temp; + } else { + /* here we "know" root ports should always stay powered, + * and that if we try to turn them back on the root hub + * will respond to CSC processing. + */ + i = ahcd->num_ports; + while (i--) + admhc_writel(ahcd, RH_PS_PSS, + &ahcd->regs->portstatus[i]); + admhc_dbg(ahcd, "restart complete\n"); + } + return 0; +} + +#else /* CONFIG_PM */ + +static inline int admhc_rh_resume(struct admhcd *ahcd) +{ + return 0; +} + +/* Carry out polling-related state changes. + * autostop isn't used when CONFIG_PM is turned off. + */ +static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed, + int any_connected) +{ + /* If INSM is enabled, don't poll */ + if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM) + return 0; + + /* If no status changes are pending, enable status-change interrupts */ + if (!changed) { + admhc_intr_enable(ahcd, ADMHC_INTR_INSM); + return 0; + } + + return 1; +} + +#endif /* CONFIG_PM */ + diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-q.c b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-q.c new file mode 100644 index 0000000000..cd9c8920af --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120-q.c @@ -0,0 +1,964 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci-q.c + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * 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 + +/*-------------------------------------------------------------------------*/ + +/* + * URB goes back to driver, and isn't reissued. + * It's completely gone from HC data structures. + * PRECONDITION: ahcd lock held, irqs blocked. + */ +static void +finish_urb(struct admhcd *ahcd, struct urb *urb, int status) +__releases(ahcd->lock) +__acquires(ahcd->lock) +{ + urb_priv_free(ahcd, urb->hcpriv); + + if (likely(status == -EINPROGRESS)) + status = 0; + + switch (usb_pipetype(urb->pipe)) { + case PIPE_ISOCHRONOUS: + admhcd_to_hcd(ahcd)->self.bandwidth_isoc_reqs--; + break; + case PIPE_INTERRUPT: + admhcd_to_hcd(ahcd)->self.bandwidth_int_reqs--; + break; + } + +#ifdef ADMHC_VERBOSE_DEBUG + urb_print(ahcd, urb, "RET", usb_pipeout(urb->pipe), status); +#endif + + /* urb->complete() can reenter this HCD */ + usb_hcd_unlink_urb_from_ep(admhcd_to_hcd(ahcd), urb); + spin_unlock(&ahcd->lock); + usb_hcd_giveback_urb(admhcd_to_hcd(ahcd), urb, status); + spin_lock(&ahcd->lock); +} + + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +#if 0 /* FIXME */ +/* search for the right schedule branch to use for a periodic ed. + * does some load balancing; returns the branch, or negative errno. + */ +static int balance(struct admhcd *ahcd, int interval, int load) +{ + int i, branch = -ENOSPC; + + /* iso periods can be huge; iso tds specify frame numbers */ + if (interval > NUM_INTS) + interval = NUM_INTS; + + /* search for the least loaded schedule branch of that period + * that has enough bandwidth left unreserved. + */ + for (i = 0; i < interval ; i++) { + if (branch < 0 || ahcd->load[branch] > ahcd->load[i]) { + int j; + + /* usb 1.1 says 90% of one frame */ + for (j = i; j < NUM_INTS; j += interval) { + if ((ahcd->load[j] + load) > 900) + break; + } + if (j < NUM_INTS) + continue; + branch = i; + } + } + return branch; +} +#endif + +/*-------------------------------------------------------------------------*/ + +#if 0 /* FIXME */ +/* both iso and interrupt requests have periods; this routine puts them + * into the schedule tree in the apppropriate place. most iso devices use + * 1msec periods, but that's not required. + */ +static void periodic_link(struct admhcd *ahcd, struct ed *ed) +{ + unsigned i; + + admhc_vdbg(ahcd, "link %sed %p branch %d [%dus.], interval %d\n", + (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); + + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed **prev = &ahcd->periodic[i]; + __hc32 *prev_p = &ahcd->hcca->int_table[i]; + struct ed *here = *prev; + + /* sorting each branch by period (slow before fast) + * lets us share the faster parts of the tree. + * (plus maybe: put interrupt eds before iso) + */ + while (here && ed != here) { + if (ed->interval > here->interval) + break; + prev = &here->ed_next; + prev_p = &here->hwNextED; + here = *prev; + } + if (ed != here) { + ed->ed_next = here; + if (here) + ed->hwNextED = *prev_p; + wmb(); + *prev = ed; + *prev_p = cpu_to_hc32(ahcd, ed->dma); + wmb(); + } + ahcd->load[i] += ed->load; + } + admhcd_to_hcd(ahcd)->self.bandwidth_allocated += ed->load / ed->interval; +} +#endif + +/* link an ed into the HC chain */ + +static int ed_schedule(struct admhcd *ahcd, struct ed *ed) +{ + struct ed *old_tail; + + if (admhcd_to_hcd(ahcd)->state == HC_STATE_QUIESCING) + return -EAGAIN; + + ed->state = ED_OPER; + + old_tail = ahcd->ed_tails[ed->type]; + + ed->ed_next = old_tail->ed_next; + if (ed->ed_next) { + ed->ed_next->ed_prev = ed; + ed->hwNextED = cpu_to_hc32(ahcd, ed->ed_next->dma); + } + ed->ed_prev = old_tail; + + old_tail->ed_next = ed; + old_tail->hwNextED = cpu_to_hc32(ahcd, ed->dma); + + ahcd->ed_tails[ed->type] = ed; + + admhc_dma_enable(ahcd); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#if 0 /* FIXME */ +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink(struct admhcd *ahcd, struct ed *ed) +{ + int i; + + for (i = ed->branch; i < NUM_INTS; i += ed->interval) { + struct ed *temp; + struct ed **prev = &ahcd->periodic[i]; + __hc32 *prev_p = &ahcd->hcca->int_table[i]; + + while (*prev && (temp = *prev) != ed) { + prev_p = &temp->hwNextED; + prev = &temp->ed_next; + } + if (*prev) { + *prev_p = ed->hwNextED; + *prev = ed->ed_next; + } + ahcd->load[i] -= ed->load; + } + + admhcd_to_hcd(ahcd)->self.bandwidth_allocated -= ed->load / ed->interval; + admhc_vdbg(ahcd, "unlink %sed %p branch %d [%dus.], interval %d\n", + (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "", + ed, ed->branch, ed->load, ed->interval); +} +#endif + +/* unlink an ed from the HC chain. + * just the link to the ed is unlinked. + * the link from the ed still points to another operational ed or 0 + * so the HC can eventually finish the processing of the unlinked ed + * (assuming it already started that, which needn't be true). + * + * ED_UNLINK is a transient state: the HC may still see this ED, but soon + * it won't. ED_SKIP means the HC will finish its current transaction, + * but won't start anything new. The TD queue may still grow; device + * drivers don't know about this HCD-internal state. + * + * When the HC can't see the ED, something changes ED_UNLINK to one of: + * + * - ED_OPER: when there's any request queued, the ED gets rescheduled + * immediately. HC should be working on them. + * + * - ED_IDLE: when there's no TD queue. there's no reason for the HC + * to care about this ED; safe to disable the endpoint. + * + * When finish_unlinks() runs later, after SOF interrupt, it will often + * complete one or more URB unlinks before making that state change. + */ +static void ed_deschedule(struct admhcd *ahcd, struct ed *ed) +{ + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "ED-DESCHED", ed, 1); +#endif + + ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); + wmb(); + ed->state = ED_UNLINK; + + /* remove this ED from the HC list */ + ed->ed_prev->hwNextED = ed->hwNextED; + + /* and remove it from our list also */ + ed->ed_prev->ed_next = ed->ed_next; + + if (ed->ed_next) + ed->ed_next->ed_prev = ed->ed_prev; + + if (ahcd->ed_tails[ed->type] == ed) + ahcd->ed_tails[ed->type] = ed->ed_prev; +} + +/*-------------------------------------------------------------------------*/ + +static struct ed *ed_create(struct admhcd *ahcd, unsigned int type, u32 info) +{ + struct ed *ed; + struct td *td; + + ed = ed_alloc(ahcd, GFP_ATOMIC); + if (!ed) + goto err; + + /* dummy td; end of td list for this ed */ + td = td_alloc(ahcd, GFP_ATOMIC); + if (!td) + goto err_free_ed; + + switch (type) { + case PIPE_INTERRUPT: + info |= ED_INT; + break; + case PIPE_ISOCHRONOUS: + info |= ED_ISO; + break; + } + + ed->dummy = td; + ed->state = ED_IDLE; + ed->type = type; + + ed->hwINFO = cpu_to_hc32(ahcd, info); + ed->hwTailP = cpu_to_hc32(ahcd, td->td_dma); + ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ + + return ed; + +err_free_ed: + ed_free(ahcd, ed); +err: + return NULL; +} + +/* get and maybe (re)init an endpoint. init _should_ be done only as part + * of enumeration, usb_set_configuration() or usb_set_interface(). + */ +static struct ed *ed_get(struct admhcd *ahcd, struct usb_host_endpoint *ep, + struct usb_device *udev, unsigned int pipe, int interval) +{ + struct ed *ed; + unsigned long flags; + + spin_lock_irqsave(&ahcd->lock, flags); + + ed = ep->hcpriv; + if (!ed) { + u32 info; + + /* FIXME: usbcore changes dev->devnum before SET_ADDRESS + * succeeds ... otherwise we wouldn't need "pipe". + */ + info = usb_pipedevice(pipe); + info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << ED_EN_SHIFT; + info |= le16_to_cpu(ep->desc.wMaxPacketSize) << ED_MPS_SHIFT; + if (udev->speed == USB_SPEED_FULL) + info |= ED_SPEED_FULL; + + ed = ed_create(ahcd, usb_pipetype(pipe), info); + if (ed) + ep->hcpriv = ed; + } + + spin_unlock_irqrestore(&ahcd->lock, flags); + + return ed; +} + +/*-------------------------------------------------------------------------*/ + +/* request unlinking of an endpoint from an operational HC. + * put the ep on the rm_list + * real work is done at the next start frame (SOFI) hardware interrupt + * caller guarantees HCD is running, so hardware access is safe, + * and that ed->state is ED_OPER + */ +static void start_ed_unlink(struct admhcd *ahcd, struct ed *ed) +{ + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "ED-UNLINK", ed, 1); +#endif + + ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE); + ed_deschedule(ahcd, ed); + + /* add this ED into the remove list */ + ed->ed_rm_next = ahcd->ed_rm_list; + ahcd->ed_rm_list = ed; + + /* enable SOF interrupt */ + admhc_intr_ack(ahcd, ADMHC_INTR_SOFI); + admhc_intr_enable(ahcd, ADMHC_INTR_SOFI); + /* flush those writes */ + admhc_writel_flush(ahcd); + + /* SOF interrupt might get delayed; record the frame counter value that + * indicates when the HC isn't looking at it, so concurrent unlinks + * behave. frame_no wraps every 2^16 msec, and changes right before + * SOF is triggered. + */ + ed->tick = admhc_frame_no(ahcd) + 1; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void +td_fill(struct admhcd *ahcd, u32 info, dma_addr_t data, int len, + struct urb *urb, int index) +{ + struct td *td, *td_pt; + struct urb_priv *urb_priv = urb->hcpriv; + int hash; + u32 cbl = 0; + +#if 1 + if (index == (urb_priv->td_cnt - 1) && + ((urb->transfer_flags & URB_NO_INTERRUPT) == 0)) + cbl |= TD_IE; +#else + if (index == (urb_priv->td_cnt - 1)) + cbl |= TD_IE; +#endif + + /* use this td as the next dummy */ + td_pt = urb_priv->td[index]; + + /* fill the old dummy TD */ + td = urb_priv->td[index] = urb_priv->ed->dummy; + urb_priv->ed->dummy = td_pt; + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->urb = urb; + td->data_dma = data; + if (!len) + data = 0; + + if (data) + cbl |= (len & TD_BL_MASK); + + info |= TD_OWN; + + /* setup hardware specific fields */ + td->hwINFO = cpu_to_hc32(ahcd, info); + td->hwDBP = cpu_to_hc32(ahcd, data); + td->hwCBL = cpu_to_hc32(ahcd, cbl); + td->hwNextTD = cpu_to_hc32(ahcd, td_pt->td_dma); + + /* append to queue */ + list_add_tail(&td->td_list, &td->ed->td_list); + + /* hash it for later reverse mapping */ + hash = TD_HASH_FUNC(td->td_dma); + td->td_hash = ahcd->td_hash[hash]; + ahcd->td_hash[hash] = td; + + /* HC might read the TD (or cachelines) right away ... */ + wmb(); + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* Prepare all TDs of a transfer, and queue them onto the ED. + * Caller guarantees HC is active. + * Usually the ED is already on the schedule, so TDs might be + * processed as soon as they're queued. + */ +static void td_submit_urb(struct admhcd *ahcd, struct urb *urb) +{ + struct urb_priv *urb_priv = urb->hcpriv; + dma_addr_t data; + int data_len = urb->transfer_buffer_length; + int cnt = 0; + u32 info = 0; + int is_out = usb_pipeout(urb->pipe); + u32 toggle = 0; + + /* OHCI handles the bulk/interrupt data toggles itself. We just + * use the device toggle bits for resetting, and rely on the fact + * that resetting toggle is meaningless if the endpoint is active. + */ + + if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), is_out)) { + toggle = TD_T_CARRY; + } else { + toggle = TD_T_DATA0; + usb_settoggle(urb->dev, usb_pipeendpoint (urb->pipe), + is_out, 1); + } + + urb_priv->td_idx = 0; + list_add(&urb_priv->pending, &ahcd->pending); + + if (data_len) + data = urb->transfer_dma; + else + data = 0; + + /* NOTE: TD_CC is set so we can tell which TDs the HC processed by + * using TD_CC_GET, as well as by seeing them on the done list. + * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.) + */ + switch (urb_priv->ed->type) { + case PIPE_INTERRUPT: + info = is_out + ? TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_OUT + : TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_IN; + + /* setup service interval and starting frame number */ + info |= (urb->start_frame & TD_FN_MASK); + info |= (urb->interval & TD_ISI_MASK) << TD_ISI_SHIFT; + + td_fill(ahcd, info, data, data_len, urb, cnt); + cnt++; + + admhcd_to_hcd(ahcd)->self.bandwidth_int_reqs++; + break; + + case PIPE_BULK: + info = is_out + ? TD_SCC_NOTACCESSED | TD_DP_OUT + : TD_SCC_NOTACCESSED | TD_DP_IN; + + /* TDs _could_ transfer up to 8K each */ + while (data_len > TD_DATALEN_MAX) { + td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), + data, TD_DATALEN_MAX, urb, cnt); + data += TD_DATALEN_MAX; + data_len -= TD_DATALEN_MAX; + cnt++; + } + + td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), data, + data_len, urb, cnt); + cnt++; + + if ((urb->transfer_flags & URB_ZERO_PACKET) + && (cnt < urb_priv->td_cnt)) { + td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), + 0, 0, urb, cnt); + cnt++; + } + break; + + /* control manages DATA0/DATA1 toggle per-request; SETUP resets it, + * any DATA phase works normally, and the STATUS ack is special. + */ + case PIPE_CONTROL: + /* fill a TD for the setup */ + info = TD_SCC_NOTACCESSED | TD_DP_SETUP | TD_T_DATA0; + td_fill(ahcd, info, urb->setup_dma, 8, urb, cnt++); + + if (data_len > 0) { + /* fill a TD for the data */ + info = TD_SCC_NOTACCESSED | TD_T_DATA1; + info |= is_out ? TD_DP_OUT : TD_DP_IN; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill(ahcd, info, data, data_len, urb, cnt++); + } + + /* fill a TD for the ACK */ + info = (is_out || data_len == 0) + ? TD_SCC_NOTACCESSED | TD_DP_IN | TD_T_DATA1 + : TD_SCC_NOTACCESSED | TD_DP_OUT | TD_T_DATA1; + td_fill(ahcd, info, data, 0, urb, cnt++); + + break; + + /* ISO has no retransmit, so no toggle; + * Each TD could handle multiple consecutive frames (interval 1); + * we could often reduce the number of TDs here. + */ + case PIPE_ISOCHRONOUS: + info = is_out + ? TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_OUT + : TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_IN; + + for (cnt = 0; cnt < urb->number_of_packets; cnt++) { + int frame = urb->start_frame; + + frame += cnt * urb->interval; + frame &= TD_FN_MASK; + td_fill(ahcd, info | frame, + data + urb->iso_frame_desc[cnt].offset, + urb->iso_frame_desc[cnt].length, urb, cnt); + } + admhcd_to_hcd(ahcd)->self.bandwidth_isoc_reqs++; + break; + } + + if (urb_priv->td_cnt != cnt) + admhc_err(ahcd, "bad number of tds created for urb %p\n", urb); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + +/* calculate transfer length/status and update the urb */ +static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td) +{ + struct urb_priv *urb_priv = urb->hcpriv; + u32 info; + u32 bl; + u32 tdDBP; + int type = usb_pipetype(urb->pipe); + int cc; + int status = -EINPROGRESS; + + info = hc32_to_cpup(ahcd, &td->hwINFO); + tdDBP = hc32_to_cpup(ahcd, &td->hwDBP); + bl = TD_BL_GET(hc32_to_cpup(ahcd, &td->hwCBL)); + cc = TD_CC_GET(info); + + /* ISO ... drivers see per-TD length/status */ + if (type == PIPE_ISOCHRONOUS) { + /* TODO */ + int dlen = 0; + + /* NOTE: assumes FC in tdINFO == 0, and that + * only the first of 0..MAXPSW psws is used. + */ + if (info & TD_CC) /* hc didn't touch? */ + return status; + + if (usb_pipeout(urb->pipe)) + dlen = urb->iso_frame_desc[td->index].length; + else { + /* short reads are always OK for ISO */ + if (cc == TD_CC_DATAUNDERRUN) + cc = TD_CC_NOERROR; + dlen = tdDBP - td->data_dma + bl; + } + + urb->actual_length += dlen; + urb->iso_frame_desc[td->index].actual_length = dlen; + urb->iso_frame_desc[td->index].status = cc_to_error[cc]; + + if (cc != TD_CC_NOERROR) + admhc_vdbg(ahcd, + "urb %p iso td %p (%d) len %d cc %d\n", + urb, td, 1 + td->index, dlen, cc); + + /* BULK, INT, CONTROL ... drivers see aggregate length/status, + * except that "setup" bytes aren't counted and "short" transfers + * might not be reported as errors. + */ + } else { + /* update packet status if needed (short is normally ok) */ + if (cc == TD_CC_DATAUNDERRUN + && !(urb->transfer_flags & URB_SHORT_NOT_OK)) + cc = TD_CC_NOERROR; + + if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0) + status = cc_to_error[cc]; + + + /* count all non-empty packets except control SETUP packet */ + if ((type != PIPE_CONTROL || td->index != 0) && tdDBP != 0) + urb->actual_length += tdDBP - td->data_dma + bl; + + if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0) + admhc_vdbg(ahcd, + "urb %p td %p (%d) cc %d, len=%d/%d\n", + urb, td, td->index, cc, + urb->actual_length, + urb->transfer_buffer_length); + } + + list_del(&td->td_list); + urb_priv->td_idx++; + + return status; +} + +/*-------------------------------------------------------------------------*/ + +static void ed_halted(struct admhcd *ahcd, struct td *td, int cc) +{ + struct urb *urb = td->urb; + struct urb_priv *urb_priv = urb->hcpriv; + struct ed *ed = td->ed; + struct list_head *tmp = td->td_list.next; + __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); + + admhc_dump_ed(ahcd, "ed halted", td->ed, 1); + /* clear ed halt; this is the td that caused it, but keep it inactive + * until its urb->complete() has a chance to clean up. + */ + ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); + wmb(); + ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); + + /* Get rid of all later tds from this urb. We don't have + * to be careful: no errors and nothing was transferred. + * Also patch the ed so it looks as if those tds completed normally. + */ + while (tmp != &ed->td_list) { + struct td *next; + + next = list_entry(tmp, struct td, td_list); + tmp = next->td_list.next; + + if (next->urb != urb) + break; + + /* NOTE: if multi-td control DATA segments get supported, + * this urb had one of them, this td wasn't the last td + * in that segment (TD_R clear), this ed halted because + * of a short read, _and_ URB_SHORT_NOT_OK is clear ... + * then we need to leave the control STATUS packet queued + * and clear ED_SKIP. + */ + list_del(&next->td_list); + urb_priv->td_cnt++; + ed->hwHeadP = next->hwNextTD | toggle; + } + + /* help for troubleshooting: report anything that + * looks odd ... that doesn't include protocol stalls + * (or maybe some other things) + */ + switch (cc) { + case TD_CC_DATAUNDERRUN: + if ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0) + break; + /* fallthrough */ + case TD_CC_STALL: + if (usb_pipecontrol(urb->pipe)) + break; + /* fallthrough */ + default: + admhc_dbg(ahcd, + "urb %p path %s ep%d%s %08x cc %d --> status %d\n", + urb, urb->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein(urb->pipe) ? "in" : "out", + hc32_to_cpu(ahcd, td->hwINFO), + cc, cc_to_error[cc]); + } +} + +/*-------------------------------------------------------------------------*/ + +/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ +static void +finish_unlinks(struct admhcd *ahcd, u16 tick) +{ + struct ed *ed, **last; + +rescan_all: + for (last = &ahcd->ed_rm_list, ed = *last; ed != NULL; ed = *last) { + struct list_head *entry, *tmp; + int completed, modified; + __hc32 *prev; + + /* only take off EDs that the HC isn't using, accounting for + * frame counter wraps and EDs with partially retired TDs + */ + if (likely(HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state))) { + if (tick_before(tick, ed->tick)) { +skip_ed: + last = &ed->ed_rm_next; + continue; + } +#if 0 + if (!list_empty(&ed->td_list)) { + struct td *td; + u32 head; + + td = list_entry(ed->td_list.next, struct td, + td_list); + head = hc32_to_cpu(ahcd, ed->hwHeadP) & + TD_MASK; + + /* INTR_WDH may need to clean up first */ + if (td->td_dma != head) + goto skip_ed; + } +#endif + } + + /* reentrancy: if we drop the schedule lock, someone might + * have modified this list. normally it's just prepending + * entries (which we'd ignore), but paranoia won't hurt. + */ + *last = ed->ed_rm_next; + ed->ed_rm_next = NULL; + modified = 0; + + /* unlink urbs as requested, but rescan the list after + * we call a completion since it might have unlinked + * another (earlier) urb + * + * When we get here, the HC doesn't see this ed. But it + * must not be rescheduled until all completed URBs have + * been given back to the driver. + */ +rescan_this: + completed = 0; + prev = &ed->hwHeadP; + list_for_each_safe(entry, tmp, &ed->td_list) { + struct td *td; + struct urb *urb; + struct urb_priv *urb_priv; + __hc32 savebits; + u32 tdINFO; + int status; + + td = list_entry(entry, struct td, td_list); + urb = td->urb; + urb_priv = td->urb->hcpriv; + + if (!urb->unlinked) { + prev = &td->hwNextTD; + continue; + } + + if ((urb_priv) == NULL) + continue; + + /* patch pointer hc uses */ + savebits = *prev & ~cpu_to_hc32(ahcd, TD_MASK); + *prev = td->hwNextTD | savebits; + /* If this was unlinked, the TD may not have been + * retired ... so manually save dhe data toggle. + * The controller ignores the value we save for + * control and ISO endpoints. + */ + tdINFO = hc32_to_cpup(ahcd, &td->hwINFO); + if ((tdINFO & TD_T) == TD_T_DATA0) + ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_C); + else if ((tdINFO & TD_T) == TD_T_DATA1) + ed->hwHeadP |= cpu_to_hc32(ahcd, ED_C); + + /* HC may have partly processed this TD */ +#ifdef ADMHC_VERBOSE_DEBUG + urb_print(ahcd, urb, "PARTIAL", 0); +#endif + status = td_done(ahcd, urb, td); + + /* if URB is done, clean up */ + if (urb_priv->td_idx == urb_priv->td_cnt) { + modified = completed = 1; + finish_urb(ahcd, urb, status); + } + } + if (completed && !list_empty(&ed->td_list)) + goto rescan_this; + + /* ED's now officially unlinked, hc doesn't see */ + ed->state = ED_IDLE; + ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); + ed->hwNextED = 0; + wmb(); + ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP | ED_DEQUEUE); + + /* but if there's work queued, reschedule */ + if (!list_empty(&ed->td_list)) { + if (HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state)) + ed_schedule(ahcd, ed); + } + + if (modified) + goto rescan_all; + } +} + +/*-------------------------------------------------------------------------*/ +/* + * Process normal completions (error or success) and clean the schedules. + * + * This is the main path for handing urbs back to drivers. The only other + * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list, + * instead of scanning the (re-reversed) donelist as this does. + */ + +static void ed_unhalt(struct admhcd *ahcd, struct ed *ed, struct urb *urb) +{ + struct list_head *entry, *tmp; + __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "UNHALT", ed, 0); +#endif + /* clear ed halt; this is the td that caused it, but keep it inactive + * until its urb->complete() has a chance to clean up. + */ + ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); + wmb(); + ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); + + list_for_each_safe(entry, tmp, &ed->td_list) { + struct td *td = list_entry(entry, struct td, td_list); + __hc32 info; + + if (td->urb != urb) + break; + + info = td->hwINFO; + info &= ~cpu_to_hc32(ahcd, TD_CC | TD_OWN); + td->hwINFO = info; + + ed->hwHeadP = td->hwNextTD | toggle; + wmb(); + } + +} + +static void ed_intr_refill(struct admhcd *ahcd, struct ed *ed) +{ + __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); + + ed->hwHeadP = ed->hwTailP | toggle; +} + + +static inline int is_ed_halted(struct admhcd *ahcd, struct ed *ed) +{ + return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) == ED_H); +} + +static inline int is_td_halted(struct admhcd *ahcd, struct ed *ed, + struct td *td) +{ + return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & TD_MASK) == + (hc32_to_cpup(ahcd, &td->hwNextTD) & TD_MASK)); +} + +static void ed_update(struct admhcd *ahcd, struct ed *ed) +{ + struct list_head *entry, *tmp; + +#ifdef ADMHC_VERBOSE_DEBUG + admhc_dump_ed(ahcd, "UPDATE", ed, 1); +#endif + + list_for_each_safe(entry, tmp, &ed->td_list) { + struct td *td = list_entry(entry, struct td, td_list); + struct urb *urb = td->urb; + struct urb_priv *urb_priv = urb->hcpriv; + int status; + + if (hc32_to_cpup(ahcd, &td->hwINFO) & TD_OWN) + break; + + /* update URB's length and status from TD */ + status = td_done(ahcd, urb, td); + if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td)) + ed_unhalt(ahcd, ed, urb); + + if (ed->type == PIPE_INTERRUPT) + ed_intr_refill(ahcd, ed); + + /* If all this urb's TDs are done, call complete() */ + if (urb_priv->td_idx == urb_priv->td_cnt) + finish_urb(ahcd, urb, status); + + /* clean schedule: unlink EDs that are no longer busy */ + if (list_empty(&ed->td_list)) { + if (ed->state == ED_OPER) + start_ed_unlink(ahcd, ed); + + /* ... reenabling halted EDs only after fault cleanup */ + } else if ((ed->hwINFO & cpu_to_hc32(ahcd, + ED_SKIP | ED_DEQUEUE)) + == cpu_to_hc32(ahcd, ED_SKIP)) { + td = list_entry(ed->td_list.next, struct td, td_list); +#if 0 + if (!(td->hwINFO & cpu_to_hc32(ahcd, TD_DONE))) { + ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); + /* ... hc may need waking-up */ + switch (ed->type) { + case PIPE_CONTROL: + admhc_writel(ahcd, OHCI_CLF, + &ahcd->regs->cmdstatus); + break; + case PIPE_BULK: + admhc_writel(ahcd, OHCI_BLF, + &ahcd->regs->cmdstatus); + break; + } + } +#else + if ((td->hwINFO & cpu_to_hc32(ahcd, TD_OWN))) + ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); +#endif + } + + } +} + +/* there are some tds completed; called in_irq(), with HCD locked */ +static void admhc_td_complete(struct admhcd *ahcd) +{ + struct ed *ed; + + for (ed = ahcd->ed_head; ed; ed = ed->ed_next) { + if (ed->state != ED_OPER) + continue; + + ed_update(ahcd, ed); + } +} diff --git a/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120.h b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120.h new file mode 100644 index 0000000000..e47aac8e7a --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/usb/host/adm5120.h @@ -0,0 +1,755 @@ +/* + * ADM5120 HCD (Host Controller Driver) for USB + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was derived from: drivers/usb/host/ohci.h + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2002 David Brownell + * + * 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. + * + */ + +/* + * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to + * __leXX (normally) or __beXX (given OHCI_BIG_ENDIAN), depending on the + * host controller implementation. + */ +typedef __u32 __bitwise __hc32; +typedef __u16 __bitwise __hc16; + +/* + * OHCI Endpoint Descriptor (ED) ... holds TD queue + * See OHCI spec, section 4.2 + * + * This is a "Queue Head" for those transfers, which is why + * both EHCI and UHCI call similar structures a "QH". + */ + +#define TD_DATALEN_MAX 4096 + +#define ED_ALIGN 16 +#define ED_MASK ((u32)~(ED_ALIGN-1)) /* strip hw status in low addr bits */ + +struct ed { + /* first fields are hardware-specified */ + __hc32 hwINFO; /* endpoint config bitmap */ + /* info bits defined by hcd */ +#define ED_DEQUEUE (1 << 27) + /* info bits defined by the hardware */ +#define ED_MPS_SHIFT 16 +#define ED_MPS_MASK ((1 << 11)-1) +#define ED_MPS_GET(x) (((x) >> ED_MPS_SHIFT) & ED_MPS_MASK) +#define ED_ISO (1 << 15) /* isochronous endpoint */ +#define ED_SKIP (1 << 14) +#define ED_SPEED_FULL (1 << 13) /* fullspeed device */ +#define ED_INT (1 << 11) /* interrupt endpoint */ +#define ED_EN_SHIFT 7 /* endpoint shift */ +#define ED_EN_MASK ((1 << 4)-1) /* endpoint mask */ +#define ED_EN_GET(x) (((x) >> ED_EN_SHIFT) & ED_EN_MASK) +#define ED_FA_MASK ((1 << 7)-1) /* function address mask */ +#define ED_FA_GET(x) ((x) & ED_FA_MASK) + __hc32 hwTailP; /* tail of TD list */ + __hc32 hwHeadP; /* head of TD list (hc r/w) */ +#define ED_C (0x02) /* toggle carry */ +#define ED_H (0x01) /* halted */ + __hc32 hwNextED; /* next ED in list */ + + /* rest are purely for the driver's use */ + dma_addr_t dma; /* addr of ED */ + struct td *dummy; /* next TD to activate */ + + struct list_head urb_list; /* list of our URBs */ + + /* host's view of schedule */ + struct ed *ed_next; /* on schedule list */ + struct ed *ed_prev; /* for non-interrupt EDs */ + struct ed *ed_rm_next; /* on rm list */ + struct list_head td_list; /* "shadow list" of our TDs */ + + /* create --> IDLE --> OPER --> ... --> IDLE --> destroy + * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... + */ + u8 state; /* ED_{IDLE,UNLINK,OPER} */ +#define ED_IDLE 0x00 /* NOT linked to HC */ +#define ED_UNLINK 0x01 /* being unlinked from hc */ +#define ED_OPER 0x02 /* IS linked to hc */ + + u8 type; /* PIPE_{BULK,...} */ + + /* periodic scheduling params (for intr and iso) */ + u8 branch; + u16 interval; + u16 load; + u16 last_iso; /* iso only */ + + /* HC may see EDs on rm_list until next frame (frame_no == tick) */ + u16 tick; +} __attribute__ ((aligned(ED_ALIGN))); + +/* + * OHCI Transfer Descriptor (TD) ... one per transfer segment + * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) + * and 4.3.2 (iso) + */ + +#define TD_ALIGN 32 +#define TD_MASK ((u32)~(TD_ALIGN-1)) /* strip hw status in low addr bits */ + +struct td { + /* first fields are hardware-specified */ + __hc32 hwINFO; /* transfer info bitmask */ + + /* hwINFO bits */ +#define TD_OWN (1 << 31) /* owner of the descriptor */ +#define TD_CC_SHIFT 27 /* condition code */ +#define TD_CC_MASK 0xf +#define TD_CC (TD_CC_MASK << TD_CC_SHIFT) +#define TD_CC_GET(x) (((x) >> TD_CC_SHIFT) & TD_CC_MASK) + +#define TD_EC_SHIFT 25 /* error count */ +#define TD_EC_MASK 0x3 +#define TD_EC (TD_EC_MASK << TD_EC_SHIFT) +#define TD_EC_GET(x) ((x >> TD_EC_SHIFT) & TD_EC_MASK) +#define TD_T_SHIFT 23 /* data toggle state */ +#define TD_T_MASK 0x3 +#define TD_T (TD_T_MASK << TD_T_SHIFT) +#define TD_T_DATA0 (0x2 << TD_T_SHIFT) /* DATA0 */ +#define TD_T_DATA1 (0x3 << TD_T_SHIFT) /* DATA1 */ +#define TD_T_CARRY (0x0 << TD_T_SHIFT) /* uses ED_C */ +#define TD_T_GET(x) (((x) >> TD_T_SHIFT) & TD_T_MASK) +#define TD_DP_SHIFT 21 /* direction/pid */ +#define TD_DP_MASK 0x3 +#define TD_DP (TD_DP_MASK << TD_DP_SHIFT) +#define TD_DP_GET (((x) >> TD_DP_SHIFT) & TD_DP_MASK) +#define TD_DP_SETUP (0x0 << TD_DP_SHIFT) /* SETUP pid */ +#define TD_DP_OUT (0x1 << TD_DP_SHIFT) /* OUT pid */ +#define TD_DP_IN (0x2 << TD_DP_SHIFT) /* IN pid */ +#define TD_ISI_SHIFT 8 /* Interrupt Service Interval */ +#define TD_ISI_MASK 0x3f +#define TD_ISI_GET(x) (((x) >> TD_ISI_SHIFT) & TD_ISI_MASK) +#define TD_FN_MASK 0x3f /* frame number */ +#define TD_FN_GET(x) ((x) & TD_FN_MASK) + + __hc32 hwDBP; /* Data Buffer Pointer (or 0) */ + __hc32 hwCBL; /* Controller/Buffer Length */ + + /* hwCBL bits */ +#define TD_BL_MASK 0xffff /* buffer length */ +#define TD_BL_GET(x) ((x) & TD_BL_MASK) +#define TD_IE (1 << 16) /* interrupt enable */ + __hc32 hwNextTD; /* Next TD Pointer */ + + /* rest are purely for the driver's use */ + __u8 index; + struct ed *ed; + struct td *td_hash; /* dma-->td hashtable */ + struct td *next_dl_td; + struct urb *urb; + + dma_addr_t td_dma; /* addr of this TD */ + dma_addr_t data_dma; /* addr of data it points to */ + + struct list_head td_list; /* "shadow list", TDs on same ED */ + + u32 flags; +#define TD_FLAG_DONE (1 << 17) /* retired to done list */ +#define TD_FLAG_ISO (1 << 16) /* copy of ED_ISO */ +} __attribute__ ((aligned(TD_ALIGN))); /* c/b/i need 16; only iso needs 32 */ + +/* + * Hardware transfer status codes -- CC from td->hwINFO + */ +#define TD_CC_NOERROR 0x00 +#define TD_CC_CRC 0x01 +#define TD_CC_BITSTUFFING 0x02 +#define TD_CC_DATATOGGLEM 0x03 +#define TD_CC_STALL 0x04 +#define TD_CC_DEVNOTRESP 0x05 +#define TD_CC_PIDCHECKFAIL 0x06 +#define TD_CC_UNEXPECTEDPID 0x07 +#define TD_CC_DATAOVERRUN 0x08 +#define TD_CC_DATAUNDERRUN 0x09 + /* 0x0A, 0x0B reserved for hardware */ +#define TD_CC_BUFFEROVERRUN 0x0C +#define TD_CC_BUFFERUNDERRUN 0x0D + /* 0x0E, 0x0F reserved for HCD */ +#define TD_CC_HCD0 0x0E +#define TD_CC_NOTACCESSED 0x0F + +/* + * preshifted status codes + */ +#define TD_SCC_NOTACCESSED (TD_CC_NOTACCESSED << TD_CC_SHIFT) + + +/* map OHCI TD status codes (CC) to errno values */ +static const int cc_to_error[16] = { + /* No Error */ 0, + /* CRC Error */ -EILSEQ, + /* Bit Stuff */ -EPROTO, + /* Data Togg */ -EILSEQ, + /* Stall */ -EPIPE, + /* DevNotResp */ -ETIME, + /* PIDCheck */ -EPROTO, + /* UnExpPID */ -EPROTO, + /* DataOver */ -EOVERFLOW, + /* DataUnder */ -EREMOTEIO, + /* (for hw) */ -EIO, + /* (for hw) */ -EIO, + /* BufferOver */ -ECOMM, + /* BuffUnder */ -ENOSR, + /* (for HCD) */ -EALREADY, + /* (for HCD) */ -EALREADY +}; + +#define NUM_INTS 32 + +/* + * This is the structure of the OHCI controller's memory mapped I/O region. + * You must use readl() and writel() (in ) to access these fields!! + * Layout is in section 7 (and appendix B) of the spec. + */ +struct admhcd_regs { + __hc32 gencontrol; /* General Control */ + __hc32 int_status; /* Interrupt Status */ + __hc32 int_enable; /* Interrupt Enable */ + __hc32 reserved00; + __hc32 host_control; /* Host General Control */ + __hc32 reserved01; + __hc32 fminterval; /* Frame Interval */ + __hc32 fmnumber; /* Frame Number */ + __hc32 reserved02; + __hc32 reserved03; + __hc32 reserved04; + __hc32 reserved05; + __hc32 reserved06; + __hc32 reserved07; + __hc32 reserved08; + __hc32 reserved09; + __hc32 reserved10; + __hc32 reserved11; + __hc32 reserved12; + __hc32 reserved13; + __hc32 reserved14; + __hc32 reserved15; + __hc32 reserved16; + __hc32 reserved17; + __hc32 reserved18; + __hc32 reserved19; + __hc32 reserved20; + __hc32 reserved21; + __hc32 lsthresh; /* Low Speed Threshold */ + __hc32 rhdesc; /* Root Hub Descriptor */ +#define MAX_ROOT_PORTS 2 + __hc32 portstatus[MAX_ROOT_PORTS]; /* Port Status */ + __hc32 hosthead; /* Host Descriptor Head */ +} __attribute__ ((aligned(32))); + +/* + * General Control register bits + */ +#define ADMHC_CTRL_UHFE (1 << 0) /* USB Host Function Enable */ +#define ADMHC_CTRL_SIR (1 << 1) /* Software Interrupt request */ +#define ADMHC_CTRL_DMAA (1 << 2) /* DMA Arbitration Control */ +#define ADMHC_CTRL_SR (1 << 3) /* Software Reset */ + +/* + * Host General Control register bits + */ +#define ADMHC_HC_BUSS 0x3 /* USB bus state */ +#define ADMHC_BUSS_RESET 0x0 +#define ADMHC_BUSS_RESUME 0x1 +#define ADMHC_BUSS_OPER 0x2 +#define ADMHC_BUSS_SUSPEND 0x3 +#define ADMHC_HC_DMAE (1 << 2) /* DMA enable */ + +/* + * Interrupt Status/Enable register bits + */ +#define ADMHC_INTR_SOFI (1 << 4) /* start of frame */ +#define ADMHC_INTR_RESI (1 << 5) /* resume detected */ +#define ADMHC_INTR_6 (1 << 6) /* unknown */ +#define ADMHC_INTR_7 (1 << 7) /* unknown */ +#define ADMHC_INTR_BABI (1 << 8) /* babble detected */ +#define ADMHC_INTR_INSM (1 << 9) /* root hub status change */ +#define ADMHC_INTR_SO (1 << 10) /* scheduling overrun */ +#define ADMHC_INTR_FNO (1 << 11) /* frame number overflow */ +#define ADMHC_INTR_TDC (1 << 20) /* transfer descriptor completed */ +#define ADMHC_INTR_SWI (1 << 29) /* software interrupt */ +#define ADMHC_INTR_FATI (1 << 30) /* fatal error */ +#define ADMHC_INTR_INTA (1 << 31) /* interrupt active */ + +#define ADMHC_INTR_MIE (1 << 31) /* master interrupt enable */ + +/* + * SOF Frame Interval register bits + */ +#define ADMHC_SFI_FI_MASK ((1 << 14)-1) /* Frame Interval value */ +#define ADMHC_SFI_FSLDP_SHIFT 16 +#define ADMHC_SFI_FSLDP_MASK ((1 << 15)-1) +#define ADMHC_SFI_FIT (1 << 31) /* Frame Interval Toggle */ + +/* + * SOF Frame Number register bits + */ +#define ADMHC_SFN_FN_MASK ((1 << 16)-1) /* Frame Number Mask */ +#define ADMHC_SFN_FR_SHIFT 16 /* Frame Remaining Shift */ +#define ADMHC_SFN_FR_MASK ((1 << 14)-1) /* Frame Remaining Mask */ +#define ADMHC_SFN_FRT (1 << 31) /* Frame Remaining Toggle */ + +/* + * Root Hub Descriptor register bits + */ +#define ADMHC_RH_NUMP 0xff /* number of ports */ +#define ADMHC_RH_PSM (1 << 8) /* power switching mode */ +#define ADMHC_RH_NPS (1 << 9) /* no power switching */ +#define ADMHC_RH_OCPM (1 << 10) /* over current protection mode */ +#define ADMHC_RH_NOCP (1 << 11) /* no over current protection */ +#define ADMHC_RH_PPCM (0xff << 16) /* port power control */ + +#define ADMHC_RH_LPS (1 << 24) /* local power switch */ +#define ADMHC_RH_OCI (1 << 25) /* over current indicator */ + +/* status change bits */ +#define ADMHC_RH_LPSC (1 << 26) /* local power switch change */ +#define ADMHC_RH_OCIC (1 << 27) /* over current indicator change */ + +#define ADMHC_RH_DRWE (1 << 28) /* device remote wakeup enable */ +#define ADMHC_RH_CRWE (1 << 29) /* clear remote wakeup enable */ + +#define ADMHC_RH_CGP (1 << 24) /* clear global power */ +#define ADMHC_RH_SGP (1 << 26) /* set global power */ + +/* + * Port Status register bits + */ +#define ADMHC_PS_CCS (1 << 0) /* current connect status */ +#define ADMHC_PS_PES (1 << 1) /* port enable status */ +#define ADMHC_PS_PSS (1 << 2) /* port suspend status */ +#define ADMHC_PS_POCI (1 << 3) /* port over current indicator */ +#define ADMHC_PS_PRS (1 << 4) /* port reset status */ +#define ADMHC_PS_PPS (1 << 8) /* port power status */ +#define ADMHC_PS_LSDA (1 << 9) /* low speed device attached */ + +/* status change bits */ +#define ADMHC_PS_CSC (1 << 16) /* connect status change */ +#define ADMHC_PS_PESC (1 << 17) /* port enable status change */ +#define ADMHC_PS_PSSC (1 << 18) /* port suspend status change */ +#define ADMHC_PS_OCIC (1 << 19) /* over current indicator change */ +#define ADMHC_PS_PRSC (1 << 20) /* port reset status change */ + +/* port feature bits */ +#define ADMHC_PS_CPE (1 << 0) /* clear port enable */ +#define ADMHC_PS_SPE (1 << 1) /* set port enable */ +#define ADMHC_PS_SPS (1 << 2) /* set port suspend */ +#define ADMHC_PS_CPS (1 << 3) /* clear suspend status */ +#define ADMHC_PS_SPR (1 << 4) /* set port reset */ +#define ADMHC_PS_SPP (1 << 8) /* set port power */ +#define ADMHC_PS_CPP (1 << 9) /* clear port power */ + +/* + * the POTPGT value is not defined in the ADMHC, so define a dummy value + */ +#define ADMHC_POTPGT 2 /* in ms */ + +/* hcd-private per-urb state */ +struct urb_priv { + struct ed *ed; + struct list_head pending; /* URBs on the same ED */ + + u32 td_cnt; /* # tds in this request */ + u32 td_idx; /* index of the current td */ + struct td *td[0]; /* all TDs in this request */ +}; + +#define TD_HASH_SIZE 64 /* power'o'two */ +/* sizeof (struct td) ~= 64 == 2^6 ... */ +#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) + +/* + * This is the full ADMHCD controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + +struct admhcd { + spinlock_t lock; + + /* + * I/O memory used to communicate with the HC (dma-consistent) + */ + struct admhcd_regs __iomem *regs; + + /* + * hcd adds to schedule for a live hc any time, but removals finish + * only at the start of the next frame. + */ + + struct ed *ed_head; + struct ed *ed_tails[4]; + + struct ed *ed_rm_list; /* to be removed */ + + struct ed *periodic[NUM_INTS]; /* shadow int_table */ + +#if 0 /* TODO: remove? */ + /* + * OTG controllers and transceivers need software interaction; + * other external transceivers should be software-transparent + */ + struct otg_transceiver *transceiver; + void (*start_hnp)(struct admhcd *ahcd); +#endif + + /* + * memory management for queue data structures + */ + struct dma_pool *td_cache; + struct dma_pool *ed_cache; + struct td *td_hash[TD_HASH_SIZE]; + struct list_head pending; + + /* + * driver state + */ + int num_ports; + int load[NUM_INTS]; + u32 host_control; /* copy of the host_control reg */ + unsigned long next_statechange; /* suspend/resume */ + u32 fminterval; /* saved register */ + unsigned autostop:1; /* rh auto stopping/stopped */ + + unsigned long flags; /* for HC bugs */ +#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ +#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ +#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ +#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ +#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ +#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ + /* there are also chip quirks/bugs in init logic */ + +#ifdef DEBUG + struct dentry *debug_dir; + struct dentry *debug_async; + struct dentry *debug_periodic; + struct dentry *debug_registers; +#endif +}; + +/* convert between an hcd pointer and the corresponding ahcd_hcd */ +static inline struct admhcd *hcd_to_admhcd(struct usb_hcd *hcd) +{ + return (struct admhcd *)(hcd->hcd_priv); +} +static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd) +{ + return container_of((void *)ahcd, struct usb_hcd, hcd_priv); +} + +/*-------------------------------------------------------------------------*/ + +#ifndef DEBUG +#define STUB_DEBUG_FILES +#endif /* DEBUG */ + +#ifdef DEBUG +# define admhc_dbg(ahcd, fmt, args...) \ + printk(KERN_DEBUG "adm5120-hcd: " fmt, ## args) +#else +# define admhc_dbg(ahcd, fmt, args...) do { } while (0) +#endif + +#define admhc_err(ahcd, fmt, args...) \ + printk(KERN_ERR "adm5120-hcd: " fmt, ## args) +#define admhc_info(ahcd, fmt, args...) \ + printk(KERN_INFO "adm5120-hcd: " fmt, ## args) +#define admhc_warn(ahcd, fmt, args...) \ + printk(KERN_WARNING "adm5120-hcd: " fmt, ## args) + +#ifdef ADMHC_VERBOSE_DEBUG +# define admhc_vdbg admhc_dbg +#else +# define admhc_vdbg(ahcd, fmt, args...) do { } while (0) +#endif + +/*-------------------------------------------------------------------------*/ + +/* + * While most USB host controllers implement their registers and + * in-memory communication descriptors in little-endian format, + * a minority (notably the IBM STB04XXX and the Motorola MPC5200 + * processors) implement them in big endian format. + * + * In addition some more exotic implementations like the Toshiba + * Spider (aka SCC) cell southbridge are "mixed" endian, that is, + * they have a different endianness for registers vs. in-memory + * descriptors. + * + * This attempts to support either format at compile time without a + * runtime penalty, or both formats with the additional overhead + * of checking a flag bit. + * + * That leads to some tricky Kconfig rules howevber. There are + * different defaults based on some arch/ppc platforms, though + * the basic rules are: + * + * Controller type Kconfig options needed + * --------------- ---------------------- + * little endian CONFIG_USB_ADMHC_LITTLE_ENDIAN + * + * fully big endian CONFIG_USB_ADMHC_BIG_ENDIAN_DESC _and_ + * CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO + * + * mixed endian CONFIG_USB_ADMHC_LITTLE_ENDIAN _and_ + * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC} + * + * (If you have a mixed endian controller, you -must- also define + * CONFIG_USB_ADMHC_LITTLE_ENDIAN or things will not work when building + * both your mixed endian and a fully big endian controller support in + * the same kernel image). + */ + +#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_DESC +#ifdef CONFIG_USB_ADMHC_LITTLE_ENDIAN +#define big_endian_desc(ahcd) (ahcd->flags & OHCI_QUIRK_BE_DESC) +#else +#define big_endian_desc(ahcd) 1 /* only big endian */ +#endif +#else +#define big_endian_desc(ahcd) 0 /* only little endian */ +#endif + +#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO +#ifdef CONFIG_USB_ADMHC_LITTLE_ENDIAN +#define big_endian_mmio(ahcd) (ahcd->flags & OHCI_QUIRK_BE_MMIO) +#else +#define big_endian_mmio(ahcd) 1 /* only big endian */ +#endif +#else +#define big_endian_mmio(ahcd) 0 /* only little endian */ +#endif + +/* + * Big-endian read/write functions are arch-specific. + * Other arches can be added if/when they're needed. + * + */ +static inline unsigned int admhc_readl(const struct admhcd *ahcd, + __hc32 __iomem *regs) +{ +#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO + return big_endian_mmio(ahcd) ? + readl_be(regs) : + readl(regs); +#else + return readl(regs); +#endif +} + +static inline void admhc_writel(const struct admhcd *ahcd, + const unsigned int val, __hc32 __iomem *regs) +{ +#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO + big_endian_mmio(ahcd) ? + writel_be(val, regs) : + writel(val, regs); +#else + writel(val, regs); +#endif +} + +static inline void admhc_writel_flush(const struct admhcd *ahcd) +{ +#if 0 + /* TODO: remove? */ + (void) admhc_readl(ahcd, &ahcd->regs->gencontrol); +#endif +} + + +/*-------------------------------------------------------------------------*/ + +/* cpu to ahcd */ +static inline __hc16 cpu_to_hc16(const struct admhcd *ahcd, const u16 x) +{ + return big_endian_desc(ahcd) ? + (__force __hc16)cpu_to_be16(x) : + (__force __hc16)cpu_to_le16(x); +} + +static inline __hc16 cpu_to_hc16p(const struct admhcd *ahcd, const u16 *x) +{ + return big_endian_desc(ahcd) ? + cpu_to_be16p(x) : + cpu_to_le16p(x); +} + +static inline __hc32 cpu_to_hc32(const struct admhcd *ahcd, const u32 x) +{ + return big_endian_desc(ahcd) ? + (__force __hc32)cpu_to_be32(x) : + (__force __hc32)cpu_to_le32(x); +} + +static inline __hc32 cpu_to_hc32p(const struct admhcd *ahcd, const u32 *x) +{ + return big_endian_desc(ahcd) ? + cpu_to_be32p(x) : + cpu_to_le32p(x); +} + +/* ahcd to cpu */ +static inline u16 hc16_to_cpu(const struct admhcd *ahcd, const __hc16 x) +{ + return big_endian_desc(ahcd) ? + be16_to_cpu((__force __be16)x) : + le16_to_cpu((__force __le16)x); +} + +static inline u16 hc16_to_cpup(const struct admhcd *ahcd, const __hc16 *x) +{ + return big_endian_desc(ahcd) ? + be16_to_cpup((__force __be16 *)x) : + le16_to_cpup((__force __le16 *)x); +} + +static inline u32 hc32_to_cpu(const struct admhcd *ahcd, const __hc32 x) +{ + return big_endian_desc(ahcd) ? + be32_to_cpu((__force __be32)x) : + le32_to_cpu((__force __le32)x); +} + +static inline u32 hc32_to_cpup(const struct admhcd *ahcd, const __hc32 *x) +{ + return big_endian_desc(ahcd) ? + be32_to_cpup((__force __be32 *)x) : + le32_to_cpup((__force __le32 *)x); +} + +/*-------------------------------------------------------------------------*/ + +static inline u16 admhc_frame_no(const struct admhcd *ahcd) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->fmnumber) & ADMHC_SFN_FN_MASK; + return (u16)t; +} + +static inline u16 admhc_frame_remain(const struct admhcd *ahcd) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->fmnumber) >> ADMHC_SFN_FR_SHIFT; + t &= ADMHC_SFN_FR_MASK; + return (u16)t; +} + +/*-------------------------------------------------------------------------*/ + +static inline void admhc_disable(struct admhcd *ahcd) +{ + admhcd_to_hcd(ahcd)->state = HC_STATE_HALT; +} + +#define FI 0x2edf /* 12000 bits per frame (-1) */ +#define FSLDP(fi) (0x7fff & ((6 * ((fi) - 1200)) / 7)) +#define FIT ADMHC_SFI_FIT +#define LSTHRESH 0x628 /* lowspeed bit threshold */ + +static inline void periodic_reinit(struct admhcd *ahcd) +{ +#if 0 + u32 fi = ahcd->fminterval & ADMHC_SFI_FI_MASK; + u32 fit = admhc_readl(ahcd, &ahcd->regs->fminterval) & FIT; + + /* TODO: adjust FSLargestDataPacket value too? */ + admhc_writel(ahcd, (fit ^ FIT) | ahcd->fminterval, + &ahcd->regs->fminterval); +#else + u32 fit = admhc_readl(ahcd, &ahcd->regs->fminterval) & FIT; + + /* TODO: adjust FSLargestDataPacket value too? */ + admhc_writel(ahcd, (fit ^ FIT) | ahcd->fminterval, + &ahcd->regs->fminterval); +#endif +} + +static inline u32 admhc_read_rhdesc(struct admhcd *ahcd) +{ + return admhc_readl(ahcd, &ahcd->regs->rhdesc); +} + +static inline u32 admhc_read_portstatus(struct admhcd *ahcd, int port) +{ + return admhc_readl(ahcd, &ahcd->regs->portstatus[port]); +} + +static inline void admhc_write_portstatus(struct admhcd *ahcd, int port, + u32 value) +{ + admhc_writel(ahcd, value, &ahcd->regs->portstatus[port]); +} + +static inline void roothub_write_status(struct admhcd *ahcd, u32 value) +{ + /* FIXME: read-only bits must be masked out */ + admhc_writel(ahcd, value, &ahcd->regs->rhdesc); +} + +static inline void admhc_intr_disable(struct admhcd *ahcd, u32 ints) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->int_enable); + t &= ~(ints); + admhc_writel(ahcd, t, &ahcd->regs->int_enable); + /* TODO: flush writes ?*/ +} + +static inline void admhc_intr_enable(struct admhcd *ahcd, u32 ints) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->int_enable); + t |= ints; + admhc_writel(ahcd, t, &ahcd->regs->int_enable); + /* TODO: flush writes ?*/ +} + +static inline void admhc_intr_ack(struct admhcd *ahcd, u32 ints) +{ + admhc_writel(ahcd, ints, &ahcd->regs->int_status); +} + +static inline void admhc_dma_enable(struct admhcd *ahcd) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->host_control); + if (t & ADMHC_HC_DMAE) + return; + + t |= ADMHC_HC_DMAE; + admhc_writel(ahcd, t, &ahcd->regs->host_control); + admhc_vdbg(ahcd, "DMA enabled\n"); +} + +static inline void admhc_dma_disable(struct admhcd *ahcd) +{ + u32 t; + + t = admhc_readl(ahcd, &ahcd->regs->host_control); + if (!(t & ADMHC_HC_DMAE)) + return; + + t &= ~ADMHC_HC_DMAE; + admhc_writel(ahcd, t, &ahcd->regs->host_control); + admhc_vdbg(ahcd, "DMA disabled\n"); +} diff --git a/target/linux/adm5120/files-3.8/drivers/watchdog/adm5120_wdt.c b/target/linux/adm5120/files-3.8/drivers/watchdog/adm5120_wdt.c new file mode 100644 index 0000000000..d5d63b27a5 --- /dev/null +++ b/target/linux/adm5120/files-3.8/drivers/watchdog/adm5120_wdt.c @@ -0,0 +1,202 @@ +/* + * ADM5120_WDT 0.01: Infineon ADM5120 SoC watchdog driver + * Copyright (c) Ondrej Zajicek , 2007 + * + * based on + * + * RC32434_WDT 0.01: IDT Interprise 79RC32434 watchdog driver + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#define DEFAULT_TIMEOUT 15 /* (secs) Default is 15 seconds */ +#define MAX_TIMEOUT 327 +/* Max is 327 seconds, counter is 15-bit integer, step is 10 ms */ + +#define NAME "adm5120_wdt" +#define VERSION "0.1" + +static int expect_close; +static int access; +static unsigned int timeout = DEFAULT_TIMEOUT; + +static int nowayout = WATCHDOG_NOWAYOUT; +module_param(nowayout, int, 0); +MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +MODULE_LICENSE("GPL"); + + +static inline void wdt_set_timeout(void) +{ + u32 val = (1 << 31) | (((timeout * 100) & 0x7FFF) << 16); + SW_WRITE_REG(SWITCH_REG_WDOG0, val); +} + +/* + It looks like WDOG0-register-write don't modify counter, + but WDOG0-register-read resets counter. +*/ + +static inline void wdt_reset_counter(void) +{ + SW_READ_REG(SWITCH_REG_WDOG0); +} + +static inline void wdt_disable(void) +{ + SW_WRITE_REG(SWITCH_REG_WDOG0, 0x7FFF0000); +} + + + +static int wdt_open(struct inode *inode, struct file *file) +{ + /* Allow only one person to hold it open */ + if (access) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); + + /* Activate timer */ + wdt_reset_counter(); + wdt_set_timeout(); + printk(KERN_INFO NAME ": enabling watchdog timer\n"); + access = 1; + return 0; +} + +static int wdt_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + * Lock it in if it's a module and we set nowayout + */ + if (expect_close && (nowayout == 0)) { + wdt_disable(); + printk(KERN_INFO NAME ": disabling watchdog timer\n"); + module_put(THIS_MODULE); + } else + printk(KERN_CRIT NAME ": device closed unexpectedly. WDT will not stop!\n"); + + access = 0; + return 0; +} + +static ssize_t wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) +{ + /* Refresh the timer. */ + if (len) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; + } + } + wdt_reset_counter(); + return len; + } + return 0; +} + +static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +{ + int new_timeout; + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "ADM5120_WDT Watchdog", + }; + switch (cmd) { + default: + return -ENOTTY; + case WDIOC_GETSUPPORT: + if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) + return -EFAULT; + return 0; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user(0, (int *)arg); + case WDIOC_KEEPALIVE: + wdt_reset_counter(); + return 0; + case WDIOC_SETTIMEOUT: + if (get_user(new_timeout, (int *)arg)) + return -EFAULT; + if (new_timeout < 1) + return -EINVAL; + if (new_timeout > MAX_TIMEOUT) + return -EINVAL; + timeout = new_timeout; + wdt_set_timeout(); + /* Fall */ + case WDIOC_GETTIMEOUT: + return put_user(timeout, (int *)arg); + } +} + +static const struct file_operations wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = wdt_write, + .unlocked_ioctl = wdt_ioctl, + .open = wdt_open, + .release = wdt_release, +}; + +static struct miscdevice wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &wdt_fops, +}; + +static char banner[] __initdata = KERN_INFO NAME ": Watchdog Timer version " VERSION "\n"; + +static int __init watchdog_init(void) +{ + int ret; + + ret = misc_register(&wdt_miscdev); + + if (ret) + return ret; + + wdt_disable(); + printk(banner); + + return 0; +} + +static void __exit watchdog_exit(void) +{ + misc_deregister(&wdt_miscdev); +} + +module_init(watchdog_init); +module_exit(watchdog_exit); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/Kconfig b/target/linux/adm5120/files/arch/mips/adm5120/Kconfig deleted file mode 100644 index be35a8f72e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/Kconfig +++ /dev/null @@ -1,197 +0,0 @@ -if ADM5120 - -menu "ADM5120 Board selection" - -config ADM5120_MACH_CAS_771 - bool "Cellvision CAS-771/771W support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_CELLVISION - default y - -config ADM5120_MACH_NFS_101 - bool "Cellvision NFS-101U/101WU support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_CELLVISION - default y - -config ADM5120_MACH_NP27G - bool "Compex NP27G support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_COMPEX - default y - -config ADM5120_MACH_NP28G - bool "Compex NP28G support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_COMPEX - default y - -config ADM5120_MACH_WP54 - bool "Compex WP54 family support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_COMPEX - default y - -config ADM5120_MACH_EB_214A - bool "EB-214A support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_GENERIC - default y - -config ADM5120_MACH_BR_6104K - bool "Edimax BR-6104K support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_OEM_EDIMAX - default y - -config ADM5120_MACH_BR_6104KP - bool "Edimax BR-6104KP support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_OEM_EDIMAX - default y - -config ADM5120_MACH_BR_61X4WG - bool "Edimax BR-6104WG/6114WG support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_EDIMAX - default y - -config ADM5120_MACH_EASY5120_RT - bool "Infineon EASY 5120-RT Reference Board support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_INFINEON - default y - -config ADM5120_MACH_EASY5120_WVOIP - bool "Infineon EASY 5120-WVoIP Reference Board support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_INFINEON - default y - -config ADM5120_MACH_EASY5120P_ATA - bool "Infineon EASY 5120P-ATA Reference Board support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_OEM_INFINEON - default y - -config ADM5120_MACH_EASY83000 - bool "Infineon EASY 83000 Reference Board support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_OEM_INFINEON - default y - -config ADM5120_MACH_RB_11X - bool "MikroTik RouterBOARD 111/112 support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_RB_133 - bool "MikroTik RouterBOARD 133 support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_RB_133C - bool "MikroTik RouterBOARD 133C support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_RB_150 - bool "MikroTik RouterBOARD 150 support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_RB_153 - bool "MikroTik RouterBOARD 153 support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_RB_192 - bool "MikroTik RouterBOARD 192 support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MIKROTIK - default y - -config ADM5120_MACH_PMUGW - bool "Motorola Powerline MU Gateway" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_MOTOROLA - default y - -config ADM5120_MACH_5GXI - bool "OSBRiDGE 5GXi/5XLi support" - depends on CPU_LITTLE_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_OSBRIDGE - default y - -config ADM5120_MACH_P_334WT - bool "ZyXEL Prestige 334WT" - depends on CPU_BIG_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_ZYXEL - default y - -config ADM5120_MACH_P_335 - bool "ZyXEL Prestige 335/335WT" - depends on CPU_BIG_ENDIAN - select ADM5120_SOC_BGA - select ADM5120_OEM_ZYXEL - default y - -endmenu - -config ADM5120_SOC_BGA - select HW_HAS_PCI - def_bool n - -config ADM5120_OEM_CELLVISION - def_bool n - -config ADM5120_OEM_COMPEX - def_bool n - -config ADM5120_OEM_EDIMAX - def_bool n - -config ADM5120_OEM_GENERIC - def_bool n - -config ADM5120_OEM_INFINEON - def_bool n - -config ADM5120_OEM_MIKROTIK - def_bool n - -config ADM5120_OEM_MOTOROLA - def_bool n - -config ADM5120_OEM_OSBRIDGE - def_bool n - -config ADM5120_OEM_ZYXEL - def_bool n - -config ARM_AMBA - def_bool y - -endif diff --git a/target/linux/adm5120/files/arch/mips/adm5120/Platform b/target/linux/adm5120/files/arch/mips/adm5120/Platform deleted file mode 100644 index 0c9edf218b..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/Platform +++ /dev/null @@ -1,19 +0,0 @@ -# -# Infineon/ADMtek ADM5120 -# - -platform-$(CONFIG_ADM5120) += adm5120/common/ - -platform-$(CONFIG_ADM5120_OEM_CELLVISION) += adm5120/cellvision/ -platform-$(CONFIG_ADM5120_OEM_COMPEX) += adm5120/compex/ -platform-$(CONFIG_ADM5120_OEM_EDIMAX) += adm5120/edimax/ -platform-$(CONFIG_ADM5120_OEM_GENERIC) += adm5120/generic/ -platform-$(CONFIG_ADM5120_OEM_INFINEON) += adm5120/infineon/ -platform-$(CONFIG_ADM5120_OEM_MIKROTIK) += adm5120/mikrotik/ -platform-$(CONFIG_ADM5120_OEM_MOTOROLA) += adm5120/motorola/ -platform-$(CONFIG_ADM5120_OEM_OSBRIDGE) += adm5120/osbridge/ -platform-$(CONFIG_ADM5120_OEM_ZYXEL) += adm5120/zyxel/ - -cflags-$(CONFIG_ADM5120) += -I$(srctree)/arch/mips/include/asm/mach-adm5120 -libs-$(CONFIG_ADM5120) += arch/mips/adm5120/prom/ -load-$(CONFIG_ADM5120) += 0xffffffff80001000 diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/Makefile deleted file mode 100644 index a949fc9f61..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += cellvision.o - -obj-$(CONFIG_ADM5120_MACH_CAS_771) += cas-771.o -obj-$(CONFIG_ADM5120_MACH_NFS_101) += nfs-101.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cas-771.c b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cas-771.c deleted file mode 100644 index 5033e02469..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cas-771.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Cellvision/SparkLAN CAS-771/771W support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "cellvision.h" - -static struct adm5120_pci_irq cas771_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), - PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI1), - PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2) -}; - -static struct gpio_led cas771_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN0, "cam_flash", NULL), - /* GPIO PIN3 is the reset */ - GPIO_LED_STD(ADM5120_GPIO_PIN6, "access", NULL), - GPIO_LED_STD(ADM5120_GPIO_P0L1, "status", NULL), - GPIO_LED_STD(ADM5120_GPIO_P0L2, "diag", NULL), -}; - -static void __init cas771_setup(void) -{ - cas7xx_setup(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(cas771_gpio_leds), - cas771_gpio_leds); - adm5120_pci_set_irq_map(ARRAY_SIZE(cas771_pci_irqs), cas771_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_CAS771, "CAS-771", "Cellvision CAS-771/771W", - cas771_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.c b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.c deleted file mode 100644 index a7cedf03bc..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.c +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Cellvision/SparkLAN boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "cellvision.h" - -#include - -#define CELLVISION_GPIO_FLASH_A20 ADM5120_GPIO_PIN5 -#define CELLVISION_GPIO_DEV_MASK (1 << CELLVISION_GPIO_FLASH_A20) - -#define CELLVISION_CONFIG_OFFSET 0x8000 -#define CELLVISION_CONFIG_SIZE 0x1000 - -static struct mtd_partition cas6xx_partitions[] = { - { - .name = "admboot", - .offset = 0, - .size = 32*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "config", - .offset = MTDPART_OFS_APPEND, - .size = 32*1024, - } , { - .name = "nvfs1", - .offset = MTDPART_OFS_APPEND, - .size = 64*1024, - } , { - .name = "nvfs2", - .offset = MTDPART_OFS_APPEND, - .size = 64*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct mtd_partition cas7xx_partitions[] = { - { - .name = "admboot", - .offset = 0, - .size = 32*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "config", - .offset = MTDPART_OFS_APPEND, - .size = 32*1024, - } , { - .name = "nvfs", - .offset = MTDPART_OFS_APPEND, - .size = 128*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static void switch_bank_gpio5(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(CELLVISION_GPIO_FLASH_A20, 0); - break; - case 1: - gpio_set_value(CELLVISION_GPIO_FLASH_A20, 1); - break; - } -} - -static void __init cellvision_flash_setup(void) -{ - /* setup flash A20 line */ - gpio_request(CELLVISION_GPIO_FLASH_A20, NULL); - gpio_direction_output(CELLVISION_GPIO_FLASH_A20, 0); - - adm5120_flash0_data.switch_bank = switch_bank_gpio5; - adm5120_add_device_flash(0); -} - -void __init cellvision_mac_setup(void) -{ - u8 mac_base[6]; - int err; - - err = admboot_get_mac_base(CELLVISION_CONFIG_OFFSET, - CELLVISION_CONFIG_SIZE, mac_base); - - if ((err) || !is_valid_ether_addr(mac_base)) - random_ether_addr(mac_base); - - adm5120_setup_eth_macs(mac_base); -} - -void __init cas6xx_flash_setup(void) -{ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas6xx_partitions); - adm5120_flash0_data.parts = cas6xx_partitions; - - cellvision_flash_setup(); -} - -void __init cas7xx_flash_setup(void) -{ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas7xx_partitions); - adm5120_flash0_data.parts = cas7xx_partitions; - - cellvision_flash_setup(); -} - -void __init cas6xx_setup(void) -{ - cas6xx_flash_setup(); - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - adm5120_add_device_switch(1, NULL); -} - -MIPS_MACHINE(MACH_ADM5120_CAS630, "CAS-630", "Cellvision CAS-630/630W", - cas6xx_setup); -MIPS_MACHINE(MACH_ADM5120_CAS670, "CAS-670", "Cellvision CAS-670/670W", - cas6xx_setup); - -void __init cas7xx_setup(void) -{ - cas7xx_flash_setup(); - cellvision_mac_setup(); - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - adm5120_add_device_switch(1, NULL); -} - -MIPS_MACHINE(MACH_ADM5120_CAS700, "CAS-700", "Cellvision CAS-700/700W", - cas7xx_setup); -MIPS_MACHINE(MACH_ADM5120_CAS790, "CAS-790", "Cellvision CAS-790", - cas7xx_setup); -MIPS_MACHINE(MACH_ADM5120_CAS861, "CAS-861", "Cellvision CAS-861/861W", - cas7xx_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h deleted file mode 100644 index 2b55ebf761..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Cellvision/SparkLAN boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -extern void cellvision_mac_setup(void) __init; - -extern void cas6xx_flash_setup(void) __init; -extern void cas7xx_flash_setup(void) __init; -extern void cas6xx_setup(void) __init; -extern void cas7xx_setup(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/nfs-101.c b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/nfs-101.c deleted file mode 100644 index 7d214c0909..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/nfs-101.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Cellvision/SparkLAN NFS-101U/WU support - * - * Copyright (C) 2007-2009 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 - * by the Free Software Foundation. - * - */ - -#include "cellvision.h" - -static struct adm5120_pci_irq nfs101_pci_irqs[] __initdata = { - /* miniPCI slot */ - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), - - /* ALi USB controller */ - PCIIRQ(3, 0, 2, ADM5120_IRQ_PCI2), - PCIIRQ(3, 3, 1, ADM5120_IRQ_PCI1), - - /* NEC USB controller */ - PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI1), - PCIIRQ(3, 1, 2, ADM5120_IRQ_PCI2), - PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2), -}; - -static u8 nfs101_vlans[6] __initdata = { - /* FIXME: not tested */ - 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init nfs101_setup(void) -{ - cas6xx_flash_setup(); - cellvision_mac_setup(); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - adm5120_add_device_switch(1, nfs101_vlans); - - adm5120_pci_set_irq_map(ARRAY_SIZE(nfs101_pci_irqs), - nfs101_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_NFS101U, "NFS-101U", "Cellvision NFS-101U/101WU", - nfs101_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile deleted file mode 100644 index 8d302c5931..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# Makefile for the Infineon/ADMtek ADM5120 SoC specific parts of the kernel -# - -obj-y := adm5120.o setup.o prom.o irq.o memory.o clock.o \ - gpio.o platform.o - -obj-$(CONFIG_EARLY_PRINTK) += early-printk.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c b/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c deleted file mode 100644 index 28388342c6..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include -#include - -unsigned int adm5120_product_code; -unsigned int adm5120_revision; -unsigned int adm5120_package; -unsigned int adm5120_nand_boot; -unsigned long adm5120_speed; - -/* - * CPU settings detection - */ -#define CODE_GET_PC(c) ((c) & CODE_PC_MASK) -#define CODE_GET_REV(c) (((c) >> CODE_REV_SHIFT) & CODE_REV_MASK) -#define CODE_GET_PK(c) (((c) >> CODE_PK_SHIFT) & CODE_PK_MASK) -#define CODE_GET_CLKS(c) (((c) >> CODE_CLKS_SHIFT) & CODE_CLKS_MASK) -#define CODE_GET_NAB(c) (((c) & CODE_NAB) != 0) - -void adm5120_ndelay(u32 ns) -{ - u32 t; - - SW_WRITE_REG(SWITCH_REG_TIMER, TIMER_PERIOD_DEFAULT); - SW_WRITE_REG(SWITCH_REG_TIMER_INT, (TIMER_INT_TOS | TIMER_INT_TOM)); - - t = (ns+640) / 640; - t &= TIMER_PERIOD_MASK; - SW_WRITE_REG(SWITCH_REG_TIMER, t | TIMER_TE); - - /* wait until the timer expires */ - do { - t = SW_READ_REG(SWITCH_REG_TIMER_INT); - } while ((t & TIMER_INT_TOS) == 0); - - /* leave the timer disabled */ - SW_WRITE_REG(SWITCH_REG_TIMER, TIMER_PERIOD_DEFAULT); - SW_WRITE_REG(SWITCH_REG_TIMER_INT, (TIMER_INT_TOS | TIMER_INT_TOM)); -} - -void __init adm5120_soc_init(void) -{ - u32 code; - u32 clks; - - code = SW_READ_REG(SWITCH_REG_CODE); - - adm5120_product_code = CODE_GET_PC(code); - adm5120_revision = CODE_GET_REV(code); - adm5120_package = (CODE_GET_PK(code) == CODE_PK_BGA) ? - ADM5120_PACKAGE_BGA : ADM5120_PACKAGE_PQFP; - adm5120_nand_boot = CODE_GET_NAB(code); - - clks = CODE_GET_CLKS(code); - adm5120_speed = ADM5120_SPEED_175; - if (clks & 1) - adm5120_speed += 25000000; - if (clks & 2) - adm5120_speed += 50000000; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c b/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c deleted file mode 100644 index 52ae64c419..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c +++ /dev/null @@ -1,65 +0,0 @@ -/* - * ADM5120 minimal CLK API implementation - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was based on the CLK API implementation in: - * arch/mips/tx4938/toshiba_rbtx4938/setup.c - * Copyright (C) 2000-2001 Toshiba Corporation - * 2003-2005 (c) MontaVista Software, Inc. - * - * 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 - -struct clk { - unsigned long rate; -}; - -static struct clk uart_clk = { - .rate = ADM5120_UART_CLOCK -}; - -struct clk *clk_get(struct device *dev, const char *id) -{ - const char *name = dev_name(dev); - - if (!strcmp(name, "apb:uart0") || !strcmp(name, "apb:uart1")) - return &uart_clk; - - return ERR_PTR(-ENOENT); -} -EXPORT_SYMBOL(clk_get); - -int clk_enable(struct clk *clk) -{ - return 0; -} -EXPORT_SYMBOL(clk_enable); - -void clk_disable(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_disable); - -unsigned long clk_get_rate(struct clk *clk) -{ - return clk->rate; -} -EXPORT_SYMBOL(clk_get_rate); - -void clk_put(struct clk *clk) -{ -} -EXPORT_SYMBOL(clk_put); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c b/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c deleted file mode 100644 index d900712639..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/early-printk.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * ADM5120 specific early printk support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include - -#include -#include -#include - -#define UART_READ(r) \ - __raw_readl((void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) -#define UART_WRITE(r, v) \ - __raw_writel((v), (void __iomem *)(KSEG1ADDR(ADM5120_UART0_BASE)+(r))) - -void __init prom_putchar(char ch) -{ - while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0) - ; - UART_WRITE(UART_REG_DATA, ch); - while ((UART_READ(UART_REG_FLAG) & UART_FLAG_TXFE) == 0) - ; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/gpio.c b/target/linux/adm5120/files/arch/mips/adm5120/common/gpio.c deleted file mode 100644 index e60ed7ad01..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/gpio.c +++ /dev/null @@ -1,330 +0,0 @@ -/* - * ADM5120 generic GPIO API support via GPIOLIB - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define GPIO_REG(r) (void __iomem *)(KSEG1ADDR(ADM5120_SWITCH_BASE) + r) - -struct gpio1_desc { - void __iomem *reg; /* register address */ - u8 iv_shift; /* shift amount for input bit */ - u8 mode_shift; /* shift amount for mode bits */ -}; - -#define GPIO1_DESC(p, l) { \ - .reg = GPIO_REG(SWITCH_REG_PORT0_LED + ((p) * 4)), \ - .iv_shift = LED0_IV_SHIFT + (l), \ - .mode_shift = (l) * 4 \ - } - -static struct gpio1_desc gpio1_table[15] = { - GPIO1_DESC(0, 0), GPIO1_DESC(0, 1), GPIO1_DESC(0, 2), - GPIO1_DESC(1, 0), GPIO1_DESC(1, 1), GPIO1_DESC(1, 2), - GPIO1_DESC(2, 0), GPIO1_DESC(2, 1), GPIO1_DESC(2, 2), - GPIO1_DESC(3, 0), GPIO1_DESC(3, 1), GPIO1_DESC(3, 2), - GPIO1_DESC(4, 0), GPIO1_DESC(4, 1), GPIO1_DESC(4, 2) -}; - -static u32 gpio_conf2; - -int adm5120_gpio_to_irq(unsigned gpio) -{ - int ret; - - switch (gpio) { - case ADM5120_GPIO_PIN2: - ret = ADM5120_IRQ_GPIO2; - break; - case ADM5120_GPIO_PIN4: - ret = ADM5120_IRQ_GPIO4; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} -EXPORT_SYMBOL(adm5120_gpio_to_irq); - -int adm5120_irq_to_gpio(unsigned irq) -{ - int ret; - - switch (irq) { - case ADM5120_IRQ_GPIO2: - ret = ADM5120_GPIO_PIN2; - break; - case ADM5120_IRQ_GPIO4: - ret = ADM5120_GPIO_PIN4; - break; - default: - ret = -EINVAL; - break; - } - - return ret; -} -EXPORT_SYMBOL(adm5120_irq_to_gpio); - -/* - * Helpers for GPIO lines in GPIO_CONF0 register - */ -#define PIN_IM(p) ((1 << GPIO_CONF0_IM_SHIFT) << p) -#define PIN_IV(p) ((1 << GPIO_CONF0_IV_SHIFT) << p) -#define PIN_OE(p) ((1 << GPIO_CONF0_OE_SHIFT) << p) -#define PIN_OV(p) ((1 << GPIO_CONF0_OV_SHIFT) << p) - -int __adm5120_gpio0_get_value(unsigned offset) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = __raw_readl(reg); - if ((t & PIN_IM(offset)) != 0) - t &= PIN_IV(offset); - else - t &= PIN_OV(offset); - - return (t) ? 1 : 0; -} -EXPORT_SYMBOL(__adm5120_gpio0_get_value); - -void __adm5120_gpio0_set_value(unsigned offset, int value) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = __raw_readl(reg); - if (value == 0) - t &= ~(PIN_OV(offset)); - else - t |= PIN_OV(offset); - - __raw_writel(t, reg); -} -EXPORT_SYMBOL(__adm5120_gpio0_set_value); - -static int adm5120_gpio0_get_value(struct gpio_chip *chip, unsigned offset) -{ - return __adm5120_gpio0_get_value(offset); -} - -static void adm5120_gpio0_set_value(struct gpio_chip *chip, - unsigned offset, int value) -{ - __adm5120_gpio0_set_value(offset, value); -} - -static int adm5120_gpio0_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = __raw_readl(reg); - t &= ~(PIN_OE(offset)); - t |= PIN_IM(offset); - __raw_writel(t, reg); - - return 0; -} - -static int adm5120_gpio0_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - void __iomem **reg; - u32 t; - - reg = GPIO_REG(SWITCH_REG_GPIO_CONF0); - - t = __raw_readl(reg); - t &= ~(PIN_IM(offset) | PIN_OV(offset)); - t |= PIN_OE(offset); - - if (value) - t |= PIN_OV(offset); - - __raw_writel(t, reg); - - return 0; -} - -static struct gpio_chip adm5120_gpio0_chip = { - .label = "adm5120 gpio0", - .get = adm5120_gpio0_get_value, - .set = adm5120_gpio0_set_value, - .direction_input = adm5120_gpio0_direction_input, - .direction_output = adm5120_gpio0_direction_output, - .base = ADM5120_GPIO_PIN0, - .ngpio = ADM5120_GPIO_PIN7 - ADM5120_GPIO_PIN0 + 1, -}; - -int __adm5120_gpio1_get_value(unsigned offset) -{ - void __iomem **reg; - u32 t, m; - - reg = gpio1_table[offset].reg; - - t = __raw_readl(reg); - m = (t >> gpio1_table[offset].mode_shift) & LED_MODE_MASK; - if (m == LED_MODE_INPUT) - return (t >> gpio1_table[offset].iv_shift) & 1; - - if (m == LED_MODE_OUT_LOW) - return 0; - - return 1; -} -EXPORT_SYMBOL(__adm5120_gpio1_get_value); - -void __adm5120_gpio1_set_value(unsigned offset, int value) -{ - void __iomem **reg; - u32 t, s; - - reg = gpio1_table[offset].reg; - s = gpio1_table[offset].mode_shift; - - t = __raw_readl(reg); - t &= ~(LED_MODE_MASK << s); - - switch (value) { - case ADM5120_GPIO_LOW: - t |= (LED_MODE_OUT_LOW << s); - break; - case ADM5120_GPIO_FLASH: - case ADM5120_GPIO_LINK: - case ADM5120_GPIO_SPEED: - case ADM5120_GPIO_DUPLEX: - case ADM5120_GPIO_ACT: - case ADM5120_GPIO_COLL: - case ADM5120_GPIO_LINK_ACT: - case ADM5120_GPIO_DUPLEX_COLL: - case ADM5120_GPIO_10M_ACT: - case ADM5120_GPIO_100M_ACT: - t |= ((value & LED_MODE_MASK) << s); - break; - default: - t |= (LED_MODE_OUT_HIGH << s); - break; - } - - __raw_writel(t, reg); -} -EXPORT_SYMBOL(__adm5120_gpio1_set_value); - -static int adm5120_gpio1_get_value(struct gpio_chip *chip, unsigned offset) -{ - return __adm5120_gpio1_get_value(offset); -} - -static void adm5120_gpio1_set_value(struct gpio_chip *chip, - unsigned offset, int value) -{ - __adm5120_gpio1_set_value(offset, value); -} - -static int adm5120_gpio1_direction_input(struct gpio_chip *chip, - unsigned offset) -{ - void __iomem **reg; - u32 t; - - reg = gpio1_table[offset].reg; - t = __raw_readl(reg); - t &= ~(LED_MODE_MASK << gpio1_table[offset].mode_shift); - __raw_writel(t, reg); - - return 0; -} - -static int adm5120_gpio1_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - __adm5120_gpio1_set_value(offset, value); - return 0; -} - -static struct gpio_chip adm5120_gpio1_chip = { - .label = "adm5120 gpio1", - .get = adm5120_gpio1_get_value, - .set = adm5120_gpio1_set_value, - .direction_input = adm5120_gpio1_direction_input, - .direction_output = adm5120_gpio1_direction_output, - .base = ADM5120_GPIO_P0L0, - .ngpio = ADM5120_GPIO_P4L2 - ADM5120_GPIO_P0L0 + 1, -}; - -void __init adm5120_gpio_csx0_enable(void) -{ - gpio_conf2 |= GPIO_CONF2_CSX0; - SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - - gpio_request(ADM5120_GPIO_PIN1, "CSX0"); -} - -void __init adm5120_gpio_csx1_enable(void) -{ - gpio_conf2 |= GPIO_CONF2_CSX1; - SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - - gpio_request(ADM5120_GPIO_PIN3, "CSX1"); -} - -void __init adm5120_gpio_ew_enable(void) -{ - gpio_conf2 |= GPIO_CONF2_EW; - SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - - gpio_request(ADM5120_GPIO_PIN0, "EW"); -} - -void __init adm5120_gpio_init(void) -{ - int err; - - SW_WRITE_REG(SWITCH_REG_GPIO_CONF2, gpio_conf2); - - if (adm5120_package_pqfp()) { - gpiochip_reserve(ADM5120_GPIO_PIN4, 4); - adm5120_gpio0_chip.ngpio = 4; - } - - err = gpiochip_add(&adm5120_gpio0_chip); - if (err) - panic("cannot add ADM5120 GPIO0 chip, error=%d", err); - - err = gpiochip_add(&adm5120_gpio1_chip); - if (err) - panic("cannot add ADM5120 GPIO1 chip, error=%d", err); - -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/irq.c b/target/linux/adm5120/files/arch/mips/adm5120/common/irq.c deleted file mode 100644 index a26e65176e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/irq.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * ADM5120 specific interrupt handlers - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -static void adm5120_intc_irq_unmask(struct irq_data *d); -static void adm5120_intc_irq_mask(struct irq_data *d); -static int adm5120_intc_irq_set_type(struct irq_data *d, unsigned int flow_type); - -static inline void intc_write_reg(unsigned int reg, u32 val) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE); - - __raw_writel(val, base + reg); -} - -static inline u32 intc_read_reg(unsigned int reg) -{ - void __iomem *base = (void __iomem *)KSEG1ADDR(ADM5120_INTC_BASE); - - return __raw_readl(base + reg); -} - -static struct irq_chip adm5120_intc_irq_chip = { - .name = "INTC", - .irq_unmask = adm5120_intc_irq_unmask, - .irq_mask = adm5120_intc_irq_mask, - .irq_mask_ack = adm5120_intc_irq_mask, - .irq_set_type = adm5120_intc_irq_set_type -}; - -static struct irqaction adm5120_intc_irq_action = { - .handler = no_action, - .name = "cascade [INTC]" -}; - -static void adm5120_intc_irq_unmask(struct irq_data *d) -{ - intc_write_reg(INTC_REG_IRQ_ENABLE, 1 << (d->irq - ADM5120_INTC_IRQ_BASE)); -} - -static void adm5120_intc_irq_mask(struct irq_data *d) -{ - intc_write_reg(INTC_REG_IRQ_DISABLE, 1 << (d->irq - ADM5120_INTC_IRQ_BASE)); -} - -static int adm5120_intc_irq_set_type(struct irq_data *d, unsigned int flow_type) -{ - unsigned int irq = d->irq; - unsigned int sense; - unsigned long mode; - int err = 0; - - sense = flow_type & (IRQ_TYPE_SENSE_MASK); - switch (sense) { - case IRQ_TYPE_NONE: - case IRQ_TYPE_LEVEL_HIGH: - break; - case IRQ_TYPE_LEVEL_LOW: - switch (irq) { - case ADM5120_IRQ_GPIO2: - case ADM5120_IRQ_GPIO4: - break; - default: - err = -EINVAL; - break; - } - break; - default: - err = -EINVAL; - break; - } - - if (err) - return err; - - switch (irq) { - case ADM5120_IRQ_GPIO2: - case ADM5120_IRQ_GPIO4: - mode = intc_read_reg(INTC_REG_INT_MODE); - if (sense == IRQ_TYPE_LEVEL_LOW) - mode |= (1 << (irq - ADM5120_INTC_IRQ_BASE)); - else - mode &= ~(1 << (irq - ADM5120_INTC_IRQ_BASE)); - - intc_write_reg(INTC_REG_INT_MODE, mode); - break; - } - - return 0; -} - -static void adm5120_intc_irq_dispatch(void) -{ - unsigned long status; - int irq; - - status = intc_read_reg(INTC_REG_IRQ_STATUS) & INTC_INT_ALL; - if (status) { - irq = ADM5120_INTC_IRQ_BASE + fls(status) - 1; - do_IRQ(irq); - } else - spurious_interrupt(); -} - -asmlinkage void plat_irq_dispatch(void) -{ - unsigned long pending; - - pending = read_c0_status() & read_c0_cause() & ST0_IM; - - if (pending & STATUSF_IP7) - do_IRQ(ADM5120_IRQ_COUNTER); - else if (pending & STATUSF_IP2) - adm5120_intc_irq_dispatch(); - else - spurious_interrupt(); -} - -#define INTC_IRQ_STATUS (IRQ_LEVEL | IRQ_TYPE_LEVEL_HIGH | IRQ_DISABLED) -static void __init adm5120_intc_irq_init(void) -{ - int i; - - /* disable all interrupts */ - intc_write_reg(INTC_REG_IRQ_DISABLE, INTC_INT_ALL); - - /* setup all interrupts to generate IRQ instead of FIQ */ - intc_write_reg(INTC_REG_INT_MODE, 0); - - /* set active level for all external interrupts to HIGH */ - intc_write_reg(INTC_REG_INT_LEVEL, 0); - - /* disable usage of the TEST_SOURCE register */ - intc_write_reg(INTC_REG_IRQ_SOURCE_SELECT, 0); - - for (i = ADM5120_INTC_IRQ_BASE; - i <= ADM5120_INTC_IRQ_BASE + INTC_IRQ_LAST; - i++) { - irq_set_chip_and_handler(i, &adm5120_intc_irq_chip, - handle_level_irq); - } - - setup_irq(ADM5120_IRQ_INTC, &adm5120_intc_irq_action); -} - -void __init arch_init_irq(void) -{ - mips_cpu_irq_init(); - adm5120_intc_irq_init(); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/memory.c b/target/linux/adm5120/files/arch/mips/adm5120/common/memory.c deleted file mode 100644 index d07266fa38..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/memory.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#ifdef DEBUG -# define mem_dbg(f, a...) printk(KERN_INFO "mem_detect: " f, ## a) -#else -# define mem_dbg(f, a...) -#endif - -unsigned long adm5120_memsize; - -#define MEM_READL(a) __raw_readl((void __iomem *)(a)) -#define MEM_WRITEL(a, v) __raw_writel((v), (void __iomem *)(a)) - -static int __init mem_check_pattern(u8 *addr, unsigned long offs) -{ - u32 *p1 = (u32 *)addr; - u32 *p2 = (u32 *)(addr+offs); - u32 t, u, v; - - /* save original value */ - t = MEM_READL(p1); - - u = MEM_READL(p2); - if (t != u) - return 0; - - v = 0x55555555; - if (u == v) - v = 0xAAAAAAAA; - - mem_dbg("write 0x%08X to 0x%08lX\n", v, (unsigned long)p1); - - MEM_WRITEL(p1, v); - adm5120_ndelay(1000); - u = MEM_READL(p2); - - mem_dbg("pattern at 0x%08lX is 0x%08X\n", (unsigned long)p2, u); - - /* restore original value */ - MEM_WRITEL(p1, t); - - return (v == u); -} - -static void __init adm5120_detect_memsize(void) -{ - u32 memctrl; - u32 size, maxsize; - u8 *p; - - memctrl = SW_READ_REG(SWITCH_REG_MEMCTRL); - switch (memctrl & MEMCTRL_SDRS_MASK) { - case MEMCTRL_SDRS_4M: - maxsize = 4 << 20; - break; - case MEMCTRL_SDRS_8M: - maxsize = 8 << 20; - break; - case MEMCTRL_SDRS_16M: - maxsize = 16 << 20; - break; - default: - maxsize = 64 << 20; - break; - } - - mem_dbg("checking for %uMB chip in 1st bank\n", maxsize >> 20); - - /* detect size of the 1st SDRAM bank */ - p = (u8 *)KSEG1ADDR(0); - for (size = 2<<20; size <= (maxsize >> 1); size <<= 1) { - if (mem_check_pattern(p, size)) { - /* mirrored address */ - mem_dbg("mirrored data found at offset 0x%08X\n", size); - break; - } - } - - mem_dbg("chip size in 1st bank is %uMB\n", size >> 20); - adm5120_memsize = size; - - if (size != maxsize) - /* 2nd bank is not supported */ - goto out; - - if ((memctrl & MEMCTRL_SDR1_ENABLE) == 0) - /* 2nd bank is disabled */ - goto out; - - /* - * some bootloaders enable 2nd bank, even if the 2nd SDRAM chip - * are missing. - */ - mem_dbg("check presence of 2nd bank\n"); - - p = (u8 *)KSEG1ADDR(maxsize+size-4); - if (mem_check_pattern(p, 0)) - adm5120_memsize += size; - - if (maxsize != size) { - /* adjusting MECTRL register */ - memctrl &= ~(MEMCTRL_SDRS_MASK); - switch (size>>20) { - case 4: - memctrl |= MEMCTRL_SDRS_4M; - break; - case 8: - memctrl |= MEMCTRL_SDRS_8M; - break; - case 16: - memctrl |= MEMCTRL_SDRS_16M; - break; - default: - memctrl |= MEMCTRL_SDRS_64M; - break; - } - SW_WRITE_REG(SWITCH_REG_MEMCTRL, memctrl); - } - -out: - mem_dbg("%dx%uMB memory found\n", (adm5120_memsize == size) ? 1 : 2 , - size>>20); -} - -void __init adm5120_mem_init(void) -{ - adm5120_detect_memsize(); - add_memory_region(0, adm5120_memsize, BOOT_MEM_RAM); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c b/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c deleted file mode 100644 index bdbfbcbae5..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * ADM5120 generic platform devices - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#if 1 -/* - * TODO:remove global adm5120_eth* variables when the switch driver will be - * converted into a real platform driver - */ -unsigned int adm5120_eth_num_ports = 6; -EXPORT_SYMBOL_GPL(adm5120_eth_num_ports); - -unsigned char adm5120_eth_macs[6][6] = { - {'\00', 'A', 'D', 'M', '\x51', '\x20' }, - {'\00', 'A', 'D', 'M', '\x51', '\x21' }, - {'\00', 'A', 'D', 'M', '\x51', '\x22' }, - {'\00', 'A', 'D', 'M', '\x51', '\x23' }, - {'\00', 'A', 'D', 'M', '\x51', '\x24' }, - {'\00', 'A', 'D', 'M', '\x51', '\x25' } -}; -EXPORT_SYMBOL_GPL(adm5120_eth_macs); - -unsigned char adm5120_eth_vlans[6] = { - 0x41, 0x42, 0x44, 0x48, 0x50, 0x60 -}; -EXPORT_SYMBOL_GPL(adm5120_eth_vlans); -#endif - -void __init adm5120_setup_eth_macs(u8 *mac_base) -{ - u32 t; - int i, j; - - t = ((u32) mac_base[3] << 16) | ((u32) mac_base[4] << 8) - | ((u32) mac_base[5]); - - for (i = 0; i < ARRAY_SIZE(adm5120_eth_macs); i++) { - for (j = 0; j < 3; j++) - adm5120_eth_macs[i][j] = mac_base[j]; - - adm5120_eth_macs[i][3] = (t >> 16) & 0xff; - adm5120_eth_macs[i][4] = (t >> 8) & 0xff; - adm5120_eth_macs[i][5] = t & 0xff; - - t++; - } -} - -/* - * Built-in ethernet switch - */ -struct resource adm5120_switch_resources[] = { - [0] = { - .start = ADM5120_SWITCH_BASE, - .end = ADM5120_SWITCH_BASE+ADM5120_SWITCH_SIZE-1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = ADM5120_IRQ_SWITCH, - .end = ADM5120_IRQ_SWITCH, - .flags = IORESOURCE_IRQ, - }, -}; - -struct adm5120_switch_platform_data adm5120_switch_data; -struct platform_device adm5120_switch_device = { - .name = "adm5120-switch", - .id = -1, - .num_resources = ARRAY_SIZE(adm5120_switch_resources), - .resource = adm5120_switch_resources, - .dev.platform_data = &adm5120_switch_data, -}; - -void __init adm5120_add_device_switch(unsigned num_ports, u8 *vlan_map) -{ - if (num_ports > 0) - adm5120_eth_num_ports = num_ports; - - if (vlan_map) - memcpy(adm5120_eth_vlans, vlan_map, sizeof(adm5120_eth_vlans)); - - platform_device_register(&adm5120_switch_device); -} - -/* - * USB Host Controller - */ -struct resource adm5120_hcd_resources[] = { - [0] = { - .start = ADM5120_USBC_BASE, - .end = ADM5120_USBC_BASE+ADM5120_USBC_SIZE-1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = ADM5120_IRQ_USBC, - .end = ADM5120_IRQ_USBC, - .flags = IORESOURCE_IRQ, - }, -}; - -static u64 adm5120_hcd_dma_mask = DMA_BIT_MASK(24); -struct platform_device adm5120_hcd_device = { - .name = "adm5120-hcd", - .id = -1, - .num_resources = ARRAY_SIZE(adm5120_hcd_resources), - .resource = adm5120_hcd_resources, - .dev = { - .dma_mask = &adm5120_hcd_dma_mask, - .coherent_dma_mask = DMA_BIT_MASK(24), - } -}; - -void __init adm5120_add_device_usb(void) -{ - platform_device_register(&adm5120_hcd_device); -} - -/* - * NOR flash devices - */ -struct adm5120_flash_platform_data adm5120_flash0_data; -struct platform_device adm5120_flash0_device = { - .name = "adm5120-flash", - .id = 0, - .dev.platform_data = &adm5120_flash0_data, -}; - -struct adm5120_flash_platform_data adm5120_flash1_data; -struct platform_device adm5120_flash1_device = { - .name = "adm5120-flash", - .id = 1, - .dev.platform_data = &adm5120_flash1_data, -}; - -void __init adm5120_add_device_flash(unsigned id) -{ - struct platform_device *pdev; - - switch (id) { - case 0: - pdev = &adm5120_flash0_device; - break; - case 1: - pdev = &adm5120_flash1_device; - break; - default: - pdev = NULL; - break; - } - - if (pdev) - platform_device_register(pdev); -} - -/* - * built-in UARTs - */ -static void adm5120_uart_set_mctrl(struct amba_device *dev, void __iomem *base, - unsigned int mctrl) -{ -} - -struct amba_pl010_data adm5120_uart0_data = { - .set_mctrl = adm5120_uart_set_mctrl -}; - -struct amba_device adm5120_uart0_device = { - .dev = { - .init_name = "apb:uart0", - .platform_data = &adm5120_uart0_data, - }, - .res = { - .start = ADM5120_UART0_BASE, - .end = ADM5120_UART0_BASE + ADM5120_UART_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { ADM5120_IRQ_UART0, 0 }, - .periphid = 0x0041010, -}; - -struct amba_pl010_data adm5120_uart1_data = { - .set_mctrl = adm5120_uart_set_mctrl -}; - -struct amba_device adm5120_uart1_device = { - .dev = { - .init_name = "apb:uart1", - .platform_data = &adm5120_uart1_data, - }, - .res = { - .start = ADM5120_UART1_BASE, - .end = ADM5120_UART1_BASE + ADM5120_UART_SIZE - 1, - .flags = IORESOURCE_MEM, - }, - .irq = { ADM5120_IRQ_UART1, 0 }, - .periphid = 0x0041010, -}; - -void __init adm5120_add_device_uart(unsigned id) -{ - struct amba_device *dev; - - switch (id) { - case 0: - dev = &adm5120_uart0_device; - break; - case 1: - dev = &adm5120_uart1_device; - break; - default: - dev = NULL; - break; - } - - if (dev) - amba_device_register(dev, &iomem_resource); -} - -/* - * GPIO buttons - */ -void __init adm5120_register_gpio_buttons(int id, - unsigned poll_interval, - unsigned nbuttons, - struct gpio_keys_button *buttons) -{ - struct platform_device *pdev; - struct gpio_keys_platform_data pdata; - struct gpio_keys_button *p; - int err; - - p = kmemdup(buttons, nbuttons * sizeof(*p), GFP_KERNEL); - if (!p) - return; - - pdev = platform_device_alloc("gpio-keys-polled", id); - if (!pdev) - goto err_free_buttons; - - memset(&pdata, 0, sizeof(pdata)); - pdata.poll_interval = poll_interval; - pdata.nbuttons = nbuttons; - pdata.buttons = p; - - err = platform_device_add_data(pdev, &pdata, sizeof(pdata)); - if (err) - goto err_put_pdev; - - err = platform_device_add(pdev); - if (err) - goto err_put_pdev; - - return; - -err_put_pdev: - platform_device_put(pdev); - -err_free_buttons: - kfree(p); -} - -/* - * GPIO LEDS - */ -struct gpio_led_platform_data adm5120_gpio_leds_data; -struct platform_device adm5120_gpio_leds_device = { - .name = "leds-gpio", - .id = -1, - .dev.platform_data = &adm5120_gpio_leds_data, -}; - -void __init adm5120_add_device_gpio_leds(unsigned num_leds, - struct gpio_led *leds) -{ - struct gpio_led *p; - - p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memcpy(p, leds, num_leds * sizeof(*p)); - adm5120_gpio_leds_data.num_leds = num_leds; - adm5120_gpio_leds_data.leds = p; - - platform_device_register(&adm5120_gpio_leds_device); -} - -/* - * NAND flash - */ -struct resource adm5120_nand_resources[] = { - [0] = { - .start = ADM5120_NAND_BASE, - .end = ADM5120_NAND_BASE + ADM5120_NAND_SIZE-1, - .flags = IORESOURCE_MEM, - }, -}; - -static int adm5120_nand_ready(struct mtd_info *mtd) -{ - return ((adm5120_nand_get_status() & ADM5120_NAND_STATUS_READY) != 0); -} - -static void adm5120_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) -{ - if (ctrl & NAND_CTRL_CHANGE) { - adm5120_nand_set_cle(ctrl & NAND_CLE); - adm5120_nand_set_ale(ctrl & NAND_ALE); - adm5120_nand_set_cen(ctrl & NAND_NCE); - } - - if (cmd != NAND_CMD_NONE) - NAND_WRITE_REG(NAND_REG_DATA, cmd); -} - -void __init adm5120_add_device_nand(struct platform_nand_data *pdata) -{ - struct platform_device *pdev; - int err; - - pdev = platform_device_alloc("gen_nand", -1); - if (!pdev) - goto err_out; - - err = platform_device_add_resources(pdev, adm5120_nand_resources, - ARRAY_SIZE(adm5120_nand_resources)); - if (err) - goto err_put; - - err = platform_device_add_data(pdev, pdata, sizeof(*pdata)); - if (err) - goto err_put; - - pdata = pdev->dev.platform_data; - pdata->ctrl.dev_ready = adm5120_nand_ready; - pdata->ctrl.cmd_ctrl = adm5120_nand_cmd_ctrl; - - err = platform_device_add(pdev); - if (err) - goto err_put; - - return; - -err_put: - platform_device_put(pdev); -err_out: - return; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c b/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c deleted file mode 100644 index 5c52ea27e2..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * ADM5120 specific prom routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include - -#include - -#include -#include -#include -#include -#include - -unsigned int adm5120_prom_type = ADM5120_PROM_GENERIC; - -struct board_desc { - unsigned long mach_type; - char *name; -}; - -#define DEFBOARD(n, mt) { .mach_type = (mt), .name = (n)} -static struct board_desc common_boards[] __initdata = { - /* Cellvision/SparkLAN boards */ - DEFBOARD("CAS-630", MACH_ADM5120_CAS630), - DEFBOARD("CAS-670", MACH_ADM5120_CAS670), - DEFBOARD("CAS-700", MACH_ADM5120_CAS700), - DEFBOARD("CAS-771", MACH_ADM5120_CAS771), - DEFBOARD("CAS-790", MACH_ADM5120_CAS790), - DEFBOARD("CAS-861", MACH_ADM5120_CAS861), - DEFBOARD("NFS-101U", MACH_ADM5120_NFS101U), - /* Compex boards */ - DEFBOARD("WP54G-WRT", MACH_ADM5120_WP54G_WRT), - /* Edimax boards */ - DEFBOARD("BR-6104K", MACH_ADM5120_BR6104K), - DEFBOARD("BR-6104KP", MACH_ADM5120_BR6104KP), - DEFBOARD("BR-6104WG", MACH_ADM5120_BR61X4WG), - DEFBOARD("BR-6114WG", MACH_ADM5120_BR61X4WG), - /* Infineon boards */ - DEFBOARD("EASY 5120P-ATA", MACH_ADM5120_EASY5120PATA), - DEFBOARD("EASY 5120-RT", MACH_ADM5120_EASY5120RT), - DEFBOARD("EASY 5120-WVoIP", MACH_ADM5120_EASY5120WVOIP), - DEFBOARD("EASY 83000", MACH_ADM5120_EASY83000), - /* Mikrotik RouterBOARDs */ - DEFBOARD("111", MACH_ADM5120_RB_11X), - DEFBOARD("112", MACH_ADM5120_RB_11X), - DEFBOARD("133", MACH_ADM5120_RB_133), - DEFBOARD("133C", MACH_ADM5120_RB_133C), - DEFBOARD("133C3", MACH_ADM5120_RB_133C), - DEFBOARD("150", MACH_ADM5120_RB_153), /* it's intentional */ - DEFBOARD("153", MACH_ADM5120_RB_153), - DEFBOARD("192", MACH_ADM5120_RB_192), - DEFBOARD("miniROUTER", MACH_ADM5120_RB_150), - /* OSBRiDGE boards */ - DEFBOARD("OSBRiDGE 5GXi", MACH_ADM5120_5GXI), - /* Motorola boards */ - DEFBOARD("Powerline MU Gateway", MACH_ADM5120_PMUGW), - /* Generic EB-214A */ - DEFBOARD("ADM5120", MACH_ADM5120_EB_214A), -}; - -static unsigned long __init find_machtype_byname(char *name) -{ - unsigned long ret; - int i; - - ret = MACH_ADM5120_GENERIC; - if (name == NULL) - goto out; - - if (*name == '\0') - goto out; - - for (i = 0; i < ARRAY_SIZE(common_boards); i++) { - if (strcmp(common_boards[i].name, name) == 0) { - ret = common_boards[i].mach_type; - break; - } - } - -out: - return ret; -} - -static unsigned long __init detect_machtype_routerboot(void) -{ - char *name; - - name = routerboot_get_boardname(); - return find_machtype_byname(name); -} - -static unsigned long __init detect_machtype_generic(void) -{ - char *name; - - name = generic_prom_getenv("board_name"); - return find_machtype_byname(name); -} - -unsigned long __init detect_machtype_cfe(void) -{ - char *name; - - name = cfe_getenv("BOARD_NAME"); - return find_machtype_byname(name); -} - -static struct { - unsigned long mach_type; - u16 vendor_id; - u16 board_id; -} zynos_boards[] __initdata = { -#define ZYNOS_BOARD(vi, bi, mt) \ - {.vendor_id = (vi), .board_id = (bi), .mach_type = (mt)} - -#define ZYXEL_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_ZYXEL, bi, mt) -#define DLINK_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_DLINK, bi, mt) -#define LUCENT_BOARD(bi, mt) ZYNOS_BOARD(ZYNOS_VENDOR_ID_LUCENT, bi, mt) - ZYXEL_BOARD(ZYNOS_BOARD_HS100, MACH_ADM5120_HS100), - ZYXEL_BOARD(ZYNOS_BOARD_P334U, MACH_ADM5120_P334U), - ZYXEL_BOARD(ZYNOS_BOARD_P334W, MACH_ADM5120_P334W), - ZYXEL_BOARD(ZYNOS_BOARD_P334WH, MACH_ADM5120_P334WH), - ZYXEL_BOARD(ZYNOS_BOARD_P334WHD, MACH_ADM5120_P334WHD), - ZYXEL_BOARD(ZYNOS_BOARD_P334WT, MACH_ADM5120_P334WT), - ZYXEL_BOARD(ZYNOS_BOARD_P334WT_ALT, MACH_ADM5120_P334WT), - ZYXEL_BOARD(ZYNOS_BOARD_P335, MACH_ADM5120_P335), - ZYXEL_BOARD(ZYNOS_BOARD_P335PLUS, MACH_ADM5120_P335PLUS), - ZYXEL_BOARD(ZYNOS_BOARD_P335U, MACH_ADM5120_P335U) -}; - -static unsigned long __init detect_machtype_bootbase(void) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(zynos_boards); i++) { - if (zynos_boards[i].vendor_id == bootbase_info.vendor_id && - zynos_boards[i].board_id == bootbase_info.board_id) { - return zynos_boards[i].mach_type; - break; - } - } - - printk(KERN_WARNING "Unknown ZyXEL model (%u)\n", - bootbase_info.board_id); - return MACH_ADM5120_GENERIC; -} - -static struct { - unsigned long mach_type; - u16 vid; - u16 did; - u16 svid; - u16 sdid; -} mylo_boards[] __initdata = { -#define MYLO_BOARD(v, d, sv, sd, mt) \ - {.vid = (v), .did = (d), .svid = (sv), .sdid = (sd), .mach_type = (mt)} -#define COMPEX_BOARD(d, mt) \ - MYLO_BOARD(VENID_COMPEX, (d), VENID_COMPEX, (d), (mt)) - - COMPEX_BOARD(DEVID_COMPEX_NP27G, MACH_ADM5120_NP27G), - COMPEX_BOARD(DEVID_COMPEX_NP28G, MACH_ADM5120_NP28G), - COMPEX_BOARD(DEVID_COMPEX_NP28GHS, MACH_ADM5120_NP28GHS), - COMPEX_BOARD(DEVID_COMPEX_WP54G, MACH_ADM5120_WP54), - COMPEX_BOARD(DEVID_COMPEX_WP54Gv1C, MACH_ADM5120_WP54Gv1C), - COMPEX_BOARD(DEVID_COMPEX_WP54AG, MACH_ADM5120_WP54), - COMPEX_BOARD(DEVID_COMPEX_WPP54G, MACH_ADM5120_WP54), - COMPEX_BOARD(DEVID_COMPEX_WPP54AG, MACH_ADM5120_WP54), -}; - -static unsigned long __init detect_machtype_myloader(void) -{ - unsigned long ret; - int i; - - ret = MACH_ADM5120_GENERIC; - for (i = 0; i < ARRAY_SIZE(mylo_boards); i++) { - if (mylo_boards[i].vid == myloader_info.vid && - mylo_boards[i].did == myloader_info.did && - mylo_boards[i].svid == myloader_info.svid && - mylo_boards[i].sdid == myloader_info.sdid) { - ret = mylo_boards[i].mach_type; - break; - } - } - - return ret; -} - -static void __init prom_detect_machtype(void) -{ - if (bootbase_present()) { - adm5120_prom_type = ADM5120_PROM_BOOTBASE; - mips_machtype = detect_machtype_bootbase(); - return; - } - - if (cfe_present()) { - adm5120_prom_type = ADM5120_PROM_CFE; - mips_machtype = detect_machtype_cfe(); - return; - } - - if (myloader_present()) { - adm5120_prom_type = ADM5120_PROM_MYLOADER; - mips_machtype = detect_machtype_myloader(); - return; - } - - if (routerboot_present()) { - adm5120_prom_type = ADM5120_PROM_ROUTERBOOT; - mips_machtype = detect_machtype_routerboot(); - return; - } - - if (generic_prom_present()) { - adm5120_prom_type = ADM5120_PROM_GENERIC; - mips_machtype = detect_machtype_generic(); - return; - } - - mips_machtype = MACH_ADM5120_GENERIC; -} - -#ifdef CONFIG_IMAGE_CMDLINE_HACK -extern char __image_cmdline[]; - -static void __init prom_init_cmdline(void) -{ - char *cmd; - - /* init command line, register a default kernel command line */ - cmd = __image_cmdline; - if (strlen(cmd) > 0) - strlcpy(arcs_cmdline, cmd, sizeof(arcs_cmdline)); - -} -#else -static inline void prom_init_cmdline(void) {} -#endif /* CONFIG_IMAGE_CMDLINE_HACK */ - -void __init prom_init(void) -{ - prom_detect_machtype(); - prom_init_cmdline(); -} - -void __init prom_free_prom_memory(void) -{ - /* We do not have to prom memory to free */ -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c b/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c deleted file mode 100644 index c4be845170..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ADM5120 specific setup - * - * Copyright (C) 2007-2009 Gabor Juhos - * - * This code was based on the ADM5120 specific port of the Linux 2.6.10 kernel - * done by Jeroen Vreeken - * Copyright (C) 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * Jeroen's code was based on the Linux 2.4.xx source codes found in various - * tarballs released by Edimax for it's ADM5120 based devices - * Copyright (C) ADMtek Incorporated - * - * 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 -#include -#include -#include - -#define ADM5120_SYS_TYPE_LEN 64 - -unsigned char adm5120_sys_type[ADM5120_SYS_TYPE_LEN]; -void (*adm5120_board_reset)(void); - -static char *prom_names[ADM5120_PROM_LAST+1] __initdata = { - [ADM5120_PROM_GENERIC] = "Generic", - [ADM5120_PROM_CFE] = "CFE", - [ADM5120_PROM_UBOOT] = "U-Boot", - [ADM5120_PROM_MYLOADER] = "MyLoader", - [ADM5120_PROM_ROUTERBOOT] = "RouterBOOT", - [ADM5120_PROM_BOOTBASE] = "Bootbase" -}; - -static void __init adm5120_report(void) -{ - printk(KERN_INFO "SoC : %s\n", adm5120_sys_type); - printk(KERN_INFO "Bootdev : %s flash\n", - adm5120_nand_boot ? "NAND" : "NOR"); - printk(KERN_INFO "Prom : %s\n", prom_names[adm5120_prom_type]); -} - -const char *get_system_type(void) -{ - return adm5120_sys_type; -} - -static void adm5120_restart(char *command) -{ - /* TODO: stop switch before reset */ - - if (adm5120_board_reset) - adm5120_board_reset(); - - SW_WRITE_REG(SWITCH_REG_SOFT_RESET, 1); -} - -static void adm5120_halt(void) -{ - local_irq_disable(); - - while (1) { - if (cpu_wait) - cpu_wait(); - } -} - -void __init plat_time_init(void) -{ - mips_hpt_frequency = adm5120_speed / 2; -} - -void __init plat_mem_setup(void) -{ - adm5120_soc_init(); - adm5120_mem_init(); - - sprintf(adm5120_sys_type, "ADM%04X%s rev %u, running at %lu.%03lu MHz", - adm5120_product_code, - adm5120_package_bga() ? "" : "P", - adm5120_revision, - (adm5120_speed / 1000000), (adm5120_speed / 1000) % 1000); - - adm5120_report(); - - _machine_restart = adm5120_restart; - _machine_halt = adm5120_halt; - pm_power_off = adm5120_halt; - - set_io_port_base(KSEG1); -} - -static int __init adm5120_board_setup(void) -{ - adm5120_gpio_init(); - - mips_machine_setup(); - - return 0; -} -arch_initcall(adm5120_board_setup); - -static void __init adm5120_generic_board_setup(void) -{ - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_flash(0); - adm5120_add_device_switch(6, NULL); -} - -MIPS_MACHINE(MACH_ADM5120_GENERIC, "Generic", "Generic ADM5120 board", - adm5120_generic_board_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/compex/Makefile deleted file mode 100644 index 8c66c171e7..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-y += compex.o - -obj-$(CONFIG_ADM5120_MACH_NP27G) += np27g.o -obj-$(CONFIG_ADM5120_MACH_NP28G) += np28g.o -obj-$(CONFIG_ADM5120_MACH_WP54) += wp54.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.c b/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.c deleted file mode 100644 index 814acfb0cf..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Compex boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "compex.h" - -#include - -static void switch_bank_gpio5(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(ADM5120_GPIO_PIN5, 0); - break; - case 1: - gpio_set_value(ADM5120_GPIO_PIN5, 1); - break; - } -} - -void __init compex_mac_setup(void) -{ - if (myloader_present()) { - int i; - - for (i = 0; i < 6; i++) { - if (is_valid_ether_addr(myloader_info.macs[i])) - memcpy(adm5120_eth_macs[i], - myloader_info.macs[i], ETH_ALEN); - else - random_ether_addr(adm5120_eth_macs[i]); - } - } else { - u8 mac[ETH_ALEN]; - - random_ether_addr(mac); - adm5120_setup_eth_macs(mac); - } -} - -void __init compex_generic_setup(void) -{ - gpio_request(ADM5120_GPIO_PIN5, NULL); /* for flash A20 line */ - gpio_direction_output(ADM5120_GPIO_PIN5, 0); - - adm5120_flash0_data.switch_bank = switch_bank_gpio5; - adm5120_add_device_flash(0); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - compex_mac_setup(); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.h b/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.h deleted file mode 100644 index 124e676971..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Compex boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -extern void compex_generic_setup(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/np27g.c b/target/linux/adm5120/files/arch/mips/adm5120/compex/np27g.c deleted file mode 100644 index 82da46d1c7..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/np27g.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Compex NP27G board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "compex.h" - -static u8 np27g_vlans[6] __initdata = { - /* FIXME: untested */ - 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 -}; - -static void __init np27g_setup(void) -{ - compex_generic_setup(); - adm5120_add_device_switch(5, np27g_vlans); - adm5120_add_device_usb(); - - /* TODO: add PCI IRQ map */ -} - -MIPS_MACHINE(MACH_ADM5120_NP27G, "NP27G", "Compex NetPassage 27G", np27g_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/np28g.c b/target/linux/adm5120/files/arch/mips/adm5120/compex/np28g.c deleted file mode 100644 index a541439998..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/np28g.c +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Compex NP28G board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "compex.h" - -static struct adm5120_pci_irq np28g_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), - PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI0), - PCIIRQ(3, 1, 2, ADM5120_IRQ_PCI1), - PCIIRQ(3, 2, 3, ADM5120_IRQ_PCI2) -}; - -static struct gpio_led np28g_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN2, "diag", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN3, "power", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN6, "wan_cond", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN7, "wifi", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L2, "usb1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L2, "usb2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L2, "usb3", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L2, "usb4", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), -}; - -static u8 np28g_vlans[6] __initdata = { - 0x50, 0x42, 0x44, 0x48, 0x00, 0x00 -}; - -static void np28g_reset(void) -{ - gpio_set_value(ADM5120_GPIO_PIN4, 0); -} - -static void __init np28g_setup(void) -{ - compex_generic_setup(); - - /* setup reset line */ - gpio_request(ADM5120_GPIO_PIN4, NULL); - gpio_direction_output(ADM5120_GPIO_PIN4, 1); - adm5120_board_reset = np28g_reset; - - adm5120_add_device_switch(4, np28g_vlans); - adm5120_add_device_usb(); - - adm5120_add_device_gpio_leds(ARRAY_SIZE(np28g_gpio_leds), - np28g_gpio_leds); - - adm5120_pci_set_irq_map(ARRAY_SIZE(np28g_pci_irqs), np28g_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_NP28G, "NP28G", "Compex NetPassage 28G", np28g_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/wp54.c b/target/linux/adm5120/files/arch/mips/adm5120/compex/wp54.c deleted file mode 100644 index 8aa35c555a..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/compex/wp54.c +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Compex WP54 board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "compex.h" - -#define WP54_KEYS_POLL_INTERVAL 20 -#define WP54_KEYS_DEBOUNCE_INTERVAL (3 * WP54_KEYS_POLL_INTERVAL) - -static struct mtd_partition wp54g_wrt_partitions[] = { - { - .name = "cfe", - .offset = 0, - .size = 0x050000, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "trx", - .offset = MTDPART_OFS_APPEND, - .size = 0x3A0000, - } , { - .name = "nvram", - .offset = MTDPART_OFS_APPEND, - .size = 0x010000, - } -}; - -static struct adm5120_pci_irq wp54_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static struct gpio_keys_button wp54_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = KEY_RESTART, - .debounce_interval = WP54_KEYS_DEBOUNCE_INTERVAL, - .gpio = ADM5120_GPIO_PIN4, - } -}; - -static struct gpio_led wp54_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN2, "diag", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN6, "wlan", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN7, "wan", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan2", NULL), -}; - -static u8 wp54_vlans[6] __initdata = { - 0x41, 0x42, 0x00, 0x00, 0x00, 0x00 -}; - -static void wp54_reset(void) -{ - gpio_set_value(ADM5120_GPIO_PIN3, 0); -} - -static void __init wp54_setup(void) -{ - compex_generic_setup(); - - /* setup reset line */ - gpio_request(ADM5120_GPIO_PIN3, NULL); - gpio_direction_output(ADM5120_GPIO_PIN3, 1); - adm5120_board_reset = wp54_reset; - - adm5120_add_device_switch(2, wp54_vlans); - adm5120_register_gpio_buttons(-1, WP54_KEYS_POLL_INTERVAL, - ARRAY_SIZE(wp54_gpio_buttons), - wp54_gpio_buttons); - adm5120_add_device_gpio_leds(ARRAY_SIZE(wp54_gpio_leds), - wp54_gpio_leds); - - adm5120_pci_set_irq_map(ARRAY_SIZE(wp54_pci_irqs), wp54_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_WP54, "WP54", "Compex WP54 family", wp54_setup); - -static void __init wp54_wrt_setup(void) -{ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(wp54g_wrt_partitions); - adm5120_flash0_data.parts = wp54g_wrt_partitions; - - wp54_setup(); -} - -MIPS_MACHINE(MACH_ADM5120_WP54G_WRT, "WP54G-WRT", "Compex WP54G-WRT", - wp54_wrt_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/edimax/Makefile deleted file mode 100644 index 1286ed4c1e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-y := br-61xx.o - -obj-$(CONFIG_ADM5120_MACH_BR_6104K) += br-6104k.o -obj-$(CONFIG_ADM5120_MACH_BR_6104KP) += br-6104kp.o -obj-$(CONFIG_ADM5120_MACH_BR_61X4WG) += br-61x4wg.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104k.c b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104k.c deleted file mode 100644 index 8b2b445506..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104k.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Edimax BR-6104K board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "br-61xx.h" - -static struct gpio_led br6104k_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), -}; - -static void __init br6104k_setup(void) -{ - br61xx_generic_setup(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(br6104k_gpio_leds), - br6104k_gpio_leds); -} - -MIPS_MACHINE(MACH_ADM5120_BR6104K, "BR-6104K", "Edimax BR-6104K", - br6104k_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104kp.c b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104kp.c deleted file mode 100644 index 034575d6b2..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104kp.c +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Edimax BR-6104KP board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "br-61xx.h" - -static struct gpio_led br6104kp_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN3, "usb1", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN1, "usb2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), -}; - -static void __init br6104kp_setup(void) -{ - br61xx_generic_setup(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(br6104kp_gpio_leds), - br6104kp_gpio_leds); - adm5120_add_device_usb(); -} - -MIPS_MACHINE(MACH_ADM5120_BR6104KP, "BR-6104KP", "Edimax BR-6104KP", - br6104kp_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61x4wg.c b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61x4wg.c deleted file mode 100644 index 5d57507101..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61x4wg.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Edimax BR-6104Wg/6114WG board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "br-61xx.h" - -static struct adm5120_pci_irq br61x4wg_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static struct gpio_led br61x4wg_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN0, "power", NULL), - GPIO_LED_STD(ADM5120_GPIO_PIN5, "wlan", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "wan_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "wan_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan4_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan4_lnkact", NULL), -}; - -static void __init br61x4wg_setup(void) -{ - br61xx_generic_setup(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(br61x4wg_gpio_leds), - br61x4wg_gpio_leds); - adm5120_pci_set_irq_map(ARRAY_SIZE(br61x4wg_pci_irqs), - br61x4wg_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_BR61X4WG, "BR-6104WG", "Edimax BR-6104WG/6114WG", - br61x4wg_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.c b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.c deleted file mode 100644 index 62a1cee384..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Edimax BR-61xx support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "br-61xx.h" - -#include - -#define BR61XX_CONFIG_OFFSET 0x8000 -#define BR61XX_CONFIG_SIZE 0x1000 - -#define BR61XX_KEYS_POLL_INTERVAL 20 -#define BR61XX_KEYS_DEBOUNCE_INTERVAL (3 * BR61XX_KEYS_POLL_INTERVAL) - -static struct mtd_partition br61xx_partitions[] = { - { - .name = "admboot", - .offset = 0, - .size = 32*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "config", - .offset = MTDPART_OFS_APPEND, - .size = 32*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct gpio_keys_button br61xx_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = KEY_RESTART, - .debounce_interval = BR61XX_KEYS_DEBOUNCE_INTERVAL, - .gpio = ADM5120_GPIO_PIN2, - } -}; - -static u8 br61xx_vlans[6] __initdata = { - 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 -}; - -static void __init br61xx_mac_setup(void) -{ - u8 mac_base[6]; - int err; - - err = admboot_get_mac_base(BR61XX_CONFIG_OFFSET, - BR61XX_CONFIG_SIZE, mac_base); - - if ((err) || !is_valid_ether_addr(mac_base)) - random_ether_addr(mac_base); - - adm5120_setup_eth_macs(mac_base); -} - -void __init br61xx_generic_setup(void) -{ - - adm5120_flash0_data.nr_parts = ARRAY_SIZE(br61xx_partitions); - adm5120_flash0_data.parts = br61xx_partitions; - adm5120_add_device_flash(0); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_switch(5, br61xx_vlans); - - adm5120_register_gpio_buttons(-1, BR61XX_KEYS_POLL_INTERVAL, - ARRAY_SIZE(br61xx_gpio_buttons), - br61xx_gpio_buttons); - - br61xx_mac_setup(); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.h b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.h deleted file mode 100644 index c4a9eced56..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Edimax BR-61xx board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include - -extern void __init br61xx_generic_setup(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/generic/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/generic/Makefile deleted file mode 100644 index 0c032e3a52..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/generic/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ADM5120_MACH_EB_214A) += eb-214a.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/generic/eb-214a.c b/target/linux/adm5120/files/arch/mips/adm5120/generic/eb-214a.c deleted file mode 100644 index cf491a1efc..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/generic/eb-214a.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * EB-214A board support - * - * Copyright (C) 2007-2008 Gabor Juhos - * Copyright (C) 2010 Cezary Jackiewicz - * - * 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 -#include - - -#define EB214A_CONFIG_OFFSET 0x4000 - -#define EB214A_KEYS_POLL_INTERVAL 20 -#define EB214A_KEYS_DEBOUNCE_INTERVAL (3 * EB214A_KEYS_POLL_INTERVAL) - -static struct mtd_partition eb214a_partitions[] = { - { - .name = "bootloader", - .offset = 0, - .size = 32*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "config", - .offset = MTDPART_OFS_APPEND, - .size = 32*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct adm5120_pci_irq eb214a_pci_irqs[] __initdata = { - PCIIRQ(4, 0, 1, ADM5120_IRQ_PCI0), - PCIIRQ(4, 1, 2, ADM5120_IRQ_PCI0), - PCIIRQ(4, 2, 3, ADM5120_IRQ_PCI0), -}; - -static struct gpio_led eb214a_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN7, "power", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "usb1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "usb2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L2, "usb3", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "usb4", NULL), -}; - -static struct gpio_keys_button eb214a_gpio_buttons[] __initdata = { - { - .desc = "reset", - .type = EV_KEY, - .code = KEY_RESTART, - .debounce_interval = EB214A_KEYS_DEBOUNCE_INTERVAL, - .gpio = ADM5120_GPIO_PIN1, - } -}; - -static u8 eb214a_vlans[6] __initdata = { - 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 -}; - -static void __init eb214a_mac_setup(void) -{ - u8 mac_base[6]; - u8 *cfg; - int i; - - cfg = (u8 *) KSEG1ADDR(ADM5120_SRAM0_BASE + EB214A_CONFIG_OFFSET); - for (i = 0; i < 6; i++) - mac_base[i] = cfg[i]; - - if (!is_valid_ether_addr(mac_base)) - random_ether_addr(mac_base); - - adm5120_setup_eth_macs(mac_base); -} - -static void __init eb214a_setup(void) -{ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(eb214a_partitions); - adm5120_flash0_data.parts = eb214a_partitions; - adm5120_add_device_flash(0); - - adm5120_add_device_uart(0); - /* adm5120_add_device_uart(1); */ - - adm5120_add_device_switch(5, eb214a_vlans); - - eb214a_mac_setup(); - - adm5120_register_gpio_buttons(-1, EB214A_KEYS_POLL_INTERVAL, - ARRAY_SIZE(eb214a_gpio_buttons), - eb214a_gpio_buttons); - - adm5120_add_device_gpio_leds(ARRAY_SIZE(eb214a_gpio_leds), - eb214a_gpio_leds); - - adm5120_pci_set_irq_map(ARRAY_SIZE(eb214a_pci_irqs), - eb214a_pci_irqs); - /* adm5120_add_device_usb(); */ -} - -MIPS_MACHINE(MACH_ADM5120_EB_214A, "EB-214A", "Generic EB-214A", eb214a_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/infineon/Makefile deleted file mode 100644 index 49453cba9a..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-y += infineon.o - -obj-$(CONFIG_ADM5120_MACH_EASY5120_RT) += easy5120-rt.o -obj-$(CONFIG_ADM5120_MACH_EASY5120_WVOIP) += easy5120-wvoip.o -obj-$(CONFIG_ADM5120_MACH_EASY5120P_ATA) += easy5120p-ata.o -obj-$(CONFIG_ADM5120_MACH_EASY83000) += easy83000.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-rt.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-rt.c deleted file mode 100644 index 31eaee7721..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-rt.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Infineon EASY 5120-RT Reference Board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "infineon.h" - -static struct gpio_led easy5120_rt_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN6, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan0_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan0_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan1_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan1_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan2_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), -}; - -static struct adm5120_pci_irq easy5120_rt_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static u8 easy5120_rt_vlans[6] __initdata = { - 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 -}; - -static void __init easy5120_rt_setup(void) -{ - easy_setup_bga(); - - adm5120_add_device_switch(5, easy5120_rt_vlans); - adm5120_add_device_usb(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(easy5120_rt_gpio_leds), - easy5120_rt_gpio_leds); - adm5120_pci_set_irq_map(ARRAY_SIZE(easy5120_rt_pci_irqs), - easy5120_rt_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_EASY5120RT, "EASY5120-RT", - "Infineon EASY 5120-RT Reference Board", easy5120_rt_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-wvoip.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-wvoip.c deleted file mode 100644 index 0bf404cc26..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-wvoip.c +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Infineon EASY 5120-WVoIP Reference Board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "infineon.h" - -static void __init easy5120wvoip_setup(void) -{ - easy_setup_bga(); - adm5120_add_device_switch(6, NULL); - - /* TODO: add VINETIC2 device */ - /* TODO: setup PCI IRQ map */ -} - -MIPS_MACHINE(MACH_ADM5120_EASY5120WVOIP, "EASY5120WVoIP", - "Infineon EASY 5120-WVoIP Reference Board", easy5120wvoip_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120p-ata.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120p-ata.c deleted file mode 100644 index fafe0238bd..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120p-ata.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Infineon EASY 5120P-ATA Reference Board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "infineon.h" - -static void __init easy5120pata_setup(void) -{ - easy_setup_pqfp(); - - adm5120_add_device_switch(6, NULL); -} - -MIPS_MACHINE(MACH_ADM5120_EASY5120PATA, "EASY5120P-ATA", - "Infineon EASY 5120P-ATA Reference Board", easy5120pata_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy83000.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy83000.c deleted file mode 100644 index 051b852749..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy83000.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Infineon EASY 83000 Reference Board support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "infineon.h" - -static void __init easy83000_setup(void) -{ - easy_setup_pqfp(); - adm5120_add_device_switch(6, NULL); - - /* TODO: add VINAX device */ -} - -MIPS_MACHINE(MACH_ADM5120_EASY83000, "EASY8300", - "Infineon EASY 83000 Reference Board", easy83000_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.c deleted file mode 100644 index 5c441da90e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Infineon Reference Boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "infineon.h" - -#include - -#define EASY_CONFIG_OFFSET 0x10000 -#define EASY_CONFIG_SIZE 0x1000 - -static struct mtd_partition easy_partitions[] = { - { - .name = "admboot", - .offset = 0, - .size = 64*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "boardcfg", - .offset = MTDPART_OFS_APPEND, - .size = 64*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static __init void easy_setup_mac(void) -{ - u8 mac_base[6]; - int err; - - err = admboot_get_mac_base(EASY_CONFIG_OFFSET, - EASY_CONFIG_SIZE, mac_base); - - if ((err) || !is_valid_ether_addr(mac_base)) - random_ether_addr(mac_base); - - adm5120_setup_eth_macs(mac_base); -} - -static void switch_bank_gpio3(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(ADM5120_GPIO_PIN3, 0); - break; - case 1: - gpio_set_value(ADM5120_GPIO_PIN3, 1); - break; - } -} - -void __init easy_setup_pqfp(void) -{ - /* setup flash A20 line */ - gpio_request(ADM5120_GPIO_PIN3, NULL); - gpio_direction_output(ADM5120_GPIO_PIN3, 0); - adm5120_flash0_data.switch_bank = switch_bank_gpio3; - - adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); - adm5120_flash0_data.parts = easy_partitions; - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_flash(0); - - easy_setup_mac(); -} - -static void switch_bank_gpio5(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(ADM5120_GPIO_PIN5, 0); - break; - case 1: - gpio_set_value(ADM5120_GPIO_PIN5, 1); - break; - } -} - -void __init easy_setup_bga(void) -{ - /* setup flash A20 line */ - gpio_request(ADM5120_GPIO_PIN5, NULL); - gpio_direction_output(ADM5120_GPIO_PIN5, 0); - adm5120_flash0_data.switch_bank = switch_bank_gpio5; - - adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); - adm5120_flash0_data.parts = easy_partitions; - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_flash(0); - - easy_setup_mac(); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.h b/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.h deleted file mode 100644 index a5f28b4fec..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Infineon Reference Boards - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -extern void easy_setup_pqfp(void) __init; -extern void easy_setup_bga(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/Makefile deleted file mode 100644 index 34ea0a3d88..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-y += rb-1xx.o - -obj-${CONFIG_ADM5120_MACH_RB_11X} += rb-11x.o -obj-${CONFIG_ADM5120_MACH_RB_133} += rb-133.o -obj-${CONFIG_ADM5120_MACH_RB_133C} += rb-133c.o -obj-${CONFIG_ADM5120_MACH_RB_150} += rb-150.o -obj-${CONFIG_ADM5120_MACH_RB_153} += rb-153.o -obj-${CONFIG_ADM5120_MACH_RB_192} += rb-192.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-11x.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-11x.c deleted file mode 100644 index fd768d8ef0..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-11x.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Mikrotik RouterBOARD 111/112 support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -static struct gpio_led rb11x_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN3, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan_lnkact", NULL), -}; - -static u8 rb11x_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init rb11x_setup(void) -{ - rb1xx_generic_setup(); - rb1xx_add_device_nand(); - - adm5120_add_device_switch(1, rb11x_vlans); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb11x_gpio_leds), - rb11x_gpio_leds); -} - -MIPS_MACHINE(MACH_ADM5120_RB_11X, "11x", "Mikrotik RouterBOARD 111/112", - rb11x_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133.c deleted file mode 100644 index 23c57820c3..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Mikrotik RouterBOARD 133 support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -static struct gpio_led rb133_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN6, "power", NULL), - GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan1_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan2_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan2_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan3_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan3_lnkact", NULL), -}; - -static u8 rb133_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init rb133_setup(void) -{ - rb1xx_generic_setup(); - rb1xx_add_device_nand(); - - adm5120_add_device_switch(3, rb133_vlans); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133_gpio_leds), - rb133_gpio_leds); -} - -MIPS_MACHINE(MACH_ADM5120_RB_133, "133", "Mikrotik RouterBOARD 133", - rb133_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133c.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133c.c deleted file mode 100644 index 25bab70c00..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-133c.c +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Mikrotik RouterBOARD 133C support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -static struct gpio_led rb133c_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN6, "power", NULL), - GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan1_lnkact", NULL), -}; - -static u8 rb133c_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init rb133c_setup(void) -{ - rb1xx_generic_setup(); - rb1xx_add_device_nand(); - - adm5120_add_device_switch(1, rb133c_vlans); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133c_gpio_leds), - rb133c_gpio_leds); -} - -MIPS_MACHINE(MACH_ADM5120_RB_133C, "133C", "Mikrotik RouterBOARD 133C", - rb133c_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-150.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-150.c deleted file mode 100644 index 96a8c1b87b..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-150.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mikrotik RouterBOARD 150 support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -#define RB150_NAND_BASE 0x1FC80000 -#define RB150_NAND_SIZE 1 - -#define RB150_GPIO_NAND_READY ADM5120_GPIO_PIN0 -#define RB150_GPIO_NAND_NCE ADM5120_GPIO_PIN1 -#define RB150_GPIO_NAND_CLE ADM5120_GPIO_P2L2 -#define RB150_GPIO_NAND_ALE ADM5120_GPIO_P3L2 -#define RB150_GPIO_RESET_BUTTON ADM5120_GPIO_PIN1 /* FIXME */ - -#define RB150_NAND_DELAY 100 - -#define RB150_NAND_WRITE(v) \ - writeb((v), (void __iomem *)KSEG1ADDR(RB150_NAND_BASE)) - -static struct resource rb150_nand_resources[] __initdata = { - [0] = { - .start = RB150_NAND_BASE, - .end = RB150_NAND_BASE + RB150_NAND_SIZE-1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct gpio_led rb150_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_P0L2, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan1_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan5_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan5_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan4_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan4_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_led2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan2_led1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan2_led2", NULL), -}; - -static u8 rb150_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static int rb150_nand_dev_ready(struct mtd_info *mtd) -{ - return gpio_get_value(RB150_GPIO_NAND_READY); -} - -static void rb150_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, - unsigned int ctrl) -{ - if (ctrl & NAND_CTRL_CHANGE) { - gpio_set_value(RB150_GPIO_NAND_CLE, (ctrl & NAND_CLE) ? 1 : 0); - gpio_set_value(RB150_GPIO_NAND_ALE, (ctrl & NAND_ALE) ? 1 : 0); - gpio_set_value(RB150_GPIO_NAND_NCE, (ctrl & NAND_NCE) ? 0 : 1); - } - - udelay(RB150_NAND_DELAY); - - if (cmd != NAND_CMD_NONE) - RB150_NAND_WRITE(cmd); -} - -static void __init rb150_add_device_nand(void) -{ - struct platform_device *pdev; - int err; - - /* setup GPIO pins for NAND flash chip */ - gpio_request(RB150_GPIO_NAND_READY, "nand-ready"); - gpio_direction_input(RB150_GPIO_NAND_READY); - gpio_request(RB150_GPIO_NAND_NCE, "nand-nce"); - gpio_direction_output(RB150_GPIO_NAND_NCE, 1); - gpio_request(RB150_GPIO_NAND_CLE, "nand-cle"); - gpio_direction_output(RB150_GPIO_NAND_CLE, 0); - gpio_request(RB150_GPIO_NAND_ALE, "nand-ale"); - gpio_direction_output(RB150_GPIO_NAND_ALE, 0); - - pdev = platform_device_alloc("gen_nand", -1); - if (!pdev) - goto err_out; - - err = platform_device_add_resources(pdev, rb150_nand_resources, - ARRAY_SIZE(rb150_nand_resources)); - if (err) - goto err_put; - - - rb1xx_nand_data.ctrl.cmd_ctrl = rb150_nand_cmd_ctrl; - rb1xx_nand_data.ctrl.dev_ready = rb150_nand_dev_ready; - - err = platform_device_add_data(pdev, &rb1xx_nand_data, - sizeof(rb1xx_nand_data)); - if (err) - goto err_put; - - err = platform_device_add(pdev); - if (err) - goto err_put; - - return; - -err_put: - platform_device_put(pdev); -err_out: - return; -} - -static void __init rb150_setup(void) -{ - rb1xx_gpio_buttons[0].gpio = RB150_GPIO_RESET_BUTTON; - rb1xx_generic_setup(); - rb150_add_device_nand(); - - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb150_gpio_leds), - rb150_gpio_leds); - adm5120_add_device_switch(5, rb150_vlans); -} - -MIPS_MACHINE(MACH_ADM5120_RB_150, "miniROUTER", "Mikrotik RouterBOARD 150", - rb150_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-153.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-153.c deleted file mode 100644 index 8456684951..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-153.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Mikrotik RouterBOARD 153 support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -static struct resource rb153_cf_resources[] __initdata = { - { - .name = "cf_membase", - .start = ADM5120_EXTIO1_BASE, - .end = ADM5120_EXTIO1_BASE + ADM5120_EXTIO1_SIZE-1 , - .flags = IORESOURCE_MEM - }, { - .name = "cf_irq", - .start = ADM5120_IRQ_GPIO4, - .end = ADM5120_IRQ_GPIO4, - .flags = IORESOURCE_IRQ - } -}; - -static struct gpio_led rb153_gpio_leds[] __initdata = { - GPIO_LED_STD(ADM5120_GPIO_PIN5, "user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L1, "lan1_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan1_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L1, "lan5_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan5_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L1, "lan4_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan4_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L1, "lan3_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan3_lnkact", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L1, "lan2_speed", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "lan2_lnkact", NULL), -}; - -static u8 rb153_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init rb153_add_device_cf(void) -{ - /* enable CSX1:INTX1 on GPIO[3:4] for the CF slot */ - adm5120_gpio_csx1_enable(); - - /* enable the wait state pin GPIO[0] for external I/O control */ - adm5120_gpio_ew_enable(); - - platform_device_register_simple("pata-rb153-cf", -1, - rb153_cf_resources, ARRAY_SIZE(rb153_cf_resources)); -} - -static void __init rb153_setup(void) -{ - rb1xx_generic_setup(); - rb1xx_add_device_nand(); - rb153_add_device_cf(); - - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb153_gpio_leds), - rb153_gpio_leds); - adm5120_add_device_switch(5, rb153_vlans); -} - -MIPS_MACHINE(MACH_ADM5120_RB_153, "150", "Mikrotik RouterBOARD 153", - rb153_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-192.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-192.c deleted file mode 100644 index 9049421397..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-192.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Mikrotik RouterBOARD 192 support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "rb-1xx.h" - -static u8 rb192_vlans[6] __initdata = { - 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init rb192_setup(void) -{ - rb1xx_generic_setup(); - rb1xx_add_device_nand(); - - adm5120_add_device_switch(6, rb192_vlans); -} - -MIPS_MACHINE(MACH_ADM5120_RB_192, "192", "Mikrotik RouterBOARD 192", - rb192_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.c deleted file mode 100644 index 8961115c7e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Mikrotik RouterBOARD 1xx series support - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * NAND initialization code was based on a driver for Linux 2.6.19+ which - * was derived from the driver for Linux 2.4.xx published by Mikrotik for - * their RouterBoard 1xx and 5xx series boards. - * Copyright (C) 2007 David Goodenough - * Copyright (C) 2007 Florian Fainelli - * - * 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 "rb-1xx.h" - -#define RB1XX_NAND_CHIP_DELAY 25 - -#define RB1XX_KEYS_POLL_INTERVAL 20 -#define RB1XX_KEYS_DEBOUNCE_INTERVAL (3 * RB1XX_KEYS_POLL_INTERVAL) - -static struct adm5120_pci_irq rb1xx_pci_irqs[] __initdata = { - PCIIRQ(1, 0, 1, ADM5120_IRQ_PCI0), - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI1), - PCIIRQ(3, 0, 1, ADM5120_IRQ_PCI2) -}; - -static struct mtd_partition rb1xx_nor_parts[] = { - { - .name = "booter", - .offset = 0, - .size = 64*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct mtd_partition rb1xx_nand_parts[] = { - { - .name = "kernel", - .offset = 0, - .size = 4 * 1024 * 1024, - } , { - .name = "rootfs", - .offset = MTDPART_OFS_NXTBLK, - .size = MTDPART_SIZ_FULL - } -}; - -/* - * We need to use the OLD Yaffs-1 OOB layout, otherwise the RB bootloader - * will not be able to find the kernel that we load. So set the oobinfo - * when creating the partitions - */ -static struct nand_ecclayout rb1xx_nand_ecclayout = { - .eccbytes = 6, - .eccpos = { 8, 9, 10, 13, 14, 15 }, - .oobavail = 9, - .oobfree = { { 0, 4 }, { 6, 2 }, { 11, 2 }, { 4, 1 } } -}; - -/*--------------------------------------------------------------------------*/ - -static int rb1xx_nand_fixup(struct mtd_info *mtd) -{ - struct nand_chip *chip = mtd->priv; - - if (mtd->writesize == 512) - chip->ecc.layout = &rb1xx_nand_ecclayout; - - return 0; -} - -struct platform_nand_data rb1xx_nand_data __initdata = { - .chip = { - .nr_chips = 1, - .nr_partitions = ARRAY_SIZE(rb1xx_nand_parts), - .partitions = rb1xx_nand_parts, - .chip_delay = RB1XX_NAND_CHIP_DELAY, - .chip_fixup = rb1xx_nand_fixup, - }, -}; - -struct gpio_keys_button rb1xx_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = KEY_RESTART, - .debounce_interval = RB1XX_KEYS_DEBOUNCE_INTERVAL, - .gpio = ADM5120_GPIO_PIN7, - } -}; - -static void __init rb1xx_mac_setup(void) -{ - if (rb_hs.mac_base != NULL && is_valid_ether_addr(rb_hs.mac_base)) { - adm5120_setup_eth_macs(rb_hs.mac_base); - } else { - u8 mac[ETH_ALEN]; - - random_ether_addr(mac); - adm5120_setup_eth_macs(mac); - } -} - -void __init rb1xx_add_device_flash(void) -{ - /* setup data for flash0 device */ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(rb1xx_nor_parts); - adm5120_flash0_data.parts = rb1xx_nor_parts; - adm5120_flash0_data.window_size = 128*1024; - - adm5120_add_device_flash(0); -} - -void __init rb1xx_add_device_nand(void) -{ - /* enable NAND flash interface */ - adm5120_nand_enable(); - - /* initialize NAND chip */ - adm5120_nand_set_spn(1); - adm5120_nand_set_wpn(0); - - adm5120_add_device_nand(&rb1xx_nand_data); -} - -void __init rb1xx_generic_setup(void) -{ - if (adm5120_package_bga()) - adm5120_pci_set_irq_map(ARRAY_SIZE(rb1xx_pci_irqs), - rb1xx_pci_irqs); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_register_gpio_buttons(-1, RB1XX_KEYS_POLL_INTERVAL, - ARRAY_SIZE(rb1xx_gpio_buttons), - rb1xx_gpio_buttons); - - rb1xx_add_device_flash(); - rb1xx_mac_setup(); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.h b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.h deleted file mode 100644 index 05e68bd0a8..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Mikrotik RouterBOARD 1xx series support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include - -#include - -extern struct platform_nand_data rb1xx_nand_data __initdata; -extern struct gpio_keys_button rb1xx_gpio_buttons[] __initdata; - -extern void rb1xx_add_device_flash(void) __init; -extern void rb1xx_add_device_nand(void) __init; -extern void rb1xx_generic_setup(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/adm5120/motorola/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/motorola/Makefile deleted file mode 100644 index 239d5a0880..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/motorola/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ADM5120_MACH_PMUGW) += pmugw.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/motorola/pmugw.c b/target/linux/adm5120/files/arch/mips/adm5120/motorola/pmugw.c deleted file mode 100644 index 369892fd13..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/motorola/pmugw.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Motorola Powerline MU Gateway board - * - * Copyright (C) 2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#include - -#define PMUGW_CONFIG_OFFSET 0x10000 -#define PMUGW_CONFIG_SIZE 0x1000 - -static struct mtd_partition pmugw_partitions[] = { - { - .name = "admboot", - .offset = 0, - .size = 64*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "boardcfg", - .offset = MTDPART_OFS_APPEND, - .size = 64*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static u8 pmugw_vlans[6] __initdata = { - 0x41, 0x42, 0x44, 0x48, 0x50, 0x00 -}; - -static __init void pmugw_setup_mac(void) -{ - u8 mac_base[6]; - int err; - - err = admboot_get_mac_base(PMUGW_CONFIG_OFFSET, - PMUGW_CONFIG_SIZE, mac_base); - - if ((err) || !is_valid_ether_addr(mac_base)) - random_ether_addr(mac_base); - - adm5120_setup_eth_macs(mac_base); -} - -static void switch_bank_gpio5(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(ADM5120_GPIO_PIN5, 0); - break; - case 1: - gpio_set_value(ADM5120_GPIO_PIN5, 1); - break; - } -} - -void __init pmugw_setup(void) -{ - /* setup flash A20 line */ - gpio_request(ADM5120_GPIO_PIN5, NULL); - gpio_direction_output(ADM5120_GPIO_PIN5, 0); - adm5120_flash0_data.switch_bank = switch_bank_gpio5; - - adm5120_flash0_data.nr_parts = ARRAY_SIZE(pmugw_partitions); - adm5120_flash0_data.parts = pmugw_partitions; - - adm5120_add_device_uart(1); /* ttyAM0 */ - adm5120_add_device_uart(0); /* ttyAM1 */ - - adm5120_add_device_flash(0); - - pmugw_setup_mac(); - adm5120_add_device_switch(5, pmugw_vlans); -} - -MIPS_MACHINE(MACH_ADM5120_PMUGW, "PMUGW", "Motorola Powerline MU Gateway", - pmugw_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/osbridge/5gxi.c b/target/linux/adm5120/files/arch/mips/adm5120/osbridge/5gxi.c deleted file mode 100644 index a5c2c3653e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/osbridge/5gxi.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * OSBRiDGE 5GXi/5XLi board support - * - * Copyright (C) 2009 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 - * by the Free Software Foundation. - * - */ -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -static struct mtd_partition osbridge_5gxi_partitions[] = { - { - .name = "bootloader", - .offset = 0, - .size = 64*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "boardcfg", - .offset = 64*1024, - .size = 64*1024, - } , { - .name = "firmware", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct gpio_led osbridge_5gxi_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN6, "5gxi:green:user", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "5gxi:yellow:lan", NULL), -}; - -static struct adm5120_pci_irq osbridge_5gxi_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static u8 osbridge_5gxi_vlans[6] __initdata = { - 0x41, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static void __init osbridge_5gxi_setup(void) -{ - adm5120_flash0_data.nr_parts = ARRAY_SIZE(osbridge_5gxi_partitions); - adm5120_flash0_data.parts = osbridge_5gxi_partitions; - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_flash(0); - - adm5120_add_device_switch(1, osbridge_5gxi_vlans); - adm5120_add_device_gpio_leds(ARRAY_SIZE(osbridge_5gxi_gpio_leds), - osbridge_5gxi_gpio_leds); - adm5120_pci_set_irq_map(ARRAY_SIZE(osbridge_5gxi_pci_irqs), - osbridge_5gxi_pci_irqs); -} - -MIPS_MACHINE(MACH_ADM5120_5GXI, "5GXi", "OSBRiDGE 5GXi/5XLi board", - osbridge_5gxi_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/osbridge/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/osbridge/Makefile deleted file mode 100644 index 34946c5e58..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/osbridge/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ADM5120_MACH_5GXI) += 5gxi.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/prom/Makefile deleted file mode 100644 index 650be40779..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the ADMtek ADM5120 SoC specific parts of the kernel -# - -lib-y += admboot.o -lib-y += bootbase.o -lib-y += cfe.o -lib-y += generic.o -lib-y += myloader.o -lib-y += routerboot.o diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/admboot.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/admboot.c deleted file mode 100644 index b655390c16..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/admboot.c +++ /dev/null @@ -1,55 +0,0 @@ -/* - * ADMBoot specific prom routines - * - * Copyright (C) 2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include "prom_read.h" - -#define ADMBOOT_MAGIC_MAC_BASE 0x636D676D /* 'mgmc' */ -#define ADMBOOT_MAGIC_MAC_BASE_BR6104XX 0x31305348 /* 'HS01' */ - -int __init admboot_get_mac_base(u32 offset, u32 len, u8 *mac) -{ - u8 *cfg; - int i; - - cfg = (u8 *) KSEG1ADDR(ADM5120_SRAM0_BASE + offset); - for (i = 0; i < len; i += 4) { - u32 magic; - - magic = prom_read_le32(cfg + i); - if (magic == ADMBOOT_MAGIC_MAC_BASE) { - int j; - - for (j = 0; j < 6; j++) - mac[j] = cfg[i + 4 + j]; - - return 0; - } - if (magic == ADMBOOT_MAGIC_MAC_BASE_BR6104XX) { - int j; - - for (j = 0; j < 6; j++) - mac[j] = cfg[i + 7 + j]; - - return 0; - } - } - - return -ENXIO; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/bootbase.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/bootbase.c deleted file mode 100644 index 063281e3f7..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/bootbase.c +++ /dev/null @@ -1,119 +0,0 @@ -/* - * ZyXEL's Bootbase specific prom routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "prom_read.h" - -#define ZYNOS_INFO_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x3F90) -#define ZYNOS_HDBG_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x4000) -#define BOOTEXT_ADDR_MIN KSEG1ADDR(ADM5120_SRAM0_BASE) -#define BOOTEXT_ADDR_MAX (BOOTEXT_ADDR_MIN + (2*1024*1024)) - -static int bootbase_found; -static struct zynos_board_info *board_info; - -struct bootbase_info bootbase_info; - -static inline int bootbase_dbgarea_present(u8 *data) -{ - u32 t; - - t = prom_read_be32(data+5); - if (t != ZYNOS_MAGIC_DBGAREA1) - return 0; - - t = prom_read_be32(data+9); - if (t != ZYNOS_MAGIC_DBGAREA2) - return 0; - - return 1; -} - -static inline u32 bootbase_get_bootext_addr(void) -{ - return prom_read_be32(&board_info->bootext_addr); -} - -static inline void bootbase_get_mac(u8 *mac) -{ - int i; - - for (i = 0; i < 6; i++) - mac[i] = board_info->mac[i]; -} - -static inline u16 bootbase_get_vendor_id(void) -{ -#define CHECK_VENDOR(n) (strnicmp(board_info->vendor, (n), strlen(n)) == 0) - unsigned char vendor[ZYNOS_NAME_LEN]; - int i; - - for (i = 0; i < ZYNOS_NAME_LEN; i++) - vendor[i] = board_info->vendor[i]; - - if CHECK_VENDOR(ZYNOS_VENDOR_ZYXEL) - return ZYNOS_VENDOR_ID_ZYXEL; - - if CHECK_VENDOR(ZYNOS_VENDOR_DLINK) - return ZYNOS_VENDOR_ID_DLINK; - - if CHECK_VENDOR(ZYNOS_VENDOR_LUCENT) - return ZYNOS_VENDOR_ID_LUCENT; - - if CHECK_VENDOR(ZYNOS_VENDOR_NETGEAR) - return ZYNOS_VENDOR_ID_NETGEAR; - - return ZYNOS_VENDOR_ID_OTHER; -} - -static inline u16 bootbase_get_board_id(void) -{ - return prom_read_be16(&board_info->board_id); -} - -int __init bootbase_present(void) -{ - u32 t; - - if (bootbase_found) - goto out; - - /* check presence of the dbgarea */ - if (bootbase_dbgarea_present((u8 *)ZYNOS_HDBG_ADDR) == 0) - goto out; - - board_info = (struct zynos_board_info *)(ZYNOS_INFO_ADDR); - - /* check for a valid BootExt address */ - t = bootbase_get_bootext_addr(); - if ((t < BOOTEXT_ADDR_MIN) || (t > BOOTEXT_ADDR_MAX)) - goto out; - - bootbase_info.vendor_id = bootbase_get_vendor_id(); - bootbase_info.board_id = bootbase_get_board_id(); - bootbase_get_mac(bootbase_info.mac); - - bootbase_found = 1; - -out: - return bootbase_found; -} - diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/cfe.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/cfe.c deleted file mode 100644 index 5a343cd7e4..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/cfe.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Broadcom's CFE specific prom routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include - -#include -#include - -#include -#include "prom_read.h" - -/* - * CFE based boards - */ -#define CFE_EPTSEAL 0x43464531 /* CFE1 is the magic number to recognize CFE -from other bootloaders */ - -static int cfe_found; - -static u32 cfe_handle; -static u32 cfe_entry; -static u32 cfe_seal; - -int __init cfe_present(void) -{ - /* - * This method only works, when we are booted directly from the CFE. - */ - u32 a1 = (u32) fw_arg1; - - if (cfe_found) - return 1; - - cfe_handle = (u32) fw_arg0; - cfe_entry = (u32) fw_arg2; - cfe_seal = (u32) fw_arg3; - - /* Check for CFE by finding the CFE magic number */ - if (cfe_seal != CFE_EPTSEAL) - return 0; - - /* cfe_a1_val must be 0, because only one CPU present in the ADM5120 */ - if (a1 != 0) - return 0; - - /* The cfe_handle, and the cfe_entry must be kernel mode addresses */ - if ((cfe_handle < KSEG0) || (cfe_entry < KSEG0)) - return 0; - - cfe_found = 1; - return 1; -} - -char *cfe_getenv(char *envname) -{ - if (cfe_found == 0) - return NULL; - - return NULL; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/generic.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/generic.c deleted file mode 100644 index 4d4caa8476..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/generic.c +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Generic PROM routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include - -#include - -#include - -static int *_prom_argc; -static char **_prom_argv; -static char **_prom_envp; - -char *generic_prom_getenv(char *envname) -{ - char **env; - char *ret; - - ret = NULL; - for (env = _prom_envp; *env != NULL; env++) { - if (strcmp(envname, *env++) == 0) { - ret = *env; - break; - } - } - - return ret; -} - -int generic_prom_present(void) -{ - _prom_argc = (int *)fw_arg0; - _prom_argv = (char **)fw_arg1; - _prom_envp = (char **)fw_arg2; - - return 1; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/myloader.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/myloader.c deleted file mode 100644 index 5357db511b..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/myloader.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Compex's MyLoader specific prom routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include "prom_read.h" - -#define SYS_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F000) -#define BOARD_PARAMS_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x0F800) -#define PART_TABLE_ADDR KSEG1ADDR(ADM5120_SRAM0_BASE+0x10000) - -static int myloader_found; - -struct myloader_info myloader_info; - -int __init myloader_present(void) -{ - struct mylo_system_params *sysp; - struct mylo_board_params *boardp; - struct mylo_partition_table *parts; - int i; - - if (myloader_found) - goto out; - - sysp = (struct mylo_system_params *)(SYS_PARAMS_ADDR); - boardp = (struct mylo_board_params *)(BOARD_PARAMS_ADDR); - parts = (struct mylo_partition_table *)(PART_TABLE_ADDR); - - /* Check for some magic numbers */ - if ((le32_to_cpu(sysp->magic) != MYLO_MAGIC_SYS_PARAMS) || - (le32_to_cpu(boardp->magic) != MYLO_MAGIC_BOARD_PARAMS) || - (le32_to_cpu(parts->magic) != MYLO_MAGIC_PARTITIONS)) - goto out; - - myloader_info.vid = le32_to_cpu(sysp->vid); - myloader_info.did = le32_to_cpu(sysp->did); - myloader_info.svid = le32_to_cpu(sysp->svid); - myloader_info.sdid = le32_to_cpu(sysp->sdid); - - for (i = 0; i < MYLO_ETHADDR_COUNT; i++) { - int j; - for (j = 0; j < 6; j++) - myloader_info.macs[i][j] = boardp->addr[i].mac[j]; - } - - myloader_found = 1; - -out: - return myloader_found; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/prom_read.h b/target/linux/adm5120/files/arch/mips/adm5120/prom/prom_read.h deleted file mode 100644 index 1a6ea110ce..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/prom_read.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Generic prom definitions - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _ADM5120_PROM_H_ -#define _ADM5120_PROM_H_ - -/* - * Helper routines - */ -static inline u16 prom_read_le16(void *buf) -{ - u8 *p = buf; - - return ((u16)p[0] + ((u16)p[1] << 8)); -} - -static inline u32 prom_read_le32(void *buf) -{ - u8 *p = buf; - - return ((u32)p[0] + ((u32)p[1] << 8) + ((u32)p[2] << 16) + - ((u32)p[3] << 24)); -} - -static inline u16 prom_read_be16(void *buf) -{ - u8 *p = buf; - - return (((u16)p[0] << 8) + (u16)p[1]); -} - -static inline u32 prom_read_be32(void *buf) -{ - u8 *p = buf; - - return (((u32)p[0] << 24) + ((u32)p[1] << 16) + ((u32)p[2] << 8) + - ((u32)p[3])); -} - -#endif /* _ADM5120_PROM_H_ */ - - diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/routerboot.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/routerboot.c deleted file mode 100644 index d9a06d968e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/prom/routerboot.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Mikrotik's RouterBOOT specific prom routines - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include "prom_read.h" - -struct rb_hard_settings rb_hs; -static int rb_found; - -static int __init routerboot_load_hs(u8 *buf, u16 buflen) -{ - u16 id, len; - - memset(&rb_hs, 0, sizeof(rb_hs)); - - if (buflen < 4) - return -1; - - if (prom_read_le32(buf) != RB_MAGIC_HARD) - return -1; - - /* skip magic value */ - buf += 4; - buflen -= 4; - - while (buflen > 2) { - id = prom_read_le16(buf); - buf += 2; - buflen -= 2; - if (id == RB_ID_TERMINATOR || buflen < 2) - break; - - len = prom_read_le16(buf); - buf += 2; - buflen -= 2; - - if (buflen < len) - break; - - switch (id) { - case RB_ID_BIOS_VERSION: - rb_hs.bios_ver = (char *)buf; - break; - case RB_ID_BOARD_NAME: - rb_hs.name = (char *)buf; - break; - case RB_ID_MEMORY_SIZE: - rb_hs.mem_size = prom_read_le32(buf); - break; - case RB_ID_MAC_ADDRESS_COUNT: - rb_hs.mac_count = prom_read_le32(buf); - break; - case RB_ID_MAC_ADDRESS_PACK: - if ((len / RB_MAC_SIZE) > 0) - rb_hs.mac_base = buf; - break; - } - - buf += len; - buflen -= len; - - } - - return 0; -} - -#define RB_BS_OFFS 0x14 -#define RB_OFFS_MAX (128*1024) - -int __init routerboot_present(void) -{ - struct rb_bios_settings *bs; - u8 *base; - u32 off, len; - - if (rb_found) - goto out; - - base = (u8 *)KSEG1ADDR(ADM5120_SRAM0_BASE); - bs = (struct rb_bios_settings *)(base + RB_BS_OFFS); - - off = prom_read_le32(&bs->hs_offs); - len = prom_read_le32(&bs->hs_size); - if (off > RB_OFFS_MAX) - goto out; - - if (routerboot_load_hs(base+off, len) != 0) - goto out; - - rb_found = 1; - -out: - return rb_found; -} - -char *routerboot_get_boardname(void) -{ - if (rb_found == 0) - return NULL; - - return rb_hs.name; -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/Makefile deleted file mode 100644 index e8325a1b1f..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-y += p-33x.o - -obj-${CONFIG_ADM5120_MACH_P_334WT} += p-334wt.o -obj-${CONFIG_ADM5120_MACH_P_335} += p-335.o \ No newline at end of file diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-334wt.c b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-334wt.c deleted file mode 100644 index 6cc9aee857..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-334wt.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * ZyXEL Prestige P-334WT support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "p-33x.h" - -static struct gpio_led p334wt_gpio_leds[] __initdata = { - GPIO_LED_INV(ADM5120_GPIO_PIN2, "power", NULL), - GPIO_LED_INV(ADM5120_GPIO_P3L0, "lan1", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L0, "lan2", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L0, "lan3", NULL), - GPIO_LED_INV(ADM5120_GPIO_P0L0, "lan4", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L0, "wan", NULL), - GPIO_LED_INV(ADM5120_GPIO_P4L2, "wlan", NULL), - GPIO_LED_INV(ADM5120_GPIO_P2L2, "otist", NULL), - GPIO_LED_INV(ADM5120_GPIO_P1L2, "hidden", NULL), -}; - -static void __init p334wt_setup(void) -{ - p33x_generic_setup(); - adm5120_add_device_gpio_leds(ARRAY_SIZE(p334wt_gpio_leds), - p334wt_gpio_leds); -} - -MIPS_MACHINE(MACH_ADM5120_P334WT, "P-334WT", "ZyXEL Prestige 334WT", - p334wt_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-335.c b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-335.c deleted file mode 100644 index 6ac2b09158..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-335.c +++ /dev/null @@ -1,21 +0,0 @@ -/* - * ZyXEL Prestige P-335/335WT support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "p-33x.h" - -static void __init p335_setup(void) -{ - p33x_generic_setup(); - adm5120_add_device_usb(); -} - -MIPS_MACHINE(MACH_ADM5120_P335, "P-335", "ZyXEL Prestige 335/335WT", - p335_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c deleted file mode 100644 index 2626cf9eec..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ZyXEL Prestige P-33x boards support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include "p-33x.h" - -#include - -#define P33X_GPIO_FLASH_A20 ADM5120_GPIO_PIN5 -static struct mtd_partition p33x_partitions[] = { - { - .name = "bootbase", - .offset = 0, - .size = 16*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "rom", - .offset = MTDPART_OFS_APPEND, - .size = 16*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "bootext1", - .offset = MTDPART_OFS_APPEND, - .size = 32*1024, - } , { - .name = "bootext2", - .offset = MTDPART_OFS_APPEND, - .size = 64*1024, - } , { - .name = "trx", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } , { - .name = "firmware", - .offset = 32*1024, - .size = MTDPART_SIZ_FULL, - } -}; - -static struct adm5120_pci_irq p33x_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static u8 p33x_vlans[6] __initdata = { - /* FIXME: untested */ - 0x50, 0x48, 0x44, 0x42, 0x41, 0x00 -}; - -static void switch_bank_gpio5(unsigned bank) -{ - switch (bank) { - case 0: - gpio_set_value(P33X_GPIO_FLASH_A20, 0); - break; - case 1: - gpio_set_value(P33X_GPIO_FLASH_A20, 1); - break; - } -} - -void __init p33x_generic_setup(void) -{ - /* setup data for flash0 device */ - gpio_request(P33X_GPIO_FLASH_A20, NULL); /* for flash A20 line */ - gpio_direction_output(P33X_GPIO_FLASH_A20, 0); - adm5120_flash0_data.switch_bank = switch_bank_gpio5; - adm5120_flash0_data.nr_parts = ARRAY_SIZE(p33x_partitions); - adm5120_flash0_data.parts = p33x_partitions; - adm5120_add_device_flash(0); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_setup_eth_macs(bootbase_info.mac); - adm5120_add_device_switch(6, p33x_vlans); - - adm5120_pci_set_irq_map(ARRAY_SIZE(p33x_pci_irqs), p33x_pci_irqs); -} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.h b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.h deleted file mode 100644 index 8a7340cb5e..0000000000 --- a/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * ZyXEL Prestige P-33x boards support - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include - -#include - -#include -#include - -extern void p33x_generic_setup(void) __init; diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_defs.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_defs.h deleted file mode 100644 index bf220ff4d6..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_defs.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * ADM5120 SoC definitions - * - * This file defines some constants specific to the ADM5120 SoC - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ -#ifndef _ASM_MIPS_MACH_ADM5120_DEFS_H -#define _ASM_MIPS_MACH_ADM5120_DEFS_H - -#define ADM5120_SDRAM0_BASE 0x00000000 -#define ADM5120_SDRAM1_BASE 0x01000000 -#define ADM5120_SRAM1_BASE 0x10000000 -#define ADM5120_EXTIO0_BASE 0x10C00000 -#define ADM5120_EXTIO0_SIZE 0x00200000 -#define ADM5120_EXTIO1_BASE 0x10E00000 -#define ADM5120_EXTIO1_SIZE 0x00200000 -#define ADM5120_MPMC_BASE 0x11000000 -#define ADM5120_MPMC_SIZE 0x00200000 -#define ADM5120_USBC_BASE 0x11200000 -#define ADM5120_USBC_SIZE 0x00200000 -#define ADM5120_PCIMEM_BASE 0x11400000 -#define ADM5120_PCIMEM_SIZE 0x00100000 -#define ADM5120_PCIIO_BASE 0x11500000 -#define ADM5120_PCIIO_SIZE 0x000FFFF0 -#define ADM5120_PCICFG_ADDR 0x115FFFF0 -#define ADM5120_PCICFG_DATA 0x115FFFF8 -#define ADM5120_PCICFG_SIZE 0x00000010 -#define ADM5120_SWITCH_BASE 0x12000000 -#define ADM5120_SWITCH_SIZE 0x00200000 -#define ADM5120_INTC_BASE 0x12200000 -#define ADM5120_INTC_SIZE 0x00200000 -#define ADM5120_UART0_BASE 0x12600000 -#define ADM5120_UART1_BASE 0x12800000 -#define ADM5120_UART_SIZE 0x00200000 -#define ADM5120_SRAM0_BASE 0x1FC00000 - -#define ADM5120_NAND_BASE ADM5120_SRAM1_BASE -#define ADM5120_NAND_SIZE 0xB - -#define ADM5120_CLK_175 175000000 -#define ADM5120_CLK_200 200000000 -#define ADM5120_CLK_225 225000000 -#define ADM5120_CLK_250 250000000 - -#define ADM5120_UART_CLOCK 62500000 - -#endif /* _ASM_MIPS_MACH_ADM5120_DEFS_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h deleted file mode 100644 index 1d34d80ee6..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_info.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2007-2009 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MACH_ADM5120_INFO_H -#define _MACH_ADM5120_INFO_H - -#include - -extern unsigned int adm5120_prom_type; -#define ADM5120_PROM_GENERIC 0 -#define ADM5120_PROM_CFE 1 -#define ADM5120_PROM_MYLOADER 2 -#define ADM5120_PROM_ROUTERBOOT 3 -#define ADM5120_PROM_BOOTBASE 4 -#define ADM5120_PROM_UBOOT 5 -#define ADM5120_PROM_LAST 5 - -extern unsigned int adm5120_product_code; -extern unsigned int adm5120_revision; -extern unsigned int adm5120_nand_boot; - -extern unsigned long adm5120_speed; -#define ADM5120_SPEED_175 175000000 -#define ADM5120_SPEED_200 200000000 -#define ADM5120_SPEED_225 225000000 -#define ADM5120_SPEED_250 250000000 - -extern unsigned int adm5120_package; -#define ADM5120_PACKAGE_PQFP 0 -#define ADM5120_PACKAGE_BGA 1 - -extern unsigned long adm5120_memsize; - -enum { - MACH_ADM5120_GENERIC = 0, /* Generic board */ - MACH_ADM5120_5GXI, /* OSBRiDGE 5GXi/5XLi */ - MACH_ADM5120_BR6104K, /* Edimax BR-6104K */ - MACH_ADM5120_BR6104KP, /* Edimax BR-6104KP */ - MACH_ADM5120_BR61X4WG, /* Edimax BR-6104Wg/BR-6114WG */ - MACH_ADM5120_CAS630, /* Cellvision CAS-630/630W */ - MACH_ADM5120_CAS670, /* Cellvision CAS-670/670W */ - MACH_ADM5120_CAS700, /* Cellvision CAS-700/700W */ - MACH_ADM5120_CAS771, /* Cellvision CAS-771/771W */ - MACH_ADM5120_CAS790, /* Cellvision CAS-790 */ - MACH_ADM5120_CAS861, /* Cellvision CAS-861/861W */ - MACH_ADM5120_EASY5120PATA, /* Infineon EASY 5120P-ATA */ - MACH_ADM5120_EASY5120RT, /* Infineon EASY 5120-RT */ - MACH_ADM5120_EASY5120WVOIP, /* Infineon EASY 5120-WVoIP */ - MACH_ADM5120_EASY83000, /* Infineon EASY-83000 */ - MACH_ADM5120_ES2108, /* ZyXEL Ethernet Switch 2108 */ - MACH_ADM5120_ES2108F, /* ZyXEL Ethernet Switch 2108-F */ - MACH_ADM5120_ES2108G, /* ZyXEL Ethernet Switch 2108-G */ - MACH_ADM5120_ES2108LC, /* ZyXEL Ethernet Switch 2108-LC */ - MACH_ADM5120_ES2108PWR, /* ZyXEL Ethernet Switch 2108-PWR */ - MACH_ADM5120_ES2024A, /* ZyXEL Ethernet Switch 2024A */ - MACH_ADM5120_ES2024PWR, /* ZyXEL Ethernet Switch 2024PWR */ - MACH_ADM5120_HS100, /* ZyXEL HomeSafe 100/100W */ - MACH_ADM5120_NFS101U, /* Cellvision NFS-101U/101WU */ - MACH_ADM5120_NFS202U, /* Cellvision NFS-202U/202WU */ - MACH_ADM5120_NP28G, /* Compex NP28G */ - MACH_ADM5120_NP28GHS, /* Compex NP28G HotSpot */ - MACH_ADM5120_NP27G, /* Compex NP27G */ - MACH_ADM5120_RB_11X, /* Mikrotik RouterBOARD 111/112 */ - MACH_ADM5120_RB_133, /* Mikrotik RouterBOARD 133 */ - MACH_ADM5120_RB_133C, /* Mikrotik RouterBOARD 133c */ - MACH_ADM5120_RB_150, /* Mikrotik RouterBOARD 150 */ - MACH_ADM5120_RB_153, /* Mikrotik RouterBOARD 153 */ - MACH_ADM5120_RB_192, /* Mikrotik RouterBOARD 192 */ - MACH_ADM5120_P334U, /* ZyXEL Prestige 334U */ - MACH_ADM5120_P334W, /* ZyXEL Prestige 334W */ - MACH_ADM5120_P334WH, /* ZyXEL Prestige 334WH */ - MACH_ADM5120_P334WHD, /* ZyXEL Prestige 334WHD */ - MACH_ADM5120_P334WT, /* ZyXEL Prestige 334WT */ - MACH_ADM5120_P335, /* ZyXEL Prestige 335/335WT */ - MACH_ADM5120_P335PLUS, /* ZyXEL Prestige 335Plus */ - MACH_ADM5120_P335U, /* ZyXEL Prestige 335U */ - MACH_ADM5120_PMUGW, /* Motorola Powerline MU Gateway */ - MACH_ADM5120_WP54, /* Compex WP54G/WP54AG/WPP54G/WPP54AG */ - MACH_ADM5120_WP54G_WRT, /* Compex WP54G-WRT */ - MACH_ADM5120_WP54Gv1C, /* Compex WP54G version 1C */ - MACH_ADM5120_EB_214A, /* Generic EB-214A */ -}; - -/* - * TODO:remove adm5120_eth* variables when the switch driver will be - * converted into a real platform driver - */ -extern unsigned int adm5120_eth_num_ports; -extern unsigned char adm5120_eth_macs[6][6]; -extern unsigned char adm5120_eth_vlans[6]; - -extern void adm5120_soc_init(void) __init; -extern void adm5120_mem_init(void) __init; -extern void adm5120_ndelay(u32 ns); - -extern void (*adm5120_board_reset)(void); - -extern void adm5120_gpio_init(void) __init; -extern void adm5120_gpio_csx0_enable(void) __init; -extern void adm5120_gpio_csx1_enable(void) __init; -extern void adm5120_gpio_ew_enable(void) __init; - -static inline int adm5120_package_pqfp(void) -{ - return (adm5120_package == ADM5120_PACKAGE_PQFP); -} - -static inline int adm5120_package_bga(void) -{ - return (adm5120_package == ADM5120_PACKAGE_BGA); -} - -static inline int adm5120_has_pci(void) -{ - return (adm5120_package == ADM5120_PACKAGE_BGA); -} - -static inline int adm5120_has_gmii(void) -{ - return (adm5120_package == ADM5120_PACKAGE_BGA); -} - -#endif /* _MACH_ADM5120_INFO_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_intc.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_intc.h deleted file mode 100644 index 70dd6bbe85..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_intc.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * ADM5120 interrupt controller definitions - * - * This header file defines the hardware registers of the ADM5120 SoC - * built-in interrupt controller. - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MACH_ADM5120_INTC_H -#define _MACH_ADM5120_INTC_H - -/* - * INTC register offsets - */ -#define INTC_REG_IRQ_STATUS 0x00 /* Interrupt status after masking */ -#define INTC_REG_IRQ_RAW_STATUS 0x04 /* Interrupt status before masking */ -#define INTC_REG_IRQ_ENABLE 0x08 /* Used to enable the interrupt sources */ -#define INTC_REG_IRQ_ENABLE_CLEAR 0x0C /* Used to disable the interrupt sources */ -#define INTC_REG_IRQ_DISABLE INTC_REG_IRQ_ENABLE_CLEAR -#define INTC_REG_INT_MODE 0x14 /* The interrupt mode of the sources */ -#define INTC_REG_FIQ_STATUS 0x18 /* FIQ status */ -#define INTC_REG_IRQ_TEST_SOURCE 0x1C -#define INTC_REG_IRQ_SOURCE_SELECT 0x20 -#define INTC_REG_INT_LEVEL 0x24 - -/* - * INTC IRQ numbers - */ -#define INTC_IRQ_TIMER 0 /* built in timer */ -#define INTC_IRQ_UART0 1 /* built-in UART0 */ -#define INTC_IRQ_UART1 2 /* built-in UART1 */ -#define INTC_IRQ_USBC 3 /* USB Host Controller */ -#define INTC_IRQ_GPIO2 4 /* GPIO line 2 */ -#define INTC_IRQ_GPIO4 5 /* GPIO line 4 */ -#define INTC_IRQ_PCI0 6 /* PCI slot 2 */ -#define INTC_IRQ_PCI1 7 /* PCI slot 3 */ -#define INTC_IRQ_PCI2 8 /* PCI slot 4 */ -#define INTC_IRQ_SWITCH 9 /* built-in ethernet switch */ -#define INTC_IRQ_LAST INTC_IRQ_SWITCH -#define INTC_IRQ_COUNT 10 - -/* - * INTC register bits - */ -#define INTC_INT_TIMER (1 << INTC_IRQ_TIMER) -#define INTC_INT_UART0 (1 << INTC_IRQ_UART0) -#define INTC_INT_UART1 (1 << INTC_IRQ_UART1) -#define INTC_INT_USBC (1 << INTC_IRQ_USBC) -#define INTC_INT_INTX0 (1 << INTC_IRQ_INTX0) -#define INTC_INT_INTX1 (1 << INTC_IRQ_INTX1) -#define INTC_INT_PCI0 (1 << INTC_IRQ_PCI0) -#define INTC_INT_PCI1 (1 << INTC_IRQ_PCI1) -#define INTC_INT_PCI2 (1 << INTC_IRQ_PCI2) -#define INTC_INT_SWITCH (1 << INTC_IRQ_SWITCH) -#define INTC_INT_ALL ((1 << INTC_IRQ_COUNT) - 1) - -#endif /* _MACH_ADM5120_INTC_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h deleted file mode 100644 index c4e9591fb8..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_mpmc.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * ADM5120 MPMC (Multiport Memory Controller) register definitions - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MACH_ADM5120_MPMC_H -#define _MACH_ADM5120_MPMC_H - -#define MPMC_READ_REG(r) __raw_readl( \ - (void __iomem *)KSEG1ADDR(ADM5120_MPMC_BASE) + MPMC_REG_ ## r) -#define MPMC_WRITE_REG(r, v) __raw_writel((v), \ - (void __iomem *)KSEG1ADDR(ADM5120_MPMC_BASE) + MPMC_REG_ ## r) - -#define MPMC_REG_CTRL 0x0000 -#define MPMC_REG_STATUS 0x0004 -#define MPMC_REG_CONF 0x0008 -#define MPMC_REG_DC 0x0020 -#define MPMC_REG_DR 0x0024 -#define MPMC_REG_DRP 0x0030 - -#define MPMC_REG_DC0 0x0100 -#define MPMC_REG_DRC0 0x0104 -#define MPMC_REG_DC1 0x0120 -#define MPMC_REG_DRC1 0x0124 -#define MPMC_REG_DC2 0x0140 -#define MPMC_REG_DRC2 0x0144 -#define MPMC_REG_DC3 0x0160 -#define MPMC_REG_DRC3 0x0164 -#define MPMC_REG_SC0 0x0200 /* for F_CS1_N */ -#define MPMC_REG_SC1 0x0220 /* for F_CS0_N */ -#define MPMC_REG_SC2 0x0240 -#define MPMC_REG_WEN2 0x0244 -#define MPMC_REG_OEN2 0x0248 -#define MPMC_REG_RD2 0x024C -#define MPMC_REG_PG2 0x0250 -#define MPMC_REG_WR2 0x0254 -#define MPMC_REG_TN2 0x0258 -#define MPMC_REG_SC3 0x0260 - -/* Control register bits */ -#define MPMC_CTRL_AM (1 << 1) /* Address Mirror */ -#define MPMC_CTRL_LPM (1 << 2) /* Low Power Mode */ -#define MPMC_CTRL_DWB (1 << 3) /* Drain Write Buffers */ - -/* Status register bits */ -#define MPMC_STATUS_BUSY (1 << 0) /* Busy */ -#define MPMC_STATUS_WBS (1 << 1) /* Write Buffer Status */ -#define MPMC_STATUS_SRA (1 << 2) /* Self-Refresh Acknowledge*/ - -/* Dynamic Control register bits */ -#define MPMC_DC_CE (1 << 0) -#define MPMC_DC_DMC (1 << 1) -#define MPMC_DC_SRR (1 << 2) -#define MPMC_DC_SI_SHIFT 7 -#define MPMC_DC_SI_MASK (3 << 7) -#define MPMC_DC_SI_NORMAL (0 << 7) -#define MPMC_DC_SI_MODE (1 << 7) -#define MPMC_DC_SI_PALL (2 << 7) -#define MPMC_DC_SI_NOP (3 << 7) - -#define SRAM_REG_CONF 0x00 -#define SRAM_REG_WWE 0x04 -#define SRAM_REG_WOE 0x08 -#define SRAM_REG_WRD 0x0C -#define SRAM_REG_WPG 0x10 -#define SRAM_REG_WWR 0x14 -#define SRAM_REG_WTR 0x18 - -/* Dynamic Configuration register bits */ -#define DC_BE (1 << 19) /* buffer enable */ -#define DC_RW_SHIFT 28 /* shift for number of rows */ -#define DC_RW_MASK 0x03 -#define DC_NB_SHIFT 26 /* shift for number of banks */ -#define DC_NB_MASK 0x01 -#define DC_CW_SHIFT 22 /* shift for number of columns */ -#define DC_CW_MASK 0x07 -#define DC_DW_SHIFT 7 /* shift for device width */ -#define DC_DW_MASK 0x03 - -/* Static Configuration register bits */ -#define SC_MW_MASK 0x03 /* memory width mask */ -#define SC_MW_8 0x00 /* 8 bit memory width */ -#define SC_MW_16 0x01 /* 16 bit memory width */ -#define SC_MW_32 0x02 /* 32 bit memory width */ - -#endif /* _MACH_ADM5120_MPMC_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_nand.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_nand.h deleted file mode 100644 index 1e2f3bd15d..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_nand.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * ADM5120 NAND interface definitions - * - * This header file defines the hardware registers of the ADM5120 SoC - * built-in NAND interface. - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * NAND interface routines was based on a driver for Linux 2.6.19+ which - * was derived from the driver for Linux 2.4.xx published by Mikrotik for - * their RouterBoard 1xx and 5xx series boards. - * Copyright (C) 2007 David Goodenough - * Copyright (C) 2007 Florian Fainelli - * - * 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 _MACH_ADM5120_NAND_H -#define _MACH_ADM5120_NAND_H - -#include -#include - -#include -#include - -/* NAND control registers */ -#define NAND_REG_DATA 0x0 /* data register */ -#define NAND_REG_SET_CEn 0x1 /* CE# low */ -#define NAND_REG_CLR_CEn 0x2 /* CE# high */ -#define NAND_REG_CLR_CLE 0x3 /* CLE low */ -#define NAND_REG_SET_CLE 0x4 /* CLE high */ -#define NAND_REG_CLR_ALE 0x5 /* ALE low */ -#define NAND_REG_SET_ALE 0x6 /* ALE high */ -#define NAND_REG_SET_SPn 0x7 /* SP# low (use spare area) */ -#define NAND_REG_CLR_SPn 0x8 /* SP# high (do not use spare area) */ -#define NAND_REG_SET_WPn 0x9 /* WP# low */ -#define NAND_REG_CLR_WPn 0xA /* WP# high */ -#define NAND_REG_STATUS 0xB /* Status register */ - -#define ADM5120_NAND_STATUS_READY 0x80 - -#define NAND_READ_REG(r) \ - readb((void __iomem *)KSEG1ADDR(ADM5120_NAND_BASE) + (r)) -#define NAND_WRITE_REG(r, v) \ - writeb((v), (void __iomem *)KSEG1ADDR(ADM5120_NAND_BASE) + (r)) - -/*-------------------------------------------------------------------------*/ - -static inline void adm5120_nand_enable(void) -{ - SW_WRITE_REG(SWITCH_REG_BW_CNTL1, BW_CNTL1_NAND_ENABLE); - SW_WRITE_REG(SWITCH_REG_BOOT_DONE, 1); -} - -static inline void adm5120_nand_set_wpn(unsigned int set) -{ - NAND_WRITE_REG((set) ? NAND_REG_SET_WPn : NAND_REG_CLR_WPn, 1); -} - -static inline void adm5120_nand_set_spn(unsigned int set) -{ - NAND_WRITE_REG((set) ? NAND_REG_SET_SPn : NAND_REG_CLR_SPn, 1); -} - -static inline void adm5120_nand_set_cle(unsigned int set) -{ - NAND_WRITE_REG((set) ? NAND_REG_SET_CLE : NAND_REG_CLR_CLE, 1); -} - -static inline void adm5120_nand_set_ale(unsigned int set) -{ - NAND_WRITE_REG((set) ? NAND_REG_SET_ALE : NAND_REG_CLR_ALE, 1); -} - -static inline void adm5120_nand_set_cen(unsigned int set) -{ - NAND_WRITE_REG((set) ? NAND_REG_SET_CEn : NAND_REG_CLR_CEn, 1); -} - -static inline u8 adm5120_nand_get_status(void) -{ - return NAND_READ_REG(NAND_REG_STATUS); -} - -#endif /* _MACH_ADM5120_NAND_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_platform.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_platform.h deleted file mode 100644 index ed73b53297..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_platform.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ADM5120 specific platform definitions - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _ASM_MIPS_MACH_ADM5120_PLATFORM_H -#define _ASM_MIPS_MACH_ADM5120_PLATFORM_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct adm5120_flash_platform_data { - void (*set_vpp)(struct map_info *, int); - void (*switch_bank)(unsigned); - u32 window_size; - unsigned int nr_parts; - struct mtd_partition *parts; -}; - -struct adm5120_switch_platform_data { - /* TODO: not yet implemented */ -}; - -struct adm5120_pci_irq { - u8 slot; - u8 func; - u8 pin; - unsigned irq; -}; - -#define PCIIRQ(s, f, p, i) {.slot = (s), .func = (f), .pin = (p), .irq = (i)} - -#ifdef CONFIG_PCI -extern void adm5120_pci_set_irq_map(unsigned int nr_irqs, - struct adm5120_pci_irq *map) __init; -#else -static inline void adm5120_pci_set_irq_map(unsigned int nr_irqs, - struct adm5120_pci_irq *map) -{ -} -#endif - -extern void adm5120_setup_eth_macs(u8 *mac_base) __init; - -extern struct adm5120_flash_platform_data adm5120_flash0_data; -extern struct adm5120_flash_platform_data adm5120_flash1_data; - -extern void adm5120_add_device_flash(unsigned id) __init; -extern void adm5120_add_device_usb(void) __init; -extern void adm5120_add_device_uart(unsigned id) __init; -extern void adm5120_add_device_nand(struct platform_nand_data *pdata) __init; -extern void adm5120_add_device_switch(unsigned num_ports, u8 *vlan_map) __init; -extern void adm5120_register_gpio_buttons(int id, - unsigned poll_interval, - unsigned nbuttons, - struct gpio_keys_button *buttons); - -#define GPIO_LED_DEF(g, n, t, a) { \ - .name = (n), \ - .default_trigger = (t), \ - .gpio = (g), \ - .active_low = (a) \ -} - -#define GPIO_LED_STD(g, n, t) GPIO_LED_DEF((g), (n), (t), 0) -#define GPIO_LED_INV(g, n, t) GPIO_LED_DEF((g), (n), (t), 1) - -extern void adm5120_add_device_gpio_leds(unsigned num_leds, - struct gpio_led *leds) __init; - -#endif /* _ASM_MIPS_MACH_ADM5120_PLATFORM_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_switch.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_switch.h deleted file mode 100644 index 91adc5bae9..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_switch.h +++ /dev/null @@ -1,300 +0,0 @@ -/* - * ADM5120 ethernet switch definitions - * - * This header file defines the hardware registers of the ADM5120 SoC - * built-in Ethernet switch. - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MACH_ADM5120_SWITCH_H -#define _MACH_ADM5120_SWITCH_H - -#ifndef BIT -# define BIT(at) (1 << (at)) -#endif -#define BITMASK(len) (BIT(len)-1) - -#define SW_READ_REG(r) __raw_readl( \ - (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE) + r) -#define SW_WRITE_REG(r, v) __raw_writel((v), \ - (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE) + r) - -/* Switch register offsets */ -#define SWITCH_REG_CODE 0x0000 -#define SWITCH_REG_SOFT_RESET 0x0004 /* Soft Reset */ -#define SWITCH_REG_BOOT_DONE 0x0008 /* Boot Done */ -#define SWITCH_REG_SW_RESET 0x000C /* Switch Reset */ -#define SWITCH_REG_PHY_STATUS 0x0014 /* PHY Status */ -#define SWITCH_REG_MEMCTRL 0x001C /* Memory Control */ -#define SWITCH_REG_CPUP_CONF 0x0024 /* CPU Port Configuration */ -#define SWITCH_REG_PORT_CONF0 0x0028 /* Port Configuration 0 */ -#define SWITCH_REG_PORT_CONF1 0x002C /* Port Configuration 1 */ -#define SWITCH_REG_PORT_CONF2 0x0030 /* Port Configuration 2 */ -#define SWITCH_REG_VLAN_G1 0x0040 /* VLAN group 1 */ -#define SWITCH_REG_VLAN_G2 0x0044 /* VLAN group 2 */ -#define SWITCH_REG_SEND_TRIG 0x0048 /* Send Trigger */ -#define SWITCH_REG_MAC_WT0 0x0058 /* MAC Write Address 0 */ -#define SWITCH_REG_MAC_WT1 0x005C /* MAC Write Address 1 */ -#define SWITCH_REG_BW_CNTL0 0x0060 /* Bandwidth Control 0 */ -#define SWITCH_REG_BW_CNTL1 0x0064 /* Bandwidth Control 1 */ -#define SWITCH_REG_PHY_CNTL0 0x0068 /* PHY Control 0 */ -#define SWITCH_REG_PHY_CNTL1 0x006C /* PHY Control 1 */ -#define SWITCH_REG_PORT_TH 0x0078 /* Port Threshold */ -#define SWITCH_REG_PHY_CNTL2 0x007C /* PHY Control 2 */ -#define SWITCH_REG_PHY_CNTL3 0x0080 /* PHY Control 3 */ -#define SWITCH_REG_PRI_CNTL 0x0084 /* Priority Control */ -#define SWITCH_REG_PHY_CNTL4 0x00A0 /* PHY Control 4 */ -#define SWITCH_REG_EMPTY_CNT 0x00A4 /* Empty Count */ -#define SWITCH_REG_PORT_CNTLS 0x00A8 /* Port Control Select */ -#define SWITCH_REG_PORT_CNTL 0x00AC /* Port Control */ -#define SWITCH_REG_INT_STATUS 0x00B0 /* Interrupt Status */ -#define SWITCH_REG_INT_MASK 0x00B4 /* Interrupt Mask */ -#define SWITCH_REG_GPIO_CONF0 0x00B8 /* GPIO Configuration 0 */ -#define SWITCH_REG_GPIO_CONF2 0x00BC /* GPIO Configuration 1 */ -#define SWITCH_REG_WDOG0 0x00C0 /* Watchdog 0 */ -#define SWITCH_REG_WDOG1 0x00C4 /* Watchdog 1 */ - -#define SWITCH_REG_SHDA 0x00D0 /* Send High Descriptors Address */ -#define SWITCH_REG_SLDA 0x00D4 /* Send Low Descriptors Address */ -#define SWITCH_REG_RHDA 0x00D8 /* Receive High Descriptor Address */ -#define SWITCH_REG_RLDA 0x00DC /* Receive Low Descriptor Address */ -#define SWITCH_REG_SHWA 0x00E0 /* Send High Working Address */ -#define SWITCH_REG_SLWA 0x00E4 /* Send Low Working Address */ -#define SWITCH_REG_RHWA 0x00E8 /* Receive High Working Address */ -#define SWITCH_REG_RLWA 0x00EC /* Receive Low Working Address */ - -#define SWITCH_REG_TIMER_INT 0x00F0 /* Timer */ -#define SWITCH_REG_TIMER 0x00F4 /* Timer Interrupt */ - -#define SWITCH_REG_PORT0_LED 0x0100 -#define SWITCH_REG_PORT1_LED 0x0104 -#define SWITCH_REG_PORT2_LED 0x0108 -#define SWITCH_REG_PORT3_LED 0x010C -#define SWITCH_REG_PORT4_LED 0x0110 - -/* CODE register bits */ -#define CODE_PC_MASK BITMASK(16) /* Product Code */ -#define CODE_REV_SHIFT 16 -#define CODE_REV_MASK BITMASK(4) /* Product Revision */ -#define CODE_CLKS_SHIFT 20 -#define CODE_CLKS_MASK BITMASK(2) /* Clock Speed */ -#define CODE_CLKS_175 0 /* 175 MHz */ -#define CODE_CLKS_200 1 /* 200 MHz */ -#define CODE_CLKS_225 2 /* 225 MHz */ -#define CODE_CLKS_250 3 /* 250 MHz */ -#define CODE_NAB BIT(24) /* NAND boot */ -#define CODE_PK_MASK BITMASK(1) /* Package type */ -#define CODE_PK_SHIFT 29 -#define CODE_PK_BGA 0 /* BGA package */ -#define CODE_PK_PQFP 1 /* PQFP package */ - -/* MEMCTRL register bits */ -#define MEMCTRL_SDRS_MASK BITMASK(3) /* SDRAM bank size */ -#define MEMCTRL_SDRS_4M 0x01 -#define MEMCTRL_SDRS_8M 0x02 -#define MEMCTRL_SDRS_16M 0x03 -#define MEMCTRL_SDRS_64M 0x04 -#define MEMCTRL_SDRS_128M 0x05 -#define MEMCTRL_SDR1_ENABLE BIT(5) /* enable SDRAM bank 1 */ - -#define MEMCTRL_SRS0_SHIFT 8 /* shift for SRAM0 size */ -#define MEMCTRL_SRS1_SHIFT 16 /* shift for SRAM1 size */ -#define MEMCTRL_SRS_MASK BITMASK(3) /* SRAM size mask */ -#define MEMCTRL_SRS_DISABLED 0x00 /* Disabled */ -#define MEMCTRL_SRS_512K 0x01 /* 512KB*/ -#define MEMCTRL_SRS_1M 0x02 /* 1MB */ -#define MEMCTRL_SRS_2M 0x03 /* 2MB */ -#define MEMCTRL_SRS_4M 0x04 /* 4MB */ - -/* Port bits used in various registers */ -#define SWITCH_PORT_PHY0 BIT(0) -#define SWITCH_PORT_PHY1 BIT(1) -#define SWITCH_PORT_PHY2 BIT(2) -#define SWITCH_PORT_PHY3 BIT(3) -#define SWITCH_PORT_PHY4 BIT(4) -#define SWITCH_PORT_MII BIT(5) -#define SWITCH_PORT_CPU BIT(6) - -/* Port bit shorthands */ -#define SWITCH_PORTS_PHY 0x1F /* phy ports */ -#define SWITCH_PORTS_NOCPU 0x3F /* physical ports */ -#define SWITCH_PORTS_ALL 0x7F /* all ports */ - -/* CPUP_CONF register bits */ -#define CPUP_CONF_DCPUP BIT(0) /* Disable CPU port */ -#define CPUP_CONF_CRCP BIT(1) /* CRC padding from CPU */ -#define CPUP_CONF_BTM BIT(2) /* Bridge Testing Mode */ -#define CPUP_CONF_DUNP_SHIFT 9 /* Disable Unknown Packets for portX */ -#define CPUP_CONF_DMCP_SHIFT 16 /* Disable Mcast Packets form portX */ -#define CPUP_CONF_DBCP_SHIFT 24 /* Disable Bcast Packets form portX */ - -/* PORT_CONF0 register bits */ -#define PORT_CONF0_DP_SHIFT 0 /* Disable Port */ -#define PORT_CONF0_EMCP_SHIFT 8 /* Enable All MC Packets */ -#define PORT_CONF0_BP_SHIFT 16 /* Enable Back Pressure */ - -/* PORT_CONF1 register bits */ -#define PORT_CONF1_DISL_SHIFT 0 /* Disable Learning */ -#define PORT_CONF1_BS_SHIFT 6 /* Blocking State */ -#define PORT_CONF1_BM_SHIFT 12 /* Blocking Mode */ - -/* SEND_TRIG register bits */ -#define SEND_TRIG_STL BIT(0) /* Send Trigger Low */ -#define SEND_TRIG_STH BIT(1) /* Send Trigger High */ - -/* MAC_WT0 register bits */ -#define MAC_WT0_MAWC BIT(0) /* MAC address write command */ -#define MAC_WT0_MWD_SHIFT 1 -#define MAC_WT0_MWD BIT(1) /* MAC write done */ -#define MAC_WT0_WFB BIT(2) /* Write Filter Bit */ -#define MAC_WT0_WVN_SHIFT 3 /* Write Vlan Number shift */ -#define MAC_WT0_WVE BIT(6) /* Write VLAN enable */ -#define MAC_WT0_WPMN_SHIFT 7 -#define MAC_WT0_WAF_SHIFT 13 /* Write Age Field shift */ -#define MAC_WT0_WAF_EMPTY 0 -#define MAC_WT0_WAF_STATIC 7 /* age: static */ -#define MAC_WT0_MAC0_SHIFT 16 -#define MAC_WT0_MAC1_SHIFT 24 - -/* MAC_WT1 register bits */ -#define MAC_WT1_MAC2_SHIFT 0 -#define MAC_WT1_MAC3_SHIFT 8 -#define MAC_WT1_MAC4_SHIFT 16 -#define MAC_WT1_MAC5_SHIFT 24 - -/* BW_CNTL0/BW_CNTL1 register bits */ -#define BW_CNTL_DISABLE 0x00 -#define BW_CNTL_64K 0x01 -#define BW_CNTL_128K 0x02 -#define BW_CNTL_256K 0x03 -#define BW_CNTL_512K 0x04 -#define BW_CNTL_1M 0x05 -#define BW_CNTL_4M 0x06 -#define BW_CNTL_10M 0x07 - -#define P4TBC_SHIFT 0 -#define P4RBC_SHIFT 4 -#define P5TBC_SHIFT 8 -#define P5RBC_SHIFT 12 - -#define BW_CNTL1_NAND_ENABLE 0x100 - -/* PHY_CNTL0 register bits */ -#define PHY_CNTL0_PHYA_MASK BITMASK(5) -#define PHY_CNTL0_PHYR_MASK BITMASK(5) -#define PHY_CNTL0_PHYR_SHIFT 8 -#define PHY_CNTL0_WC BIT(13) /* Write Command */ -#define PHY_CNTL0_RC BIT(14) /* Read Command */ -#define PHY_CNTL0_WTD_MASK BIT(16) /* Read Command */ -#define PHY_CNTL0_WTD_SHIFT 16 - -/* PHY_CNTL1 register bits */ -#define PHY_CNTL1_WOD BIT(0) /* Write Operation Done */ -#define PHY_CNTL1_ROD BIT(1) /* Read Operation Done */ -#define PHY_CNTL1_RD_MASK BITMASK(16) -#define PHY_CNTL1_RD_SHIFT 16 - -/* PHY_CNTL2 register bits */ -#define PHY_CNTL2_ANE_SHIFT 0 /* Auto Negotiation Enable */ -#define PHY_CNTL2_SC_SHIFT 5 /* Speed Control */ -#define PHY_CNTL2_DC_SHIFT 10 /* Duplex Control */ -#define PHY_CNTL2_FNCV_SHIFT 15 /* Recommended FC Value */ -#define PHY_CNTL2_PHYR_SHIFT 20 /* PHY reset */ -#define PHY_CNTL2_AMDIX_SHIFT 25 /* Auto MDIX enable */ -/* PHY_CNTL2_RMAE is bad in datasheet */ -#define PHY_CNTL2_RMAE BIT(31) /* Recommended MCC Average enable */ - -/* PHY_CNTL3 register bits */ -#define PHY_CNTL3_RNT BIT(10) /* Recommend Normal Threshold */ - -/* PORT_TH register bits */ -#define PORT_TH_PPT_MASK BITMASK(8) /* Per Port Threshold */ -#define PORT_TH_CPUT_SHIFT 8 /* CPU Port Buffer Threshold */ -#define PORT_TH_CPUT_MASK BITMASK(8) -#define PORT_TH_CPUHT_SHIFT 16 /* CPU Hold Threshold */ -#define PORT_TH_CPUHT_MASK BITMASK(8) -#define PORT_TH_CPURT_SHIFT 24 /* CPU Release Threshold */ -#define PORT_TH_CPURT_MASK BITMASK(8) - -/* EMPTY_CNT register bits */ -#define EMPTY_CNT_EBGB_MASK BITMASK(9) /* Empty Blocks in the Global Buffer */ - -/* GPIO_CONF0 register bits */ -#define GPIO_CONF0_MASK BITMASK(8) -#define GPIO_CONF0_IM_SHIFT 0 -#define GPIO_CONF0_IV_SHIFT 8 -#define GPIO_CONF0_OE_SHIFT 16 -#define GPIO_CONF0_OV_SHIFT 24 -#define GPIO_CONF0_IM_MASK (0xFF << GPIO_CONF0_IM_SHIFT) -#define GPIO_CONF0_IV_MASK (0xFF << GPIO_CONF0_IV_SHIFT) -#define GPIO_CONF0_OE_MASK (0xFF << GPIO_CONF0_OE_SHIFT) -#define GPIO_CONF0_OV_MASK (0xFF << GPIO_CONF0_OV_SHIFT) - -/* GPIO_CONF2 register bits */ -#define GPIO_CONF2_CSX0 BIT(4) /* enable CSX0:INTX0 on GPIO 1:2 */ -#define GPIO_CONF2_CSX1 BIT(5) /* enable CSX1:INTX1 on GPIO 3:4 */ -#define GPIO_CONF2_EW BIT(6) /* enable wait state pin for CSX0/1 */ - -/* INT_STATUS/INT_MASK register bits */ -#define SWITCH_INT_SHD BIT(0) /* Send High Done */ -#define SWITCH_INT_SLD BIT(1) /* Send Low Done */ -#define SWITCH_INT_RHD BIT(2) /* Receive High Done */ -#define SWITCH_INT_RLD BIT(3) /* Receive Low Done */ -#define SWITCH_INT_HDF BIT(4) /* High Descriptor Full */ -#define SWITCH_INT_LDF BIT(5) /* Low Descriptor Full */ -#define SWITCH_INT_P0QF BIT(6) /* Port0 Queue Full */ -#define SWITCH_INT_P1QF BIT(7) /* Port1 Queue Full */ -#define SWITCH_INT_P2QF BIT(8) /* Port2 Queue Full */ -#define SWITCH_INT_P3QF BIT(9) /* Port3 Queue Full */ -#define SWITCH_INT_P4QF BIT(10) /* Port4 Queue Full */ -#define SWITCH_INT_P5QF BIT(11) /* Port5 Queue Full */ -#define SWITCH_INT_CPQF BIT(13) /* CPU Queue Full */ -#define SWITCH_INT_GQF BIT(14) /* Global Queue Full */ -#define SWITCH_INT_MD BIT(15) /* Must Drop */ -#define SWITCH_INT_BCS BIT(16) /* BC Storm */ -#define SWITCH_INT_PSC BIT(18) /* Port Status Change */ -#define SWITCH_INT_ID BIT(19) /* Intruder Detected */ -#define SWITCH_INT_W0TE BIT(20) /* Watchdog 0 Timer Expired */ -#define SWITCH_INT_W1TE BIT(21) /* Watchdog 1 Timer Expired */ -#define SWITCH_INT_RDE BIT(22) /* Receive Descriptor Error */ -#define SWITCH_INT_SDE BIT(23) /* Send Descriptor Error */ -#define SWITCH_INT_CPUH BIT(24) /* CPU Hold */ - -/* TIMER_INT register bits */ -#define TIMER_INT_TOS BIT(0) /* time-out status */ -#define TIMER_INT_TOM BIT(16) /* mask time-out interrupt */ - -/* TIMER register bits */ -#define TIMER_PERIOD_MASK BITMASK(16) /* mask for timer period */ -#define TIMER_PERIOD_DEFAULT 0xFFFF /* default timer period */ -#define TIMER_TE BIT(16) /* timer enable bit */ - -/* PORTx_LED register bits */ -#define LED_MODE_MASK BITMASK(4) -#define LED_MODE_INPUT 0 -#define LED_MODE_FLASH 1 -#define LED_MODE_OUT_HIGH 2 -#define LED_MODE_OUT_LOW 3 -#define LED_MODE_LINK 4 -#define LED_MODE_SPEED 5 -#define LED_MODE_DUPLEX 6 -#define LED_MODE_ACT 7 -#define LED_MODE_COLL 8 -#define LED_MODE_LINK_ACT 9 -#define LED_MODE_DUPLEX_COLL 10 -#define LED_MODE_10M_ACT 11 -#define LED_MODE_100M_ACT 12 -#define LED0_MODE_SHIFT 0 /* LED0 mode shift */ -#define LED1_MODE_SHIFT 4 /* LED1 mode shift */ -#define LED2_MODE_SHIFT 8 /* LED2 mode shift */ -#define LED0_IV_SHIFT 12 /* LED0 input value shift */ -#define LED1_IV_SHIFT 13 /* LED1 input value shift */ -#define LED2_IV_SHIFT 14 /* LED2 input value shift */ - -#endif /* _MACH_ADM5120_SWITCH_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_uart.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_uart.h deleted file mode 100644 index 81d3067da3..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/adm5120_uart.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * ADM5120 UART definitions - * - * This header file defines the hardware registers of the ADM5120 SoC - * built-in UARTs. - * - * Copyright (C) 2007 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MACH_ADM5120_UART_H -#define _MACH_ADM5120_UART_H - -#define UART_BAUDDIV(clk, baud) ((clk/(16 * (baud)))-1) - -#define UART_REG_DATA 0x00 -#define UART_REG_RSR 0x04 -#define UART_REG_ECR UART_REG_RSR -#define UART_REG_LCRH 0x08 -#define UART_REG_LCRM 0x0C -#define UART_REG_LCRL 0x10 -#define UART_REG_CTRL 0x14 -#define UART_REG_FLAG 0x18 - -/* Receive Status Register bits */ -#define UART_RSR_FE (1 << 0) -#define UART_RSR_PE (1 << 1) -#define UART_RSR_BE (1 << 2) -#define UART_RSR_OE (1 << 3) -#define UART_RSR_ERR (UART_RSR_FE | UART_RSR_PE | UART_RSR_BE) - -#define UART_ECR_ALL 0xFF - -/* Line Control High register bits */ -#define UART_LCRH_BRK (1 << 0) /* send break */ -#define UART_LCRH_PEN (1 << 1) /* parity enable */ -#define UART_LCRH_EPS (1 << 2) /* even parity select */ -#define UART_LCRH_STP1 (0 << 3) /* one stop bits select */ -#define UART_LCRH_STP2 (1 << 3) /* two stop bits select */ -#define UART_LCRH_FEN (1 << 4) /* FIFO enable */ - -#define UART_LCRH_WLEN5 (0 << 5) -#define UART_LCRH_WLEN6 (1 << 5) -#define UART_LCRH_WLEN7 (2 << 5) -#define UART_LCRH_WLEN8 (3 << 5) - -/* Control register bits */ -#define UART_CTRL_EN (1 << 0) - -/* Flag register bits */ -#define UART_FLAG_CTS (1 << 0) -#define UART_FLAG_DSR (1 << 1) -#define UART_FLAG_DCD (1 << 2) -#define UART_FLAG_BUSY (1 << 3) -#define UART_FLAG_RXFE (1 << 4) -#define UART_FLAG_TXFF (1 << 5) -#define UART_FLAG_RXFF (1 << 6) -#define UART_FLAG_TXFE (1 << 7) - -#endif /* _MACH_ADM5120_UART_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/asm/sizes.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/asm/sizes.h deleted file mode 100644 index 503843db15..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/asm/sizes.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 - */ -/* DO NOT EDIT!! - this file automatically generated - * from .s file by awk -f s2h.awk - */ -/* Size definitions - * Copyright (C) ARM Limited 1998. All rights reserved. - */ - -#ifndef __sizes_h -#define __sizes_h 1 - -/* handy sizes */ -#define SZ_16 0x00000010 -#define SZ_256 0x00000100 -#define SZ_512 0x00000200 - -#define SZ_1K 0x00000400 -#define SZ_4K 0x00001000 -#define SZ_8K 0x00002000 -#define SZ_16K 0x00004000 -#define SZ_64K 0x00010000 -#define SZ_128K 0x00020000 -#define SZ_256K 0x00040000 -#define SZ_512K 0x00080000 - -#define SZ_1M 0x00100000 -#define SZ_2M 0x00200000 -#define SZ_4M 0x00400000 -#define SZ_8M 0x00800000 -#define SZ_16M 0x01000000 -#define SZ_32M 0x02000000 -#define SZ_64M 0x04000000 -#define SZ_128M 0x08000000 -#define SZ_256M 0x10000000 -#define SZ_512M 0x20000000 - -#define SZ_1G 0x40000000 -#define SZ_2G 0x80000000 - -#endif - -/* END */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h deleted file mode 100644 index c6310cc6e6..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/cpu-feature-overrides.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * ADM5120 specific CPU feature overrides - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: include/asm-mips/cpu-features.h - * Copyright (C) 2003, 2004 Ralf Baechle - * Copyright (C) 2004 Maciej W. Rozycki - * - * 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_ADM5120_CPU_FEATURE_OVERRIDES_H -#define __ASM_MACH_ADM5120_CPU_FEATURE_OVERRIDES_H - -/* - * The ADM5120 SOC has a built-in MIPS 4Kc core. - */ -#define cpu_has_tlb 1 -#define cpu_has_4kex 1 -#define cpu_has_3k_cache 0 -#define cpu_has_4k_cache 1 -#define cpu_has_tx39_cache 0 -#define cpu_has_sb1_cache 0 -#define cpu_has_fpu 0 -#define cpu_has_32fpr 0 -#define cpu_has_counter 1 -#define cpu_has_watch 1 -#define cpu_has_divec 1 -/* #define cpu_has_vce ? */ -/* #define cpu_has_cache_cdex_p ? */ -/* #define cpu_has_cache_cdex_s ? */ -#define cpu_has_prefetch 1 -/* #define cpu_has_mcheck ? */ -#define cpu_has_ejtag 1 -#define cpu_has_llsc 1 - -#define cpu_has_mips16 0 -#define cpu_has_mdmx 0 -#define cpu_has_mips3d 0 -#define cpu_has_smartmips 0 - -/* #define cpu_has_vtag_icache ? */ -/* #define cpu_has_dc_aliases ? */ -/* #define cpu_has_ic_fills_f_dc ? */ -/* #define cpu_has_pindexed_dcache ? */ - -/* #define cpu_icache_snoops_remote_store ? */ - -#define cpu_has_mips32r1 1 -#define cpu_has_mips32r2 0 -#define cpu_has_mips64r1 0 -#define cpu_has_mips64r2 0 - -#define cpu_has_dsp 0 -#define cpu_has_mipsmt 0 - -/* #define cpu_has_nofpuex ? */ -#define cpu_has_64bits 0 -#define cpu_has_64bit_zero_reg 0 -#define cpu_has_64bit_gp_regs 0 -#define cpu_has_64bit_addresses 0 - -/* #define cpu_has_inclusive_pcaches ? */ - -#define cpu_dcache_line_size() 16 -#define cpu_icache_line_size() 16 - -#endif /* __ASM_MACH_ADM5120_CPU_FEATURE_OVERRIDES_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/gpio.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/gpio.h deleted file mode 100644 index 7ba7efca1f..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/gpio.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * ADM5120 GPIO wrappers for arch-neutral GPIO calls - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _ASM_MIPS_MACH_ADM5120_GPIO_H -#define _ASM_MIPS_MACH_ADM5120_GPIO_H - -#define ARCH_NR_GPIOS 64 - -#include - -#include - -#define ADM5120_GPIO_PIN0 0 -#define ADM5120_GPIO_PIN1 1 -#define ADM5120_GPIO_PIN2 2 -#define ADM5120_GPIO_PIN3 3 -#define ADM5120_GPIO_PIN4 4 -#define ADM5120_GPIO_PIN5 5 -#define ADM5120_GPIO_PIN6 6 -#define ADM5120_GPIO_PIN7 7 -#define ADM5120_GPIO_P0L0 8 -#define ADM5120_GPIO_P0L1 9 -#define ADM5120_GPIO_P0L2 10 -#define ADM5120_GPIO_P1L0 11 -#define ADM5120_GPIO_P1L1 12 -#define ADM5120_GPIO_P1L2 13 -#define ADM5120_GPIO_P2L0 14 -#define ADM5120_GPIO_P2L1 15 -#define ADM5120_GPIO_P2L2 16 -#define ADM5120_GPIO_P3L0 17 -#define ADM5120_GPIO_P3L1 18 -#define ADM5120_GPIO_P3L2 19 -#define ADM5120_GPIO_P4L0 20 -#define ADM5120_GPIO_P4L1 21 -#define ADM5120_GPIO_P4L2 22 -#define ADM5120_GPIO_MAX 22 -#define ADM5120_GPIO_COUNT ADM5120_GPIO_MAX+1 - -#define ADM5120_GPIO_LOW 0 -#define ADM5120_GPIO_HIGH 1 - -#define ADM5120_GPIO_SWITCH 0x10 -#define ADM5120_GPIO_FLASH (ADM5120_GPIO_SWITCH | LED_MODE_FLASH) -#define ADM5120_GPIO_LINK (ADM5120_GPIO_SWITCH | LED_MODE_LINK) -#define ADM5120_GPIO_SPEED (ADM5120_GPIO_SWITCH | LED_MODE_SPEED) -#define ADM5120_GPIO_DUPLEX (ADM5120_GPIO_SWITCH | LED_MODE_DUPLEX) -#define ADM5120_GPIO_ACT (ADM5120_GPIO_SWITCH | LED_MODE_ACT) -#define ADM5120_GPIO_COLL (ADM5120_GPIO_SWITCH | LED_MODE_COLL) -#define ADM5120_GPIO_LINK_ACT (ADM5120_GPIO_SWITCH | LED_MODE_LINK_ACT) -#define ADM5120_GPIO_DUPLEX_COLL (ADM5120_GPIO_SWITCH | LED_MODE_DUPLEX_COLL) -#define ADM5120_GPIO_10M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_10M_ACT) -#define ADM5120_GPIO_100M_ACT (ADM5120_GPIO_SWITCH | LED_MODE_100M_ACT) - -extern int __adm5120_gpio0_get_value(unsigned gpio); -extern void __adm5120_gpio0_set_value(unsigned gpio, int value); -extern int __adm5120_gpio1_get_value(unsigned gpio); -extern void __adm5120_gpio1_set_value(unsigned gpio, int value); -extern int adm5120_gpio_to_irq(unsigned gpio); -extern int adm5120_irq_to_gpio(unsigned irq); - -static inline int gpio_get_value(unsigned gpio) -{ - int ret; - - switch (gpio) { - case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: - ret = __adm5120_gpio0_get_value(gpio); - break; - case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: - ret = __adm5120_gpio1_get_value(gpio - ADM5120_GPIO_P0L0); - break; - default: - ret = __gpio_get_value(gpio); - break; - } - - return ret; -} - -static inline void gpio_set_value(unsigned gpio, int value) -{ - switch (gpio) { - case ADM5120_GPIO_PIN0 ... ADM5120_GPIO_PIN7: - __adm5120_gpio0_set_value(gpio, value); - break; - case ADM5120_GPIO_P0L0 ... ADM5120_GPIO_P4L2: - __adm5120_gpio1_set_value(gpio - ADM5120_GPIO_P0L0, value); - break; - default: - __gpio_set_value(gpio, value); - break; - } -} - -static inline int gpio_to_irq(unsigned gpio) -{ - return adm5120_gpio_to_irq(gpio); -} - -static inline int irq_to_gpio(unsigned irq) -{ - return adm5120_irq_to_gpio(irq); -} - -#define gpio_cansleep __gpio_cansleep - -#endif /* _ASM_MIPS_MACH_ADM5120_GPIO_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/irq.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/irq.h deleted file mode 100644 index b0350c8b83..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/irq.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * ADM5120 specific IRQ numbers - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ -#ifndef _ASM_MIPS_MACH_ADM5120_IRQ_H -#define _ASM_MIPS_MACH_ADM5120_IRQ_H - -#define MIPS_CPU_IRQ_BASE 0 -#define NR_IRQS 24 - -#include_next - -#include - -#define NO_IRQ (-1) - -#define MIPS_CPU_IRQ_COUNT 8 -#define MIPS_CPU_IRQ(x) (MIPS_CPU_IRQ_BASE + (x)) - -#define ADM5120_INTC_IRQ_BASE (MIPS_CPU_IRQ_BASE + MIPS_CPU_IRQ_COUNT) -#define ADM5120_INTC_IRQ(x) (ADM5120_INTC_IRQ_BASE + (x)) - -#define ADM5120_IRQ_INTC MIPS_CPU_IRQ(2) -#define ADM5120_IRQ_COUNTER MIPS_CPU_IRQ(7) - -#define ADM5120_IRQ_TIMER ADM5120_INTC_IRQ(INTC_IRQ_TIMER) -#define ADM5120_IRQ_UART0 ADM5120_INTC_IRQ(INTC_IRQ_UART0) -#define ADM5120_IRQ_UART1 ADM5120_INTC_IRQ(INTC_IRQ_UART1) -#define ADM5120_IRQ_USBC ADM5120_INTC_IRQ(INTC_IRQ_USBC) -#define ADM5120_IRQ_GPIO2 ADM5120_INTC_IRQ(INTC_IRQ_GPIO2) -#define ADM5120_IRQ_GPIO4 ADM5120_INTC_IRQ(INTC_IRQ_GPIO4) -#define ADM5120_IRQ_PCI0 ADM5120_INTC_IRQ(INTC_IRQ_PCI0) -#define ADM5120_IRQ_PCI1 ADM5120_INTC_IRQ(INTC_IRQ_PCI1) -#define ADM5120_IRQ_PCI2 ADM5120_INTC_IRQ(INTC_IRQ_PCI2) -#define ADM5120_IRQ_SWITCH ADM5120_INTC_IRQ(INTC_IRQ_SWITCH) - -#endif /* _ASM_MIPS_MACH_ADM5120_IRQ_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/admboot.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/admboot.h deleted file mode 100644 index fa42bf7148..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/admboot.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * ADMBoot specific definitions - * - * Copyright (C) 2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _ADMBOOT_H -#define _ADMBOOT_H - -extern int admboot_get_mac_base(u32 offset, u32 len, u8 *mac) __init; - -#endif /* _ADMBOOT_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/cfe.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/cfe.h deleted file mode 100644 index 0cb3eee70e..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/cfe.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Broadcom's CFE definitions - * - * Copyright (C) 2006-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _PROM_CFE_H_ -#define _PROM_CFE_H_ - -extern int cfe_present(void) __init; -extern char *cfe_getenv(char *); - -#endif /*_PROM_CFE_H_*/ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/generic.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/generic.h deleted file mode 100644 index 778df24677..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/generic.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Generic prom definitions - * - * Copyright (C) 2006-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _PROM_GENERIC_H_ -#define _PROM_GENERIC_H_ - -extern int generic_prom_present(void) __init; -extern char *generic_prom_getenv(char *); - -#endif /*_PROM_GENERIC_H_*/ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/myloader.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/myloader.h deleted file mode 100644 index ea8db81ed3..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/myloader.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Compex's MyLoader specific definitions - * - * Copyright (C) 2006-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _MYLOADER_H_ -#define _MYLOADER_H_ - -/* - * Firmware file format: - * - *
- * [] - * ... - * [] - * - * [] - * ... - * [] - * - * - */ - -/* Myloader specific magic numbers */ -#define MYLO_MAGIC_FIRMWARE 0x4C594D00 -#define MYLO_MAGIC_20021103 0x20021103 -#define MYLO_MAGIC_20021107 0x20021107 - -#define MYLO_MAGIC_SYS_PARAMS MYLO_MAGIC_20021107 -#define MYLO_MAGIC_PARTITIONS MYLO_MAGIC_20021103 -#define MYLO_MAGIC_BOARD_PARAMS MYLO_MAGIC_20021103 - -/* - * Addresses of the data structures provided by MyLoader - */ -#define MYLO_MIPS_SYS_PARAMS 0x80000800 /* System Parameters */ -#define MYLO_MIPS_BOARD_PARAMS 0x80000A00 /* Board Parameters */ -#define MYLO_MIPS_PARTITIONS 0x80000C00 /* Partition Table */ -#define MYLO_MIPS_BOOT_PARAMS 0x80000E00 /* Boot Parameters */ - -/* Vendor ID's (seems to be same as the PCI vendor ID's) */ -#define VENID_COMPEX 0x11F6 - -/* Devices based on the ADM5120 */ -#define DEVID_COMPEX_NP27G 0x0078 -#define DEVID_COMPEX_NP28G 0x044C -#define DEVID_COMPEX_NP28GHS 0x044E -#define DEVID_COMPEX_WP54Gv1C 0x0514 -#define DEVID_COMPEX_WP54G 0x0515 -#define DEVID_COMPEX_WP54AG 0x0546 -#define DEVID_COMPEX_WPP54AG 0x0550 -#define DEVID_COMPEX_WPP54G 0x0555 - -/* Devices based on the IXP422 */ -#define DEVID_COMPEX_WP18 0x047E -#define DEVID_COMPEX_NP18A 0x0489 - -/* Other devices */ -#define DEVID_COMPEX_NP26G8M 0x03E8 -#define DEVID_COMPEX_NP26G16M 0x03E9 - -struct mylo_fw_header { - uint32_t magic; /* must be MYLO_MAGIC_FIRMWARE */ - uint32_t crc; /* CRC of the whole firmware */ - uint32_t res0; /* unknown/unused */ - uint32_t res1; /* unknown/unused */ - uint16_t vid; /* vendor ID */ - uint16_t did; /* device ID */ - uint16_t svid; /* sub vendor ID */ - uint16_t sdid; /* sub device ID */ - uint32_t rev; /* device revision */ - uint32_t fwhi; /* FIXME: firmware version high? */ - uint32_t fwlo; /* FIXME: firmware version low? */ - uint32_t flags; /* firmware flags */ -}; - -#define FW_FLAG_BOARD_PARAMS_WP 0x01 /* board parameters are write protected */ -#define FW_FLAG_BOOT_SECTOR_WE 0x02 /* enable of write boot sectors (below 64K) */ - -struct mylo_fw_blockdesc { - uint32_t type; /* block type */ - uint32_t addr; /* relative address to flash start */ - uint32_t dlen; /* size of block data in bytes */ - uint32_t blen; /* total size of block in bytes */ -}; - -#define FW_DESC_TYPE_UNUSED 0 -#define FW_DESC_TYPE_USED 1 - -struct mylo_partition { - uint16_t flags; /* partition flags */ - uint16_t type; /* type of the partition */ - uint32_t addr; /* relative address of the partition from the - flash start */ - uint32_t size; /* size of the partition in bytes */ - uint32_t param; /* if this is the active partition, the - MyLoader load code to this address */ -}; - -#define PARTITION_FLAG_ACTIVE 0x8000 /* this is the active partition, - * MyLoader loads firmware from here */ -#define PARTITION_FLAG_ISRAM 0x2000 /* FIXME: this is a RAM partition? */ -#define PARTIIION_FLAG_RAMLOAD 0x1000 /* FIXME: load this partition into the RAM? */ -#define PARTITION_FLAG_PRELOAD 0x0800 /* the partition data preloaded to RAM - * before decompression */ -#define PARTITION_FLAG_HAVEHDR 0x0002 /* the partition data have a header */ - -#define PARTITION_TYPE_FREE 0 -#define PARTITION_TYPE_USED 1 - -#define MYLO_MAX_PARTITIONS 8 /* maximum number of partitions in the - partition table */ - -struct mylo_partition_table { - uint32_t magic; /* must be MYLO_MAGIC_PARTITIONS */ - uint32_t res0; /* unknown/unused */ - uint32_t res1; /* unknown/unused */ - uint32_t res2; /* unknown/unused */ - struct mylo_partition partitions[MYLO_MAX_PARTITIONS]; -}; - -struct mylo_partition_header { - uint32_t len; /* length of the partition data */ - uint32_t crc; /* CRC value of the partition data */ -}; - -struct mylo_system_params { - uint32_t magic; /* must be MYLO_MAGIC_SYS_PARAMS */ - uint32_t res0; - uint32_t res1; - uint32_t mylo_ver; - uint16_t vid; /* Vendor ID */ - uint16_t did; /* Device ID */ - uint16_t svid; /* Sub Vendor ID */ - uint16_t sdid; /* Sub Device ID */ - uint32_t rev; /* device revision */ - uint32_t fwhi; - uint32_t fwlo; - uint32_t tftp_addr; - uint32_t prog_start; - uint32_t flash_size; /* Size of boot FLASH in bytes */ - uint32_t dram_size; /* Size of onboard RAM in bytes */ -}; - - -struct mylo_eth_addr { - uint8_t mac[6]; - uint8_t csum[2]; -}; - -#define MYLO_ETHADDR_COUNT 8 /* maximum number of ethernet address - in the board parameters */ - -struct mylo_board_params { - uint32_t magic; /* must be MYLO_MAGIC_BOARD_PARAMS */ - uint32_t res0; - uint32_t res1; - uint32_t res2; - struct mylo_eth_addr addr[MYLO_ETHADDR_COUNT]; -}; - -struct myloader_info { - u32 vid; - u32 did; - u32 svid; - u32 sdid; - uint8_t macs[MYLO_ETHADDR_COUNT][6]; -}; - -extern struct myloader_info myloader_info; -extern int myloader_present(void) __init; - -#endif /* _MYLOADER_H_*/ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/routerboot.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/routerboot.h deleted file mode 100644 index 91ac05a630..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/routerboot.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Mikrotik's RouterBOOT definitions - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _PROM_ROUTERBOOT_H_ -#define _PROM_ROUTERBOOT_H_ - -struct rb_bios_settings { - u32 hs_offs; /* hard settings offset */ - u32 hs_size; /* hard settings size */ - u32 fw_offs; /* firmware offset */ - u32 ss_offs; /* soft settings offset */ - u32 ss_size; /* soft settings size */ -}; - -struct rb_hard_settings { - char *name; /* board name */ - char *bios_ver; /* BIOS version */ - u32 mem_size; /* memory size in bytes */ - u32 mac_count; /* number of mac addresses */ - u8 *mac_base; /* mac address base */ -}; - -extern int routerboot_present(void) __init; -extern char *routerboot_get_boardname(void); - -extern struct rb_hard_settings rb_hs; - -#endif /* _PROM_ROUTERBOOT_H_ */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/zynos.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/zynos.h deleted file mode 100644 index d1e3e5b941..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/prom/zynos.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * ZyNOS (ZyXEL's Networking OS) definitions - * - * Copyright (C) 2007-2008 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 - * by the Free Software Foundation. - * - */ - -#ifndef _ZYNOS_H -#define _ZYNOS_H - -#define ZYNOS_NAME_LEN 32 -#define ZYNOS_FEAT_BYTES 22 -#define ZYNOS_MAC_LEN 6 - -struct zynos_board_info { - unsigned char vendor[ZYNOS_NAME_LEN]; - unsigned char product[ZYNOS_NAME_LEN]; - u32 bootext_addr; - u32 res0; - u16 board_id; - u8 res1[6]; - u8 feat_other[ZYNOS_FEAT_BYTES]; - u8 feat_main; - u8 res2; - u8 mac[ZYNOS_MAC_LEN]; - u8 country; - u8 dbgflag; -} __attribute__ ((packed)); - -/* - * Vendor IDs - */ -#define ZYNOS_VENDOR_ID_ZYXEL 0 -#define ZYNOS_VENDOR_ID_NETGEAR 1 -#define ZYNOS_VENDOR_ID_DLINK 2 -#define ZYNOS_VENDOR_ID_OTHER 3 -#define ZYNOS_VENDOR_ID_LUCENT 4 - -/* - * Vendor names - */ -#define ZYNOS_VENDOR_DLINK "D-Link" -#define ZYNOS_VENDOR_LUCENT "LUCENT" -#define ZYNOS_VENDOR_NETGEAR "NetGear" -#define ZYNOS_VENDOR_ZYXEL "ZyXEL" - -/* - * Board IDs (big-endian) - */ -#define ZYNOS_BOARD_ES2108 0x00F2 /* Ethernet Switch 2108 */ -#define ZYNOS_BOARD_ES2108F 0x01AF /* Ethernet Switch 2108-F */ -#define ZYNOS_BOARD_ES2108G 0x00F3 /* Ethernet Switch 2108-G */ -#define ZYNOS_BOARD_ES2108LC 0x00FC /* Ethernet Switch 2108-LC */ -#define ZYNOS_BOARD_ES2108PWR 0x00F4 /* Ethernet Switch 2108PWR */ -#define ZYNOS_BOARD_HS100 0x9FF1 /* HomeSafe 100/100W */ -#define ZYNOS_BOARD_P334 0x9FF5 /* Prestige 334 */ -#define ZYNOS_BOARD_P334U 0x9FDD /* Prestige 334U */ -#define ZYNOS_BOARD_P334W 0x9FF3 /* Prestige 334W */ -#define ZYNOS_BOARD_P334WH 0x00E0 /* Prestige 334WH */ -#define ZYNOS_BOARD_P334WHD 0x00E1 /* Prestige 334WHD */ -#define ZYNOS_BOARD_P334WT 0x9FEF /* Prestige 334WT */ -#define ZYNOS_BOARD_P334WT_ALT 0x9F02 /* Prestige 334WT alternative*/ -#define ZYNOS_BOARD_P335 0x9FED /* Prestige 335/335WT */ -#define ZYNOS_BOARD_P335PLUS 0x0025 /* Prestige 335Plus */ -#define ZYNOS_BOARD_P335U 0x9FDC /* Prestige 335U */ - -/* - * Some magic numbers (big-endian) - */ -#define ZYNOS_MAGIC_DBGAREA1 0x48646267 /* "Hdbg" */ -#define ZYNOS_MAGIC_DBGAREA2 0x61726561 /* "area" */ - -struct bootbase_info { - u16 vendor_id; - u16 board_id; - u8 mac[6]; -}; - -extern struct bootbase_info bootbase_info; -extern int bootbase_present(void) __init; - -#endif /* _ZYNOS_H */ diff --git a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/war.h b/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/war.h deleted file mode 100644 index 87c35f375b..0000000000 --- a/target/linux/adm5120/files/arch/mips/include/asm/mach-adm5120/war.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file "COPYING" in the main directory of this archive - * for more details. - * - * Copyright (C) 2002, 2004, 2007 by Ralf Baechle - */ -#ifndef __ASM_MIPS_MACH_ADM5120_WAR_H -#define __ASM_MIPS_MACH_ADM5120_WAR_H - -#define R4600_V1_INDEX_ICACHEOP_WAR 0 -#define R4600_V1_HIT_CACHEOP_WAR 0 -#define R4600_V2_HIT_CACHEOP_WAR 0 -#define R5432_CP0_INTERRUPT_WAR 0 -#define BCM1250_M3_WAR 0 -#define SIBYTE_1956_WAR 0 -#define MIPS4K_ICACHE_REFILL_WAR 0 -#define MIPS_CACHE_SYNC_WAR 0 -#define TX49XX_ICACHE_INDEX_INV_WAR 0 -#define RM9000_CDEX_SMP_WAR 0 -#define ICACHE_REFILLS_WORKAROUND_WAR 0 -#define R10000_LLSC_WAR 0 -#define MIPS34K_MISSED_ITLB_WAR 0 - -#endif /* __ASM_MIPS_MACH_ADM5120_WAR_H */ diff --git a/target/linux/adm5120/files/arch/mips/pci/pci-adm5120.c b/target/linux/adm5120/files/arch/mips/pci/pci-adm5120.c deleted file mode 100644 index f8d359806a..0000000000 --- a/target/linux/adm5120/files/arch/mips/pci/pci-adm5120.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * ADM5120 PCI Host Controller driver - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This code was based on the ADM5120 specific port of the Linux 2.6.10 kernel - * done by Jeroen Vreeken - * Copyright (C) 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * Jeroen's code was based on the Linux 2.4.xx source codes found in various - * tarballs released by Edimax for it's ADM5120 based devices - * Copyright (C) ADMtek Incorporated - * - * 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 - -#include -#include -#include -#include - -#undef DEBUG - -#ifdef DEBUG -#define DBG(f, a...) printk(KERN_DEBUG f, ## a) -#else -#define DBG(f, a...) do {} while (0) -#endif - -#define PCI_ENABLE 0x80000000 - -/* -------------------------------------------------------------------------*/ - -static unsigned int adm5120_pci_nr_irqs __initdata; -static struct adm5120_pci_irq *adm5120_pci_irq_map __initdata; - -static DEFINE_SPINLOCK(pci_lock); - -/* -------------------------------------------------------------------------*/ - -static inline void write_cfgaddr(u32 addr) -{ - __raw_writel((addr | PCI_ENABLE), - (void __iomem *)(KSEG1ADDR(ADM5120_PCICFG_ADDR))); -} - -static inline void write_cfgdata(u32 data) -{ - __raw_writel(data, (void __iomem *)KSEG1ADDR(ADM5120_PCICFG_DATA)); -} - -static inline u32 read_cfgdata(void) -{ - return __raw_readl((void __iomem *)KSEG1ADDR(ADM5120_PCICFG_DATA)); -} - -static inline u32 mkaddr(struct pci_bus *bus, unsigned int devfn, int where) -{ - return ((bus->number & 0xFF) << 16) | ((devfn & 0xFF) << 8) | \ - (where & 0xFC); -} - -/* -------------------------------------------------------------------------*/ - -static int pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 *val) -{ - unsigned long flags; - u32 data; - - spin_lock_irqsave(&pci_lock, flags); - - write_cfgaddr(mkaddr(bus, devfn, where)); - data = read_cfgdata(); - - DBG("PCI: cfg_read %02u.%02u.%01u/%02X:%01d, cfg:0x%08X", - bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), - where, size, data); - - switch (size) { - case 1: - if (where & 1) - data >>= 8; - if (where & 2) - data >>= 16; - data &= 0xFF; - break; - case 2: - if (where & 2) - data >>= 16; - data &= 0xFFFF; - break; - } - - *val = data; - DBG(", 0x%08X returned\n", data); - - spin_unlock_irqrestore(&pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -static int pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, - int size, u32 val) -{ - unsigned long flags; - u32 data; - int s; - - spin_lock_irqsave(&pci_lock, flags); - - write_cfgaddr(mkaddr(bus, devfn, where)); - data = read_cfgdata(); - - DBG("PCI: cfg_write %02u.%02u.%01u/%02X:%01d, cfg:0x%08X", - bus->number, PCI_SLOT(devfn), PCI_FUNC(devfn), - where, size, data); - - switch (size) { - case 1: - s = ((where & 3) << 3); - data &= ~(0xFF << s); - data |= ((val & 0xFF) << s); - break; - case 2: - s = ((where & 2) << 4); - data &= ~(0xFFFF << s); - data |= ((val & 0xFFFF) << s); - break; - case 4: - data = val; - break; - } - - write_cfgdata(data); - DBG(", 0x%08X written\n", data); - - spin_unlock_irqrestore(&pci_lock, flags); - - return PCIBIOS_SUCCESSFUL; -} - -struct pci_ops adm5120_pci_ops = { - .read = pci_config_read, - .write = pci_config_write, -}; - -/* -------------------------------------------------------------------------*/ - -static void adm5120_pci_fixup(struct pci_dev *dev) -{ - if (dev->devfn != 0) - return; - - /* setup COMMAND register */ - pci_write_config_word(dev, PCI_COMMAND, - (PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER)); - - /* setup CACHE_LINE_SIZE register */ - pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 4); - - /* setup BARS */ - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, 0); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0); -} - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ADMTEK, PCI_DEVICE_ID_ADMTEK_ADM5120, - adm5120_pci_fixup); - -/* -------------------------------------------------------------------------*/ - -void __init adm5120_pci_set_irq_map(unsigned int nr_irqs, - struct adm5120_pci_irq *map) -{ - adm5120_pci_nr_irqs = nr_irqs; - adm5120_pci_irq_map = map; -} - -int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) -{ - int irq = -1; - int i; - - if ((!adm5120_pci_nr_irqs) || (!adm5120_pci_irq_map)) { - printk(KERN_ALERT "PCI: pci_irq_map is not initialized\n"); - goto out; - } - - if (slot < 1 || slot > 4) { - printk(KERN_ALERT "PCI: slot number %u is not supported\n", - slot); - goto out; - } - - for (i = 0; i < adm5120_pci_nr_irqs; i++) { - if ((adm5120_pci_irq_map[i].slot == slot) - && (adm5120_pci_irq_map[i].func == PCI_FUNC(dev->devfn)) - && (adm5120_pci_irq_map[i].pin == pin)) { - irq = adm5120_pci_irq_map[i].irq; - break; - } - } - - if (irq < 0) { - printk(KERN_ALERT "PCI: no irq found for %s pin:%u\n", - pci_name((struct pci_dev *)dev), pin); - } else { - printk(KERN_INFO "PCI: mapping irq for %s pin:%u, irq:%d\n", - pci_name((struct pci_dev *)dev), pin, irq); - } - -out: - return irq; -} - -int pcibios_plat_dev_init(struct pci_dev *dev) -{ - return 0; -} - -/* -------------------------------------------------------------------------*/ - -static struct resource pci_io_resource = { - .name = "ADM5120 PCI I/O", - .start = ADM5120_PCIIO_BASE, - .end = ADM5120_PCICFG_ADDR-1, - .flags = IORESOURCE_IO -}; - -static struct resource pci_mem_resource = { - .name = "ADM5120 PCI MEM", - .start = ADM5120_PCIMEM_BASE, - .end = ADM5120_PCIIO_BASE-1, - .flags = IORESOURCE_MEM -}; - -static struct pci_controller adm5120_controller = { - .pci_ops = &adm5120_pci_ops, - .io_resource = &pci_io_resource, - .mem_resource = &pci_mem_resource, -}; - -static int __init adm5120_pci_setup(void) -{ - if (adm5120_package_pqfp()) { - printk(KERN_INFO "PCI: not available on ADM5120P\n"); - return -1; - } - - /* Avoid ISA compat ranges. */ - PCIBIOS_MIN_IO = 0x00000000; - PCIBIOS_MIN_MEM = 0x00000000; - - /* Set I/O resource limits. */ - ioport_resource.end = 0x1fffffff; - iomem_resource.end = 0xffffffff; - - register_pci_controller(&adm5120_controller); - return 0; -} - -arch_initcall(adm5120_pci_setup); diff --git a/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c b/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c deleted file mode 100644 index 92a4d1390d..0000000000 --- a/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * A low-level PATA driver to handle a Compact Flash connected on the - * Mikrotik's RouterBoard 153 board. - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was based on: drivers/ata/pata_ixp4xx_cf.c - * Copyright (C) 2006-07 Tower Technologies - * Author: Alessandro Zummo - * - * Also was based on the driver for Linux 2.4.xx published by Mikrotik for - * their RouterBoard 1xx and 5xx series devices. The original Mikrotik code - * seems not to have a license. - * - * 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 - -#define DRV_NAME "pata-rb153-cf" -#define DRV_VERSION "0.5.0" -#define DRV_DESC "PATA driver for RouterBOARD 153 Compact Flash" - -#define RB153_CF_MAXPORTS 1 -#define RB153_CF_IO_DELAY 100 - -#define RB153_CF_REG_CMD 0x0800 -#define RB153_CF_REG_CTRL 0x080E -#define RB153_CF_REG_DATA 0x0C00 - -struct rb153_cf_info { - void __iomem *iobase; - unsigned int gpio_line; - int frozen; - unsigned int irq; -}; - -static inline void rb153_pata_finish_io(struct ata_port *ap) -{ - struct rb153_cf_info *info = ap->host->private_data; - - /* FIXME: Keep previous delay. If this is merely a fence then - * ata_sff_sync might be sufficient. */ - ata_sff_dma_pause(ap); - ndelay(RB153_CF_IO_DELAY); - - irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); -} - -static void rb153_pata_exec_command(struct ata_port *ap, - const struct ata_taskfile *tf) -{ - writeb(tf->command, ap->ioaddr.command_addr); - rb153_pata_finish_io(ap); -} - -static unsigned int rb153_pata_data_xfer(struct ata_device *adev, - unsigned char *buf, - unsigned int buflen, - int write_data) -{ - void __iomem *ioaddr = adev->link->ap->ioaddr.data_addr; - unsigned int t; - - t = buflen; - if (write_data) { - for (; t > 0; t--, buf++) - writeb(*buf, ioaddr); - } else { - for (; t > 0; t--, buf++) - *buf = readb(ioaddr); - } - - rb153_pata_finish_io(adev->link->ap); - return buflen; -} - -static void rb153_pata_freeze(struct ata_port *ap) -{ - struct rb153_cf_info *info = ap->host->private_data; - - info->frozen = 1; -} - -static void rb153_pata_thaw(struct ata_port *ap) -{ - struct rb153_cf_info *info = ap->host->private_data; - - info->frozen = 0; -} - -static irqreturn_t rb153_pata_irq_handler(int irq, void *dev_instance) -{ - struct ata_host *ah = dev_instance; - struct rb153_cf_info *info = ah->private_data; - - if (gpio_get_value(info->gpio_line)) { - irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); - if (!info->frozen) - ata_sff_interrupt(irq, dev_instance); - } else { - irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); - } - - return IRQ_HANDLED; -} - -static struct ata_port_operations rb153_pata_port_ops = { - .inherits = &ata_sff_port_ops, - .sff_exec_command = rb153_pata_exec_command, - .sff_data_xfer = rb153_pata_data_xfer, - .freeze = rb153_pata_freeze, - .thaw = rb153_pata_thaw, -}; - -static struct scsi_host_template rb153_pata_sht = { - ATA_PIO_SHT(DRV_NAME), -}; - -static void rb153_pata_setup_port(struct ata_host *ah) -{ - struct rb153_cf_info *info = ah->private_data; - struct ata_port *ap; - - ap = ah->ports[0]; - - ap->ops = &rb153_pata_port_ops; - ap->pio_mask = 0x1f; /* PIO4 */ - - ap->ioaddr.cmd_addr = info->iobase + RB153_CF_REG_CMD; - ap->ioaddr.ctl_addr = info->iobase + RB153_CF_REG_CTRL; - ap->ioaddr.altstatus_addr = info->iobase + RB153_CF_REG_CTRL; - - ata_sff_std_ports(&ap->ioaddr); - - ap->ioaddr.data_addr = info->iobase + RB153_CF_REG_DATA; -} - -static int rb153_pata_driver_probe(struct platform_device *pdev) -{ - unsigned int irq; - int gpio; - struct resource *res; - struct ata_host *ah; - struct rb153_cf_info *info; - int ret; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "no IOMEM resource found\n"); - return -EINVAL; - } - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, "no IRQ resource found\n"); - return -ENOENT; - } - - gpio = irq_to_gpio(irq); - if (gpio < 0) { - dev_err(&pdev->dev, "no GPIO found for irq%d\n", irq); - return -ENOENT; - } - - ret = gpio_request(gpio, DRV_NAME); - if (ret) { - dev_err(&pdev->dev, "GPIO request failed\n"); - return ret; - } - - ah = ata_host_alloc(&pdev->dev, RB153_CF_MAXPORTS); - if (!ah) - return -ENOMEM; - - platform_set_drvdata(pdev, ah); - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - ah->private_data = info; - info->gpio_line = gpio; - info->irq = irq; - - info->iobase = devm_ioremap_nocache(&pdev->dev, res->start, - res->end - res->start + 1); - if (!info->iobase) - return -ENOMEM; - - ret = gpio_direction_input(gpio); - if (ret) { - dev_err(&pdev->dev, "unable to set GPIO direction, err=%d\n", - ret); - goto err_free_gpio; - } - - rb153_pata_setup_port(ah); - - ret = ata_host_activate(ah, irq, rb153_pata_irq_handler, - IRQF_TRIGGER_LOW, &rb153_pata_sht); - if (ret) - goto err_free_gpio; - - return 0; - -err_free_gpio: - gpio_free(gpio); - - return ret; -} - -static int rb153_pata_driver_remove(struct platform_device *pdev) -{ - struct ata_host *ah = platform_get_drvdata(pdev); - struct rb153_cf_info *info = ah->private_data; - - ata_host_detach(ah); - gpio_free(info->gpio_line); - - return 0; -} - -static struct platform_driver rb153_pata_platform_driver = { - .probe = rb153_pata_driver_probe, - .remove = rb153_pata_driver_remove, - .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, - }, -}; - -/* ------------------------------------------------------------------------ */ - -#define DRV_INFO DRV_DESC " version " DRV_VERSION - -static int __init rb153_pata_module_init(void) -{ - printk(KERN_INFO DRV_INFO "\n"); - - return platform_driver_register(&rb153_pata_platform_driver); -} - -static void __exit rb153_pata_module_exit(void) -{ - platform_driver_unregister(&rb153_pata_platform_driver); -} - -MODULE_AUTHOR("Gabor Juhos "); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_VERSION(DRV_VERSION); -MODULE_LICENSE("GPL v2"); - -module_init(rb153_pata_module_init); -module_exit(rb153_pata_module_exit); diff --git a/target/linux/adm5120/files/drivers/leds/ledtrig-adm5120-switch.c b/target/linux/adm5120/files/drivers/leds/ledtrig-adm5120-switch.c deleted file mode 100644 index 23a54a0b9a..0000000000 --- a/target/linux/adm5120/files/drivers/leds/ledtrig-adm5120-switch.c +++ /dev/null @@ -1,149 +0,0 @@ -/* - * LED ADM5120 Switch Port State Trigger - * - * Copyright (C) 2007 Bernhard Held - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was based on: drivers/leds/ledtrig-timer.c - * Copyright 2005-2006 Openedhand Ltd. - * Author: Richard Purdie - * - * 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 "leds.h" - -#define DRV_NAME "port_state" -#define DRV_DESC "LED ADM5120 Switch Port State Trigger" - -struct port_state { - char *name; - unsigned int value; -}; - -#define PORT_STATE(n, v) {.name = (n), .value = (v)} - -static struct port_state port_states[] = { - PORT_STATE("off", LED_OFF), - PORT_STATE("on", LED_FULL), - PORT_STATE("flash", ADM5120_GPIO_FLASH), - PORT_STATE("link", ADM5120_GPIO_LINK), - PORT_STATE("speed", ADM5120_GPIO_SPEED), - PORT_STATE("duplex", ADM5120_GPIO_DUPLEX), - PORT_STATE("act", ADM5120_GPIO_ACT), - PORT_STATE("coll", ADM5120_GPIO_COLL), - PORT_STATE("link_act", ADM5120_GPIO_LINK_ACT), - PORT_STATE("duplex_coll", ADM5120_GPIO_DUPLEX_COLL), - PORT_STATE("10M_act", ADM5120_GPIO_10M_ACT), - PORT_STATE("100M_act", ADM5120_GPIO_100M_ACT), -}; - -static ssize_t led_port_state_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - struct port_state *state = led_cdev->trigger_data; - int len = 0; - int i; - - *buf = '\0'; - for (i = 0; i < ARRAY_SIZE(port_states); i++) { - if (&port_states[i] == state) - len += sprintf(buf+len, "[%s] ", port_states[i].name); - else - len += sprintf(buf+len, "%s ", port_states[i].name); - } - len += sprintf(buf+len, "\n"); - - return len; -} - -static ssize_t led_port_state_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct led_classdev *led_cdev = dev_get_drvdata(dev); - size_t len; - int i; - - for (i = 0; i < ARRAY_SIZE(port_states); i++) { - len = strlen(port_states[i].name); - if (strncmp(port_states[i].name, buf, len) != 0) - continue; - - if (buf[len] != '\0' && buf[len] != '\n') - continue; - - led_cdev->trigger_data = &port_states[i]; - led_set_brightness(led_cdev, port_states[i].value); - return size; - } - - return -EINVAL; -} - -static DEVICE_ATTR(port_state, 0644, led_port_state_show, - led_port_state_store); - -static void adm5120_switch_trig_activate(struct led_classdev *led_cdev) -{ - struct port_state *state = port_states; - int rc; - - led_cdev->trigger_data = state; - - rc = device_create_file(led_cdev->dev, &dev_attr_port_state); - if (rc) - goto err; - - led_set_brightness(led_cdev, state->value); - - return; -err: - led_cdev->trigger_data = NULL; -} - -static void adm5120_switch_trig_deactivate(struct led_classdev *led_cdev) -{ - struct port_state *state = led_cdev->trigger_data; - - if (!state) - return; - - device_remove_file(led_cdev->dev, &dev_attr_port_state); - -} - -static struct led_trigger adm5120_switch_led_trigger = { - .name = DRV_NAME, - .activate = adm5120_switch_trig_activate, - .deactivate = adm5120_switch_trig_deactivate, -}; - -static int __init adm5120_switch_trig_init(void) -{ - led_trigger_register(&adm5120_switch_led_trigger); - return 0; -} - -static void __exit adm5120_switch_trig_exit(void) -{ - led_trigger_unregister(&adm5120_switch_led_trigger); -} - -module_init(adm5120_switch_trig_init); -module_exit(adm5120_switch_trig_exit); - -MODULE_AUTHOR("Bernhard Held , " - "Gabor Juhos "); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c b/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c deleted file mode 100644 index f6a86f4897..0000000000 --- a/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Platform driver for NOR flash devices on ADM5120 based boards - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/mtd/map/physmap.c - * Copyright (C) 2003 MontaVista Software Inc. - * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net - * - * 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 -#include - -#include -#include -#include -#include - -#define DRV_NAME "adm5120-flash" -#define DRV_DESC "ADM5120 flash MAP driver" -#define MAX_PARSED_PARTS 8 - -#ifdef ADM5120_FLASH_DEBUG -#define MAP_DBG(m, f, a...) printk(KERN_INFO "%s: " f, (m->name) , ## a) -#else -#define MAP_DBG(m, f, a...) do {} while (0) -#endif -#define MAP_ERR(m, f, a...) printk(KERN_ERR "%s: " f, (m->name) , ## a) -#define MAP_INFO(m, f, a...) printk(KERN_INFO "%s: " f, (m->name) , ## a) - -struct adm5120_map_info { - struct map_info map; - void (*switch_bank)(unsigned); - unsigned long window_size; -}; - -struct adm5120_flash_info { - struct mtd_info *mtd; - struct resource *res; - struct platform_device *dev; - struct adm5120_map_info amap; -}; - -struct flash_desc { - u32 phys; - u32 srs_shift; -}; - -/* - * Globals - */ -static DEFINE_SPINLOCK(adm5120_flash_spin); -#define FLASH_LOCK() spin_lock(&adm5120_flash_spin) -#define FLASH_UNLOCK() spin_unlock(&adm5120_flash_spin) - -static u32 flash_bankwidths[4] = { 1, 2, 4, 0 }; - -static u32 flash_sizes[8] = { - 0, 512*1024, 1024*1024, 2*1024*1024, - 4*1024*1024, 0, 0, 0 -}; - -static struct flash_desc flash_descs[2] = { - { - .phys = ADM5120_SRAM0_BASE, - .srs_shift = MEMCTRL_SRS0_SHIFT, - }, { - .phys = ADM5120_SRAM1_BASE, - .srs_shift = MEMCTRL_SRS1_SHIFT, - } -}; - -static const char const *probe_types[] = { - "cfi_probe", - "jedec_probe", - "map_rom", - NULL -}; - -static const char const *parse_types[] = { - "cmdlinepart", -#ifdef CONFIG_MTD_REDBOOT_PARTS - "RedBoot", -#endif -#ifdef CONFIG_MTD_MYLOADER_PARTS - "MyLoader", -#endif - NULL, -}; - -#define BANK_SIZE (2<<20) -#define BANK_SIZE_MAX (4<<20) -#define BANK_OFFS_MASK (BANK_SIZE-1) -#define BANK_START_MASK (~BANK_OFFS_MASK) - -static inline struct adm5120_map_info *map_to_amap(struct map_info *map) -{ - return (struct adm5120_map_info *)map; -} - -static void adm5120_flash_switchbank(struct map_info *map, - unsigned long ofs) -{ - struct adm5120_map_info *amap = map_to_amap(map); - unsigned bank; - - if (amap->switch_bank == NULL) - return; - - bank = (ofs & BANK_START_MASK) >> 21; - if (bank > 1) - BUG(); - - MAP_DBG(map, "switching to bank %u, ofs=%lX\n", bank, ofs); - amap->switch_bank(bank); -} - -static map_word adm5120_flash_read(struct map_info *map, unsigned long ofs) -{ - struct adm5120_map_info *amap = map_to_amap(map); - map_word ret; - - MAP_DBG(map, "reading from ofs %lX\n", ofs); - - if (ofs >= amap->window_size) - return map_word_ff(map); - - FLASH_LOCK(); - adm5120_flash_switchbank(map, ofs); - ret = inline_map_read(map, (ofs & (amap->window_size-1))); - FLASH_UNLOCK(); - - return ret; -} - -static void adm5120_flash_write(struct map_info *map, const map_word datum, - unsigned long ofs) -{ - struct adm5120_map_info *amap = map_to_amap(map); - - MAP_DBG(map, "writing to ofs %lX\n", ofs); - - if (ofs > amap->window_size) - return; - - FLASH_LOCK(); - adm5120_flash_switchbank(map, ofs); - inline_map_write(map, datum, (ofs & (amap->window_size-1))); - FLASH_UNLOCK(); -} - -static void adm5120_flash_copy_from(struct map_info *map, void *to, - unsigned long from, ssize_t len) -{ - struct adm5120_map_info *amap = map_to_amap(map); - char *p; - ssize_t t; - - MAP_DBG(map, "copy_from, to=%lX, from=%lX, len=%lX\n", - (unsigned long)to, from, (unsigned long)len); - - if (from > amap->window_size) - return; - - p = (char *)to; - while (len > 0) { - t = len; - if ((from < BANK_SIZE) && ((from+len) > BANK_SIZE)) - t = BANK_SIZE-from; - - FLASH_LOCK(); - MAP_DBG(map, "copying %lu byte(s) from %lX to %lX\n", - (unsigned long)t, (from & (amap->window_size-1)), - (unsigned long)p); - adm5120_flash_switchbank(map, from); - inline_map_copy_from(map, p, (from & (amap->window_size-1)), t); - FLASH_UNLOCK(); - p += t; - from += t; - len -= t; - } -} - -static int adm5120_flash_initres(struct adm5120_flash_info *info) -{ - struct map_info *map = &info->amap.map; - int err = 0; - - info->res = request_mem_region(map->phys, info->amap.window_size, - map->name); - if (info->res == NULL) { - MAP_ERR(map, "could not reserve memory region\n"); - err = -ENOMEM; - goto out; - } - - map->virt = ioremap_nocache(map->phys, info->amap.window_size); - if (map->virt == NULL) { - MAP_ERR(map, "failed to ioremap flash region\n"); - err = -ENOMEM; - goto out; - } - -out: - return err; -} - -static int adm5120_flash_initinfo(struct adm5120_flash_info *info, - struct platform_device *dev) -{ - struct map_info *map = &info->amap.map; - struct adm5120_flash_platform_data *pdata = dev->dev.platform_data; - struct flash_desc *fdesc; - u32 t = 0; - - map->name = dev_name(&dev->dev); - - if (dev->id > 1) { - MAP_ERR(map, "invalid flash id\n"); - goto err_out; - } - - fdesc = &flash_descs[dev->id]; - - if (pdata) - info->amap.window_size = pdata->window_size; - - if (info->amap.window_size == 0) { - /* get memory window size */ - t = SW_READ_REG(SWITCH_REG_MEMCTRL) >> fdesc->srs_shift; - t &= MEMCTRL_SRS_MASK; - info->amap.window_size = flash_sizes[t]; - } - - if (info->amap.window_size == 0) { - MAP_ERR(map, "unable to determine window size\n"); - goto err_out; - } - - /* get flash bus width */ - switch (dev->id) { - case 0: - t = MPMC_READ_REG(SC1) & SC_MW_MASK; - break; - case 1: - t = MPMC_READ_REG(SC0) & SC_MW_MASK; - break; - } - map->bankwidth = flash_bankwidths[t]; - if (map->bankwidth == 0) { - MAP_ERR(map, "invalid bus width detected\n"); - goto err_out; - } - - map->phys = fdesc->phys; - map->size = BANK_SIZE_MAX; - - simple_map_init(map); - map->read = adm5120_flash_read; - map->write = adm5120_flash_write; - map->copy_from = adm5120_flash_copy_from; - - if (pdata) { - map->set_vpp = pdata->set_vpp; - info->amap.switch_bank = pdata->switch_bank; - } - - info->dev = dev; - - MAP_INFO(map, "probing at 0x%lX, size:%ldKiB, width:%d bits\n", - (unsigned long)map->phys, - (unsigned long)info->amap.window_size >> 10, - map->bankwidth*8); - - return 0; - -err_out: - return -ENODEV; -} - -static void adm5120_flash_initbanks(struct adm5120_flash_info *info) -{ - struct map_info *map = &info->amap.map; - - if (info->mtd->size <= BANK_SIZE) - /* no bank switching needed */ - return; - - if (info->amap.switch_bank) { - info->amap.window_size = info->mtd->size; - return; - } - - MAP_ERR(map, "reduce visibility from %ldKiB to %ldKiB\n", - (unsigned long)map->size >> 10, - (unsigned long)info->mtd->size >> 10); - - info->mtd->size = info->amap.window_size; -} - -static int adm5120_flash_remove(struct platform_device *dev) -{ - struct adm5120_flash_info *info; - - info = platform_get_drvdata(dev); - if (info == NULL) - return 0; - - platform_set_drvdata(dev, NULL); - - if (info->mtd != NULL) { - mtd_device_unregister(info->mtd); - map_destroy(info->mtd); - } - - if (info->amap.map.virt != NULL) - iounmap(info->amap.map.virt); - - if (info->res != NULL) { - release_resource(info->res); - kfree(info->res); - } - - return 0; -} - -static int adm5120_flash_probe(struct platform_device *dev) -{ - struct adm5120_flash_platform_data *pdata; - struct adm5120_flash_info *info; - struct map_info *map; - const char **probe_type; - int err; - - pdata = dev->dev.platform_data; - if (!pdata) { - dev_err(&dev->dev, "no platform data\n"); - return -EINVAL; - } - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (info == NULL) { - err = -ENOMEM; - goto err_out; - } - - platform_set_drvdata(dev, info); - - err = adm5120_flash_initinfo(info, dev); - if (err) - goto err_out; - - err = adm5120_flash_initres(info); - if (err) - goto err_out; - - map = &info->amap.map; - for (probe_type = probe_types; info->mtd == NULL && *probe_type != NULL; - probe_type++) - info->mtd = do_map_probe(*probe_type, map); - - if (info->mtd == NULL) { - MAP_ERR(map, "map_probe failed\n"); - err = -ENXIO; - goto err_out; - } - - adm5120_flash_initbanks(info); - - if (info->mtd->size < info->amap.window_size) { - /* readjust resources */ - iounmap(map->virt); - release_resource(info->res); - kfree(info->res); - - info->amap.window_size = info->mtd->size; - map->size = info->mtd->size; - MAP_INFO(map, "reducing map size to %ldKiB\n", - (unsigned long)map->size >> 10); - err = adm5120_flash_initres(info); - if (err) - goto err_out; - } - - MAP_INFO(map, "found at 0x%lX, size:%ldKiB, width:%d bits\n", - (unsigned long)map->phys, (unsigned long)info->mtd->size >> 10, - map->bankwidth*8); - - info->mtd->owner = THIS_MODULE; - - err = mtd_device_parse_register(info->mtd, parse_types, 0, - pdata->parts, pdata->nr_parts); - if (err) - goto err_out; - - return 0; - -err_out: - adm5120_flash_remove(dev); - return err; -} - -#ifdef CONFIG_PM -static int adm5120_flash_suspend(struct platform_device *dev, - pm_message_t state) -{ - struct adm5120_flash_info *info = platform_get_drvdata(dev); - int ret = 0; - - if (info) - ret = info->mtd->suspend(info->mtd); - - return ret; -} - -static int adm5120_flash_resume(struct platform_device *dev) -{ - struct adm5120_flash_info *info = platform_get_drvdata(dev); - - if (info) - info->mtd->resume(info->mtd); - - return 0; -} - -static void adm5120_flash_shutdown(struct platform_device *dev) -{ - struct adm5120_flash_info *info = platform_get_drvdata(dev); - - if (info && info->mtd->suspend(info->mtd) == 0) - info->mtd->resume(info->mtd); -} -#endif - -static struct platform_driver adm5120_flash_driver = { - .probe = adm5120_flash_probe, - .remove = adm5120_flash_remove, -#ifdef CONFIG_PM - .suspend = adm5120_flash_suspend, - .resume = adm5120_flash_resume, - .shutdown = adm5120_flash_shutdown, -#endif - .driver = { - .name = DRV_NAME, - }, -}; - -static int __init adm5120_flash_init(void) -{ - int err; - - err = platform_driver_register(&adm5120_flash_driver); - - return err; -} - -static void __exit adm5120_flash_exit(void) -{ - platform_driver_unregister(&adm5120_flash_driver); -} - -module_init(adm5120_flash_init); -module_exit(adm5120_flash_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_DESCRIPTION(DRV_DESC); diff --git a/target/linux/adm5120/files/drivers/mtd/trxsplit.c b/target/linux/adm5120/files/drivers/mtd/trxsplit.c deleted file mode 100644 index 76cbdc7494..0000000000 --- a/target/linux/adm5120/files/drivers/mtd/trxsplit.c +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 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 - * by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define PFX "trxsplit: " - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 -#define TRX_MAX_LEN 0x3A0000 -#define TRX_NO_HEADER 0x1 /* do not write TRX header */ -#define TRX_GZ_FILES 0x2 /* contains individual gzip files */ -#define TRX_MAX_OFFSET 3 -#define TRX_MIN_KERNEL_SIZE (256 * 1024) - -struct trx_header { - u32 magic; /* "HDR0" */ - u32 len; /* Length of file including header */ - u32 crc32; /* 32-bit CRC from flag_version to end of file */ - u32 flag_version; /* 0:15 flags, 16:31 version */ - u32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions */ -}; - -#define TRX_ALIGN 0x1000 - -static int trx_nr_parts; -static unsigned long trx_offset; -static struct mtd_info *trx_mtd; -static struct mtd_partition trx_parts[TRX_MAX_OFFSET]; -static struct trx_header trx_hdr; - -static int trxsplit_refresh_partitions(struct mtd_info *mtd); - -static int trxsplit_checktrx(struct mtd_info *mtd, unsigned long offset) -{ - size_t retlen; - int err; - - err = mtd_read(mtd, offset, sizeof(trx_hdr), &retlen, (void *)&trx_hdr); - if (err) { - printk(KERN_ALERT PFX "unable to read from '%s'\n", mtd->name); - goto err_out; - } - - if (retlen != sizeof(trx_hdr)) { - printk(KERN_ALERT PFX "reading failed on '%s'\n", mtd->name); - goto err_out; - } - - trx_hdr.magic = le32_to_cpu(trx_hdr.magic); - trx_hdr.len = le32_to_cpu(trx_hdr.len); - trx_hdr.crc32 = le32_to_cpu(trx_hdr.crc32); - trx_hdr.flag_version = le32_to_cpu(trx_hdr.flag_version); - trx_hdr.offsets[0] = le32_to_cpu(trx_hdr.offsets[0]); - trx_hdr.offsets[1] = le32_to_cpu(trx_hdr.offsets[1]); - trx_hdr.offsets[2] = le32_to_cpu(trx_hdr.offsets[2]); - - /* sanity checks */ - if (trx_hdr.magic != TRX_MAGIC) - goto err_out; - - if (trx_hdr.len > mtd->size - offset) - goto err_out; - - /* TODO: add crc32 checking too? */ - - return 0; - -err_out: - return -1; -} - -static void trxsplit_findtrx(struct mtd_info *mtd) -{ - unsigned long offset; - int err; - - printk(KERN_INFO PFX "searching TRX header in '%s'\n", mtd->name); - - err = 0; - for (offset = 0; offset < mtd->size; offset += TRX_ALIGN) { - err = trxsplit_checktrx(mtd, offset); - if (err == 0) - break; - } - - if (err) - return; - - printk(KERN_INFO PFX "TRX header found at 0x%lX\n", offset); - - trx_mtd = mtd; - trx_offset = offset; -} - -static void trxsplit_create_partitions(struct mtd_info *mtd) -{ - struct mtd_partition *part = trx_parts; - int err; - int i; - - for (i = 0; i < TRX_MAX_OFFSET; i++) { - part = &trx_parts[i]; - if (trx_hdr.offsets[i] == 0) - continue; - part->offset = trx_offset + trx_hdr.offsets[i]; - trx_nr_parts++; - } - - for (i = 0; i < trx_nr_parts-1; i++) - trx_parts[i].size = trx_parts[i+1].offset - trx_parts[i].offset; - - trx_parts[i].size = mtd->size - trx_parts[i].offset; - - i = 0; - part = &trx_parts[i]; - if (part->size < TRX_MIN_KERNEL_SIZE) { - part->name = "loader"; - i++; - } - - part = &trx_parts[i]; - part->name = "kernel"; - i++; - - part = &trx_parts[i]; - part->name = "rootfs"; - - err = mtd_device_register(mtd, trx_parts, trx_nr_parts); - if (err) { - printk(KERN_ALERT PFX "adding TRX partitions failed\n"); - return; - } - - mtd->refresh_device = trxsplit_refresh_partitions; -} - -static int trxsplit_refresh_partitions(struct mtd_info *mtd) -{ - printk(KERN_INFO PFX "refreshing TRX partitions in '%s' (%d,%d)\n", - mtd->name, MTD_BLOCK_MAJOR, mtd->index); - - /* remove old partitions */ - mtd_device_unregister(mtd); - - trxsplit_findtrx(mtd); - if (!trx_mtd) - goto err; - - trxsplit_create_partitions(trx_mtd); - return 1; - -err: - return 0; -} - -static void __init trxsplit_add_mtd(struct mtd_info *mtd) -{ - if (mtd->type != MTD_NORFLASH) { - printk(KERN_INFO PFX "'%s' is not a NOR flash, skipped\n", - mtd->name); - return; - } - - if (!trx_mtd) - trxsplit_findtrx(mtd); -} - -static void __init trxsplit_remove_mtd(struct mtd_info *mtd) -{ - /* nothing to do */ -} - -static struct mtd_notifier trxsplit_notifier __initdata = { - .add = trxsplit_add_mtd, - .remove = trxsplit_remove_mtd, -}; - -static void __init trxsplit_scan(void) -{ - register_mtd_user(&trxsplit_notifier); - unregister_mtd_user(&trxsplit_notifier); -} - -static int __init trxsplit_init(void) -{ - trxsplit_scan(); - - if (trx_mtd) { - printk(KERN_INFO PFX "creating TRX partitions in '%s' " - "(%d,%d)\n", trx_mtd->name, MTD_BLOCK_MAJOR, - trx_mtd->index); - trxsplit_create_partitions(trx_mtd); - } - - return 0; -} - -late_initcall(trxsplit_init); diff --git a/target/linux/adm5120/files/drivers/net/adm5120sw.c b/target/linux/adm5120/files/drivers/net/adm5120sw.c deleted file mode 100644 index 7fbabb00e4..0000000000 --- a/target/linux/adm5120/files/drivers/net/adm5120sw.c +++ /dev/null @@ -1,1219 +0,0 @@ -/* - * ADM5120 built-in ethernet switch driver - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This code was based on a driver for Linux 2.6.xx by Jeroen Vreeken. - * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005 - * NAPI extension for the Jeroen's driver - * Copyright Thomas Langer (Thomas.Langer@infineon.com), 2007 - * Copyright Friedrich Beckmann (Friedrich.Beckmann@infineon.com), 2007 - * Inspiration for the Jeroen's driver came from the ADMtek 2.4 driver. - * Copyright ADMtek Inc. - * - * 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 -#include -#include - -#include - -#include -#include -#include - -#include "adm5120sw.h" -#include - -#define DRV_NAME "adm5120-switch" -#define DRV_DESC "ADM5120 built-in ethernet switch driver" -#define DRV_VERSION "0.1.1" - -#define CONFIG_ADM5120_SWITCH_NAPI 1 -#undef CONFIG_ADM5120_SWITCH_DEBUG - -/* ------------------------------------------------------------------------ */ - -#ifdef CONFIG_ADM5120_SWITCH_DEBUG -#define SW_DBG(f, a...) printk(KERN_DEBUG "%s: " f, DRV_NAME , ## a) -#else -#define SW_DBG(f, a...) do {} while (0) -#endif -#define SW_ERR(f, a...) printk(KERN_ERR "%s: " f, DRV_NAME , ## a) -#define SW_INFO(f, a...) printk(KERN_INFO "%s: " f, DRV_NAME , ## a) - -#define SWITCH_NUM_PORTS 6 -#define ETH_CSUM_LEN 4 - -#define RX_MAX_PKTLEN 1550 -#define RX_RING_SIZE 64 - -#define TX_RING_SIZE 32 -#define TX_QUEUE_LEN 28 /* Limit ring entries actually used. */ -#define TX_TIMEOUT (HZ * 400) - -#define RX_DESCS_SIZE (RX_RING_SIZE * sizeof(struct dma_desc *)) -#define RX_SKBS_SIZE (RX_RING_SIZE * sizeof(struct sk_buff *)) -#define TX_DESCS_SIZE (TX_RING_SIZE * sizeof(struct dma_desc *)) -#define TX_SKBS_SIZE (TX_RING_SIZE * sizeof(struct sk_buff *)) - -#define SKB_ALLOC_LEN (RX_MAX_PKTLEN + 32) -#define SKB_RESERVE_LEN (NET_IP_ALIGN + NET_SKB_PAD) - -#define SWITCH_INTS_HIGH (SWITCH_INT_SHD | SWITCH_INT_RHD | SWITCH_INT_HDF) -#define SWITCH_INTS_LOW (SWITCH_INT_SLD | SWITCH_INT_RLD | SWITCH_INT_LDF) -#define SWITCH_INTS_ERR (SWITCH_INT_RDE | SWITCH_INT_SDE | SWITCH_INT_CPUH) -#define SWITCH_INTS_Q (SWITCH_INT_P0QF | SWITCH_INT_P1QF | SWITCH_INT_P2QF | \ - SWITCH_INT_P3QF | SWITCH_INT_P4QF | SWITCH_INT_P5QF | \ - SWITCH_INT_CPQF | SWITCH_INT_GQF) - -#define SWITCH_INTS_ALL (SWITCH_INTS_HIGH | SWITCH_INTS_LOW | \ - SWITCH_INTS_ERR | SWITCH_INTS_Q | \ - SWITCH_INT_MD | SWITCH_INT_PSC) - -#define SWITCH_INTS_USED (SWITCH_INTS_LOW | SWITCH_INT_PSC) -#define SWITCH_INTS_POLL (SWITCH_INT_RLD | SWITCH_INT_LDF | SWITCH_INT_SLD) - -/* ------------------------------------------------------------------------ */ - -struct adm5120_if_priv { - struct net_device *dev; - - unsigned int vlan_no; - unsigned int port_mask; - -#ifdef CONFIG_ADM5120_SWITCH_NAPI - struct napi_struct napi; -#endif -}; - -struct dma_desc { - __u32 buf1; -#define DESC_OWN (1UL << 31) /* Owned by the switch */ -#define DESC_EOR (1UL << 28) /* End of Ring */ -#define DESC_ADDR_MASK 0x1FFFFFF -#define DESC_ADDR(x) ((__u32)(x) & DESC_ADDR_MASK) - __u32 buf2; -#define DESC_BUF2_EN (1UL << 31) /* Buffer 2 enable */ - __u32 buflen; - __u32 misc; -/* definitions for tx/rx descriptors */ -#define DESC_PKTLEN_SHIFT 16 -#define DESC_PKTLEN_MASK 0x7FF -/* tx descriptor specific part */ -#define DESC_CSUM (1UL << 31) /* Append checksum */ -#define DESC_DSTPORT_SHIFT 8 -#define DESC_DSTPORT_MASK 0x3F -#define DESC_VLAN_MASK 0x3F -/* rx descriptor specific part */ -#define DESC_SRCPORT_SHIFT 12 -#define DESC_SRCPORT_MASK 0x7 -#define DESC_DA_MASK 0x3 -#define DESC_DA_SHIFT 4 -#define DESC_IPCSUM_FAIL (1UL << 3) /* IP checksum fail */ -#define DESC_VLAN_TAG (1UL << 2) /* VLAN tag present */ -#define DESC_TYPE_MASK 0x3 /* mask for Packet type */ -#define DESC_TYPE_IP 0x0 /* IP packet */ -#define DESC_TYPE_PPPoE 0x1 /* PPPoE packet */ -} __attribute__ ((aligned(16))); - -/* ------------------------------------------------------------------------ */ - -static int adm5120_nrdevs; - -static struct net_device *adm5120_devs[SWITCH_NUM_PORTS]; -/* Lookup table port -> device */ -static struct net_device *adm5120_port[SWITCH_NUM_PORTS]; - -static struct dma_desc *txl_descs; -static struct dma_desc *rxl_descs; - -static dma_addr_t txl_descs_dma; -static dma_addr_t rxl_descs_dma; - -static struct sk_buff **txl_skbuff; -static struct sk_buff **rxl_skbuff; - -static unsigned int cur_rxl, dirty_rxl; /* producer/consumer ring indices */ -static unsigned int cur_txl, dirty_txl; - -static unsigned int sw_used; - -static DEFINE_SPINLOCK(tx_lock); - -/* ------------------------------------------------------------------------ */ - -static inline u32 sw_read_reg(u32 reg) -{ - return __raw_readl((void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); -} - -static inline void sw_write_reg(u32 reg, u32 val) -{ - __raw_writel(val, (void __iomem *)KSEG1ADDR(ADM5120_SWITCH_BASE)+reg); -} - -static inline void sw_int_mask(u32 mask) -{ - u32 t; - - t = sw_read_reg(SWITCH_REG_INT_MASK); - t |= mask; - sw_write_reg(SWITCH_REG_INT_MASK, t); -} - -static inline void sw_int_unmask(u32 mask) -{ - u32 t; - - t = sw_read_reg(SWITCH_REG_INT_MASK); - t &= ~mask; - sw_write_reg(SWITCH_REG_INT_MASK, t); -} - -static inline void sw_int_ack(u32 mask) -{ - sw_write_reg(SWITCH_REG_INT_STATUS, mask); -} - -static inline u32 sw_int_status(void) -{ - u32 t; - - t = sw_read_reg(SWITCH_REG_INT_STATUS); - t &= ~sw_read_reg(SWITCH_REG_INT_MASK); - return t; -} - -static inline u32 desc_get_srcport(struct dma_desc *desc) -{ - return (desc->misc >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK; -} - -static inline u32 desc_get_pktlen(struct dma_desc *desc) -{ - return (desc->misc >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK; -} - -static inline int desc_ipcsum_fail(struct dma_desc *desc) -{ - return ((desc->misc & DESC_IPCSUM_FAIL) != 0); -} - -/* ------------------------------------------------------------------------ */ - -#ifdef CONFIG_ADM5120_SWITCH_DEBUG -static void sw_dump_desc(char *label, struct dma_desc *desc, int tx) -{ - u32 t; - - SW_DBG("%s %s desc/%p\n", label, tx ? "tx" : "rx", desc); - - t = desc->buf1; - SW_DBG(" buf1 %08X addr=%08X; len=%08X %s%s\n", t, - t & DESC_ADDR_MASK, - desc->buflen, - (t & DESC_OWN) ? "SWITCH" : "CPU", - (t & DESC_EOR) ? " RE" : ""); - - t = desc->buf2; - SW_DBG(" buf2 %08X addr=%08X%s\n", desc->buf2, - t & DESC_ADDR_MASK, - (t & DESC_BUF2_EN) ? " EN" : ""); - - t = desc->misc; - if (tx) - SW_DBG(" misc %08X%s pktlen=%04X ports=%02X vlan=%02X\n", t, - (t & DESC_CSUM) ? " CSUM" : "", - (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, - (t >> DESC_DSTPORT_SHIFT) & DESC_DSTPORT_MASK, - t & DESC_VLAN_MASK); - else - SW_DBG(" misc %08X pktlen=%04X port=%d DA=%d%s%s type=%d\n", - t, - (t >> DESC_PKTLEN_SHIFT) & DESC_PKTLEN_MASK, - (t >> DESC_SRCPORT_SHIFT) & DESC_SRCPORT_MASK, - (t >> DESC_DA_SHIFT) & DESC_DA_MASK, - (t & DESC_IPCSUM_FAIL) ? " IPCF" : "", - (t & DESC_VLAN_TAG) ? " VLAN" : "", - (t & DESC_TYPE_MASK)); -} - -static void sw_dump_intr_mask(char *label, u32 mask) -{ - SW_DBG("%s %08X%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - label, mask, - (mask & SWITCH_INT_SHD) ? " SHD" : "", - (mask & SWITCH_INT_SLD) ? " SLD" : "", - (mask & SWITCH_INT_RHD) ? " RHD" : "", - (mask & SWITCH_INT_RLD) ? " RLD" : "", - (mask & SWITCH_INT_HDF) ? " HDF" : "", - (mask & SWITCH_INT_LDF) ? " LDF" : "", - (mask & SWITCH_INT_P0QF) ? " P0QF" : "", - (mask & SWITCH_INT_P1QF) ? " P1QF" : "", - (mask & SWITCH_INT_P2QF) ? " P2QF" : "", - (mask & SWITCH_INT_P3QF) ? " P3QF" : "", - (mask & SWITCH_INT_P4QF) ? " P4QF" : "", - (mask & SWITCH_INT_CPQF) ? " CPQF" : "", - (mask & SWITCH_INT_GQF) ? " GQF" : "", - (mask & SWITCH_INT_MD) ? " MD" : "", - (mask & SWITCH_INT_BCS) ? " BCS" : "", - (mask & SWITCH_INT_PSC) ? " PSC" : "", - (mask & SWITCH_INT_ID) ? " ID" : "", - (mask & SWITCH_INT_W0TE) ? " W0TE" : "", - (mask & SWITCH_INT_W1TE) ? " W1TE" : "", - (mask & SWITCH_INT_RDE) ? " RDE" : "", - (mask & SWITCH_INT_SDE) ? " SDE" : "", - (mask & SWITCH_INT_CPUH) ? " CPUH" : ""); -} - -static void sw_dump_regs(void) -{ - u32 t; - - t = sw_read_reg(SWITCH_REG_PHY_STATUS); - SW_DBG("phy_status: %08X\n", t); - - t = sw_read_reg(SWITCH_REG_CPUP_CONF); - SW_DBG("cpup_conf: %08X%s%s%s\n", t, - (t & CPUP_CONF_DCPUP) ? " DCPUP" : "", - (t & CPUP_CONF_CRCP) ? " CRCP" : "", - (t & CPUP_CONF_BTM) ? " BTM" : ""); - - t = sw_read_reg(SWITCH_REG_PORT_CONF0); - SW_DBG("port_conf0: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PORT_CONF1); - SW_DBG("port_conf1: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PORT_CONF2); - SW_DBG("port_conf2: %08X\n", t); - - t = sw_read_reg(SWITCH_REG_VLAN_G1); - SW_DBG("vlan g1: %08X\n", t); - t = sw_read_reg(SWITCH_REG_VLAN_G2); - SW_DBG("vlan g2: %08X\n", t); - - t = sw_read_reg(SWITCH_REG_BW_CNTL0); - SW_DBG("bw_cntl0: %08X\n", t); - t = sw_read_reg(SWITCH_REG_BW_CNTL1); - SW_DBG("bw_cntl1: %08X\n", t); - - t = sw_read_reg(SWITCH_REG_PHY_CNTL0); - SW_DBG("phy_cntl0: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PHY_CNTL1); - SW_DBG("phy_cntl1: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PHY_CNTL2); - SW_DBG("phy_cntl2: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PHY_CNTL3); - SW_DBG("phy_cntl3: %08X\n", t); - t = sw_read_reg(SWITCH_REG_PHY_CNTL4); - SW_DBG("phy_cntl4: %08X\n", t); - - t = sw_read_reg(SWITCH_REG_INT_STATUS); - sw_dump_intr_mask("int_status: ", t); - - t = sw_read_reg(SWITCH_REG_INT_MASK); - sw_dump_intr_mask("int_mask: ", t); - - t = sw_read_reg(SWITCH_REG_SHDA); - SW_DBG("shda: %08X\n", t); - t = sw_read_reg(SWITCH_REG_SLDA); - SW_DBG("slda: %08X\n", t); - t = sw_read_reg(SWITCH_REG_RHDA); - SW_DBG("rhda: %08X\n", t); - t = sw_read_reg(SWITCH_REG_RLDA); - SW_DBG("rlda: %08X\n", t); -} -#else -static inline void sw_dump_desc(char *label, struct dma_desc *desc, int tx) {} -static void sw_dump_intr_mask(char *label, u32 mask) {} -static inline void sw_dump_regs(void) {} -#endif /* CONFIG_ADM5120_SWITCH_DEBUG */ - -/* ------------------------------------------------------------------------ */ - -static inline void adm5120_rx_dma_update(struct dma_desc *desc, - struct sk_buff *skb, int end) -{ - desc->misc = 0; - desc->buf2 = 0; - desc->buflen = RX_MAX_PKTLEN; - desc->buf1 = DESC_ADDR(skb->data) | - DESC_OWN | (end ? DESC_EOR : 0); -} - -static void adm5120_switch_rx_refill(void) -{ - unsigned int entry; - - for (; cur_rxl - dirty_rxl > 0; dirty_rxl++) { - struct dma_desc *desc; - struct sk_buff *skb; - - entry = dirty_rxl % RX_RING_SIZE; - desc = &rxl_descs[entry]; - - skb = rxl_skbuff[entry]; - if (skb == NULL) { - skb = alloc_skb(SKB_ALLOC_LEN, GFP_ATOMIC); - if (skb) { - skb_reserve(skb, SKB_RESERVE_LEN); - rxl_skbuff[entry] = skb; - } else { - SW_ERR("no memory for skb\n"); - desc->buflen = 0; - desc->buf2 = 0; - desc->misc = 0; - desc->buf1 = (desc->buf1 & DESC_EOR) | DESC_OWN; - break; - } - } - - desc->buf2 = 0; - desc->buflen = RX_MAX_PKTLEN; - desc->misc = 0; - desc->buf1 = (desc->buf1 & DESC_EOR) | DESC_OWN | - DESC_ADDR(skb->data); - } -} - -static int adm5120_switch_rx(int limit) -{ - unsigned int done = 0; - - SW_DBG("rx start, limit=%d, cur_rxl=%u, dirty_rxl=%u\n", - limit, cur_rxl, dirty_rxl); - - while (done < limit) { - int entry = cur_rxl % RX_RING_SIZE; - struct dma_desc *desc = &rxl_descs[entry]; - struct net_device *rdev; - unsigned int port; - - if (desc->buf1 & DESC_OWN) - break; - - if (dirty_rxl + RX_RING_SIZE == cur_rxl) - break; - - port = desc_get_srcport(desc); - rdev = adm5120_port[port]; - - SW_DBG("rx descriptor %u, desc=%p, skb=%p\n", entry, desc, - rxl_skbuff[entry]); - - if ((rdev) && netif_running(rdev)) { - struct sk_buff *skb = rxl_skbuff[entry]; - int pktlen; - - pktlen = desc_get_pktlen(desc); - pktlen -= ETH_CSUM_LEN; - - if ((pktlen == 0) || desc_ipcsum_fail(desc)) { - rdev->stats.rx_errors++; - if (pktlen == 0) - rdev->stats.rx_length_errors++; - if (desc_ipcsum_fail(desc)) - rdev->stats.rx_crc_errors++; - SW_DBG("rx error, recycling skb %u\n", entry); - } else { - skb_put(skb, pktlen); - - skb->dev = rdev; - skb->protocol = eth_type_trans(skb, rdev); - skb->ip_summed = CHECKSUM_UNNECESSARY; - - dma_cache_wback_inv((unsigned long)skb->data, - skb->len); - -#ifdef CONFIG_ADM5120_SWITCH_NAPI - netif_receive_skb(skb); -#else - netif_rx(skb); -#endif - - rdev->last_rx = jiffies; - rdev->stats.rx_packets++; - rdev->stats.rx_bytes += pktlen; - - rxl_skbuff[entry] = NULL; - done++; - } - } else { - SW_DBG("no rx device, recycling skb %u\n", entry); - } - - cur_rxl++; - if (cur_rxl - dirty_rxl > RX_RING_SIZE / 4) - adm5120_switch_rx_refill(); - } - - adm5120_switch_rx_refill(); - - SW_DBG("rx finished, cur_rxl=%u, dirty_rxl=%u, processed %d\n", - cur_rxl, dirty_rxl, done); - - return done; -} - -static void adm5120_switch_tx(void) -{ - unsigned int entry; - - spin_lock(&tx_lock); - entry = dirty_txl % TX_RING_SIZE; - while (dirty_txl != cur_txl) { - struct dma_desc *desc = &txl_descs[entry]; - struct sk_buff *skb = txl_skbuff[entry]; - - if (desc->buf1 & DESC_OWN) - break; - - if (netif_running(skb->dev)) { - skb->dev->stats.tx_bytes += skb->len; - skb->dev->stats.tx_packets++; - } - - dev_kfree_skb_irq(skb); - txl_skbuff[entry] = NULL; - entry = (++dirty_txl) % TX_RING_SIZE; - } - - if ((cur_txl - dirty_txl) < TX_QUEUE_LEN - 4) { - int i; - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - if (!adm5120_devs[i]) - continue; - netif_wake_queue(adm5120_devs[i]); - } - } - spin_unlock(&tx_lock); -} - -#ifdef CONFIG_ADM5120_SWITCH_NAPI -static int adm5120_if_poll(struct napi_struct *napi, int limit) -{ - struct adm5120_if_priv *priv = container_of(napi, - struct adm5120_if_priv, napi); - struct net_device *dev __maybe_unused = priv->dev; - int done; - u32 status; - - sw_int_ack(SWITCH_INTS_POLL); - - SW_DBG("%s: processing TX ring\n", dev->name); - adm5120_switch_tx(); - - SW_DBG("%s: processing RX ring\n", dev->name); - done = adm5120_switch_rx(limit); - - status = sw_int_status() & SWITCH_INTS_POLL; - if ((done < limit) && (!status)) { - SW_DBG("disable polling mode for %s\n", dev->name); - napi_complete(napi); - sw_int_unmask(SWITCH_INTS_POLL); - return 0; - } - - SW_DBG("%s still in polling mode, done=%d, status=%x\n", - dev->name, done, status); - return 1; -} -#endif /* CONFIG_ADM5120_SWITCH_NAPI */ - - -static irqreturn_t adm5120_switch_irq(int irq, void *dev_id) -{ - u32 status; - - status = sw_int_status(); - status &= SWITCH_INTS_ALL; - if (!status) - return IRQ_NONE; - -#ifdef CONFIG_ADM5120_SWITCH_NAPI - sw_int_ack(status & ~SWITCH_INTS_POLL); - - if (status & SWITCH_INTS_POLL) { - struct net_device *dev = dev_id; - struct adm5120_if_priv *priv = netdev_priv(dev); - - sw_dump_intr_mask("poll ints", status); - SW_DBG("enable polling mode for %s\n", dev->name); - sw_int_mask(SWITCH_INTS_POLL); - napi_schedule(&priv->napi); - } -#else - sw_int_ack(status); - - if (status & (SWITCH_INT_RLD | SWITCH_INT_LDF)) - adm5120_switch_rx(RX_RING_SIZE); - - if (status & SWITCH_INT_SLD) - adm5120_switch_tx(); -#endif - - return IRQ_HANDLED; -} - -static void adm5120_set_bw(char *matrix) -{ - unsigned long val; - - /* Port 0 to 3 are set using the bandwidth control 0 register */ - val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); - sw_write_reg(SWITCH_REG_BW_CNTL0, val); - - /* Port 4 and 5 are set using the bandwidth control 1 register */ - val = matrix[4]; - if (matrix[5] == 1) - sw_write_reg(SWITCH_REG_BW_CNTL1, val | 0x80000000); - else - sw_write_reg(SWITCH_REG_BW_CNTL1, val & ~0x8000000); - - SW_DBG("D: ctl0 0x%ux, ctl1 0x%ux\n", sw_read_reg(SWITCH_REG_BW_CNTL0), - sw_read_reg(SWITCH_REG_BW_CNTL1)); -} - -static void adm5120_switch_tx_ring_reset(struct dma_desc *desc, - struct sk_buff **skbl, int num) -{ - memset(desc, 0, num * sizeof(*desc)); - desc[num-1].buf1 |= DESC_EOR; - memset(skbl, 0, sizeof(struct skb *) * num); - - cur_txl = 0; - dirty_txl = 0; -} - -static void adm5120_switch_rx_ring_reset(struct dma_desc *desc, - struct sk_buff **skbl, int num) -{ - int i; - - memset(desc, 0, num * sizeof(*desc)); - for (i = 0; i < num; i++) { - skbl[i] = dev_alloc_skb(SKB_ALLOC_LEN); - if (!skbl[i]) { - i = num; - break; - } - skb_reserve(skbl[i], SKB_RESERVE_LEN); - adm5120_rx_dma_update(&desc[i], skbl[i], (num - 1 == i)); - } - - cur_rxl = 0; - dirty_rxl = 0; -} - -static int adm5120_switch_tx_ring_alloc(void) -{ - int err; - - txl_descs = dma_alloc_coherent(NULL, TX_DESCS_SIZE, &txl_descs_dma, - GFP_ATOMIC); - if (!txl_descs) { - err = -ENOMEM; - goto err; - } - - txl_skbuff = kzalloc(TX_SKBS_SIZE, GFP_KERNEL); - if (!txl_skbuff) { - err = -ENOMEM; - goto err; - } - - return 0; - -err: - return err; -} - -static void adm5120_switch_tx_ring_free(void) -{ - int i; - - if (txl_skbuff) { - for (i = 0; i < TX_RING_SIZE; i++) - if (txl_skbuff[i]) - kfree_skb(txl_skbuff[i]); - kfree(txl_skbuff); - } - - if (txl_descs) - dma_free_coherent(NULL, TX_DESCS_SIZE, txl_descs, - txl_descs_dma); -} - -static int adm5120_switch_rx_ring_alloc(void) -{ - int err; - int i; - - /* init RX ring */ - rxl_descs = dma_alloc_coherent(NULL, RX_DESCS_SIZE, &rxl_descs_dma, - GFP_ATOMIC); - if (!rxl_descs) { - err = -ENOMEM; - goto err; - } - - rxl_skbuff = kzalloc(RX_SKBS_SIZE, GFP_KERNEL); - if (!rxl_skbuff) { - err = -ENOMEM; - goto err; - } - - for (i = 0; i < RX_RING_SIZE; i++) { - struct sk_buff *skb; - skb = alloc_skb(SKB_ALLOC_LEN, GFP_ATOMIC); - if (!skb) { - err = -ENOMEM; - goto err; - } - rxl_skbuff[i] = skb; - skb_reserve(skb, SKB_RESERVE_LEN); - } - - return 0; - -err: - return err; -} - -static void adm5120_switch_rx_ring_free(void) -{ - int i; - - if (rxl_skbuff) { - for (i = 0; i < RX_RING_SIZE; i++) - if (rxl_skbuff[i]) - kfree_skb(rxl_skbuff[i]); - kfree(rxl_skbuff); - } - - if (rxl_descs) - dma_free_coherent(NULL, RX_DESCS_SIZE, rxl_descs, - rxl_descs_dma); -} - -static void adm5120_write_mac(struct net_device *dev) -{ - struct adm5120_if_priv *priv = netdev_priv(dev); - unsigned char *mac = dev->dev_addr; - u32 t; - - t = mac[2] | (mac[3] << MAC_WT1_MAC3_SHIFT) | - (mac[4] << MAC_WT1_MAC4_SHIFT) | (mac[5] << MAC_WT1_MAC5_SHIFT); - sw_write_reg(SWITCH_REG_MAC_WT1, t); - - t = (mac[0] << MAC_WT0_MAC0_SHIFT) | (mac[1] << MAC_WT0_MAC1_SHIFT) | - MAC_WT0_MAWC | MAC_WT0_WVE | (priv->vlan_no<<3); - - sw_write_reg(SWITCH_REG_MAC_WT0, t); - - while (!(sw_read_reg(SWITCH_REG_MAC_WT0) & MAC_WT0_MWD)) - ; -} - -static void adm5120_set_vlan(char *matrix) -{ - unsigned long val; - int vlan_port, port; - - val = matrix[0] + (matrix[1]<<8) + (matrix[2]<<16) + (matrix[3]<<24); - sw_write_reg(SWITCH_REG_VLAN_G1, val); - val = matrix[4] + (matrix[5]<<8); - sw_write_reg(SWITCH_REG_VLAN_G2, val); - - /* Now set/update the port vs. device lookup table */ - for (port = 0; port < SWITCH_NUM_PORTS; port++) { - for (vlan_port = 0; vlan_port < SWITCH_NUM_PORTS && !(matrix[vlan_port] & (0x00000001 << port)); vlan_port++) - ; - if (vlan_port < SWITCH_NUM_PORTS) - adm5120_port[port] = adm5120_devs[vlan_port]; - else - adm5120_port[port] = NULL; - } -} - -static void adm5120_switch_set_vlan_mac(unsigned int vlan, unsigned char *mac) -{ - u32 t; - - t = mac[2] | (mac[3] << MAC_WT1_MAC3_SHIFT) - | (mac[4] << MAC_WT1_MAC4_SHIFT) - | (mac[5] << MAC_WT1_MAC5_SHIFT); - sw_write_reg(SWITCH_REG_MAC_WT1, t); - - t = (mac[0] << MAC_WT0_MAC0_SHIFT) | (mac[1] << MAC_WT0_MAC1_SHIFT) | - MAC_WT0_MAWC | MAC_WT0_WVE | (vlan << MAC_WT0_WVN_SHIFT) | - (MAC_WT0_WAF_STATIC << MAC_WT0_WAF_SHIFT); - sw_write_reg(SWITCH_REG_MAC_WT0, t); - - do { - t = sw_read_reg(SWITCH_REG_MAC_WT0); - } while ((t & MAC_WT0_MWD) == 0); -} - -static void adm5120_switch_set_vlan_ports(unsigned int vlan, u32 ports) -{ - unsigned int reg; - u32 t; - - if (vlan < 4) - reg = SWITCH_REG_VLAN_G1; - else { - vlan -= 4; - reg = SWITCH_REG_VLAN_G2; - } - - t = sw_read_reg(reg); - t &= ~(0xFF << (vlan*8)); - t |= (ports << (vlan*8)); - sw_write_reg(reg, t); -} - -/* ------------------------------------------------------------------------ */ - -#ifdef CONFIG_ADM5120_SWITCH_NAPI -static inline void adm5120_if_napi_enable(struct net_device *dev) -{ - struct adm5120_if_priv *priv = netdev_priv(dev); - napi_enable(&priv->napi); -} - -static inline void adm5120_if_napi_disable(struct net_device *dev) -{ - struct adm5120_if_priv *priv = netdev_priv(dev); - napi_disable(&priv->napi); -} -#else -static inline void adm5120_if_napi_enable(struct net_device *dev) {} -static inline void adm5120_if_napi_disable(struct net_device *dev) {} -#endif /* CONFIG_ADM5120_SWITCH_NAPI */ - -static int adm5120_if_open(struct net_device *dev) -{ - u32 t; - int err; - int i; - - adm5120_if_napi_enable(dev); - - err = request_irq(dev->irq, adm5120_switch_irq, IRQF_SHARED, - dev->name, dev); - if (err) { - SW_ERR("unable to get irq for %s\n", dev->name); - goto err; - } - - if (!sw_used++) - /* enable interrupts on first open */ - sw_int_unmask(SWITCH_INTS_USED); - - /* enable (additional) port */ - t = sw_read_reg(SWITCH_REG_PORT_CONF0); - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - if (dev == adm5120_devs[i]) - t &= ~adm5120_eth_vlans[i]; - } - sw_write_reg(SWITCH_REG_PORT_CONF0, t); - - netif_start_queue(dev); - - return 0; - -err: - adm5120_if_napi_disable(dev); - return err; -} - -static int adm5120_if_stop(struct net_device *dev) -{ - u32 t; - int i; - - netif_stop_queue(dev); - adm5120_if_napi_disable(dev); - - /* disable port if not assigned to other devices */ - t = sw_read_reg(SWITCH_REG_PORT_CONF0); - t |= SWITCH_PORTS_NOCPU; - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - if ((dev != adm5120_devs[i]) && netif_running(adm5120_devs[i])) - t &= ~adm5120_eth_vlans[i]; - } - sw_write_reg(SWITCH_REG_PORT_CONF0, t); - - if (!--sw_used) - sw_int_mask(SWITCH_INTS_USED); - - free_irq(dev->irq, dev); - - return 0; -} - -static int adm5120_if_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct dma_desc *desc; - struct adm5120_if_priv *priv = netdev_priv(dev); - unsigned int entry; - unsigned long data; - int i; - - /* lock switch irq */ - spin_lock_irq(&tx_lock); - - /* calculate the next TX descriptor entry. */ - entry = cur_txl % TX_RING_SIZE; - - desc = &txl_descs[entry]; - if (desc->buf1 & DESC_OWN) { - /* We want to write a packet but the TX queue is still - * occupied by the DMA. We are faster than the DMA... */ - SW_DBG("%s unable to transmit, packet dopped\n", dev->name); - dev_kfree_skb(skb); - dev->stats.tx_dropped++; - return 0; - } - - txl_skbuff[entry] = skb; - data = (desc->buf1 & DESC_EOR); - data |= DESC_ADDR(skb->data); - - desc->misc = - ((skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len) << DESC_PKTLEN_SHIFT) | - (0x1 << priv->vlan_no); - - desc->buflen = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; - - desc->buf1 = data | DESC_OWN; - sw_write_reg(SWITCH_REG_SEND_TRIG, SEND_TRIG_STL); - - cur_txl++; - if (cur_txl == dirty_txl + TX_QUEUE_LEN) { - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - if (!adm5120_devs[i]) - continue; - netif_stop_queue(adm5120_devs[i]); - } - } - - dev->trans_start = jiffies; - - spin_unlock_irq(&tx_lock); - - return 0; -} - -static void adm5120_if_tx_timeout(struct net_device *dev) -{ - SW_INFO("TX timeout on %s\n", dev->name); -} - -static void adm5120_if_set_rx_mode(struct net_device *dev) -{ - struct adm5120_if_priv *priv = netdev_priv(dev); - u32 ports; - u32 t; - - ports = adm5120_eth_vlans[priv->vlan_no] & SWITCH_PORTS_NOCPU; - - t = sw_read_reg(SWITCH_REG_CPUP_CONF); - if (dev->flags & IFF_PROMISC) - /* enable unknown packets */ - t &= ~(ports << CPUP_CONF_DUNP_SHIFT); - else - /* disable unknown packets */ - t |= (ports << CPUP_CONF_DUNP_SHIFT); - - if (dev->flags & IFF_PROMISC || dev->flags & IFF_ALLMULTI || - netdev_mc_count(dev)) - /* enable multicast packets */ - t &= ~(ports << CPUP_CONF_DMCP_SHIFT); - else - /* disable multicast packets */ - t |= (ports << CPUP_CONF_DMCP_SHIFT); - - /* If there is any port configured to be in promiscuous mode, then the */ - /* Bridge Test Mode has to be activated. This will result in */ - /* transporting also packets learned in another VLAN to be forwarded */ - /* to the CPU. */ - /* The difficult scenario is when we want to build a bridge on the CPU.*/ - /* Assume we have port0 and the CPU port in VLAN0 and port1 and the */ - /* CPU port in VLAN1. Now we build a bridge on the CPU between */ - /* VLAN0 and VLAN1. Both ports of the VLANs are set in promisc mode. */ - /* Now assume a packet with ethernet source address 99 enters port 0 */ - /* It will be forwarded to the CPU because it is unknown. Then the */ - /* bridge in the CPU will send it to VLAN1 and it goes out at port 1. */ - /* When now a packet with ethernet destination address 99 comes in at */ - /* port 1 in VLAN1, then the switch has learned that this address is */ - /* located at port 0 in VLAN0. Therefore the switch will drop */ - /* this packet. In order to avoid this and to send the packet still */ - /* to the CPU, the Bridge Test Mode has to be activated. */ - - /* Check if there is any vlan in promisc mode. */ - if (~t & (SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT)) - t |= CPUP_CONF_BTM; /* Enable Bridge Testing Mode */ - else - t &= ~CPUP_CONF_BTM; /* Disable Bridge Testing Mode */ - - sw_write_reg(SWITCH_REG_CPUP_CONF, t); - -} - -static int adm5120_if_set_mac_address(struct net_device *dev, void *p) -{ - int ret; - - ret = eth_mac_addr(dev, p); - if (ret) - return ret; - - adm5120_write_mac(dev); - return 0; -} - -static int adm5120_if_do_ioctl(struct net_device *dev, struct ifreq *rq, - int cmd) -{ - int err; - struct adm5120_sw_info info; - struct adm5120_if_priv *priv = netdev_priv(dev); - - switch (cmd) { - case SIOCGADMINFO: - info.magic = 0x5120; - info.ports = adm5120_nrdevs; - info.vlan = priv->vlan_no; - err = copy_to_user(rq->ifr_data, &info, sizeof(info)); - if (err) - return -EFAULT; - break; - case SIOCSMATRIX: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - err = copy_from_user(adm5120_eth_vlans, rq->ifr_data, - sizeof(adm5120_eth_vlans)); - if (err) - return -EFAULT; - adm5120_set_vlan(adm5120_eth_vlans); - break; - case SIOCGMATRIX: - err = copy_to_user(rq->ifr_data, adm5120_eth_vlans, - sizeof(adm5120_eth_vlans)); - if (err) - return -EFAULT; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - -static const struct net_device_ops adm5120sw_netdev_ops = { - .ndo_open = adm5120_if_open, - .ndo_stop = adm5120_if_stop, - .ndo_start_xmit = adm5120_if_hard_start_xmit, - .ndo_set_rx_mode = adm5120_if_set_rx_mode, - .ndo_do_ioctl = adm5120_if_do_ioctl, - .ndo_tx_timeout = adm5120_if_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = adm5120_if_set_mac_address, -}; - -static struct net_device *adm5120_if_alloc(void) -{ - struct net_device *dev; - struct adm5120_if_priv *priv; - - dev = alloc_etherdev(sizeof(*priv)); - if (!dev) - return NULL; - - priv = netdev_priv(dev); - priv->dev = dev; - - dev->irq = ADM5120_IRQ_SWITCH; - dev->netdev_ops = &adm5120sw_netdev_ops; - dev->watchdog_timeo = TX_TIMEOUT; - -#ifdef CONFIG_ADM5120_SWITCH_NAPI - netif_napi_add(dev, &priv->napi, adm5120_if_poll, 64); -#endif - - return dev; -} - -/* ------------------------------------------------------------------------ */ - -static void adm5120_switch_cleanup(void) -{ - int i; - - /* disable interrupts */ - sw_int_mask(SWITCH_INTS_ALL); - - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - struct net_device *dev = adm5120_devs[i]; - if (dev) { - unregister_netdev(dev); - free_netdev(dev); - } - } - - adm5120_switch_tx_ring_free(); - adm5120_switch_rx_ring_free(); -} - -static int adm5120_switch_probe(struct platform_device *pdev) -{ - u32 t; - int i, err; - - adm5120_nrdevs = adm5120_eth_num_ports; - - t = CPUP_CONF_DCPUP | CPUP_CONF_CRCP | - SWITCH_PORTS_NOCPU << CPUP_CONF_DUNP_SHIFT | - SWITCH_PORTS_NOCPU << CPUP_CONF_DMCP_SHIFT ; - sw_write_reg(SWITCH_REG_CPUP_CONF, t); - - t = (SWITCH_PORTS_NOCPU << PORT_CONF0_EMCP_SHIFT) | - (SWITCH_PORTS_NOCPU << PORT_CONF0_BP_SHIFT) | - (SWITCH_PORTS_NOCPU); - sw_write_reg(SWITCH_REG_PORT_CONF0, t); - - /* setup ports to Autoneg/100M/Full duplex/Auto MDIX */ - t = SWITCH_PORTS_PHY | - (SWITCH_PORTS_PHY << PHY_CNTL2_SC_SHIFT) | - (SWITCH_PORTS_PHY << PHY_CNTL2_DC_SHIFT) | - (SWITCH_PORTS_PHY << PHY_CNTL2_PHYR_SHIFT) | - (SWITCH_PORTS_PHY << PHY_CNTL2_AMDIX_SHIFT) | - PHY_CNTL2_RMAE; - sw_write_reg(SWITCH_REG_PHY_CNTL2, t); - - t = sw_read_reg(SWITCH_REG_PHY_CNTL3); - t |= PHY_CNTL3_RNT; - sw_write_reg(SWITCH_REG_PHY_CNTL3, t); - - /* Force all the packets from all ports are low priority */ - sw_write_reg(SWITCH_REG_PRI_CNTL, 0); - - sw_int_mask(SWITCH_INTS_ALL); - sw_int_ack(SWITCH_INTS_ALL); - - err = adm5120_switch_rx_ring_alloc(); - if (err) - goto err; - - err = adm5120_switch_tx_ring_alloc(); - if (err) - goto err; - - adm5120_switch_tx_ring_reset(txl_descs, txl_skbuff, TX_RING_SIZE); - adm5120_switch_rx_ring_reset(rxl_descs, rxl_skbuff, RX_RING_SIZE); - - sw_write_reg(SWITCH_REG_SHDA, 0); - sw_write_reg(SWITCH_REG_SLDA, KSEG1ADDR(txl_descs)); - sw_write_reg(SWITCH_REG_RHDA, 0); - sw_write_reg(SWITCH_REG_RLDA, KSEG1ADDR(rxl_descs)); - - for (i = 0; i < SWITCH_NUM_PORTS; i++) { - struct net_device *dev; - struct adm5120_if_priv *priv; - - dev = adm5120_if_alloc(); - if (!dev) { - err = -ENOMEM; - goto err; - } - - adm5120_devs[i] = dev; - priv = netdev_priv(dev); - - priv->vlan_no = i; - priv->port_mask = adm5120_eth_vlans[i]; - - memcpy(dev->dev_addr, adm5120_eth_macs[i], 6); - adm5120_write_mac(dev); - - err = register_netdev(dev); - if (err) { - SW_INFO("%s register failed, error=%d\n", - dev->name, err); - goto err; - } - } - - /* setup vlan/port mapping after devs are filled up */ - adm5120_set_vlan(adm5120_eth_vlans); - - /* enable CPU port */ - t = sw_read_reg(SWITCH_REG_CPUP_CONF); - t &= ~CPUP_CONF_DCPUP; - sw_write_reg(SWITCH_REG_CPUP_CONF, t); - - return 0; - -err: - adm5120_switch_cleanup(); - - SW_ERR("init failed\n"); - return err; -} - -static int adm5120_switch_remove(struct platform_device *pdev) -{ - adm5120_switch_cleanup(); - return 0; -} - -static struct platform_driver adm5120_switch_driver = { - .probe = adm5120_switch_probe, - .remove = adm5120_switch_remove, - .driver = { - .name = DRV_NAME, - }, -}; - -/* -------------------------------------------------------------------------- */ - -static int __init adm5120_switch_mod_init(void) -{ - int err; - - pr_info(DRV_DESC " version " DRV_VERSION "\n"); - err = platform_driver_register(&adm5120_switch_driver); - - return err; -} - -static void __exit adm5120_switch_mod_exit(void) -{ - platform_driver_unregister(&adm5120_switch_driver); -} - -module_init(adm5120_switch_mod_init); -module_exit(adm5120_switch_mod_exit); - -MODULE_LICENSE("GPL v2"); -MODULE_AUTHOR("Gabor Juhos "); -MODULE_DESCRIPTION(DRV_DESC); -MODULE_VERSION(DRV_VERSION); diff --git a/target/linux/adm5120/files/drivers/net/adm5120sw.h b/target/linux/adm5120/files/drivers/net/adm5120sw.h deleted file mode 100644 index fa9e503359..0000000000 --- a/target/linux/adm5120/files/drivers/net/adm5120sw.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Defines for ADM5120 built in ethernet switch driver - * - * Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2005 - * - * Values come from ADM5120 datasheet and original ADMtek 2.4 driver, - * Copyright ADMtek Inc. - */ - -#ifndef _INCLUDE_ADM5120SW_H_ -#define _INCLUDE_ADM5120SW_H_ - -#define SIOCSMATRIX SIOCDEVPRIVATE -#define SIOCGMATRIX (SIOCDEVPRIVATE + 1) -#define SIOCGADMINFO (SIOCDEVPRIVATE + 2) - -struct adm5120_sw_info { - u16 magic; - u16 ports; - u16 vlan; -}; - -#endif /* _INCLUDE_ADM5120SW_H_ */ diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c deleted file mode 100644 index 2d5dc2a5a7..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c +++ /dev/null @@ -1,836 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-dbg.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * 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. - * - */ - -/*-------------------------------------------------------------------------*/ - -static inline char *ed_typestring(int ed_type) -{ - switch (ed_type) { - case PIPE_CONTROL: - return "ctrl"; - case PIPE_BULK: - return "bulk"; - case PIPE_INTERRUPT: - return "intr"; - case PIPE_ISOCHRONOUS: - return "isoc"; - } - return "(bad ed_type)"; -} - -static inline char *ed_statestring(int state) -{ - switch (state) { - case ED_IDLE: - return "IDLE"; - case ED_UNLINK: - return "UNLINK"; - case ED_OPER: - return "OPER"; - } - return "?STATE"; -} - -static inline char *pipestring(int pipe) -{ - return ed_typestring(usb_pipetype(pipe)); -} - -static inline char *td_pidstring(u32 info) -{ - switch (info & TD_DP) { - case TD_DP_SETUP: - return "SETUP"; - case TD_DP_IN: - return "IN"; - case TD_DP_OUT: - return "OUT"; - } - return "?PID"; -} - -static inline char *td_togglestring(u32 info) -{ - switch (info & TD_T) { - case TD_T_DATA0: - return "DATA0"; - case TD_T_DATA1: - return "DATA1"; - case TD_T_CARRY: - return "CARRY"; - } - return "?TOGGLE"; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef DEBUG - -/* debug| print the main components of an URB - * small: 0) header + data packets 1) just header - */ -static void __attribute__((unused)) -urb_print(struct admhcd *ahcd, struct urb *urb, char *str, int small, int status) -{ - unsigned int pipe = urb->pipe; - - if (!urb->dev || !urb->dev->bus) { - admhc_dbg(ahcd, "%s URB: no dev", str); - return; - } - -#ifndef ADMHC_VERBOSE_DEBUG - if (status != 0) -#endif - admhc_dbg(ahcd, "URB-%s %p dev=%d ep=%d%s-%s flags=%x len=%d/%d " - "stat=%d\n", - str, - urb, - usb_pipedevice(pipe), - usb_pipeendpoint(pipe), - usb_pipeout(pipe) ? "out" : "in", - pipestring(pipe), - urb->transfer_flags, - urb->actual_length, - urb->transfer_buffer_length, - status); - -#ifdef ADMHC_VERBOSE_DEBUG - if (!small) { - int i, len; - - if (usb_pipecontrol(pipe)) { - admhc_dbg(ahcd, "setup(8):"); - for (i = 0; i < 8 ; i++) - printk(KERN_INFO" %02x", ((__u8 *)urb->setup_packet)[i]); - printk(KERN_INFO "\n"); - } - if (urb->transfer_buffer_length > 0 && urb->transfer_buffer) { - admhc_dbg(ahcd, "data(%d/%d):", - urb->actual_length, - urb->transfer_buffer_length); - len = usb_pipeout(pipe) ? - urb->transfer_buffer_length : urb->actual_length; - for (i = 0; i < 16 && i < len; i++) - printk(KERN_INFO " %02x", ((__u8 *)urb->transfer_buffer)[i]); - printk(KERN_INFO "%s stat:%d\n", i < len ? "..." : "", status); - } - } -#endif /* ADMHC_VERBOSE_DEBUG */ -} - -#define admhc_dbg_sw(ahcd, next, size, format, arg...) \ - do { \ - if (next) { \ - unsigned s_len; \ - s_len = scnprintf(*next, *size, format, ## arg); \ - *size -= s_len; *next += s_len; \ - } else \ - admhc_dbg(ahcd, format, ## arg); \ - } while (0); - - -static void admhc_dump_intr_mask(struct admhcd *ahcd, char *label, u32 mask, - char **next, unsigned *size) -{ - admhc_dbg_sw(ahcd, next, size, "%s 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", - label, - mask, - (mask & ADMHC_INTR_INTA) ? " INTA" : "", - (mask & ADMHC_INTR_FATI) ? " FATI" : "", - (mask & ADMHC_INTR_SWI) ? " SWI" : "", - (mask & ADMHC_INTR_TDC) ? " TDC" : "", - (mask & ADMHC_INTR_FNO) ? " FNO" : "", - (mask & ADMHC_INTR_SO) ? " SO" : "", - (mask & ADMHC_INTR_INSM) ? " INSM" : "", - (mask & ADMHC_INTR_BABI) ? " BABI" : "", - (mask & ADMHC_INTR_7) ? " !7!" : "", - (mask & ADMHC_INTR_6) ? " !6!" : "", - (mask & ADMHC_INTR_RESI) ? " RESI" : "", - (mask & ADMHC_INTR_SOFI) ? " SOFI" : "" - ); -} - -static void maybe_print_eds(struct admhcd *ahcd, char *label, u32 value, - char **next, unsigned *size) -{ - if (value) - admhc_dbg_sw(ahcd, next, size, "%s %08x\n", label, value); -} - -static char *buss2string(int state) -{ - switch (state) { - case ADMHC_BUSS_RESET: - return "reset"; - case ADMHC_BUSS_RESUME: - return "resume"; - case ADMHC_BUSS_OPER: - return "operational"; - case ADMHC_BUSS_SUSPEND: - return "suspend"; - } - return "?state"; -} - -static void -admhc_dump_status(struct admhcd *ahcd, char **next, unsigned *size) -{ - struct admhcd_regs __iomem *regs = ahcd->regs; - u32 temp; - - temp = admhc_readl(ahcd, ®s->gencontrol); - admhc_dbg_sw(ahcd, next, size, - "gencontrol 0x%08x%s%s%s%s\n", - temp, - (temp & ADMHC_CTRL_UHFE) ? " UHFE" : "", - (temp & ADMHC_CTRL_SIR) ? " SIR" : "", - (temp & ADMHC_CTRL_DMAA) ? " DMAA" : "", - (temp & ADMHC_CTRL_SR) ? " SR" : "" - ); - - temp = admhc_readl(ahcd, ®s->host_control); - admhc_dbg_sw(ahcd, next, size, - "host_control 0x%08x BUSS=%s%s\n", - temp, - buss2string(temp & ADMHC_HC_BUSS), - (temp & ADMHC_HC_DMAE) ? " DMAE" : "" - ); - - admhc_dump_intr_mask(ahcd, "int_status", - admhc_readl(ahcd, ®s->int_status), - next, size); - admhc_dump_intr_mask(ahcd, "int_enable", - admhc_readl(ahcd, ®s->int_enable), - next, size); - - maybe_print_eds(ahcd, "hosthead", - admhc_readl(ahcd, ®s->hosthead), next, size); -} - -#define dbg_port_sw(hc, num, value, next, size) \ - admhc_dbg_sw(hc, next, size, \ - "portstatus [%d] " \ - "0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ - num, temp, \ - (temp & ADMHC_PS_PRSC) ? " PRSC" : "", \ - (temp & ADMHC_PS_OCIC) ? " OCIC" : "", \ - (temp & ADMHC_PS_PSSC) ? " PSSC" : "", \ - (temp & ADMHC_PS_PESC) ? " PESC" : "", \ - (temp & ADMHC_PS_CSC) ? " CSC" : "", \ - \ - (temp & ADMHC_PS_LSDA) ? " LSDA" : "", \ - (temp & ADMHC_PS_PPS) ? " PPS" : "", \ - (temp & ADMHC_PS_PRS) ? " PRS" : "", \ - (temp & ADMHC_PS_POCI) ? " POCI" : "", \ - (temp & ADMHC_PS_PSS) ? " PSS" : "", \ - \ - (temp & ADMHC_PS_PES) ? " PES" : "", \ - (temp & ADMHC_PS_CCS) ? " CCS" : "" \ - ); - - -static void -admhc_dump_roothub( - struct admhcd *ahcd, - int verbose, - char **next, - unsigned *size) -{ - u32 temp, i; - - temp = admhc_read_rhdesc(ahcd); - if (temp == ~(u32)0) - return; - - if (verbose) { - admhc_dbg_sw(ahcd, next, size, - "rhdesc %08x%s%s%s%s%s%s PPCM=%02x%s%s%s%s NUMP=%d(%d)\n", - temp, - (temp & ADMHC_RH_CRWE) ? " CRWE" : "", - (temp & ADMHC_RH_OCIC) ? " OCIC" : "", - (temp & ADMHC_RH_LPSC) ? " LPSC" : "", - (temp & ADMHC_RH_LPSC) ? " DRWE" : "", - (temp & ADMHC_RH_LPSC) ? " OCI" : "", - (temp & ADMHC_RH_LPSC) ? " LPS" : "", - ((temp & ADMHC_RH_PPCM) >> 16), - (temp & ADMHC_RH_NOCP) ? " NOCP" : "", - (temp & ADMHC_RH_OCPM) ? " OCPM" : "", - (temp & ADMHC_RH_NPS) ? " NPS" : "", - (temp & ADMHC_RH_PSM) ? " PSM" : "", - (temp & ADMHC_RH_NUMP), ahcd->num_ports - ); - } - - for (i = 0; i < ahcd->num_ports; i++) { - temp = admhc_read_portstatus(ahcd, i); - dbg_port_sw(ahcd, i, temp, next, size); - } -} - -static void admhc_dump(struct admhcd *ahcd, int verbose) -{ - admhc_dbg(ahcd, "ADMHC ahcd state\n"); - - /* dumps some of the state we know about */ - admhc_dump_status(ahcd, NULL, NULL); - admhc_dbg(ahcd, "current frame #%04x\n", - admhc_frame_no(ahcd)); - - admhc_dump_roothub(ahcd, verbose, NULL, NULL); -} - -static const char data0[] = "DATA0"; -static const char data1[] = "DATA1"; - -static void admhc_dump_td(const struct admhcd *ahcd, const char *label, - const struct td *td) -{ - u32 tmp; - - admhc_dbg(ahcd, "%s td %p; urb %p index %d; hwNextTD %08x\n", - label, td, - td->urb, td->index, - hc32_to_cpup(ahcd, &td->hwNextTD)); - - tmp = hc32_to_cpup(ahcd, &td->hwINFO); - admhc_dbg(ahcd, " status %08x%s CC=%x EC=%d %s %s ISI=%x FN=%x\n", - tmp, - (tmp & TD_OWN) ? " OWN" : "", - TD_CC_GET(tmp), - TD_EC_GET(tmp), - td_togglestring(tmp), - td_pidstring(tmp), - TD_ISI_GET(tmp), - TD_FN_GET(tmp)); - - tmp = hc32_to_cpup(ahcd, &td->hwCBL); - admhc_dbg(ahcd, " dbp %08x; cbl %08x; LEN=%d%s\n", - hc32_to_cpup(ahcd, &td->hwDBP), - tmp, - TD_BL_GET(tmp), - (tmp & TD_IE) ? " IE" : ""); -} - -/* caller MUST own hcd spinlock if verbose is set! */ -static void __attribute__((unused)) -admhc_dump_ed(const struct admhcd *ahcd, const char *label, - const struct ed *ed, int verbose) -{ - u32 tmp = hc32_to_cpu(ahcd, ed->hwINFO); - - admhc_dbg(ahcd, "%s ed %p %s type %s; next ed %08x\n", - label, - ed, ed_statestring(ed->state), ed_typestring(ed->type), - hc32_to_cpup(ahcd, &ed->hwNextED)); - - admhc_dbg(ahcd, " info %08x MAX=%d%s%s%s%s EP=%d DEV=%d\n", tmp, - ED_MPS_GET(tmp), - (tmp & ED_ISO) ? " ISO" : "", - (tmp & ED_SKIP) ? " SKIP" : "", - (tmp & ED_SPEED_FULL) ? " FULL" : " LOW", - (tmp & ED_INT) ? " INT" : "", - ED_EN_GET(tmp), - ED_FA_GET(tmp)); - - tmp = hc32_to_cpup(ahcd, &ed->hwHeadP); - admhc_dbg(ahcd, " tds: head %08x tail %08x %s%s%s\n", - tmp & TD_MASK, - hc32_to_cpup(ahcd, &ed->hwTailP), - (tmp & ED_C) ? data1 : data0, - (tmp & ED_H) ? " HALT" : "", - verbose ? " td list follows" : " (not listing)"); - - if (verbose) { - struct list_head *tmp; - - /* use ed->td_list because HC concurrently modifies - * hwNextTD as it accumulates ed_donelist. - */ - list_for_each(tmp, &ed->td_list) { - struct td *td; - td = list_entry(tmp, struct td, td_list); - admhc_dump_td(ahcd, " ->", td); - } - } -} - -#else /* ifdef DEBUG */ - -static inline void urb_print(struct admhcd *ahcd, struct urb * urb, char * str, - int small, int status) {} -static inline void admhc_dump_ed(const struct admhcd *ahcd, const char *label, - const struct ed *ed, int verbose) {} -static inline void admhc_dump_td(const struct admhcd *ahcd, const char *label, - const struct td *td) {} -static inline void admhc_dump(struct admhcd *ahcd, int verbose) {} - -#undef ADMHC_VERBOSE_DEBUG - -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files(struct admhcd *bus) { } -static inline void remove_debug_files(struct admhcd *bus) { } - -#else - -static int debug_async_open(struct inode *, struct file *); -static int debug_periodic_open(struct inode *, struct file *); -static int debug_registers_open(struct inode *, struct file *); -static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); -static int debug_close(struct inode *, struct file *); - -static const struct file_operations debug_async_fops = { - .owner = THIS_MODULE, - .open = debug_async_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_periodic_fops = { - .owner = THIS_MODULE, - .open = debug_periodic_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_registers_fops = { - .owner = THIS_MODULE, - .open = debug_registers_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; - -static struct dentry *admhc_debug_root; - -struct debug_buffer { - ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ - struct admhcd *ahcd; - struct mutex mutex; /* protect filling of buffer */ - size_t count; /* number of characters filled into buffer */ - char *page; -}; - -static ssize_t -show_list(struct admhcd *ahcd, char *buf, size_t count, struct ed *ed) -{ - unsigned temp; - unsigned size = count; - - if (!ed) - return 0; - - /* dump a snapshot of the bulk or control schedule */ - while (ed) { - u32 info = hc32_to_cpu(ahcd, ed->hwINFO); - u32 headp = hc32_to_cpu(ahcd, ed->hwHeadP); - u32 tailp = hc32_to_cpu(ahcd, ed->hwTailP); - struct list_head *entry; - struct td *td; - - temp = scnprintf(buf, size, - "ed/%p %s %s %cs dev%d ep%d %s%smax %d %08x%s%s %s" - " h:%08x t:%08x", - ed, - ed_statestring(ed->state), - ed_typestring(ed->type), - (info & ED_SPEED_FULL) ? 'f' : 'l', - info & ED_FA_MASK, - (info >> ED_EN_SHIFT) & ED_EN_MASK, - (info & ED_INT) ? "INT " : "", - (info & ED_ISO) ? "ISO " : "", - (info >> ED_MPS_SHIFT) & ED_MPS_MASK , - info, - (info & ED_SKIP) ? " S" : "", - (headp & ED_H) ? " H" : "", - (headp & ED_C) ? data1 : data0, - headp & ED_MASK, tailp); - size -= temp; - buf += temp; - - list_for_each(entry, &ed->td_list) { - u32 dbp, cbl; - - td = list_entry(entry, struct td, td_list); - info = hc32_to_cpup(ahcd, &td->hwINFO); - dbp = hc32_to_cpup(ahcd, &td->hwDBP); - cbl = hc32_to_cpup(ahcd, &td->hwCBL); - - temp = scnprintf(buf, size, - "\n\ttd/%p %s %d %s%scc=%x urb %p (%08x,%08x)", - td, - td_pidstring(info), - TD_BL_GET(cbl), - (info & TD_OWN) ? "" : "DONE ", - (cbl & TD_IE) ? "IE " : "", - TD_CC_GET(info), td->urb, info, cbl); - size -= temp; - buf += temp; - } - - temp = scnprintf(buf, size, "\n"); - size -= temp; - buf += temp; - - ed = ed->ed_next; - } - - return count - size; -} - -static ssize_t fill_async_buffer(struct debug_buffer *buf) -{ - struct admhcd *ahcd; - size_t temp; - unsigned long flags; - - ahcd = buf->ahcd; - - spin_lock_irqsave(&ahcd->lock, flags); - temp = show_list(ahcd, buf->page, PAGE_SIZE, ahcd->ed_head); - spin_unlock_irqrestore(&ahcd->lock, flags); - - return temp; -} - - -#define DBG_SCHED_LIMIT 64 - -static ssize_t fill_periodic_buffer(struct debug_buffer *buf) -{ - struct admhcd *ahcd; - struct ed **seen, *ed; - unsigned long flags; - unsigned temp, size, seen_count; - char *next; - unsigned i; - - seen = kmalloc(DBG_SCHED_LIMIT * sizeof(*seen), GFP_ATOMIC); - if (!seen) - return 0; - seen_count = 0; - - ahcd = buf->ahcd; - next = buf->page; - size = PAGE_SIZE; - - temp = scnprintf(next, size, "size = %d\n", NUM_INTS); - size -= temp; - next += temp; - - /* dump a snapshot of the periodic schedule (and load) */ - spin_lock_irqsave(&ahcd->lock, flags); - for (i = 0; i < NUM_INTS; i++) { - ed = ahcd->periodic[i]; - if (!ed) - continue; - - temp = scnprintf(next, size, "%2d [%3d]:", i, ahcd->load[i]); - size -= temp; - next += temp; - - do { - temp = scnprintf(next, size, " ed%d/%p", - ed->interval, ed); - size -= temp; - next += temp; - for (temp = 0; temp < seen_count; temp++) { - if (seen[temp] == ed) - break; - } - - /* show more info the first time around */ - if (temp == seen_count) { - u32 info = hc32_to_cpu(ahcd, ed->hwINFO); - struct list_head *entry; - unsigned qlen = 0; - - /* qlen measured here in TDs, not urbs */ - list_for_each(entry, &ed->td_list) - qlen++; - temp = scnprintf(next, size, - " (%cs dev%d ep%d%s qlen %u" - " max %d %08x%s%s)", - (info & ED_SPEED_FULL) ? 'f' : 'l', - ED_FA_GET(info), - ED_EN_GET(info), - (info & ED_ISO) ? "iso" : "int", - qlen, - ED_MPS_GET(info), - info, - (info & ED_SKIP) ? " K" : "", - (ed->hwHeadP & - cpu_to_hc32(ahcd, ED_H)) ? - " H" : ""); - size -= temp; - next += temp; - - if (seen_count < DBG_SCHED_LIMIT) - seen[seen_count++] = ed; - - ed = ed->ed_next; - - } else { - /* we've seen it and what's after */ - temp = 0; - ed = NULL; - } - - } while (ed); - - temp = scnprintf(next, size, "\n"); - size -= temp; - next += temp; - } - spin_unlock_irqrestore(&ahcd->lock, flags); - kfree(seen); - - return PAGE_SIZE - size; -} - - -#undef DBG_SCHED_LIMIT - -static ssize_t fill_registers_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct admhcd *ahcd; - struct admhcd_regs __iomem *regs; - unsigned long flags; - unsigned temp, size; - char *next; - u32 rdata; - - ahcd = buf->ahcd; - hcd = admhc_to_hcd(ahcd); - regs = ahcd->regs; - next = buf->page; - size = PAGE_SIZE; - - spin_lock_irqsave(&ahcd->lock, flags); - - /* dump driver info, then registers in spec order */ - - admhc_dbg_sw(ahcd, &next, &size, - "bus %s, device %s\n" - "%s\n" - "%s\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc, - hcd_name); - - if (!HCD_HW_ACCESSIBLE(hcd)) { - size -= scnprintf(next, size, - "SUSPENDED (no register access)\n"); - goto done; - } - - admhc_dump_status(ahcd, &next, &size); - - /* other registers mostly affect frame timings */ - rdata = admhc_readl(ahcd, ®s->fminterval); - temp = scnprintf(next, size, - "fmintvl 0x%08x %sFSLDP=0x%04x FI=0x%04x\n", - rdata, (rdata & ADMHC_SFI_FIT) ? "FIT " : "", - (rdata >> ADMHC_SFI_FSLDP_SHIFT) & ADMHC_SFI_FSLDP_MASK, - rdata & ADMHC_SFI_FI_MASK); - size -= temp; - next += temp; - - rdata = admhc_readl(ahcd, ®s->fmnumber); - temp = scnprintf(next, size, "fmnumber 0x%08x %sFR=0x%04x FN=%04x\n", - rdata, (rdata & ADMHC_SFN_FRT) ? "FRT " : "", - (rdata >> ADMHC_SFN_FR_SHIFT) & ADMHC_SFN_FR_MASK, - rdata & ADMHC_SFN_FN_MASK); - size -= temp; - next += temp; - - /* TODO: use predefined bitmask */ - rdata = admhc_readl(ahcd, ®s->lsthresh); - temp = scnprintf(next, size, "lsthresh 0x%04x\n", - rdata & 0x3fff); - size -= temp; - next += temp; - - temp = scnprintf(next, size, "hub poll timer: %s\n", - admhcd_to_hcd(ahcd)->poll_rh ? "ON" : "OFF"); - size -= temp; - next += temp; - - /* roothub */ - admhc_dump_roothub(ahcd, 1, &next, &size); - -done: - spin_unlock_irqrestore(&ahcd->lock, flags); - return PAGE_SIZE - size; -} - - -static struct debug_buffer *alloc_buffer(struct admhcd *ahcd, - ssize_t (*fill_func)(struct debug_buffer *)) -{ - struct debug_buffer *buf; - - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); - - if (buf) { - buf->ahcd = ahcd; - buf->fill_func = fill_func; - mutex_init(&buf->mutex); - } - - return buf; -} - -static int fill_buffer(struct debug_buffer *buf) -{ - int ret = 0; - - if (!buf->page) - buf->page = (char *)get_zeroed_page(GFP_KERNEL); - - if (!buf->page) { - ret = -ENOMEM; - goto out; - } - - ret = buf->fill_func(buf); - - if (ret >= 0) { - buf->count = ret; - ret = 0; - } - -out: - return ret; -} - -static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) -{ - struct debug_buffer *buf = file->private_data; - int ret = 0; - - mutex_lock(&buf->mutex); - if (buf->count == 0) { - ret = fill_buffer(buf); - if (ret != 0) { - mutex_unlock(&buf->mutex); - goto out; - } - } - mutex_unlock(&buf->mutex); - - ret = simple_read_from_buffer(user_buf, len, offset, - buf->page, buf->count); - -out: - return ret; -} - -static int debug_close(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf = file->private_data; - - if (buf) { - if (buf->page) - free_page((unsigned long)buf->page); - kfree(buf); - } - - return 0; -} - -static int debug_async_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_periodic_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_periodic_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_registers_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_registers_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static inline void create_debug_files(struct admhcd *ahcd) -{ - struct usb_bus *bus = &admhcd_to_hcd(ahcd)->self; - - ahcd->debug_dir = debugfs_create_dir(bus->bus_name, admhc_debug_root); - if (!ahcd->debug_dir) - goto dir_error; - - ahcd->debug_async = debugfs_create_file("async", S_IRUGO, - ahcd->debug_dir, ahcd, - &debug_async_fops); - if (!ahcd->debug_async) - goto async_error; - - ahcd->debug_periodic = debugfs_create_file("periodic", S_IRUGO, - ahcd->debug_dir, ahcd, - &debug_periodic_fops); - if (!ahcd->debug_periodic) - goto periodic_error; - - ahcd->debug_registers = debugfs_create_file("registers", S_IRUGO, - ahcd->debug_dir, ahcd, - &debug_registers_fops); - if (!ahcd->debug_registers) - goto registers_error; - - admhc_dbg(ahcd, "created debug files\n"); - return; - -registers_error: - debugfs_remove(ahcd->debug_periodic); -periodic_error: - debugfs_remove(ahcd->debug_async); -async_error: - debugfs_remove(ahcd->debug_dir); -dir_error: - ahcd->debug_periodic = NULL; - ahcd->debug_async = NULL; - ahcd->debug_dir = NULL; -} - -static inline void remove_debug_files(struct admhcd *ahcd) -{ - debugfs_remove(ahcd->debug_registers); - debugfs_remove(ahcd->debug_periodic); - debugfs_remove(ahcd->debug_async); - debugfs_remove(ahcd->debug_dir); -} - -#endif - -/*-------------------------------------------------------------------------*/ diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c deleted file mode 100644 index 798fd22081..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-au1xxx.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * (C) Copyright 2002 Hewlett-Packard Company - * - * Written by Christopher Hoover - * Based on fragments of previous driver by Russell King et al. - * - * Modified for LH7A404 from ahcd-sa1111.c - * by Durgesh Pattamatta - * Modified for AMD Alchemy Au1xxx - * by Matt Porter - * - * 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 - -#ifdef DEBUG -#define HCD_DBG(f, a...) printk(KERN_DEBUG "%s: " f, hcd_name, ## a) -#else -#define HCD_DBG(f, a...) do {} while (0) -#endif -#define HCD_ERR(f, a...) printk(KERN_ERR "%s: " f, hcd_name, ## a) -#define HCD_INFO(f, a...) printk(KERN_INFO "%s: " f, hcd_name, ## a) - -/*-------------------------------------------------------------------------*/ - -static int admhc_adm5120_probe(const struct hc_driver *driver, - struct platform_device *dev) -{ - int retval; - struct usb_hcd *hcd; - int irq; - struct resource *regs; - - /* sanity checks */ - regs = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (!regs) { - HCD_DBG("no IOMEM resource found\n"); - return -ENODEV; - } - - irq = platform_get_irq(dev, 0); - if (irq < 0) { - HCD_DBG("no IRQ resource found\n"); - return -ENODEV; - } - - hcd = usb_create_hcd(driver, &dev->dev, "ADM5120"); - if (!hcd) - return -ENOMEM; - - hcd->rsrc_start = regs->start; - hcd->rsrc_len = regs->end - regs->start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - HCD_DBG("request_mem_region failed\n"); - retval = -EBUSY; - goto err_dev; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) { - HCD_DBG("ioremap failed\n"); - retval = -ENOMEM; - goto err_mem; - } - - admhc_hcd_init(hcd_to_admhcd(hcd)); - - retval = usb_add_hcd(hcd, irq, 0); - if (retval) - goto err_io; - - return 0; - -err_io: - iounmap(hcd->regs); -err_mem: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_dev: - usb_put_hcd(hcd); - return retval; -} - - -/* may be called without controller electrically present */ -/* may be called with controller, bus, and devices active */ - -static void admhc_adm5120_remove(struct usb_hcd *hcd, - struct platform_device *dev) -{ - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -static int admhc_adm5120_start(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - int ret; - - ret = admhc_init(ahcd); - if (ret < 0) { - HCD_ERR("unable to init %s\n", hcd->self.bus_name); - goto err; - } - - ret = admhc_run(ahcd); - if (ret < 0) { - HCD_ERR("unable to run %s\n", hcd->self.bus_name); - goto err_stop; - } - - return 0; - -err_stop: - admhc_stop(hcd); -err: - return ret; -} - -static const struct hc_driver adm5120_hc_driver = { - .description = hcd_name, - .product_desc = "ADM5120 built-in USB 1.1 Host Controller", - .hcd_priv_size = sizeof(struct admhcd), - - /* - * generic hardware linkage - */ - .irq = admhc_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .start = admhc_adm5120_start, - .stop = admhc_stop, - .shutdown = admhc_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = admhc_urb_enqueue, - .urb_dequeue = admhc_urb_dequeue, - .endpoint_disable = admhc_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = admhc_get_frame_number, - - /* - * root hub support - */ - .hub_status_data = admhc_hub_status_data, - .hub_control = admhc_hub_control, -#ifdef CONFIG_PM - .bus_suspend = admhc_bus_suspend, - .bus_resume = admhc_bus_resume, -#endif - .start_port_reset = admhc_start_port_reset, -}; - -static int usb_hcd_adm5120_probe(struct platform_device *pdev) -{ - int ret; - - ret = admhc_adm5120_probe(&adm5120_hc_driver, pdev); - - return ret; -} - -static int usb_hcd_adm5120_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - admhc_adm5120_remove(hcd, pdev); - - return 0; -} - -#ifdef CONFIG_PM -/* TODO */ -static int usb_hcd_adm5120_suspend(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - return 0; -} - -static int usb_hcd_adm5120_resume(struct platform_device *dev) -{ - struct usb_hcd *hcd = platform_get_drvdata(dev); - - return 0; -} -#else -#define usb_hcd_adm5120_suspend NULL -#define usb_hcd_adm5120_resume NULL -#endif /* CONFIG_PM */ - -static struct platform_driver usb_hcd_adm5120_driver = { - .probe = usb_hcd_adm5120_probe, - .remove = usb_hcd_adm5120_remove, - .shutdown = usb_hcd_platform_shutdown, - .suspend = usb_hcd_adm5120_suspend, - .resume = usb_hcd_adm5120_resume, - .driver = { - .name = "adm5120-hcd", - .owner = THIS_MODULE, - }, -}; - diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c deleted file mode 100644 index f721ec1ff8..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c +++ /dev/null @@ -1,843 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-hcd.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2004 David Brownell - * - * [ Initialisation is based on Linus' ] - * [ uhci code and gregs ahcd fragments ] - * [ (C) Copyright 1999 Linus Torvalds ] - * [ (C) Copyright 1999 Gregory P. Smith] - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define DRIVER_VERSION "0.27.0" -#define DRIVER_AUTHOR "Gabor Juhos " -#define DRIVER_DESC "ADMtek USB 1.1 Host Controller Driver" - -/*-------------------------------------------------------------------------*/ - -#undef ADMHC_VERBOSE_DEBUG /* not always helpful */ - -/* For initializing controller (mask in an HCFS mode too) */ -#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR - -#define ADMHC_INTR_INIT \ - (ADMHC_INTR_MIE | ADMHC_INTR_INSM | ADMHC_INTR_FATI \ - | ADMHC_INTR_RESI | ADMHC_INTR_TDC | ADMHC_INTR_BABI) - -/*-------------------------------------------------------------------------*/ - -static const char hcd_name[] = "admhc-hcd"; - -#define STATECHANGE_DELAY msecs_to_jiffies(300) - -#include "adm5120.h" - -static void admhc_dump(struct admhcd *ahcd, int verbose); -static int admhc_init(struct admhcd *ahcd); -static void admhc_stop(struct usb_hcd *hcd); - -#include "adm5120-dbg.c" -#include "adm5120-mem.c" -#include "adm5120-pm.c" -#include "adm5120-hub.c" -#include "adm5120-q.c" - -/*-------------------------------------------------------------------------*/ - -/* - * queue up an urb for anything except the root hub - */ -static int admhc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, - gfp_t mem_flags) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - struct ed *ed; - struct urb_priv *urb_priv; - unsigned int pipe = urb->pipe; - int td_cnt = 0; - unsigned long flags; - int ret = 0; - -#ifdef ADMHC_VERBOSE_DEBUG - spin_lock_irqsave(&ahcd->lock, flags); - urb_print(ahcd, urb, "ENQEUE", usb_pipein(pipe), -EINPROGRESS); - spin_unlock_irqrestore(&ahcd->lock, flags); -#endif - - /* every endpoint has an ed, locate and maybe (re)initialize it */ - ed = ed_get(ahcd, urb->ep, urb->dev, pipe, urb->interval); - if (!ed) - return -ENOMEM; - - /* for the private part of the URB we need the number of TDs */ - switch (ed->type) { - case PIPE_CONTROL: - if (urb->transfer_buffer_length > TD_DATALEN_MAX) - /* td_submit_urb() doesn't yet handle these */ - return -EMSGSIZE; - - /* 1 TD for setup, 1 for ACK, plus ... */ - td_cnt = 2; - /* FALLTHROUGH */ - case PIPE_BULK: - /* one TD for every 4096 Bytes (can be up to 8K) */ - td_cnt += urb->transfer_buffer_length / TD_DATALEN_MAX; - /* ... and for any remaining bytes ... */ - if ((urb->transfer_buffer_length % TD_DATALEN_MAX) != 0) - td_cnt++; - /* ... and maybe a zero length packet to wrap it up */ - if (td_cnt == 0) - td_cnt++; - else if ((urb->transfer_flags & URB_ZERO_PACKET) != 0 - && (urb->transfer_buffer_length - % usb_maxpacket(urb->dev, pipe, - usb_pipeout(pipe))) == 0) - td_cnt++; - break; - case PIPE_INTERRUPT: - /* - * for Interrupt IN/OUT transactions, each ED contains - * only 1 TD. - * TODO: check transfer_buffer_length? - */ - td_cnt = 1; - break; - case PIPE_ISOCHRONOUS: - /* number of packets from URB */ - td_cnt = urb->number_of_packets; - break; - } - - urb_priv = urb_priv_alloc(ahcd, td_cnt, mem_flags); - if (!urb_priv) - return -ENOMEM; - - urb_priv->ed = ed; - - spin_lock_irqsave(&ahcd->lock, flags); - /* don't submit to a dead HC */ - if (!HCD_HW_ACCESSIBLE(hcd)) { - ret = -ENODEV; - goto fail; - } - if (!HC_IS_RUNNING(hcd->state)) { - ret = -ENODEV; - goto fail; - } - - ret = usb_hcd_link_urb_to_ep(hcd, urb); - if (ret) - goto fail; - - /* schedule the ed if needed */ - if (ed->state == ED_IDLE) { - ret = ed_schedule(ahcd, ed); - if (ret < 0) { - usb_hcd_unlink_urb_from_ep(hcd, urb); - goto fail; - } - if (ed->type == PIPE_ISOCHRONOUS) { - u16 frame = admhc_frame_no(ahcd); - - /* delay a few frames before the first TD */ - frame += max_t (u16, 8, ed->interval); - frame &= ~(ed->interval - 1); - frame |= ed->branch; - urb->start_frame = frame; - - /* yes, only URB_ISO_ASAP is supported, and - * urb->start_frame is never used as input. - */ - } - } else if (ed->type == PIPE_ISOCHRONOUS) - urb->start_frame = ed->last_iso + ed->interval; - - /* fill the TDs and link them to the ed; and - * enable that part of the schedule, if needed - * and update count of queued periodic urbs - */ - urb->hcpriv = urb_priv; - td_submit_urb(ahcd, urb); - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "admhc_urb_enqueue", urb_priv->ed, 1); -#endif - -fail: - if (ret) - urb_priv_free(ahcd, urb_priv); - - spin_unlock_irqrestore(&ahcd->lock, flags); - return ret; -} - -/* - * decouple the URB from the HC queues (TDs, urb_priv); - * reporting is always done - * asynchronously, and we might be dealing with an urb that's - * partially transferred, or an ED with other urbs being unlinked. - */ -static int admhc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, - int status) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - unsigned long flags; - int ret; - - spin_lock_irqsave(&ahcd->lock, flags); - -#ifdef ADMHC_VERBOSE_DEBUG - urb_print(ahcd, urb, "DEQUEUE", 1, status); -#endif - ret = usb_hcd_check_unlink_urb(hcd, urb, status); - if (ret) { - /* Do nothing */ - ; - } else if (HC_IS_RUNNING(hcd->state)) { - struct urb_priv *urb_priv; - - /* Unless an IRQ completed the unlink while it was being - * handed to us, flag it for unlink and giveback, and force - * some upcoming INTR_SF to call finish_unlinks() - */ - urb_priv = urb->hcpriv; - if (urb_priv) { - if (urb_priv->ed->state == ED_OPER) - start_ed_unlink(ahcd, urb_priv->ed); - } - } else { - /* - * with HC dead, we won't respect hc queue pointers - * any more ... just clean up every urb's memory. - */ - if (urb->hcpriv) - finish_urb(ahcd, urb, status); - } - spin_unlock_irqrestore(&ahcd->lock, flags); - - return ret; -} - -/*-------------------------------------------------------------------------*/ - -/* frees config/altsetting state for endpoints, - * including ED memory, dummy TD, and bulk/intr data toggle - */ - -static void admhc_endpoint_disable(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - unsigned long flags; - struct ed *ed = ep->hcpriv; - unsigned limit = 1000; - - /* ASSERT: any requests/urbs are being unlinked */ - /* ASSERT: nobody can be submitting urbs for this any more */ - - if (!ed) - return; - -#ifdef ADMHC_VERBOSE_DEBUG - spin_lock_irqsave(&ahcd->lock, flags); - admhc_dump_ed(ahcd, "EP-DISABLE", ed, 1); - spin_unlock_irqrestore(&ahcd->lock, flags); -#endif - -rescan: - spin_lock_irqsave(&ahcd->lock, flags); - - if (!HC_IS_RUNNING(hcd->state)) { -sanitize: - ed->state = ED_IDLE; - finish_unlinks(ahcd, 0); - } - - switch (ed->state) { - case ED_UNLINK: /* wait for hw to finish? */ - /* major IRQ delivery trouble loses INTR_SOFI too... */ - if (limit-- == 0) { - admhc_warn(ahcd, "IRQ INTR_SOFI lossage\n"); - goto sanitize; - } - spin_unlock_irqrestore(&ahcd->lock, flags); - schedule_timeout_uninterruptible(1); - goto rescan; - case ED_IDLE: /* fully unlinked */ - if (list_empty(&ed->td_list)) { - td_free(ahcd, ed->dummy); - ed_free(ahcd, ed); - break; - } - /* else FALL THROUGH */ - default: - /* caller was supposed to have unlinked any requests; - * that's not our job. can't recover; must leak ed. - */ - admhc_err(ahcd, "leak ed %p (#%02x) state %d%s\n", - ed, ep->desc.bEndpointAddress, ed->state, - list_empty(&ed->td_list) ? "" : " (has tds)"); - td_free(ahcd, ed->dummy); - break; - } - - ep->hcpriv = NULL; - - spin_unlock_irqrestore(&ahcd->lock, flags); -} - -static int admhc_get_frame_number(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - - return admhc_frame_no(ahcd); -} - -static void admhc_usb_reset(struct admhcd *ahcd) -{ -#if 0 - ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); - ahcd->hc_control &= OHCI_CTRL_RWC; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->regs->control); -#else - /* FIXME */ - ahcd->host_control = ADMHC_BUSS_RESET; - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); -#endif -} - -/* admhc_shutdown forcibly disables IRQs and DMA, helping kexec and - * other cases where the next software may expect clean state from the - * "firmware". this is bus-neutral, unlike shutdown() methods. - */ -static void -admhc_shutdown(struct usb_hcd *hcd) -{ - struct admhcd *ahcd; - - ahcd = hcd_to_admhcd(hcd); - admhc_intr_disable(ahcd, ADMHC_INTR_MIE); - admhc_dma_disable(ahcd); - admhc_usb_reset(ahcd); - /* flush the writes */ - admhc_writel_flush(ahcd); -} - -/*-------------------------------------------------------------------------* - * HC functions - *-------------------------------------------------------------------------*/ - -static void admhc_eds_cleanup(struct admhcd *ahcd) -{ - if (ahcd->ed_tails[PIPE_INTERRUPT]) { - ed_free(ahcd, ahcd->ed_tails[PIPE_INTERRUPT]); - ahcd->ed_tails[PIPE_INTERRUPT] = NULL; - } - - if (ahcd->ed_tails[PIPE_ISOCHRONOUS]) { - ed_free(ahcd, ahcd->ed_tails[PIPE_ISOCHRONOUS]); - ahcd->ed_tails[PIPE_ISOCHRONOUS] = NULL; - } - - if (ahcd->ed_tails[PIPE_CONTROL]) { - ed_free(ahcd, ahcd->ed_tails[PIPE_CONTROL]); - ahcd->ed_tails[PIPE_CONTROL] = NULL; - } - - if (ahcd->ed_tails[PIPE_BULK]) { - ed_free(ahcd, ahcd->ed_tails[PIPE_BULK]); - ahcd->ed_tails[PIPE_BULK] = NULL; - } - - ahcd->ed_head = NULL; -} - -#define ED_DUMMY_INFO (ED_SPEED_FULL | ED_SKIP) - -static int admhc_eds_init(struct admhcd *ahcd) -{ - struct ed *ed; - - ed = ed_create(ahcd, PIPE_INTERRUPT, ED_DUMMY_INFO); - if (!ed) - goto err; - - ahcd->ed_tails[PIPE_INTERRUPT] = ed; - - ed = ed_create(ahcd, PIPE_ISOCHRONOUS, ED_DUMMY_INFO); - if (!ed) - goto err; - - ahcd->ed_tails[PIPE_ISOCHRONOUS] = ed; - ed->ed_prev = ahcd->ed_tails[PIPE_INTERRUPT]; - ahcd->ed_tails[PIPE_INTERRUPT]->ed_next = ed; - ahcd->ed_tails[PIPE_INTERRUPT]->hwNextED = cpu_to_hc32(ahcd, ed->dma); - - ed = ed_create(ahcd, PIPE_CONTROL, ED_DUMMY_INFO); - if (!ed) - goto err; - - ahcd->ed_tails[PIPE_CONTROL] = ed; - ed->ed_prev = ahcd->ed_tails[PIPE_ISOCHRONOUS]; - ahcd->ed_tails[PIPE_ISOCHRONOUS]->ed_next = ed; - ahcd->ed_tails[PIPE_ISOCHRONOUS]->hwNextED = cpu_to_hc32(ahcd, ed->dma); - - ed = ed_create(ahcd, PIPE_BULK, ED_DUMMY_INFO); - if (!ed) - goto err; - - ahcd->ed_tails[PIPE_BULK] = ed; - ed->ed_prev = ahcd->ed_tails[PIPE_CONTROL]; - ahcd->ed_tails[PIPE_CONTROL]->ed_next = ed; - ahcd->ed_tails[PIPE_CONTROL]->hwNextED = cpu_to_hc32(ahcd, ed->dma); - - ahcd->ed_head = ahcd->ed_tails[PIPE_INTERRUPT]; - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "ed intr", ahcd->ed_tails[PIPE_INTERRUPT], 1); - admhc_dump_ed(ahcd, "ed isoc", ahcd->ed_tails[PIPE_ISOCHRONOUS], 1); - admhc_dump_ed(ahcd, "ed ctrl", ahcd->ed_tails[PIPE_CONTROL], 1); - admhc_dump_ed(ahcd, "ed bulk", ahcd->ed_tails[PIPE_BULK], 1); -#endif - - return 0; - -err: - admhc_eds_cleanup(ahcd); - return -ENOMEM; -} - -/* init memory, and kick BIOS/SMM off */ - -static int admhc_init(struct admhcd *ahcd) -{ - struct usb_hcd *hcd = admhcd_to_hcd(ahcd); - int ret; - - admhc_disable(ahcd); - ahcd->regs = hcd->regs; - - /* Disable HC interrupts */ - admhc_intr_disable(ahcd, ADMHC_INTR_MIE); - - /* Read the number of ports unless overridden */ - if (ahcd->num_ports == 0) - ahcd->num_ports = admhc_read_rhdesc(ahcd) & ADMHC_RH_NUMP; - - ret = admhc_mem_init(ahcd); - if (ret) - goto err; - - /* init dummy endpoints */ - ret = admhc_eds_init(ahcd); - if (ret) - goto err; - - create_debug_files(ahcd); - - return 0; - -err: - admhc_stop(hcd); - return ret; -} - -/*-------------------------------------------------------------------------*/ - -/* Start an OHCI controller, set the BUS operational - * resets USB and controller - * enable interrupts - */ -static int admhc_run(struct admhcd *ahcd) -{ - u32 val; - int first = ahcd->fminterval == 0; - struct usb_hcd *hcd = admhcd_to_hcd(ahcd); - - admhc_disable(ahcd); - - /* boot firmware should have set this up (5.1.1.3.1) */ - if (first) { - val = admhc_readl(ahcd, &ahcd->regs->fminterval); - ahcd->fminterval = val & ADMHC_SFI_FI_MASK; - if (ahcd->fminterval != FI) - admhc_dbg(ahcd, "fminterval delta %d\n", - ahcd->fminterval - FI); - ahcd->fminterval |= - (FSLDP(ahcd->fminterval) << ADMHC_SFI_FSLDP_SHIFT); - /* also: power/overcurrent flags in rhdesc */ - } - -#if 0 /* TODO: not applicable */ - /* Reset USB nearly "by the book". RemoteWakeupConnected has - * to be checked in case boot firmware (BIOS/SMM/...) has set up - * wakeup in a way the bus isn't aware of (e.g., legacy PCI PM). - * If the bus glue detected wakeup capability then it should - * already be enabled; if so we'll just enable it again. - */ - if ((ahcd->hc_control & OHCI_CTRL_RWC) != 0) - device_set_wakeup_capable(hcd->self.controller, 1); -#endif - - switch (ahcd->host_control & ADMHC_HC_BUSS) { - case ADMHC_BUSS_OPER: - val = 0; - break; - case ADMHC_BUSS_SUSPEND: - /* FALLTHROUGH ? */ - case ADMHC_BUSS_RESUME: - ahcd->host_control = ADMHC_BUSS_RESUME; - val = 10 /* msec wait */; - break; - /* case ADMHC_BUSS_RESET: */ - default: - ahcd->host_control = ADMHC_BUSS_RESET; - val = 50 /* msec wait */; - break; - } - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); - - /* flush the writes */ - admhc_writel_flush(ahcd); - - msleep(val); - val = admhc_read_rhdesc(ahcd); - if (!(val & ADMHC_RH_NPS)) { - /* power down each port */ - for (val = 0; val < ahcd->num_ports; val++) - admhc_write_portstatus(ahcd, val, ADMHC_PS_CPP); - } - /* flush those writes */ - admhc_writel_flush(ahcd); - - /* 2msec timelimit here means no irqs/preempt */ - spin_lock_irq(&ahcd->lock); - - admhc_writel(ahcd, ADMHC_CTRL_SR, &ahcd->regs->gencontrol); - val = 30; /* ... allow extra time */ - while ((admhc_readl(ahcd, &ahcd->regs->gencontrol) & ADMHC_CTRL_SR) != 0) { - if (--val == 0) { - spin_unlock_irq(&ahcd->lock); - admhc_err(ahcd, "USB HC reset timed out!\n"); - return -1; - } - udelay(1); - } - - /* enable HOST mode, before access any host specific register */ - admhc_writel(ahcd, ADMHC_CTRL_UHFE, &ahcd->regs->gencontrol); - - /* Tell the controller where the descriptor list is */ - admhc_writel(ahcd, (u32)ahcd->ed_head->dma, &ahcd->regs->hosthead); - - periodic_reinit(ahcd); - - /* use rhsc irqs after khubd is fully initialized */ - set_bit(HCD_FLAG_POLL_RH, &hcd->flags); - hcd->uses_new_polling = 1; - -#if 0 - /* wake on ConnectStatusChange, matching external hubs */ - admhc_writel(ahcd, RH_HS_DRWE, &ahcd->regs->roothub.status); -#else - /* FIXME roothub_write_status (ahcd, ADMHC_RH_DRWE); */ -#endif - - /* Choose the interrupts we care about now, others later on demand */ - admhc_intr_ack(ahcd, ~0); - admhc_intr_enable(ahcd, ADMHC_INTR_INIT); - - admhc_writel(ahcd, ADMHC_RH_NPS | ADMHC_RH_LPSC, &ahcd->regs->rhdesc); - - /* flush those writes */ - admhc_writel_flush(ahcd); - - /* start controller operations */ - ahcd->host_control = ADMHC_BUSS_OPER; - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); - - val = 20; - while ((admhc_readl(ahcd, &ahcd->regs->host_control) - & ADMHC_HC_BUSS) != ADMHC_BUSS_OPER) { - if (--val == 0) { - spin_unlock_irq(&ahcd->lock); - admhc_err(ahcd, "unable to setup operational mode!\n"); - return -1; - } - mdelay(1); - } - - hcd->state = HC_STATE_RUNNING; - - ahcd->next_statechange = jiffies + STATECHANGE_DELAY; - -#if 0 - /* FIXME: enabling DMA is always failed here for an unknown reason */ - admhc_dma_enable(ahcd); - - val = 200; - while ((admhc_readl(ahcd, &ahcd->regs->host_control) - & ADMHC_HC_DMAE) != ADMHC_HC_DMAE) { - if (--val == 0) { - spin_unlock_irq(&ahcd->lock); - admhc_err(ahcd, "unable to enable DMA!\n"); - admhc_dump(ahcd, 1); - return -1; - } - mdelay(1); - } - -#endif - - spin_unlock_irq(&ahcd->lock); - - mdelay(ADMHC_POTPGT); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -/* an interrupt happens */ - -static irqreturn_t admhc_irq(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - struct admhcd_regs __iomem *regs = ahcd->regs; - u32 ints; - - ints = admhc_readl(ahcd, ®s->int_status); - if ((ints & ADMHC_INTR_INTA) == 0) { - /* no unmasked interrupt status is set */ - return IRQ_NONE; - } - - ints &= admhc_readl(ahcd, ®s->int_enable); - - if (ints & ADMHC_INTR_FATI) { - /* e.g. due to PCI Master/Target Abort */ - admhc_disable(ahcd); - admhc_err(ahcd, "Fatal Error, controller disabled\n"); - admhc_dump(ahcd, 1); - admhc_usb_reset(ahcd); - } - - if (ints & ADMHC_INTR_BABI) { - admhc_intr_disable(ahcd, ADMHC_INTR_BABI); - admhc_intr_ack(ahcd, ADMHC_INTR_BABI); - admhc_err(ahcd, "Babble Detected\n"); - } - - if (ints & ADMHC_INTR_INSM) { - admhc_vdbg(ahcd, "Root Hub Status Change\n"); - ahcd->next_statechange = jiffies + STATECHANGE_DELAY; - admhc_intr_ack(ahcd, ADMHC_INTR_RESI | ADMHC_INTR_INSM); - - /* NOTE: Vendors didn't always make the same implementation - * choices for RHSC. Many followed the spec; RHSC triggers - * on an edge, like setting and maybe clearing a port status - * change bit. With others it's level-triggered, active - * until khubd clears all the port status change bits. We'll - * always disable it here and rely on polling until khubd - * re-enables it. - */ - admhc_intr_disable(ahcd, ADMHC_INTR_INSM); - usb_hcd_poll_rh_status(hcd); - } else if (ints & ADMHC_INTR_RESI) { - /* For connect and disconnect events, we expect the controller - * to turn on RHSC along with RD. But for remote wakeup events - * this might not happen. - */ - admhc_vdbg(ahcd, "Resume Detect\n"); - admhc_intr_ack(ahcd, ADMHC_INTR_RESI); - set_bit(HCD_FLAG_POLL_RH, &hcd->flags); - if (ahcd->autostop) { - spin_lock(&ahcd->lock); - admhc_rh_resume(ahcd); - spin_unlock(&ahcd->lock); - } else - usb_hcd_resume_root_hub(hcd); - } - - if (ints & ADMHC_INTR_TDC) { - admhc_vdbg(ahcd, "Transfer Descriptor Complete\n"); - admhc_intr_ack(ahcd, ADMHC_INTR_TDC); - if (HC_IS_RUNNING(hcd->state)) - admhc_intr_disable(ahcd, ADMHC_INTR_TDC); - spin_lock(&ahcd->lock); - admhc_td_complete(ahcd); - spin_unlock(&ahcd->lock); - if (HC_IS_RUNNING(hcd->state)) - admhc_intr_enable(ahcd, ADMHC_INTR_TDC); - } - - if (ints & ADMHC_INTR_SO) { - /* could track INTR_SO to reduce available PCI/... bandwidth */ - admhc_vdbg(ahcd, "Schedule Overrun\n"); - } - -#if 1 - spin_lock(&ahcd->lock); - if (ahcd->ed_rm_list) - finish_unlinks(ahcd, admhc_frame_no(ahcd)); - - if ((ints & ADMHC_INTR_SOFI) != 0 && !ahcd->ed_rm_list - && HC_IS_RUNNING(hcd->state)) - admhc_intr_disable(ahcd, ADMHC_INTR_SOFI); - spin_unlock(&ahcd->lock); -#else - if (ints & ADMHC_INTR_SOFI) { - admhc_vdbg(ahcd, "Start Of Frame\n"); - spin_lock(&ahcd->lock); - - /* handle any pending ED removes */ - finish_unlinks(ahcd, admhc_frameno(ahcd)); - - /* leaving INTR_SOFI enabled when there's still unlinking - * to be done in the (next frame). - */ - if ((ahcd->ed_rm_list == NULL) || - HC_IS_RUNNING(hcd->state) == 0) - /* - * disable INTR_SOFI if there are no unlinking to be - * done (in the next frame) - */ - admhc_intr_disable(ahcd, ADMHC_INTR_SOFI); - - spin_unlock(&ahcd->lock); - } -#endif - - if (HC_IS_RUNNING(hcd->state)) { - admhc_intr_ack(ahcd, ints); - admhc_intr_enable(ahcd, ADMHC_INTR_MIE); - admhc_writel_flush(ahcd); - } - - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -static void admhc_stop(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - - admhc_dump(ahcd, 1); - - flush_scheduled_work(); - - admhc_usb_reset(ahcd); - admhc_intr_disable(ahcd, ADMHC_INTR_MIE); - - free_irq(hcd->irq, hcd); - hcd->irq = -1; - - remove_debug_files(ahcd); - admhc_eds_cleanup(ahcd); - admhc_mem_cleanup(ahcd); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_ADM5120 -#include "adm5120-drv.c" -#define PLATFORM_DRIVER usb_hcd_adm5120_driver -#endif - -#if !defined(PLATFORM_DRIVER) -#error "missing bus glue for admhc-hcd" -#endif - -#define DRIVER_INFO DRIVER_DESC " version " DRIVER_VERSION - -static int __init admhc_hcd_mod_init(void) -{ - int ret = 0; - - if (usb_disabled()) - return -ENODEV; - - pr_info("%s: " DRIVER_INFO "\n", hcd_name); - pr_info("%s: block sizes: ed %Zd td %Zd\n", hcd_name, - sizeof(struct ed), sizeof(struct td)); - set_bit(USB_OHCI_LOADED, &usb_hcds_loaded); - -#ifdef DEBUG - admhc_debug_root = debugfs_create_dir("admhc", usb_debug_root); - if (!admhc_debug_root) { - ret = -ENOENT; - goto error_debug; - } -#endif - -#ifdef PLATFORM_DRIVER - ret = platform_driver_register(&PLATFORM_DRIVER); - if (ret < 0) - goto error_platform; -#endif - - return ret; - -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -error_platform: -#endif - -#ifdef DEBUG - debugfs_remove(admhc_debug_root); - admhc_debug_root = NULL; -error_debug: -#endif - clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); - return ret; -} -module_init(admhc_hcd_mod_init); - -static void __exit admhc_hcd_mod_exit(void) -{ - platform_driver_unregister(&PLATFORM_DRIVER); -#ifdef DEBUG - debugfs_remove(admhc_debug_root); -#endif - clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded); -} -module_exit(admhc_hcd_mod_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_INFO); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c deleted file mode 100644 index 8cabaf902d..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-hub.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2004 David Brownell - * - * 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. - * - */ - -/*-------------------------------------------------------------------------*/ - -/* - * ADM5120 Root Hub ... the nonsharable stuff - */ - -#define dbg_port(hc, label, num, value) \ - admhc_dbg(hc, \ - "%s port%d " \ - "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ - label, num, value, \ - (value & ADMHC_PS_PRSC) ? " PRSC" : "", \ - (value & ADMHC_PS_OCIC) ? " OCIC" : "", \ - (value & ADMHC_PS_PSSC) ? " PSSC" : "", \ - (value & ADMHC_PS_PESC) ? " PESC" : "", \ - (value & ADMHC_PS_CSC) ? " CSC" : "", \ - \ - (value & ADMHC_PS_LSDA) ? " LSDA" : "", \ - (value & ADMHC_PS_PPS) ? " PPS" : "", \ - (value & ADMHC_PS_PRS) ? " PRS" : "", \ - (value & ADMHC_PS_POCI) ? " POCI" : "", \ - (value & ADMHC_PS_PSS) ? " PSS" : "", \ - \ - (value & ADMHC_PS_PES) ? " PES" : "", \ - (value & ADMHC_PS_CCS) ? " CCS" : "" \ - ); - -#define dbg_port_write(hc, label, num, value) \ - admhc_dbg(hc, \ - "%s port%d " \ - "= 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", \ - label, num, value, \ - (value & ADMHC_PS_PRSC) ? " PRSC" : "", \ - (value & ADMHC_PS_OCIC) ? " OCIC" : "", \ - (value & ADMHC_PS_PSSC) ? " PSSC" : "", \ - (value & ADMHC_PS_PESC) ? " PESC" : "", \ - (value & ADMHC_PS_CSC) ? " CSC" : "", \ - \ - (value & ADMHC_PS_CPP) ? " CPP" : "", \ - (value & ADMHC_PS_SPP) ? " SPP" : "", \ - (value & ADMHC_PS_SPR) ? " SPR" : "", \ - (value & ADMHC_PS_CPS) ? " CPS" : "", \ - (value & ADMHC_PS_SPS) ? " SPS" : "", \ - \ - (value & ADMHC_PS_SPE) ? " SPE" : "", \ - (value & ADMHC_PS_CPE) ? " CPE" : "" \ - ); - -/*-------------------------------------------------------------------------*/ - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -admhc_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - int i, changed = 0, length = 1; - int any_connected = 0; - unsigned long flags; - u32 status; - - spin_lock_irqsave(&ahcd->lock, flags); - if (!HCD_HW_ACCESSIBLE(hcd)) - goto done; - - /* init status */ - status = admhc_read_rhdesc(ahcd); - if (status & (ADMHC_RH_LPSC | ADMHC_RH_OCIC)) - buf[0] = changed = 1; - else - buf[0] = 0; - if (ahcd->num_ports > 7) { - buf[1] = 0; - length++; - } - - /* look at each port */ - for (i = 0; i < ahcd->num_ports; i++) { - status = admhc_read_portstatus(ahcd, i); - - /* can't autostop if ports are connected */ - any_connected |= (status & ADMHC_PS_CCS); - - if (status & (ADMHC_PS_CSC | ADMHC_PS_PESC | ADMHC_PS_PSSC - | ADMHC_PS_OCIC | ADMHC_PS_PRSC)) { - changed = 1; - if (i < 7) - buf[0] |= 1 << (i + 1); - else - buf[1] |= 1 << (i - 7); - } - } - - if (admhc_root_hub_state_changes(ahcd, changed, - any_connected)) - set_bit(HCD_FLAG_POLL_RH, &hcd->flags); - else - clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); - -done: - spin_unlock_irqrestore(&ahcd->lock, flags); - - return changed ? length : 0; -} - -/*-------------------------------------------------------------------------*/ - -static int admhc_get_hub_descriptor(struct admhcd *ahcd, char *buf) -{ - struct usb_hub_descriptor *desc = (struct usb_hub_descriptor *)buf; - u32 rh = admhc_read_rhdesc(ahcd); - u16 temp; - - desc->bDescriptorType = USB_DT_HUB; /* Hub-descriptor */ - desc->bPwrOn2PwrGood = ADMHC_POTPGT/2; /* use default value */ - desc->bHubContrCurrent = 0x00; /* 0mA */ - - desc->bNbrPorts = ahcd->num_ports; - temp = 1 + (ahcd->num_ports / 8); - desc->bDescLength = USB_DT_HUB_NONVAR_SIZE + 2 * temp; - - /* FIXME */ - temp = 0; - if (rh & ADMHC_RH_NPS) /* no power switching? */ - temp |= 0x0002; - if (rh & ADMHC_RH_PSM) /* per-port power switching? */ - temp |= 0x0001; - if (rh & ADMHC_RH_NOCP) /* no overcurrent reporting? */ - temp |= 0x0010; - else if (rh & ADMHC_RH_OCPM) /* per-port overcurrent reporting? */ - temp |= 0x0008; - desc->wHubCharacteristics = (__force __u16)cpu_to_hc16(ahcd, temp); - - /* ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - desc->u.hs.DeviceRemovable[0] = 0; - desc->u.hs.DeviceRemovable[0] = ~0; - - return 0; -} - -static int admhc_get_hub_status(struct admhcd *ahcd, char *buf) -{ - struct usb_hub_status *hs = (struct usb_hub_status *)buf; - u32 t = admhc_read_rhdesc(ahcd); - u16 status, change; - - status = 0; - status |= (t & ADMHC_RH_LPS) ? HUB_STATUS_LOCAL_POWER : 0; - status |= (t & ADMHC_RH_OCI) ? HUB_STATUS_OVERCURRENT : 0; - - change = 0; - change |= (t & ADMHC_RH_LPSC) ? HUB_CHANGE_LOCAL_POWER : 0; - change |= (t & ADMHC_RH_OCIC) ? HUB_CHANGE_OVERCURRENT : 0; - - hs->wHubStatus = (__force __u16)cpu_to_hc16(ahcd, status); - hs->wHubChange = (__force __u16)cpu_to_hc16(ahcd, change); - - return 0; -} - -static int admhc_get_port_status(struct admhcd *ahcd, unsigned port, char *buf) -{ - struct usb_port_status *ps = (struct usb_port_status *)buf; - u32 t = admhc_read_portstatus(ahcd, port); - u16 status, change; - - status = 0; - status |= (t & ADMHC_PS_CCS) ? USB_PORT_STAT_CONNECTION : 0; - status |= (t & ADMHC_PS_PES) ? USB_PORT_STAT_ENABLE : 0; - status |= (t & ADMHC_PS_PSS) ? USB_PORT_STAT_SUSPEND : 0; - status |= (t & ADMHC_PS_POCI) ? USB_PORT_STAT_OVERCURRENT : 0; - status |= (t & ADMHC_PS_PRS) ? USB_PORT_STAT_RESET : 0; - status |= (t & ADMHC_PS_PPS) ? USB_PORT_STAT_POWER : 0; - status |= (t & ADMHC_PS_LSDA) ? USB_PORT_STAT_LOW_SPEED : 0; - - change = 0; - change |= (t & ADMHC_PS_CSC) ? USB_PORT_STAT_C_CONNECTION : 0; - change |= (t & ADMHC_PS_PESC) ? USB_PORT_STAT_C_ENABLE : 0; - change |= (t & ADMHC_PS_PSSC) ? USB_PORT_STAT_C_SUSPEND : 0; - change |= (t & ADMHC_PS_OCIC) ? USB_PORT_STAT_C_OVERCURRENT : 0; - change |= (t & ADMHC_PS_PRSC) ? USB_PORT_STAT_C_RESET : 0; - - ps->wPortStatus = (__force __u16)cpu_to_hc16(ahcd, status); - ps->wPortChange = (__force __u16)cpu_to_hc16(ahcd, change); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_OTG - -static int admhc_start_port_reset(struct usb_hcd *hcd, unsigned port) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - u32 status; - - if (!port) - return -EINVAL; - port--; - - /* start port reset before HNP protocol times out */ - status = admhc_read_portstatus(ahcd, port); - if (!(status & ADMHC_PS_CCS)) - return -ENODEV; - - /* khubd will finish the reset later */ - admhc_write_portstatus(ahcd, port, ADMHC_PS_PRS); - return 0; -} - -static void start_hnp(struct admhcd *ahcd); - -#else - -#define admhc_start_port_reset NULL - -#endif - -/*-------------------------------------------------------------------------*/ - - -/* See usb 7.1.7.5: root hubs must issue at least 50 msec reset signaling, - * not necessarily continuous ... to guard against resume signaling. - * The short timeout is safe for non-root hubs, and is backward-compatible - * with earlier Linux hosts. - */ -#ifdef CONFIG_USB_SUSPEND -#define PORT_RESET_MSEC 50 -#else -#define PORT_RESET_MSEC 10 -#endif - -/* this timer value might be vendor-specific ... */ -#define PORT_RESET_HW_MSEC 10 - -/* wrap-aware logic morphed from */ -#define tick_before(t1, t2) ((s16)(((s16)(t1)) - ((s16)(t2))) < 0) - -/* called from some task, normally khubd */ -static inline int admhc_port_reset(struct admhcd *ahcd, unsigned port) -{ - u32 t; - - admhc_vdbg(ahcd, "reset port%d\n", port); - t = admhc_read_portstatus(ahcd, port); - if (!(t & ADMHC_PS_CCS)) - return -ENODEV; - - admhc_write_portstatus(ahcd, port, ADMHC_PS_SPR); - mdelay(10); - admhc_write_portstatus(ahcd, port, (ADMHC_PS_SPE | ADMHC_PS_CSC)); - mdelay(100); - - return 0; -} - -static inline int admhc_port_enable(struct admhcd *ahcd, unsigned port) -{ - u32 t; - - admhc_vdbg(ahcd, "enable port%d\n", port); - t = admhc_read_portstatus(ahcd, port); - if (!(t & ADMHC_PS_CCS)) - return -ENODEV; - - admhc_write_portstatus(ahcd, port, ADMHC_PS_SPE); - - return 0; -} - -static inline int admhc_port_disable(struct admhcd *ahcd, unsigned port) -{ - u32 t; - - admhc_vdbg(ahcd, "disable port%d\n", port); - t = admhc_read_portstatus(ahcd, port); - if (!(t & ADMHC_PS_CCS)) - return -ENODEV; - - admhc_write_portstatus(ahcd, port, ADMHC_PS_CPE); - - return 0; -} - -static inline int admhc_port_write(struct admhcd *ahcd, unsigned port, - u32 val) -{ -#ifdef ADMHC_VERBOSE_DEBUG - dbg_port_write(ahcd, "write", port, val); -#endif - admhc_write_portstatus(ahcd, port, val); - - return 0; -} - -static int admhc_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, char *buf, u16 wLength) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - int ports = ahcd->num_ports; - int ret = 0; - - if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) - return -ESHUTDOWN; - - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: -#if 0 /* FIXME */ - admhc_writel(ahcd, ADMHC_RH_OCIC, - &ahcd->regs->roothub.status); -#endif - case C_HUB_LOCAL_POWER: - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - ret = admhc_port_disable(ahcd, wIndex); - break; - case USB_PORT_FEAT_SUSPEND: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CPS); - break; - case USB_PORT_FEAT_POWER: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CPP); - break; - case USB_PORT_FEAT_C_CONNECTION: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_CSC); - break; - case USB_PORT_FEAT_C_ENABLE: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PESC); - break; - case USB_PORT_FEAT_C_SUSPEND: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PSSC); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_OCIC); - break; - case USB_PORT_FEAT_C_RESET: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_PRSC); - break; - default: - goto error; - } - break; - case GetHubDescriptor: - ret = admhc_get_hub_descriptor(ahcd, buf); - break; - case GetHubStatus: - ret = admhc_get_hub_status(ahcd, buf); - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - - ret = admhc_get_port_status(ahcd, wIndex, buf); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_OVER_CURRENT: - /* FIXME: this can be cleared, yes? */ - case C_HUB_LOCAL_POWER: - break; - default: - goto error; - } - break; - case SetPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - ret = admhc_port_enable(ahcd, wIndex); - break; - case USB_PORT_FEAT_RESET: - ret = admhc_port_reset(ahcd, wIndex); - break; - case USB_PORT_FEAT_SUSPEND: -#ifdef CONFIG_USB_OTG - if (hcd->self.otg_port == (wIndex + 1) - && hcd->self.b_hnp_enable) - start_hnp(ahcd); - else -#endif - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_SPS); - break; - case USB_PORT_FEAT_POWER: - ret = admhc_port_write(ahcd, wIndex, ADMHC_PS_SPP); - break; - default: - goto error; - } - break; - - default: -error: - /* "protocol stall" on error */ - ret = -EPIPE; - } - - return ret; -} - diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c deleted file mode 100644 index 79fff70e2d..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-mem.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-mem.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * 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. - * - */ - -/*-------------------------------------------------------------------------*/ - -/* - * OHCI deals with three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use dma_pool or dma_alloc_coherent - * - driver buffers, read/written by HC ... the hcd glue or the - * device driver provides us with dma addresses - * - * There's also "register" data, which is memory mapped. - * No memory seen by this driver (or any HCD) may be paged out. - */ - -/*-------------------------------------------------------------------------*/ - -static void admhc_hcd_init(struct admhcd *ahcd) -{ - ahcd->next_statechange = jiffies; - spin_lock_init(&ahcd->lock); - INIT_LIST_HEAD(&ahcd->pending); -} - -/*-------------------------------------------------------------------------*/ - -static int admhc_mem_init(struct admhcd *ahcd) -{ - ahcd->td_cache = dma_pool_create("admhc_td", - admhcd_to_hcd(ahcd)->self.controller, - sizeof(struct td), - TD_ALIGN, /* byte alignment */ - 0 /* no page-crossing issues */ - ); - if (!ahcd->td_cache) - goto err; - - ahcd->ed_cache = dma_pool_create("admhc_ed", - admhcd_to_hcd(ahcd)->self.controller, - sizeof(struct ed), - ED_ALIGN, /* byte alignment */ - 0 /* no page-crossing issues */ - ); - if (!ahcd->ed_cache) - goto err_td_cache; - - return 0; - -err_td_cache: - dma_pool_destroy(ahcd->td_cache); - ahcd->td_cache = NULL; -err: - return -ENOMEM; -} - -static void admhc_mem_cleanup(struct admhcd *ahcd) -{ - if (ahcd->td_cache) { - dma_pool_destroy(ahcd->td_cache); - ahcd->td_cache = NULL; - } - - if (ahcd->ed_cache) { - dma_pool_destroy(ahcd->ed_cache); - ahcd->ed_cache = NULL; - } -} - -/*-------------------------------------------------------------------------*/ - -/* ahcd "done list" processing needs this mapping */ -static inline struct td *dma_to_td(struct admhcd *ahcd, dma_addr_t td_dma) -{ - struct td *td; - - td_dma &= TD_MASK; - td = ahcd->td_hash[TD_HASH_FUNC(td_dma)]; - while (td && td->td_dma != td_dma) - td = td->td_hash; - - return td; -} - -/* TDs ... */ -static struct td *td_alloc(struct admhcd *ahcd, gfp_t mem_flags) -{ - dma_addr_t dma; - struct td *td; - - td = dma_pool_alloc(ahcd->td_cache, mem_flags, &dma); - if (!td) - return NULL; - - /* in case ahcd fetches it, make it look dead */ - memset(td, 0, sizeof *td); - td->hwNextTD = cpu_to_hc32(ahcd, dma); - td->td_dma = dma; - /* hashed in td_fill */ - - return td; -} - -static void td_free(struct admhcd *ahcd, struct td *td) -{ - struct td **prev = &ahcd->td_hash[TD_HASH_FUNC(td->td_dma)]; - - while (*prev && *prev != td) - prev = &(*prev)->td_hash; - if (*prev) - *prev = td->td_hash; -#if 0 - /* TODO: remove */ - else if ((td->hwINFO & cpu_to_hc32(ahcd, TD_DONE)) != 0) - admhc_dbg(ahcd, "no hash for td %p\n", td); -#else - else if ((td->flags & TD_FLAG_DONE) != 0) - admhc_dbg(ahcd, "no hash for td %p\n", td); -#endif - dma_pool_free(ahcd->td_cache, td, td->td_dma); -} - -/*-------------------------------------------------------------------------*/ - -/* EDs ... */ -static struct ed *ed_alloc(struct admhcd *ahcd, gfp_t mem_flags) -{ - dma_addr_t dma; - struct ed *ed; - - ed = dma_pool_alloc(ahcd->ed_cache, mem_flags, &dma); - if (!ed) - return NULL; - - memset(ed, 0, sizeof(*ed)); - ed->dma = dma; - - INIT_LIST_HEAD(&ed->td_list); - INIT_LIST_HEAD(&ed->urb_list); - - return ed; -} - -static void ed_free(struct admhcd *ahcd, struct ed *ed) -{ - dma_pool_free(ahcd->ed_cache, ed, ed->dma); -} - -/*-------------------------------------------------------------------------*/ - -/* URB priv ... */ -static void urb_priv_free(struct admhcd *ahcd, struct urb_priv *urb_priv) -{ - int i; - - for (i = 0; i < urb_priv->td_cnt; i++) - if (urb_priv->td[i]) - td_free(ahcd, urb_priv->td[i]); - - list_del(&urb_priv->pending); - kfree(urb_priv); -} - -static struct urb_priv *urb_priv_alloc(struct admhcd *ahcd, int num_tds, - gfp_t mem_flags) -{ - struct urb_priv *priv; - - /* allocate the private part of the URB */ - priv = kzalloc(sizeof(*priv) + sizeof(struct td) * num_tds, mem_flags); - if (!priv) - goto err; - - /* allocate the TDs (deferring hash chain updates) */ - for (priv->td_cnt = 0; priv->td_cnt < num_tds; priv->td_cnt++) { - priv->td[priv->td_cnt] = td_alloc(ahcd, mem_flags); - if (priv->td[priv->td_cnt] == NULL) - goto err_free; - } - - INIT_LIST_HEAD(&priv->pending); - - return priv; - -err_free: - urb_priv_free(ahcd, priv); -err: - return NULL; -} diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c deleted file mode 100644 index 7d7fc2438f..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from fragments of the OHCI driver. - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2004 David Brownell - * - * 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. - * - */ - -#define OHCI_SCHED_ENABLES \ - (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) - -#ifdef CONFIG_PM -static int admhc_restart(struct admhcd *ahcd); - -static int admhc_rh_suspend(struct admhcd *ahcd, int autostop) -__releases(ahcd->lock) -__acquires(ahcd->lock) -{ - int status = 0; - - ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); - switch (ahcd->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_RESUME: - admhc_dbg(ahcd, "resume/suspend?\n"); - ahcd->hc_control &= ~OHCI_CTRL_HCFS; - ahcd->hc_control |= OHCI_USB_RESET; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); - (void) admhc_readl(ahcd, &ahcd->regs->control); - /* FALL THROUGH */ - case OHCI_USB_RESET: - status = -EBUSY; - admhc_dbg(ahcd, "needs reinit!\n"); - goto done; - case OHCI_USB_SUSPEND: - if (!ahcd->autostop) { - admhc_dbg(ahcd, "already suspended\n"); - goto done; - } - } - admhc_dbg(ahcd, "%s root hub\n", - autostop ? "auto-stop" : "suspend"); - - /* First stop any processing */ - if (!autostop && (ahcd->hc_control & OHCI_SCHED_ENABLES)) { - ahcd->hc_control &= ~OHCI_SCHED_ENABLES; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); - ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); - admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->intrstatus); - - /* sched disables take effect on the next frame, - * then the last WDH could take 6+ msec - */ - admhc_dbg(ahcd, "stopping schedules ...\n"); - ahcd->autostop = 0; - spin_unlock_irq (&ahcd->lock); - msleep (8); - spin_lock_irq(&ahcd->lock); - } - dl_done_list (ahcd); - finish_unlinks (ahcd, admhc_frame_no(ahcd)); - - /* maybe resume can wake root hub */ - if (device_may_wakeup(&admhcd_to_hcd(ahcd)->self.root_hub->dev) || - autostop) - ahcd->hc_control |= OHCI_CTRL_RWE; - else { - admhc_writel(ahcd, OHCI_INTR_RHSC, &ahcd->regs->intrdisable); - ahcd->hc_control &= ~OHCI_CTRL_RWE; - } - - /* Suspend hub ... this is the "global (to this bus) suspend" mode, - * which doesn't imply ports will first be individually suspended. - */ - ahcd->hc_control &= ~OHCI_CTRL_HCFS; - ahcd->hc_control |= OHCI_USB_SUSPEND; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); - (void) admhc_readl(ahcd, &ahcd->regs->control); - - /* no resumes until devices finish suspending */ - if (!autostop) { - ahcd->next_statechange = jiffies + msecs_to_jiffies (5); - ahcd->autostop = 0; - } - -done: - return status; -} - -static inline struct ed *find_head(struct ed *ed) -{ - /* for bulk and control lists */ - while (ed->ed_prev) - ed = ed->ed_prev; - return ed; -} - -/* caller has locked the root hub */ -static int admhc_rh_resume(struct admhcd *ahcd) -__releases(ahcd->lock) -__acquires(ahcd->lock) -{ - struct usb_hcd *hcd = admhcd_to_hcd (ahcd); - u32 temp, enables; - int status = -EINPROGRESS; - int autostopped = ahcd->autostop; - - ahcd->autostop = 0; - ahcd->hc_control = admhc_readl(ahcd, &ahcd->regs->control); - - if (ahcd->hc_control & (OHCI_CTRL_IR | OHCI_SCHED_ENABLES)) { - /* this can happen after resuming a swsusp snapshot */ - if (hcd->state == HC_STATE_RESUMING) { - admhc_dbg(ahcd, "BIOS/SMM active, control %03x\n", - ahcd->hc_control); - status = -EBUSY; - /* this happens when pmcore resumes HC then root */ - } else { - admhc_dbg(ahcd, "duplicate resume\n"); - status = 0; - } - } else switch (ahcd->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_SUSPEND: - ahcd->hc_control &= ~(OHCI_CTRL_HCFS|OHCI_SCHED_ENABLES); - ahcd->hc_control |= OHCI_USB_RESUME; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); - (void) admhc_readl(ahcd, &ahcd->regs->control); - admhc_dbg(ahcd, "%s root hub\n", - autostopped ? "auto-start" : "resume"); - break; - case OHCI_USB_RESUME: - /* HCFS changes sometime after INTR_RD */ - admhc_dbg(ahcd, "%swakeup root hub\n", - autostopped ? "auto-" : ""); - break; - case OHCI_USB_OPER: - /* this can happen after resuming a swsusp snapshot */ - admhc_dbg(ahcd, "snapshot resume? reinit\n"); - status = -EBUSY; - break; - default: /* RESET, we lost power */ - admhc_dbg(ahcd, "lost power\n"); - status = -EBUSY; - } - if (status == -EBUSY) { - if (!autostopped) { - spin_unlock_irq (&ahcd->lock); - (void) ahcd_init (ahcd); - status = admhc_restart (ahcd); - spin_lock_irq(&ahcd->lock); - } - return status; - } - if (status != -EINPROGRESS) - return status; - if (autostopped) - goto skip_resume; - spin_unlock_irq (&ahcd->lock); - - /* Some controllers (lucent erratum) need extra-long delays */ - msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); - - temp = admhc_readl(ahcd, &ahcd->regs->control); - temp &= OHCI_CTRL_HCFS; - if (temp != OHCI_USB_RESUME) { - admhc_err (ahcd, "controller won't resume\n"); - spin_lock_irq(&ahcd->lock); - return -EBUSY; - } - - /* disable old schedule state, reinit from scratch */ - admhc_writel(ahcd, 0, &ahcd->regs->ed_controlhead); - admhc_writel(ahcd, 0, &ahcd->regs->ed_controlcurrent); - admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkhead); - admhc_writel(ahcd, 0, &ahcd->regs->ed_bulkcurrent); - admhc_writel(ahcd, 0, &ahcd->regs->ed_periodcurrent); - admhc_writel(ahcd, (u32) ahcd->hcca_dma, &ahcd->ahcd->regs->hcca); - - /* Sometimes PCI D3 suspend trashes frame timings ... */ - periodic_reinit(ahcd); - - /* the following code is executed with ahcd->lock held and - * irqs disabled if and only if autostopped is true - */ - -skip_resume: - /* interrupts might have been disabled */ - admhc_writel(ahcd, OHCI_INTR_INIT, &ahcd->regs->int_enable); - if (ahcd->ed_rm_list) - admhc_writel(ahcd, OHCI_INTR_SF, &ahcd->regs->int_enable); - - /* Then re-enable operations */ - admhc_writel(ahcd, OHCI_USB_OPER, &ahcd->regs->control); - (void) admhc_readl(ahcd, &ahcd->regs->control); - if (!autostopped) - msleep (3); - - temp = ahcd->hc_control; - temp &= OHCI_CTRL_RWC; - temp |= OHCI_CONTROL_INIT | OHCI_USB_OPER; - ahcd->hc_control = temp; - admhc_writel(ahcd, temp, &ahcd->regs->control); - (void) admhc_readl(ahcd, &ahcd->regs->control); - - /* TRSMRCY */ - if (!autostopped) { - msleep (10); - spin_lock_irq(&ahcd->lock); - } - /* now ahcd->lock is always held and irqs are always disabled */ - - /* keep it alive for more than ~5x suspend + resume costs */ - ahcd->next_statechange = jiffies + STATECHANGE_DELAY; - - /* maybe turn schedules back on */ - enables = 0; - temp = 0; - if (!ahcd->ed_rm_list) { - if (ahcd->ed_controltail) { - admhc_writel(ahcd, - find_head (ahcd->ed_controltail)->dma, - &ahcd->regs->ed_controlhead); - enables |= OHCI_CTRL_CLE; - temp |= OHCI_CLF; - } - if (ahcd->ed_bulktail) { - admhc_writel(ahcd, find_head (ahcd->ed_bulktail)->dma, - &ahcd->regs->ed_bulkhead); - enables |= OHCI_CTRL_BLE; - temp |= OHCI_BLF; - } - } - if (hcd->self.bandwidth_isoc_reqs || hcd->self.bandwidth_int_reqs) - enables |= OHCI_CTRL_PLE|OHCI_CTRL_IE; - if (enables) { - admhc_dbg(ahcd, "restarting schedules ... %08x\n", enables); - ahcd->hc_control |= enables; - admhc_writel(ahcd, ahcd->hc_control, &ahcd->ahcd->regs->control); - if (temp) - admhc_writel(ahcd, temp, &ahcd->regs->cmdstatus); - (void) admhc_readl(ahcd, &ahcd->regs->control); - } - - return 0; -} - -static int admhc_bus_suspend(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - int rc; - - spin_lock_irq(&ahcd->lock); - - if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) - rc = -ESHUTDOWN; - else - rc = admhc_rh_suspend(ahcd, 0); - spin_unlock_irq(&ahcd->lock); - return rc; -} - -static int admhc_bus_resume(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - int rc; - - if (time_before(jiffies, ahcd->next_statechange)) - msleep(5); - - spin_lock_irq(&ahcd->lock); - - if (unlikely(!HCD_HW_ACCESSIBLE(hcd))) - rc = -ESHUTDOWN; - else - rc = admhc_rh_resume(ahcd); - spin_unlock_irq(&ahcd->lock); - - /* poll until we know a device is connected or we autostop */ - if (rc == 0) - usb_hcd_poll_rh_status(hcd); - return rc; -} - -/* Carry out polling-, autostop-, and autoresume-related state changes */ -static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed, - int any_connected) -{ - int poll_rh = 1; - - switch (ahcd->hc_control & OHCI_CTRL_HCFS) { - - case OHCI_USB_OPER: - /* keep on polling until we know a device is connected - * and RHSC is enabled */ - if (!ahcd->autostop) { - if (any_connected || - !device_may_wakeup(&admhcd_to_hcd(ahcd) - ->self.root_hub->dev)) { - if (admhc_readl(ahcd, &ahcd->regs->int_enable) & - OHCI_INTR_RHSC) - poll_rh = 0; - } else { - ahcd->autostop = 1; - ahcd->next_statechange = jiffies + HZ; - } - - /* if no devices have been attached for one second, autostop */ - } else { - if (changed || any_connected) { - ahcd->autostop = 0; - ahcd->next_statechange = jiffies + - STATECHANGE_DELAY; - } else if (time_after_eq(jiffies, - ahcd->next_statechange) - && !ahcd->ed_rm_list - && !(ahcd->hc_control & - OHCI_SCHED_ENABLES)) { - ahcd_rh_suspend(ahcd, 1); - } - } - break; - - /* if there is a port change, autostart or ask to be resumed */ - case OHCI_USB_SUSPEND: - case OHCI_USB_RESUME: - if (changed) { - if (ahcd->autostop) - admhc_rh_resume(ahcd); - else - usb_hcd_resume_root_hub(admhcd_to_hcd(ahcd)); - } else { - /* everything is idle, no need for polling */ - poll_rh = 0; - } - break; - } - return poll_rh; -} - -/*-------------------------------------------------------------------------*/ - -/* must not be called from interrupt context */ -static int admhc_restart(struct admhcd *ahcd) -{ - int temp; - int i; - struct urb_priv *priv; - - /* mark any devices gone, so they do nothing till khubd disconnects. - * recycle any "live" eds/tds (and urbs) right away. - * later, khubd disconnect processing will recycle the other state, - * (either as disconnect/reconnect, or maybe someday as a reset). - */ - spin_lock_irq(&ahcd->lock); - admhc_disable(ahcd); - usb_root_hub_lost_power(admhcd_to_hcd(ahcd)->self.root_hub); - if (!list_empty(&ahcd->pending)) - admhc_dbg(ahcd, "abort schedule...\n"); - list_for_each_entry(priv, &ahcd->pending, pending) { - struct urb *urb = priv->td[0]->urb; - struct ed *ed = priv->ed; - - switch (ed->state) { - case ED_OPER: - ed->state = ED_UNLINK; - ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE); - ed_deschedule (ahcd, ed); - - ed->ed_next = ahcd->ed_rm_list; - ed->ed_prev = NULL; - ahcd->ed_rm_list = ed; - /* FALLTHROUGH */ - case ED_UNLINK: - break; - default: - admhc_dbg(ahcd, "bogus ed %p state %d\n", - ed, ed->state); - } - - if (!urb->unlinked) - urb->unlinked = -ESHUTDOWN; - } - finish_unlinks(ahcd, 0); - spin_unlock_irq(&ahcd->lock); - - /* paranoia, in case that didn't work: */ - - /* empty the interrupt branches */ - for (i = 0; i < NUM_INTS; i++) ahcd->load[i] = 0; - for (i = 0; i < NUM_INTS; i++) ahcd->hcca->int_table[i] = 0; - - /* no EDs to remove */ - ahcd->ed_rm_list = NULL; - - /* empty control and bulk lists */ - ahcd->ed_controltail = NULL; - ahcd->ed_bulktail = NULL; - - if ((temp = admhc_run(ahcd)) < 0) { - admhc_err(ahcd, "can't restart, %d\n", temp); - return temp; - } else { - /* here we "know" root ports should always stay powered, - * and that if we try to turn them back on the root hub - * will respond to CSC processing. - */ - i = ahcd->num_ports; - while (i--) - admhc_writel(ahcd, RH_PS_PSS, - &ahcd->regs->portstatus[i]); - admhc_dbg(ahcd, "restart complete\n"); - } - return 0; -} - -#else /* CONFIG_PM */ - -static inline int admhc_rh_resume(struct admhcd *ahcd) -{ - return 0; -} - -/* Carry out polling-related state changes. - * autostop isn't used when CONFIG_PM is turned off. - */ -static int admhc_root_hub_state_changes(struct admhcd *ahcd, int changed, - int any_connected) -{ - /* If INSM is enabled, don't poll */ - if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM) - return 0; - - /* If no status changes are pending, enable status-change interrupts */ - if (!changed) { - admhc_intr_enable(ahcd, ADMHC_INTR_INSM); - return 0; - } - - return 1; -} - -#endif /* CONFIG_PM */ - diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c deleted file mode 100644 index cd9c8920af..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c +++ /dev/null @@ -1,964 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci-q.c - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * 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 - -/*-------------------------------------------------------------------------*/ - -/* - * URB goes back to driver, and isn't reissued. - * It's completely gone from HC data structures. - * PRECONDITION: ahcd lock held, irqs blocked. - */ -static void -finish_urb(struct admhcd *ahcd, struct urb *urb, int status) -__releases(ahcd->lock) -__acquires(ahcd->lock) -{ - urb_priv_free(ahcd, urb->hcpriv); - - if (likely(status == -EINPROGRESS)) - status = 0; - - switch (usb_pipetype(urb->pipe)) { - case PIPE_ISOCHRONOUS: - admhcd_to_hcd(ahcd)->self.bandwidth_isoc_reqs--; - break; - case PIPE_INTERRUPT: - admhcd_to_hcd(ahcd)->self.bandwidth_int_reqs--; - break; - } - -#ifdef ADMHC_VERBOSE_DEBUG - urb_print(ahcd, urb, "RET", usb_pipeout(urb->pipe), status); -#endif - - /* urb->complete() can reenter this HCD */ - usb_hcd_unlink_urb_from_ep(admhcd_to_hcd(ahcd), urb); - spin_unlock(&ahcd->lock); - usb_hcd_giveback_urb(admhcd_to_hcd(ahcd), urb, status); - spin_lock(&ahcd->lock); -} - - -/*-------------------------------------------------------------------------* - * ED handling functions - *-------------------------------------------------------------------------*/ - -#if 0 /* FIXME */ -/* search for the right schedule branch to use for a periodic ed. - * does some load balancing; returns the branch, or negative errno. - */ -static int balance(struct admhcd *ahcd, int interval, int load) -{ - int i, branch = -ENOSPC; - - /* iso periods can be huge; iso tds specify frame numbers */ - if (interval > NUM_INTS) - interval = NUM_INTS; - - /* search for the least loaded schedule branch of that period - * that has enough bandwidth left unreserved. - */ - for (i = 0; i < interval ; i++) { - if (branch < 0 || ahcd->load[branch] > ahcd->load[i]) { - int j; - - /* usb 1.1 says 90% of one frame */ - for (j = i; j < NUM_INTS; j += interval) { - if ((ahcd->load[j] + load) > 900) - break; - } - if (j < NUM_INTS) - continue; - branch = i; - } - } - return branch; -} -#endif - -/*-------------------------------------------------------------------------*/ - -#if 0 /* FIXME */ -/* both iso and interrupt requests have periods; this routine puts them - * into the schedule tree in the apppropriate place. most iso devices use - * 1msec periods, but that's not required. - */ -static void periodic_link(struct admhcd *ahcd, struct ed *ed) -{ - unsigned i; - - admhc_vdbg(ahcd, "link %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "", - ed, ed->branch, ed->load, ed->interval); - - for (i = ed->branch; i < NUM_INTS; i += ed->interval) { - struct ed **prev = &ahcd->periodic[i]; - __hc32 *prev_p = &ahcd->hcca->int_table[i]; - struct ed *here = *prev; - - /* sorting each branch by period (slow before fast) - * lets us share the faster parts of the tree. - * (plus maybe: put interrupt eds before iso) - */ - while (here && ed != here) { - if (ed->interval > here->interval) - break; - prev = &here->ed_next; - prev_p = &here->hwNextED; - here = *prev; - } - if (ed != here) { - ed->ed_next = here; - if (here) - ed->hwNextED = *prev_p; - wmb(); - *prev = ed; - *prev_p = cpu_to_hc32(ahcd, ed->dma); - wmb(); - } - ahcd->load[i] += ed->load; - } - admhcd_to_hcd(ahcd)->self.bandwidth_allocated += ed->load / ed->interval; -} -#endif - -/* link an ed into the HC chain */ - -static int ed_schedule(struct admhcd *ahcd, struct ed *ed) -{ - struct ed *old_tail; - - if (admhcd_to_hcd(ahcd)->state == HC_STATE_QUIESCING) - return -EAGAIN; - - ed->state = ED_OPER; - - old_tail = ahcd->ed_tails[ed->type]; - - ed->ed_next = old_tail->ed_next; - if (ed->ed_next) { - ed->ed_next->ed_prev = ed; - ed->hwNextED = cpu_to_hc32(ahcd, ed->ed_next->dma); - } - ed->ed_prev = old_tail; - - old_tail->ed_next = ed; - old_tail->hwNextED = cpu_to_hc32(ahcd, ed->dma); - - ahcd->ed_tails[ed->type] = ed; - - admhc_dma_enable(ahcd); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -#if 0 /* FIXME */ -/* scan the periodic table to find and unlink this ED */ -static void periodic_unlink(struct admhcd *ahcd, struct ed *ed) -{ - int i; - - for (i = ed->branch; i < NUM_INTS; i += ed->interval) { - struct ed *temp; - struct ed **prev = &ahcd->periodic[i]; - __hc32 *prev_p = &ahcd->hcca->int_table[i]; - - while (*prev && (temp = *prev) != ed) { - prev_p = &temp->hwNextED; - prev = &temp->ed_next; - } - if (*prev) { - *prev_p = ed->hwNextED; - *prev = ed->ed_next; - } - ahcd->load[i] -= ed->load; - } - - admhcd_to_hcd(ahcd)->self.bandwidth_allocated -= ed->load / ed->interval; - admhc_vdbg(ahcd, "unlink %sed %p branch %d [%dus.], interval %d\n", - (ed->hwINFO & cpu_to_hc32(ahcd, ED_ISO)) ? "iso " : "", - ed, ed->branch, ed->load, ed->interval); -} -#endif - -/* unlink an ed from the HC chain. - * just the link to the ed is unlinked. - * the link from the ed still points to another operational ed or 0 - * so the HC can eventually finish the processing of the unlinked ed - * (assuming it already started that, which needn't be true). - * - * ED_UNLINK is a transient state: the HC may still see this ED, but soon - * it won't. ED_SKIP means the HC will finish its current transaction, - * but won't start anything new. The TD queue may still grow; device - * drivers don't know about this HCD-internal state. - * - * When the HC can't see the ED, something changes ED_UNLINK to one of: - * - * - ED_OPER: when there's any request queued, the ED gets rescheduled - * immediately. HC should be working on them. - * - * - ED_IDLE: when there's no TD queue. there's no reason for the HC - * to care about this ED; safe to disable the endpoint. - * - * When finish_unlinks() runs later, after SOF interrupt, it will often - * complete one or more URB unlinks before making that state change. - */ -static void ed_deschedule(struct admhcd *ahcd, struct ed *ed) -{ - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "ED-DESCHED", ed, 1); -#endif - - ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); - wmb(); - ed->state = ED_UNLINK; - - /* remove this ED from the HC list */ - ed->ed_prev->hwNextED = ed->hwNextED; - - /* and remove it from our list also */ - ed->ed_prev->ed_next = ed->ed_next; - - if (ed->ed_next) - ed->ed_next->ed_prev = ed->ed_prev; - - if (ahcd->ed_tails[ed->type] == ed) - ahcd->ed_tails[ed->type] = ed->ed_prev; -} - -/*-------------------------------------------------------------------------*/ - -static struct ed *ed_create(struct admhcd *ahcd, unsigned int type, u32 info) -{ - struct ed *ed; - struct td *td; - - ed = ed_alloc(ahcd, GFP_ATOMIC); - if (!ed) - goto err; - - /* dummy td; end of td list for this ed */ - td = td_alloc(ahcd, GFP_ATOMIC); - if (!td) - goto err_free_ed; - - switch (type) { - case PIPE_INTERRUPT: - info |= ED_INT; - break; - case PIPE_ISOCHRONOUS: - info |= ED_ISO; - break; - } - - ed->dummy = td; - ed->state = ED_IDLE; - ed->type = type; - - ed->hwINFO = cpu_to_hc32(ahcd, info); - ed->hwTailP = cpu_to_hc32(ahcd, td->td_dma); - ed->hwHeadP = ed->hwTailP; /* ED_C, ED_H zeroed */ - - return ed; - -err_free_ed: - ed_free(ahcd, ed); -err: - return NULL; -} - -/* get and maybe (re)init an endpoint. init _should_ be done only as part - * of enumeration, usb_set_configuration() or usb_set_interface(). - */ -static struct ed *ed_get(struct admhcd *ahcd, struct usb_host_endpoint *ep, - struct usb_device *udev, unsigned int pipe, int interval) -{ - struct ed *ed; - unsigned long flags; - - spin_lock_irqsave(&ahcd->lock, flags); - - ed = ep->hcpriv; - if (!ed) { - u32 info; - - /* FIXME: usbcore changes dev->devnum before SET_ADDRESS - * succeeds ... otherwise we wouldn't need "pipe". - */ - info = usb_pipedevice(pipe); - info |= (ep->desc.bEndpointAddress & ~USB_DIR_IN) << ED_EN_SHIFT; - info |= le16_to_cpu(ep->desc.wMaxPacketSize) << ED_MPS_SHIFT; - if (udev->speed == USB_SPEED_FULL) - info |= ED_SPEED_FULL; - - ed = ed_create(ahcd, usb_pipetype(pipe), info); - if (ed) - ep->hcpriv = ed; - } - - spin_unlock_irqrestore(&ahcd->lock, flags); - - return ed; -} - -/*-------------------------------------------------------------------------*/ - -/* request unlinking of an endpoint from an operational HC. - * put the ep on the rm_list - * real work is done at the next start frame (SOFI) hardware interrupt - * caller guarantees HCD is running, so hardware access is safe, - * and that ed->state is ED_OPER - */ -static void start_ed_unlink(struct admhcd *ahcd, struct ed *ed) -{ - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "ED-UNLINK", ed, 1); -#endif - - ed->hwINFO |= cpu_to_hc32(ahcd, ED_DEQUEUE); - ed_deschedule(ahcd, ed); - - /* add this ED into the remove list */ - ed->ed_rm_next = ahcd->ed_rm_list; - ahcd->ed_rm_list = ed; - - /* enable SOF interrupt */ - admhc_intr_ack(ahcd, ADMHC_INTR_SOFI); - admhc_intr_enable(ahcd, ADMHC_INTR_SOFI); - /* flush those writes */ - admhc_writel_flush(ahcd); - - /* SOF interrupt might get delayed; record the frame counter value that - * indicates when the HC isn't looking at it, so concurrent unlinks - * behave. frame_no wraps every 2^16 msec, and changes right before - * SOF is triggered. - */ - ed->tick = admhc_frame_no(ahcd) + 1; -} - -/*-------------------------------------------------------------------------* - * TD handling functions - *-------------------------------------------------------------------------*/ - -/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ - -static void -td_fill(struct admhcd *ahcd, u32 info, dma_addr_t data, int len, - struct urb *urb, int index) -{ - struct td *td, *td_pt; - struct urb_priv *urb_priv = urb->hcpriv; - int hash; - u32 cbl = 0; - -#if 1 - if (index == (urb_priv->td_cnt - 1) && - ((urb->transfer_flags & URB_NO_INTERRUPT) == 0)) - cbl |= TD_IE; -#else - if (index == (urb_priv->td_cnt - 1)) - cbl |= TD_IE; -#endif - - /* use this td as the next dummy */ - td_pt = urb_priv->td[index]; - - /* fill the old dummy TD */ - td = urb_priv->td[index] = urb_priv->ed->dummy; - urb_priv->ed->dummy = td_pt; - - td->ed = urb_priv->ed; - td->next_dl_td = NULL; - td->index = index; - td->urb = urb; - td->data_dma = data; - if (!len) - data = 0; - - if (data) - cbl |= (len & TD_BL_MASK); - - info |= TD_OWN; - - /* setup hardware specific fields */ - td->hwINFO = cpu_to_hc32(ahcd, info); - td->hwDBP = cpu_to_hc32(ahcd, data); - td->hwCBL = cpu_to_hc32(ahcd, cbl); - td->hwNextTD = cpu_to_hc32(ahcd, td_pt->td_dma); - - /* append to queue */ - list_add_tail(&td->td_list, &td->ed->td_list); - - /* hash it for later reverse mapping */ - hash = TD_HASH_FUNC(td->td_dma); - td->td_hash = ahcd->td_hash[hash]; - ahcd->td_hash[hash] = td; - - /* HC might read the TD (or cachelines) right away ... */ - wmb(); - td->ed->hwTailP = td->hwNextTD; -} - -/*-------------------------------------------------------------------------*/ - -/* Prepare all TDs of a transfer, and queue them onto the ED. - * Caller guarantees HC is active. - * Usually the ED is already on the schedule, so TDs might be - * processed as soon as they're queued. - */ -static void td_submit_urb(struct admhcd *ahcd, struct urb *urb) -{ - struct urb_priv *urb_priv = urb->hcpriv; - dma_addr_t data; - int data_len = urb->transfer_buffer_length; - int cnt = 0; - u32 info = 0; - int is_out = usb_pipeout(urb->pipe); - u32 toggle = 0; - - /* OHCI handles the bulk/interrupt data toggles itself. We just - * use the device toggle bits for resetting, and rely on the fact - * that resetting toggle is meaningless if the endpoint is active. - */ - - if (usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), is_out)) { - toggle = TD_T_CARRY; - } else { - toggle = TD_T_DATA0; - usb_settoggle(urb->dev, usb_pipeendpoint (urb->pipe), - is_out, 1); - } - - urb_priv->td_idx = 0; - list_add(&urb_priv->pending, &ahcd->pending); - - if (data_len) - data = urb->transfer_dma; - else - data = 0; - - /* NOTE: TD_CC is set so we can tell which TDs the HC processed by - * using TD_CC_GET, as well as by seeing them on the done list. - * (CC = NotAccessed ... 0x0F, or 0x0E in PSWs for ISO.) - */ - switch (urb_priv->ed->type) { - case PIPE_INTERRUPT: - info = is_out - ? TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_OUT - : TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_IN; - - /* setup service interval and starting frame number */ - info |= (urb->start_frame & TD_FN_MASK); - info |= (urb->interval & TD_ISI_MASK) << TD_ISI_SHIFT; - - td_fill(ahcd, info, data, data_len, urb, cnt); - cnt++; - - admhcd_to_hcd(ahcd)->self.bandwidth_int_reqs++; - break; - - case PIPE_BULK: - info = is_out - ? TD_SCC_NOTACCESSED | TD_DP_OUT - : TD_SCC_NOTACCESSED | TD_DP_IN; - - /* TDs _could_ transfer up to 8K each */ - while (data_len > TD_DATALEN_MAX) { - td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), - data, TD_DATALEN_MAX, urb, cnt); - data += TD_DATALEN_MAX; - data_len -= TD_DATALEN_MAX; - cnt++; - } - - td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), data, - data_len, urb, cnt); - cnt++; - - if ((urb->transfer_flags & URB_ZERO_PACKET) - && (cnt < urb_priv->td_cnt)) { - td_fill(ahcd, info | ((cnt) ? TD_T_CARRY : toggle), - 0, 0, urb, cnt); - cnt++; - } - break; - - /* control manages DATA0/DATA1 toggle per-request; SETUP resets it, - * any DATA phase works normally, and the STATUS ack is special. - */ - case PIPE_CONTROL: - /* fill a TD for the setup */ - info = TD_SCC_NOTACCESSED | TD_DP_SETUP | TD_T_DATA0; - td_fill(ahcd, info, urb->setup_dma, 8, urb, cnt++); - - if (data_len > 0) { - /* fill a TD for the data */ - info = TD_SCC_NOTACCESSED | TD_T_DATA1; - info |= is_out ? TD_DP_OUT : TD_DP_IN; - /* NOTE: mishandles transfers >8K, some >4K */ - td_fill(ahcd, info, data, data_len, urb, cnt++); - } - - /* fill a TD for the ACK */ - info = (is_out || data_len == 0) - ? TD_SCC_NOTACCESSED | TD_DP_IN | TD_T_DATA1 - : TD_SCC_NOTACCESSED | TD_DP_OUT | TD_T_DATA1; - td_fill(ahcd, info, data, 0, urb, cnt++); - - break; - - /* ISO has no retransmit, so no toggle; - * Each TD could handle multiple consecutive frames (interval 1); - * we could often reduce the number of TDs here. - */ - case PIPE_ISOCHRONOUS: - info = is_out - ? TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_OUT - : TD_T_CARRY | TD_SCC_NOTACCESSED | TD_DP_IN; - - for (cnt = 0; cnt < urb->number_of_packets; cnt++) { - int frame = urb->start_frame; - - frame += cnt * urb->interval; - frame &= TD_FN_MASK; - td_fill(ahcd, info | frame, - data + urb->iso_frame_desc[cnt].offset, - urb->iso_frame_desc[cnt].length, urb, cnt); - } - admhcd_to_hcd(ahcd)->self.bandwidth_isoc_reqs++; - break; - } - - if (urb_priv->td_cnt != cnt) - admhc_err(ahcd, "bad number of tds created for urb %p\n", urb); -} - -/*-------------------------------------------------------------------------* - * Done List handling functions - *-------------------------------------------------------------------------*/ - -/* calculate transfer length/status and update the urb */ -static int td_done(struct admhcd *ahcd, struct urb *urb, struct td *td) -{ - struct urb_priv *urb_priv = urb->hcpriv; - u32 info; - u32 bl; - u32 tdDBP; - int type = usb_pipetype(urb->pipe); - int cc; - int status = -EINPROGRESS; - - info = hc32_to_cpup(ahcd, &td->hwINFO); - tdDBP = hc32_to_cpup(ahcd, &td->hwDBP); - bl = TD_BL_GET(hc32_to_cpup(ahcd, &td->hwCBL)); - cc = TD_CC_GET(info); - - /* ISO ... drivers see per-TD length/status */ - if (type == PIPE_ISOCHRONOUS) { - /* TODO */ - int dlen = 0; - - /* NOTE: assumes FC in tdINFO == 0, and that - * only the first of 0..MAXPSW psws is used. - */ - if (info & TD_CC) /* hc didn't touch? */ - return status; - - if (usb_pipeout(urb->pipe)) - dlen = urb->iso_frame_desc[td->index].length; - else { - /* short reads are always OK for ISO */ - if (cc == TD_CC_DATAUNDERRUN) - cc = TD_CC_NOERROR; - dlen = tdDBP - td->data_dma + bl; - } - - urb->actual_length += dlen; - urb->iso_frame_desc[td->index].actual_length = dlen; - urb->iso_frame_desc[td->index].status = cc_to_error[cc]; - - if (cc != TD_CC_NOERROR) - admhc_vdbg(ahcd, - "urb %p iso td %p (%d) len %d cc %d\n", - urb, td, 1 + td->index, dlen, cc); - - /* BULK, INT, CONTROL ... drivers see aggregate length/status, - * except that "setup" bytes aren't counted and "short" transfers - * might not be reported as errors. - */ - } else { - /* update packet status if needed (short is normally ok) */ - if (cc == TD_CC_DATAUNDERRUN - && !(urb->transfer_flags & URB_SHORT_NOT_OK)) - cc = TD_CC_NOERROR; - - if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0) - status = cc_to_error[cc]; - - - /* count all non-empty packets except control SETUP packet */ - if ((type != PIPE_CONTROL || td->index != 0) && tdDBP != 0) - urb->actual_length += tdDBP - td->data_dma + bl; - - if (cc != TD_CC_NOERROR && cc < TD_CC_HCD0) - admhc_vdbg(ahcd, - "urb %p td %p (%d) cc %d, len=%d/%d\n", - urb, td, td->index, cc, - urb->actual_length, - urb->transfer_buffer_length); - } - - list_del(&td->td_list); - urb_priv->td_idx++; - - return status; -} - -/*-------------------------------------------------------------------------*/ - -static void ed_halted(struct admhcd *ahcd, struct td *td, int cc) -{ - struct urb *urb = td->urb; - struct urb_priv *urb_priv = urb->hcpriv; - struct ed *ed = td->ed; - struct list_head *tmp = td->td_list.next; - __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); - - admhc_dump_ed(ahcd, "ed halted", td->ed, 1); - /* clear ed halt; this is the td that caused it, but keep it inactive - * until its urb->complete() has a chance to clean up. - */ - ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); - wmb(); - ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); - - /* Get rid of all later tds from this urb. We don't have - * to be careful: no errors and nothing was transferred. - * Also patch the ed so it looks as if those tds completed normally. - */ - while (tmp != &ed->td_list) { - struct td *next; - - next = list_entry(tmp, struct td, td_list); - tmp = next->td_list.next; - - if (next->urb != urb) - break; - - /* NOTE: if multi-td control DATA segments get supported, - * this urb had one of them, this td wasn't the last td - * in that segment (TD_R clear), this ed halted because - * of a short read, _and_ URB_SHORT_NOT_OK is clear ... - * then we need to leave the control STATUS packet queued - * and clear ED_SKIP. - */ - list_del(&next->td_list); - urb_priv->td_cnt++; - ed->hwHeadP = next->hwNextTD | toggle; - } - - /* help for troubleshooting: report anything that - * looks odd ... that doesn't include protocol stalls - * (or maybe some other things) - */ - switch (cc) { - case TD_CC_DATAUNDERRUN: - if ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0) - break; - /* fallthrough */ - case TD_CC_STALL: - if (usb_pipecontrol(urb->pipe)) - break; - /* fallthrough */ - default: - admhc_dbg(ahcd, - "urb %p path %s ep%d%s %08x cc %d --> status %d\n", - urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out", - hc32_to_cpu(ahcd, td->hwINFO), - cc, cc_to_error[cc]); - } -} - -/*-------------------------------------------------------------------------*/ - -/* there are some urbs/eds to unlink; called in_irq(), with HCD locked */ -static void -finish_unlinks(struct admhcd *ahcd, u16 tick) -{ - struct ed *ed, **last; - -rescan_all: - for (last = &ahcd->ed_rm_list, ed = *last; ed != NULL; ed = *last) { - struct list_head *entry, *tmp; - int completed, modified; - __hc32 *prev; - - /* only take off EDs that the HC isn't using, accounting for - * frame counter wraps and EDs with partially retired TDs - */ - if (likely(HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state))) { - if (tick_before(tick, ed->tick)) { -skip_ed: - last = &ed->ed_rm_next; - continue; - } -#if 0 - if (!list_empty(&ed->td_list)) { - struct td *td; - u32 head; - - td = list_entry(ed->td_list.next, struct td, - td_list); - head = hc32_to_cpu(ahcd, ed->hwHeadP) & - TD_MASK; - - /* INTR_WDH may need to clean up first */ - if (td->td_dma != head) - goto skip_ed; - } -#endif - } - - /* reentrancy: if we drop the schedule lock, someone might - * have modified this list. normally it's just prepending - * entries (which we'd ignore), but paranoia won't hurt. - */ - *last = ed->ed_rm_next; - ed->ed_rm_next = NULL; - modified = 0; - - /* unlink urbs as requested, but rescan the list after - * we call a completion since it might have unlinked - * another (earlier) urb - * - * When we get here, the HC doesn't see this ed. But it - * must not be rescheduled until all completed URBs have - * been given back to the driver. - */ -rescan_this: - completed = 0; - prev = &ed->hwHeadP; - list_for_each_safe(entry, tmp, &ed->td_list) { - struct td *td; - struct urb *urb; - struct urb_priv *urb_priv; - __hc32 savebits; - u32 tdINFO; - int status; - - td = list_entry(entry, struct td, td_list); - urb = td->urb; - urb_priv = td->urb->hcpriv; - - if (!urb->unlinked) { - prev = &td->hwNextTD; - continue; - } - - if ((urb_priv) == NULL) - continue; - - /* patch pointer hc uses */ - savebits = *prev & ~cpu_to_hc32(ahcd, TD_MASK); - *prev = td->hwNextTD | savebits; - /* If this was unlinked, the TD may not have been - * retired ... so manually save dhe data toggle. - * The controller ignores the value we save for - * control and ISO endpoints. - */ - tdINFO = hc32_to_cpup(ahcd, &td->hwINFO); - if ((tdINFO & TD_T) == TD_T_DATA0) - ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_C); - else if ((tdINFO & TD_T) == TD_T_DATA1) - ed->hwHeadP |= cpu_to_hc32(ahcd, ED_C); - - /* HC may have partly processed this TD */ -#ifdef ADMHC_VERBOSE_DEBUG - urb_print(ahcd, urb, "PARTIAL", 0); -#endif - status = td_done(ahcd, urb, td); - - /* if URB is done, clean up */ - if (urb_priv->td_idx == urb_priv->td_cnt) { - modified = completed = 1; - finish_urb(ahcd, urb, status); - } - } - if (completed && !list_empty(&ed->td_list)) - goto rescan_this; - - /* ED's now officially unlinked, hc doesn't see */ - ed->state = ED_IDLE; - ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); - ed->hwNextED = 0; - wmb(); - ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP | ED_DEQUEUE); - - /* but if there's work queued, reschedule */ - if (!list_empty(&ed->td_list)) { - if (HC_IS_RUNNING(admhcd_to_hcd(ahcd)->state)) - ed_schedule(ahcd, ed); - } - - if (modified) - goto rescan_all; - } -} - -/*-------------------------------------------------------------------------*/ -/* - * Process normal completions (error or success) and clean the schedules. - * - * This is the main path for handing urbs back to drivers. The only other - * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list, - * instead of scanning the (re-reversed) donelist as this does. - */ - -static void ed_unhalt(struct admhcd *ahcd, struct ed *ed, struct urb *urb) -{ - struct list_head *entry, *tmp; - __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "UNHALT", ed, 0); -#endif - /* clear ed halt; this is the td that caused it, but keep it inactive - * until its urb->complete() has a chance to clean up. - */ - ed->hwINFO |= cpu_to_hc32(ahcd, ED_SKIP); - wmb(); - ed->hwHeadP &= ~cpu_to_hc32(ahcd, ED_H); - - list_for_each_safe(entry, tmp, &ed->td_list) { - struct td *td = list_entry(entry, struct td, td_list); - __hc32 info; - - if (td->urb != urb) - break; - - info = td->hwINFO; - info &= ~cpu_to_hc32(ahcd, TD_CC | TD_OWN); - td->hwINFO = info; - - ed->hwHeadP = td->hwNextTD | toggle; - wmb(); - } - -} - -static void ed_intr_refill(struct admhcd *ahcd, struct ed *ed) -{ - __hc32 toggle = ed->hwHeadP & cpu_to_hc32(ahcd, ED_C); - - ed->hwHeadP = ed->hwTailP | toggle; -} - - -static inline int is_ed_halted(struct admhcd *ahcd, struct ed *ed) -{ - return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & ED_H) == ED_H); -} - -static inline int is_td_halted(struct admhcd *ahcd, struct ed *ed, - struct td *td) -{ - return ((hc32_to_cpup(ahcd, &ed->hwHeadP) & TD_MASK) == - (hc32_to_cpup(ahcd, &td->hwNextTD) & TD_MASK)); -} - -static void ed_update(struct admhcd *ahcd, struct ed *ed) -{ - struct list_head *entry, *tmp; - -#ifdef ADMHC_VERBOSE_DEBUG - admhc_dump_ed(ahcd, "UPDATE", ed, 1); -#endif - - list_for_each_safe(entry, tmp, &ed->td_list) { - struct td *td = list_entry(entry, struct td, td_list); - struct urb *urb = td->urb; - struct urb_priv *urb_priv = urb->hcpriv; - int status; - - if (hc32_to_cpup(ahcd, &td->hwINFO) & TD_OWN) - break; - - /* update URB's length and status from TD */ - status = td_done(ahcd, urb, td); - if (is_ed_halted(ahcd, ed) && is_td_halted(ahcd, ed, td)) - ed_unhalt(ahcd, ed, urb); - - if (ed->type == PIPE_INTERRUPT) - ed_intr_refill(ahcd, ed); - - /* If all this urb's TDs are done, call complete() */ - if (urb_priv->td_idx == urb_priv->td_cnt) - finish_urb(ahcd, urb, status); - - /* clean schedule: unlink EDs that are no longer busy */ - if (list_empty(&ed->td_list)) { - if (ed->state == ED_OPER) - start_ed_unlink(ahcd, ed); - - /* ... reenabling halted EDs only after fault cleanup */ - } else if ((ed->hwINFO & cpu_to_hc32(ahcd, - ED_SKIP | ED_DEQUEUE)) - == cpu_to_hc32(ahcd, ED_SKIP)) { - td = list_entry(ed->td_list.next, struct td, td_list); -#if 0 - if (!(td->hwINFO & cpu_to_hc32(ahcd, TD_DONE))) { - ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); - /* ... hc may need waking-up */ - switch (ed->type) { - case PIPE_CONTROL: - admhc_writel(ahcd, OHCI_CLF, - &ahcd->regs->cmdstatus); - break; - case PIPE_BULK: - admhc_writel(ahcd, OHCI_BLF, - &ahcd->regs->cmdstatus); - break; - } - } -#else - if ((td->hwINFO & cpu_to_hc32(ahcd, TD_OWN))) - ed->hwINFO &= ~cpu_to_hc32(ahcd, ED_SKIP); -#endif - } - - } -} - -/* there are some tds completed; called in_irq(), with HCD locked */ -static void admhc_td_complete(struct admhcd *ahcd) -{ - struct ed *ed; - - for (ed = ahcd->ed_head; ed; ed = ed->ed_next) { - if (ed->state != ED_OPER) - continue; - - ed_update(ahcd, ed); - } -} diff --git a/target/linux/adm5120/files/drivers/usb/host/adm5120.h b/target/linux/adm5120/files/drivers/usb/host/adm5120.h deleted file mode 100644 index e47aac8e7a..0000000000 --- a/target/linux/adm5120/files/drivers/usb/host/adm5120.h +++ /dev/null @@ -1,755 +0,0 @@ -/* - * ADM5120 HCD (Host Controller Driver) for USB - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was derived from: drivers/usb/host/ohci.h - * (C) Copyright 1999 Roman Weissgaerber - * (C) Copyright 2000-2002 David Brownell - * - * 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. - * - */ - -/* - * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to - * __leXX (normally) or __beXX (given OHCI_BIG_ENDIAN), depending on the - * host controller implementation. - */ -typedef __u32 __bitwise __hc32; -typedef __u16 __bitwise __hc16; - -/* - * OHCI Endpoint Descriptor (ED) ... holds TD queue - * See OHCI spec, section 4.2 - * - * This is a "Queue Head" for those transfers, which is why - * both EHCI and UHCI call similar structures a "QH". - */ - -#define TD_DATALEN_MAX 4096 - -#define ED_ALIGN 16 -#define ED_MASK ((u32)~(ED_ALIGN-1)) /* strip hw status in low addr bits */ - -struct ed { - /* first fields are hardware-specified */ - __hc32 hwINFO; /* endpoint config bitmap */ - /* info bits defined by hcd */ -#define ED_DEQUEUE (1 << 27) - /* info bits defined by the hardware */ -#define ED_MPS_SHIFT 16 -#define ED_MPS_MASK ((1 << 11)-1) -#define ED_MPS_GET(x) (((x) >> ED_MPS_SHIFT) & ED_MPS_MASK) -#define ED_ISO (1 << 15) /* isochronous endpoint */ -#define ED_SKIP (1 << 14) -#define ED_SPEED_FULL (1 << 13) /* fullspeed device */ -#define ED_INT (1 << 11) /* interrupt endpoint */ -#define ED_EN_SHIFT 7 /* endpoint shift */ -#define ED_EN_MASK ((1 << 4)-1) /* endpoint mask */ -#define ED_EN_GET(x) (((x) >> ED_EN_SHIFT) & ED_EN_MASK) -#define ED_FA_MASK ((1 << 7)-1) /* function address mask */ -#define ED_FA_GET(x) ((x) & ED_FA_MASK) - __hc32 hwTailP; /* tail of TD list */ - __hc32 hwHeadP; /* head of TD list (hc r/w) */ -#define ED_C (0x02) /* toggle carry */ -#define ED_H (0x01) /* halted */ - __hc32 hwNextED; /* next ED in list */ - - /* rest are purely for the driver's use */ - dma_addr_t dma; /* addr of ED */ - struct td *dummy; /* next TD to activate */ - - struct list_head urb_list; /* list of our URBs */ - - /* host's view of schedule */ - struct ed *ed_next; /* on schedule list */ - struct ed *ed_prev; /* for non-interrupt EDs */ - struct ed *ed_rm_next; /* on rm list */ - struct list_head td_list; /* "shadow list" of our TDs */ - - /* create --> IDLE --> OPER --> ... --> IDLE --> destroy - * usually: OPER --> UNLINK --> (IDLE | OPER) --> ... - */ - u8 state; /* ED_{IDLE,UNLINK,OPER} */ -#define ED_IDLE 0x00 /* NOT linked to HC */ -#define ED_UNLINK 0x01 /* being unlinked from hc */ -#define ED_OPER 0x02 /* IS linked to hc */ - - u8 type; /* PIPE_{BULK,...} */ - - /* periodic scheduling params (for intr and iso) */ - u8 branch; - u16 interval; - u16 load; - u16 last_iso; /* iso only */ - - /* HC may see EDs on rm_list until next frame (frame_no == tick) */ - u16 tick; -} __attribute__ ((aligned(ED_ALIGN))); - -/* - * OHCI Transfer Descriptor (TD) ... one per transfer segment - * See OHCI spec, sections 4.3.1 (general = control/bulk/interrupt) - * and 4.3.2 (iso) - */ - -#define TD_ALIGN 32 -#define TD_MASK ((u32)~(TD_ALIGN-1)) /* strip hw status in low addr bits */ - -struct td { - /* first fields are hardware-specified */ - __hc32 hwINFO; /* transfer info bitmask */ - - /* hwINFO bits */ -#define TD_OWN (1 << 31) /* owner of the descriptor */ -#define TD_CC_SHIFT 27 /* condition code */ -#define TD_CC_MASK 0xf -#define TD_CC (TD_CC_MASK << TD_CC_SHIFT) -#define TD_CC_GET(x) (((x) >> TD_CC_SHIFT) & TD_CC_MASK) - -#define TD_EC_SHIFT 25 /* error count */ -#define TD_EC_MASK 0x3 -#define TD_EC (TD_EC_MASK << TD_EC_SHIFT) -#define TD_EC_GET(x) ((x >> TD_EC_SHIFT) & TD_EC_MASK) -#define TD_T_SHIFT 23 /* data toggle state */ -#define TD_T_MASK 0x3 -#define TD_T (TD_T_MASK << TD_T_SHIFT) -#define TD_T_DATA0 (0x2 << TD_T_SHIFT) /* DATA0 */ -#define TD_T_DATA1 (0x3 << TD_T_SHIFT) /* DATA1 */ -#define TD_T_CARRY (0x0 << TD_T_SHIFT) /* uses ED_C */ -#define TD_T_GET(x) (((x) >> TD_T_SHIFT) & TD_T_MASK) -#define TD_DP_SHIFT 21 /* direction/pid */ -#define TD_DP_MASK 0x3 -#define TD_DP (TD_DP_MASK << TD_DP_SHIFT) -#define TD_DP_GET (((x) >> TD_DP_SHIFT) & TD_DP_MASK) -#define TD_DP_SETUP (0x0 << TD_DP_SHIFT) /* SETUP pid */ -#define TD_DP_OUT (0x1 << TD_DP_SHIFT) /* OUT pid */ -#define TD_DP_IN (0x2 << TD_DP_SHIFT) /* IN pid */ -#define TD_ISI_SHIFT 8 /* Interrupt Service Interval */ -#define TD_ISI_MASK 0x3f -#define TD_ISI_GET(x) (((x) >> TD_ISI_SHIFT) & TD_ISI_MASK) -#define TD_FN_MASK 0x3f /* frame number */ -#define TD_FN_GET(x) ((x) & TD_FN_MASK) - - __hc32 hwDBP; /* Data Buffer Pointer (or 0) */ - __hc32 hwCBL; /* Controller/Buffer Length */ - - /* hwCBL bits */ -#define TD_BL_MASK 0xffff /* buffer length */ -#define TD_BL_GET(x) ((x) & TD_BL_MASK) -#define TD_IE (1 << 16) /* interrupt enable */ - __hc32 hwNextTD; /* Next TD Pointer */ - - /* rest are purely for the driver's use */ - __u8 index; - struct ed *ed; - struct td *td_hash; /* dma-->td hashtable */ - struct td *next_dl_td; - struct urb *urb; - - dma_addr_t td_dma; /* addr of this TD */ - dma_addr_t data_dma; /* addr of data it points to */ - - struct list_head td_list; /* "shadow list", TDs on same ED */ - - u32 flags; -#define TD_FLAG_DONE (1 << 17) /* retired to done list */ -#define TD_FLAG_ISO (1 << 16) /* copy of ED_ISO */ -} __attribute__ ((aligned(TD_ALIGN))); /* c/b/i need 16; only iso needs 32 */ - -/* - * Hardware transfer status codes -- CC from td->hwINFO - */ -#define TD_CC_NOERROR 0x00 -#define TD_CC_CRC 0x01 -#define TD_CC_BITSTUFFING 0x02 -#define TD_CC_DATATOGGLEM 0x03 -#define TD_CC_STALL 0x04 -#define TD_CC_DEVNOTRESP 0x05 -#define TD_CC_PIDCHECKFAIL 0x06 -#define TD_CC_UNEXPECTEDPID 0x07 -#define TD_CC_DATAOVERRUN 0x08 -#define TD_CC_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define TD_CC_BUFFEROVERRUN 0x0C -#define TD_CC_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define TD_CC_HCD0 0x0E -#define TD_CC_NOTACCESSED 0x0F - -/* - * preshifted status codes - */ -#define TD_SCC_NOTACCESSED (TD_CC_NOTACCESSED << TD_CC_SHIFT) - - -/* map OHCI TD status codes (CC) to errno values */ -static const int cc_to_error[16] = { - /* No Error */ 0, - /* CRC Error */ -EILSEQ, - /* Bit Stuff */ -EPROTO, - /* Data Togg */ -EILSEQ, - /* Stall */ -EPIPE, - /* DevNotResp */ -ETIME, - /* PIDCheck */ -EPROTO, - /* UnExpPID */ -EPROTO, - /* DataOver */ -EOVERFLOW, - /* DataUnder */ -EREMOTEIO, - /* (for hw) */ -EIO, - /* (for hw) */ -EIO, - /* BufferOver */ -ECOMM, - /* BuffUnder */ -ENOSR, - /* (for HCD) */ -EALREADY, - /* (for HCD) */ -EALREADY -}; - -#define NUM_INTS 32 - -/* - * This is the structure of the OHCI controller's memory mapped I/O region. - * You must use readl() and writel() (in ) to access these fields!! - * Layout is in section 7 (and appendix B) of the spec. - */ -struct admhcd_regs { - __hc32 gencontrol; /* General Control */ - __hc32 int_status; /* Interrupt Status */ - __hc32 int_enable; /* Interrupt Enable */ - __hc32 reserved00; - __hc32 host_control; /* Host General Control */ - __hc32 reserved01; - __hc32 fminterval; /* Frame Interval */ - __hc32 fmnumber; /* Frame Number */ - __hc32 reserved02; - __hc32 reserved03; - __hc32 reserved04; - __hc32 reserved05; - __hc32 reserved06; - __hc32 reserved07; - __hc32 reserved08; - __hc32 reserved09; - __hc32 reserved10; - __hc32 reserved11; - __hc32 reserved12; - __hc32 reserved13; - __hc32 reserved14; - __hc32 reserved15; - __hc32 reserved16; - __hc32 reserved17; - __hc32 reserved18; - __hc32 reserved19; - __hc32 reserved20; - __hc32 reserved21; - __hc32 lsthresh; /* Low Speed Threshold */ - __hc32 rhdesc; /* Root Hub Descriptor */ -#define MAX_ROOT_PORTS 2 - __hc32 portstatus[MAX_ROOT_PORTS]; /* Port Status */ - __hc32 hosthead; /* Host Descriptor Head */ -} __attribute__ ((aligned(32))); - -/* - * General Control register bits - */ -#define ADMHC_CTRL_UHFE (1 << 0) /* USB Host Function Enable */ -#define ADMHC_CTRL_SIR (1 << 1) /* Software Interrupt request */ -#define ADMHC_CTRL_DMAA (1 << 2) /* DMA Arbitration Control */ -#define ADMHC_CTRL_SR (1 << 3) /* Software Reset */ - -/* - * Host General Control register bits - */ -#define ADMHC_HC_BUSS 0x3 /* USB bus state */ -#define ADMHC_BUSS_RESET 0x0 -#define ADMHC_BUSS_RESUME 0x1 -#define ADMHC_BUSS_OPER 0x2 -#define ADMHC_BUSS_SUSPEND 0x3 -#define ADMHC_HC_DMAE (1 << 2) /* DMA enable */ - -/* - * Interrupt Status/Enable register bits - */ -#define ADMHC_INTR_SOFI (1 << 4) /* start of frame */ -#define ADMHC_INTR_RESI (1 << 5) /* resume detected */ -#define ADMHC_INTR_6 (1 << 6) /* unknown */ -#define ADMHC_INTR_7 (1 << 7) /* unknown */ -#define ADMHC_INTR_BABI (1 << 8) /* babble detected */ -#define ADMHC_INTR_INSM (1 << 9) /* root hub status change */ -#define ADMHC_INTR_SO (1 << 10) /* scheduling overrun */ -#define ADMHC_INTR_FNO (1 << 11) /* frame number overflow */ -#define ADMHC_INTR_TDC (1 << 20) /* transfer descriptor completed */ -#define ADMHC_INTR_SWI (1 << 29) /* software interrupt */ -#define ADMHC_INTR_FATI (1 << 30) /* fatal error */ -#define ADMHC_INTR_INTA (1 << 31) /* interrupt active */ - -#define ADMHC_INTR_MIE (1 << 31) /* master interrupt enable */ - -/* - * SOF Frame Interval register bits - */ -#define ADMHC_SFI_FI_MASK ((1 << 14)-1) /* Frame Interval value */ -#define ADMHC_SFI_FSLDP_SHIFT 16 -#define ADMHC_SFI_FSLDP_MASK ((1 << 15)-1) -#define ADMHC_SFI_FIT (1 << 31) /* Frame Interval Toggle */ - -/* - * SOF Frame Number register bits - */ -#define ADMHC_SFN_FN_MASK ((1 << 16)-1) /* Frame Number Mask */ -#define ADMHC_SFN_FR_SHIFT 16 /* Frame Remaining Shift */ -#define ADMHC_SFN_FR_MASK ((1 << 14)-1) /* Frame Remaining Mask */ -#define ADMHC_SFN_FRT (1 << 31) /* Frame Remaining Toggle */ - -/* - * Root Hub Descriptor register bits - */ -#define ADMHC_RH_NUMP 0xff /* number of ports */ -#define ADMHC_RH_PSM (1 << 8) /* power switching mode */ -#define ADMHC_RH_NPS (1 << 9) /* no power switching */ -#define ADMHC_RH_OCPM (1 << 10) /* over current protection mode */ -#define ADMHC_RH_NOCP (1 << 11) /* no over current protection */ -#define ADMHC_RH_PPCM (0xff << 16) /* port power control */ - -#define ADMHC_RH_LPS (1 << 24) /* local power switch */ -#define ADMHC_RH_OCI (1 << 25) /* over current indicator */ - -/* status change bits */ -#define ADMHC_RH_LPSC (1 << 26) /* local power switch change */ -#define ADMHC_RH_OCIC (1 << 27) /* over current indicator change */ - -#define ADMHC_RH_DRWE (1 << 28) /* device remote wakeup enable */ -#define ADMHC_RH_CRWE (1 << 29) /* clear remote wakeup enable */ - -#define ADMHC_RH_CGP (1 << 24) /* clear global power */ -#define ADMHC_RH_SGP (1 << 26) /* set global power */ - -/* - * Port Status register bits - */ -#define ADMHC_PS_CCS (1 << 0) /* current connect status */ -#define ADMHC_PS_PES (1 << 1) /* port enable status */ -#define ADMHC_PS_PSS (1 << 2) /* port suspend status */ -#define ADMHC_PS_POCI (1 << 3) /* port over current indicator */ -#define ADMHC_PS_PRS (1 << 4) /* port reset status */ -#define ADMHC_PS_PPS (1 << 8) /* port power status */ -#define ADMHC_PS_LSDA (1 << 9) /* low speed device attached */ - -/* status change bits */ -#define ADMHC_PS_CSC (1 << 16) /* connect status change */ -#define ADMHC_PS_PESC (1 << 17) /* port enable status change */ -#define ADMHC_PS_PSSC (1 << 18) /* port suspend status change */ -#define ADMHC_PS_OCIC (1 << 19) /* over current indicator change */ -#define ADMHC_PS_PRSC (1 << 20) /* port reset status change */ - -/* port feature bits */ -#define ADMHC_PS_CPE (1 << 0) /* clear port enable */ -#define ADMHC_PS_SPE (1 << 1) /* set port enable */ -#define ADMHC_PS_SPS (1 << 2) /* set port suspend */ -#define ADMHC_PS_CPS (1 << 3) /* clear suspend status */ -#define ADMHC_PS_SPR (1 << 4) /* set port reset */ -#define ADMHC_PS_SPP (1 << 8) /* set port power */ -#define ADMHC_PS_CPP (1 << 9) /* clear port power */ - -/* - * the POTPGT value is not defined in the ADMHC, so define a dummy value - */ -#define ADMHC_POTPGT 2 /* in ms */ - -/* hcd-private per-urb state */ -struct urb_priv { - struct ed *ed; - struct list_head pending; /* URBs on the same ED */ - - u32 td_cnt; /* # tds in this request */ - u32 td_idx; /* index of the current td */ - struct td *td[0]; /* all TDs in this request */ -}; - -#define TD_HASH_SIZE 64 /* power'o'two */ -/* sizeof (struct td) ~= 64 == 2^6 ... */ -#define TD_HASH_FUNC(td_dma) ((td_dma ^ (td_dma >> 6)) % TD_HASH_SIZE) - -/* - * This is the full ADMHCD controller description - * - * Note how the "proper" USB information is just - * a subset of what the full implementation needs. (Linus) - */ - -struct admhcd { - spinlock_t lock; - - /* - * I/O memory used to communicate with the HC (dma-consistent) - */ - struct admhcd_regs __iomem *regs; - - /* - * hcd adds to schedule for a live hc any time, but removals finish - * only at the start of the next frame. - */ - - struct ed *ed_head; - struct ed *ed_tails[4]; - - struct ed *ed_rm_list; /* to be removed */ - - struct ed *periodic[NUM_INTS]; /* shadow int_table */ - -#if 0 /* TODO: remove? */ - /* - * OTG controllers and transceivers need software interaction; - * other external transceivers should be software-transparent - */ - struct otg_transceiver *transceiver; - void (*start_hnp)(struct admhcd *ahcd); -#endif - - /* - * memory management for queue data structures - */ - struct dma_pool *td_cache; - struct dma_pool *ed_cache; - struct td *td_hash[TD_HASH_SIZE]; - struct list_head pending; - - /* - * driver state - */ - int num_ports; - int load[NUM_INTS]; - u32 host_control; /* copy of the host_control reg */ - unsigned long next_statechange; /* suspend/resume */ - u32 fminterval; /* saved register */ - unsigned autostop:1; /* rh auto stopping/stopped */ - - unsigned long flags; /* for HC bugs */ -#define OHCI_QUIRK_AMD756 0x01 /* erratum #4 */ -#define OHCI_QUIRK_SUPERIO 0x02 /* natsemi */ -#define OHCI_QUIRK_INITRESET 0x04 /* SiS, OPTi, ... */ -#define OHCI_QUIRK_BE_DESC 0x08 /* BE descriptors */ -#define OHCI_QUIRK_BE_MMIO 0x10 /* BE registers */ -#define OHCI_QUIRK_ZFMICRO 0x20 /* Compaq ZFMicro chipset*/ - /* there are also chip quirks/bugs in init logic */ - -#ifdef DEBUG - struct dentry *debug_dir; - struct dentry *debug_async; - struct dentry *debug_periodic; - struct dentry *debug_registers; -#endif -}; - -/* convert between an hcd pointer and the corresponding ahcd_hcd */ -static inline struct admhcd *hcd_to_admhcd(struct usb_hcd *hcd) -{ - return (struct admhcd *)(hcd->hcd_priv); -} -static inline struct usb_hcd *admhcd_to_hcd(const struct admhcd *ahcd) -{ - return container_of((void *)ahcd, struct usb_hcd, hcd_priv); -} - -/*-------------------------------------------------------------------------*/ - -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -#ifdef DEBUG -# define admhc_dbg(ahcd, fmt, args...) \ - printk(KERN_DEBUG "adm5120-hcd: " fmt, ## args) -#else -# define admhc_dbg(ahcd, fmt, args...) do { } while (0) -#endif - -#define admhc_err(ahcd, fmt, args...) \ - printk(KERN_ERR "adm5120-hcd: " fmt, ## args) -#define admhc_info(ahcd, fmt, args...) \ - printk(KERN_INFO "adm5120-hcd: " fmt, ## args) -#define admhc_warn(ahcd, fmt, args...) \ - printk(KERN_WARNING "adm5120-hcd: " fmt, ## args) - -#ifdef ADMHC_VERBOSE_DEBUG -# define admhc_vdbg admhc_dbg -#else -# define admhc_vdbg(ahcd, fmt, args...) do { } while (0) -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * While most USB host controllers implement their registers and - * in-memory communication descriptors in little-endian format, - * a minority (notably the IBM STB04XXX and the Motorola MPC5200 - * processors) implement them in big endian format. - * - * In addition some more exotic implementations like the Toshiba - * Spider (aka SCC) cell southbridge are "mixed" endian, that is, - * they have a different endianness for registers vs. in-memory - * descriptors. - * - * This attempts to support either format at compile time without a - * runtime penalty, or both formats with the additional overhead - * of checking a flag bit. - * - * That leads to some tricky Kconfig rules howevber. There are - * different defaults based on some arch/ppc platforms, though - * the basic rules are: - * - * Controller type Kconfig options needed - * --------------- ---------------------- - * little endian CONFIG_USB_ADMHC_LITTLE_ENDIAN - * - * fully big endian CONFIG_USB_ADMHC_BIG_ENDIAN_DESC _and_ - * CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO - * - * mixed endian CONFIG_USB_ADMHC_LITTLE_ENDIAN _and_ - * CONFIG_USB_OHCI_BIG_ENDIAN_{MMIO,DESC} - * - * (If you have a mixed endian controller, you -must- also define - * CONFIG_USB_ADMHC_LITTLE_ENDIAN or things will not work when building - * both your mixed endian and a fully big endian controller support in - * the same kernel image). - */ - -#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_DESC -#ifdef CONFIG_USB_ADMHC_LITTLE_ENDIAN -#define big_endian_desc(ahcd) (ahcd->flags & OHCI_QUIRK_BE_DESC) -#else -#define big_endian_desc(ahcd) 1 /* only big endian */ -#endif -#else -#define big_endian_desc(ahcd) 0 /* only little endian */ -#endif - -#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO -#ifdef CONFIG_USB_ADMHC_LITTLE_ENDIAN -#define big_endian_mmio(ahcd) (ahcd->flags & OHCI_QUIRK_BE_MMIO) -#else -#define big_endian_mmio(ahcd) 1 /* only big endian */ -#endif -#else -#define big_endian_mmio(ahcd) 0 /* only little endian */ -#endif - -/* - * Big-endian read/write functions are arch-specific. - * Other arches can be added if/when they're needed. - * - */ -static inline unsigned int admhc_readl(const struct admhcd *ahcd, - __hc32 __iomem *regs) -{ -#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO - return big_endian_mmio(ahcd) ? - readl_be(regs) : - readl(regs); -#else - return readl(regs); -#endif -} - -static inline void admhc_writel(const struct admhcd *ahcd, - const unsigned int val, __hc32 __iomem *regs) -{ -#ifdef CONFIG_USB_ADMHC_BIG_ENDIAN_MMIO - big_endian_mmio(ahcd) ? - writel_be(val, regs) : - writel(val, regs); -#else - writel(val, regs); -#endif -} - -static inline void admhc_writel_flush(const struct admhcd *ahcd) -{ -#if 0 - /* TODO: remove? */ - (void) admhc_readl(ahcd, &ahcd->regs->gencontrol); -#endif -} - - -/*-------------------------------------------------------------------------*/ - -/* cpu to ahcd */ -static inline __hc16 cpu_to_hc16(const struct admhcd *ahcd, const u16 x) -{ - return big_endian_desc(ahcd) ? - (__force __hc16)cpu_to_be16(x) : - (__force __hc16)cpu_to_le16(x); -} - -static inline __hc16 cpu_to_hc16p(const struct admhcd *ahcd, const u16 *x) -{ - return big_endian_desc(ahcd) ? - cpu_to_be16p(x) : - cpu_to_le16p(x); -} - -static inline __hc32 cpu_to_hc32(const struct admhcd *ahcd, const u32 x) -{ - return big_endian_desc(ahcd) ? - (__force __hc32)cpu_to_be32(x) : - (__force __hc32)cpu_to_le32(x); -} - -static inline __hc32 cpu_to_hc32p(const struct admhcd *ahcd, const u32 *x) -{ - return big_endian_desc(ahcd) ? - cpu_to_be32p(x) : - cpu_to_le32p(x); -} - -/* ahcd to cpu */ -static inline u16 hc16_to_cpu(const struct admhcd *ahcd, const __hc16 x) -{ - return big_endian_desc(ahcd) ? - be16_to_cpu((__force __be16)x) : - le16_to_cpu((__force __le16)x); -} - -static inline u16 hc16_to_cpup(const struct admhcd *ahcd, const __hc16 *x) -{ - return big_endian_desc(ahcd) ? - be16_to_cpup((__force __be16 *)x) : - le16_to_cpup((__force __le16 *)x); -} - -static inline u32 hc32_to_cpu(const struct admhcd *ahcd, const __hc32 x) -{ - return big_endian_desc(ahcd) ? - be32_to_cpu((__force __be32)x) : - le32_to_cpu((__force __le32)x); -} - -static inline u32 hc32_to_cpup(const struct admhcd *ahcd, const __hc32 *x) -{ - return big_endian_desc(ahcd) ? - be32_to_cpup((__force __be32 *)x) : - le32_to_cpup((__force __le32 *)x); -} - -/*-------------------------------------------------------------------------*/ - -static inline u16 admhc_frame_no(const struct admhcd *ahcd) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->fmnumber) & ADMHC_SFN_FN_MASK; - return (u16)t; -} - -static inline u16 admhc_frame_remain(const struct admhcd *ahcd) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->fmnumber) >> ADMHC_SFN_FR_SHIFT; - t &= ADMHC_SFN_FR_MASK; - return (u16)t; -} - -/*-------------------------------------------------------------------------*/ - -static inline void admhc_disable(struct admhcd *ahcd) -{ - admhcd_to_hcd(ahcd)->state = HC_STATE_HALT; -} - -#define FI 0x2edf /* 12000 bits per frame (-1) */ -#define FSLDP(fi) (0x7fff & ((6 * ((fi) - 1200)) / 7)) -#define FIT ADMHC_SFI_FIT -#define LSTHRESH 0x628 /* lowspeed bit threshold */ - -static inline void periodic_reinit(struct admhcd *ahcd) -{ -#if 0 - u32 fi = ahcd->fminterval & ADMHC_SFI_FI_MASK; - u32 fit = admhc_readl(ahcd, &ahcd->regs->fminterval) & FIT; - - /* TODO: adjust FSLargestDataPacket value too? */ - admhc_writel(ahcd, (fit ^ FIT) | ahcd->fminterval, - &ahcd->regs->fminterval); -#else - u32 fit = admhc_readl(ahcd, &ahcd->regs->fminterval) & FIT; - - /* TODO: adjust FSLargestDataPacket value too? */ - admhc_writel(ahcd, (fit ^ FIT) | ahcd->fminterval, - &ahcd->regs->fminterval); -#endif -} - -static inline u32 admhc_read_rhdesc(struct admhcd *ahcd) -{ - return admhc_readl(ahcd, &ahcd->regs->rhdesc); -} - -static inline u32 admhc_read_portstatus(struct admhcd *ahcd, int port) -{ - return admhc_readl(ahcd, &ahcd->regs->portstatus[port]); -} - -static inline void admhc_write_portstatus(struct admhcd *ahcd, int port, - u32 value) -{ - admhc_writel(ahcd, value, &ahcd->regs->portstatus[port]); -} - -static inline void roothub_write_status(struct admhcd *ahcd, u32 value) -{ - /* FIXME: read-only bits must be masked out */ - admhc_writel(ahcd, value, &ahcd->regs->rhdesc); -} - -static inline void admhc_intr_disable(struct admhcd *ahcd, u32 ints) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->int_enable); - t &= ~(ints); - admhc_writel(ahcd, t, &ahcd->regs->int_enable); - /* TODO: flush writes ?*/ -} - -static inline void admhc_intr_enable(struct admhcd *ahcd, u32 ints) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->int_enable); - t |= ints; - admhc_writel(ahcd, t, &ahcd->regs->int_enable); - /* TODO: flush writes ?*/ -} - -static inline void admhc_intr_ack(struct admhcd *ahcd, u32 ints) -{ - admhc_writel(ahcd, ints, &ahcd->regs->int_status); -} - -static inline void admhc_dma_enable(struct admhcd *ahcd) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->host_control); - if (t & ADMHC_HC_DMAE) - return; - - t |= ADMHC_HC_DMAE; - admhc_writel(ahcd, t, &ahcd->regs->host_control); - admhc_vdbg(ahcd, "DMA enabled\n"); -} - -static inline void admhc_dma_disable(struct admhcd *ahcd) -{ - u32 t; - - t = admhc_readl(ahcd, &ahcd->regs->host_control); - if (!(t & ADMHC_HC_DMAE)) - return; - - t &= ~ADMHC_HC_DMAE; - admhc_writel(ahcd, t, &ahcd->regs->host_control); - admhc_vdbg(ahcd, "DMA disabled\n"); -} diff --git a/target/linux/adm5120/files/drivers/watchdog/adm5120_wdt.c b/target/linux/adm5120/files/drivers/watchdog/adm5120_wdt.c deleted file mode 100644 index d5d63b27a5..0000000000 --- a/target/linux/adm5120/files/drivers/watchdog/adm5120_wdt.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * ADM5120_WDT 0.01: Infineon ADM5120 SoC watchdog driver - * Copyright (c) Ondrej Zajicek , 2007 - * - * based on - * - * RC32434_WDT 0.01: IDT Interprise 79RC32434 watchdog driver - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version - * 2 of the License, or (at your option) any later version. - * - */ -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#define DEFAULT_TIMEOUT 15 /* (secs) Default is 15 seconds */ -#define MAX_TIMEOUT 327 -/* Max is 327 seconds, counter is 15-bit integer, step is 10 ms */ - -#define NAME "adm5120_wdt" -#define VERSION "0.1" - -static int expect_close; -static int access; -static unsigned int timeout = DEFAULT_TIMEOUT; - -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -MODULE_LICENSE("GPL"); - - -static inline void wdt_set_timeout(void) -{ - u32 val = (1 << 31) | (((timeout * 100) & 0x7FFF) << 16); - SW_WRITE_REG(SWITCH_REG_WDOG0, val); -} - -/* - It looks like WDOG0-register-write don't modify counter, - but WDOG0-register-read resets counter. -*/ - -static inline void wdt_reset_counter(void) -{ - SW_READ_REG(SWITCH_REG_WDOG0); -} - -static inline void wdt_disable(void) -{ - SW_WRITE_REG(SWITCH_REG_WDOG0, 0x7FFF0000); -} - - - -static int wdt_open(struct inode *inode, struct file *file) -{ - /* Allow only one person to hold it open */ - if (access) - return -EBUSY; - - if (nowayout) - __module_get(THIS_MODULE); - - /* Activate timer */ - wdt_reset_counter(); - wdt_set_timeout(); - printk(KERN_INFO NAME ": enabling watchdog timer\n"); - access = 1; - return 0; -} - -static int wdt_release(struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - * Lock it in if it's a module and we set nowayout - */ - if (expect_close && (nowayout == 0)) { - wdt_disable(); - printk(KERN_INFO NAME ": disabling watchdog timer\n"); - module_put(THIS_MODULE); - } else - printk(KERN_CRIT NAME ": device closed unexpectedly. WDT will not stop!\n"); - - access = 0; - return 0; -} - -static ssize_t wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) -{ - /* Refresh the timer. */ - if (len) { - if (!nowayout) { - size_t i; - - /* In case it was set long ago */ - expect_close = 0; - - for (i = 0; i != len; i++) { - char c; - if (get_user(c, data + i)) - return -EFAULT; - if (c == 'V') - expect_close = 1; - } - } - wdt_reset_counter(); - return len; - } - return 0; -} - -static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int new_timeout; - static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 0, - .identity = "ADM5120_WDT Watchdog", - }; - switch (cmd) { - default: - return -ENOTTY; - case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, &ident, sizeof(ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user(0, (int *)arg); - case WDIOC_KEEPALIVE: - wdt_reset_counter(); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) - return -EFAULT; - if (new_timeout < 1) - return -EINVAL; - if (new_timeout > MAX_TIMEOUT) - return -EINVAL; - timeout = new_timeout; - wdt_set_timeout(); - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user(timeout, (int *)arg); - } -} - -static const struct file_operations wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = wdt_write, - .unlocked_ioctl = wdt_ioctl, - .open = wdt_open, - .release = wdt_release, -}; - -static struct miscdevice wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &wdt_fops, -}; - -static char banner[] __initdata = KERN_INFO NAME ": Watchdog Timer version " VERSION "\n"; - -static int __init watchdog_init(void) -{ - int ret; - - ret = misc_register(&wdt_miscdev); - - if (ret) - return ret; - - wdt_disable(); - printk(banner); - - return 0; -} - -static void __exit watchdog_exit(void) -{ - misc_deregister(&wdt_miscdev); -} - -module_init(watchdog_init); -module_exit(watchdog_exit);