From: Gabor Juhos Date: Sun, 5 Oct 2008 11:07:49 +0000 (+0000) Subject: experimental support for 2.6.27 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=6bfeb815486de741db535b4c93b5d7f9aeb2b3c5;p=librecmc%2Flibrecmc.git experimental support for 2.6.27 SVN-Revision: 12863 --- diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/Kconfig b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/Kconfig deleted file mode 100644 index 71868f9b5f..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/Kconfig +++ /dev/null @@ -1,177 +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_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_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_INFINEON - def_bool n - -config ADM5120_OEM_MIKROTIK - def_bool n - -config ADM5120_OEM_MOTOROLA - def_bool n - -config ADM5120_OEM_ZYXEL - def_bool n - -config ARM_AMBA - def_bool y - -endif diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/Makefile deleted file mode 100644 index a949fc9f61..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/cellvision/cas-771.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cas-771.c deleted file mode 100644 index 26995bb0a1..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cas-771.c +++ /dev/null @@ -1,36 +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); -} - -ADM5120_BOARD(MACH_ADM5120_CAS771, "Cellvision CAS-771/771W", cas771_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.c deleted file mode 100644 index 282c8c778c..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.c +++ /dev/null @@ -1,152 +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 - -#ifdef CONFIG_MTD_PARTITIONS -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, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -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) -{ -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas6xx_partitions); - adm5120_flash0_data.parts = cas6xx_partitions; -#endif /* CONFIG_MTD_PARTITIONS */ - - cellvision_flash_setup(); -} - -void __init cas7xx_flash_setup(void) -{ -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas7xx_partitions); - adm5120_flash0_data.parts = cas7xx_partitions; -#endif /* CONFIG_MTD_PARTITIONS */ - - cellvision_flash_setup(); -} - -#if 0 -void __init cas6xx_setup(void) -{ - cas6xx_flash_setup(); - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - adm5120_add_device_switch(1, NULL); -} - -ADM5120_BOARD(MACH_ADM5120_CAS630, "Cellvision CAS-630/630W", cas6xx_setup); -ADM5120_BOARD(MACH_ADM5120_CAS670, "Cellvision CAS-670/670W", cas6xx_setup); -#endif - -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); -} - -#if 0 -ADM5120_BOARD(MACH_ADM5120_CAS700, "Cellvision CAS-700/700W", cas7xx_setup); -ADM5120_BOARD(MACH_ADM5120_CAS790, "Cellvision CAS-790", cas7xx_setup); -ADM5120_BOARD(MACH_ADM5120_CAS861, "Cellvision CAS-861/861W", cas7xx_setup); -#endif diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.h deleted file mode 100644 index 175fbb249c..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/cellvision.h +++ /dev/null @@ -1,29 +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 -#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-2.6.26/arch/mips/adm5120/cellvision/nfs-101.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/nfs-101.c deleted file mode 100644 index 3482e11bd2..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/cellvision/nfs-101.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Cellvision/SparkLAN NFS-101U/WU 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 u8 nfs101_vlans[6] __initdata = { /* TODO: not tested */ - 0x41, 0x42, 0x44, 0x48, 0x50, 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(5, nfs101_vlans); -} - -ADM5120_BOARD(MACH_ADM5120_NFS101U, "Cellvision NFS-101U/101WU", nfs101_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/Makefile deleted file mode 100644 index 663fd21501..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/Makefile +++ /dev/null @@ -1,6 +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 board.o clock.o \ - gpio.o platform.o diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/adm5120.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/adm5120.c deleted file mode 100644 index f227e871da..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/adm5120.c +++ /dev/null @@ -1,77 +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 - -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-2.6.26/arch/mips/adm5120/common/board.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/board.c deleted file mode 100644 index be1fc9ab03..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/board.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ADM5120 generic board code - * - * 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 - -#define PFX "ADM5120: " - -static struct list_head adm5120_boards __initdata = - LIST_HEAD_INIT(adm5120_boards); - -static char adm5120_board_name[ADM5120_BOARD_NAMELEN] = "Unknown board"; - -const char *get_system_type(void) -{ - return adm5120_board_name; -} - -static struct adm5120_board * __init adm5120_board_find(unsigned long machtype) -{ - struct list_head *this; - - list_for_each(this, &adm5120_boards) { - struct adm5120_board *board; - - board = list_entry(this, struct adm5120_board, list); - if (board->mach_type == machtype) - return board; - } - - return NULL; -} - -static int __init adm5120_board_setup(void) -{ - struct adm5120_board *board; - - board = adm5120_board_find(mips_machtype); - if (board == NULL) - panic(PFX "no board registered for machtype %lu\n", - mips_machtype); - - if (board->name[0]) - strlcpy(adm5120_board_name, board->name, ADM5120_BOARD_NAMELEN); - - printk(KERN_INFO PFX "board is '%s'\n", adm5120_board_name); - - adm5120_gpio_init(); - - if (board->board_setup) - board->board_setup(); - - return 0; -} -arch_initcall(adm5120_board_setup); - -void __init adm5120_board_register(struct adm5120_board *board) -{ - list_add_tail(&board->list, &adm5120_boards); -} - -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); -} - -ADM5120_BOARD(MACH_ADM5120_GENERIC, "Generic ADM5120 board", - adm5120_generic_board_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/clock.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/clock.c deleted file mode 100644 index d004309959..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/clock.c +++ /dev/null @@ -1,62 +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 - -struct clk { - unsigned long rate; -}; - -static struct clk uart_clk = { - .rate = ADM5120_UART_CLOCK -}; - -struct clk *clk_get(struct device *dev, const char *id) -{ - if (!strcmp(id, "UARTCLK")) - 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-2.6.26/arch/mips/adm5120/common/gpio.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c deleted file mode 100644 index 8143d31f67..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/gpio.c +++ /dev/null @@ -1,331 +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 -#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-2.6.26/arch/mips/adm5120/common/irq.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/irq.c deleted file mode 100644 index 140a7a0e95..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/irq.c +++ /dev/null @@ -1,176 +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(unsigned int irq); -static void adm5120_intc_irq_mask(unsigned int irq); -static int adm5120_intc_irq_set_type(unsigned int irq, 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", - .unmask = adm5120_intc_irq_unmask, - .mask = adm5120_intc_irq_mask, - .mask_ack = adm5120_intc_irq_mask, - .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(unsigned int irq) -{ - irq -= ADM5120_INTC_IRQ_BASE; - intc_write_reg(INTC_REG_IRQ_ENABLE, 1 << irq); -} - -static void adm5120_intc_irq_mask(unsigned int irq) -{ - irq -= ADM5120_INTC_IRQ_BASE; - intc_write_reg(INTC_REG_IRQ_DISABLE, 1 << irq); -} - -static int adm5120_intc_irq_set_type(unsigned int irq, unsigned int flow_type) -{ - 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); - /* fallthrough */ - default: - irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK; - irq_desc[irq].status |= sense; - 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_desc[i].status = INTC_IRQ_STATUS; - set_irq_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-2.6.26/arch/mips/adm5120/common/memory.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/memory.c deleted file mode 100644 index d07266fa38..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/common/platform.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/platform.c deleted file mode 100644 index 9526fe977f..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/platform.c +++ /dev/null @@ -1,380 +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 - -#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 = { - .bus_id = "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, -1 }, - .periphid = 0x0041010, -}; - -struct amba_pl010_data adm5120_uart1_data = { - .set_mctrl = adm5120_uart_set_mctrl -}; - -struct amba_device adm5120_uart1_device = { - .dev = { - .bus_id = "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, -1 }, - .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 - */ -#define ADM5120_BUTTON_INTERVAL 20 -struct gpio_buttons_platform_data adm5120_gpio_buttons_data = { - .poll_interval = ADM5120_BUTTON_INTERVAL, -}; - -struct platform_device adm5120_gpio_buttons_device = { - .name = "gpio-buttons", - .id = -1, - .dev.platform_data = &adm5120_gpio_buttons_data, -}; - -void __init adm5120_add_device_gpio_buttons(unsigned nbuttons, - struct gpio_button *buttons) -{ - struct gpio_button *p; - - p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); - if (!p) - return; - - memcpy(p, buttons, nbuttons * sizeof(*p)); - adm5120_gpio_buttons_data.nbuttons = nbuttons; - adm5120_gpio_buttons_data.buttons = p; - - platform_device_register(&adm5120_gpio_buttons_device); -} - -/* - * 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); -} - -/* - * GPIO device - */ -static struct resource adm5120_gpio_resource[] __initdata = { - { - .start = 0x3fffff, - }, -}; - -void __init adm5120_add_device_gpio(u32 disable_mask) -{ - if (adm5120_package_pqfp()) - disable_mask |= 0xf0; - - adm5120_gpio_resource[0].start &= ~disable_mask; - platform_device_register_simple("GPIODEV", -1, - adm5120_gpio_resource, - ARRAY_SIZE(adm5120_gpio_resource)); -} - -/* - * 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-2.6.26/arch/mips/adm5120/common/prom.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/prom.c deleted file mode 100644 index 4c48dc0be2..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/prom.c +++ /dev/null @@ -1,271 +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 -#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), - /* Motorola boards */ - DEFBOARD("Powerline MU Gateway",MACH_ADM5120_PMUGW), -}; - -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; -} - -/* TODO: this is an ugly hack for RouterBOARDS */ -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 + 8; - if (strlen(cmd) > 0) - strlcpy(arcs_cmdline, cmd, sizeof(arcs_cmdline)); - -} - -#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); -} - -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-2.6.26/arch/mips/adm5120/common/setup.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/setup.c deleted file mode 100644 index 0a11774624..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/common/setup.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * ADM5120 specific setup - * - * 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 - -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 : ADM%04X%s revision %d, running " - "at %ldMHz\n", - adm5120_product_code, - adm5120_package_bga() ? "" : "P", - adm5120_revision, (adm5120_speed / 1000000)); - printk(KERN_INFO "Bootdev : %s flash\n", - adm5120_nand_boot ? "NAND":"NOR"); - printk(KERN_INFO "Prom : %s\n", prom_names[adm5120_prom_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(); - adm5120_report(); - - _machine_restart = adm5120_restart; - _machine_halt = adm5120_halt; - pm_power_off = adm5120_halt; - - set_io_port_base(KSEG1); -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/Makefile deleted file mode 100644 index 8c66c171e7..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/compex/compex.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/compex.c deleted file mode 100644 index c14655ada7..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/compex.c +++ /dev/null @@ -1,64 +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 - -#define COMPEX_GPIO_DEV_MASK (1 << ADM5120_GPIO_PIN5) - -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); - - adm5120_add_device_gpio(COMPEX_GPIO_DEV_MASK); - - compex_mac_setup(); -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/compex.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/compex.h deleted file mode 100644 index 62425374ad..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/compex.h +++ /dev/null @@ -1,24 +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 -#include - -extern void compex_generic_setup(void) __init; diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/np27g.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/np27g.c deleted file mode 100644 index edd980ed7d..0000000000 --- a/target/linux/adm5120/files-2.6.26/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 */ -} - -ADM5120_BOARD(MACH_ADM5120_NP27G, "Compex NetPassage 27G", np27g_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/np28g.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/np28g.c deleted file mode 100644 index eba288fc66..0000000000 --- a/target/linux/adm5120/files-2.6.26/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); -} - -ADM5120_BOARD(MACH_ADM5120_NP28G, "Compex NetPassage 28G", np28g_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/wp54.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/wp54.c deleted file mode 100644 index 86b9d681b3..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/compex/wp54.c +++ /dev/null @@ -1,94 +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" - -#ifdef CONFIG_MTD_PARTITIONS -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, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -static struct adm5120_pci_irq wp54_pci_irqs[] __initdata = { - PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), -}; - -static struct gpio_button wp54_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = BTN_0, - .threshold = 5, - .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_add_device_gpio_buttons(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); -} - -ADM5120_BOARD(MACH_ADM5120_WP54, "Compex WP54 family", wp54_setup); - -static void __init wp54_wrt_setup(void) -{ -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(wp54g_wrt_partitions); - adm5120_flash0_data.parts = wp54g_wrt_partitions; -#endif - - wp54_setup(); -} - -ADM5120_BOARD(MACH_ADM5120_WP54G_WRT, "Compex WP54G-WRT", wp54_wrt_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/Makefile deleted file mode 100644 index 1286ed4c1e..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/edimax/br-6104k.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-6104k.c deleted file mode 100644 index b0ed8fa373..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-6104k.c +++ /dev/null @@ -1,35 +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); -} - -ADM5120_BOARD(MACH_ADM5120_BR6104K, "Edimax BR-6104K", br6104k_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-6104kp.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-6104kp.c deleted file mode 100644 index e0556b7416..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-6104kp.c +++ /dev/null @@ -1,38 +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_STD(ADM5120_GPIO_PIN1, "usb1", NULL), - GPIO_LED_INV(ADM5120_GPIO_PIN3, "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(); -} - -ADM5120_BOARD(MACH_ADM5120_BR6104KP, "Edimax BR-6104KP", br6104kp_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61x4wg.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61x4wg.c deleted file mode 100644 index 98d64f1559..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61x4wg.c +++ /dev/null @@ -1,42 +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); -} - -ADM5120_BOARD(MACH_ADM5120_BR61X4WG, "Edimax BR-6104WG/6114WG", br61x4wg_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61xx.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61xx.c deleted file mode 100644 index 6ecdb4e425..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61xx.c +++ /dev/null @@ -1,87 +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_GPIO_DEV_MASK 0 - -#define BR61XX_CONFIG_OFFSET 0x8000 -#define BR61XX_CONFIG_SIZE 0x1000 - -#ifdef CONFIG_MTD_PARTITIONS -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, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -static struct gpio_button br61xx_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = BTN_0, - .threshold = 5, - .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) -{ - -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(br61xx_partitions); - adm5120_flash0_data.parts = br61xx_partitions; -#endif /* CONFIG_MTD_PARTITIONS */ - adm5120_add_device_flash(0); - - adm5120_add_device_gpio(BR61XX_GPIO_DEV_MASK); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_switch(5, br61xx_vlans); - adm5120_add_device_gpio_buttons(ARRAY_SIZE(br61xx_gpio_buttons), - br61xx_gpio_buttons); - - br61xx_mac_setup(); -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61xx.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/edimax/br-61xx.h deleted file mode 100644 index f8ad137a49..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/infineon/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/Makefile deleted file mode 100644 index 49453cba9a..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/infineon/easy5120-rt.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120-rt.c deleted file mode 100644 index 618564e5c0..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120-rt.c +++ /dev/null @@ -1,49 +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); -} - -ADM5120_BOARD(MACH_ADM5120_EASY5120RT, - "Infineon EASY 5120-RT Reference Board", - easy5120_rt_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120-wvoip.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120-wvoip.c deleted file mode 100644 index f51f4634cb..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120-wvoip.c +++ /dev/null @@ -1,25 +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 */ -} - -ADM5120_BOARD(MACH_ADM5120_EASY5120WVOIP, - "Infineon EASY 5120-WVoIP Reference Board", - easy5120wvoip_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120p-ata.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120p-ata.c deleted file mode 100644 index 90c975bf09..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy5120p-ata.c +++ /dev/null @@ -1,23 +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); -} - -ADM5120_BOARD(MACH_ADM5120_EASY5120PATA, - "Infineon EASY 5120P-ATA Reference Board", - easy5120pata_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy83000.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy83000.c deleted file mode 100644 index dd14badd32..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/easy83000.c +++ /dev/null @@ -1,24 +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 */ -} - -ADM5120_BOARD(MACH_ADM5120_EASY83000, - "Infineon EASY 83000 Reference Board", - easy83000_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/infineon.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/infineon.c deleted file mode 100644 index b52edf0f67..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/infineon.c +++ /dev/null @@ -1,114 +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 - -#ifdef CONFIG_MTD_PARTITIONS -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, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -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; - -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); - adm5120_flash0_data.parts = easy_partitions; -#endif /* CONFIG_MTD_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; - -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); - adm5120_flash0_data.parts = easy_partitions; -#endif /* CONFIG_MTD_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-2.6.26/arch/mips/adm5120/infineon/infineon.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/infineon.h deleted file mode 100644 index 2e25a8f3de..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/infineon/infineon.h +++ /dev/null @@ -1,26 +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 -#include - -extern void easy_setup_pqfp(void) __init; -extern void easy_setup_bga(void) __init; diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/Makefile deleted file mode 100644 index 34ea0a3d88..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/mikrotik/rb-11x.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-11x.c deleted file mode 100644 index e238c625af..0000000000 --- a/target/linux/adm5120/files-2.6.26/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(0); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb11x_gpio_leds), - rb11x_gpio_leds); -} - -ADM5120_BOARD(MACH_ADM5120_RB_11X, "Mikrotik RouterBOARD 111/112", rb11x_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-133.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-133.c deleted file mode 100644 index 9000a20830..0000000000 --- a/target/linux/adm5120/files-2.6.26/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(0); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133_gpio_leds), - rb133_gpio_leds); -} - -ADM5120_BOARD(MACH_ADM5120_RB_133, "Mikrotik RouterBOARD 133", rb133_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-133c.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-133c.c deleted file mode 100644 index 9003b868e3..0000000000 --- a/target/linux/adm5120/files-2.6.26/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(0); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133c_gpio_leds), - rb133c_gpio_leds); -} - -ADM5120_BOARD(MACH_ADM5120_RB_133C, "Mikrotik RouterBOARD 133C", rb133c_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-150.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-150.c deleted file mode 100644 index bba3be233f..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-150.c +++ /dev/null @@ -1,136 +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_GPIO_DEV_MASK ( 1 << RB150_GPIO_NAND_READY \ - | 1 << RB150_GPIO_NAND_NCE \ - | 1 << RB150_GPIO_NAND_CLE \ - | 1 << RB150_GPIO_NAND_ALE) - -#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(RB150_GPIO_DEV_MASK); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb150_gpio_leds), - rb150_gpio_leds); - adm5120_add_device_switch(5, rb150_vlans); -} - -ADM5120_BOARD(MACH_ADM5120_RB_150, "Mikrotik RouterBOARD 150", rb150_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-153.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-153.c deleted file mode 100644 index ee38ff2735..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-153.c +++ /dev/null @@ -1,74 +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" - -#define RB153_GPIO_DEV_MASK ( 1 << ADM5120_GPIO_PIN0 \ - | 1 << ADM5120_GPIO_PIN3 \ - | 1 << ADM5120_GPIO_PIN4 ) - -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(RB153_GPIO_DEV_MASK); - adm5120_add_device_gpio_leds(ARRAY_SIZE(rb153_gpio_leds), - rb153_gpio_leds); - adm5120_add_device_switch(5, rb153_vlans); -} - -ADM5120_BOARD(MACH_ADM5120_RB_153, "Mikrotik RouterBOARD 153", rb153_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-192.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-192.c deleted file mode 100644 index 0821607c87..0000000000 --- a/target/linux/adm5120/files-2.6.26/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_gpio(0); - adm5120_add_device_switch(6, rb192_vlans); -} - -ADM5120_BOARD(MACH_ADM5120_RB_192, "Mikrotik RouterBOARD 192", rb192_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.c deleted file mode 100644 index 7fc6e74dad..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.c +++ /dev/null @@ -1,152 +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 - -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) -}; - -#ifdef CONFIG_MTD_PARTITIONS -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 - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -/* - * 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, -#ifdef CONFIG_MTD_PARTITIONS - .nr_partitions = ARRAY_SIZE(rb1xx_nand_parts), - .partitions = rb1xx_nand_parts, -#endif /* CONFIG_MTD_PARTITIONS */ - .chip_delay = RB1XX_NAND_CHIP_DELAY, - .options = NAND_NO_AUTOINCR, - .chip_fixup = rb1xx_nand_fixup, - }, -}; - -struct gpio_button rb1xx_gpio_buttons[] __initdata = { - { - .desc = "reset_button", - .type = EV_KEY, - .code = BTN_0, - .threshold = 5, - .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 */ -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(rb1xx_nor_parts); - adm5120_flash0_data.parts = rb1xx_nor_parts; -#endif /* CONFIG_MTD_PARTITIONS */ - 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_add_device_gpio_buttons(ARRAY_SIZE(rb1xx_gpio_buttons), - rb1xx_gpio_buttons); - - rb1xx_add_device_flash(); - rb1xx_mac_setup(); -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.h deleted file mode 100644 index 1577ed66d0..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/mikrotik/rb-1xx.h +++ /dev/null @@ -1,34 +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 - -#include - -extern struct platform_nand_data rb1xx_nand_data __initdata; -extern struct gpio_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-2.6.26/arch/mips/adm5120/motorola/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/motorola/Makefile deleted file mode 100644 index 239d5a0880..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/motorola/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ADM5120_MACH_PMUGW) += pmugw.o diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/motorola/pmugw.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/motorola/pmugw.c deleted file mode 100644 index a74d37d4f3..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/motorola/pmugw.c +++ /dev/null @@ -1,102 +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 - -#include - -#define PMUGW_CONFIG_OFFSET 0x10000 -#define PMUGW_CONFIG_SIZE 0x1000 - -#ifdef CONFIG_MTD_PARTITIONS -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, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -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; - -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(pmugw_partitions); - adm5120_flash0_data.parts = pmugw_partitions; -#endif /* CONFIG_MTD_PARTITIONS */ - - adm5120_add_device_uart(1); /* ttyS0 */ - adm5120_add_device_uart(0); /* ttyS1 */ - - adm5120_add_device_flash(0); - - pmugw_setup_mac(); - adm5120_add_device_switch(5, pmugw_vlans); -} - -ADM5120_BOARD(MACH_ADM5120_PMUGW, - "Motorola Powerline MU Gateway", - pmugw_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/Makefile deleted file mode 100644 index 650be40779..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/prom/admboot.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/admboot.c deleted file mode 100644 index 5d436f62f6..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/admboot.c +++ /dev/null @@ -1,46 +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' */ - -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; - } - } - - return -ENXIO; -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/bootbase.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/bootbase.c deleted file mode 100644 index b6a94ff46a..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/bootbase.c +++ /dev/null @@ -1,120 +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 -#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-2.6.26/arch/mips/adm5120/prom/cfe.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/cfe.c deleted file mode 100644 index 5a343cd7e4..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/prom/generic.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/generic.c deleted file mode 100644 index 4d4caa8476..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/prom/myloader.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/myloader.c deleted file mode 100644 index 939422681b..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/myloader.c +++ /dev/null @@ -1,69 +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 -#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-2.6.26/arch/mips/adm5120/prom/prom_read.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/prom_read.h deleted file mode 100644 index 1a6ea110ce..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/prom/routerboot.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/prom/routerboot.c deleted file mode 100644 index d9e1096cbe..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/zyxel/Makefile b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/Makefile deleted file mode 100644 index e8325a1b1f..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/adm5120/zyxel/p-334wt.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-334wt.c deleted file mode 100644 index 6eb23dab9c..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-334wt.c +++ /dev/null @@ -1,33 +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); -} - -ADM5120_BOARD(MACH_ADM5120_P334WT, "ZyXEL Prestige 334WT", p334wt_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-335.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-335.c deleted file mode 100644 index 0e6cdd96ef..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-335.c +++ /dev/null @@ -1,20 +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(); -} - -ADM5120_BOARD(MACH_ADM5120_P335, "ZyXEL Prestige 335/335WT", p335_setup); diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-33x.c b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-33x.c deleted file mode 100644 index 6d4d4ddee7..0000000000 --- a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-33x.c +++ /dev/null @@ -1,89 +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 -#define P33X_GPIO_DEV_MASK (1 << P33X_GPIO_FLASH_A20) - -#ifdef CONFIG_MTD_PARTITIONS -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, - } , { - .name = "bootext", - .offset = MTDPART_OFS_APPEND, - .size = 96*1024, - .mask_flags = MTD_WRITEABLE, - } , { - .name = "trx", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - } , { - .name = "firmware", - .offset = 32*1024, - .size = MTDPART_SIZ_FULL, - } -}; -#endif /* CONFIG_MTD_PARTITIONS */ - -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; -#ifdef CONFIG_MTD_PARTITIONS - adm5120_flash0_data.nr_parts = ARRAY_SIZE(p33x_partitions); - adm5120_flash0_data.parts = p33x_partitions; -#endif /* CONFIG_MTD_PARTITIONS */ - adm5120_add_device_flash(0); - - adm5120_add_device_uart(0); - adm5120_add_device_uart(1); - - adm5120_add_device_gpio(P33X_GPIO_DEV_MASK); - - adm5120_setup_eth_macs(bootbase_info.mac); - adm5120_add_device_switch(5, p33x_vlans); - - adm5120_pci_set_irq_map(ARRAY_SIZE(p33x_pci_irqs), p33x_pci_irqs); -} diff --git a/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-33x.h b/target/linux/adm5120/files-2.6.26/arch/mips/adm5120/zyxel/p-33x.h deleted file mode 100644 index 0971cd5d26..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/arch/mips/pci/pci-adm5120.c b/target/linux/adm5120/files-2.6.26/arch/mips/pci/pci-adm5120.c deleted file mode 100644 index bde3e32082..0000000000 --- a/target/linux/adm5120/files-2.6.26/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 spinlock_t pci_lock = SPIN_LOCK_UNLOCKED; - -/* -------------------------------------------------------------------------*/ - -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 > 3) { - 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-2.6.26/drivers/ata/pata_rb153_cf.c b/target/linux/adm5120/files-2.6.26/drivers/ata/pata_rb153_cf.c deleted file mode 100644 index ef7f5835ae..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/ata/pata_rb153_cf.c +++ /dev/null @@ -1,268 +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); - - 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)) { - set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); - if (!info->frozen) - ata_sff_interrupt(irq, dev_instance); - } else { - 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->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; - - 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 __devinit 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 __devexit 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 = __devexit_p(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-2.6.26/drivers/leds/ledtrig-adm5120-switch.c b/target/linux/adm5120/files-2.6.26/drivers/leds/ledtrig-adm5120-switch.c deleted file mode 100644 index b4a5dbbea9..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/drivers/mtd/maps/adm5120-flash.c b/target/linux/adm5120/files-2.6.26/drivers/mtd/maps/adm5120-flash.c deleted file mode 100644 index 8bd7ae1c0b..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/mtd/maps/adm5120-flash.c +++ /dev/null @@ -1,568 +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; -#ifdef CONFIG_MTD_PARTITIONS - int nr_parts; - struct mtd_partition *parts[MAX_PARSED_PARTS]; -#endif -}; - -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 *probe_types[] = { - "cfi_probe", - "jedec_probe", - "map_rom", - NULL -}; - -#ifdef CONFIG_MTD_PARTITIONS -static const char *parse_types[] = { - "cmdlinepart", -#ifdef CONFIG_MTD_REDBOOT_PARTS - "RedBoot", -#endif -#ifdef CONFIG_MTD_MYLOADER_PARTS - "MyLoader", -#endif -}; -#endif - -#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->dev.bus_id; - - 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; -} - -#ifdef CONFIG_MTD_PARTITIONS -static int adm5120_flash_initparts(struct adm5120_flash_info *info) -{ - struct adm5120_flash_platform_data *pdata; - struct map_info *map = &info->amap.map; - int num_parsers; - const char *parser[2]; - int err = 0; - int nr_parts; - int i; - - info->nr_parts = 0; - - pdata = info->dev->dev.platform_data; - if (pdata == NULL) - goto out; - - if (pdata->nr_parts) { - MAP_INFO(map, "adding static partitions\n"); - err = add_mtd_partitions(info->mtd, pdata->parts, - pdata->nr_parts); - if (err == 0) { - info->nr_parts += pdata->nr_parts; - goto out; - } - } - - num_parsers = ARRAY_SIZE(parse_types); - if (num_parsers > MAX_PARSED_PARTS) - num_parsers = MAX_PARSED_PARTS; - - parser[1] = NULL; - for (i = 0; i < num_parsers; i++) { - parser[0] = parse_types[i]; - - MAP_INFO(map, "parsing \"%s\" partitions\n", - parser[0]); - nr_parts = parse_mtd_partitions(info->mtd, parser, - &info->parts[i], 0); - - if (nr_parts <= 0) - continue; - - MAP_INFO(map, "adding \"%s\" partitions\n", - parser[0]); - - err = add_mtd_partitions(info->mtd, info->parts[i], nr_parts); - if (err) - break; - - info->nr_parts += nr_parts; - } -out: - return err; -} -#else -static int adm5120_flash_initparts(struct adm5120_flash_info *info) -{ - return 0; -} -#endif /* CONFIG_MTD_PARTITIONS */ - -#ifdef CONFIG_MTD_PARTITIONS -static void adm5120_flash_remove_mtd(struct adm5120_flash_info *info) -{ - int i; - - if (info->nr_parts) { - del_mtd_partitions(info->mtd); - for (i = 0; i < MAX_PARSED_PARTS; i++) - if (info->parts[i] != NULL) - kfree(info->parts[i]); - } else { - del_mtd_device(info->mtd); - } -} -#else -static void adm5120_flash_remove_mtd(struct adm5120_flash_info *info) -{ - del_mtd_device(info->mtd); -} -#endif - -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) { - adm5120_flash_remove_mtd(info); - 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_info *info; - struct map_info *map; - const char **probe_type; - int err; - - 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 = adm5120_flash_initparts(info); - if (err) - goto err_out; - - if (info->nr_parts == 0) { - MAP_INFO(map, "no partitions available, registering " - "whole flash\n"); - add_mtd_device(info->mtd); - } - - 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-2.6.26/drivers/mtd/myloader.c b/target/linux/adm5120/files-2.6.26/drivers/mtd/myloader.c deleted file mode 100644 index 22d076b72c..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/mtd/myloader.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Parse MyLoader-style flash partition tables and produce a Linux partition - * array to match. - * - * Copyright (C) 2007-2008 Gabor Juhos - * - * This file was based on drivers/mtd/redboot.c - * Author: Red Hat, Inc. - David Woodhouse - * - * 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 - -#define NAME_LEN_MAX 20 -#define NAME_MYLOADER "MyLoader" -#define NAME_PARTITION_TABLE "Partition Table" -#define BLOCK_LEN_MIN 0x10000 - -int parse_myloader_partitions(struct mtd_info *master, - struct mtd_partition **pparts, - unsigned long origin) -{ - struct mylo_partition_table *tab; - struct mylo_partition *part; - struct mtd_partition *mtd_parts; - struct mtd_partition *mtd_part; - int num_parts; - int ret, i; - size_t retlen; - char *names; - unsigned long offset; - unsigned long blocklen; - - tab = vmalloc(sizeof(*tab)); - if (!tab) { - return -ENOMEM; - goto out; - } - - blocklen = master->erasesize; - if (blocklen < BLOCK_LEN_MIN) - blocklen = BLOCK_LEN_MIN; - - /* Partition Table is always located on the second erase block */ - offset = blocklen; - printk(KERN_NOTICE "%s: searching for MyLoader partition table at " - "offset 0x%lx\n", master->name, offset); - - ret = master->read(master, offset, sizeof(*tab), &retlen, (void *)tab); - if (ret) - goto out; - - if (retlen != sizeof(*tab)) { - ret = -EIO; - goto out_free_buf; - } - - /* Check for Partition Table magic number */ - if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) { - printk(KERN_NOTICE "%s: no MyLoader partition table found\n", - master->name); - ret = 0; - goto out_free_buf; - } - - /* The MyLoader and the Partition Table is always present */ - num_parts = 2; - - /* Detect number of used partitions */ - for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { - part = &tab->partitions[i]; - - if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) - continue; - - num_parts++; - } - - mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + - num_parts * NAME_LEN_MAX), GFP_KERNEL); - - if (!mtd_parts) { - ret = -ENOMEM; - goto out_free_buf; - } - - mtd_part = mtd_parts; - names = (char *)&mtd_parts[num_parts]; - - strncpy(names, NAME_MYLOADER, NAME_LEN_MAX-1); - mtd_part->name = names; - mtd_part->offset = 0; - mtd_part->size = blocklen; - mtd_part->mask_flags = MTD_WRITEABLE; - mtd_part++; - names += NAME_LEN_MAX; - - strncpy(names, NAME_PARTITION_TABLE, NAME_LEN_MAX-1); - mtd_part->name = names; - mtd_part->offset = blocklen; - mtd_part->size = blocklen; - mtd_part->mask_flags = MTD_WRITEABLE; - mtd_part++; - names += NAME_LEN_MAX; - - for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { - part = &tab->partitions[i]; - - if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) - continue; - - sprintf(names, "partition%d", i); - mtd_part->offset = le32_to_cpu(part->addr); - mtd_part->size = le32_to_cpu(part->size); - mtd_part->name = names; - mtd_part++; - names += NAME_LEN_MAX; - } - - *pparts = mtd_parts; - ret = num_parts; - -out_free_buf: - vfree(tab); -out: - return ret; -} - -static struct mtd_part_parser mylo_mtd_parser = { - .owner = THIS_MODULE, - .parse_fn = parse_myloader_partitions, - .name = NAME_MYLOADER, -}; - -static int __init mylo_mtd_parser_init(void) -{ - return register_mtd_parser(&mylo_mtd_parser); -} - -static void __exit mylo_mtd_parser_exit(void) -{ - deregister_mtd_parser(&mylo_mtd_parser); -} - -module_init(mylo_mtd_parser_init); -module_exit(mylo_mtd_parser_exit); - -MODULE_AUTHOR("Gabor Juhos "); -MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files-2.6.26/drivers/mtd/trxsplit.c b/target/linux/adm5120/files-2.6.26/drivers/mtd/trxsplit.c deleted file mode 100644 index 7e4a63b74b..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/mtd/trxsplit.c +++ /dev/null @@ -1,217 +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 = add_mtd_partitions(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 */ - del_mtd_partitions(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-2.6.26/drivers/net/adm5120sw.c b/target/linux/adm5120/files-2.6.26/drivers/net/adm5120sw.c deleted file mode 100644 index 7acc84d248..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/net/adm5120sw.c +++ /dev/null @@ -1,1203 +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" - -#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_DBG "%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 spinlock_t tx_lock = SPIN_LOCK_UNLOCKED; - -/* ------------------------------------------------------------------------ */ - -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); -} - -/* ------------------------------------------------------------------------ */ - -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); -} - -/* ------------------------------------------------------------------------ */ - -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 = 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); - netif_rx_complete(dev, 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); - netif_rx_schedule(dev, &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; portnapi); -} - -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 | IRQF_DISABLED), 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->lenlen) << 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_multicast_list(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 || - dev->mc_count) - /* 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; /* Disable Bridge Testing Mode */ - else - t |= CPUP_CONF_BTM; /* Enable Bridge Testing Mode */ - - sw_write_reg(SWITCH_REG_CPUP_CONF, t); - -} - -static int adm5120_if_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - 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 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->open = adm5120_if_open; - dev->hard_start_xmit = adm5120_if_hard_start_xmit; - dev->stop = adm5120_if_stop; - dev->set_multicast_list = adm5120_if_set_multicast_list; - dev->do_ioctl = adm5120_if_do_ioctl; - dev->tx_timeout = adm5120_if_tx_timeout; - dev->watchdog_timeo = TX_TIMEOUT; - dev->set_mac_address = adm5120_if_set_mac_address; - -#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 __init 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 *dev) -{ - 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-2.6.26/drivers/net/adm5120sw.h b/target/linux/adm5120/files-2.6.26/drivers/net/adm5120sw.h deleted file mode 100644 index c7c5ceddc7..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/drivers/usb/host/adm5120-dbg.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-dbg.c deleted file mode 100644 index c121f7be2d..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-dbg.c +++ /dev/null @@ -1,842 +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 (" %02x", ((__u8 *) urb->setup_packet) [i]); - printk ("\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(" %02x", ((__u8 *)urb->transfer_buffer)[i]); - printk("%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) {} -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, -}; -static const struct file_operations debug_periodic_fops = { - .owner = THIS_MODULE, - .open = debug_periodic_open, - .read = debug_output, - .release = debug_close, -}; -static const struct file_operations debug_registers_fops = { - .owner = THIS_MODULE, - .open = debug_registers_open, - .read = debug_output, - .release = debug_close, -}; - -static struct dentry *admhc_debug_root; - -struct debug_buffer { - ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ - struct device *dev; - 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 usb_bus *bus; - struct usb_hcd *hcd; - struct admhcd *ahcd; - size_t temp; - unsigned long flags; - - bus = dev_get_drvdata(buf->dev); - hcd = bus_to_hcd(bus); - ahcd = hcd_to_admhcd(hcd); - - 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 usb_bus *bus; - struct usb_hcd *hcd; - struct admhcd *ahcd; - struct ed **seen, *ed; - unsigned long flags; - unsigned temp, size, seen_count; - char *next; - unsigned i; - - if (!(seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) - return 0; - seen_count = 0; - - bus = dev_get_drvdata(buf->dev); - hcd = bus_to_hcd(bus); - ahcd = hcd_to_admhcd(hcd); - 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++) { - if (!(ed = ahcd->periodic [i])) - 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_bus *bus; - struct usb_hcd *hcd; - struct admhcd *ahcd; - struct admhcd_regs __iomem *regs; - unsigned long flags; - unsigned temp, size; - char *next; - u32 rdata; - - bus = dev_get_drvdata(buf->dev); - hcd = bus_to_hcd(bus); - ahcd = hcd_to_admhcd(hcd); - 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 version " DRIVER_VERSION "\n", - hcd->self.controller->bus->name, - hcd->self.controller->bus_id, - hcd->product_desc, - hcd_name); - - if (bus->controller->power.power_state.event) { - 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 device *dev, - ssize_t (*fill_func)(struct debug_buffer *)) -{ - struct debug_buffer *buf; - - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); - - if (buf) { - buf->dev = dev; - 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; - struct device *dev = bus->dev; - - 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, dev, - &debug_async_fops); - if (!ahcd->debug_async) - goto async_error; - - ahcd->debug_periodic = debugfs_create_file("periodic", S_IRUGO, - ahcd->debug_dir, dev, - &debug_periodic_fops); - if (!ahcd->debug_periodic) - goto periodic_error; - - ahcd->debug_registers = debugfs_create_file("registers", S_IRUGO, - ahcd->debug_dir, dev, - &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-2.6.26/drivers/usb/host/adm5120-drv.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-drv.c deleted file mode 100644 index bf250c056b..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-drv.c +++ /dev/null @@ -1,236 +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 Rusell 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, IRQF_DISABLED); - 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 __devinit -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, - .hub_irq_enable = admhc_hub_irq_enable, -#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-2.6.26/drivers/usb/host/adm5120-hcd.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-hcd.c deleted file mode 100644 index c947a6c2dc..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-hcd.c +++ /dev/null @@ -1,845 +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 -#include - -#include "../core/hcd.h" -#include "../core/hub.h" - -#define DRIVER_VERSION "0.25.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 upto 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 (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { - 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); - return; -} - -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 temp; - 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) { - temp = admhc_readl(ahcd, &ahcd->regs->fminterval); - ahcd->fminterval = temp & 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 was - * saved if boot firmware (BIOS/SMM/...) told us it's connected, - * or if bus glue did the same (e.g. for PCI add-in cards with - * PCI PM support). - */ - if ((ahcd->hc_control & OHCI_CTRL_RWC) != 0 - && !device_may_wakeup(hcd->self.controller)) - device_init_wakeup(hcd->self.controller, 1); -#endif - - switch (ahcd->host_control & ADMHC_HC_BUSS) { - case ADMHC_BUSS_OPER: - temp = 0; - break; - case ADMHC_BUSS_SUSPEND: - /* FALLTHROUGH ? */ - case ADMHC_BUSS_RESUME: - ahcd->host_control = ADMHC_BUSS_RESUME; - temp = 10 /* msec wait */; - break; - /* case ADMHC_BUSS_RESET: */ - default: - ahcd->host_control = ADMHC_BUSS_RESET; - temp = 50 /* msec wait */; - break; - } - admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); - - /* flush the writes */ - admhc_writel_flush(ahcd); - - msleep(temp); - temp = admhc_read_rhdesc(ahcd); - if (!(temp & ADMHC_RH_NPS)) { - /* power down each port */ - for (temp = 0; temp < ahcd->num_ports; temp++) - admhc_write_portstatus(ahcd, temp, 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); - temp = 30; /* ... allow extra time */ - while ((admhc_readl(ahcd, &ahcd->regs->gencontrol) & ADMHC_CTRL_SR) != 0) { - if (--temp == 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 */ - hcd->poll_rh = 1; - 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); - - temp = 20; - while ((admhc_readl(ahcd, &ahcd->regs->host_control) - & ADMHC_HC_BUSS) != ADMHC_BUSS_OPER) { - if (--temp == 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); - - temp = 200; - while ((admhc_readl(ahcd, &ahcd->regs->host_control) - & ADMHC_HC_DMAE) != ADMHC_HC_DMAE) { - if (--temp == 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); - hcd->poll_rh = 1; - 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)); - -#ifdef DEBUG - admhc_debug_root = debugfs_create_dir("admhc", NULL); - 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 - 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 -} -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-2.6.26/drivers/usb/host/adm5120-hub.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-hub.c deleted file mode 100644 index 6ba62050b1..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-hub.c +++ /dev/null @@ -1,441 +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" : "" \ - ); - -/*-------------------------------------------------------------------------*/ - -/* hcd->hub_irq_enable() */ -static void admhc_hub_irq_enable(struct usb_hcd *hcd) -{ - struct admhcd *ahcd = hcd_to_admhcd(hcd); - - spin_lock_irq(&ahcd->lock); - if (!ahcd->autostop) - del_timer(&hcd->rh_timer); /* Prevent next poll */ - admhc_intr_enable(ahcd, ADMHC_INTR_INSM); - spin_unlock_irq(&ahcd->lock); -} - -/*-------------------------------------------------------------------------*/ - -/* 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 (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) - 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); - } - } - - hcd->poll_rh = admhc_root_hub_state_changes(ahcd, changed, - any_connected); - -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); - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - desc->bitmap[0] = 0; - desc->bitmap[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 = hcd_to_bus(hcd)->root_hub->maxchild; - int ret = 0; - - if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) - 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-2.6.26/drivers/usb/host/adm5120-mem.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-mem.c deleted file mode 100644 index da50d42eb0..0000000000 --- a/target/linux/adm5120/files-2.6.26/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-2.6.26/drivers/usb/host/adm5120-pm.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-pm.c deleted file mode 100644 index 9d49664cba..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-pm.c +++ /dev/null @@ -1,445 +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(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) - 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(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) - 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) -{ - int poll_rh = 1; - - /* keep on polling until RHSC is enabled */ - if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM) - poll_rh = 0; - - return poll_rh; -} - -#endif /* CONFIG_PM */ - diff --git a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-q.c b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-q.c deleted file mode 100644 index 4c742c0f30..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120-q.c +++ /dev/null @@ -1,955 +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 - -/*-------------------------------------------------------------------------*/ - -/* - * 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 - * suceeds ... 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 inline void -ed_halted(struct admhcd *ahcd, struct td *td, int cc, struct td *rev) -{ - 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; - 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; - - /* 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 - * 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-2.6.26/drivers/usb/host/adm5120.h b/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120.h deleted file mode 100644 index 7c47cb8b7d..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/usb/host/adm5120.h +++ /dev/null @@ -1,762 +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; -#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. - * - * REVISIT: arch/powerpc now has readl/writel_be, so the - * definition below can die once the STB04xxx support is - * finally ported over. - */ -#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) -#define readl_be(addr) in_be32((__force unsigned *)addr) -#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) -#endif - -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-2.6.26/drivers/watchdog/adm5120_wdt.c b/target/linux/adm5120/files-2.6.26/drivers/watchdog/adm5120_wdt.c deleted file mode 100644 index e92a898431..0000000000 --- a/target/linux/adm5120/files-2.6.26/drivers/watchdog/adm5120_wdt.c +++ /dev/null @@ -1,204 +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 = 0; -static int access = 0; -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 int wdt_ioctl(struct inode *inode, 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 struct file_operations wdt_fops = { - owner: THIS_MODULE, - llseek: no_llseek, - write: wdt_write, - 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-2.6.26/include/asm-mips/mach-adm5120/adm5120_board.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_board.h deleted file mode 100644 index c45b53fc6c..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_board.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * ADM5120 board 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_BOARD_H -#define _ASM_MIPS_MACH_ADM5120_BOARD_H - -#include -#include - -#define ADM5120_BOARD_NAMELEN 64 - -struct adm5120_board { - unsigned long mach_type; - char name[ADM5120_BOARD_NAMELEN]; - - void (*board_setup)(void); - struct list_head list; -}; - -extern void adm5120_board_register(struct adm5120_board *) __init; - -#define ADM5120_BOARD(_type, _name, _setup) \ -static struct adm5120_board adm5120_board_##_type __initdata = { \ - .mach_type = _type, \ - .name = _name, \ - .board_setup = _setup, \ -}; \ - \ -static __init int adm5120_board_##_type##_register(void) \ -{ \ - adm5120_board_register(&adm5120_board_##_type); \ - return 0; \ -} \ -pure_initcall(adm5120_board_##_type##_register) - -#endif /* _ASM_MIPS_MACH_ADM5120_BOARD_H */ diff --git a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_defs.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_defs.h deleted file mode 100644 index bf220ff4d6..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_info.h deleted file mode 100644 index d28ef800a5..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_info.h +++ /dev/null @@ -1,79 +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. - * - */ - -#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; - -/* - * 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-2.6.26/include/asm-mips/mach-adm5120/adm5120_intc.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_intc.h deleted file mode 100644 index 52883cf2dc..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/adm5120_mpmc.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_mpmc.h deleted file mode 100644 index 5383659dbf..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/adm5120_nand.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_nand.h deleted file mode 100644 index 636d27fecf..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/adm5120_platform.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_platform.h deleted file mode 100644 index 9d2e430cd8..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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 - -struct adm5120_flash_platform_data { - void (*set_vpp)(struct map_info *, int); - void (*switch_bank)(unsigned); - u32 window_size; -#ifdef CONFIG_MTD_PARTITIONS - unsigned int nr_parts; - struct mtd_partition *parts; -#endif -}; - -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_add_device_gpio(u32 disable_mask) __init; -extern void adm5120_add_device_gpio_buttons(unsigned nbuttons, - struct gpio_button *buttons) __init; - -#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-2.6.26/include/asm-mips/mach-adm5120/adm5120_switch.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_switch.h deleted file mode 100644 index 91adc5bae9..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/adm5120_uart.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/adm5120_uart.h deleted file mode 100644 index 6308f6bd18..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/asm/sizes.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/asm/sizes.h deleted file mode 100644 index 503843db15..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/cpu-feature-overrides.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/cpu-feature-overrides.h deleted file mode 100644 index c6310cc6e6..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/gpio.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/gpio.h deleted file mode 100644 index 7ba7efca1f..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/irq.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/irq.h deleted file mode 100644 index b0350c8b83..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/prom/admboot.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/admboot.h deleted file mode 100644 index fa42bf7148..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/prom/cfe.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/cfe.h deleted file mode 100644 index 0cb3eee70e..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/prom/generic.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/generic.h deleted file mode 100644 index 778df24677..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/prom/myloader.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/myloader.h deleted file mode 100644 index ea8db81ed3..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/prom/routerboot.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/routerboot.h deleted file mode 100644 index d5ad513d56..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/routerboot.h +++ /dev/null @@ -1,125 +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 _ROUTERBOOT_H -#define _ROUTERBOOT_H - -#define RB_MAC_SIZE 6 - -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 */ -}; - -/* - * Magic numbers - */ -#define RB_MAGIC_HARD 0x64726148 /* "Hard" */ -#define RB_MAGIC_SOFT 0x74666F53 /* "Soft" */ -#define RB_MAGIC_DAWN 0x6E776144 /* "Dawn" */ - -#define RB_ID_TERMINATOR 0 - -/* - * ID values for Hardware settings - */ -#define RB_ID_HARD_01 1 -#define RB_ID_HARD_02 2 -#define RB_ID_FLASH_INFO 3 -#define RB_ID_MAC_ADDRESS_PACK 4 -#define RB_ID_BOARD_NAME 5 -#define RB_ID_BIOS_VERSION 6 -#define RB_ID_HARD_07 7 -#define RB_ID_SDRAM_TIMINGS 8 -#define RB_ID_DEVICE_TIMINGS 9 -#define RB_ID_SOFTWARE_ID 10 -#define RB_ID_SERIAL_NUMBER 11 -#define RB_ID_HARD_12 12 -#define RB_ID_MEMORY_SIZE 13 -#define RB_ID_MAC_ADDRESS_COUNT 14 - -/* - * ID values for Software settings - */ -#define RB_ID_UART_SPEED 1 -#define RB_ID_BOOT_DELAY 2 -#define RB_ID_BOOT_DEVICE 3 -#define RB_ID_BOOT_KEY 4 -#define RB_ID_CPU_MODE 5 -#define RB_ID_FW_VERSION 6 -#define RB_ID_SOFT_07 7 -#define RB_ID_SOFT_08 8 -#define RB_ID_BOOT_PROTOCOL 9 -#define RB_ID_SOFT_10 10 -#define RB_ID_SOFT_11 11 - -/* - * UART_SPEED values - */ -#define RB_UART_SPEED_115200 0 -#define RB_UART_SPEED_57600 1 -#define RB_UART_SPEED_38400 2 -#define RB_UART_SPEED_19200 3 -#define RB_UART_SPEED_9600 4 -#define RB_UART_SPEED_4800 5 -#define RB_UART_SPEED_2400 6 -#define RB_UART_SPEED_1200 7 - -/* - * BOOT_DELAY values - */ -#define RB_BOOT_DELAY_0SEC 0 -#define RB_BOOT_DELAY_1SEC 1 -#define RB_BOOT_DELAY_2SEC 2 - -/* - * BOOT_DEVICE values - */ -#define RB_BOOT_DEVICE_ETHER 0 -#define RB_BOOT_DEVICE_NANDETH 1 -#define RB_BOOT_DEVICE_ETHONCE 2 -#define RB_BOOT_DEVICE_NANDONLY 3 - -/* - * BOOT_KEY values - */ -#define RB_BOOT_KEY_ANY 0 -#define RB_BOOT_KEY_DEL 1 - -/* - * CPU_MODE values - */ -#define RB_CPU_MODE_POWERSAVE 0 -#define RB_CPU_MODE_REGULAR 1 - -/* - * BOOT_PROTOCOL values - */ -#define RB_BOOT_PROTOCOL_BOOTP 0 -#define RB_BOOT_PROTOCOL_DHCP 1 - -extern int routerboot_present(void) __init; -extern char *routerboot_get_boardname(void); - -extern struct rb_hard_settings rb_hs; - -#endif /* _ROUTERBOOT_H */ diff --git a/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/zynos.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/prom/zynos.h deleted file mode 100644 index d1e3e5b941..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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-2.6.26/include/asm-mips/mach-adm5120/war.h b/target/linux/adm5120/files-2.6.26/include/asm-mips/mach-adm5120/war.h deleted file mode 100644 index 87c35f375b..0000000000 --- a/target/linux/adm5120/files-2.6.26/include/asm-mips/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/adm5120/Kconfig b/target/linux/adm5120/files/arch/mips/adm5120/Kconfig new file mode 100644 index 0000000000..71868f9b5f --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/Kconfig @@ -0,0 +1,177 @@ +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_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_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_INFINEON + def_bool n + +config ADM5120_OEM_MIKROTIK + def_bool n + +config ADM5120_OEM_MOTOROLA + 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/cellvision/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/Makefile new file mode 100644 index 0000000000..a949fc9f61 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/cellvision/cas-771.c b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cas-771.c new file mode 100644 index 0000000000..26995bb0a1 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cas-771.c @@ -0,0 +1,36 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_CAS771, "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 new file mode 100644 index 0000000000..282c8c778c --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.c @@ -0,0 +1,152 @@ +/* + * 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 + +#ifdef CONFIG_MTD_PARTITIONS +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, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +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) +{ +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas6xx_partitions); + adm5120_flash0_data.parts = cas6xx_partitions; +#endif /* CONFIG_MTD_PARTITIONS */ + + cellvision_flash_setup(); +} + +void __init cas7xx_flash_setup(void) +{ +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(cas7xx_partitions); + adm5120_flash0_data.parts = cas7xx_partitions; +#endif /* CONFIG_MTD_PARTITIONS */ + + cellvision_flash_setup(); +} + +#if 0 +void __init cas6xx_setup(void) +{ + cas6xx_flash_setup(); + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + adm5120_add_device_switch(1, NULL); +} + +ADM5120_BOARD(MACH_ADM5120_CAS630, "Cellvision CAS-630/630W", cas6xx_setup); +ADM5120_BOARD(MACH_ADM5120_CAS670, "Cellvision CAS-670/670W", cas6xx_setup); +#endif + +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); +} + +#if 0 +ADM5120_BOARD(MACH_ADM5120_CAS700, "Cellvision CAS-700/700W", cas7xx_setup); +ADM5120_BOARD(MACH_ADM5120_CAS790, "Cellvision CAS-790", cas7xx_setup); +ADM5120_BOARD(MACH_ADM5120_CAS861, "Cellvision CAS-861/861W", cas7xx_setup); +#endif diff --git a/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h new file mode 100644 index 0000000000..175fbb249c --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/cellvision.h @@ -0,0 +1,29 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..3482e11bd2 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/cellvision/nfs-101.c @@ -0,0 +1,28 @@ +/* + * Cellvision/SparkLAN NFS-101U/WU 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 u8 nfs101_vlans[6] __initdata = { /* TODO: not tested */ + 0x41, 0x42, 0x44, 0x48, 0x50, 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(5, nfs101_vlans); +} + +ADM5120_BOARD(MACH_ADM5120_NFS101U, "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 new file mode 100644 index 0000000000..663fd21501 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/Makefile @@ -0,0 +1,6 @@ +# +# Makefile for the Infineon/ADMtek ADM5120 SoC specific parts of the kernel +# + +obj-y := adm5120.o setup.o prom.o irq.o memory.o board.o clock.o \ + gpio.o platform.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 new file mode 100644 index 0000000000..f227e871da --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/adm5120.c @@ -0,0 +1,77 @@ +/* + * 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 + +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/board.c b/target/linux/adm5120/files/arch/mips/adm5120/common/board.c new file mode 100644 index 0000000000..be1fc9ab03 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/board.c @@ -0,0 +1,91 @@ +/* + * ADM5120 generic board code + * + * 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 + +#define PFX "ADM5120: " + +static struct list_head adm5120_boards __initdata = + LIST_HEAD_INIT(adm5120_boards); + +static char adm5120_board_name[ADM5120_BOARD_NAMELEN] = "Unknown board"; + +const char *get_system_type(void) +{ + return adm5120_board_name; +} + +static struct adm5120_board * __init adm5120_board_find(unsigned long machtype) +{ + struct list_head *this; + + list_for_each(this, &adm5120_boards) { + struct adm5120_board *board; + + board = list_entry(this, struct adm5120_board, list); + if (board->mach_type == machtype) + return board; + } + + return NULL; +} + +static int __init adm5120_board_setup(void) +{ + struct adm5120_board *board; + + board = adm5120_board_find(mips_machtype); + if (board == NULL) + panic(PFX "no board registered for machtype %lu\n", + mips_machtype); + + if (board->name[0]) + strlcpy(adm5120_board_name, board->name, ADM5120_BOARD_NAMELEN); + + printk(KERN_INFO PFX "board is '%s'\n", adm5120_board_name); + + adm5120_gpio_init(); + + if (board->board_setup) + board->board_setup(); + + return 0; +} +arch_initcall(adm5120_board_setup); + +void __init adm5120_board_register(struct adm5120_board *board) +{ + list_add_tail(&board->list, &adm5120_boards); +} + +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); +} + +ADM5120_BOARD(MACH_ADM5120_GENERIC, "Generic ADM5120 board", + adm5120_generic_board_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c b/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c new file mode 100644 index 0000000000..d004309959 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/clock.c @@ -0,0 +1,62 @@ +/* + * 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 + +struct clk { + unsigned long rate; +}; + +static struct clk uart_clk = { + .rate = ADM5120_UART_CLOCK +}; + +struct clk *clk_get(struct device *dev, const char *id) +{ + if (!strcmp(id, "UARTCLK")) + 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/gpio.c b/target/linux/adm5120/files/arch/mips/adm5120/common/gpio.c new file mode 100644 index 0000000000..8143d31f67 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/gpio.c @@ -0,0 +1,331 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..140a7a0e95 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/irq.c @@ -0,0 +1,176 @@ +/* + * 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(unsigned int irq); +static void adm5120_intc_irq_mask(unsigned int irq); +static int adm5120_intc_irq_set_type(unsigned int irq, 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", + .unmask = adm5120_intc_irq_unmask, + .mask = adm5120_intc_irq_mask, + .mask_ack = adm5120_intc_irq_mask, + .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(unsigned int irq) +{ + irq -= ADM5120_INTC_IRQ_BASE; + intc_write_reg(INTC_REG_IRQ_ENABLE, 1 << irq); +} + +static void adm5120_intc_irq_mask(unsigned int irq) +{ + irq -= ADM5120_INTC_IRQ_BASE; + intc_write_reg(INTC_REG_IRQ_DISABLE, 1 << irq); +} + +static int adm5120_intc_irq_set_type(unsigned int irq, unsigned int flow_type) +{ + 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); + /* fallthrough */ + default: + irq_desc[irq].status &= ~IRQ_TYPE_SENSE_MASK; + irq_desc[irq].status |= sense; + 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_desc[i].status = INTC_IRQ_STATUS; + set_irq_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 new file mode 100644 index 0000000000..d07266fa38 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/common/platform.c b/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c new file mode 100644 index 0000000000..9526fe977f --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/platform.c @@ -0,0 +1,380 @@ +/* + * 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 + +#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 = { + .bus_id = "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, -1 }, + .periphid = 0x0041010, +}; + +struct amba_pl010_data adm5120_uart1_data = { + .set_mctrl = adm5120_uart_set_mctrl +}; + +struct amba_device adm5120_uart1_device = { + .dev = { + .bus_id = "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, -1 }, + .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 + */ +#define ADM5120_BUTTON_INTERVAL 20 +struct gpio_buttons_platform_data adm5120_gpio_buttons_data = { + .poll_interval = ADM5120_BUTTON_INTERVAL, +}; + +struct platform_device adm5120_gpio_buttons_device = { + .name = "gpio-buttons", + .id = -1, + .dev.platform_data = &adm5120_gpio_buttons_data, +}; + +void __init adm5120_add_device_gpio_buttons(unsigned nbuttons, + struct gpio_button *buttons) +{ + struct gpio_button *p; + + p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL); + if (!p) + return; + + memcpy(p, buttons, nbuttons * sizeof(*p)); + adm5120_gpio_buttons_data.nbuttons = nbuttons; + adm5120_gpio_buttons_data.buttons = p; + + platform_device_register(&adm5120_gpio_buttons_device); +} + +/* + * 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); +} + +/* + * GPIO device + */ +static struct resource adm5120_gpio_resource[] __initdata = { + { + .start = 0x3fffff, + }, +}; + +void __init adm5120_add_device_gpio(u32 disable_mask) +{ + if (adm5120_package_pqfp()) + disable_mask |= 0xf0; + + adm5120_gpio_resource[0].start &= ~disable_mask; + platform_device_register_simple("GPIODEV", -1, + adm5120_gpio_resource, + ARRAY_SIZE(adm5120_gpio_resource)); +} + +/* + * 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 new file mode 100644 index 0000000000..4c48dc0be2 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/prom.c @@ -0,0 +1,271 @@ +/* + * 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 +#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), + /* Motorola boards */ + DEFBOARD("Powerline MU Gateway",MACH_ADM5120_PMUGW), +}; + +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; +} + +/* TODO: this is an ugly hack for RouterBOARDS */ +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 + 8; + if (strlen(cmd) > 0) + strlcpy(arcs_cmdline, cmd, sizeof(arcs_cmdline)); + +} + +#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); +} + +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 new file mode 100644 index 0000000000..0a11774624 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/common/setup.c @@ -0,0 +1,91 @@ +/* + * ADM5120 specific setup + * + * 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 + +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 : ADM%04X%s revision %d, running " + "at %ldMHz\n", + adm5120_product_code, + adm5120_package_bga() ? "" : "P", + adm5120_revision, (adm5120_speed / 1000000)); + printk(KERN_INFO "Bootdev : %s flash\n", + adm5120_nand_boot ? "NAND":"NOR"); + printk(KERN_INFO "Prom : %s\n", prom_names[adm5120_prom_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(); + adm5120_report(); + + _machine_restart = adm5120_restart; + _machine_halt = adm5120_halt; + pm_power_off = adm5120_halt; + + set_io_port_base(KSEG1); +} diff --git a/target/linux/adm5120/files/arch/mips/adm5120/compex/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/compex/Makefile new file mode 100644 index 0000000000..8c66c171e7 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/compex/compex.c b/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.c new file mode 100644 index 0000000000..c14655ada7 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.c @@ -0,0 +1,64 @@ +/* + * 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 + +#define COMPEX_GPIO_DEV_MASK (1 << ADM5120_GPIO_PIN5) + +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); + + adm5120_add_device_gpio(COMPEX_GPIO_DEV_MASK); + + 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 new file mode 100644 index 0000000000..62425374ad --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/compex/compex.h @@ -0,0 +1,24 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..edd980ed7d --- /dev/null +++ b/target/linux/adm5120/files/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 */ +} + +ADM5120_BOARD(MACH_ADM5120_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 new file mode 100644 index 0000000000..eba288fc66 --- /dev/null +++ b/target/linux/adm5120/files/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); +} + +ADM5120_BOARD(MACH_ADM5120_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 new file mode 100644 index 0000000000..86b9d681b3 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/compex/wp54.c @@ -0,0 +1,94 @@ +/* + * 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" + +#ifdef CONFIG_MTD_PARTITIONS +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, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct adm5120_pci_irq wp54_pci_irqs[] __initdata = { + PCIIRQ(2, 0, 1, ADM5120_IRQ_PCI0), +}; + +static struct gpio_button wp54_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .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_add_device_gpio_buttons(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); +} + +ADM5120_BOARD(MACH_ADM5120_WP54, "Compex WP54 family", wp54_setup); + +static void __init wp54_wrt_setup(void) +{ +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(wp54g_wrt_partitions); + adm5120_flash0_data.parts = wp54g_wrt_partitions; +#endif + + wp54_setup(); +} + +ADM5120_BOARD(MACH_ADM5120_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 new file mode 100644 index 0000000000..1286ed4c1e --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/edimax/br-6104k.c b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104k.c new file mode 100644 index 0000000000..b0ed8fa373 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104k.c @@ -0,0 +1,35 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_BR6104K, "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 new file mode 100644 index 0000000000..e0556b7416 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-6104kp.c @@ -0,0 +1,38 @@ +/* + * 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_STD(ADM5120_GPIO_PIN1, "usb1", NULL), + GPIO_LED_INV(ADM5120_GPIO_PIN3, "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(); +} + +ADM5120_BOARD(MACH_ADM5120_BR6104KP, "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 new file mode 100644 index 0000000000..98d64f1559 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61x4wg.c @@ -0,0 +1,42 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_BR61X4WG, "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 new file mode 100644 index 0000000000..6ecdb4e425 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/edimax/br-61xx.c @@ -0,0 +1,87 @@ +/* + * 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_GPIO_DEV_MASK 0 + +#define BR61XX_CONFIG_OFFSET 0x8000 +#define BR61XX_CONFIG_SIZE 0x1000 + +#ifdef CONFIG_MTD_PARTITIONS +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, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +static struct gpio_button br61xx_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .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) +{ + +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(br61xx_partitions); + adm5120_flash0_data.parts = br61xx_partitions; +#endif /* CONFIG_MTD_PARTITIONS */ + adm5120_add_device_flash(0); + + adm5120_add_device_gpio(BR61XX_GPIO_DEV_MASK); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_switch(5, br61xx_vlans); + adm5120_add_device_gpio_buttons(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 new file mode 100644 index 0000000000..f8ad137a49 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/infineon/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/infineon/Makefile new file mode 100644 index 0000000000..49453cba9a --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/infineon/easy5120-rt.c b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-rt.c new file mode 100644 index 0000000000..618564e5c0 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-rt.c @@ -0,0 +1,49 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_EASY5120RT, + "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 new file mode 100644 index 0000000000..f51f4634cb --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120-wvoip.c @@ -0,0 +1,25 @@ +/* + * 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 */ +} + +ADM5120_BOARD(MACH_ADM5120_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 new file mode 100644 index 0000000000..90c975bf09 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy5120p-ata.c @@ -0,0 +1,23 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_EASY5120PATA, + "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 new file mode 100644 index 0000000000..dd14badd32 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/easy83000.c @@ -0,0 +1,24 @@ +/* + * 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 */ +} + +ADM5120_BOARD(MACH_ADM5120_EASY83000, + "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 new file mode 100644 index 0000000000..b52edf0f67 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.c @@ -0,0 +1,114 @@ +/* + * 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 + +#ifdef CONFIG_MTD_PARTITIONS +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, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +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; + +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); + adm5120_flash0_data.parts = easy_partitions; +#endif /* CONFIG_MTD_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; + +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(easy_partitions); + adm5120_flash0_data.parts = easy_partitions; +#endif /* CONFIG_MTD_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 new file mode 100644 index 0000000000..2e25a8f3de --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/infineon/infineon.h @@ -0,0 +1,26 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..34ea0a3d88 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/mikrotik/rb-11x.c b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-11x.c new file mode 100644 index 0000000000..e238c625af --- /dev/null +++ b/target/linux/adm5120/files/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(0); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb11x_gpio_leds), + rb11x_gpio_leds); +} + +ADM5120_BOARD(MACH_ADM5120_RB_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 new file mode 100644 index 0000000000..9000a20830 --- /dev/null +++ b/target/linux/adm5120/files/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(0); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133_gpio_leds), + rb133_gpio_leds); +} + +ADM5120_BOARD(MACH_ADM5120_RB_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 new file mode 100644 index 0000000000..9003b868e3 --- /dev/null +++ b/target/linux/adm5120/files/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(0); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb133c_gpio_leds), + rb133c_gpio_leds); +} + +ADM5120_BOARD(MACH_ADM5120_RB_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 new file mode 100644 index 0000000000..bba3be233f --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-150.c @@ -0,0 +1,136 @@ +/* + * 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_GPIO_DEV_MASK ( 1 << RB150_GPIO_NAND_READY \ + | 1 << RB150_GPIO_NAND_NCE \ + | 1 << RB150_GPIO_NAND_CLE \ + | 1 << RB150_GPIO_NAND_ALE) + +#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(RB150_GPIO_DEV_MASK); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb150_gpio_leds), + rb150_gpio_leds); + adm5120_add_device_switch(5, rb150_vlans); +} + +ADM5120_BOARD(MACH_ADM5120_RB_150, "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 new file mode 100644 index 0000000000..ee38ff2735 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-153.c @@ -0,0 +1,74 @@ +/* + * 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" + +#define RB153_GPIO_DEV_MASK ( 1 << ADM5120_GPIO_PIN0 \ + | 1 << ADM5120_GPIO_PIN3 \ + | 1 << ADM5120_GPIO_PIN4 ) + +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(RB153_GPIO_DEV_MASK); + adm5120_add_device_gpio_leds(ARRAY_SIZE(rb153_gpio_leds), + rb153_gpio_leds); + adm5120_add_device_switch(5, rb153_vlans); +} + +ADM5120_BOARD(MACH_ADM5120_RB_153, "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 new file mode 100644 index 0000000000..0821607c87 --- /dev/null +++ b/target/linux/adm5120/files/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_gpio(0); + adm5120_add_device_switch(6, rb192_vlans); +} + +ADM5120_BOARD(MACH_ADM5120_RB_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 new file mode 100644 index 0000000000..7fc6e74dad --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.c @@ -0,0 +1,152 @@ +/* + * 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 + +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) +}; + +#ifdef CONFIG_MTD_PARTITIONS +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 + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +/* + * 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, +#ifdef CONFIG_MTD_PARTITIONS + .nr_partitions = ARRAY_SIZE(rb1xx_nand_parts), + .partitions = rb1xx_nand_parts, +#endif /* CONFIG_MTD_PARTITIONS */ + .chip_delay = RB1XX_NAND_CHIP_DELAY, + .options = NAND_NO_AUTOINCR, + .chip_fixup = rb1xx_nand_fixup, + }, +}; + +struct gpio_button rb1xx_gpio_buttons[] __initdata = { + { + .desc = "reset_button", + .type = EV_KEY, + .code = BTN_0, + .threshold = 5, + .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 */ +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(rb1xx_nor_parts); + adm5120_flash0_data.parts = rb1xx_nor_parts; +#endif /* CONFIG_MTD_PARTITIONS */ + 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_add_device_gpio_buttons(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 new file mode 100644 index 0000000000..1577ed66d0 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/mikrotik/rb-1xx.h @@ -0,0 +1,34 @@ +/* + * 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 + +#include + +extern struct platform_nand_data rb1xx_nand_data __initdata; +extern struct gpio_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 new file mode 100644 index 0000000000..239d5a0880 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/motorola/Makefile @@ -0,0 +1 @@ +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 new file mode 100644 index 0000000000..a74d37d4f3 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/motorola/pmugw.c @@ -0,0 +1,102 @@ +/* + * 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 + +#include + +#define PMUGW_CONFIG_OFFSET 0x10000 +#define PMUGW_CONFIG_SIZE 0x1000 + +#ifdef CONFIG_MTD_PARTITIONS +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, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +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; + +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(pmugw_partitions); + adm5120_flash0_data.parts = pmugw_partitions; +#endif /* CONFIG_MTD_PARTITIONS */ + + adm5120_add_device_uart(1); /* ttyS0 */ + adm5120_add_device_uart(0); /* ttyS1 */ + + adm5120_add_device_flash(0); + + pmugw_setup_mac(); + adm5120_add_device_switch(5, pmugw_vlans); +} + +ADM5120_BOARD(MACH_ADM5120_PMUGW, + "Motorola Powerline MU Gateway", + pmugw_setup); diff --git a/target/linux/adm5120/files/arch/mips/adm5120/prom/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/prom/Makefile new file mode 100644 index 0000000000..650be40779 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/prom/admboot.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/admboot.c new file mode 100644 index 0000000000..5d436f62f6 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/prom/admboot.c @@ -0,0 +1,46 @@ +/* + * 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' */ + +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; + } + } + + 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 new file mode 100644 index 0000000000..b6a94ff46a --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/prom/bootbase.c @@ -0,0 +1,120 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..5a343cd7e4 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/prom/generic.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/generic.c new file mode 100644 index 0000000000..4d4caa8476 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/prom/myloader.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/myloader.c new file mode 100644 index 0000000000..939422681b --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/prom/myloader.c @@ -0,0 +1,69 @@ +/* + * 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 +#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 new file mode 100644 index 0000000000..1a6ea110ce --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/prom/routerboot.c b/target/linux/adm5120/files/arch/mips/adm5120/prom/routerboot.c new file mode 100644 index 0000000000..d9e1096cbe --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/zyxel/Makefile b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/Makefile new file mode 100644 index 0000000000..e8325a1b1f --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/adm5120/zyxel/p-334wt.c b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-334wt.c new file mode 100644 index 0000000000..6eb23dab9c --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-334wt.c @@ -0,0 +1,33 @@ +/* + * 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); +} + +ADM5120_BOARD(MACH_ADM5120_P334WT, "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 new file mode 100644 index 0000000000..0e6cdd96ef --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-335.c @@ -0,0 +1,20 @@ +/* + * 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(); +} + +ADM5120_BOARD(MACH_ADM5120_P335, "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 new file mode 100644 index 0000000000..6d4d4ddee7 --- /dev/null +++ b/target/linux/adm5120/files/arch/mips/adm5120/zyxel/p-33x.c @@ -0,0 +1,89 @@ +/* + * 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 +#define P33X_GPIO_DEV_MASK (1 << P33X_GPIO_FLASH_A20) + +#ifdef CONFIG_MTD_PARTITIONS +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, + } , { + .name = "bootext", + .offset = MTDPART_OFS_APPEND, + .size = 96*1024, + .mask_flags = MTD_WRITEABLE, + } , { + .name = "trx", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + } , { + .name = "firmware", + .offset = 32*1024, + .size = MTDPART_SIZ_FULL, + } +}; +#endif /* CONFIG_MTD_PARTITIONS */ + +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; +#ifdef CONFIG_MTD_PARTITIONS + adm5120_flash0_data.nr_parts = ARRAY_SIZE(p33x_partitions); + adm5120_flash0_data.parts = p33x_partitions; +#endif /* CONFIG_MTD_PARTITIONS */ + adm5120_add_device_flash(0); + + adm5120_add_device_uart(0); + adm5120_add_device_uart(1); + + adm5120_add_device_gpio(P33X_GPIO_DEV_MASK); + + adm5120_setup_eth_macs(bootbase_info.mac); + adm5120_add_device_switch(5, 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 new file mode 100644 index 0000000000..0971cd5d26 --- /dev/null +++ b/target/linux/adm5120/files/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/arch/mips/pci/pci-adm5120.c b/target/linux/adm5120/files/arch/mips/pci/pci-adm5120.c new file mode 100644 index 0000000000..bde3e32082 --- /dev/null +++ b/target/linux/adm5120/files/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 spinlock_t pci_lock = SPIN_LOCK_UNLOCKED; + +/* -------------------------------------------------------------------------*/ + +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 > 3) { + 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 new file mode 100644 index 0000000000..ef7f5835ae --- /dev/null +++ b/target/linux/adm5120/files/drivers/ata/pata_rb153_cf.c @@ -0,0 +1,268 @@ +/* + * 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); + + 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)) { + set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); + if (!info->frozen) + ata_sff_interrupt(irq, dev_instance); + } else { + 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->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; + + 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 __devinit 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 __devexit 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 = __devexit_p(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 new file mode 100644 index 0000000000..b4a5dbbea9 --- /dev/null +++ b/target/linux/adm5120/files/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/drivers/mtd/maps/adm5120-flash.c b/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c new file mode 100644 index 0000000000..8bd7ae1c0b --- /dev/null +++ b/target/linux/adm5120/files/drivers/mtd/maps/adm5120-flash.c @@ -0,0 +1,568 @@ +/* + * 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; +#ifdef CONFIG_MTD_PARTITIONS + int nr_parts; + struct mtd_partition *parts[MAX_PARSED_PARTS]; +#endif +}; + +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 *probe_types[] = { + "cfi_probe", + "jedec_probe", + "map_rom", + NULL +}; + +#ifdef CONFIG_MTD_PARTITIONS +static const char *parse_types[] = { + "cmdlinepart", +#ifdef CONFIG_MTD_REDBOOT_PARTS + "RedBoot", +#endif +#ifdef CONFIG_MTD_MYLOADER_PARTS + "MyLoader", +#endif +}; +#endif + +#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->dev.bus_id; + + 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; +} + +#ifdef CONFIG_MTD_PARTITIONS +static int adm5120_flash_initparts(struct adm5120_flash_info *info) +{ + struct adm5120_flash_platform_data *pdata; + struct map_info *map = &info->amap.map; + int num_parsers; + const char *parser[2]; + int err = 0; + int nr_parts; + int i; + + info->nr_parts = 0; + + pdata = info->dev->dev.platform_data; + if (pdata == NULL) + goto out; + + if (pdata->nr_parts) { + MAP_INFO(map, "adding static partitions\n"); + err = add_mtd_partitions(info->mtd, pdata->parts, + pdata->nr_parts); + if (err == 0) { + info->nr_parts += pdata->nr_parts; + goto out; + } + } + + num_parsers = ARRAY_SIZE(parse_types); + if (num_parsers > MAX_PARSED_PARTS) + num_parsers = MAX_PARSED_PARTS; + + parser[1] = NULL; + for (i = 0; i < num_parsers; i++) { + parser[0] = parse_types[i]; + + MAP_INFO(map, "parsing \"%s\" partitions\n", + parser[0]); + nr_parts = parse_mtd_partitions(info->mtd, parser, + &info->parts[i], 0); + + if (nr_parts <= 0) + continue; + + MAP_INFO(map, "adding \"%s\" partitions\n", + parser[0]); + + err = add_mtd_partitions(info->mtd, info->parts[i], nr_parts); + if (err) + break; + + info->nr_parts += nr_parts; + } +out: + return err; +} +#else +static int adm5120_flash_initparts(struct adm5120_flash_info *info) +{ + return 0; +} +#endif /* CONFIG_MTD_PARTITIONS */ + +#ifdef CONFIG_MTD_PARTITIONS +static void adm5120_flash_remove_mtd(struct adm5120_flash_info *info) +{ + int i; + + if (info->nr_parts) { + del_mtd_partitions(info->mtd); + for (i = 0; i < MAX_PARSED_PARTS; i++) + if (info->parts[i] != NULL) + kfree(info->parts[i]); + } else { + del_mtd_device(info->mtd); + } +} +#else +static void adm5120_flash_remove_mtd(struct adm5120_flash_info *info) +{ + del_mtd_device(info->mtd); +} +#endif + +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) { + adm5120_flash_remove_mtd(info); + 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_info *info; + struct map_info *map; + const char **probe_type; + int err; + + 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 = adm5120_flash_initparts(info); + if (err) + goto err_out; + + if (info->nr_parts == 0) { + MAP_INFO(map, "no partitions available, registering " + "whole flash\n"); + add_mtd_device(info->mtd); + } + + 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/myloader.c b/target/linux/adm5120/files/drivers/mtd/myloader.c new file mode 100644 index 0000000000..22d076b72c --- /dev/null +++ b/target/linux/adm5120/files/drivers/mtd/myloader.c @@ -0,0 +1,164 @@ +/* + * Parse MyLoader-style flash partition tables and produce a Linux partition + * array to match. + * + * Copyright (C) 2007-2008 Gabor Juhos + * + * This file was based on drivers/mtd/redboot.c + * Author: Red Hat, Inc. - David Woodhouse + * + * 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 + +#define NAME_LEN_MAX 20 +#define NAME_MYLOADER "MyLoader" +#define NAME_PARTITION_TABLE "Partition Table" +#define BLOCK_LEN_MIN 0x10000 + +int parse_myloader_partitions(struct mtd_info *master, + struct mtd_partition **pparts, + unsigned long origin) +{ + struct mylo_partition_table *tab; + struct mylo_partition *part; + struct mtd_partition *mtd_parts; + struct mtd_partition *mtd_part; + int num_parts; + int ret, i; + size_t retlen; + char *names; + unsigned long offset; + unsigned long blocklen; + + tab = vmalloc(sizeof(*tab)); + if (!tab) { + return -ENOMEM; + goto out; + } + + blocklen = master->erasesize; + if (blocklen < BLOCK_LEN_MIN) + blocklen = BLOCK_LEN_MIN; + + /* Partition Table is always located on the second erase block */ + offset = blocklen; + printk(KERN_NOTICE "%s: searching for MyLoader partition table at " + "offset 0x%lx\n", master->name, offset); + + ret = master->read(master, offset, sizeof(*tab), &retlen, (void *)tab); + if (ret) + goto out; + + if (retlen != sizeof(*tab)) { + ret = -EIO; + goto out_free_buf; + } + + /* Check for Partition Table magic number */ + if (tab->magic != le32_to_cpu(MYLO_MAGIC_PARTITIONS)) { + printk(KERN_NOTICE "%s: no MyLoader partition table found\n", + master->name); + ret = 0; + goto out_free_buf; + } + + /* The MyLoader and the Partition Table is always present */ + num_parts = 2; + + /* Detect number of used partitions */ + for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { + part = &tab->partitions[i]; + + if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) + continue; + + num_parts++; + } + + mtd_parts = kzalloc((num_parts * sizeof(*mtd_part) + + num_parts * NAME_LEN_MAX), GFP_KERNEL); + + if (!mtd_parts) { + ret = -ENOMEM; + goto out_free_buf; + } + + mtd_part = mtd_parts; + names = (char *)&mtd_parts[num_parts]; + + strncpy(names, NAME_MYLOADER, NAME_LEN_MAX-1); + mtd_part->name = names; + mtd_part->offset = 0; + mtd_part->size = blocklen; + mtd_part->mask_flags = MTD_WRITEABLE; + mtd_part++; + names += NAME_LEN_MAX; + + strncpy(names, NAME_PARTITION_TABLE, NAME_LEN_MAX-1); + mtd_part->name = names; + mtd_part->offset = blocklen; + mtd_part->size = blocklen; + mtd_part->mask_flags = MTD_WRITEABLE; + mtd_part++; + names += NAME_LEN_MAX; + + for (i = 0; i < MYLO_MAX_PARTITIONS; i++) { + part = &tab->partitions[i]; + + if (le16_to_cpu(part->type) == PARTITION_TYPE_FREE) + continue; + + sprintf(names, "partition%d", i); + mtd_part->offset = le32_to_cpu(part->addr); + mtd_part->size = le32_to_cpu(part->size); + mtd_part->name = names; + mtd_part++; + names += NAME_LEN_MAX; + } + + *pparts = mtd_parts; + ret = num_parts; + +out_free_buf: + vfree(tab); +out: + return ret; +} + +static struct mtd_part_parser mylo_mtd_parser = { + .owner = THIS_MODULE, + .parse_fn = parse_myloader_partitions, + .name = NAME_MYLOADER, +}; + +static int __init mylo_mtd_parser_init(void) +{ + return register_mtd_parser(&mylo_mtd_parser); +} + +static void __exit mylo_mtd_parser_exit(void) +{ + deregister_mtd_parser(&mylo_mtd_parser); +} + +module_init(mylo_mtd_parser_init); +module_exit(mylo_mtd_parser_exit); + +MODULE_AUTHOR("Gabor Juhos "); +MODULE_DESCRIPTION("Parsing code for MyLoader partition tables"); +MODULE_LICENSE("GPL v2"); diff --git a/target/linux/adm5120/files/drivers/mtd/trxsplit.c b/target/linux/adm5120/files/drivers/mtd/trxsplit.c new file mode 100644 index 0000000000..7e4a63b74b --- /dev/null +++ b/target/linux/adm5120/files/drivers/mtd/trxsplit.c @@ -0,0 +1,217 @@ +/* + * 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 = add_mtd_partitions(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 */ + del_mtd_partitions(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 new file mode 100644 index 0000000000..7acc84d248 --- /dev/null +++ b/target/linux/adm5120/files/drivers/net/adm5120sw.c @@ -0,0 +1,1203 @@ +/* + * 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" + +#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_DBG "%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 spinlock_t tx_lock = SPIN_LOCK_UNLOCKED; + +/* ------------------------------------------------------------------------ */ + +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); +} + +/* ------------------------------------------------------------------------ */ + +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); +} + +/* ------------------------------------------------------------------------ */ + +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 = 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); + netif_rx_complete(dev, 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); + netif_rx_schedule(dev, &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; portnapi); +} + +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 | IRQF_DISABLED), 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->lenlen) << 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_multicast_list(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 || + dev->mc_count) + /* 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; /* Disable Bridge Testing Mode */ + else + t |= CPUP_CONF_BTM; /* Enable Bridge Testing Mode */ + + sw_write_reg(SWITCH_REG_CPUP_CONF, t); + +} + +static int adm5120_if_set_mac_address(struct net_device *dev, void *p) +{ + struct sockaddr *addr = p; + + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); + 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 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->open = adm5120_if_open; + dev->hard_start_xmit = adm5120_if_hard_start_xmit; + dev->stop = adm5120_if_stop; + dev->set_multicast_list = adm5120_if_set_multicast_list; + dev->do_ioctl = adm5120_if_do_ioctl; + dev->tx_timeout = adm5120_if_tx_timeout; + dev->watchdog_timeo = TX_TIMEOUT; + dev->set_mac_address = adm5120_if_set_mac_address; + +#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 __init 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 *dev) +{ + 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 new file mode 100644 index 0000000000..c7c5ceddc7 --- /dev/null +++ b/target/linux/adm5120/files/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/drivers/usb/host/adm5120-dbg.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c new file mode 100644 index 0000000000..c121f7be2d --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-dbg.c @@ -0,0 +1,842 @@ +/* + * 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 (" %02x", ((__u8 *) urb->setup_packet) [i]); + printk ("\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(" %02x", ((__u8 *)urb->transfer_buffer)[i]); + printk("%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) {} +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, +}; +static const struct file_operations debug_periodic_fops = { + .owner = THIS_MODULE, + .open = debug_periodic_open, + .read = debug_output, + .release = debug_close, +}; +static const struct file_operations debug_registers_fops = { + .owner = THIS_MODULE, + .open = debug_registers_open, + .read = debug_output, + .release = debug_close, +}; + +static struct dentry *admhc_debug_root; + +struct debug_buffer { + ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ + struct device *dev; + 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 usb_bus *bus; + struct usb_hcd *hcd; + struct admhcd *ahcd; + size_t temp; + unsigned long flags; + + bus = dev_get_drvdata(buf->dev); + hcd = bus_to_hcd(bus); + ahcd = hcd_to_admhcd(hcd); + + 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 usb_bus *bus; + struct usb_hcd *hcd; + struct admhcd *ahcd; + struct ed **seen, *ed; + unsigned long flags; + unsigned temp, size, seen_count; + char *next; + unsigned i; + + if (!(seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) + return 0; + seen_count = 0; + + bus = dev_get_drvdata(buf->dev); + hcd = bus_to_hcd(bus); + ahcd = hcd_to_admhcd(hcd); + 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++) { + if (!(ed = ahcd->periodic [i])) + 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_bus *bus; + struct usb_hcd *hcd; + struct admhcd *ahcd; + struct admhcd_regs __iomem *regs; + unsigned long flags; + unsigned temp, size; + char *next; + u32 rdata; + + bus = dev_get_drvdata(buf->dev); + hcd = bus_to_hcd(bus); + ahcd = hcd_to_admhcd(hcd); + 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 version " DRIVER_VERSION "\n", + hcd->self.controller->bus->name, + hcd->self.controller->bus_id, + hcd->product_desc, + hcd_name); + + if (bus->controller->power.power_state.event) { + 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 device *dev, + ssize_t (*fill_func)(struct debug_buffer *)) +{ + struct debug_buffer *buf; + + buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); + + if (buf) { + buf->dev = dev; + 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; + struct device *dev = bus->dev; + + 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, dev, + &debug_async_fops); + if (!ahcd->debug_async) + goto async_error; + + ahcd->debug_periodic = debugfs_create_file("periodic", S_IRUGO, + ahcd->debug_dir, dev, + &debug_periodic_fops); + if (!ahcd->debug_periodic) + goto periodic_error; + + ahcd->debug_registers = debugfs_create_file("registers", S_IRUGO, + ahcd->debug_dir, dev, + &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 new file mode 100644 index 0000000000..bf250c056b --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-drv.c @@ -0,0 +1,236 @@ +/* + * 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 Rusell 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, IRQF_DISABLED); + 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 __devinit +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, + .hub_irq_enable = admhc_hub_irq_enable, +#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 new file mode 100644 index 0000000000..c947a6c2dc --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-hcd.c @@ -0,0 +1,845 @@ +/* + * 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 +#include + +#include "../core/hcd.h" +#include "../core/hub.h" + +#define DRIVER_VERSION "0.25.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 upto 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 (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { + 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); + return; +} + +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 temp; + 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) { + temp = admhc_readl(ahcd, &ahcd->regs->fminterval); + ahcd->fminterval = temp & 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 was + * saved if boot firmware (BIOS/SMM/...) told us it's connected, + * or if bus glue did the same (e.g. for PCI add-in cards with + * PCI PM support). + */ + if ((ahcd->hc_control & OHCI_CTRL_RWC) != 0 + && !device_may_wakeup(hcd->self.controller)) + device_init_wakeup(hcd->self.controller, 1); +#endif + + switch (ahcd->host_control & ADMHC_HC_BUSS) { + case ADMHC_BUSS_OPER: + temp = 0; + break; + case ADMHC_BUSS_SUSPEND: + /* FALLTHROUGH ? */ + case ADMHC_BUSS_RESUME: + ahcd->host_control = ADMHC_BUSS_RESUME; + temp = 10 /* msec wait */; + break; + /* case ADMHC_BUSS_RESET: */ + default: + ahcd->host_control = ADMHC_BUSS_RESET; + temp = 50 /* msec wait */; + break; + } + admhc_writel(ahcd, ahcd->host_control, &ahcd->regs->host_control); + + /* flush the writes */ + admhc_writel_flush(ahcd); + + msleep(temp); + temp = admhc_read_rhdesc(ahcd); + if (!(temp & ADMHC_RH_NPS)) { + /* power down each port */ + for (temp = 0; temp < ahcd->num_ports; temp++) + admhc_write_portstatus(ahcd, temp, 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); + temp = 30; /* ... allow extra time */ + while ((admhc_readl(ahcd, &ahcd->regs->gencontrol) & ADMHC_CTRL_SR) != 0) { + if (--temp == 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 */ + hcd->poll_rh = 1; + 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); + + temp = 20; + while ((admhc_readl(ahcd, &ahcd->regs->host_control) + & ADMHC_HC_BUSS) != ADMHC_BUSS_OPER) { + if (--temp == 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); + + temp = 200; + while ((admhc_readl(ahcd, &ahcd->regs->host_control) + & ADMHC_HC_DMAE) != ADMHC_HC_DMAE) { + if (--temp == 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); + hcd->poll_rh = 1; + 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)); + +#ifdef DEBUG + admhc_debug_root = debugfs_create_dir("admhc", NULL); + 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 + 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 +} +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 new file mode 100644 index 0000000000..6ba62050b1 --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-hub.c @@ -0,0 +1,441 @@ +/* + * 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" : "" \ + ); + +/*-------------------------------------------------------------------------*/ + +/* hcd->hub_irq_enable() */ +static void admhc_hub_irq_enable(struct usb_hcd *hcd) +{ + struct admhcd *ahcd = hcd_to_admhcd(hcd); + + spin_lock_irq(&ahcd->lock); + if (!ahcd->autostop) + del_timer(&hcd->rh_timer); /* Prevent next poll */ + admhc_intr_enable(ahcd, ADMHC_INTR_INSM); + spin_unlock_irq(&ahcd->lock); +} + +/*-------------------------------------------------------------------------*/ + +/* 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 (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) + 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); + } + } + + hcd->poll_rh = admhc_root_hub_state_changes(ahcd, changed, + any_connected); + +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); + + /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ + desc->bitmap[0] = 0; + desc->bitmap[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 = hcd_to_bus(hcd)->root_hub->maxchild; + int ret = 0; + + if (unlikely(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + 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 new file mode 100644 index 0000000000..da50d42eb0 --- /dev/null +++ b/target/linux/adm5120/files/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/drivers/usb/host/adm5120-pm.c b/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c new file mode 100644 index 0000000000..9d49664cba --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-pm.c @@ -0,0 +1,445 @@ +/* + * 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(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + 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(!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags))) + 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) +{ + int poll_rh = 1; + + /* keep on polling until RHSC is enabled */ + if (admhc_readl(ahcd, &ahcd->regs->int_enable) & ADMHC_INTR_INSM) + poll_rh = 0; + + return poll_rh; +} + +#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 new file mode 100644 index 0000000000..4c742c0f30 --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120-q.c @@ -0,0 +1,955 @@ +/* + * 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 + +/*-------------------------------------------------------------------------*/ + +/* + * 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 + * suceeds ... 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 inline void +ed_halted(struct admhcd *ahcd, struct td *td, int cc, struct td *rev) +{ + 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; + 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; + + /* 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 + * 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 new file mode 100644 index 0000000000..7c47cb8b7d --- /dev/null +++ b/target/linux/adm5120/files/drivers/usb/host/adm5120.h @@ -0,0 +1,762 @@ +/* + * 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; +#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. + * + * REVISIT: arch/powerpc now has readl/writel_be, so the + * definition below can die once the STB04xxx support is + * finally ported over. + */ +#if defined(CONFIG_PPC) && !defined(CONFIG_PPC_MERGE) +#define readl_be(addr) in_be32((__force unsigned *)addr) +#define writel_be(val, addr) out_be32((__force unsigned *)addr, val) +#endif + +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 new file mode 100644 index 0000000000..e92a898431 --- /dev/null +++ b/target/linux/adm5120/files/drivers/watchdog/adm5120_wdt.c @@ -0,0 +1,204 @@ +/* + * 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 = 0; +static int access = 0; +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 int wdt_ioctl(struct inode *inode, 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 struct file_operations wdt_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + write: wdt_write, + 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/include/asm-mips/mach-adm5120/adm5120_board.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_board.h new file mode 100644 index 0000000000..c45b53fc6c --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_board.h @@ -0,0 +1,44 @@ +/* + * ADM5120 board 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_BOARD_H +#define _ASM_MIPS_MACH_ADM5120_BOARD_H + +#include +#include + +#define ADM5120_BOARD_NAMELEN 64 + +struct adm5120_board { + unsigned long mach_type; + char name[ADM5120_BOARD_NAMELEN]; + + void (*board_setup)(void); + struct list_head list; +}; + +extern void adm5120_board_register(struct adm5120_board *) __init; + +#define ADM5120_BOARD(_type, _name, _setup) \ +static struct adm5120_board adm5120_board_##_type __initdata = { \ + .mach_type = _type, \ + .name = _name, \ + .board_setup = _setup, \ +}; \ + \ +static __init int adm5120_board_##_type##_register(void) \ +{ \ + adm5120_board_register(&adm5120_board_##_type); \ + return 0; \ +} \ +pure_initcall(adm5120_board_##_type##_register) + +#endif /* _ASM_MIPS_MACH_ADM5120_BOARD_H */ diff --git a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_defs.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_defs.h new file mode 100644 index 0000000000..bf220ff4d6 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/adm5120_info.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h new file mode 100644 index 0000000000..d28ef800a5 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_info.h @@ -0,0 +1,79 @@ +/* + * 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_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; + +/* + * 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/include/asm-mips/mach-adm5120/adm5120_intc.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_intc.h new file mode 100644 index 0000000000..52883cf2dc --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/adm5120_mpmc.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_mpmc.h new file mode 100644 index 0000000000..5383659dbf --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/adm5120_nand.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_nand.h new file mode 100644 index 0000000000..636d27fecf --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/adm5120_platform.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_platform.h new file mode 100644 index 0000000000..9d2e430cd8 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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 + +struct adm5120_flash_platform_data { + void (*set_vpp)(struct map_info *, int); + void (*switch_bank)(unsigned); + u32 window_size; +#ifdef CONFIG_MTD_PARTITIONS + unsigned int nr_parts; + struct mtd_partition *parts; +#endif +}; + +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_add_device_gpio(u32 disable_mask) __init; +extern void adm5120_add_device_gpio_buttons(unsigned nbuttons, + struct gpio_button *buttons) __init; + +#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/include/asm-mips/mach-adm5120/adm5120_switch.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_switch.h new file mode 100644 index 0000000000..91adc5bae9 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/adm5120_uart.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/adm5120_uart.h new file mode 100644 index 0000000000..6308f6bd18 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/asm/sizes.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/asm/sizes.h new file mode 100644 index 0000000000..503843db15 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/cpu-feature-overrides.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/cpu-feature-overrides.h new file mode 100644 index 0000000000..c6310cc6e6 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/gpio.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/gpio.h new file mode 100644 index 0000000000..7ba7efca1f --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/irq.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/irq.h new file mode 100644 index 0000000000..b0350c8b83 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/prom/admboot.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/admboot.h new file mode 100644 index 0000000000..fa42bf7148 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/prom/cfe.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/cfe.h new file mode 100644 index 0000000000..0cb3eee70e --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/prom/generic.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/generic.h new file mode 100644 index 0000000000..778df24677 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/prom/myloader.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/myloader.h new file mode 100644 index 0000000000..ea8db81ed3 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/prom/routerboot.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/routerboot.h new file mode 100644 index 0000000000..d5ad513d56 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/routerboot.h @@ -0,0 +1,125 @@ +/* + * 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 _ROUTERBOOT_H +#define _ROUTERBOOT_H + +#define RB_MAC_SIZE 6 + +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 */ +}; + +/* + * Magic numbers + */ +#define RB_MAGIC_HARD 0x64726148 /* "Hard" */ +#define RB_MAGIC_SOFT 0x74666F53 /* "Soft" */ +#define RB_MAGIC_DAWN 0x6E776144 /* "Dawn" */ + +#define RB_ID_TERMINATOR 0 + +/* + * ID values for Hardware settings + */ +#define RB_ID_HARD_01 1 +#define RB_ID_HARD_02 2 +#define RB_ID_FLASH_INFO 3 +#define RB_ID_MAC_ADDRESS_PACK 4 +#define RB_ID_BOARD_NAME 5 +#define RB_ID_BIOS_VERSION 6 +#define RB_ID_HARD_07 7 +#define RB_ID_SDRAM_TIMINGS 8 +#define RB_ID_DEVICE_TIMINGS 9 +#define RB_ID_SOFTWARE_ID 10 +#define RB_ID_SERIAL_NUMBER 11 +#define RB_ID_HARD_12 12 +#define RB_ID_MEMORY_SIZE 13 +#define RB_ID_MAC_ADDRESS_COUNT 14 + +/* + * ID values for Software settings + */ +#define RB_ID_UART_SPEED 1 +#define RB_ID_BOOT_DELAY 2 +#define RB_ID_BOOT_DEVICE 3 +#define RB_ID_BOOT_KEY 4 +#define RB_ID_CPU_MODE 5 +#define RB_ID_FW_VERSION 6 +#define RB_ID_SOFT_07 7 +#define RB_ID_SOFT_08 8 +#define RB_ID_BOOT_PROTOCOL 9 +#define RB_ID_SOFT_10 10 +#define RB_ID_SOFT_11 11 + +/* + * UART_SPEED values + */ +#define RB_UART_SPEED_115200 0 +#define RB_UART_SPEED_57600 1 +#define RB_UART_SPEED_38400 2 +#define RB_UART_SPEED_19200 3 +#define RB_UART_SPEED_9600 4 +#define RB_UART_SPEED_4800 5 +#define RB_UART_SPEED_2400 6 +#define RB_UART_SPEED_1200 7 + +/* + * BOOT_DELAY values + */ +#define RB_BOOT_DELAY_0SEC 0 +#define RB_BOOT_DELAY_1SEC 1 +#define RB_BOOT_DELAY_2SEC 2 + +/* + * BOOT_DEVICE values + */ +#define RB_BOOT_DEVICE_ETHER 0 +#define RB_BOOT_DEVICE_NANDETH 1 +#define RB_BOOT_DEVICE_ETHONCE 2 +#define RB_BOOT_DEVICE_NANDONLY 3 + +/* + * BOOT_KEY values + */ +#define RB_BOOT_KEY_ANY 0 +#define RB_BOOT_KEY_DEL 1 + +/* + * CPU_MODE values + */ +#define RB_CPU_MODE_POWERSAVE 0 +#define RB_CPU_MODE_REGULAR 1 + +/* + * BOOT_PROTOCOL values + */ +#define RB_BOOT_PROTOCOL_BOOTP 0 +#define RB_BOOT_PROTOCOL_DHCP 1 + +extern int routerboot_present(void) __init; +extern char *routerboot_get_boardname(void); + +extern struct rb_hard_settings rb_hs; + +#endif /* _ROUTERBOOT_H */ diff --git a/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/zynos.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/prom/zynos.h new file mode 100644 index 0000000000..d1e3e5b941 --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/include/asm-mips/mach-adm5120/war.h b/target/linux/adm5120/files/include/asm-mips/mach-adm5120/war.h new file mode 100644 index 0000000000..87c35f375b --- /dev/null +++ b/target/linux/adm5120/files/include/asm-mips/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/patches-2.6.27/001-adm5120.patch b/target/linux/adm5120/patches-2.6.27/001-adm5120.patch new file mode 100644 index 0000000000..909c846caa --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/001-adm5120.patch @@ -0,0 +1,113 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -19,6 +19,20 @@ + prompt "System type" + default SGI_IP22 + ++config ADM5120 ++ bool "Infineon/ADMtek ADM5120 SoC based machines" ++ select CEVT_R4K ++ select CSRC_R4K ++ select SYS_HAS_CPU_MIPS32_R1 ++ select SYS_HAS_EARLY_PRINTK ++ select DMA_NONCOHERENT ++ select IRQ_CPU ++ select SYS_SUPPORTS_LITTLE_ENDIAN ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select ARCH_REQUIRE_GPIOLIB ++ select SWAP_IO_SPACE if CPU_BIG_ENDIAN ++ + config MACH_ALCHEMY + bool "Alchemy processor based machines" + +@@ -597,6 +611,7 @@ + + endchoice + ++source "arch/mips/adm5120/Kconfig" + source "arch/mips/au1000/Kconfig" + source "arch/mips/basler/excite/Kconfig" + source "arch/mips/jazz/Kconfig" +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -174,6 +174,21 @@ + load-$(CONFIG_MACH_JAZZ) += 0xffffffff80080000 + + # ++# Infineon/ADMtek ADM5120 ++# ++libs-$(CONFIG_ADM5120) += arch/mips/adm5120/prom/ ++core-$(CONFIG_ADM5120) += arch/mips/adm5120/common/ ++core-$(CONFIG_ADM5120_OEM_CELLVISION) += arch/mips/adm5120/cellvision/ ++core-$(CONFIG_ADM5120_OEM_COMPEX) += arch/mips/adm5120/compex/ ++core-$(CONFIG_ADM5120_OEM_EDIMAX) += arch/mips/adm5120/edimax/ ++core-$(CONFIG_ADM5120_OEM_INFINEON) += arch/mips/adm5120/infineon/ ++core-$(CONFIG_ADM5120_OEM_MIKROTIK) += arch/mips/adm5120/mikrotik/ ++core-$(CONFIG_ADM5120_OEM_MOTOROLA) += arch/mips/adm5120/motorola/ ++core-$(CONFIG_ADM5120_OEM_ZYXEL) += arch/mips/adm5120/zyxel/ ++cflags-$(CONFIG_ADM5120) += -Iinclude/asm-mips/mach-adm5120 ++load-$(CONFIG_ADM5120) += 0xffffffff80001000 ++ ++# + # Common Alchemy Au1x00 stuff + # + core-$(CONFIG_SOC_AU1X00) += arch/mips/au1000/common/ +--- a/include/asm-mips/bootinfo.h ++++ b/include/asm-mips/bootinfo.h +@@ -57,6 +57,55 @@ + #define MACH_MIKROTIK_RB532 0 /* Mikrotik RouterBoard 532 */ + #define MACH_MIKROTIK_RB532A 1 /* Mikrotik RouterBoard 532A */ + ++/* ++ * Valid machtype for group ADM5120 ++ */ ++#define MACH_ADM5120_GENERIC 0 /* Generic board */ ++#define MACH_ADM5120_WP54G_WRT 1 /* Compex WP54G-WRT */ ++#define MACH_ADM5120_WP54 2 /* Compex WP54G/WP54AG/WPP54G/WPP54AG */ ++#define MACH_ADM5120_NP28G 3 /* Compex NP28G */ ++#define MACH_ADM5120_NP28GHS 4 /* Compex NP28G HotSpot */ ++#define MACH_ADM5120_NP27G 5 /* Compex NP27G */ ++#define MACH_ADM5120_WP54Gv1C 6 /* Compex WP54G version 1C */ ++#define MACH_ADM5120_RB_11X 7 /* Mikrotik RouterBOARD 111/112 */ ++#define MACH_ADM5120_RB_133 8 /* Mikrotik RouterBOARD 133 */ ++#define MACH_ADM5120_RB_133C 9 /* Mikrotik RouterBOARD 133c */ ++#define MACH_ADM5120_RB_150 10 /* Mikrotik RouterBOARD 150 */ ++#define MACH_ADM5120_RB_153 11 /* Mikrotik RouterBOARD 153 */ ++#define MACH_ADM5120_RB_192 12 /* Mikrotik RouterBOARD 192 */ ++#define MACH_ADM5120_HS100 13 /* ZyXEL HomeSafe 100/100W */ ++#define MACH_ADM5120_P334U 14 /* ZyXEL Prestige 334U */ ++#define MACH_ADM5120_P334W 15 /* ZyXEL Prestige 334W */ ++#define MACH_ADM5120_P334WH 16 /* ZyXEL Prestige 334WH */ ++#define MACH_ADM5120_P334WHD 17 /* ZyXEL Prestige 334WHD */ ++#define MACH_ADM5120_P334WT 18 /* ZyXEL Prestige 334WT */ ++#define MACH_ADM5120_P335 19 /* ZyXEL Prestige 335/335WT */ ++#define MACH_ADM5120_P335PLUS 20 /* ZyXEL Prestige 335Plus */ ++#define MACH_ADM5120_P335U 21 /* ZyXEL Prestige 335U */ ++#define MACH_ADM5120_ES2108 22 /* ZyXEL Ethernet Switch 2108 */ ++#define MACH_ADM5120_ES2108F 23 /* ZyXEL Ethernet Switch 2108-F */ ++#define MACH_ADM5120_ES2108G 24 /* ZyXEL Ethernet Switch 2108-G */ ++#define MACH_ADM5120_ES2108LC 25 /* ZyXEL Ethernet Switch 2108-LC */ ++#define MACH_ADM5120_ES2108PWR 26 /* ZyXEL Ethernet Switch 2108-PWR */ ++#define MACH_ADM5120_ES2024A 27 /* ZyXEL Ethernet Switch 2024A */ ++#define MACH_ADM5120_ES2024PWR 28 /* ZyXEL Ethernet Switch 2024PWR */ ++#define MACH_ADM5120_CAS630 29 /* Cellvision CAS-630/630W */ ++#define MACH_ADM5120_CAS670 30 /* Cellvision CAS-670/670W */ ++#define MACH_ADM5120_CAS700 31 /* Cellvision CAS-700/700W */ ++#define MACH_ADM5120_CAS771 32 /* Cellvision CAS-771/771W */ ++#define MACH_ADM5120_CAS790 33 /* Cellvision CAS-790 */ ++#define MACH_ADM5120_CAS861 34 /* Cellvision CAS-861/861W */ ++#define MACH_ADM5120_NFS101U 35 /* Cellvision NFS-101U/101WU */ ++#define MACH_ADM5120_NFS202U 36 /* Cellvision NFS-202U/202WU */ ++#define MACH_ADM5120_EASY5120PATA 37 /* Infineon EASY 5120P-ATA */ ++#define MACH_ADM5120_EASY5120RT 38 /* Infineon EASY 5120-RT */ ++#define MACH_ADM5120_EASY5120WVOIP 39 /* Infineon EASY 5120-WVoIP */ ++#define MACH_ADM5120_EASY83000 40 /* Infineon EASY-83000 */ ++#define MACH_ADM5120_BR6104K 41 /* Edimax BR-6104K */ ++#define MACH_ADM5120_BR6104KP 42 /* Edimax BR-6104KP */ ++#define MACH_ADM5120_BR61X4WG 43 /* Edimax BR-6104Wg/BR-6114WG */ ++#define MACH_ADM5120_PMUGW 44 /* Motorola Powerline MU Gateway */ ++ + #define CL_SIZE COMMAND_LINE_SIZE + + extern char *system_type; diff --git a/target/linux/adm5120/patches-2.6.27/002-adm5120_flash.patch b/target/linux/adm5120/patches-2.6.27/002-adm5120_flash.patch new file mode 100644 index 0000000000..923b4fa1fe --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/002-adm5120_flash.patch @@ -0,0 +1,22 @@ +--- a/drivers/mtd/maps/Kconfig ++++ b/drivers/mtd/maps/Kconfig +@@ -571,5 +571,9 @@ + + This selection automatically selects the map_ram driver. + ++config MTD_ADM5120 ++ tristate "Map driver for ADM5120 based boards" ++ depends on ADM5120 ++ + endmenu + +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -42,6 +42,7 @@ + obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o + obj-$(CONFIG_MTD_PCI) += pci.o + obj-$(CONFIG_MTD_ALCHEMY) += alchemy-flash.o ++obj-$(CONFIG_MTD_ADM5120) += adm5120-flash.o + obj-$(CONFIG_MTD_AUTCPU12) += autcpu12-nvram.o + obj-$(CONFIG_MTD_EDB7312) += edb7312.o + obj-$(CONFIG_MTD_IMPA7) += impa7.o diff --git a/target/linux/adm5120/patches-2.6.27/003-adm5120_switch.patch b/target/linux/adm5120/patches-2.6.27/003-adm5120_switch.patch new file mode 100644 index 0000000000..1502a4225d --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/003-adm5120_switch.patch @@ -0,0 +1,23 @@ +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -596,6 +596,10 @@ + If you have an Alchemy Semi AU1X00 based system + say Y. Otherwise, say N. + ++config ADM5120_ENET ++ tristate "ADM5120 Ethernet switch support" ++ depends on ADM5120 ++ + config SGI_IOC3_ETH + bool "SGI IOC3 Ethernet" + depends on PCI && SGI_IP27 +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -187,6 +187,7 @@ + # This is also a 82596 and should probably be merged + obj-$(CONFIG_LP486E) += lp486e.o + ++obj-$(CONFIG_ADM5120_ENET) += adm5120sw.o + obj-$(CONFIG_ETH16I) += eth16i.o + obj-$(CONFIG_ZORRO8390) += zorro8390.o + obj-$(CONFIG_HPLANCE) += hplance.o 7990.o diff --git a/target/linux/adm5120/patches-2.6.27/005-adm5120_usb.patch b/target/linux/adm5120/patches-2.6.27/005-adm5120_usb.patch new file mode 100644 index 0000000000..ae85e6468d --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/005-adm5120_usb.patch @@ -0,0 +1,33 @@ +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -4,6 +4,10 @@ + comment "USB Host Controller Drivers" + depends on USB + ++config USB_ADM5120_HCD ++ tristate "ADM5120 HCD support (EXPERIMENTAL)" ++ depends on USB && ADM5120 && EXPERIMENTAL ++ + config USB_C67X00_HCD + tristate "Cypress C67x00 HCD support" + depends on USB +--- a/drivers/usb/host/Makefile ++++ b/drivers/usb/host/Makefile +@@ -10,6 +10,7 @@ + + obj-$(CONFIG_PCI) += pci-quirks.o + ++obj-$(CONFIG_USB_ADM5120_HCD) += adm5120-hcd.o + obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o + obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o + obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -16,6 +16,7 @@ + obj-$(CONFIG_USB_SL811_HCD) += host/ + obj-$(CONFIG_USB_U132_HCD) += host/ + obj-$(CONFIG_USB_R8A66597_HCD) += host/ ++obj-$(CONFIG_USB_ADM5120_HCD) += host/ + + obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ + diff --git a/target/linux/adm5120/patches-2.6.27/007-adm5120_pci.patch b/target/linux/adm5120/patches-2.6.27/007-adm5120_pci.patch new file mode 100644 index 0000000000..63f90671d7 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/007-adm5120_pci.patch @@ -0,0 +1,19 @@ +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -51,3 +51,4 @@ + obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o + obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o + obj-$(CONFIG_MIKROTIK_RB532) += pci-rc32434.o ops-rc32434.o fixup-rc32434.o ++obj-$(CONFIG_ADM5120) += pci-adm5120.o +--- a/include/linux/pci_ids.h ++++ b/include/linux/pci_ids.h +@@ -1708,6 +1708,9 @@ + #define PCI_VENDOR_ID_ESDGMBH 0x12fe + #define PCI_DEVICE_ID_ESDGMBH_CPCIASIO4 0x0111 + ++#define PCI_VENDOR_ID_ADMTEK 0x1317 ++#define PCI_DEVICE_ID_ADMTEK_ADM5120 0x5120 ++ + #define PCI_VENDOR_ID_SIIG 0x131f + #define PCI_SUBVENDOR_ID_SIIG 0x131f + #define PCI_DEVICE_ID_SIIG_1S_10x_550 0x1000 diff --git a/target/linux/adm5120/patches-2.6.27/009-adm5120_leds_switch_trigger.patch b/target/linux/adm5120/patches-2.6.27/009-adm5120_leds_switch_trigger.patch new file mode 100644 index 0000000000..79d0bcbd3b --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/009-adm5120_leds_switch_trigger.patch @@ -0,0 +1,22 @@ +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -223,4 +223,12 @@ + This allows LEDs to be controlled by network device activity. + If unsure, say Y. + ++config LEDS_TRIGGER_ADM5120_SWITCH ++ tristate "LED ADM5120 Switch Port Status Trigger" ++ depends on LEDS_TRIGGERS && ADM5120 ++ help ++ This allows LEDs to be controlled by the port states of ++ the ADM5120 built-in Ethernet Switch ++ If unsure, say N. ++ + endif # NEW_LEDS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -32,3 +32,4 @@ + obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o + obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o + obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o ++obj-$(CONFIG_LEDS_TRIGGER_ADM5120_SWITCH) += ledtrig-adm5120-switch.o diff --git a/target/linux/adm5120/patches-2.6.27/100-mtd_myloder_partition_parser.patch b/target/linux/adm5120/patches-2.6.27/100-mtd_myloder_partition_parser.patch new file mode 100644 index 0000000000..6d4daeeeb2 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/100-mtd_myloder_partition_parser.patch @@ -0,0 +1,35 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -172,6 +172,22 @@ + ---help--- + TI AR7 partitioning support + ++config MTD_MYLOADER_PARTS ++ tristate "MyLoader partition parsing" ++ depends on ADM5120 && MTD_PARTITIONS ++ ---help--- ++ MyLoader is a bootloader which allows the user to define partitions ++ in flash devices, by putting a table in the second erase block ++ on the device, similar to a partition table. This table gives the ++ offsets and lengths of the user defined partitions. ++ ++ If you need code which can detect and parse these tables, and ++ register MTD 'partitions' corresponding to each image detected, ++ enable this option. ++ ++ You will still need the parsing functions to be called by the driver ++ for your particular device. It won't happen automatically. ++ + comment "User Modules And Translation Layers" + + config MTD_CHAR +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -13,6 +13,7 @@ + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o + obj-$(CONFIG_MTD_AR7_PARTS) += ar7part.o + obj-$(CONFIG_MTD_OF_PARTS) += ofpart.o ++obj-$(CONFIG_MTD_MYLOADER_PARTS) += myloader.o + + # 'Users' - code which presents functionality to userspace. + obj-$(CONFIG_MTD_CHAR) += mtdchar.o diff --git a/target/linux/adm5120/patches-2.6.27/101-cfi_fixup_macronix_bootloc.patch b/target/linux/adm5120/patches-2.6.27/101-cfi_fixup_macronix_bootloc.patch new file mode 100644 index 0000000000..19ad785a44 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/101-cfi_fixup_macronix_bootloc.patch @@ -0,0 +1,91 @@ +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -44,12 +44,19 @@ + #define MANUFACTURER_AMD 0x0001 + #define MANUFACTURER_ATMEL 0x001F + #define MANUFACTURER_SST 0x00BF ++#define MANUFACTURER_MACRONIX 0x00C2 + #define SST49LF004B 0x0060 + #define SST49LF040B 0x0050 + #define SST49LF008A 0x005a + #define AT49BV6416 0x00d6 + #define MANUFACTURER_SAMSUNG 0x00ec + ++/* Macronix */ ++#define MX29LV160B 0x2249 /* MX29LV160 Bottom-boot chip */ ++#define MX29LV160T 0x22C4 /* MX29LV160 Top-boot chip */ ++#define MX29LV320B 0x22A8 /* MX29LV320 Bottom-boot chip */ ++#define MX29LV320T 0x22A7 /* MX29LV320 Top-boot chip */ ++ + static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); + static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); + static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +@@ -240,6 +247,41 @@ + } + } + ++#ifdef CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC ++/* ++ * Some Macronix chips has no/bad bootblock information in the CFI table ++ */ ++static void fixup_macronix_bootloc(struct mtd_info *mtd, void* param) ++{ ++ struct map_info *map = mtd->priv; ++ struct cfi_private *cfi = map->fldrv_priv; ++ struct cfi_pri_amdstd *extp = cfi->cmdset_priv; ++ __u8 t; ++ ++ switch (cfi->id) { ++ /* TODO: put affected chip ids here */ ++ case MX29LV160B: ++ case MX29LV320B: ++ t = 2; /* Bottom boot */ ++ break; ++ case MX29LV160T: ++ case MX29LV320T: ++ t = 3; /* Top boot */ ++ break; ++ default: ++ return; ++ } ++ ++ if (extp->TopBottom == t) ++ /* boot location detected by the CFI layer is correct */ ++ return; ++ ++ extp->TopBottom = t; ++ printk("%s: Macronix chip detected, id:0x%04X, boot location forced " ++ "to %s\n", map->name, cfi->id, (t == 2) ? "bottom" : "top"); ++} ++#endif /* CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC */ ++ + static struct cfi_fixup cfi_fixup_table[] = { + { CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri, NULL }, + #ifdef AMD_BOOTLOC_BUG +@@ -275,6 +317,9 @@ + */ + { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_erase_chip, NULL }, + { CFI_MFR_ATMEL, AT49BV6416, fixup_use_atmel_lock, NULL }, ++#ifdef CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC ++ { MANUFACTURER_MACRONIX, CFI_ID_ANY, fixup_macronix_bootloc, NULL, }, ++#endif + { 0, 0, NULL, NULL } + }; + +--- a/drivers/mtd/chips/Kconfig ++++ b/drivers/mtd/chips/Kconfig +@@ -196,6 +196,14 @@ + provides support for one of those command sets, used on chips + including the AMD Am29LV320. + ++config MTD_CFI_FIXUP_MACRONIX_BOOTLOC ++ bool "Fix boot-block location for Macronix flash chips" ++ depends on MTD_CFI_AMDSTD ++ help ++ Some Macronix flash chips have no/wrong boot-block location in the ++ CFI table, and the driver may detect the type incorrectly. Select ++ this if your board has such chip. ++ + config MTD_CFI_STAA + tristate "Support for ST (Advanced Architecture) flash chips" + depends on MTD_GEN_PROBE diff --git a/target/linux/adm5120/patches-2.6.27/102-jedec_pmc_39lvxxx_chips.patch b/target/linux/adm5120/patches-2.6.27/102-jedec_pmc_39lvxxx_chips.patch new file mode 100644 index 0000000000..9501800fe2 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/102-jedec_pmc_39lvxxx_chips.patch @@ -0,0 +1,68 @@ +--- a/drivers/mtd/chips/jedec_probe.c ++++ b/drivers/mtd/chips/jedec_probe.c +@@ -128,6 +128,10 @@ + #define UPD29F064115 0x221C + + /* PMC */ ++#define PM39LV512 0x001B ++#define PM39LV010 0x001C ++#define PM39LV020 0x003D ++#define PM39LV040 0x003E + #define PM49FL002 0x006D + #define PM49FL004 0x006E + #define PM49FL008 0x006A +@@ -1248,6 +1252,54 @@ + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1), + } ++ }, { ++ .mfr_id = MANUFACTURER_PMC, ++ .dev_id = PM39LV512, ++ .name = "PMC Pm39LV512", ++ .devtypes = CFI_DEVICETYPE_X8, ++ .uaddr = MTD_UADDR_0x0555_0x02AA, ++ .dev_size = SIZE_64KiB, ++ .cmd_set = P_ID_AMD_STD, ++ .nr_regions = 1, ++ .regions = { ++ ERASEINFO(0x01000,16), ++ } ++ }, { ++ .mfr_id = MANUFACTURER_PMC, ++ .dev_id = PM39LV010, ++ .name = "PMC Pm39LV010", ++ .devtypes = CFI_DEVICETYPE_X8, ++ .uaddr = MTD_UADDR_0x0555_0x02AA, ++ .dev_size = SIZE_128KiB, ++ .cmd_set = P_ID_AMD_STD, ++ .nr_regions = 1, ++ .regions = { ++ ERASEINFO(0x01000,32), ++ } ++ }, { ++ .mfr_id = MANUFACTURER_PMC, ++ .dev_id = PM39LV020, ++ .name = "PMC Pm39LV020", ++ .devtypes = CFI_DEVICETYPE_X8, ++ .uaddr = MTD_UADDR_0x0555_0x02AA, ++ .dev_size = SIZE_256KiB, ++ .cmd_set = P_ID_AMD_STD, ++ .nr_regions = 1, ++ .regions = { ++ ERASEINFO(0x01000,64), ++ } ++ }, { ++ .mfr_id = MANUFACTURER_PMC, ++ .dev_id = PM39LV040, ++ .name = "PMC Pm39LV040", ++ .devtypes = CFI_DEVICETYPE_X8, ++ .uaddr = MTD_UADDR_0x0555_0x02AA, ++ .dev_size = SIZE_512KiB, ++ .cmd_set = P_ID_AMD_STD, ++ .nr_regions = 1, ++ .regions = { ++ ERASEINFO(0x01000,128), ++ } + }, { + .mfr_id = MANUFACTURER_PMC, + .dev_id = PM49FL002, diff --git a/target/linux/adm5120/patches-2.6.27/103-mtd_trxsplit.patch b/target/linux/adm5120/patches-2.6.27/103-mtd_trxsplit.patch new file mode 100644 index 0000000000..4ebf10ca23 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/103-mtd_trxsplit.patch @@ -0,0 +1,24 @@ +--- a/drivers/mtd/Kconfig ++++ b/drivers/mtd/Kconfig +@@ -55,6 +55,11 @@ + depends on MTD_PARTITIONS + default y + ++config MTD_TRXSPLIT ++ bool "Automatically find and split TRX partitions" ++ depends on MTD_PARTITIONS ++ default n ++ + config MTD_REDBOOT_PARTS + tristate "RedBoot partition table parsing" + depends on MTD_PARTITIONS +--- a/drivers/mtd/Makefile ++++ b/drivers/mtd/Makefile +@@ -8,6 +8,7 @@ + mtd-$(CONFIG_MTD_PARTITIONS) += mtdpart.o + + obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o ++obj-$(CONFIG_MTD_TRXSPLIT) += trxsplit.o + obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o + obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o + obj-$(CONFIG_MTD_AFS_PARTS) += afs.o diff --git a/target/linux/adm5120/patches-2.6.27/120-rb153_cf_driver.patch b/target/linux/adm5120/patches-2.6.27/120-rb153_cf_driver.patch new file mode 100644 index 0000000000..b30c5def6b --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/120-rb153_cf_driver.patch @@ -0,0 +1,28 @@ +--- a/drivers/ata/Makefile ++++ b/drivers/ata/Makefile +@@ -72,6 +72,7 @@ + obj-$(CONFIG_PATA_PLATFORM) += pata_platform.o + obj-$(CONFIG_PATA_OF_PLATFORM) += pata_of_platform.o + obj-$(CONFIG_PATA_ICSIDE) += pata_icside.o ++obj-$(CONFIG_PATA_RB153_CF) += pata_rb153_cf.o + # Should be last but two libata driver + obj-$(CONFIG_PATA_ACPI) += pata_acpi.o + # Should be last but one libata driver +--- a/drivers/ata/Kconfig ++++ b/drivers/ata/Kconfig +@@ -568,6 +568,15 @@ + + If unsure, say N. + ++config PATA_RB153_CF ++ tristate "RouterBOARD 153 Compact Flash support" ++ depends on ADM5120_MACH_RB_153 ++ help ++ This option enables support for a Compact Flash connected on ++ the RouterBOARD 153. ++ ++ If unsure, say N. ++ + config PATA_RB532 + tristate "RouterBoard 532 PATA CompactFlash support" + depends on MIKROTIK_RB532 diff --git a/target/linux/adm5120/patches-2.6.27/140-cmdline_hack.patch b/target/linux/adm5120/patches-2.6.27/140-cmdline_hack.patch new file mode 100644 index 0000000000..1ced3f62dd --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/140-cmdline_hack.patch @@ -0,0 +1,15 @@ +--- a/arch/mips/kernel/head.S ++++ b/arch/mips/kernel/head.S +@@ -126,7 +126,12 @@ + /* + * Reserved space for exception handlers. + * Necessary for machines which link their kernels at KSEG0. ++ * Use as temporary storage for the kernel command line, so that it ++ * can be updated easily without having to relink the kernel. + */ ++ ++EXPORT(_image_cmdline) ++ .ascii "CMDLINE:" + .fill 0x400 + #endif + diff --git a/target/linux/adm5120/patches-2.6.27/200-amba_pl010_hacks.patch b/target/linux/adm5120/patches-2.6.27/200-amba_pl010_hacks.patch new file mode 100644 index 0000000000..0352b86eae --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/200-amba_pl010_hacks.patch @@ -0,0 +1,378 @@ +--- a/drivers/serial/amba-pl010.c ++++ b/drivers/serial/amba-pl010.c +@@ -50,11 +50,10 @@ + + #include + +-#define UART_NR 8 +- + #define SERIAL_AMBA_MAJOR 204 + #define SERIAL_AMBA_MINOR 16 +-#define SERIAL_AMBA_NR UART_NR ++#define SERIAL_AMBA_NR CONFIG_SERIAL_AMBA_PL010_NUMPORTS ++#define SERIAL_AMBA_NAME CONFIG_SERIAL_AMBA_PL010_PORTNAME + + #define AMBA_ISR_PASS_LIMIT 256 + +@@ -80,9 +79,9 @@ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + +- cr = readb(uap->port.membase + UART010_CR); ++ cr = __raw_readl(uap->port.membase + UART010_CR); + cr &= ~UART010_CR_TIE; +- writel(cr, uap->port.membase + UART010_CR); ++ __raw_writel(cr, uap->port.membase + UART010_CR); + } + + static void pl010_start_tx(struct uart_port *port) +@@ -90,9 +89,9 @@ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + +- cr = readb(uap->port.membase + UART010_CR); ++ cr = __raw_readl(uap->port.membase + UART010_CR); + cr |= UART010_CR_TIE; +- writel(cr, uap->port.membase + UART010_CR); ++ __raw_writel(cr, uap->port.membase + UART010_CR); + } + + static void pl010_stop_rx(struct uart_port *port) +@@ -100,9 +99,9 @@ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + +- cr = readb(uap->port.membase + UART010_CR); ++ cr = __raw_readl(uap->port.membase + UART010_CR); + cr &= ~(UART010_CR_RIE | UART010_CR_RTIE); +- writel(cr, uap->port.membase + UART010_CR); ++ __raw_writel(cr, uap->port.membase + UART010_CR); + } + + static void pl010_enable_ms(struct uart_port *port) +@@ -110,9 +109,9 @@ + struct uart_amba_port *uap = (struct uart_amba_port *)port; + unsigned int cr; + +- cr = readb(uap->port.membase + UART010_CR); ++ cr = __raw_readl(uap->port.membase + UART010_CR); + cr |= UART010_CR_MSIE; +- writel(cr, uap->port.membase + UART010_CR); ++ __raw_writel(cr, uap->port.membase + UART010_CR); + } + + static void pl010_rx_chars(struct uart_amba_port *uap) +@@ -120,9 +119,9 @@ + struct tty_struct *tty = uap->port.info->port.tty; + unsigned int status, ch, flag, rsr, max_count = 256; + +- status = readb(uap->port.membase + UART01x_FR); ++ status = __raw_readl(uap->port.membase + UART01x_FR); + while (UART_RX_DATA(status) && max_count--) { +- ch = readb(uap->port.membase + UART01x_DR); ++ ch = __raw_readl(uap->port.membase + UART01x_DR); + flag = TTY_NORMAL; + + uap->port.icount.rx++; +@@ -131,9 +130,9 @@ + * Note that the error handling code is + * out of the main execution path + */ +- rsr = readb(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; ++ rsr = __raw_readl(uap->port.membase + UART01x_RSR) | UART_DUMMY_RSR_RX; + if (unlikely(rsr & UART01x_RSR_ANY)) { +- writel(0, uap->port.membase + UART01x_ECR); ++ __raw_writel(0, uap->port.membase + UART01x_ECR); + + if (rsr & UART01x_RSR_BE) { + rsr &= ~(UART01x_RSR_FE | UART01x_RSR_PE); +@@ -163,7 +162,7 @@ + uart_insert_char(&uap->port, rsr, UART01x_RSR_OE, ch, flag); + + ignore_char: +- status = readb(uap->port.membase + UART01x_FR); ++ status = __raw_readl(uap->port.membase + UART01x_FR); + } + spin_unlock(&uap->port.lock); + tty_flip_buffer_push(tty); +@@ -176,7 +175,7 @@ + int count; + + if (uap->port.x_char) { +- writel(uap->port.x_char, uap->port.membase + UART01x_DR); ++ __raw_writel(uap->port.x_char, uap->port.membase + UART01x_DR); + uap->port.icount.tx++; + uap->port.x_char = 0; + return; +@@ -188,7 +187,7 @@ + + count = uap->port.fifosize >> 1; + do { +- writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); ++ __raw_writel(xmit->buf[xmit->tail], uap->port.membase + UART01x_DR); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + uap->port.icount.tx++; + if (uart_circ_empty(xmit)) +@@ -206,9 +205,9 @@ + { + unsigned int status, delta; + +- writel(0, uap->port.membase + UART010_ICR); ++ __raw_writel(0, uap->port.membase + UART010_ICR); + +- status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; ++ status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + + delta = status ^ uap->old_status; + uap->old_status = status; +@@ -236,7 +235,7 @@ + + spin_lock(&uap->port.lock); + +- status = readb(uap->port.membase + UART010_IIR); ++ status = __raw_readl(uap->port.membase + UART010_IIR); + if (status) { + do { + if (status & (UART010_IIR_RTIS | UART010_IIR_RIS)) +@@ -249,7 +248,7 @@ + if (pass_counter-- == 0) + break; + +- status = readb(uap->port.membase + UART010_IIR); ++ status = __raw_readl(uap->port.membase + UART010_IIR); + } while (status & (UART010_IIR_RTIS | UART010_IIR_RIS | + UART010_IIR_TIS)); + handled = 1; +@@ -263,7 +262,7 @@ + static unsigned int pl010_tx_empty(struct uart_port *port) + { + struct uart_amba_port *uap = (struct uart_amba_port *)port; +- unsigned int status = readb(uap->port.membase + UART01x_FR); ++ unsigned int status = __raw_readl(uap->port.membase + UART01x_FR); + return status & UART01x_FR_BUSY ? 0 : TIOCSER_TEMT; + } + +@@ -273,7 +272,7 @@ + unsigned int result = 0; + unsigned int status; + +- status = readb(uap->port.membase + UART01x_FR); ++ status = __raw_readl(uap->port.membase + UART01x_FR); + if (status & UART01x_FR_DCD) + result |= TIOCM_CAR; + if (status & UART01x_FR_DSR) +@@ -299,12 +298,12 @@ + unsigned int lcr_h; + + spin_lock_irqsave(&uap->port.lock, flags); +- lcr_h = readb(uap->port.membase + UART010_LCRH); ++ lcr_h = __raw_readl(uap->port.membase + UART010_LCRH); + if (break_state == -1) + lcr_h |= UART01x_LCRH_BRK; + else + lcr_h &= ~UART01x_LCRH_BRK; +- writel(lcr_h, uap->port.membase + UART010_LCRH); ++ __raw_writel(lcr_h, uap->port.membase + UART010_LCRH); + spin_unlock_irqrestore(&uap->port.lock, flags); + } + +@@ -332,12 +331,12 @@ + /* + * initialise the old status of the modem signals + */ +- uap->old_status = readb(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; ++ uap->old_status = __raw_readl(uap->port.membase + UART01x_FR) & UART01x_FR_MODEM_ANY; + + /* + * Finally, enable interrupts + */ +- writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, ++ __raw_writel(UART01x_CR_UARTEN | UART010_CR_RIE | UART010_CR_RTIE, + uap->port.membase + UART010_CR); + + return 0; +@@ -360,10 +359,10 @@ + /* + * disable all interrupts, disable the port + */ +- writel(0, uap->port.membase + UART010_CR); ++ __raw_writel(0, uap->port.membase + UART010_CR); + + /* disable break condition and fifos */ +- writel(readb(uap->port.membase + UART010_LCRH) & ++ __raw_writel(__raw_readl(uap->port.membase + UART010_LCRH) & + ~(UART01x_LCRH_BRK | UART01x_LCRH_FEN), + uap->port.membase + UART010_LCRH); + +@@ -385,7 +384,7 @@ + /* + * Ask the core to calculate the divisor for us. + */ +- baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); ++ baud = uart_get_baud_rate(port, termios, old, 0, uap->port.uartclk/16); + quot = uart_get_divisor(port, baud); + + switch (termios->c_cflag & CSIZE) { +@@ -448,25 +447,25 @@ + uap->port.ignore_status_mask |= UART_DUMMY_RSR_RX; + + /* first, disable everything */ +- old_cr = readb(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; ++ old_cr = __raw_readl(uap->port.membase + UART010_CR) & ~UART010_CR_MSIE; + + if (UART_ENABLE_MS(port, termios->c_cflag)) + old_cr |= UART010_CR_MSIE; + +- writel(0, uap->port.membase + UART010_CR); ++ __raw_writel(0, uap->port.membase + UART010_CR); + + /* Set baud rate */ + quot -= 1; +- writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); +- writel(quot & 0xff, uap->port.membase + UART010_LCRL); ++ __raw_writel((quot & 0xf00) >> 8, uap->port.membase + UART010_LCRM); ++ __raw_writel(quot & 0xff, uap->port.membase + UART010_LCRL); + + /* + * ----------v----------v----------v----------v----- + * NOTE: MUST BE WRITTEN AFTER UARTLCR_M & UARTLCR_L + * ----------^----------^----------^----------^----- + */ +- writel(lcr_h, uap->port.membase + UART010_LCRH); +- writel(old_cr, uap->port.membase + UART010_CR); ++ __raw_writel(lcr_h, uap->port.membase + UART010_LCRH); ++ __raw_writel(old_cr, uap->port.membase + UART010_CR); + + spin_unlock_irqrestore(&uap->port.lock, flags); + } +@@ -538,7 +537,7 @@ + .verify_port = pl010_verify_port, + }; + +-static struct uart_amba_port *amba_ports[UART_NR]; ++static struct uart_amba_port *amba_ports[SERIAL_AMBA_NR]; + + #ifdef CONFIG_SERIAL_AMBA_PL010_CONSOLE + +@@ -548,10 +547,10 @@ + unsigned int status; + + do { +- status = readb(uap->port.membase + UART01x_FR); ++ status = __raw_readl(uap->port.membase + UART01x_FR); + barrier(); + } while (!UART_TX_READY(status)); +- writel(ch, uap->port.membase + UART01x_DR); ++ __raw_writel(ch, uap->port.membase + UART01x_DR); + } + + static void +@@ -565,8 +564,8 @@ + /* + * First save the CR then disable the interrupts + */ +- old_cr = readb(uap->port.membase + UART010_CR); +- writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); ++ old_cr = __raw_readl(uap->port.membase + UART010_CR); ++ __raw_writel(UART01x_CR_UARTEN, uap->port.membase + UART010_CR); + + uart_console_write(&uap->port, s, count, pl010_console_putchar); + +@@ -575,10 +574,10 @@ + * and restore the TCR + */ + do { +- status = readb(uap->port.membase + UART01x_FR); ++ status = __raw_readl(uap->port.membase + UART01x_FR); + barrier(); + } while (status & UART01x_FR_BUSY); +- writel(old_cr, uap->port.membase + UART010_CR); ++ __raw_writel(old_cr, uap->port.membase + UART010_CR); + + clk_disable(uap->clk); + } +@@ -587,9 +586,9 @@ + pl010_console_get_options(struct uart_amba_port *uap, int *baud, + int *parity, int *bits) + { +- if (readb(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) { ++ if (__raw_readl(uap->port.membase + UART010_CR) & UART01x_CR_UARTEN) { + unsigned int lcr_h, quot; +- lcr_h = readb(uap->port.membase + UART010_LCRH); ++ lcr_h = __raw_readl(uap->port.membase + UART010_LCRH); + + *parity = 'n'; + if (lcr_h & UART01x_LCRH_PEN) { +@@ -604,8 +603,8 @@ + else + *bits = 8; + +- quot = readb(uap->port.membase + UART010_LCRL) | +- readb(uap->port.membase + UART010_LCRM) << 8; ++ quot = __raw_readl(uap->port.membase + UART010_LCRL) | ++ __raw_readl(uap->port.membase + UART010_LCRM) << 8; + *baud = uap->port.uartclk / (16 * (quot + 1)); + } + } +@@ -623,7 +622,7 @@ + * if so, search for the first available port that does have + * console support. + */ +- if (co->index >= UART_NR) ++ if (co->index >= SERIAL_AMBA_NR) + co->index = 0; + uap = amba_ports[co->index]; + if (!uap) +@@ -641,7 +640,7 @@ + + static struct uart_driver amba_reg; + static struct console amba_console = { +- .name = "ttyAM", ++ .name = SERIAL_AMBA_NAME, + .write = pl010_console_write, + .device = uart_console_device, + .setup = pl010_console_setup, +@@ -657,11 +656,11 @@ + + static struct uart_driver amba_reg = { + .owner = THIS_MODULE, +- .driver_name = "ttyAM", +- .dev_name = "ttyAM", ++ .driver_name = SERIAL_AMBA_NAME, ++ .dev_name = SERIAL_AMBA_NAME, + .major = SERIAL_AMBA_MAJOR, + .minor = SERIAL_AMBA_MINOR, +- .nr = UART_NR, ++ .nr = SERIAL_AMBA_NR, + .cons = AMBA_CONSOLE, + }; + +--- a/drivers/serial/Kconfig ++++ b/drivers/serial/Kconfig +@@ -285,10 +285,25 @@ + help + This selects the ARM(R) AMBA(R) PrimeCell PL010 UART. If you have + an Integrator/AP or Integrator/PP2 platform, or if you have a +- Cirrus Logic EP93xx CPU, say Y or M here. ++ Cirrus Logic EP93xx CPU or an Infineon ADM5120 SOC, say Y or M here. + + If unsure, say N. + ++config SERIAL_AMBA_PL010_NUMPORTS ++ int "Maximum number of AMBA PL010 serial ports" ++ depends on SERIAL_AMBA_PL010 ++ default "8" ++ ---help--- ++ Set this to the number of serial ports you want the AMBA PL010 driver ++ to support. ++ ++config SERIAL_AMBA_PL010_PORTNAME ++ string "Name of the AMBA PL010 serial ports" ++ depends on SERIAL_AMBA_PL010 ++ default "ttyAM" ++ ---help--- ++ ::: To be written ::: ++ + config SERIAL_AMBA_PL010_CONSOLE + bool "Support for console on AMBA serial port" + depends on SERIAL_AMBA_PL010=y diff --git a/target/linux/adm5120/patches-2.6.27/201-amba_bus_hacks.patch b/target/linux/adm5120/patches-2.6.27/201-amba_bus_hacks.patch new file mode 100644 index 0000000000..299f216523 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/201-amba_bus_hacks.patch @@ -0,0 +1,13 @@ +--- a/drivers/amba/bus.c ++++ b/drivers/amba/bus.c +@@ -17,6 +17,10 @@ + #include + #include + ++#ifndef NO_IRQ ++#define NO_IRQ (-1) ++#endif ++ + #define to_amba_device(d) container_of(d, struct amba_device, dev) + #define to_amba_driver(d) container_of(d, struct amba_driver, drv) + diff --git a/target/linux/adm5120/patches-2.6.27/202-pci_disable_common_quirks.patch b/target/linux/adm5120/patches-2.6.27/202-pci_disable_common_quirks.patch new file mode 100644 index 0000000000..469f040f95 --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/202-pci_disable_common_quirks.patch @@ -0,0 +1,46 @@ +--- a/drivers/pci/Kconfig ++++ b/drivers/pci/Kconfig +@@ -42,6 +42,12 @@ + + When in doubt, say N. + ++config PCI_DISABLE_COMMON_QUIRKS ++ bool "PCI disable common quirks" ++ depends on PCI ++ help ++ If you don't know what to do here, say N. ++ + config HT_IRQ + bool "Interrupts on hypertransport devices" + default y +--- a/drivers/pci/quirks.c ++++ b/drivers/pci/quirks.c +@@ -24,6 +24,7 @@ + #include + #include "pci.h" + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + /* The Mellanox Tavor device gives false positive parity errors + * Mark this device with a broken_parity_status, to allow + * PCI scanning code to "skip" this now blacklisted device. +@@ -1554,6 +1555,7 @@ + } + } + DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_NCR, PCI_DEVICE_ID_NCR_53C810, fixup_rev1_53c810); ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ + + static void pci_do_fixups(struct pci_dev *dev, struct pci_fixup *f, struct pci_fixup *end) + { +@@ -1634,6 +1636,7 @@ + } + EXPORT_SYMBOL(pci_fixup_device); + ++#ifndef CONFIG_PCI_DISABLE_COMMON_QUIRKS + /* Enable 1k I/O space granularity on the Intel P64H2 */ + static void __devinit quirk_p64h2_1k_io(struct pci_dev *dev) + { +@@ -2007,3 +2010,4 @@ + quirk_msi_intx_disable_bug); + + #endif /* CONFIG_PCI_MSI */ ++#endif /* !CONFIG_PCI_DISABLE_COMMON_QUIRKS */ diff --git a/target/linux/adm5120/patches-2.6.27/203-gpio_leds_brightness.patch b/target/linux/adm5120/patches-2.6.27/203-gpio_leds_brightness.patch new file mode 100644 index 0000000000..5a3c11aabe --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/203-gpio_leds_brightness.patch @@ -0,0 +1,27 @@ +--- a/drivers/leds/leds-gpio.c ++++ b/drivers/leds/leds-gpio.c +@@ -43,13 +43,17 @@ + container_of(led_cdev, struct gpio_led_data, cdev); + int level; + +- if (value == LED_OFF) +- level = 0; +- else +- level = 1; +- +- if (led_dat->active_low) +- level = !level; ++ switch (value) { ++ case LED_OFF: ++ level = led_dat->active_low ? 1 : 0; ++ break; ++ case LED_FULL: ++ level = led_dat->active_low ? 0 : 1; ++ break; ++ default: ++ level = value; ++ break; ++ } + + /* Setting GPIOs with I2C/etc requires a task context, and we don't + * seem to have a reliable way to know if we're already in one; so diff --git a/target/linux/adm5120/patches-2.6.27/310-adm5120_wdt.patch b/target/linux/adm5120/patches-2.6.27/310-adm5120_wdt.patch new file mode 100644 index 0000000000..8c93912e0a --- /dev/null +++ b/target/linux/adm5120/patches-2.6.27/310-adm5120_wdt.patch @@ -0,0 +1,31 @@ +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -653,6 +653,18 @@ + To compile this driver as a module, choose M here: the + module will be called rc32434_wdt. + ++config ADM5120_WDT ++ tristate "Infineon ADM5120 SoC hardware watchdog" ++ depends on WATCHDOG && ADM5120 ++ help ++ This is a driver for hardware watchdog integrated in Infineon ++ ADM5120 SoC. This watchdog simply watches your kernel to make sure ++ it doesn't freeze, and if it does, it reboots your computer after a ++ certain amount of time. ++ ++ To compile this driver as a module, choose M here: the module will be ++ called adm5120_wdt. ++ + config INDYDOG + tristate "Indy/I2 Hardware Watchdog" + depends on SGI_HAS_INDYDOG +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -102,6 +102,7 @@ + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o + obj-$(CONFIG_TXX9_WDT) += txx9wdt.o ++obj-$(CONFIG_ADM5120_WDT) += adm5120_wdt.o + + # PARISC Architecture + diff --git a/target/linux/adm5120/router_be/config-2.6.27 b/target/linux/adm5120/router_be/config-2.6.27 new file mode 100644 index 0000000000..9bb052e072 --- /dev/null +++ b/target/linux/adm5120/router_be/config-2.6.27 @@ -0,0 +1,283 @@ +CONFIG_32BIT=y +# CONFIG_64BIT is not set +CONFIG_ADM5120=y +CONFIG_ADM5120_ENET=y +CONFIG_ADM5120_MACH_P_334WT=y +CONFIG_ADM5120_MACH_P_335=y +# CONFIG_ADM5120_OEM_CELLVISION is not set +# CONFIG_ADM5120_OEM_COMPEX is not set +# CONFIG_ADM5120_OEM_EDIMAX is not set +# CONFIG_ADM5120_OEM_INFINEON is not set +# CONFIG_ADM5120_OEM_MIKROTIK is not set +# CONFIG_ADM5120_OEM_MOTOROLA is not set +CONFIG_ADM5120_OEM_ZYXEL=y +CONFIG_ADM5120_SOC_BGA=y +CONFIG_ADM5120_WDT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_AMBA=y +CONFIG_BASE_SMALL=0 +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +# CONFIG_BCM47XX is not set +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +CONFIG_CEVT_R4K=y +CONFIG_CIFS_DEBUG2=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CLASSIC_RCU=y +CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,jffs2 init=/etc/preinit" +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +# CONFIG_CPU_LITTLE_ENDIAN is not set +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +CONFIG_CPU_MIPSR1=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_VR41XX is not set +CONFIG_CSRC_R4K=y +CONFIG_DEVPORT=y +# CONFIG_DM9000 is not set +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_EARLY_PRINTK=y +CONFIG_ELF_CORE=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_FS_MBCACHE=m +CONFIG_FS_POSIX_ACL=y +CONFIG_GENERIC_ACL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_GPIOLIB=y +# CONFIG_GPIO_BT8XX is not set +CONFIG_GPIO_SYSFS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_CLK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +# CONFIG_HAVE_IOREMAP_PROT is not set +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HID=m +CONFIG_HID_SUPPORT=y +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_I2C is not set +# CONFIG_IDE is not set +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=m +# CONFIG_INPUT_EVDEV is not set +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IRQ_CPU=y +# CONFIG_ISDN is not set +# CONFIG_JOLIET is not set +CONFIG_KMOD=y +# CONFIG_LEDS_ALIX is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_TRIGGER_ADM5120_SWITCH=m +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_TMIO is not set +CONFIG_MII=m +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_MINIX_FS is not set +CONFIG_MIPS=y +# CONFIG_MIPS_COBALT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_SIM is not set +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +CONFIG_MTD_ADM5120=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_BLOCK2MTD=y +CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_GEN_PROBE=y +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_MYLOADER_PARTS is not set +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_TRXSPLIT=y +# CONFIG_NET_PCI is not set +# CONFIG_NET_PKTGEN is not set +CONFIG_NF_CT_ACCT=y +# CONFIG_NO_IOPORT is not set +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_SIZE_16KB is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCSPKR_PLATFORM is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PROBE_INITRD_HEADER is not set +CONFIG_RFKILL_LEDS=y +CONFIG_RTC_LIB=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +CONFIG_SERIAL_AMBA_PL010_NUMPORTS=2 +CONFIG_SERIAL_AMBA_PL010_PORTNAME="ttyS" +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIO=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SND_MIPS=y +CONFIG_SND_USB=y +CONFIG_SOFT_WATCHDOG=m +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SSB_POSSIBLE=y +CONFIG_SWAP_IO_SPACE=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_TICK_ONESHOT=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TRAD_SIGNALS=y +CONFIG_USB=m +CONFIG_USB_ADM5120_HCD=m +CONFIG_USB_DEBUG=y +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_SUPPORT=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_MEDIA=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +# CONFIG_VLAN_8021Q_GVRP is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/adm5120/router_le/config-2.6.27 b/target/linux/adm5120/router_le/config-2.6.27 new file mode 100644 index 0000000000..71f47707b7 --- /dev/null +++ b/target/linux/adm5120/router_le/config-2.6.27 @@ -0,0 +1,331 @@ +CONFIG_32BIT=y +# CONFIG_64BIT is not set +# CONFIG_8139TOO is not set +CONFIG_ADM5120=y +CONFIG_ADM5120_ENET=y +CONFIG_ADM5120_MACH_BR_6104K=y +CONFIG_ADM5120_MACH_BR_6104KP=y +CONFIG_ADM5120_MACH_BR_61X4WG=y +CONFIG_ADM5120_MACH_CAS_771=y +CONFIG_ADM5120_MACH_EASY5120P_ATA=y +CONFIG_ADM5120_MACH_EASY5120_RT=y +CONFIG_ADM5120_MACH_EASY5120_WVOIP=y +CONFIG_ADM5120_MACH_EASY83000=y +CONFIG_ADM5120_MACH_NFS_101=y +CONFIG_ADM5120_MACH_NP27G=y +CONFIG_ADM5120_MACH_NP28G=y +CONFIG_ADM5120_MACH_PMUGW=y +CONFIG_ADM5120_MACH_RB_11X=y +CONFIG_ADM5120_MACH_RB_133=y +CONFIG_ADM5120_MACH_RB_133C=y +CONFIG_ADM5120_MACH_RB_150=y +CONFIG_ADM5120_MACH_RB_153=y +CONFIG_ADM5120_MACH_RB_192=y +CONFIG_ADM5120_MACH_WP54=y +CONFIG_ADM5120_OEM_CELLVISION=y +CONFIG_ADM5120_OEM_COMPEX=y +CONFIG_ADM5120_OEM_EDIMAX=y +CONFIG_ADM5120_OEM_INFINEON=y +CONFIG_ADM5120_OEM_MIKROTIK=y +CONFIG_ADM5120_OEM_MOTOROLA=y +# CONFIG_ADM5120_OEM_ZYXEL is not set +CONFIG_ADM5120_SOC_BGA=y +CONFIG_ADM5120_WDT=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +CONFIG_ARCH_REQUIRE_GPIOLIB=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +CONFIG_ARM_AMBA=y +CONFIG_ATA=m +# CONFIG_ATA_NONSTANDARD is not set +# CONFIG_ATA_PIIX is not set +CONFIG_ATA_SFF=y +CONFIG_BASE_SMALL=0 +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +# CONFIG_BCM47XX is not set +CONFIG_BINFMT_MISC=m +CONFIG_BITREVERSE=y +CONFIG_CEVT_R4K=y +CONFIG_CIFS_DEBUG2=y +CONFIG_CIFS_EXPERIMENTAL=y +CONFIG_CIFS_STATS2=y +CONFIG_CIFS_WEAK_PW_HASH=y +CONFIG_CIFS_XATTR=y +CONFIG_CLASSIC_RCU=y +CONFIG_CMDLINE="console=ttyS0,115200 rootfstype=squashfs,yaffs2,jffs2 init=/etc/preinit" +# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_HAS_LLSC=y +CONFIG_CPU_HAS_PREFETCH=y +CONFIG_CPU_HAS_SYNC=y +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_CPU_LOONGSON2 is not set +CONFIG_CPU_MIPS32=y +CONFIG_CPU_MIPS32_R1=y +# CONFIG_CPU_MIPS32_R2 is not set +# CONFIG_CPU_MIPS64_R1 is not set +# CONFIG_CPU_MIPS64_R2 is not set +CONFIG_CPU_MIPSR1=y +# CONFIG_CPU_NEVADA is not set +# CONFIG_CPU_R10000 is not set +# CONFIG_CPU_R3000 is not set +# CONFIG_CPU_R4300 is not set +# CONFIG_CPU_R4X00 is not set +# CONFIG_CPU_R5000 is not set +# CONFIG_CPU_R5432 is not set +# CONFIG_CPU_R6000 is not set +# CONFIG_CPU_R8000 is not set +# CONFIG_CPU_RM7000 is not set +# CONFIG_CPU_RM9000 is not set +# CONFIG_CPU_SB1 is not set +CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y +CONFIG_CPU_SUPPORTS_HIGHMEM=y +# CONFIG_CPU_TX39XX is not set +# CONFIG_CPU_TX49XX is not set +# CONFIG_CPU_VR41XX is not set +CONFIG_CSRC_R4K=y +CONFIG_DEVPORT=y +# CONFIG_DM9000 is not set +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_DMA_NONCOHERENT=y +CONFIG_EARLY_PRINTK=y +CONFIG_ELF_CORE=y +# CONFIG_EXT3_FS_POSIX_ACL is not set +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXTRA_FIRMWARE="" +CONFIG_FIRMWARE_IN_KERNEL=y +CONFIG_FS_MBCACHE=m +CONFIG_FS_POSIX_ACL=y +CONFIG_GENERIC_ACL=y +CONFIG_GENERIC_CLOCKEVENTS=y +CONFIG_GENERIC_CLOCKEVENTS_BUILD=y +CONFIG_GENERIC_CMOS_UPDATE=y +# CONFIG_GENERIC_FIND_FIRST_BIT is not set +CONFIG_GENERIC_FIND_NEXT_BIT=y +CONFIG_GENERIC_GPIO=y +# CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ is not set +CONFIG_GPIOLIB=y +# CONFIG_GPIO_BT8XX is not set +CONFIG_GPIO_SYSFS=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAVE_ARCH_KGDB=y +# CONFIG_HAVE_ARCH_TRACEHOOK is not set +# CONFIG_HAVE_CLK is not set +# CONFIG_HAVE_DMA_ATTRS is not set +# CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS is not set +# CONFIG_HAVE_GENERIC_DMA_COHERENT is not set +CONFIG_HAVE_IDE=y +# CONFIG_HAVE_IOREMAP_PROT is not set +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HID=m +CONFIG_HID_SUPPORT=y +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +CONFIG_HZ=250 +# CONFIG_HZ_100 is not set +CONFIG_HZ_250=y +# CONFIG_I2C is not set +# CONFIG_IDE is not set +CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION=m +CONFIG_INITRAMFS_SOURCE="" +CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y +CONFIG_INPUT=m +# CONFIG_INPUT_EVDEV is not set +CONFIG_IPV6_MIP6=m +CONFIG_IPV6_PRIVACY=y +CONFIG_IPV6_TUNNEL=m +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IRQ_CPU=y +# CONFIG_ISDN is not set +# CONFIG_JOLIET is not set +CONFIG_KEXEC=y +CONFIG_KMOD=y +# CONFIG_LEDS_ALIX is not set +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_TRIGGER_ADM5120_SWITCH=m +CONFIG_LEGACY_PTYS=y +CONFIG_LEGACY_PTY_COUNT=256 +# CONFIG_LEMOTE_FULONG is not set +# CONFIG_MACH_ALCHEMY is not set +# CONFIG_MACH_DECSTATION is not set +# CONFIG_MACH_JAZZ is not set +# CONFIG_MACH_TX39XX is not set +# CONFIG_MACH_TX49XX is not set +# CONFIG_MACH_VR41XX is not set +# CONFIG_MFD_CORE is not set +# CONFIG_MFD_TMIO is not set +CONFIG_MII=m +# CONFIG_MIKROTIK_RB532 is not set +# CONFIG_MINIX_FS is not set +CONFIG_MIPS=y +# CONFIG_MIPS_COBALT is not set +CONFIG_MIPS_L1_CACHE_SHIFT=5 +# CONFIG_MIPS_MALTA is not set +CONFIG_MIPS_MT_DISABLED=y +# CONFIG_MIPS_MT_SMP is not set +# CONFIG_MIPS_MT_SMTC is not set +# CONFIG_MIPS_SIM is not set +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_MTD=y +# CONFIG_MTD_ABSENT is not set +CONFIG_MTD_ADM5120=y +# CONFIG_MTD_ALAUDA is not set +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_MTD_BLOCK2MTD is not set +CONFIG_MTD_CFI=y +# CONFIG_MTD_CFI_ADV_OPTIONS is not set +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_FIXUP_MACRONIX_BOOTLOC=y +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_CFI_INTELEXT is not set +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_JEDECPROBE=y +CONFIG_MTD_MAP_BANK_WIDTH_1=y +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +CONFIG_MTD_MAP_BANK_WIDTH_2=y +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MTDRAM is not set +CONFIG_MTD_MYLOADER_PARTS=y +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_CAFE is not set +# CONFIG_MTD_NAND_DISKONCHIP is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_NANDSIM is not set +CONFIG_MTD_NAND_PLATFORM=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_ONENAND is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_PHYSMAP is not set +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +CONFIG_MTD_TRXSPLIT=y +# CONFIG_NATSEMI is not set +# CONFIG_NETFILTER_XT_TARGET_TARPIT is not set +# CONFIG_NET_PKTGEN is not set +CONFIG_NF_CT_ACCT=y +# CONFIG_NO_IOPORT is not set +CONFIG_PAGEFLAGS_EXTENDED=y +# CONFIG_PAGE_SIZE_16KB is not set +CONFIG_PAGE_SIZE_4KB=y +# CONFIG_PAGE_SIZE_64KB is not set +# CONFIG_PAGE_SIZE_8KB is not set +# CONFIG_PARTITION_ADVANCED is not set +# CONFIG_PATA_PLATFORM is not set +CONFIG_PATA_RB153_CF=m +# CONFIG_PATA_SCH is not set +CONFIG_PCI=y +CONFIG_PCI_DISABLE_COMMON_QUIRKS=y +CONFIG_PCI_DOMAINS=y +# CONFIG_PCSPKR_PLATFORM is not set +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_PROBE_INITRD_HEADER is not set +# CONFIG_R6040 is not set +CONFIG_RFKILL_LEDS=y +CONFIG_RTC_LIB=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y +CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y +CONFIG_SCSI_WAIT_SCAN=m +# CONFIG_SERIAL_8250 is not set +CONFIG_SERIAL_AMBA_PL010=y +CONFIG_SERIAL_AMBA_PL010_CONSOLE=y +CONFIG_SERIAL_AMBA_PL010_NUMPORTS=2 +CONFIG_SERIAL_AMBA_PL010_PORTNAME="ttyS" +# CONFIG_SERIAL_AMBA_PL011 is not set +CONFIG_SERIO=y +# CONFIG_SERIO_AMBAKMI is not set +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_LIBPS2 is not set +# CONFIG_SERIO_PCIPS2 is not set +# CONFIG_SERIO_RAW is not set +CONFIG_SERIO_SERPORT=y +# CONFIG_SGI_IP22 is not set +# CONFIG_SGI_IP27 is not set +# CONFIG_SGI_IP28 is not set +# CONFIG_SGI_IP32 is not set +# CONFIG_SIBYTE_BIGSUR is not set +# CONFIG_SIBYTE_CARMEL is not set +# CONFIG_SIBYTE_CRHINE is not set +# CONFIG_SIBYTE_CRHONE is not set +# CONFIG_SIBYTE_LITTLESUR is not set +# CONFIG_SIBYTE_RHONE is not set +# CONFIG_SIBYTE_SENTOSA is not set +# CONFIG_SIBYTE_SWARM is not set +# CONFIG_SLAB is not set +CONFIG_SLUB=y +CONFIG_SND_MIPS=y +CONFIG_SND_USB=y +CONFIG_SOFT_WATCHDOG=m +# CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set +CONFIG_SSB_POSSIBLE=y +CONFIG_SYSVIPC_SYSCTL=y +CONFIG_SYS_HAS_CPU_MIPS32_R1=y +CONFIG_SYS_HAS_EARLY_PRINTK=y +CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y +CONFIG_SYS_SUPPORTS_ARBIT_HZ=y +CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y +CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y +# CONFIG_TC35815 is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +CONFIG_TICK_ONESHOT=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_TRAD_SIGNALS=y +CONFIG_USB=m +CONFIG_USB_ADM5120_HCD=m +CONFIG_USB_EHCI_HCD=m +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set +CONFIG_USB_OHCI_HCD=m +CONFIG_USB_SUPPORT=y +# CONFIG_USB_UHCI_HCD is not set +# CONFIG_VGASTATE is not set +# CONFIG_VIA_RHINE is not set +CONFIG_VIDEO_MEDIA=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +# CONFIG_VLAN_8021Q_GVRP is not set +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_YAFFS_9BYTE_TAGS=y +# CONFIG_YAFFS_ALWAYS_CHECK_CHUNK_ERASED is not set +CONFIG_YAFFS_AUTO_YAFFS2=y +CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS=0 +# CONFIG_YAFFS_DISABLE_LAZY_LOAD is not set +# CONFIG_YAFFS_DISABLE_WIDE_TNODES is not set +CONFIG_YAFFS_FS=y +CONFIG_YAFFS_SHORT_NAMES_IN_RAM=y +CONFIG_YAFFS_YAFFS1=y +CONFIG_YAFFS_YAFFS2=y +CONFIG_ZONE_DMA_FLAG=0