From 2e6ab844ee985e740d32a9f440e2c186f0f1b57c Mon Sep 17 00:00:00 2001 From: John Crispin Date: Tue, 30 Sep 2008 08:12:06 +0000 Subject: [PATCH] adds ifxmips, uboot-ifxmips and removes etrax from 8.09 branch SVN-Revision: 12811 --- package/uboot-ifxmips/Makefile | 47 + .../uboot-ifxmips/files/board/danube/Makefile | 41 + .../uboot-ifxmips/files/board/danube/README | 55 + .../files/board/danube/config.mk | 33 + .../uboot-ifxmips/files/board/danube/danube.c | 208 + .../files/board/danube/ddr_settings.h | 50 + .../files/board/danube/ddr_settings_111.h | 50 + .../files/board/danube/ddr_settings_166.h | 50 + .../board/danube/ddr_settings_PROMOSDDR400.h | 50 + .../board/danube/ddr_settings_Samsung_166.h | 51 + .../files/board/danube/ddr_settings_e111.h | 50 + .../files/board/danube/ddr_settings_e166.h | 50 + .../files/board/danube/ddr_settings_psc_166.h | 51 + .../files/board/danube/ddr_settings_r111.h | 50 + .../files/board/danube/ddr_settings_r166.h | 50 + .../uboot-ifxmips/files/board/danube/flash.c | 892 +++ .../files/board/danube/lowlevel_init.S | 582 ++ .../files/board/danube/pmuenable.S | 48 + .../files/board/danube/u-boot-bootstrap.lds | 69 + .../files/board/danube/u-boot.lds | 69 + .../uboot-ifxmips/files/common/flash_danube.c | 228 + .../files/cpu/mips/danube/Makefile | 49 + .../files/cpu/mips/danube/asc_serial.c | 371 ++ .../files/cpu/mips/danube/asc_serial.h | 177 + .../files/cpu/mips/danube/au1x00_eth.c | 311 + .../files/cpu/mips/danube/au1x00_serial.c | 135 + .../files/cpu/mips/danube/au1x00_usb_ohci.c | 1727 ++++++ .../files/cpu/mips/danube/au1x00_usb_ohci.h | 416 ++ .../files/cpu/mips/danube/cache.S | 278 + .../files/cpu/mips/danube/config.mk | 53 + .../uboot-ifxmips/files/cpu/mips/danube/cpu.c | 61 + .../files/cpu/mips/danube/ifx_asc.c | 257 + .../files/cpu/mips/danube/ifx_cache.S | 60 + .../files/cpu/mips/danube/ifx_cgu.c | 1086 ++++ .../files/cpu/mips/danube/ifx_cgu.h | 91 + .../files/cpu/mips/danube/ifx_clock.c | 91 + .../files/cpu/mips/danube/ifx_cpu.c | 5 + .../files/cpu/mips/danube/ifx_start.S | 51 + .../files/cpu/mips/danube/incaip_clock.c | 120 + .../files/cpu/mips/danube/incaip_wdt.S | 75 + .../files/cpu/mips/danube/interrupts.c | 33 + .../files/cpu/mips/danube/start.S | 442 ++ .../files/cpu/mips/danube/start_bootstrap.S | 428 ++ package/uboot-ifxmips/files/drivers/ifx_sw.c | 423 ++ .../uboot-ifxmips/files/include/LzmaWrapper.h | 36 + .../files/include/asm-mips/danube.h | 2033 +++++++ .../files/include/asm-mips/errno.h | 138 + .../files/include/asm-mips/ifx_asc.h | 220 + .../files/include/asm-mips/inca-ip2.h | 634 ++ .../files/include/asm-mips/pinstrap.h | 12 + .../files/include/asm-mips/romconfig.h | 66 + package/uboot-ifxmips/files/include/boot.h | 86 + .../files/include/configs/danube.h | 262 + .../files/include/configs/ifx_cfg.h | 249 + .../files/include/configs/ifx_extra_env.h | 94 + .../files/lib_bootstrap/LzmaDecode.c | 622 ++ .../files/lib_bootstrap/LzmaDecode.h | 113 + .../files/lib_bootstrap/LzmaTypes.h | 45 + .../files/lib_bootstrap/LzmaWrapper.c | 223 + .../files/lib_bootstrap/Makefile | 52 + .../lib_bootstrap/bootstrap_board_danube.c | 501 ++ .../files/lib_bootstrap/console.c | 573 ++ .../uboot-ifxmips/files/lib_bootstrap/crc32.c | 197 + .../uboot-ifxmips/files/lib_bootstrap/ctype.c | 56 + .../files/lib_bootstrap/devices.c | 216 + .../files/lib_bootstrap/display_options.c | 67 + .../uboot-ifxmips/files/lib_bootstrap/lists.c | 734 +++ .../files/lib_bootstrap/string.c | 578 ++ .../uboot-ifxmips/files/lib_bootstrap/time.c | 99 + .../files/lib_bootstrap/vsprintf.c | 385 ++ .../files/lib_generic/LzmaDecode.c | 600 ++ .../files/lib_generic/LzmaDecode.h | 113 + .../files/lib_generic/LzmaTypes.h | 45 + .../files/lib_generic/LzmaWrapper.c | 197 + package/uboot-ifxmips/files/net/ifx_eth.c | 4 + package/uboot-ifxmips/files/net/net_danube.c | 1754 ++++++ package/uboot-ifxmips/files/net/nfs_danube.c | 778 +++ package/uboot-ifxmips/files/net/tftp_danube.c | 389 ++ .../uboot-ifxmips/files/tools/crc32_danube.c | 198 + .../files/tools/environment_danube.c | 213 + package/uboot-ifxmips/patches/100-ifx.patch | 1773 ++++++ target/linux/etrax/config-default | 257 - .../etrax/files/drivers/usb/host/hc_crisv10.c | 4550 -------------- .../etrax/files/drivers/usb/host/hc_crisv10.h | 289 - target/linux/etrax/image/Config.in | 5 - target/linux/etrax/image/Makefile | 43 - target/linux/etrax/image/boot_linux | 512 -- target/linux/etrax/image/e100boot/Makefile | 34 - target/linux/etrax/image/mkfimage/Makefile | 30 - .../linux/etrax/image/mkfimage/src/Makefile | 4 - .../linux/etrax/image/mkfimage/src/mkfimage.c | 72 - .../etrax/patches/100-compile_fixes.patch | 302 - .../etrax/patches/101-cris-eth-driver.patch | 11 - .../patches/102-missing_arch_include.patch | 11 - .../etrax/patches/200-samsung_flash.patch | 13 - .../linux/etrax/patches/201-flashsize.patch | 88 - target/linux/etrax/patches/300-sysfs.patch | 43 - .../linux/etrax/patches/301-usb_support.patch | 5301 ----------------- target/linux/etrax/profiles/100-generic.mk | 16 - target/linux/etrax/profiles/101-vhdl-nofb.mk | 17 - target/linux/{etrax => ifxmips}/Makefile | 17 +- .../base-files/etc/hotplug.d/button/00-reset | 3 + target/linux/ifxmips/base-files/etc/inittab | 4 + target/linux/ifxmips/config-2.6.26 | 236 + .../ifxmips/files/arch/mips/ifxmips/Kconfig | 40 + .../ifxmips/files/arch/mips/ifxmips/Makefile | 1 + .../ifxmips/files/arch/mips/ifxmips/board.c | 381 ++ .../ifxmips/files/arch/mips/ifxmips/clock.c | 243 + .../files/arch/mips/ifxmips/dma-core.c | 758 +++ .../ifxmips/files/arch/mips/ifxmips/gpio.c | 385 ++ .../files/arch/mips/ifxmips/interrupt.c | 203 + .../ifxmips/files/arch/mips/ifxmips/pmu.c | 42 + .../ifxmips/files/arch/mips/ifxmips/prom.c | 145 + .../ifxmips/files/arch/mips/ifxmips/reset.c | 58 + .../ifxmips/files/arch/mips/ifxmips/setup.c | 90 + .../ifxmips/files/arch/mips/ifxmips/timer.c | 844 +++ .../ifxmips/files/arch/mips/pci/ops-ifxmips.c | 120 + .../ifxmips/files/arch/mips/pci/pci-ifxmips.c | 193 + .../files/drivers/char/ifxmips_eeprom.c | 541 ++ .../files/drivers/char/ifxmips_mei_core.c | 3658 ++++++++++++ .../ifxmips/files/drivers/char/ifxmips_ssc.c | 1417 +++++ .../ifxmips/files/drivers/leds/leds-ifxmips.c | 192 + .../ifxmips/files/drivers/mtd/maps/ifxmips.c | 238 + .../ifxmips/files/drivers/net/ifxmips_mii0.c | 416 ++ .../files/drivers/serial/ifxmips_asc.c | 599 ++ .../files/drivers/watchdog/ifxmips_wdt.c | 204 + .../ifxmips/ifx_peripheral_definitions.h | 119 + .../files/include/asm-mips/ifxmips/ifx_ssc.h | 258 + .../asm-mips/ifxmips/ifx_ssc_defines.h | 547 ++ .../files/include/asm-mips/ifxmips/ifxmips.h | 515 ++ .../include/asm-mips/ifxmips/ifxmips_cgu.h | 29 + .../include/asm-mips/ifxmips/ifxmips_dma.h | 202 + .../include/asm-mips/ifxmips/ifxmips_ebu.h | 23 + .../include/asm-mips/ifxmips/ifxmips_gpio.h | 40 + .../include/asm-mips/ifxmips/ifxmips_gptu.h | 161 + .../include/asm-mips/ifxmips/ifxmips_irq.h | 72 + .../include/asm-mips/ifxmips/ifxmips_led.h | 26 + .../include/asm-mips/ifxmips/ifxmips_mei.h | 270 + .../asm-mips/ifxmips/ifxmips_mei_app.h | 116 + .../asm-mips/ifxmips/ifxmips_mei_app_ioctl.h | 1191 ++++ .../asm-mips/ifxmips/ifxmips_mei_bsp.h | 308 + .../asm-mips/ifxmips/ifxmips_mei_ioctl.h | 734 +++ .../asm-mips/ifxmips/ifxmips_mei_linux.h | 112 + .../include/asm-mips/ifxmips/ifxmips_pmu.h | 30 + .../include/asm-mips/ifxmips/ifxmips_prom.h | 26 + .../include/asm-mips/mach-ifxmips/gpio.h | 94 + .../files/include/asm-mips/mach-ifxmips/irq.h | 29 + .../files/include/asm-mips/mach-ifxmips/war.h | 24 + target/linux/ifxmips/image/Makefile | 34 + target/linux/ifxmips/patches/100-board.patch | 80 + .../linux/ifxmips/patches/110-drivers.patch | 149 + .../linux/ifxmips/patches/160-cfi-swap.patch | 13 + .../linux/ifxmips/patches/170-dma_hack.patch | 11 + target/linux/ifxmips/profiles/100-Atheros.mk | 17 + target/linux/ifxmips/profiles/200-Ralink.mk | 17 + target/linux/ifxmips/series | 88 + target/linux/ifxmips/wget-log | 25 + 157 files changed, 40248 insertions(+), 11607 deletions(-) create mode 100644 package/uboot-ifxmips/Makefile create mode 100644 package/uboot-ifxmips/files/board/danube/Makefile create mode 100644 package/uboot-ifxmips/files/board/danube/README create mode 100644 package/uboot-ifxmips/files/board/danube/config.mk create mode 100644 package/uboot-ifxmips/files/board/danube/danube.c create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_111.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_166.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_PROMOSDDR400.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_Samsung_166.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_e111.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_e166.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_psc_166.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_r111.h create mode 100644 package/uboot-ifxmips/files/board/danube/ddr_settings_r166.h create mode 100644 package/uboot-ifxmips/files/board/danube/flash.c create mode 100644 package/uboot-ifxmips/files/board/danube/lowlevel_init.S create mode 100644 package/uboot-ifxmips/files/board/danube/pmuenable.S create mode 100644 package/uboot-ifxmips/files/board/danube/u-boot-bootstrap.lds create mode 100644 package/uboot-ifxmips/files/board/danube/u-boot.lds create mode 100644 package/uboot-ifxmips/files/common/flash_danube.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/Makefile create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/cache.S create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/config.mk create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/cpu.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/start.S create mode 100644 package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S create mode 100644 package/uboot-ifxmips/files/drivers/ifx_sw.c create mode 100644 package/uboot-ifxmips/files/include/LzmaWrapper.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/danube.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/errno.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/ifx_asc.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/inca-ip2.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/pinstrap.h create mode 100644 package/uboot-ifxmips/files/include/asm-mips/romconfig.h create mode 100644 package/uboot-ifxmips/files/include/boot.h create mode 100644 package/uboot-ifxmips/files/include/configs/danube.h create mode 100644 package/uboot-ifxmips/files/include/configs/ifx_cfg.h create mode 100644 package/uboot-ifxmips/files/include/configs/ifx_extra_env.h create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.h create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/LzmaTypes.h create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/LzmaWrapper.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/Makefile create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/bootstrap_board_danube.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/console.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/crc32.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/ctype.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/devices.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/display_options.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/lists.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/string.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/time.c create mode 100644 package/uboot-ifxmips/files/lib_bootstrap/vsprintf.c create mode 100644 package/uboot-ifxmips/files/lib_generic/LzmaDecode.c create mode 100644 package/uboot-ifxmips/files/lib_generic/LzmaDecode.h create mode 100644 package/uboot-ifxmips/files/lib_generic/LzmaTypes.h create mode 100644 package/uboot-ifxmips/files/lib_generic/LzmaWrapper.c create mode 100644 package/uboot-ifxmips/files/net/ifx_eth.c create mode 100644 package/uboot-ifxmips/files/net/net_danube.c create mode 100644 package/uboot-ifxmips/files/net/nfs_danube.c create mode 100644 package/uboot-ifxmips/files/net/tftp_danube.c create mode 100644 package/uboot-ifxmips/files/tools/crc32_danube.c create mode 100644 package/uboot-ifxmips/files/tools/environment_danube.c create mode 100644 package/uboot-ifxmips/patches/100-ifx.patch delete mode 100644 target/linux/etrax/config-default delete mode 100644 target/linux/etrax/files/drivers/usb/host/hc_crisv10.c delete mode 100644 target/linux/etrax/files/drivers/usb/host/hc_crisv10.h delete mode 100644 target/linux/etrax/image/Config.in delete mode 100644 target/linux/etrax/image/Makefile delete mode 100755 target/linux/etrax/image/boot_linux delete mode 100644 target/linux/etrax/image/e100boot/Makefile delete mode 100644 target/linux/etrax/image/mkfimage/Makefile delete mode 100644 target/linux/etrax/image/mkfimage/src/Makefile delete mode 100644 target/linux/etrax/image/mkfimage/src/mkfimage.c delete mode 100644 target/linux/etrax/patches/100-compile_fixes.patch delete mode 100644 target/linux/etrax/patches/101-cris-eth-driver.patch delete mode 100644 target/linux/etrax/patches/102-missing_arch_include.patch delete mode 100644 target/linux/etrax/patches/200-samsung_flash.patch delete mode 100644 target/linux/etrax/patches/201-flashsize.patch delete mode 100644 target/linux/etrax/patches/300-sysfs.patch delete mode 100644 target/linux/etrax/patches/301-usb_support.patch delete mode 100644 target/linux/etrax/profiles/100-generic.mk delete mode 100644 target/linux/etrax/profiles/101-vhdl-nofb.mk rename target/linux/{etrax => ifxmips}/Makefile (51%) create mode 100644 target/linux/ifxmips/base-files/etc/hotplug.d/button/00-reset create mode 100644 target/linux/ifxmips/base-files/etc/inittab create mode 100644 target/linux/ifxmips/config-2.6.26 create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/Kconfig create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/Makefile create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/board.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/clock.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/dma-core.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/gpio.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/interrupt.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/pmu.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/prom.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/reset.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/setup.c create mode 100644 target/linux/ifxmips/files/arch/mips/ifxmips/timer.c create mode 100644 target/linux/ifxmips/files/arch/mips/pci/ops-ifxmips.c create mode 100644 target/linux/ifxmips/files/arch/mips/pci/pci-ifxmips.c create mode 100644 target/linux/ifxmips/files/drivers/char/ifxmips_eeprom.c create mode 100644 target/linux/ifxmips/files/drivers/char/ifxmips_mei_core.c create mode 100644 target/linux/ifxmips/files/drivers/char/ifxmips_ssc.c create mode 100644 target/linux/ifxmips/files/drivers/leds/leds-ifxmips.c create mode 100644 target/linux/ifxmips/files/drivers/mtd/maps/ifxmips.c create mode 100644 target/linux/ifxmips/files/drivers/net/ifxmips_mii0.c create mode 100644 target/linux/ifxmips/files/drivers/serial/ifxmips_asc.c create mode 100644 target/linux/ifxmips/files/drivers/watchdog/ifxmips_wdt.c create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_peripheral_definitions.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc_defines.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_cgu.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_dma.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_ebu.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gpio.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gptu.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_irq.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_led.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app_ioctl.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_bsp.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_ioctl.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_linux.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_pmu.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_prom.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/gpio.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/irq.h create mode 100644 target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/war.h create mode 100644 target/linux/ifxmips/image/Makefile create mode 100644 target/linux/ifxmips/patches/100-board.patch create mode 100644 target/linux/ifxmips/patches/110-drivers.patch create mode 100644 target/linux/ifxmips/patches/160-cfi-swap.patch create mode 100644 target/linux/ifxmips/patches/170-dma_hack.patch create mode 100644 target/linux/ifxmips/profiles/100-Atheros.mk create mode 100644 target/linux/ifxmips/profiles/200-Ralink.mk create mode 100644 target/linux/ifxmips/series create mode 100644 target/linux/ifxmips/wget-log diff --git a/package/uboot-ifxmips/Makefile b/package/uboot-ifxmips/Makefile new file mode 100644 index 0000000000..7895502b3b --- /dev/null +++ b/package/uboot-ifxmips/Makefile @@ -0,0 +1,47 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/kernel.mk + +PKG_NAME:=u-boot +PKG_VERSION:=1.1.5 +PKG_RELEASE:=1 + +PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) +PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.bz2 +PKG_SOURCE_URL:=ftp://ftp.denx.de/pub/u-boot +PKG_MD5SUM:=579707c8ecbf1ab4127285d2aac2a9ee +PKG_CAT:=bzcat +PKG_TARGETS:=bin + +include $(INCLUDE_DIR)/package.mk + +define Package/uboot-ifxmips + SECTION:=boot + CATEGORY:=Boot Loaders + DEPENDS:=@TARGET_ifxmips + TITLE:=U-Boot for Infineon MIPS boards + URL:=http://www.denx.de/wiki/UBoot/WebHome +endef + +define Build/Prepare + $(call Build/Prepare/Default) + cp -r ./files/* $(PKG_BUILD_DIR) + find $(PKG_BUILD_DIR) -name .svn | $(XARGS) rm -rf +endef + +define Build/Compile + cd $(PKG_BUILD_DIR);chmod a+x build_danube.sh;./build_danube.sh +endef + +define Package/uboot-ifxmips/install + mkdir -p $(1) + dd if=$(PKG_BUILD_DIR)/u-boot.ifx of=$(1)/u-boot.ifx bs=64k conv=sync +endef + +$(eval $(call BuildPackage,uboot-ifxmips)) diff --git a/package/uboot-ifxmips/files/board/danube/Makefile b/package/uboot-ifxmips/files/board/danube/Makefile new file mode 100644 index 0000000000..0163fd96f8 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/Makefile @@ -0,0 +1,41 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = lib$(BOARD).a + +OBJS = $(BOARD).o flash.o +SOBJS = lowlevel_init.o pmuenable.o + +$(LIB): .depend $(OBJS) $(SOBJS) + $(AR) crv $@ $^ + +######################################################################### + +.depend: Makefile $(SOBJS:.o=.S) $(OBJS:.o=.c) + $(CC) -M $(CFLAGS) $(SOBJS:.o=.S) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/package/uboot-ifxmips/files/board/danube/README b/package/uboot-ifxmips/files/board/danube/README new file mode 100644 index 0000000000..d1c5c1e88c --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/README @@ -0,0 +1,55 @@ +/* +** Copyright (C) 2005 Wu Qi Ming +** +** 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. +*/ + +To build a u-boot for danube board, user need to do the following things: +To configure u-boot for a proper board, user need to modify two files accordingly. + +To configure u-boot for evaluation board, in danube-uboot/include/configs/danube.h, set +#define USE_EVALUATION_BOARD +#undef USE_REFERENCE_BOARD +and vice-versa. + +To let u-boot boot from ebu(flash,e.g), in danube-uboot/include/configus/danube.h, set +#define DANUBE_BOOT_FROM_EBU +Otherwise u-boot will be compiled for booting from RAM. + +To use DDR RAM running at 111M, in danube-uboot/include/configus/danube. +h, set +#define DANUBE_DDR_RAM_111M +#undef DANUBE_DDR_RAM_166M +and vice-versa. + +To define RAM size of RAM, in danube-uboot/include/configus/danube. +h, set +#define RAM_SIZE 0x2000000 /*32M ram*/ +This is an example for a 32M RAM. + + +Besides above settings, user need to change danube-uboot/board/danube/config.mk to set the loading address of u-boot. +If U-Boot is to boot from EBU(flash), user needs to set +TEXT_BASE=0xB0000000 +If u-boot is to boot from RAM, user needs to set +TEXT_BASE=0xa0400000 + +Use the script gct to build a uart downloadable u-boot image: +./gct danube_ref_ddr166.conf u-boot.srec u-boot.asc + + + + + diff --git a/package/uboot-ifxmips/files/board/danube/config.mk b/package/uboot-ifxmips/files/board/danube/config.mk new file mode 100644 index 0000000000..e6fcbc6591 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/config.mk @@ -0,0 +1,33 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 +# + +# +# Danube board with MIPS 24Kec CPU core +#boot from ebu +TEXT_BASE = 0xB0000000 +BOOTSTRAP_TEXT_BASE = 0xB0000000 + +#boot from ram +#TEXT_BASE = 0xa0400000 +#TEXT_BASE = 0x807c0000 + diff --git a/package/uboot-ifxmips/files/board/danube/danube.c b/package/uboot-ifxmips/files/board/danube/danube.c new file mode 100644 index 0000000000..b6174ba6d8 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/danube.c @@ -0,0 +1,208 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#ifdef DANUBE_USE_DDR_RAM +long int initdram(int board_type) +{ + return (1024*1024*DANUBE_DDR_RAM_SIZE); +} +#else +extern uint danube_get_cpuclk(void); + +static ulong max_sdram_size(void) /* per Chip Select */ +{ + /* The only supported SDRAM data width is 16bit. + */ +#define CFG_DW 4 + + /* The only supported number of SDRAM banks is 4. + */ +#define CFG_NB 4 + + ulong cfgpb0 = *DANUBE_SDRAM_MC_CFGPB0; + int cols = cfgpb0 & 0xF; + int rows = (cfgpb0 & 0xF0) >> 4; + ulong size = (1 << (rows + cols)) * CFG_DW * CFG_NB; + + return size; +} + +/* + * Check memory range for valid RAM. A simple memory test determines + * the actually available RAM size between addresses `base' and + * `base + maxsize'. + */ + +static long int dram_size(long int *base, long int maxsize) +{ + volatile long int *addr; + ulong cnt, val; + ulong save[32]; /* to make test non-destructive */ + unsigned char i = 0; + + for (cnt = (maxsize / sizeof (long)) >> 1; cnt > 0; cnt >>= 1) { + addr = base + cnt; /* pointer arith! */ + + save[i++] = *addr; + *addr = ~cnt; + } + + /* write 0 to base address */ + addr = base; + save[i] = *addr; + *addr = 0; + + /* check at base address */ + if ((val = *addr) != 0) { + *addr = save[i]; + return (0); + } + + for (cnt = 1; cnt < maxsize / sizeof (long); cnt <<= 1) { + addr = base + cnt; /* pointer arith! */ + + val = *addr; + *addr = save[--i]; + + if (val != (~cnt)) { + return (cnt * sizeof (long)); + } + } + return (maxsize); +} + +long int initdram(int board_type) +{ + int rows, cols, best_val = *DANUBE_SDRAM_MC_CFGPB0; + ulong size, max_size = 0; + ulong our_address; + + /* load t9 into our_address */ + asm volatile ("move %0, $25" : "=r" (our_address) :); + + /* Can't probe for RAM size unless we are running from Flash. + * find out whether running from DRAM or Flash. + */ + if (PHYSADDR(our_address) < PHYSADDR(PHYS_FLASH_1)) + { + return max_sdram_size(); + } + + for (cols = 0x8; cols <= 0xC; cols++) + { + for (rows = 0xB; rows <= 0xD; rows++) + { + *DANUBE_SDRAM_MC_CFGPB0 = (0x14 << 8) | + (rows << 4) | cols; + size = dram_size((ulong *)CFG_SDRAM_BASE, + max_sdram_size()); + + if (size > max_size) + { + best_val = *DANUBE_SDRAM_MC_CFGPB0; + max_size = size; + } + } + } + + *DANUBE_SDRAM_MC_CFGPB0 = best_val; + return max_size; +} +#endif + +int checkboard (void) +{ + /* No such register in Amazon */ +#if 0 + unsigned long chipid = *AMAZON_MCD_CHIPID; + int part_num; + + puts ("Board: AMAZON "); + part_num = AMAZON_MCD_CHIPID_PART_NUMBER_GET(chipid); + switch (part_num) { + case AMAZON_CHIPID_STANDARD: + printf ("Standard Version, "); + break; + case AMAZON_CHIPID_YANGTSE: + printf ("Yangtse Version, "); + break; + default: + printf ("Unknown Part Number 0x%x ", part_num); + break; + } + + printf ("Chip V1.%ld, ", AMAZON_MCD_CHIPID_VERSION_GET(chipid)); + + + printf("CPU Speed %d MHz\n", danube_get_cpuclk()/1000000); + +#endif + return 0; +} + + +/* + * Disk On Chip (NAND) Millenium initialization. + * The NAND lives in the CS2* space + */ +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +extern void +nand_probe(ulong physadr); + +#define AT91_SMARTMEDIA_BASE 0x40000000 /* physical address to access memory on NCS3 */ +void +nand_init(void) +{ + int devtype; + /* Configure EBU */ +//TODO: should we keep this? + //Set GPIO23 to be Flash CS1; + *DANUBE_GPIO_P1_ALTSEL0 = *DANUBE_GPIO_P1_ALTSEL0 | (1<<7); + *DANUBE_GPIO_P1_ALTSEL1 = *DANUBE_GPIO_P1_ALTSEL1 & ~(1<<7); + *DANUBE_GPIO_P1_DIR = *DANUBE_GPIO_P1_DIR | (1<<7) ; + *DANUBE_GPIO_P1_OD = *DANUBE_GPIO_P1_OD | (1<<7) ; + + *EBU_ADDR_SEL_1 = (NAND_BASE_ADDRESS&0x1fffff00)|0x31; + /* byte swap;minimum delay*/ + *EBU_CON_1 = 0x40C155; + *EBU_NAND_CON = 0x000005F3; + + /* Set bus signals to inactive */ + NAND_READY_CLEAR; + + NAND_CE_CLEAR; + nand_probe(NAND_BASE_ADDRESS); + + + + //nand_probe(AT91_SMARTMEDIA_BASE); +} +#endif + + + diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings.h b/package/uboot-ifxmips/files/board/danube/ddr_settings.h new file mode 100644 index 0000000000..cecd279b39 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA03 +#define MC_DC21_VALUE 0x1d00 +#define MC_DC22_VALUE 0x1d1d +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* was 0x7f */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_111.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_111.h new file mode 100644 index 0000000000..b655ca2898 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_111.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_166.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_166.h new file mode 100644 index 0000000000..b655ca2898 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_166.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_PROMOSDDR400.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_PROMOSDDR400.h new file mode 100644 index 0000000000..54bb6c9e37 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_PROMOSDDR400.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xa02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x0 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1200 +#define MC_DC22_VALUE 0x1212 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x62 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x4e20 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_Samsung_166.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_Samsung_166.h new file mode 100644 index 0000000000..7975c3ec0d --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_Samsung_166.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Samsung DDR K4H561638H Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x120 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1400 +#define MC_DC22_VALUE 0x1414 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x4e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d93 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_e111.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_e111.h new file mode 100644 index 0000000000..b655ca2898 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_e111.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_e166.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_e166.h new file mode 100644 index 0000000000..b655ca2898 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_e166.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Eval Board DDR 167 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA03 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1800 +#define MC_DC22_VALUE 0x1818 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_psc_166.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_psc_166.h new file mode 100644 index 0000000000..445b7dac1f --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_psc_166.h @@ -0,0 +1,51 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for PSC DDR A2S56D40CTP for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 27th Nov 2006 */ + +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0x120 /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x301 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1700 +#define MC_DC22_VALUE 0x1717 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x52 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x4e20 +#define MC_DC30_VALUE 0x8235 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_r111.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_r111.h new file mode 100644 index 0000000000..385f7e4e58 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_r111.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0x1200 +#define MC_DC22_VALUE 0x1212 +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x5e /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/ddr_settings_r166.h b/package/uboot-ifxmips/files/board/danube/ddr_settings_r166.h new file mode 100644 index 0000000000..742d34f1d3 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/ddr_settings_r166.h @@ -0,0 +1,50 @@ +/* Settings for Denali DDR SDRAM controller */ +/* Optimise for Danube Ref Board DDR 166 Mhz - by Ng Aik Ann 29th April */ +#define MC_DC0_VALUE 0x1B1B +#define MC_DC1_VALUE 0x0 +#define MC_DC2_VALUE 0x0 +#define MC_DC3_VALUE 0x0 +#define MC_DC4_VALUE 0x0 +#define MC_DC5_VALUE 0x200 +#define MC_DC6_VALUE 0x605 +#define MC_DC7_VALUE 0x303 +#define MC_DC8_VALUE 0x102 +#define MC_DC9_VALUE 0x70a +#define MC_DC10_VALUE 0x203 +#define MC_DC11_VALUE 0xc02 +#define MC_DC12_VALUE 0x1C8 +#define MC_DC13_VALUE 0x1 +#define MC_DC14_VALUE 0x0 +#define MC_DC15_VALUE 0xf3c /* WDQS tuning for clk_wr*/ +#define MC_DC16_VALUE 0xC800 +#define MC_DC17_VALUE 0xd +#define MC_DC18_VALUE 0x300 +#define MC_DC19_VALUE 0x200 +#define MC_DC20_VALUE 0xA04 /* A04 for reference board, A03 for Eval board */ +#define MC_DC21_VALUE 0xd00 +#define MC_DC22_VALUE 0xd0d +#define MC_DC23_VALUE 0x0 +#define MC_DC24_VALUE 0x62 /* WDQS Tuning for DQS */ +#define MC_DC25_VALUE 0x0 +#define MC_DC26_VALUE 0x0 +#define MC_DC27_VALUE 0x0 +#define MC_DC28_VALUE 0x510 +#define MC_DC29_VALUE 0x2d89 +#define MC_DC30_VALUE 0x8300 +#define MC_DC31_VALUE 0x0 +#define MC_DC32_VALUE 0x0 +#define MC_DC33_VALUE 0x0 +#define MC_DC34_VALUE 0x0 +#define MC_DC35_VALUE 0x0 +#define MC_DC36_VALUE 0x0 +#define MC_DC37_VALUE 0x0 +#define MC_DC38_VALUE 0x0 +#define MC_DC39_VALUE 0x0 +#define MC_DC40_VALUE 0x0 +#define MC_DC41_VALUE 0x0 +#define MC_DC42_VALUE 0x0 +#define MC_DC43_VALUE 0x0 +#define MC_DC44_VALUE 0x0 +#define MC_DC45_VALUE 0x500 +//#define MC_DC45_VALUE 0x400 +#define MC_DC46_VALUE 0x0 diff --git a/package/uboot-ifxmips/files/board/danube/flash.c b/package/uboot-ifxmips/files/board/danube/flash.c new file mode 100644 index 0000000000..587c072d18 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/flash.c @@ -0,0 +1,892 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ +//joelin 10/07/2004 for MXIC MX29LV320ABTC-90 +#include +#include + +/* +#ifdef CONFIG_AMAZON + #define FLASH_DELAY {int i; \ + for(i=0;i<800;i++) \ + *((volatile u32 *)CFG_SDRAM_BASE_UNCACHE); \ + } +#else + #define FLASH_DELAY +#endif +*/ + +flash_info_t flash_info[CFG_MAX_FLASH_BANKS]; /* info for FLASH chips */ + +/* NOTE - CONFIG_FLASH_16BIT means the CPU interface is 16-bit, it + * has nothing to do with the flash chip being 8-bit or 16-bit. + */ +#ifdef CONFIG_FLASH_16BIT +typedef unsigned short FLASH_PORT_WIDTH; +typedef volatile unsigned short FLASH_PORT_WIDTHV; +#define FLASH_ID_MASK 0xFFFF +#else +typedef unsigned long FLASH_PORT_WIDTH; +typedef volatile unsigned long FLASH_PORT_WIDTHV; +#define FLASH_ID_MASK 0xFFFFFFFF +#endif + +#define FPW FLASH_PORT_WIDTH +#define FPWV FLASH_PORT_WIDTHV + +#define ORMASK(size) ((-size) & OR_AM_MSK) // 0xffff8000 + +#if 0 +#define FLASH_CYCLE1 0x0555 +#define FLASH_CYCLE2 0x02aa +#else +#define FLASH_CYCLE1 0x0554 //joelin for MX29LV320AT/B 0x0555 +#define FLASH_CYCLE2 0x02ab //joelin for MX29LV320AT/B 0x02aa +#endif + +/*----------------------------------------------------------------------- + * Functions + */ +static ulong flash_get_size(FPWV *addr, flash_info_t *info); +static void flash_reset(flash_info_t *info); +static int write_word_intel(flash_info_t *info, FPWV *dest, FPW data); +static int write_word_amd(flash_info_t *info, FPWV *dest, FPW data); +static void flash_get_offsets(ulong base, flash_info_t *info); +static flash_info_t *flash_get_info(ulong base); + +/*----------------------------------------------------------------------- + * flash_init() + * + * sets up flash_info and returns size of FLASH (bytes) + */ +unsigned long flash_init (void) +{ + unsigned long size = 0; + int i; + + /* Init: no FLASHes known */ + for (i=0; i < CFG_MAX_FLASH_BANKS; ++i) { // 1 bank + ulong flashbase = (i == 0) ? PHYS_FLASH_1 : PHYS_FLASH_2; // 0xb0000000, 0xb4000000 + + volatile ulong * buscon = (ulong *) + ((i == 0) ? DANUBE_EBU_BUSCON0 : DANUBE_EBU_BUSCON1); + + /* Disable write protection */ +// *buscon &= ~AMAZON_EBU_BUSCON0_WRDIS; + /* Enable write protection */ + *buscon |= DANUBE_EBU_BUSCON0_WRDIS; + +#if 1 + memset(&flash_info[i], 0, sizeof(flash_info_t)); +#endif + + flash_info[i].size = + flash_get_size((FPW *)flashbase, &flash_info[i]); + + if (flash_info[i].flash_id == FLASH_UNKNOWN) { + printf ("## Unknown FLASH on Bank %d - Size = 0x%08lx\n", + i, flash_info[i].size); + } + + size += flash_info[i].size; + } + +#if CFG_MONITOR_BASE >= CFG_FLASH_BASE // TEXT_BASE >= 0xB3000000 + /* monitor protection ON by default */ /* only use software protection, info->protect[i]=0/1 */ +/* flash_protect(FLAG_PROTECT_SET, + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + flash_get_info(CFG_MONITOR_BASE)); +*/ + flash_protect(FLAG_PROTECT_CLEAR, // clear protect + CFG_MONITOR_BASE, + CFG_MONITOR_BASE+CFG_MONITOR_LEN-1, + flash_get_info(CFG_MONITOR_BASE)); + +#endif + +#ifdef CFG_ENV_IS_IN_FLASH /* 1 */ + /* ENV protection ON by default */ +/* flash_protect(FLAG_PROTECT_SET, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + flash_get_info(CFG_ENV_ADDR)); +*/ + flash_protect(FLAG_PROTECT_CLEAR, + CFG_ENV_ADDR, + CFG_ENV_ADDR+CFG_ENV_SIZE-1, + flash_get_info(CFG_ENV_ADDR)); + +#endif + + + return size; +} + +/*----------------------------------------------------------------------- + */ +static void flash_reset(flash_info_t *info) +{ + FPWV *base = (FPWV *)(info->start[0]); + + (*DANUBE_EBU_BUSCON0)&=(~0x80000000); // enable writing + (*DANUBE_EBU_BUSCON1)&=(~0x80000000); // enable writing + (*EBU_NAND_CON)=0; + /* Put FLASH back in read mode */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL){ + *base = (FPW)0x00FF00FF; /* Intel Read Mode */ + asm("SYNC"); + } + else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD){ + *base = (FPW)0x00F000F0; /* AMD Read Mode */ + asm("SYNC"); //joelin + } + else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX){ + *base = (FPW)0x00F000F0; /* MXIC Read Mode */ + asm("SYNC"); //joelin + } + + (*DANUBE_EBU_BUSCON0)|=0x80000000; // disable writing + (*DANUBE_EBU_BUSCON1)|=0x80000000; // disable writing + +} + +/*----------------------------------------------------------------------- + */ +static void flash_get_offsets (ulong base, flash_info_t *info) +{ + int i; + + /* set up sector start address table */ + if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL + && (info->flash_id & FLASH_BTYPE)) { + int bootsect_size; /* number of bytes/boot sector */ + int sect_size; /* number of bytes/regular sector */ + + bootsect_size = 0x00002000 * (sizeof(FPW)/2); + sect_size = 0x00010000 * (sizeof(FPW)/2); + + /* set sector offsets for bottom boot block type */ + for (i = 0; i < 8; ++i) { + info->start[i] = base + (i * bootsect_size); + } + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i - 7) * sect_size); + } + } + else if ((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_AMD + && (info->flash_id & FLASH_TYPEMASK) == FLASH_AM640U) { + + int sect_size; /* number of bytes/sector */ + + sect_size = 0x00010000 * (sizeof(FPW)/2); + + /* set up sector start address table (uniform sector type) */ + for( i = 0; i < info->sector_count; i++ ) + info->start[i] = base + (i * sect_size); + } + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_28F128J3A)){ + int sect_size; + sect_size = 0x20000; + for(i=0;i < info->sector_count; i++) + info->start[i]= base + (i*sect_size); + } + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_28F320J3A)){ + int sect_size; + sect_size = 0x20000; + for(i=0;i < info->sector_count; i++) + info->start[i]= base + (i*sect_size); + } +//joelin add for MX29LV320AB-- SA0~SA7:sector size=8K bytes ,SA9~SA70 :sector size=64k bytes + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_29LV320AB)){ + int bootsect_size; /* number of bytes/boot sector */ + int sect_size; /* number of bytes/regular sector */ + + bootsect_size = 0x00002000 * (sizeof(FPW)/2); + sect_size = 0x00010000 * (sizeof(FPW)/2); + + /* set sector offsets for bottom boot block type */ + for (i = 0; i < 8; ++i) { + info->start[i] = base + (i * bootsect_size); + } + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i - 7) * sect_size); + } + } +//joelin add for MX29LV160BB-- SA0=16K,SA1,SA2=8K,SA3=32K bytes ,SA4~SA34 :sector size=64k bytes + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_29LV160BB)){ + int bootsect_size; /* number of bytes/boot sector */ + int sect_size; /* number of bytes/regular sector */ + + bootsect_size = 0x00002000 * (sizeof(FPW)/2); + sect_size = 0x00010000 * (sizeof(FPW)/2); +/* set sector offsets for bottom boot block type */ +//MX29LV160BB + info->start[0] = base ; //SA0=16K bytes + info->start[1] = info->start[0] + (1 * 0x00004000 * (sizeof(FPW)/2)); //SA1=8K bytes + info->start[2] = info->start[1] + (1 * 0x00002000 * (sizeof(FPW)/2)); //SA2=8K bytes + info->start[3] = info->start[2] + (1 * 0x00002000 * (sizeof(FPW)/2)); //SA3=32K bytes + + for (i = 4; i < info->sector_count; i++) { + info->start[i] = base + ((i - 3) * sect_size); + } + } +//liupeng add for MX29LV640BB-- SA0~SA7:sector size=8k bytes ,SA8~SA134 :sector size=64k bytes + else if(((info->flash_id & FLASH_VENDMASK) == FLASH_MAN_MX) + && ((info->flash_id & FLASH_TYPEMASK)==FLASH_29LV640BB)){ + int bootsect_size; /* number of bytes/boot sector */ + int sect_size; /* number of bytes/regular sector */ + + bootsect_size = 0x00002000 * (sizeof(FPW)/2); + sect_size = 0x00010000 * (sizeof(FPW)/2); + + /* set sector offsets for bottom boot block type */ + for (i = 0; i < 8; ++i) { + info->start[i] = base + (i * bootsect_size); + } + for (i = 8; i < info->sector_count; i++) { + info->start[i] = base + ((i - 7) * sect_size); + } + } + else{ + printf("flash get offsets fail\n"); + } +} + +/*----------------------------------------------------------------------- + */ + +static flash_info_t *flash_get_info(ulong base) +{ + int i; + flash_info_t * info; + + for (i = 0; i < CFG_MAX_FLASH_BANKS; i ++) { + info = & flash_info[i]; + if (info->start[0] <= base && base < info->start[0] + info->size) + break; + } + + return i == CFG_MAX_FLASH_BANKS ? 0 : info; +} + +/*----------------------------------------------------------------------- + */ + +void flash_print_info (flash_info_t *info) +{ + int i; + uchar *boottype; + uchar *bootletter; + uchar *fmt; + uchar botbootletter[] = "B"; + uchar topbootletter[] = "T"; + uchar botboottype[] = "bottom boot sector"; + uchar topboottype[] = "top boot sector"; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_SST: printf ("SST "); break; + case FLASH_MAN_STM: printf ("STM "); break; + case FLASH_MAN_INTEL: printf ("INTEL "); break; + case FLASH_MAN_MX: printf ("MXIC "); break; + default: printf ("Unknown Vendor "); break; + } + + /* check for top or bottom boot, if it applies */ + if (info->flash_id & FLASH_BTYPE) { + boottype = botboottype; + bootletter = botbootletter; + } + else { + boottype = topboottype; + bootletter = topbootletter; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM640U: + fmt = "29LV641D (64 Mbit, uniform sectors)\n"; + break; + case FLASH_28F800C3B: + case FLASH_28F800C3T: + fmt = "28F800C3%s (8 Mbit, %s)\n"; + break; + case FLASH_INTEL800B: + case FLASH_INTEL800T: + fmt = "28F800B3%s (8 Mbit, %s)\n"; + break; + case FLASH_28F160C3B: + case FLASH_28F160C3T: + fmt = "28F160C3%s (16 Mbit, %s)\n"; + break; + case FLASH_INTEL160B: + case FLASH_INTEL160T: + fmt = "28F160B3%s (16 Mbit, %s)\n"; + break; + case FLASH_28F320C3B: + case FLASH_28F320C3T: + fmt = "28F320C3%s (32 Mbit, %s)\n"; + break; + case FLASH_INTEL320B: + case FLASH_INTEL320T: + fmt = "28F320B3%s (32 Mbit, %s)\n"; + break; + case FLASH_28F640C3B: + case FLASH_28F640C3T: + fmt = "28F640C3%s (64 Mbit, %s)\n"; + break; + case FLASH_INTEL640B: + case FLASH_INTEL640T: + fmt = "28F640B3%s (64 Mbit, %s)\n"; + break; + case FLASH_28F128J3A: + fmt = "28F128J3A (128 Mbit, 128 uniform sectors)\n"; + break; + case FLASH_28F320J3A: + fmt = "28F320J3A (32 Mbit, 32 uniform sectors)\n"; + break; + case FLASH_29LV640BB: //liupeng for MXIC FLASH_29LV640BB + fmt = "29LV640BB (64 Mbit, boot sector SA0~SA126 size 64k bytes,other sectors SA127~SA135 size 8k bytes)\n"; + break; + case FLASH_29LV320AB: //joelin for MXIC FLASH_29LV320AB + fmt = "29LV320AB (32 Mbit, boot sector SA0~SA7 size 8K bytes,other sectors SA8~SA70 size 64K bytes)\n"; + break; + case FLASH_29LV160BB: //joelin for MXIC FLASH_29LV160BB + fmt = "29LV160BB (16 Mbit, boot sector SA0 size 16K bytes,SA1,SA2 size 8K bytes,SA3 size 32k bytes,other sectors SA4~SA34 size 64K bytes)\n"; + break; + default: + fmt = "Unknown Chip Type\n"; + break; + } + + printf (fmt, bootletter, boottype); + + printf (" Size: %ld MB in %d Sectors\n", + info->size >> 20, + info->sector_count); + + printf (" Sector Start Addresses:"); + + for (i=0; isector_count; ++i) { + if ((i % 5) == 0) { + printf ("\n "); + } + + printf (" %08lX%s", info->start[i], + info->protect[i] ? " (RO)" : " "); + } + + printf ("\n"); +} + +/*----------------------------------------------------------------------- + */ + +/* + * The following code cannot be run from FLASH! + */ + +ulong flash_get_size (FPWV *addr, flash_info_t *info) +{ + (*DANUBE_EBU_BUSCON0)=0x1d7ff; //value from Aikann, should be used on the real chip + (*EBU_ADDR_SEL_0) = 0x10000031; //starting address from 0xb0000000 + (*EBU_NAND_CON)=0; + (*DANUBE_EBU_BUSCON0)&=(~0x80000000); // enable writing + (*DANUBE_EBU_BUSCON1)&=(~0x80000000); // enable writing + /* Write auto select command: read Manufacturer ID */ + + /* Write auto select command sequence and test FLASH answer */ + addr[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* for AMD, Intel ignores this */ + asm("SYNC"); + addr[FLASH_CYCLE2] = (FPW)0x00550055; /* for AMD, Intel ignores this */ + asm("SYNC"); + addr[FLASH_CYCLE1] = (FPW)0x00900090; /* selects Intel or AMD */ + asm("SYNC"); + + /* The manufacturer codes are only 1 byte, so just use 1 byte. + * This works for any bus width and any FLASH device width. + */ + +// printf("\n type is %08lx", addr[1] & 0xff); //joelin 10/06/2004 flash type +// printf("\n type is %08lx", addr[0] & 0xff); //joelin 10/06/2004 flash type +// asm("SYNC"); + switch (addr[1] & 0xff) { + case (uchar)AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + case (uchar)INTEL_MANUFACT: // 0x0089 + info->flash_id = FLASH_MAN_INTEL; //0x00300000 + break; + +//joelin for MXIC + case (uchar)MX_MANUFACT: // 0x00c2 + info->flash_id = FLASH_MAN_MX ;//0x00030000 + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + break; +/* default: + info->flash_id = FLASH_MAN_INTEL; //0x00300000 + break;*/ + } + + /* Check 16 bits or 32 bits of ID so work on 32 or 16 bit bus. */ + if (info->flash_id != FLASH_UNKNOWN) switch (addr[0]) { + case (FPW)AMD_ID_LV640U: /* 29LV640 and 29LV641 have same ID */ + info->flash_id += FLASH_AM640U; + info->sector_count = 128; + info->size = 0x00800000 * (sizeof(FPW)/2); + break; /* => 8 or 16 MB */ + + case (FPW)INTEL_ID_28F800C3B: + info->flash_id += FLASH_28F800C3B; + info->sector_count = 23; + info->size = 0x00100000 * (sizeof(FPW)/2); + break; /* => 1 or 2 MB */ + + case (FPW)INTEL_ID_28F800B3B: + info->flash_id += FLASH_INTEL800B; + info->sector_count = 23; + info->size = 0x00100000 * (sizeof(FPW)/2); + break; /* => 1 or 2 MB */ + + case (FPW)INTEL_ID_28F160C3B: + info->flash_id += FLASH_28F160C3B; + info->sector_count = 39; + info->size = 0x00200000 * (sizeof(FPW)/2); + break; /* => 2 or 4 MB */ + + case (FPW)INTEL_ID_28F160B3B: + info->flash_id += FLASH_INTEL160B; + info->sector_count = 39; + info->size = 0x00200000 * (sizeof(FPW)/2); + break; /* => 2 or 4 MB */ + + case (FPW)INTEL_ID_28F320C3B: + info->flash_id += FLASH_28F320C3B; + info->sector_count = 71; + info->size = 0x00400000 * (sizeof(FPW)/2); + break; /* => 4 or 8 MB */ + + case (FPW)INTEL_ID_28F320B3B: + info->flash_id += FLASH_INTEL320B; + info->sector_count = 71; + info->size = 0x00400000 * (sizeof(FPW)/2); + break; /* => 4 or 8 MB */ + + case (FPW)INTEL_ID_28F640C3B: + info->flash_id += FLASH_28F640C3B; + info->sector_count = 135; + info->size = 0x00800000 * (sizeof(FPW)/2); + break; /* => 8 or 16 MB */ + + case (FPW)INTEL_ID_28F640B3B: + info->flash_id += FLASH_INTEL640B; + info->sector_count = 135; + info->size = 0x00800000 * (sizeof(FPW)/2); + break; /* => 8 or 16 MB */ + + case (FPW)INTEL_ID_28F128J3A: + info->flash_id +=FLASH_28F128J3A; + info->sector_count = 128; + info->size = 0x01000000 * (sizeof(FPW)/2); + break; /* => 16 MB */ + case (FPW)INTEL_ID_28F320J3A: + info->flash_id += FLASH_28F320J3A; + info->sector_count = 32; + info->size = 0x00400000 * (sizeof(FPW)/2); + break; +//joelin for MXIC + case (FPW)MX_ID_29LV320AB: + info->flash_id += FLASH_29LV320AB; + info->sector_count = 71; + info->size = 0x00400000 * (sizeof(FPW)/2); + break; /* => 4 MB */ + /* => 4 MB */ +//joelin for MXIC + case (FPW)MX_ID_29LV160BB: + info->flash_id += FLASH_29LV160BB; + info->sector_count = 35; + info->size = 0x00200000 * (sizeof(FPW)/2); + break; /* => 2 MB */ + /* => 2 MB */ + /* liupeng*/ + case (FPW)MX_ID_29LV640BB: + info->flash_id += FLASH_29LV640BB; + info->sector_count = 135; + info->size = 0x00800000 * (sizeof(FPW)/2); + break; /* => 2 MB */ + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + return (0); /* => no or unknown flash */ +/* default: + info->flash_id += FLASH_28F320J3A; + info->sector_count = 32; + info->size = 0x00400000 * (sizeof(FPW)/2); + break;*/ + } + + + (*DANUBE_EBU_BUSCON0)|=0x80000000; // disable writing + (*DANUBE_EBU_BUSCON1)|=0x80000000; // disable writing + + flash_get_offsets((ulong)addr, info); + + /* Put FLASH back in read mode */ + flash_reset(info); + + return (info->size); +} + +/*----------------------------------------------------------------------- + */ + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + FPWV *addr; + int flag, prot, sect; + int intel = (info->flash_id & FLASH_VENDMASK) == FLASH_MAN_INTEL; + ulong start, now, last; + int rcode = 0; + if ((s_first < 0) || (s_first > s_last)) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + return 1; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_INTEL800B: + case FLASH_INTEL160B: + case FLASH_INTEL320B: + case FLASH_INTEL640B: + case FLASH_28F800C3B: + case FLASH_28F160C3B: + case FLASH_28F320C3B: + case FLASH_28F640C3B: + case FLASH_28F128J3A: + case FLASH_28F320J3A: + case FLASH_AM640U: + case FLASH_29LV640BB: //liupeng for MXIC MX29LV640BB + case FLASH_29LV320AB: //joelin for MXIC MX29LV320AB + case FLASH_29LV160BB: //joelin for MXIC MX29LV160BB + break; + case FLASH_UNKNOWN: + default: + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf ("\n"); + } + + last = get_timer(0); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last && rcode == 0; sect++) { + + if (info->protect[sect] != 0) /* protected, skip it */ + continue; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + (*DANUBE_EBU_BUSCON0)&=(~0x80000000); // enable writing + (*DANUBE_EBU_BUSCON1)&=(~0x80000000); // enable writing + (*EBU_NAND_CON)=0; + addr = (FPWV *)(info->start[sect]); + if (intel) { + *addr = (FPW)0x00500050; /* clear status register */ + *addr = (FPW)0x00200020; /* erase setup */ + *addr = (FPW)0x00D000D0; /* erase confirm */ + asm("SYNC"); + } + else { + /* must be AMD style if not Intel */ + FPWV *base; /* first address in bank */ + + base = (FPWV *)(info->start[0]); + base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */ + base[FLASH_CYCLE1] = (FPW)0x00800080; /* erase mode */ + base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */ + *addr = (FPW)0x00300030; /* erase sector */ + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer(0); + + /* wait at least 50us for AMD, 80us for Intel. + * Let's wait 1 ms. + */ + udelay (1000); + + while ((*addr & (FPW)0x00800080) != (FPW)0x00800080) { + if ((now = get_timer(start)) > CFG_FLASH_ERASE_TOUT) { + printf ("Erase Timeout\n"); + + if (intel) { + /* suspend erase */ + *addr = (FPW)0x00B000B0; + } + + flash_reset(info); /* reset to read mode */ + rcode = 1; /* failed */ + break; + } + + /* show that we're waiting */ + if ((get_timer(last)) > CFG_HZ) {/* every second */ + putc ('.'); + last = get_timer(0); + } + } + + +//joelin for MXIC + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_MX: //joelin for MXIC + break; + default: + if((*addr & (FPW)0x00200020) != (FPW)0x0) + printf("Erase Error\n"); + break; + } + + + + /* show that we're waiting */ + if ((get_timer(last)) > CFG_HZ) { /* every second */ + putc ('.'); + last = get_timer(0); + } + + //flash_reset(info); /* reset to read mode */ + } + + (*DANUBE_EBU_BUSCON0)|=0x80000000; // disable writing + (*DANUBE_EBU_BUSCON1)|=0x80000000; // disable writing + + printf (" done\n"); + return rcode; +} + +/*----------------------------------------------------------------------- + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + FPW data = 0; /* 16 or 32 bit word, matches flash bus width on MPC8XX */ + int bytes; /* number of bytes to program in current word */ + int left; /* number of bytes left to program */ + int i, res; + + for (left = cnt, res = 0; + left > 0 && res == 0; + addr += sizeof(data), left -= sizeof(data) - bytes) { + + bytes = addr & (sizeof(data) - 1); + addr &= ~(sizeof(data) - 1); + + /* combine source and destination data so can program + * an entire word of 16 or 32 bits + */ + for (i = 0; i < sizeof(data); i++) { + data <<= 8; + if (i < bytes || i - bytes >= left ) + data += *((uchar *)addr + i); + else + data += *src++; + } + + /* write one word to the flash */ + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: + case FLASH_MAN_MX: //joelin for MXIC + res = write_word_amd(info, (FPWV *)addr, data); + break; + case FLASH_MAN_INTEL: + res = write_word_intel(info, (FPWV *)addr, data); + break; + default: + /* unknown flash type, error! */ + printf ("missing or unknown FLASH type\n"); + res = 1; /* not really a timeout, but gives error */ + break; + } + } + + return (res); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash for AMD FLASH + * A word is 16 or 32 bits, whichever the bus width of the flash bank + * (not an individual chip) is. + * + * returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word_amd (flash_info_t *info, FPWV *dest, FPW data) +{ + ulong start; + int flag; + int res = 0; /* result, assume success */ + FPWV *base; /* first address in flash bank */ + + /* Check if Flash is (sufficiently) erased */ + if ((*dest & data) != data) { + return (2); + } + + base = (FPWV *)(info->start[0]); + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + (*DANUBE_EBU_BUSCON0)&=(~0x80000000); // enable writing + (*DANUBE_EBU_BUSCON1)&=(~0x80000000); // enable writing + (*EBU_NAND_CON)=0; + + base[FLASH_CYCLE1] = (FPW)0x00AA00AA; /* unlock */ + base[FLASH_CYCLE2] = (FPW)0x00550055; /* unlock */ + base[FLASH_CYCLE1] = (FPW)0x00A000A0; /* selects program mode */ + + *dest = data; /* start programming the data */ + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + + /* data polling for D7 */ + while (res == 0 && (*dest & (FPW)0x00800080) != (data & (FPW)0x00800080)) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + *dest = (FPW)0x00F000F0; /* reset bank */ + res = 1; + } + } + + (*DANUBE_EBU_BUSCON0)|=0x80000000; // disable writing + (*DANUBE_EBU_BUSCON1)|=0x80000000; // disable writing + + return (res); +} + +/*----------------------------------------------------------------------- + * Write a word to Flash for Intel FLASH + * A word is 16 or 32 bits, whichever the bus width of the flash bank + * (not an individual chip) is. + * + * returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word_intel (flash_info_t *info, FPWV *dest, FPW data) +{ + ulong start; + int flag; + int res = 0; /* result, assume success */ + + /* Check if Flash is (sufficiently) erased */ + if ((*dest & data) != data) { + return (2); + } + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + (*DANUBE_EBU_BUSCON0)&=(~0x80000000); // enable writing + (*DANUBE_EBU_BUSCON1)&=(~0x80000000); // enable writing + (*EBU_NAND_CON)=0; + *dest = (FPW)0x00500050; /* clear status register */ + *dest = (FPW)0x00FF00FF; /* make sure in read mode */ + *dest = (FPW)0x00400040; /* program setup */ + *dest = data; /* start programming the data */ + asm("SYNC"); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + start = get_timer (0); + + while (res == 0 && (*dest & (FPW)0x00800080) != (FPW)0x00800080) { + if (get_timer(start) > CFG_FLASH_WRITE_TOUT) { + *dest = (FPW)0x00B000B0; /* Suspend program */ + res = 1; + } + } + + if (res == 0 && (*dest & (FPW)0x00100010)) + res = 1; /* write failed, time out error is close enough */ + + *dest = (FPW)0x00500050; /* clear status register */ + flash_reset(info); + + (*DANUBE_EBU_BUSCON0)|=0x80000000; // disable writing + (*DANUBE_EBU_BUSCON1)|=0x80000000; // disable writing + + return (res); +} diff --git a/package/uboot-ifxmips/files/board/danube/lowlevel_init.S b/package/uboot-ifxmips/files/board/danube/lowlevel_init.S new file mode 100644 index 0000000000..f5f24a40cf --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/lowlevel_init.S @@ -0,0 +1,582 @@ + +/* + * Memory sub-system initialization code for INCA-IP2 development board. + * Andre Messerschmidt + * Copyright (c) 2005 Infineon Technologies AG + * + * Based on Inca-IP code + * Copyright (c) 2003 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ +/* History: + peng liu May 25, 2006, for PLL setting after reset, 05252006 + */ +#include +#include +#include +#include + + +#ifdef USE_REFERENCE_BOARD +#ifdef DANUBE_DDR_RAM_111M +#include "ddr_settings_r111.h" +#elif defined(PROMOSDDR400) +#include "ddr_settings_PROMOSDDR400.h" +#elif defined(DDR_SAMSUNG_166M) +#include "ddr_settings_Samsung_166.h" +#elif defined(DDR_PSC_166M) +#include "ddr_settings_psc_166.h" +#else +#include "ddr_settings_r166.h" +#endif +#endif + +#ifdef USE_EVALUATION_BOARD +#ifdef DANUBE_DDR_RAM_111M +#include "ddr_settings_e111.h" +#else +#include "ddr_settings_e166.h" +#endif +#endif + + + +/*TODO: liupeng check !!! */ +#define EBU_MODUL_BASE 0xB4102000 +#define EBU_CLC(value) 0x0000(value) +#define EBU_CON(value) 0x0010(value) +#define EBU_ADDSEL0(value) 0x0020(value) +#define EBU_ADDSEL1(value) 0x0024(value) +#define EBU_ADDSEL2(value) 0x0028(value) +#define EBU_ADDSEL3(value) 0x002C(value) +#define EBU_BUSCON0(value) 0x0060(value) +#define EBU_BUSCON1(value) 0x0064(value) +#define EBU_BUSCON2(value) 0x0068(value) +#define EBU_BUSCON3(value) 0x006C(value) + +#define MC_MODUL_BASE 0xBF800000 +#define MC_ERRCAUSE(value) 0x0010(value) +#define MC_ERRADDR(value) 0x0020(value) +#define MC_CON(value) 0x0060(value) + +#define MC_SRAM_ENABLE 0x00000004 +#define MC_SDRAM_ENABLE 0x00000002 +#define MC_DDRRAM_ENABLE 0x00000001 + +#define MC_SDR_MODUL_BASE 0xBF800200 +#define MC_IOGP(value) 0x0000(value) +#define MC_CTRLENA(value) 0x0010(value) +#define MC_MRSCODE(value) 0x0020(value) +#define MC_CFGDW(value) 0x0030(value) +#define MC_CFGPB0(value) 0x0040(value) +#define MC_LATENCY(value) 0x0080(value) +#define MC_TREFRESH(value) 0x0090(value) +#define MC_SELFRFSH(value) 0x00A0(value) + +#define MC_DDR_MODUL_BASE 0xBF801000 +#define MC_DC00(value) 0x0000(value) +#define MC_DC01(value) 0x0010(value) +#define MC_DC02(value) 0x0020(value) +#define MC_DC03(value) 0x0030(value) +#define MC_DC04(value) 0x0040(value) +#define MC_DC05(value) 0x0050(value) +#define MC_DC06(value) 0x0060(value) +#define MC_DC07(value) 0x0070(value) +#define MC_DC08(value) 0x0080(value) +#define MC_DC09(value) 0x0090(value) +#define MC_DC10(value) 0x00A0(value) +#define MC_DC11(value) 0x00B0(value) +#define MC_DC12(value) 0x00C0(value) +#define MC_DC13(value) 0x00D0(value) +#define MC_DC14(value) 0x00E0(value) +#define MC_DC15(value) 0x00F0(value) +#define MC_DC16(value) 0x0100(value) +#define MC_DC17(value) 0x0110(value) +#define MC_DC18(value) 0x0120(value) +#define MC_DC19(value) 0x0130(value) +#define MC_DC20(value) 0x0140(value) +#define MC_DC21(value) 0x0150(value) +#define MC_DC22(value) 0x0160(value) +#define MC_DC23(value) 0x0170(value) +#define MC_DC24(value) 0x0180(value) +#define MC_DC25(value) 0x0190(value) +#define MC_DC26(value) 0x01A0(value) +#define MC_DC27(value) 0x01B0(value) +#define MC_DC28(value) 0x01C0(value) +#define MC_DC29(value) 0x01D0(value) +#define MC_DC30(value) 0x01E0(value) +#define MC_DC31(value) 0x01F0(value) +#define MC_DC32(value) 0x0200(value) +#define MC_DC33(value) 0x0210(value) +#define MC_DC34(value) 0x0220(value) +#define MC_DC35(value) 0x0230(value) +#define MC_DC36(value) 0x0240(value) +#define MC_DC37(value) 0x0250(value) +#define MC_DC38(value) 0x0260(value) +#define MC_DC39(value) 0x0270(value) +#define MC_DC40(value) 0x0280(value) +#define MC_DC41(value) 0x0290(value) +#define MC_DC42(value) 0x02A0(value) +#define MC_DC43(value) 0x02B0(value) +#define MC_DC44(value) 0x02C0(value) +#define MC_DC45(value) 0x02D0(value) +#define MC_DC46(value) 0x02E0(value) + +#define RCU_OFFSET 0xBF203000 +#define RCU_RST_REQ (RCU_OFFSET + 0x0010) +#define RCU_STS (RCU_OFFSET + 0x0014) + +#define CGU_OFFSET 0xBF103000 +#define PLL0_CFG (CGU_OFFSET + 0x0004) +#define PLL1_CFG (CGU_OFFSET + 0x0008) +#define PLL2_CFG (CGU_OFFSET + 0x000C) +#define CGU_SYS (CGU_OFFSET + 0x0010) +#define CGU_UPDATE (CGU_OFFSET + 0x0014) +#define IF_CLK (CGU_OFFSET + 0x0018) +#define CGU_SMD (CGU_OFFSET + 0x0020) +#define CGU_CT1SR (CGU_OFFSET + 0x0028) +#define CGU_CT2SR (CGU_OFFSET + 0x002C) +#define CGU_PCMCR (CGU_OFFSET + 0x0030) +#define PCI_CR_PCI (CGU_OFFSET + 0x0034) +#define CGU_OSC_CTRL (CGU_OFFSET + 0x001C) +#define CGU_MIPS_PWR_DWN (CGU_OFFSET + 0x0038) +#define CLK_MEASURE (CGU_OFFSET + 0x003C) + +//05252006 +#define pll0_35MHz_CONFIG 0x9D861059 +#define pll1_35MHz_CONFIG 0x1A260CD9 +#define pll2_35MHz_CONFIG 0x8000f1e5 +#define pll0_36MHz_CONFIG 0x1000125D +#define pll1_36MHz_CONFIG 0x1B1E0C99 +#define pll2_36MHz_CONFIG 0x8002f2a1 +//05252006 + +//06063001-joelin disable the PCI CFRAME mask -start +/*CFRAME is an I/O signal, in the chip, the output CFRAME is selected via GPIO altsel pins, so if you select MII1 RXD1, the CFRAME will not come out. +But the CFRAME input still take the signal from the pad and not disabled when altsel choose other function. So when MII1_RXD1 is low from other device, the EBU interface will be disabled. + +The chip function in such a way that disable the CFRAME mask mean EBU not longer check CFRAME to be the device using the bus. +The side effect is the entire PCI block will see CFRAME low all the time meaning PCI cannot use the bus at all so no more PCI function. +*/ +#define PCI_CR_PR_OFFSET 0xBE105400 +#define PCI_CR_PCI_MOD_REG (PCI_CR_PR_OFFSET + 0x0030) +#define PCI_CONFIG_SPACE 0xB7000000 +#define CS_CFM (PCI_CONFIG_SPACE + 0x6C) +//06063001-joelin disable the PCI CFRAME mask -end + .set noreorder + + +/* + * void ebu_init(long) + * + * a0 has the clock value we are going to run at + */ + .globl ebu_init + .ent ebu_init +ebu_init: +/*TODO:liupeng */ + j ra + nop + + .end ebu_init + + +/* + * void cgu_init(long) + * + * a0 has the clock value + */ + .globl cgu_init + .ent cgu_init +cgu_init: + li t2, CGU_SYS + lw t2,0(t2) + beq t2,a0,freq_up2date + nop + + li t2, RCU_STS + lw t2, 0(t2) + and t2,0x00020000 + beq t2,0x00020000,boot_36MHZ + nop +//05252006 + li t1, PLL0_CFG + li t2, pll0_35MHz_CONFIG + sw t2,0(t1) + li t1, PLL1_CFG + li t2, pll1_35MHz_CONFIG + sw t2,0(t1) + li t1, PLL2_CFG + li t2, pll2_35MHz_CONFIG + sw t2,0(t1) + li t1, CGU_SYS + sw a0,0(t1) + li t1, RCU_RST_REQ + li t2, 0x40000008 + sw t2,0(t1) + b wait_reset + nop +boot_36MHZ: + li t1, PLL0_CFG + li t2, pll0_36MHz_CONFIG + sw t2,0(t1) + li t1, PLL1_CFG + li t2, pll1_36MHz_CONFIG + sw t2,0(t1) + li t1, PLL2_CFG + li t2, pll2_36MHz_CONFIG + sw t2,0(t1) + li t1, CGU_SYS + sw a0,0(t1) + li t1, RCU_RST_REQ + li t2, 0x40000008 + sw t2,0(t1) +//05252006 + +wait_reset: + b wait_reset + nop +freq_up2date: + j ra + nop + .end cgu_init + + +/* + * void sdram_init(long) + * + * a0 has the clock value + */ + .globl sdram_init + .ent sdram_init +sdram_init: + + /* SDRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable SDRAM module in memory controller */ + li t3, MC_SDRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_SDR_MODUL_BASE + + /* disable the controller */ + li t2, 0 + sw t2, MC_CTRLENA(t1) + + li t2, 0x822 + sw t2, MC_IOGP(t1) + + li t2, 0x2 + sw t2, MC_CFGDW(t1) + + /* Set CAS Latency */ + li t2, 0x00000020 + sw t2, MC_MRSCODE(t1) + + /* Set CS0 to SDRAM parameters */ + li t2, 0x000014d8 + sw t2, MC_CFGPB0(t1) + + /* Set SDRAM latency parameters */ + li t2, 0x00036325; /* BC PC100 */ + sw t2, MC_LATENCY(t1) + + /* Set SDRAM refresh rate */ + li t2, 0x00000C30 + sw t2, MC_TREFRESH(t1) + + /* Clear Power-down registers */ + sw zero, MC_SELFRFSH(t1) + + /* Finally enable the controller */ + li t2, 1 + sw t2, MC_CTRLENA(t1) + + + j ra + nop + + + .end sdram_init + +/* + * void ddrram_init(long) + * + * a0 has the clock value + */ + .globl ddrram_init + .ent ddrram_init +ddrram_init: + + /* DDR-DRAM Initialization + */ + li t1, MC_MODUL_BASE + + /* Clear Error log registers */ + sw zero, MC_ERRCAUSE(t1) + sw zero, MC_ERRADDR(t1) + + /* Enable DDR module in memory controller */ + li t3, MC_DDRRAM_ENABLE + lw t2, MC_CON(t1) + or t3, t2, t3 + sw t3, MC_CON(t1) + + li t1, MC_DDR_MODUL_BASE + + /* Write configuration to DDR controller registers */ + li t2, MC_DC0_VALUE + sw t2, MC_DC00(t1) + + li t2, MC_DC1_VALUE + sw t2, MC_DC01(t1) + + li t2, MC_DC2_VALUE + sw t2, MC_DC02(t1) + + li t2, MC_DC3_VALUE + sw t2, MC_DC03(t1) + + li t2, MC_DC4_VALUE + sw t2, MC_DC04(t1) + + li t2, MC_DC5_VALUE + sw t2, MC_DC05(t1) + + li t2, MC_DC6_VALUE + sw t2, MC_DC06(t1) + + li t2, MC_DC7_VALUE + sw t2, MC_DC07(t1) + + li t2, MC_DC8_VALUE + sw t2, MC_DC08(t1) + + li t2, MC_DC9_VALUE + sw t2, MC_DC09(t1) + + li t2, MC_DC10_VALUE + sw t2, MC_DC10(t1) + + li t2, MC_DC11_VALUE + sw t2, MC_DC11(t1) + + li t2, MC_DC12_VALUE + sw t2, MC_DC12(t1) + + li t2, MC_DC13_VALUE + sw t2, MC_DC13(t1) + + li t2, MC_DC14_VALUE + sw t2, MC_DC14(t1) + + li t2, MC_DC15_VALUE + sw t2, MC_DC15(t1) + + li t2, MC_DC16_VALUE + sw t2, MC_DC16(t1) + + li t2, MC_DC17_VALUE + sw t2, MC_DC17(t1) + + li t2, MC_DC18_VALUE + sw t2, MC_DC18(t1) + + li t2, MC_DC19_VALUE + sw t2, MC_DC19(t1) + + li t2, MC_DC20_VALUE + sw t2, MC_DC20(t1) + + li t2, MC_DC21_VALUE + sw t2, MC_DC21(t1) + + li t2, MC_DC22_VALUE + sw t2, MC_DC22(t1) + + li t2, MC_DC23_VALUE + sw t2, MC_DC23(t1) + + li t2, MC_DC24_VALUE + sw t2, MC_DC24(t1) + + li t2, MC_DC25_VALUE + sw t2, MC_DC25(t1) + + li t2, MC_DC26_VALUE + sw t2, MC_DC26(t1) + + li t2, MC_DC27_VALUE + sw t2, MC_DC27(t1) + + li t2, MC_DC28_VALUE + sw t2, MC_DC28(t1) + + li t2, MC_DC29_VALUE + sw t2, MC_DC29(t1) + + li t2, MC_DC30_VALUE + sw t2, MC_DC30(t1) + + li t2, MC_DC31_VALUE + sw t2, MC_DC31(t1) + + li t2, MC_DC32_VALUE + sw t2, MC_DC32(t1) + + li t2, MC_DC33_VALUE + sw t2, MC_DC33(t1) + + li t2, MC_DC34_VALUE + sw t2, MC_DC34(t1) + + li t2, MC_DC35_VALUE + sw t2, MC_DC35(t1) + + li t2, MC_DC36_VALUE + sw t2, MC_DC36(t1) + + li t2, MC_DC37_VALUE + sw t2, MC_DC37(t1) + + li t2, MC_DC38_VALUE + sw t2, MC_DC38(t1) + + li t2, MC_DC39_VALUE + sw t2, MC_DC39(t1) + + li t2, MC_DC40_VALUE + sw t2, MC_DC40(t1) + + li t2, MC_DC41_VALUE + sw t2, MC_DC41(t1) + + li t2, MC_DC42_VALUE + sw t2, MC_DC42(t1) + + li t2, MC_DC43_VALUE + sw t2, MC_DC43(t1) + + li t2, MC_DC44_VALUE + sw t2, MC_DC44(t1) + + li t2, MC_DC45_VALUE + sw t2, MC_DC45(t1) + + li t2, MC_DC46_VALUE + sw t2, MC_DC46(t1) + + li t2, 0x00000100 + sw t2, MC_DC03(t1) + + j ra + nop + + + .end ddrram_init + + .globl lowlevel_init + .ent lowlevel_init +lowlevel_init: + /* EBU, CGU and SDRAM/DDR-RAM Initialization. + */ + move t0, ra + /* We rely on the fact that neither cgu_init() nor sdram_init() + * modify t0 + */ +#ifdef DANUBE_BOOT_FROM_EBU +#ifdef DANUBE_DDR_RAM_166M +//05252006 + /* 0xe8 means CPU0/CPU1 333M, DDR 167M, FPI 83M, PPE 240M */ + li a0,0xe8 + bal cgu_init + nop +#endif +#ifdef PROMOSDDR400 + li a0,0xe8 + bal cgu_init + nop +#endif +#ifdef DDR_SAMSUNG_166M + li a0,0xe8 + bal cgu_init + nop +#endif +#ifdef DDR_PSC_166M + li a0,0xe8 + bal cgu_init + nop +#endif +#ifdef DANUBE_DDR_RAM_133M + li a0,0xe9 +//05252006 + bal cgu_init + nop +#endif +#endif +/*TODO:liupeng add this define !!!! */ +/* + #define DANUBE_BOOT_FROM_EBU + #define DANUBE_USE_DDR_RAM +*/ + +//06063001-joelin disable the PCI CFRAME mask-start +#ifdef DISABLE_CFRAME + li t1, PCI_CR_PCI //mw bf103034 80000000 + li t2, 0x80000000 + sw t2,0(t1) + + li t1, PCI_CR_PCI_MOD_REG //mw be105430 103 + li t2, 0x103 + sw t2,0(t1) + + li t1, CS_CFM //mw b700006c 0 + li t2, 0x00 + sw t2, 0(t1) + + li t1, PCI_CR_PCI_MOD_REG //mw be105430 103 + li t2, 0x1000103 + sw t2, 0(t1) +#endif +//06063001-joelin disable the PCI CFRAME mask-end + +#ifdef DANUBE_BOOT_FROM_EBU +#ifdef DANUBE_USE_DDR_RAM + bal ddrram_init + nop +#else + bal sdram_init + nop +#endif +#endif + + move ra, t0 + j ra + nop + + .end lowlevel_init diff --git a/package/uboot-ifxmips/files/board/danube/pmuenable.S b/package/uboot-ifxmips/files/board/danube/pmuenable.S new file mode 100644 index 0000000000..e0d7971d89 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/pmuenable.S @@ -0,0 +1,48 @@ +/* + * Power Management unit initialization code for AMAZON development board. + * + * Copyright (c) 2003 Ou Ke, Infineon. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include + +#define PMU_PWDCR 0xBF10201C +#define PMU_SR 0xBF102020 + + .globl pmuenable + +pmuenable: + li t0, PMU_PWDCR + li t1, 0x2 /* enable everything */ + sw t1, 0(t0) +#if 0 +1: + li t0, PMU_SR + lw t2, 0(t0) + bne t1, t2, 1b + nop +#endif + j ra + nop + + diff --git a/package/uboot-ifxmips/files/board/danube/u-boot-bootstrap.lds b/package/uboot-ifxmips/files/board/danube/u-boot-bootstrap.lds new file mode 100644 index 0000000000..8738ca8a94 --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/u-boot-bootstrap.lds @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* +OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips") +*/ +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips") +OUTPUT_ARCH(mips) +ENTRY(_start_bootstrap) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .sdata : { *(.sdata) } + + _gp = ALIGN(16); + + __got_start_bootstrap = .; + .got : { *(.got) } + __got_end_bootstrap = .; + + .sdata : { *(.sdata) } + + . = .; + __u_boot_cmd_start_bootstrap = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end_bootstrap = .; + + uboot_end_data_bootstrap = .; + num_got_entries = (__got_end_bootstrap - __got_start_bootstrap) >> 2; + + . = ALIGN(4); + .sbss : { *(.sbss) } + .bss : { *(.bss) } + uboot_end_bootstrap = .; +} diff --git a/package/uboot-ifxmips/files/board/danube/u-boot.lds b/package/uboot-ifxmips/files/board/danube/u-boot.lds new file mode 100644 index 0000000000..ad3ec3194e --- /dev/null +++ b/package/uboot-ifxmips/files/board/danube/u-boot.lds @@ -0,0 +1,69 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* +OUTPUT_FORMAT("elf32-bigmips", "elf32-bigmips", "elf32-bigmips") +*/ +OUTPUT_FORMAT("elf32-tradbigmips", "elf32-tradbigmips", "elf32-tradbigmips") +OUTPUT_ARCH(mips) +ENTRY(_start) +SECTIONS +{ + . = 0x00000000; + + . = ALIGN(4); + .text : + { + *(.text) + } + + . = ALIGN(4); + .rodata : { *(.rodata) } + + . = ALIGN(4); + .data : { *(.data) } + + . = ALIGN(4); + .sdata : { *(.sdata) } + + _gp = ALIGN(16); + + __got_start = .; + .got : { *(.got) } + __got_end = .; + + .sdata : { *(.sdata) } + + . = .; + __u_boot_cmd_start = .; + .u_boot_cmd : { *(.u_boot_cmd) } + __u_boot_cmd_end = .; + + uboot_end_data = .; + num_got_entries = (__got_end - __got_start) >> 2; + + . = ALIGN(4); + .sbss : { *(.sbss) } + .bss : { *(.bss) } + uboot_end = .; +} diff --git a/package/uboot-ifxmips/files/common/flash_danube.c b/package/uboot-ifxmips/files/common/flash_danube.c new file mode 100644 index 0000000000..a64bc98529 --- /dev/null +++ b/package/uboot-ifxmips/files/common/flash_danube.c @@ -0,0 +1,228 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* #define DEBUG */ + +#include +#include + +#if !defined(CFG_NO_FLASH) + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ + +/*----------------------------------------------------------------------- + * Set protection status for monitor sectors + * + * The monitor is always located in the _first_ Flash bank. + * If necessary you have to map the second bank at lower addresses. + */ +void +flash_protect (int flag, ulong from, ulong to, flash_info_t *info) +{ + ulong b_end = info->start[0] + info->size - 1; /* bank end address */ + short s_end = info->sector_count - 1; /* index of last sector */ + int i; + + debug ("flash_protect %s: from 0x%08lX to 0x%08lX\n", + (flag & FLAG_PROTECT_SET) ? "ON" : + (flag & FLAG_PROTECT_CLEAR) ? "OFF" : "???", + from, to); + + /* Do nothing if input data is bad. */ + if (info->sector_count == 0 || info->size == 0 || to < from) { + return; + } + + /* There is nothing to do if we have no data about the flash + * or the protect range and flash range don't overlap. + */ + if (info->flash_id == FLASH_UNKNOWN || + to < info->start[0] || from > b_end) { + return; + } + + for (i=0; isector_count; ++i) { + ulong end; /* last address in current sect */ + + end = (i == s_end) ? b_end : info->start[i + 1] - 1; + + /* Update protection if any part of the sector + * is in the specified range. + */ + if (from <= end && to >= info->start[i]) { + if (flag & FLAG_PROTECT_CLEAR) { +#if defined(CFG_FLASH_PROTECTION) + flash_real_protect(info, i, 0); +#else + info->protect[i] = 0; +#endif /* CFG_FLASH_PROTECTION */ + debug ("protect off %d\n", i); + } + else if (flag & FLAG_PROTECT_SET) { +#if defined(CFG_FLASH_PROTECTION) + flash_real_protect(info, i, 1); +#else + info->protect[i] = 1; +#endif /* CFG_FLASH_PROTECTION */ + debug ("protect on %d\n", i); + } + } + } +} + +/*----------------------------------------------------------------------- + */ + +flash_info_t * +addr2info (ulong addr) +{ +#ifndef CONFIG_SPD823TS + flash_info_t *info; + int i; + + for (i=0, info=&flash_info[0]; iflash_id != FLASH_UNKNOWN && + addr >= info->start[0] && + /* WARNING - The '- 1' is needed if the flash + * is at the end of the address space, since + * info->start[0] + info->size wraps back to 0. + * Please don't change this unless you understand this. + */ + addr <= info->start[0] + info->size - 1) { + return (info); + } + } +#endif /* CONFIG_SPD823TS */ + + return (NULL); +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + * Make sure all target addresses are within Flash bounds, + * and no protected sectors are hit. + * Returns: + * ERR_OK 0 - OK + * ERR_TIMOUT 1 - write timeout + * ERR_NOT_ERASED 2 - Flash not erased + * ERR_PROTECTED 4 - target range includes protected sectors + * ERR_INVAL 8 - target address not in Flash memory + * ERR_ALIGN 16 - target address not aligned on boundary + * (only some targets require alignment) + */ +int +flash_write (char *src, ulong addr, ulong cnt) +{ +#ifdef CONFIG_SPD823TS + return (ERR_TIMOUT); /* any other error codes are possible as well */ +#else + int i; + ulong end = addr + cnt - 1; + flash_info_t *info_first = addr2info (addr); + flash_info_t *info_last = addr2info (end ); + flash_info_t *info; + + if (cnt == 0) { + return (ERR_OK); + } + + if (!info_first || !info_last) { + return (ERR_INVAL); + } + + for (info = info_first; info <= info_last; ++info) { + ulong b_end = info->start[0] + info->size; /* bank end addr */ + short s_end = info->sector_count - 1; + for (i=0; isector_count; ++i) { + ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; + + if ((end >= info->start[i]) && (addr < e_addr) && + (info->protect[i] != 0) ) { + return (ERR_PROTECTED); + } + } + } + + /* finally write data to flash */ + for (info = info_first; info <= info_last && cnt>0; ++info) { + ulong len; + + len = info->start[0] + info->size - addr; + if (len > cnt) + len = cnt; + if ((i = write_buff(info, (uchar *)src, addr, len)) != 0) { + return (i); + } + cnt -= len; + addr += len; + src += len; + } + return (ERR_OK); +#endif /* CONFIG_SPD823TS */ +} + +/*----------------------------------------------------------------------- + */ + +void flash_perror (int err) +{ + switch (err) { + case ERR_OK: + break; + case ERR_TIMOUT: + puts ("Timeout writing to Flash\n"); + break; + case ERR_NOT_ERASED: + puts ("Flash not Erased\n"); + break; + case ERR_PROTECTED: + puts ("Can't write to protected Flash sectors\n"); + break; + case ERR_INVAL: + puts ("Outside available Flash\n"); + break; + case ERR_ALIGN: + puts ("Start and/or end address not on sector boundary\n"); + break; + case ERR_UNKNOWN_FLASH_VENDOR: + puts ("Unknown Vendor of Flash\n"); + break; + case ERR_UNKNOWN_FLASH_TYPE: + puts ("Unknown Type of Flash\n"); + break; + case ERR_PROG_ERROR: + puts ("General Flash Programming Error\n"); + break; + default: + printf ("%s[%d] FIXME: rc=%d\n", __FILE__, __LINE__, err); + break; + } +} + +/*----------------------------------------------------------------------- + */ +#endif /* !CFG_NO_FLASH */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/Makefile b/package/uboot-ifxmips/files/cpu/mips/danube/Makefile new file mode 100644 index 0000000000..da329b378e --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/Makefile @@ -0,0 +1,49 @@ +# +# (C) Copyright 2003-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = $(obj)lib$(CPU).a + +START = start.o +COBJS = asc_serial.o au1x00_serial.o au1x00_eth.o au1x00_usb_ohci.o \ + cpu.o interrupts.o incaip_clock.o ifx_asc.o ifx_clock.o +SOBJS = incaip_wdt.o cache.o + +SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) +START := $(addprefix $(obj),$(START)) + +all: $(obj).depend $(START) $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c new file mode 100644 index 0000000000..d95ec3fd2f --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.c @@ -0,0 +1,371 @@ +/* + * (INCA) ASC UART support + */ + +#include + +#if defined(CONFIG_PURPLE) || defined(CONFIG_INCA_IP) + +#ifdef CONFIG_PURPLE +#define serial_init asc_serial_init +#define serial_putc asc_serial_putc +#define serial_puts asc_serial_puts +#define serial_getc asc_serial_getc +#define serial_tstc asc_serial_tstc +#define serial_setbrg asc_serial_setbrg +#endif + +#include +#include +#include "asc_serial.h" + +#ifdef CONFIG_PURPLE + +#undef ASC_FIFO_PRESENT +#define TOUT_LOOP 100000 + +/* Set base address for second FPI interrupt control register bank */ +#define SFPI_INTCON_BASEADDR 0xBF0F0000 + +/* Register offset from base address */ +#define FBS_ISR 0x00000000 /* Interrupt status register */ +#define FBS_IMR 0x00000008 /* Interrupt mask register */ +#define FBS_IDIS 0x00000010 /* Interrupt disable register */ + +/* Interrupt status register bits */ +#define FBS_ISR_AT 0x00000040 /* ASC transmit interrupt */ +#define FBS_ISR_AR 0x00000020 /* ASC receive interrupt */ +#define FBS_ISR_AE 0x00000010 /* ASC error interrupt */ +#define FBS_ISR_AB 0x00000008 /* ASC transmit buffer interrupt */ +#define FBS_ISR_AS 0x00000004 /* ASC start of autobaud detection interrupt */ +#define FBS_ISR_AF 0x00000002 /* ASC end of autobaud detection interrupt */ + +#else + +#define ASC_FIFO_PRESENT + +#endif + + +#define SET_BIT(reg, mask) reg |= (mask) +#define CLEAR_BIT(reg, mask) reg &= (~mask) +#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask) +#define SET_BITS(reg, mask) SET_BIT(reg, mask) +#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);} + +extern uint incaip_get_fpiclk(void); + +static int serial_setopt (void); + +/* pointer to ASC register base address */ +static volatile incaAsc_t *pAsc = (incaAsc_t *)INCA_IP_ASC; + +/****************************************************************************** +* +* serial_init - initialize a INCAASC channel +* +* This routine initializes the number of data bits, parity +* and set the selected baud rate. Interrupts are disabled. +* Set the modem control signals if the option is selected. +* +* RETURNS: N/A +*/ + +int serial_init (void) +{ +#ifdef CONFIG_INCA_IP + /* we have to set PMU.EN13 bit to enable an ASC device*/ + INCAASC_PMU_ENABLE(13); +#endif + + /* and we have to set CLC register*/ + CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS); + SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001); + + /* initialy we are in async mode */ + pAsc->asc_con = ASCCON_M_8ASYNC; + + /* select input port */ + pAsc->asc_pisel = (CONSOLE_TTY & 0x1); + +#ifdef ASC_FIFO_PRESENT + /* TXFIFO's filling level */ + SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK, + ASCTXFCON_TXFITLOFF, INCAASC_TXFIFO_FL); + /* enable TXFIFO */ + SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN); + + /* RXFIFO's filling level */ + SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK, + ASCRXFCON_RXFITLOFF, INCAASC_RXFIFO_FL); + /* enable RXFIFO */ + SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN); +#endif + + /* enable error signals */ + SET_BIT(pAsc->asc_con, ASCCON_FEN); + SET_BIT(pAsc->asc_con, ASCCON_OEN); + +#ifdef CONFIG_INCA_IP + /* acknowledge ASC interrupts */ + ASC_INTERRUPTS_CLEAR(INCAASC_IRQ_LINE_ALL); + + /* disable ASC interrupts */ + ASC_INTERRUPTS_DISABLE(INCAASC_IRQ_LINE_ALL); +#endif + +#ifdef ASC_FIFO_PRESENT + /* set FIFOs into the transparent mode */ + SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXTMEN); + SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXTMEN); +#endif + + /* set baud rate */ + serial_setbrg(); + + /* set the options */ + serial_setopt(); + + return 0; +} + +void serial_setbrg (void) +{ + ulong uiReloadValue, fdv; + ulong f_ASC; + +#ifdef CONFIG_INCA_IP + f_ASC = incaip_get_fpiclk(); +#else + f_ASC = ASC_CLOCK_RATE; +#endif + +#ifndef INCAASC_USE_FDV + fdv = 2; + uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1; +#else + fdv = INCAASC_FDV_HIGH_BAUDRATE; + uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1; +#endif /* INCAASC_USE_FDV */ + + if ( (uiReloadValue < 0) || (uiReloadValue > 8191) ) + { +#ifndef INCAASC_USE_FDV + fdv = 3; + uiReloadValue = (f_ASC / (fdv * 16 * CONFIG_BAUDRATE)) - 1; +#else + fdv = INCAASC_FDV_LOW_BAUDRATE; + uiReloadValue = (f_ASC / (8192 * CONFIG_BAUDRATE / fdv)) - 1; +#endif /* INCAASC_USE_FDV */ + + if ( (uiReloadValue < 0) || (uiReloadValue > 8191) ) + { + return; /* can't impossibly generate that baud rate */ + } + } + + /* Disable Baud Rate Generator; BG should only be written when R=0 */ + CLEAR_BIT(pAsc->asc_con, ASCCON_R); + +#ifndef INCAASC_USE_FDV + /* + * Disable Fractional Divider (FDE) + * Divide clock by reload-value + constant (BRS) + */ + /* FDE = 0 */ + CLEAR_BIT(pAsc->asc_con, ASCCON_FDE); + + if ( fdv == 2 ) + CLEAR_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 0 */ + else + SET_BIT(pAsc->asc_con, ASCCON_BRS); /* BRS = 1 */ + +#else /* INCAASC_USE_FDV */ + + /* Enable Fractional Divider */ + SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */ + + /* Set fractional divider value */ + pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK; + +#endif /* INCAASC_USE_FDV */ + + /* Set reload value in BG */ + pAsc->asc_bg = uiReloadValue; + + /* Enable Baud Rate Generator */ + SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */ +} + +/******************************************************************************* +* +* serial_setopt - set the serial options +* +* Set the channel operating mode to that specified. Following options +* are supported: CREAD, CSIZE, PARENB, and PARODD. +* +* Note, this routine disables the transmitter. The calling routine +* may have to re-enable it. +* +* RETURNS: +* Returns 0 to indicate success, otherwise -1 is returned +*/ + +static int serial_setopt (void) +{ + ulong con; + + switch ( ASC_OPTIONS & ASCOPT_CSIZE ) + { + /* 7-bit-data */ + case ASCOPT_CS7: + con = ASCCON_M_7ASYNCPAR; /* 7-bit-data and parity bit */ + break; + + /* 8-bit-data */ + case ASCOPT_CS8: + if ( ASC_OPTIONS & ASCOPT_PARENB ) + con = ASCCON_M_8ASYNCPAR; /* 8-bit-data and parity bit */ + else + con = ASCCON_M_8ASYNC; /* 8-bit-data no parity */ + break; + + /* + * only 7 and 8-bit frames are supported + * if we don't use IOCTL extensions + */ + default: + return -1; + } + + if ( ASC_OPTIONS & ASCOPT_STOPB ) + SET_BIT(con, ASCCON_STP); /* 2 stop bits */ + else + CLEAR_BIT(con, ASCCON_STP); /* 1 stop bit */ + + if ( ASC_OPTIONS & ASCOPT_PARENB ) + SET_BIT(con, ASCCON_PEN); /* enable parity checking */ + else + CLEAR_BIT(con, ASCCON_PEN); /* disable parity checking */ + + if ( ASC_OPTIONS & ASCOPT_PARODD ) + SET_BIT(con, ASCCON_ODD); /* odd parity */ + else + CLEAR_BIT(con, ASCCON_ODD); /* even parity */ + + if ( ASC_OPTIONS & ASCOPT_CREAD ) + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_SETREN); /* Receiver enable */ + + pAsc->asc_con |= con; + + return 0; +} + +void serial_putc (const char c) +{ +#ifdef ASC_FIFO_PRESENT + uint txFl = 0; +#else + uint timeout = 0; +#endif + + if (c == '\n') serial_putc ('\r'); + +#ifdef ASC_FIFO_PRESENT + /* check do we have a free space in the TX FIFO */ + /* get current filling level */ + do + { + txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF; + } + while ( txFl == INCAASC_TXFIFO_FULL ); +#else + + while(!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) & + FBS_ISR_AB)) + { + if (timeout++ > TOUT_LOOP) + { + break; + } + } +#endif + + pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */ + +#ifndef ASC_FIFO_PRESENT + *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AB | + FBS_ISR_AT; +#endif + + /* check for errors */ + if ( pAsc->asc_con & ASCCON_OE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE); + return; + } +} + +void serial_puts (const char *s) +{ + while (*s) + { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + ulong symbol_mask; + char c; + + while (!serial_tstc()); + + symbol_mask = + ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff); + + c = (char)(pAsc->asc_rbuf & symbol_mask); + +#ifndef ASC_FIFO_PRESENT + *(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) = FBS_ISR_AR; +#endif + + return c; +} + +int serial_tstc (void) +{ + int res = 1; + +#ifdef ASC_FIFO_PRESENT + if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ) + { + res = 0; + } +#else + if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) & + FBS_ISR_AR)) + + { + res = 0; + } +#endif + else if ( pAsc->asc_con & ASCCON_FE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE); + res = 0; + } + else if ( pAsc->asc_con & ASCCON_PE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE); + res = 0; + } + else if ( pAsc->asc_con & ASCCON_OE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE); + res = 0; + } + + return res; +} +#endif /* CONFIG_PURPLE || CONFIG_INCA_IP */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h new file mode 100644 index 0000000000..7ffdcfaf8b --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/asc_serial.h @@ -0,0 +1,177 @@ +/* incaAscSio.h - (INCA) ASC UART tty driver header */ + +#ifndef __INCincaAscSioh +#define __INCincaAscSioh + +#include + +/* channel operating modes */ +#define ASCOPT_CSIZE 0x00000003 +#define ASCOPT_CS7 0x00000001 +#define ASCOPT_CS8 0x00000002 +#define ASCOPT_PARENB 0x00000004 +#define ASCOPT_STOPB 0x00000008 +#define ASCOPT_PARODD 0x00000010 +#define ASCOPT_CREAD 0x00000020 + +#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8) + +/* ASC input select (0 or 1) */ +#define CONSOLE_TTY 0 + +/* use fractional divider for baudrate settings */ +#define INCAASC_USE_FDV + +#ifdef INCAASC_USE_FDV + #define INCAASC_FDV_LOW_BAUDRATE 71 + #define INCAASC_FDV_HIGH_BAUDRATE 453 +#endif /*INCAASC_USE_FDV*/ + + +#define INCAASC_TXFIFO_FL 1 +#define INCAASC_RXFIFO_FL 1 +#define INCAASC_TXFIFO_FULL 16 + +/* interrupt lines masks for the ASC device interrupts*/ +/* change these macroses if it's necessary */ +#define INCAASC_IRQ_LINE_ALL 0x000F0000 /* all IRQs */ + +#define INCAASC_IRQ_LINE_TIR 0x00010000 /* TIR - Tx */ +#define INCAASC_IRQ_LINE_RIR 0x00020000 /* RIR - Rx */ +#define INCAASC_IRQ_LINE_EIR 0x00040000 /* EIR - Err */ +#define INCAASC_IRQ_LINE_TBIR 0x00080000 /* TBIR - Tx Buf*/ + +/* interrupt controller access macros */ +#define ASC_INTERRUPTS_ENABLE(X) \ + *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) |= X; +#define ASC_INTERRUPTS_DISABLE(X) \ + *((volatile unsigned int*) INCA_IP_ICU_IM2_IER) &= ~X; +#define ASC_INTERRUPTS_CLEAR(X) \ + *((volatile unsigned int*) INCA_IP_ICU_IM2_ISR) = X; + +/* CLC register's bits and bitfields */ +#define ASCCLC_DISR 0x00000001 +#define ASCCLC_DISS 0x00000002 +#define ASCCLC_RMCMASK 0x0000FF00 +#define ASCCLC_RMCOFFSET 8 + +/* CON register's bits and bitfields */ +#define ASCCON_MODEMASK 0x0007 + #define ASCCON_M_8SYNC 0x0 + #define ASCCON_M_8ASYNC 0x1 + #define ASCCON_M_8IRDAASYNC 0x2 + #define ASCCON_M_7ASYNCPAR 0x3 + #define ASCCON_M_9ASYNC 0x4 + #define ASCCON_M_8WAKEUPASYNC 0x5 + #define ASCCON_M_8ASYNCPAR 0x7 +#define ASCCON_STP 0x0008 +#define ASCCON_REN 0x0010 +#define ASCCON_PEN 0x0020 +#define ASCCON_FEN 0x0040 +#define ASCCON_OEN 0x0080 +#define ASCCON_PE 0x0100 +#define ASCCON_FE 0x0200 +#define ASCCON_OE 0x0400 +#define ASCCON_FDE 0x0800 +#define ASCCON_ODD 0x1000 +#define ASCCON_BRS 0x2000 +#define ASCCON_LB 0x4000 +#define ASCCON_R 0x8000 + +/* WHBCON register's bits and bitfields */ +#define ASCWHBCON_CLRREN 0x0010 +#define ASCWHBCON_SETREN 0x0020 +#define ASCWHBCON_CLRPE 0x0100 +#define ASCWHBCON_CLRFE 0x0200 +#define ASCWHBCON_CLROE 0x0400 +#define ASCWHBCON_SETPE 0x0800 +#define ASCWHBCON_SETFE 0x1000 +#define ASCWHBCON_SETOE 0x2000 + +/* ABCON register's bits and bitfields */ +#define ASCABCON_ABEN 0x0001 +#define ASCABCON_AUREN 0x0002 +#define ASCABCON_ABSTEN 0x0004 +#define ASCABCON_ABDETEN 0x0008 +#define ASCABCON_FCDETEN 0x0010 +#define ASCABCON_EMMASK 0x0300 + #define ASCABCON_EMOFF 8 + #define ASCABCON_EM_DISAB 0x0 + #define ASCABCON_EM_DURAB 0x1 + #define ASCABCON_EM_ALWAYS 0x2 +#define ASCABCON_TXINV 0x0400 +#define ASCABCON_RXINV 0x0800 + +/* FDV register mask, offset and bitfields*/ +#define ASCFDV_VALUE_MASK 0x000001FF + +/* WHBABCON register's bits and bitfields */ +#define ASCWHBABCON_SETABEN 0x0001 +#define ASCWHBABCON_CLRABEN 0x0002 + +/* ABSTAT register's bits and bitfields */ +#define ASCABSTAT_FCSDET 0x0001 +#define ASCABSTAT_FCCDET 0x0002 +#define ASCABSTAT_SCSDET 0x0004 +#define ASCABSTAT_SCCDET 0x0008 +#define ASCABSTAT_DETWAIT 0x0010 + +/* WHBABSTAT register's bits and bitfields */ +#define ASCWHBABSTAT_CLRFCSDET 0x0001 +#define ASCWHBABSTAT_SETFCSDET 0x0002 +#define ASCWHBABSTAT_CLRFCCDET 0x0004 +#define ASCWHBABSTAT_SETFCCDET 0x0008 +#define ASCWHBABSTAT_CLRSCSDET 0x0010 +#define ASCWHBABSTAT_SETSCSDET 0x0020 +#define ASCWHBABSTAT_SETSCCDET 0x0040 +#define ASCWHBABSTAT_CLRSCCDET 0x0080 +#define ASCWHBABSTAT_CLRDETWAIT 0x0100 +#define ASCWHBABSTAT_SETDETWAIT 0x0200 + +/* TXFCON register's bits and bitfields */ +#define ASCTXFCON_TXFEN 0x0001 +#define ASCTXFCON_TXFFLU 0x0002 +#define ASCTXFCON_TXTMEN 0x0004 +#define ASCTXFCON_TXFITLMASK 0x3F00 +#define ASCTXFCON_TXFITLOFF 8 + +/* RXFCON register's bits and bitfields */ +#define ASCRXFCON_RXFEN 0x0001 +#define ASCRXFCON_RXFFLU 0x0002 +#define ASCRXFCON_RXTMEN 0x0004 +#define ASCRXFCON_RXFITLMASK 0x3F00 +#define ASCRXFCON_RXFITLOFF 8 + +/* FSTAT register's bits and bitfields */ +#define ASCFSTAT_RXFFLMASK 0x003F +#define ASCFSTAT_TXFFLMASK 0x3F00 +#define ASCFSTAT_TXFFLOFF 8 + +#define INCAASC_PMU_ENABLE(BIT) *((volatile ulong*)0xBF102000) |= (0x1 << BIT); + +typedef struct /* incaAsc_t */ +{ + volatile unsigned long asc_clc; /*0x0000*/ + volatile unsigned long asc_pisel; /*0x0004*/ + volatile unsigned long asc_rsvd1[2]; /* for mapping */ /*0x0008*/ + volatile unsigned long asc_con; /*0x0010*/ + volatile unsigned long asc_bg; /*0x0014*/ + volatile unsigned long asc_fdv; /*0x0018*/ + volatile unsigned long asc_pmw; /* not used */ /*0x001C*/ + volatile unsigned long asc_tbuf; /*0x0020*/ + volatile unsigned long asc_rbuf; /*0x0024*/ + volatile unsigned long asc_rsvd2[2]; /* for mapping */ /*0x0028*/ + volatile unsigned long asc_abcon; /*0x0030*/ + volatile unsigned long asc_abstat; /* not used */ /*0x0034*/ + volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0038*/ + volatile unsigned long asc_rxfcon; /*0x0040*/ + volatile unsigned long asc_txfcon; /*0x0044*/ + volatile unsigned long asc_fstat; /*0x0048*/ + volatile unsigned long asc_rsvd4; /* for mapping */ /*0x004C*/ + volatile unsigned long asc_whbcon; /*0x0050*/ + volatile unsigned long asc_whbabcon; /*0x0054*/ + volatile unsigned long asc_whbabstat; /* not used */ /*0x0058*/ + +} incaAsc_t; + +#endif /* __INCincaAscSioh */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c new file mode 100644 index 0000000000..078e8328b6 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_eth.c @@ -0,0 +1,311 @@ +/* Only eth0 supported for now + * + * (C) Copyright 2003 + * Thomas.Lange@corelatus.se + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#include + +#ifdef CONFIG_AU1X00 + +#if defined(CFG_DISCOVER_PHY) +#error "PHY not supported yet" +/* We just assume that we are running 100FD for now */ +/* We all use switches, right? ;-) */ +#endif + +/* I assume ethernet behaves like au1000 */ + +#ifdef CONFIG_AU1000 +/* Base address differ between cpu:s */ +#define ETH0_BASE AU1000_ETH0_BASE +#define MAC0_ENABLE AU1000_MAC0_ENABLE +#else +#ifdef CONFIG_AU1100 +#define ETH0_BASE AU1100_ETH0_BASE +#define MAC0_ENABLE AU1100_MAC0_ENABLE +#else +#ifdef CONFIG_AU1500 +#define ETH0_BASE AU1500_ETH0_BASE +#define MAC0_ENABLE AU1500_MAC0_ENABLE +#else +#ifdef CONFIG_AU1550 +#define ETH0_BASE AU1550_ETH0_BASE +#define MAC0_ENABLE AU1550_MAC0_ENABLE +#else +#error "No valid cpu set" +#endif +#endif +#endif +#endif + +#include +#include +#include +#include +#include +#include + +#if (CONFIG_COMMANDS & CFG_CMD_MII) +#include +#endif + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 +#define PKT_MAXBUF_SIZE 1518 + +static char txbuf[DBUF_LENGTH]; + +static int next_tx; +static int next_rx; + +/* 4 rx and 4 tx fifos */ +#define NO_OF_FIFOS 4 + +typedef struct{ + u32 status; + u32 addr; + u32 len; /* Only used for tx */ + u32 not_used; +} mac_fifo_t; + +mac_fifo_t mac_fifo[NO_OF_FIFOS]; + +#define MAX_WAIT 1000 + +static int au1x00_send(struct eth_device* dev, volatile void *packet, int length){ + volatile mac_fifo_t *fifo_tx = + (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS); + int i; + int res; + + /* tx fifo should always be idle */ + fifo_tx[next_tx].len = length; + fifo_tx[next_tx].addr = (virt_to_phys(packet))|TX_DMA_ENABLE; + au_sync(); + + udelay(1); + i=0; + while(!(fifo_tx[next_tx].addr&TX_T_DONE)){ + if(i>MAX_WAIT){ + printf("TX timeout\n"); + break; + } + udelay(1); + i++; + } + + /* Clear done bit */ + fifo_tx[next_tx].addr = 0; + fifo_tx[next_tx].len = 0; + au_sync(); + + res = fifo_tx[next_tx].status; + + next_tx++; + if(next_tx>=NO_OF_FIFOS){ + next_tx=0; + } + return(res); +} + +static int au1x00_recv(struct eth_device* dev){ + volatile mac_fifo_t *fifo_rx = + (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS); + + int length; + u32 status; + + for(;;){ + if(!(fifo_rx[next_rx].addr&RX_T_DONE)){ + /* Nothing has been received */ + return(-1); + } + + status = fifo_rx[next_rx].status; + + length = status&0x3FFF; + + if(status&RX_ERROR){ + printf("Rx error 0x%x\n", status); + } + else{ + /* Pass the packet up to the protocol layers. */ + NetReceive(NetRxPackets[next_rx], length - 4); + } + + fifo_rx[next_rx].addr = (virt_to_phys(NetRxPackets[next_rx]))|RX_DMA_ENABLE; + + next_rx++; + if(next_rx>=NO_OF_FIFOS){ + next_rx=0; + } + } /* for */ + + return(0); /* Does anyone use this? */ +} + +static int au1x00_init(struct eth_device* dev, bd_t * bd){ + + volatile u32 *macen = (volatile u32*)MAC0_ENABLE; + volatile u32 *mac_ctrl = (volatile u32*)(ETH0_BASE+MAC_CONTROL); + volatile u32 *mac_addr_high = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_HIGH); + volatile u32 *mac_addr_low = (volatile u32*)(ETH0_BASE+MAC_ADDRESS_LOW); + volatile u32 *mac_mcast_high = (volatile u32*)(ETH0_BASE+MAC_MCAST_HIGH); + volatile u32 *mac_mcast_low = (volatile u32*)(ETH0_BASE+MAC_MCAST_LOW); + volatile mac_fifo_t *fifo_tx = + (volatile mac_fifo_t*)(MAC0_TX_DMA_ADDR+MAC_TX_BUFF0_STATUS); + volatile mac_fifo_t *fifo_rx = + (volatile mac_fifo_t*)(MAC0_RX_DMA_ADDR+MAC_RX_BUFF0_STATUS); + int i; + + next_tx = TX_GET_DMA_BUFFER(fifo_tx[0].addr); + next_rx = RX_GET_DMA_BUFFER(fifo_rx[0].addr); + + /* We have to enable clocks before releasing reset */ + *macen = MAC_EN_CLOCK_ENABLE; + udelay(10); + + /* Enable MAC0 */ + /* We have to release reset before accessing registers */ + *macen = MAC_EN_CLOCK_ENABLE|MAC_EN_RESET0| + MAC_EN_RESET1|MAC_EN_RESET2; + udelay(10); + + for(i=0;ienetaddr + *mac_addr_high = (ea[5] << 8) | (ea[4] ) ; + *mac_addr_low = (ea[3] << 24) | (ea[2] << 16) | + (ea[1] << 8) | (ea[0] ) ; +#undef ea + *mac_mcast_low = 0; + *mac_mcast_high = 0; + + /* Make sure the MAC buffer is in the correct endian mode */ +#ifdef __LITTLE_ENDIAN + *mac_ctrl = MAC_FULL_DUPLEX; + udelay(1); + *mac_ctrl = MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE; +#else + *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX; + udelay(1); + *mac_ctrl = MAC_BIG_ENDIAN|MAC_FULL_DUPLEX|MAC_RX_ENABLE|MAC_TX_ENABLE; +#endif + + return(1); +} + +static void au1x00_halt(struct eth_device* dev){ +} + +int au1x00_enet_initialize(bd_t *bis){ + struct eth_device* dev; + + if ((dev = (struct eth_device*)malloc(sizeof *dev)) == NULL) { + puts ("malloc failed\n"); + return 0; + } + + memset(dev, 0, sizeof *dev); + + sprintf(dev->name, "Au1X00 ethernet"); + dev->iobase = 0; + dev->priv = 0; + dev->init = au1x00_init; + dev->halt = au1x00_halt; + dev->send = au1x00_send; + dev->recv = au1x00_recv; + + eth_register(dev); + +#if (CONFIG_COMMANDS & CFG_CMD_MII) + miiphy_register(dev->name, + au1x00_miiphy_read, au1x00_miiphy_write); +#endif + + return 1; +} + +#if (CONFIG_COMMANDS & CFG_CMD_MII) +int au1x00_miiphy_read(char *devname, unsigned char addr, + unsigned char reg, unsigned short * value) +{ + volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL); + volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA); + u32 mii_control; + unsigned int timedout = 20; + + while (*mii_control_reg & MAC_MII_BUSY) { + udelay(1000); + if (--timedout == 0) { + printf("au1x00_eth: miiphy_read busy timeout!!\n"); + return -1; + } + } + + mii_control = MAC_SET_MII_SELECT_REG(reg) | + MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_READ; + + *mii_control_reg = mii_control; + + timedout = 20; + while (*mii_control_reg & MAC_MII_BUSY) { + udelay(1000); + if (--timedout == 0) { + printf("au1x00_eth: miiphy_read busy timeout!!\n"); + return -1; + } + } + *value = *mii_data_reg; + return 0; +} + +int au1x00_miiphy_write(char *devname, unsigned char addr, + unsigned char reg, unsigned short value) +{ + volatile u32 *mii_control_reg = (volatile u32*)(ETH0_BASE+MAC_MII_CNTRL); + volatile u32 *mii_data_reg = (volatile u32*)(ETH0_BASE+MAC_MII_DATA); + u32 mii_control; + unsigned int timedout = 20; + + while (*mii_control_reg & MAC_MII_BUSY) { + udelay(1000); + if (--timedout == 0) { + printf("au1x00_eth: miiphy_write busy timeout!!\n"); + return; + } + } + + mii_control = MAC_SET_MII_SELECT_REG(reg) | + MAC_SET_MII_SELECT_PHY(addr) | MAC_MII_WRITE; + + *mii_data_reg = value; + *mii_control_reg = mii_control; + return 0; +} +#endif /* CONFIG_COMMANDS & CFG_CMD_MII */ + +#endif /* CONFIG_AU1X00 */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c new file mode 100644 index 0000000000..42c668ee3d --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_serial.c @@ -0,0 +1,135 @@ +/* + * AU1X00 UART support + * + * Hardcoded to UART 0 for now + * Speed and options also hardcoded to 115200 8N1 + * + * Copyright (c) 2003 Thomas.Lange@corelatus.se + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#ifdef CONFIG_AU1X00 + +#include +#include + +/****************************************************************************** +* +* serial_init - initialize a channel +* +* This routine initializes the number of data bits, parity +* and set the selected baud rate. Interrupts are disabled. +* Set the modem control signals if the option is selected. +* +* RETURNS: N/A +*/ + +int serial_init (void) +{ + volatile u32 *uart_fifoctl = (volatile u32*)(UART0_ADDR+UART_FCR); + volatile u32 *uart_enable = (volatile u32*)(UART0_ADDR+UART_ENABLE); + + /* Enable clocks first */ + *uart_enable = UART_EN_CE; + + /* Then release reset */ + /* Must release reset before setting other regs */ + *uart_enable = UART_EN_CE|UART_EN_E; + + /* Activate fifos, reset tx and rx */ + /* Set tx trigger level to 12 */ + *uart_fifoctl = UART_FCR_ENABLE_FIFO|UART_FCR_CLEAR_RCVR| + UART_FCR_CLEAR_XMIT|UART_FCR_T_TRIGGER_12; + + serial_setbrg(); + + return 0; +} + + +void serial_setbrg (void) +{ + volatile u32 *uart_clk = (volatile u32*)(UART0_ADDR+UART_CLK); + volatile u32 *uart_lcr = (volatile u32*)(UART0_ADDR+UART_LCR); + volatile u32 *sys_powerctrl = (u32 *)SYS_POWERCTRL; + int sd; + int divisorx2; + + /* sd is system clock divisor */ + /* see section 10.4.5 in au1550 datasheet */ + sd = (*sys_powerctrl & 0x03) + 2; + + /* calulate 2x baudrate and round */ + divisorx2 = ((CFG_HZ/(sd * 16 * CONFIG_BAUDRATE))); + + if (divisorx2 & 0x01) + divisorx2 = divisorx2 + 1; + + *uart_clk = divisorx2 / 2; + + /* Set parity, stop bits and word length to 8N1 */ + *uart_lcr = UART_LCR_WLEN8; +} + +void serial_putc (const char c) +{ + volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); + volatile u32 *uart_tx = (volatile u32*)(UART0_ADDR+UART_TX); + + if (c == '\n') serial_putc ('\r'); + + /* Wait for fifo to shift out some bytes */ + while((*uart_lsr&UART_LSR_THRE)==0); + + *uart_tx = (u32)c; +} + +void serial_puts (const char *s) +{ + while (*s) + { + serial_putc (*s++); + } +} + +int serial_getc (void) +{ + volatile u32 *uart_rx = (volatile u32*)(UART0_ADDR+UART_RX); + char c; + + while (!serial_tstc()); + + c = (*uart_rx&0xFF); + return c; +} + +int serial_tstc (void) +{ + volatile u32 *uart_lsr = (volatile u32*)(UART0_ADDR+UART_LSR); + + if(*uart_lsr&UART_LSR_DR){ + /* Data in rfifo */ + return(1); + } + return 0; +} +#endif /* CONFIG_SERIAL_AU1X00 */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c new file mode 100644 index 0000000000..dbf72dc6f8 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.c @@ -0,0 +1,1727 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the AU1x00. + * + * (C) Copyright 2003 + * Gary Jennejohn, DENX Software Engineering + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + * + * Note: Part of this code has been derived from linux + * + */ +/* + * IMPORTANT NOTES + * 1 - you MUST define LITTLEENDIAN in the configuration file for the + * board or this driver will NOT work! + * 2 - this driver is intended for use with USB Mass Storage Devices + * (BBB) ONLY. There is NO support for Interrupt or Isochronous pipes! + */ + +#include + +#if defined(CONFIG_AU1X00) && defined(CONFIG_USB_OHCI) + +/* #include no PCI on the AU1x00 */ + +#include +#include +#include +#include +#include +#include "au1x00_usb_ohci.h" + +#define OHCI_USE_NPS /* force NoPowerSwitching mode */ +#define OHCI_VERBOSE_DEBUG /* not always helpful */ +#define OHCI_FILL_TRACE + +#define USBH_ENABLE_BE (1<<0) +#define USBH_ENABLE_C (1<<1) +#define USBH_ENABLE_E (1<<2) +#define USBH_ENABLE_CE (1<<3) +#define USBH_ENABLE_RD (1<<4) + +#ifdef LITTLEENDIAN +#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C) +#else +#define USBH_ENABLE_INIT (USBH_ENABLE_CE | USBH_ENABLE_E | USBH_ENABLE_C | USBH_ENABLE_BE) +#endif + + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + (OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE + +#undef readl +#undef writel + +#define readl(a) au_readl((long)(a)) +#define writel(v,a) au_writel((v),(int)(a)) + +#define min_t(type,x,y) ({ type __x = (x); type __y = (y); __x < __y ? __x: __y; }) + +#define DEBUG +#ifdef DEBUG +#define dbg(format, arg...) printf("DEBUG: " format "\n", ## arg) +#else +#define dbg(format, arg...) do {} while(0) +#endif /* DEBUG */ +#define err(format, arg...) printf("ERROR: " format "\n", ## arg) +#define SHOW_INFO +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format "\n", ## arg) +#else +#define info(format, arg...) do {} while(0) +#endif + +#define m16_swap(x) swap_16(x) +#define m32_swap(x) swap_32(x) + +/* global ohci_t */ +static ohci_t gohci; +/* this must be aligned to a 256 byte boundary */ +struct ohci_hcca ghcca[1]; +/* a pointer to the aligned storage */ +struct ohci_hcca *phcca; +/* this allocates EDs for all possible endpoints */ +struct ohci_device ohci_dev; +/* urb_priv */ +urb_priv_t urb_priv; +/* RHSC flag */ +int got_rhsc; +/* device which was disconnected */ +struct usb_device *devgone; + +/*-------------------------------------------------------------------------*/ + +/* AMD-756 (D2 rev) reports corrupt register contents in some cases. + * The erratum (#4) description is incorrect. AMD's workaround waits + * till some bits (mostly reserved) are clear; ok for all revs. + */ +#define OHCI_QUIRK_AMD756 0xabcd +#define read_roothub(hc, register, mask) ({ \ + u32 temp = readl (&hc->regs->roothub.register); \ + if (hc->flags & OHCI_QUIRK_AMD756) \ + while (temp & mask) \ + temp = readl (&hc->regs->roothub.register); \ + temp; }) + +static u32 roothub_a (struct ohci *hc) + { return read_roothub (hc, a, 0xfc0fe000); } +static inline u32 roothub_b (struct ohci *hc) + { return readl (&hc->regs->roothub.b); } +static inline u32 roothub_status (struct ohci *hc) + { return readl (&hc->regs->roothub.status); } +static u32 roothub_portstatus (struct ohci *hc, int i) + { return read_roothub (hc, portstatus [i], 0xffe0fce0); } + + +/* forward declaration */ +static int hc_interrupt (void); +static void +td_submit_job (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, urb_priv_t * urb, int interval); + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv (urb_priv_t * urb) +{ + int i; + int last; + struct td * td; + + last = urb->length - 1; + if (last >= 0) { + for (i = 0; i <= last; i++) { + td = urb->td[i]; + if (td) { + td->usb_dev = NULL; + urb->td[i] = NULL; + } + } + } +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +static int sohci_get_current_frame_number (struct usb_device * dev); + +/* debug| print the main components of an URB + * small: 0) header + data packets 1) just header */ + +static void pkt_print (struct usb_device * dev, unsigned long pipe, void * buffer, + int transfer_len, struct devrequest * setup, char * str, int small) +{ + urb_priv_t * purb = &urb_priv; + + dbg("%s URB:[%4x] dev:%2d,ep:%2d-%c,type:%s,len:%d/%d stat:%#lx", + str, + sohci_get_current_frame_number (dev), + usb_pipedevice (pipe), + usb_pipeendpoint (pipe), + usb_pipeout (pipe)? 'O': 'I', + usb_pipetype (pipe) < 2? (usb_pipeint (pipe)? "INTR": "ISOC"): + (usb_pipecontrol (pipe)? "CTRL": "BULK"), + purb->actual_length, + transfer_len, dev->status); +#ifdef OHCI_VERBOSE_DEBUG + if (!small) { + int i, len; + + if (usb_pipecontrol (pipe)) { + printf (__FILE__ ": cmd(8):"); + for (i = 0; i < 8 ; i++) + printf (" %02x", ((__u8 *) setup) [i]); + printf ("\n"); + } + if (transfer_len > 0 && buffer) { + printf (__FILE__ ": data(%d/%d):", + purb->actual_length, + transfer_len); + len = usb_pipeout (pipe)? + transfer_len: purb->actual_length; + for (i = 0; i < 16 && i < len; i++) + printf (" %02x", ((__u8 *) buffer) [i]); + printf ("%s\n", i < len? "...": ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree inclusive iso eds*/ +void ep_print_int_eds (ohci_t *ohci, char * str) { + int i, j; + __u32 * ed_p; + for (i= 0; i < 32; i++) { + j = 5; + ed_p = &(ohci->hcca->int_table [i]); + if (*ed_p == 0) + continue; + printf (__FILE__ ": %s branch int %2d(%2x):", str, i, i); + while (*ed_p != 0 && j--) { + ed_t *ed = (ed_t *)m32_swap(ed_p); + printf (" ed: %4x;", ed->hwINFO); + ed_p = &ed->hwNextED; + } + printf ("\n"); + } +} + +static void ohci_dump_intr_mask (char *label, __u32 mask) +{ + dbg ("%s: 0x%08x%s%s%s%s%s%s%s%s%s", + label, + mask, + (mask & OHCI_INTR_MIE) ? " MIE" : "", + (mask & OHCI_INTR_OC) ? " OC" : "", + (mask & OHCI_INTR_RHSC) ? " RHSC" : "", + (mask & OHCI_INTR_FNO) ? " FNO" : "", + (mask & OHCI_INTR_UE) ? " UE" : "", + (mask & OHCI_INTR_RD) ? " RD" : "", + (mask & OHCI_INTR_SF) ? " SF" : "", + (mask & OHCI_INTR_WDH) ? " WDH" : "", + (mask & OHCI_INTR_SO) ? " SO" : "" + ); +} + +static void maybe_print_eds (char *label, __u32 value) +{ + ed_t *edp = (ed_t *)value; + + if (value) { + dbg ("%s %08x", label, value); + dbg ("%08x", edp->hwINFO); + dbg ("%08x", edp->hwTailP); + dbg ("%08x", edp->hwHeadP); + dbg ("%08x", edp->hwNextED); + } +} + +static char * hcfs2string (int state) +{ + switch (state) { + case OHCI_USB_RESET: return "reset"; + case OHCI_USB_RESUME: return "resume"; + case OHCI_USB_OPER: return "operational"; + case OHCI_USB_SUSPEND: return "suspend"; + } + return "?"; +} + +/* dump control and status registers */ +static void ohci_dump_status (ohci_t *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl (®s->revision) & 0xff; + if (temp != 0x10) + dbg ("spec %d.%d", (temp >> 4), (temp & 0x0f)); + + temp = readl (®s->control); + dbg ("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d", temp, + (temp & OHCI_CTRL_RWE) ? " RWE" : "", + (temp & OHCI_CTRL_RWC) ? " RWC" : "", + (temp & OHCI_CTRL_IR) ? " IR" : "", + hcfs2string (temp & OHCI_CTRL_HCFS), + (temp & OHCI_CTRL_BLE) ? " BLE" : "", + (temp & OHCI_CTRL_CLE) ? " CLE" : "", + (temp & OHCI_CTRL_IE) ? " IE" : "", + (temp & OHCI_CTRL_PLE) ? " PLE" : "", + temp & OHCI_CTRL_CBSR + ); + + temp = readl (®s->cmdstatus); + dbg ("cmdstatus: 0x%08x SOC=%d%s%s%s%s", temp, + (temp & OHCI_SOC) >> 16, + (temp & OHCI_OCR) ? " OCR" : "", + (temp & OHCI_BLF) ? " BLF" : "", + (temp & OHCI_CLF) ? " CLF" : "", + (temp & OHCI_HCR) ? " HCR" : "" + ); + + ohci_dump_intr_mask ("intrstatus", readl (®s->intrstatus)); + ohci_dump_intr_mask ("intrenable", readl (®s->intrenable)); + + maybe_print_eds ("ed_periodcurrent", readl (®s->ed_periodcurrent)); + + maybe_print_eds ("ed_controlhead", readl (®s->ed_controlhead)); + maybe_print_eds ("ed_controlcurrent", readl (®s->ed_controlcurrent)); + + maybe_print_eds ("ed_bulkhead", readl (®s->ed_bulkhead)); + maybe_print_eds ("ed_bulkcurrent", readl (®s->ed_bulkcurrent)); + + maybe_print_eds ("donehead", readl (®s->donehead)); +} + +static void ohci_dump_roothub (ohci_t *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + + if (verbose) { + dbg ("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d", temp, + ((temp & RH_A_POTPGT) >> 24) & 0xff, + (temp & RH_A_NOCP) ? " NOCP" : "", + (temp & RH_A_OCPM) ? " OCPM" : "", + (temp & RH_A_DT) ? " DT" : "", + (temp & RH_A_NPS) ? " NPS" : "", + (temp & RH_A_PSM) ? " PSM" : "", + ndp + ); + temp = roothub_b (controller); + dbg ("roothub.b: %08x PPCM=%04x DR=%04x", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status (controller); + dbg ("roothub.status: %08x%s%s%s%s%s%s", + temp, + (temp & RH_HS_CRWE) ? " CRWE" : "", + (temp & RH_HS_OCIC) ? " OCIC" : "", + (temp & RH_HS_LPSC) ? " LPSC" : "", + (temp & RH_HS_DRWE) ? " DRWE" : "", + (temp & RH_HS_OCI) ? " OCI" : "", + (temp & RH_HS_LPS) ? " LPS" : "" + ); + } + + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + dbg ("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s", + i, + temp, + (temp & RH_PS_PRSC) ? " PRSC" : "", + (temp & RH_PS_OCIC) ? " OCIC" : "", + (temp & RH_PS_PSSC) ? " PSSC" : "", + (temp & RH_PS_PESC) ? " PESC" : "", + (temp & RH_PS_CSC) ? " CSC" : "", + + (temp & RH_PS_LSDA) ? " LSDA" : "", + (temp & RH_PS_PPS) ? " PPS" : "", + (temp & RH_PS_PRS) ? " PRS" : "", + (temp & RH_PS_POCI) ? " POCI" : "", + (temp & RH_PS_PSS) ? " PSS" : "", + + (temp & RH_PS_PES) ? " PES" : "", + (temp & RH_PS_CCS) ? " CCS" : "" + ); + } +} + +static void ohci_dump (ohci_t *controller, int verbose) +{ + dbg ("OHCI controller usb-%s state", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status (controller); + if (verbose) + ep_print_int_eds (controller, "hcca"); + dbg ("hcca frame #%04x", controller->hcca->frame_no); + ohci_dump_roothub (controller, 1); +} + + +#endif /* DEBUG */ + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + ohci_t *ohci; + ed_t * ed; + urb_priv_t *purb_priv; + int i, size = 0; + + ohci = &gohci; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) { + err("sohci_submit_job: EPIPE"); + return -1; + } + + /* every endpoint has a ed, locate and fill it */ + if (!(ed = ep_add_ed (dev, pipe))) { + err("sohci_submit_job: ENOMEM"); + return -1; + } + + /* for the private part of the URB we need the number of TDs (size) */ + switch (usb_pipetype (pipe)) { + case PIPE_BULK: /* one TD for every 4096 Byte */ + size = (transfer_len - 1) / 4096 + 1; + break; + case PIPE_CONTROL: /* 1 TD for setup, 1 for ACK and 1 for every 4096 B */ + size = (transfer_len == 0)? 2: + (transfer_len - 1) / 4096 + 3; + break; + } + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d", size, N_URB_TD); + return -1; + } + purb_priv = &urb_priv; + purb_priv->pipe = pipe; + + /* fill the private part of the URB */ + purb_priv->length = size; + purb_priv->ed = ed; + purb_priv->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + purb_priv->td[i] = td_alloc (dev); + if (!purb_priv->td[i]) { + purb_priv->length = i; + urb_free_priv (purb_priv); + err("sohci_submit_job: ENOMEM"); + return -1; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv (purb_priv); + err("sohci_submit_job: EINVAL"); + return -1; + } + + /* link the ed into a chain if is not already */ + if (ed->state != ED_OPER) + ep_link (ohci, ed); + + /* fill the TDs and link it to the ed */ + td_submit_job(dev, pipe, buffer, transfer_len, setup, purb_priv, interval); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#ifdef DEBUG +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number (struct usb_device *usb_dev) +{ + ohci_t *ohci = &gohci; + + return m16_swap (ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link (ohci_t *ohci, ed_t *edi) +{ + volatile ed_t *ed = edi; + + ed->state = ED_OPER; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) { + writel ((long)ed, &ohci->regs->ed_controlhead); + } else { + ohci->ed_controltail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_controltail = edi; + break; + + case PIPE_BULK: + ed->hwNextED = 0; + if (ohci->ed_bulktail == NULL) { + writel ((long)ed, &ohci->regs->ed_bulkhead); + } else { + ohci->ed_bulktail->hwNextED = m32_swap (ed); + } + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1] && !ohci->sleeping) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* unlink an ed from one of the HC chains. + * 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 */ + +static int ep_unlink (ohci_t *ohci, ed_t *ed) +{ + ed->hwINFO |= m32_swap (OHCI_ED_SKIP); + + switch (ed->type) { + case PIPE_CONTROL: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_CLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_controlhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_controltail == ed) { + ohci->ed_controltail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_BULK: + if (ed->ed_prev == NULL) { + if (!ed->hwNextED) { + ohci->hc_control &= ~OHCI_CTRL_BLE; + writel (ohci->hc_control, &ohci->regs->control); + } + writel (m32_swap (*((__u32 *)&ed->hwNextED)), &ohci->regs->ed_bulkhead); + } else { + ed->ed_prev->hwNextED = ed->hwNextED; + } + if (ohci->ed_bulktail == ed) { + ohci->ed_bulktail = ed->ed_prev; + } else { + ((ed_t *)m32_swap (*((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + } + ed->state = ED_UNLINK; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* add/reinit an endpoint; this should be done once at the usb_set_configuration command, + * but the USB stack is a little bit stateless so we do it at every transaction + * if the state of the ed is ED_NEW then a dummy td is added and the state is changed to ED_UNLINK + * in all other cases the state is left unchanged + * the ed info fields are setted anyway even though most of them should not change */ + +static ed_t * ep_add_ed (struct usb_device *usb_dev, unsigned long pipe) +{ + td_t *td; + ed_t *ed_ret; + volatile ed_t *ed; + + ed = ed_ret = &ohci_dev.ed[(usb_pipeendpoint (pipe) << 1) | + (usb_pipecontrol (pipe)? 0: usb_pipeout (pipe))]; + + if ((ed->state & ED_DEL) || (ed->state & ED_URB_DEL)) { + err("ep_add_ed: pending delete"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + ed->hwINFO = m32_swap (OHCI_ED_SKIP); /* skip ed */ + /* dummy td; end of td list for ed */ + td = td_alloc (usb_dev); + ed->hwTailP = m32_swap (td); + ed->hwHeadP = ed->hwTailP; + ed->state = ED_UNLINK; + ed->type = usb_pipetype (pipe); + ohci_dev.ed_cnt++; + } + + ed->hwINFO = m32_swap (usb_pipedevice (pipe) + | usb_pipeendpoint (pipe) << 7 + | (usb_pipeisoc (pipe)? 0x8000: 0) + | (usb_pipecontrol (pipe)? 0: (usb_pipeout (pipe)? 0x800: 0x1000)) + | usb_pipeslow (pipe) << 13 + | usb_maxpacket (usb_dev, pipe) << 16); + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* enqueue next TD for this URB (OHCI spec 5.2.8.2) */ + +static void td_fill (ohci_t *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, urb_priv_t *urb_priv) +{ + volatile td_t *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + + if (index > urb_priv->length) { + err("index > length"); + return; + } + /* use this td as the next dummy */ + td_pt = urb_priv->td [index]; + td_pt->hwNextTD = 0; + + /* fill the old dummy TD */ + td = urb_priv->td [index] = (td_t *)(m32_swap (urb_priv->ed->hwTailP) & ~0xf); + + td->ed = urb_priv->ed; + td->next_dl_td = NULL; + td->index = index; + td->data = (__u32)data; +#ifdef OHCI_FILL_TRACE + if (1 || ((usb_pipetype(urb_priv->pipe) == PIPE_BULK) && usb_pipeout(urb_priv->pipe))) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x\n",i, ((unsigned char *)(td->data+0x80000000))[i]); + } +#endif + if (!len) + data = 0; + + td->hwINFO = m32_swap (info); + td->hwCBP = m32_swap (data); + if (data) + td->hwBE = m32_swap (data + len - 1); + else + td->hwBE = 0; + td->hwNextTD = m32_swap (td_pt); + td->hwPSW [0] = m16_swap (((__u32)data & 0x0FFF) | 0xE000); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/*-------------------------------------------------------------------------*/ + +/* prepare all TDs of a transfer */ + +#define kseg_to_phys(x) ((void *)((__u32)(x) - 0x80000000)) + +static void td_submit_job (struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, urb_priv_t *urb, int interval) +{ + ohci_t *ohci = &gohci; + int data_len = transfer_len; + void *data; + int cnt = 0; + __u32 info = 0; + unsigned int toggle = 0; + + /* OHCI handles the DATA-toggles itself, we just use the USB-toggle bits for reseting */ + if(usb_gettoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe))) { + toggle = TD_T_TOGGLE; + } else { + toggle = TD_T_DATA0; + usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 1); + } + urb->td_cnt = 0; + if (data_len) + data = kseg_to_phys(buffer); + else + data = 0; + + switch (usb_pipetype (pipe)) { + case PIPE_BULK: + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ; + while(data_len > 4096) { + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, 4096, dev, cnt, urb); + data += 4096; data_len -= 4096; cnt++; + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ; + td_fill (ohci, info | (cnt? TD_T_TOGGLE:toggle), data, data_len, dev, cnt, urb); + cnt++; + + if (!ohci->sleeping) + writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */ + break; + + case PIPE_CONTROL: + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill (ohci, info, kseg_to_phys(setup), 8, dev, cnt++, urb); + if (data_len > 0) { + info = usb_pipeout (pipe)? + TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1; + /* NOTE: mishandles transfers >8K, some >4K */ + td_fill (ohci, info, data, data_len, dev, cnt++, urb); + } + info = usb_pipeout (pipe)? + TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1; + td_fill (ohci, info, data, 0, dev, cnt++, urb); + if (!ohci->sleeping) + writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */ + break; + } + if (urb->length != cnt) + dbg("TD LENGTH %d != CNT %d", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(td_t * td) +{ + __u32 tdINFO, tdBE, tdCBP; + urb_priv_t *lurb_priv = &urb_priv; + + tdINFO = m32_swap (td->hwINFO); + tdBE = m32_swap (td->hwBE); + tdCBP = m32_swap (td->hwCBP); + + + if (!(usb_pipetype (lurb_priv->pipe) == PIPE_CONTROL && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + if (tdBE != 0) { + if (td->hwCBP == 0) + lurb_priv->actual_length += tdBE - td->data + 1; + else + lurb_priv->actual_length += tdCBP - td->data; + } + } +} + +/*-------------------------------------------------------------------------*/ + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ + +static td_t * dl_reverse_done_list (ohci_t *ohci) +{ + __u32 td_list_hc; + td_t *td_rev = NULL; + td_t *td_list = NULL; + urb_priv_t *lurb_priv = NULL; + + td_list_hc = m32_swap (ohci->hcca->done_head) & 0xfffffff0; + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = (td_t *)td_list_hc; + + if (TD_CC_GET (m32_swap (td_list->hwINFO))) { + lurb_priv = &urb_priv; + dbg(" USB-error/status: %x : %p", + TD_CC_GET (m32_swap (td_list->hwINFO)), td_list); + if (td_list->ed->hwHeadP & m32_swap (0x1)) { + if (lurb_priv && ((td_list->index + 1) < lurb_priv->length)) { + td_list->ed->hwHeadP = + (lurb_priv->td[lurb_priv->length - 1]->hwNextTD & m32_swap (0xfffffff0)) | + (td_list->ed->hwHeadP & m32_swap (0x2)); + lurb_priv->td_cnt += lurb_priv->length - td_list->index - 1; + } else + td_list->ed->hwHeadP &= m32_swap (0xfffffff2); + } + } + + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = m32_swap (td_list->hwNextTD) & 0xfffffff0; + } + return td_list; +} + +/*-------------------------------------------------------------------------*/ + +/* td done list */ +static int dl_done_list (ohci_t *ohci, td_t *td_list) +{ + td_t *td_list_next = NULL; + ed_t *ed; + int cc = 0; + int stat = 0; + /* urb_t *urb; */ + urb_priv_t *lurb_priv; + __u32 tdINFO, edHeadP, edTailP; + + while (td_list) { + td_list_next = td_list->next_dl_td; + + lurb_priv = &urb_priv; + tdINFO = m32_swap (td_list->hwINFO); + + ed = td_list->ed; + + dl_transfer_length(td_list); + + /* error code of transfer */ + cc = TD_CC_GET (tdINFO); + if (cc != 0) { + dbg("ConditionCode %#x", cc); + stat = cc_to_error[cc]; + } + + if (ed->state != ED_NEW) { + edHeadP = m32_swap (ed->hwHeadP) & 0xfffffff0; + edTailP = m32_swap (ed->hwTailP); + + /* unlink eds if they are not busy */ + if ((edHeadP == edTailP) && (ed->state == ED_OPER)) + ep_unlink (ohci, ed); + } + + td_list = td_list_next; + } + return stat; +} + +/*-------------------------------------------------------------------------* + * Virtual Root Hub + *-------------------------------------------------------------------------*/ + +/* Device descriptor */ +static __u8 root_hub_dev_des[] = +{ + 0x12, /* __u8 bLength; */ + 0x01, /* __u8 bDescriptorType; Device */ + 0x10, /* __u16 bcdUSB; v1.1 */ + 0x01, + 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ + 0x00, /* __u8 bDeviceSubClass; */ + 0x00, /* __u8 bDeviceProtocol; */ + 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ + 0x00, /* __u16 idVendor; */ + 0x00, + 0x00, /* __u16 idProduct; */ + 0x00, + 0x00, /* __u16 bcdDevice; */ + 0x00, + 0x00, /* __u8 iManufacturer; */ + 0x01, /* __u8 iProduct; */ + 0x00, /* __u8 iSerialNumber; */ + 0x01 /* __u8 bNumConfigurations; */ +}; + + +/* Configuration descriptor */ +static __u8 root_hub_config_des[] = +{ + 0x09, /* __u8 bLength; */ + 0x02, /* __u8 bDescriptorType; Configuration */ + 0x19, /* __u16 wTotalLength; */ + 0x00, + 0x01, /* __u8 bNumInterfaces; */ + 0x01, /* __u8 bConfigurationValue; */ + 0x00, /* __u8 iConfiguration; */ + 0x40, /* __u8 bmAttributes; + Bit 7: Bus-powered, 6: Self-powered, 5 Remote-wakwup, 4..0: resvd */ + 0x00, /* __u8 MaxPower; */ + + /* interface */ + 0x09, /* __u8 if_bLength; */ + 0x04, /* __u8 if_bDescriptorType; Interface */ + 0x00, /* __u8 if_bInterfaceNumber; */ + 0x00, /* __u8 if_bAlternateSetting; */ + 0x01, /* __u8 if_bNumEndpoints; */ + 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ + 0x00, /* __u8 if_bInterfaceSubClass; */ + 0x00, /* __u8 if_bInterfaceProtocol; */ + 0x00, /* __u8 if_iInterface; */ + + /* endpoint */ + 0x07, /* __u8 ep_bLength; */ + 0x05, /* __u8 ep_bDescriptorType; Endpoint */ + 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ + 0x03, /* __u8 ep_bmAttributes; Interrupt */ + 0x02, /* __u16 ep_wMaxPacketSize; ((MAX_ROOT_PORTS + 1) / 8 */ + 0x00, + 0xff /* __u8 ep_bInterval; 255 ms */ +}; + +static unsigned char root_hub_str_index0[] = +{ + 0x04, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 0x09, /* __u8 lang ID */ + 0x04, /* __u8 lang ID */ +}; + +static unsigned char root_hub_str_index1[] = +{ + 28, /* __u8 bLength; */ + 0x03, /* __u8 bDescriptorType; String-descriptor */ + 'O', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'C', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'I', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'R', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'o', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 't', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + ' ', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'H', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'u', /* __u8 Unicode */ + 0, /* __u8 Unicode */ + 'b', /* __u8 Unicode */ + 0, /* __u8 Unicode */ +}; + +/* Hub class-specific descriptor is constructed dynamically */ + + +/*-------------------------------------------------------------------------*/ + +#define OK(x) len = (x); break +#ifdef DEBUG +#define WR_RH_STAT(x) {info("WR:status %#8x", (x));writel((x), &gohci.regs->roothub.status);} +#define WR_RH_PORTSTAT(x) {info("WR:portstatus[%d] %#8x", wIndex-1, (x));writel((x), &gohci.regs->roothub.portstatus[wIndex-1]);} +#else +#define WR_RH_STAT(x) writel((x), &gohci.regs->roothub.status) +#define WR_RH_PORTSTAT(x) writel((x), &gohci.regs->roothub.portstatus[wIndex-1]) +#endif +#define RD_RH_STAT roothub_status(&gohci) +#define RD_RH_PORTSTAT roothub_portstatus(&gohci,wIndex-1) + +/* request to virtual root hub */ + +int rh_check_port_status(ohci_t *controller) +{ + __u32 temp, ndp, i; + int res; + + res = -1; + temp = roothub_a (controller); + ndp = (temp & RH_A_NDP); + for (i = 0; i < ndp; i++) { + temp = roothub_portstatus (controller, i); + /* check for a device disconnect */ + if (((temp & (RH_PS_PESC | RH_PS_CSC)) == + (RH_PS_PESC | RH_PS_CSC)) && + ((temp & RH_PS_CCS) == 0)) { + res = i; + break; + } + } + return res; +} + +static int ohci_submit_rh_msg(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, struct devrequest *cmd) +{ + void * data = buffer; + int leni = transfer_len; + int len = 0; + int stat = 0; + __u32 datab[4]; + __u8 *data_buf = (__u8 *)datab; + __u16 bmRType_bReq; + __u16 wValue; + __u16 wIndex; + __u16 wLength; + +#ifdef DEBUG +urb_priv.actual_length = 0; +pkt_print(dev, pipe, buffer, transfer_len, cmd, "SUB(rh)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if ((pipe & PIPE_INTERRUPT) == PIPE_INTERRUPT) { + info("Root-Hub submit IRQ: NOT implemented"); + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = m16_swap (cmd->value); + wIndex = m16_swap (cmd->index); + wLength = m16_swap (cmd->length); + + info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x", + dev->devnum, 8, bmRType_bReq, wValue, wIndex, wLength); + + switch (bmRType_bReq) { + /* Request Destination: + without flags: Device, + RH_INTERFACE: interface, + RH_ENDPOINT: endpoint, + RH_CLASS means HUB here, + RH_OTHER | RH_CLASS almost ever means HUB_PORT here + */ + + case RH_GET_STATUS: + *(__u16 *) data_buf = m16_swap (1); OK (2); + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = m16_swap (0); OK (2); + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = m32_swap ( + RD_RH_STAT & ~(RH_HS_CRWE | RH_HS_DRWE)); + OK (4); + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = m32_swap (RD_RH_PORTSTAT); OK (4); + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case (RH_ENDPOINT_STALL): OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + OK(0); + case (RH_C_HUB_OVER_CURRENT): + WR_RH_STAT(RH_HS_OCIC); OK (0); + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_CCS ); OK (0); + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_POCI); OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_LSDA); OK (0); + case (RH_C_PORT_CONNECTION): + WR_RH_PORTSTAT (RH_PS_CSC ); OK (0); + case (RH_C_PORT_ENABLE): + WR_RH_PORTSTAT (RH_PS_PESC); OK (0); + case (RH_C_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSSC); OK (0); + case (RH_C_PORT_OVER_CURRENT): + WR_RH_PORTSTAT (RH_PS_OCIC); OK (0); + case (RH_C_PORT_RESET): + WR_RH_PORTSTAT (RH_PS_PRSC); OK (0); + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case (RH_PORT_SUSPEND): + WR_RH_PORTSTAT (RH_PS_PSS ); OK (0); + case (RH_PORT_RESET): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PRS); + OK (0); + case (RH_PORT_POWER): + WR_RH_PORTSTAT (RH_PS_PPS ); OK (0); + case (RH_PORT_ENABLE): /* BUG IN HUP CODE *********/ + if (RD_RH_PORTSTAT & RH_PS_CCS) + WR_RH_PORTSTAT (RH_PS_PES ); + OK (0); + } + break; + + case RH_SET_ADDRESS: gohci.rh.devnum = wValue; OK(0); + + case RH_GET_DESCRIPTOR: + switch ((wValue & 0xff00) >> 8) { + case (0x01): /* device descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_dev_des), + wLength)); + data_buf = root_hub_dev_des; OK(len); + case (0x02): /* configuration descriptor */ + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_config_des), + wLength)); + data_buf = root_hub_config_des; OK(len); + case (0x03): /* string descriptors */ + if(wValue==0x0300) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index0), + wLength)); + data_buf = root_hub_str_index0; + OK(len); + } + if(wValue==0x0301) { + len = min_t(unsigned int, + leni, + min_t(unsigned int, + sizeof (root_hub_str_index1), + wLength)); + data_buf = root_hub_str_index1; + OK(len); + } + default: + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a (&gohci); + + data_buf [0] = 9; /* min length; */ + data_buf [1] = 0x29; + data_buf [2] = temp & RH_A_NDP; + data_buf [3] = 0; + if (temp & RH_A_PSM) /* per-port power switching? */ + data_buf [3] |= 0x1; + if (temp & RH_A_NOCP) /* no overcurrent reporting? */ + data_buf [3] |= 0x10; + else if (temp & RH_A_OCPM) /* per-port overcurrent reporting? */ + data_buf [3] |= 0x8; + + /* corresponds to data_buf[4-7] */ + datab [1] = 0; + data_buf [5] = (temp & RH_A_POTPGT) >> 24; + temp = roothub_b (&gohci); + data_buf [7] = temp & RH_B_DR; + if (data_buf [2] < 7) { + data_buf [8] = 0xff; + } else { + data_buf [0] += 2; + data_buf [8] = (temp & RH_B_DR) >> 8; + data_buf [10] = data_buf [9] = 0xff; + } + + len = min_t(unsigned int, leni, + min_t(unsigned int, data_buf [0], wLength)); + OK (len); + } + + case RH_GET_CONFIGURATION: *(__u8 *) data_buf = 0x01; OK (1); + + case RH_SET_CONFIGURATION: WR_RH_STAT (0x10000); OK (0); + + default: + dbg ("unsupported root hub command"); + stat = USB_ST_STALLED; + } + +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#else + wait_ms(1); +#endif + + len = min_t(int, len, leni); + if (data != data_buf) + memcpy (data, data_buf, len); + dev->act_len = len; + dev->status = stat; + +#ifdef DEBUG + if (transfer_len) + urb_priv.actual_length = transfer_len; + pkt_print(dev, pipe, buffer, transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); +#else + wait_ms(1); +#endif + + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/* common code for handling submit messages - used for all but root hub */ +/* accesses. */ +int submit_common_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int interval) +{ + int stat = 0; + int maxsize = usb_maxpacket(dev, pipe); + int timeout; + + /* device pulled? Shortcut the action. */ + if (devgone == dev) { + dev->status = USB_ST_CRC_ERR; + return 0; + } + +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_common_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + + if (sohci_submit_job(dev, pipe, buffer, transfer_len, setup, interval) < 0) { + err("sohci_submit_job failed"); + return -1; + } + + wait_ms(10); + /* ohci_dump_status(&gohci); */ + + /* allow more time for a BULK device to react - some are slow */ +#define BULK_TO 5000 /* timeout in milliseconds */ + if (usb_pipetype (pipe) == PIPE_BULK) + timeout = BULK_TO; + else + timeout = 100; + + timeout *= 4; + /* wait for it to complete */ + for (;;) { + /* check whether the controller is done */ + stat = hc_interrupt(); + if (stat < 0) { + stat = USB_ST_CRC_ERR; + break; + } + if (stat >= 0 && stat != 0xff) { + /* 0xff is returned for an SF-interrupt */ + break; + } + if (--timeout) { + udelay(250); /* wait_ms(1); */ + } else { + err("CTL:TIMEOUT "); + stat = USB_ST_CRC_ERR; + break; + } + } + /* we got an Root Hub Status Change interrupt */ + if (got_rhsc) { +#ifdef DEBUG + ohci_dump_roothub (&gohci, 1); +#endif + got_rhsc = 0; + /* abuse timeout */ + timeout = rh_check_port_status(&gohci); + if (timeout >= 0) { +#if 0 /* this does nothing useful, but leave it here in case that changes */ + /* the called routine adds 1 to the passed value */ + usb_hub_port_connect_change(gohci.rh.dev, timeout - 1); +#endif + /* + * XXX + * This is potentially dangerous because it assumes + * that only one device is ever plugged in! + */ + devgone = dev; + } + } + + dev->status = stat; + dev->act_len = transfer_len; + +#ifdef DEBUG + pkt_print(dev, pipe, buffer, transfer_len, setup, "RET(ctlr)", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + + /* free TDs in urb_priv */ + urb_free_priv (&urb_priv); + return 0; +} + +/* submit routines called from usb.c */ +int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len) +{ + info("submit_bulk_msg"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0); +} + +int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup) +{ + int maxsize = usb_maxpacket(dev, pipe); + + info("submit_control_msg"); +#ifdef DEBUG + urb_priv.actual_length = 0; + pkt_print(dev, pipe, buffer, transfer_len, setup, "SUB", usb_pipein(pipe)); +#else + wait_ms(1); +#endif + if (!maxsize) { + err("submit_control_message: pipesize for pipe %lx is zero", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == gohci.rh.devnum) { + gohci.rh.dev = dev; + /* root hub - redirect */ + return ohci_submit_rh_msg(dev, pipe, buffer, transfer_len, + setup); + } + + return submit_common_msg(dev, pipe, buffer, transfer_len, setup, 0); +} + +int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg"); + return -1; +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset (ohci_t *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + if (readl (&ohci->regs->control) & OHCI_CTRL_IR) { /* SMM owns the HC */ + writel (OHCI_OCR, &ohci->regs->cmdstatus); /* request ownership */ + info("USB HC TakeOver from SMM"); + while (readl (&ohci->regs->control) & OHCI_CTRL_IR) { + wait_ms (10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel (OHCI_INTR_MIE, &ohci->regs->intrdisable); + + dbg("USB HC reset_hc usb-%s: ctrl = 0x%X ;", + ohci->slot_name, + readl (&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + writel (0, &ohci->regs->control); + + /* HC Reset requires max 10 us delay */ + writel (OHCI_HCR, &ohci->regs->cmdstatus); + while ((readl (&ohci->regs->cmdstatus) & OHCI_HCR) != 0) { + if (--timeout == 0) { + err("USB HC reset timed out!"); + return -1; + } + udelay (1); + } + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* Start an OHCI controller, set the BUS operational + * enable interrupts + * connect the virtual root hub */ + +static int hc_start (ohci_t * ohci) +{ + __u32 mask; + unsigned int fminterval; + + ohci->disabled = 1; + + /* Tell the controller where the control and bulk lists are + * The lists are empty now. */ + + writel (0, &ohci->regs->ed_controlhead); + writel (0, &ohci->regs->ed_bulkhead); + + writel ((__u32)ohci->hcca, &ohci->regs->hcca); /* a reset clears this */ + + fminterval = 0x2edf; + writel ((fminterval * 9) / 10, &ohci->regs->periodicstart); + fminterval |= ((((fminterval - 210) * 6) / 7) << 16); + writel (fminterval, &ohci->regs->fminterval); + writel (0x628, &ohci->regs->lsthresh); + + /* start controller operations */ + ohci->hc_control = OHCI_CONTROL_INIT | OHCI_USB_OPER; + ohci->disabled = 0; + writel (ohci->hc_control, &ohci->regs->control); + + /* disable all interrupts */ + mask = (OHCI_INTR_SO | OHCI_INTR_WDH | OHCI_INTR_SF | OHCI_INTR_RD | + OHCI_INTR_UE | OHCI_INTR_FNO | OHCI_INTR_RHSC | + OHCI_INTR_OC | OHCI_INTR_MIE); + writel (mask, &ohci->regs->intrdisable); + /* clear all interrupts */ + mask &= ~OHCI_INTR_MIE; + writel (mask, &ohci->regs->intrstatus); + /* Choose the interrupts we care about now - but w/o MIE */ + mask = OHCI_INTR_RHSC | OHCI_INTR_UE | OHCI_INTR_WDH | OHCI_INTR_SO; + writel (mask, &ohci->regs->intrenable); + +#ifdef OHCI_USE_NPS + /* required for AMD-756 and some Mac platforms */ + writel ((roothub_a (ohci) | RH_A_NPS) & ~RH_A_PSM, + &ohci->regs->roothub.a); + writel (RH_HS_LPSC, &ohci->regs->roothub.status); +#endif /* OHCI_USE_NPS */ + +#define mdelay(n) ({unsigned long msec=(n); while (msec--) udelay(1000);}) + /* POTPGT delay is bits 24-31, in 2 ms units. */ + mdelay ((roothub_a (ohci) >> 23) & 0x1fe); + + /* connect the virtual root hub */ + ohci->rh.devnum = 0; + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* an interrupt happens */ + +static int +hc_interrupt (void) +{ + ohci_t *ohci = &gohci; + struct ohci_regs *regs = ohci->regs; + int ints; + int stat = -1; + + if ((ohci->hcca->done_head != 0) && !(m32_swap (ohci->hcca->done_head) & 0x01)) { + ints = OHCI_INTR_WDH; + } else { + ints = readl (®s->intrstatus); + } + + /* dbg("Interrupt: %x frame: %x", ints, le16_to_cpu (ohci->hcca->frame_no)); */ + + if (ints & OHCI_INTR_RHSC) { + got_rhsc = 1; + } + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err ("OHCI Unrecoverable Error, controller usb-%s disabled", + ohci->slot_name); + /* e.g. due to PCI Master/Target Abort */ + +#ifdef DEBUG + ohci_dump (ohci, 1); +#else + wait_ms(1); +#endif + /* FIXME: be optimistic, hope that bug won't repeat often. */ + /* Make some non-interrupt context restart the controller. */ + /* Count and limit the retries though; either hardware or */ + /* software errors can go forever... */ + hc_reset (ohci); + return -1; + } + + if (ints & OHCI_INTR_WDH) { + wait_ms(1); + writel (OHCI_INTR_WDH, ®s->intrdisable); + stat = dl_done_list (&gohci, dl_reverse_done_list (&gohci)); + writel (OHCI_INTR_WDH, ®s->intrenable); + } + + if (ints & OHCI_INTR_SO) { + dbg("USB Schedule overrun\n"); + writel (OHCI_INTR_SO, ®s->intrenable); + stat = -1; + } + + /* FIXME: this assumes SOF (1/ms) interrupts don't get lost... */ + if (ints & OHCI_INTR_SF) { + unsigned int frame = m16_swap (ohci->hcca->frame_no) & 1; + wait_ms(1); + writel (OHCI_INTR_SF, ®s->intrdisable); + if (ohci->ed_rm_list[frame] != NULL) + writel (OHCI_INTR_SF, ®s->intrenable); + stat = 0xff; + } + + writel (ints, ®s->intrstatus); + return stat; +} + +/*-------------------------------------------------------------------------*/ + +/*-------------------------------------------------------------------------*/ + +/* De-allocate all resources.. */ + +static void hc_release_ohci (ohci_t *ohci) +{ + dbg ("USB HC release ohci usb-%s", ohci->slot_name); + + if (!ohci->disabled) + hc_reset (ohci); +} + +/*-------------------------------------------------------------------------*/ + +#define __read_32bit_c0_register(source, sel) \ +({ int __res; \ + if (sel == 0) \ + __asm__ __volatile__( \ + "mfc0\t%0, " #source "\n\t" \ + : "=r" (__res)); \ + else \ + __asm__ __volatile__( \ + ".set\tmips32\n\t" \ + "mfc0\t%0, " #source ", " #sel "\n\t" \ + ".set\tmips0\n\t" \ + : "=r" (__res)); \ + __res; \ +}) + +#define read_c0_prid() __read_32bit_c0_register($15, 0) + +/* + * low level initalisation routine, called from usb.c + */ +static char ohci_inited = 0; + +int usb_lowlevel_init(void) +{ + u32 pin_func; + u32 sys_freqctrl, sys_clksrc; + u32 prid = read_c0_prid(); + + dbg("in usb_lowlevel_init\n"); + + /* zero and disable FREQ2 */ + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* zero and disable USBH/USBD clocks */ + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + au_writel(sys_clksrc, SYS_CLKSRC); + + sys_freqctrl = au_readl(SYS_FREQCTRL0); + sys_freqctrl &= ~0xFFF00000; + + sys_clksrc = au_readl(SYS_CLKSRC); + sys_clksrc &= ~0x00007FE0; + + switch (prid & 0x000000FF) { + case 0x00: /* DA */ + case 0x01: /* HA */ + case 0x02: /* HB */ + /* CPU core freq to 48MHz to slow it way down... */ + au_writel(4, SYS_CPUPLL); + + /* + * Setup 48MHz FREQ2 from CPUPLL for USB Host + */ + /* FRDIV2=3 -> div by 8 of 384MHz -> 48MHz */ + sys_freqctrl |= ((3<<22) | (1<<21) | (0<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + + /* CPU core freq to 384MHz */ + au_writel(0x20, SYS_CPUPLL); + + printf("Au1000: 48MHz OHCI workaround enabled\n"); + break; + + default: /* HC and newer */ + /* FREQ2 = aux/2 = 48 MHz */ + sys_freqctrl |= ((0<<22) | (1<<21) | (1<<20)); + au_writel(sys_freqctrl, SYS_FREQCTRL0); + break; + } + + /* + * Route 48MHz FREQ2 into USB Host and/or Device + */ + sys_clksrc |= ((4<<12) | (0<<11) | (0<<10)); + au_writel(sys_clksrc, SYS_CLKSRC); + + /* configure pins GPIO[14:9] as GPIO */ + pin_func = au_readl(SYS_PINFUNC) & (u32)(~0x8080); + + au_writel(pin_func, SYS_PINFUNC); + au_writel(0x2800, SYS_TRIOUTCLR); + au_writel(0x0030, SYS_OUTPUTCLR); + + dbg("OHCI board setup complete\n"); + + /* enable host controller */ + au_writel(USBH_ENABLE_CE, USB_HOST_CONFIG); + udelay(1000); + au_writel(USBH_ENABLE_INIT, USB_HOST_CONFIG); + udelay(1000); + + /* wait for reset complete (read register twice; see au1500 errata) */ + while (au_readl(USB_HOST_CONFIG), + !(au_readl(USB_HOST_CONFIG) & USBH_ENABLE_RD)) + udelay(1000); + + dbg("OHCI clock running\n"); + + memset (&gohci, 0, sizeof (ohci_t)); + memset (&urb_priv, 0, sizeof (urb_priv_t)); + + /* align the storage */ + if ((__u32)&ghcca[0] & 0xff) { + err("HCCA not aligned!!"); + return -1; + } + phcca = &ghcca[0]; + info("aligned ghcca %p", phcca); + memset(&ohci_dev, 0, sizeof(struct ohci_device)); + if ((__u32)&ohci_dev.ed[0] & 0x7) { + err("EDs not aligned!!"); + return -1; + } + memset(gtd, 0, sizeof(td_t) * (NUM_TD + 1)); + if ((__u32)gtd & 0x7) { + err("TDs not aligned!!"); + return -1; + } + ptd = gtd; + gohci.hcca = phcca; + memset (phcca, 0, sizeof (struct ohci_hcca)); + + gohci.disabled = 1; + gohci.sleeping = 0; + gohci.irq = -1; + gohci.regs = (struct ohci_regs *)(USB_OHCI_BASE | 0xA0000000); + + gohci.flags = 0; + gohci.slot_name = "au1x00"; + + dbg("OHCI revision: 0x%08x\n" + " RH: a: 0x%08x b: 0x%08x\n", + readl(&gohci.regs->revision), + readl(&gohci.regs->roothub.a), readl(&gohci.regs->roothub.b)); + + if (hc_reset (&gohci) < 0) + goto errout; + + /* FIXME this is a second HC reset; why?? */ + writel (gohci.hc_control = OHCI_USB_RESET, &gohci.regs->control); + wait_ms (10); + + if (hc_start (&gohci) < 0) + goto errout; + +#ifdef DEBUG + ohci_dump (&gohci, 1); +#else + wait_ms(1); +#endif + ohci_inited = 1; + return 0; + + errout: + err("OHCI initialization error\n"); + hc_release_ohci (&gohci); + /* Initialization failed */ + au_writel(readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); + return -1; +} + +int usb_lowlevel_stop(void) +{ + /* this gets called really early - before the controller has */ + /* even been initialized! */ + if (!ohci_inited) + return 0; + /* TODO release any interrupts, etc. */ + /* call hc_release_ohci() here ? */ + hc_reset (&gohci); + /* may not want to do this */ + /* Disable clock */ + au_writel(readl(USB_HOST_CONFIG) & ~USBH_ENABLE_CE, USB_HOST_CONFIG); + return 0; +} + +#endif /* CONFIG_USB_OHCI */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h new file mode 100644 index 0000000000..4ef06ffdeb --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/au1x00_usb_ohci.h @@ -0,0 +1,416 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber + * (C) Copyright 2000-2001 David Brownell + * + * usb-ohci.h + */ + + +static int cc_to_error[16] = { + +/* mapping of the OHCI CC status to error codes */ + /* No Error */ 0, + /* CRC Error */ USB_ST_CRC_ERR, + /* Bit Stuff */ USB_ST_BIT_ERR, + /* Data Togg */ USB_ST_CRC_ERR, + /* Stall */ USB_ST_STALLED, + /* DevNotResp */ -1, + /* PIDCheck */ USB_ST_BIT_ERR, + /* UnExpPID */ USB_ST_BIT_ERR, + /* DataOver */ USB_ST_BUF_ERR, + /* DataUnder */ USB_ST_BUF_ERR, + /* reservd */ -1, + /* reservd */ -1, + /* BufferOver */ USB_ST_BUF_ERR, + /* BuffUnder */ USB_ST_BUF_ERR, + /* Not Access */ -1, + /* Not Access */ -1 +}; + +/* ED States */ + +#define ED_NEW 0x00 +#define ED_UNLINK 0x01 +#define ED_OPER 0x02 +#define ED_DEL 0x04 +#define ED_URB_DEL 0x08 + +/* usb_ohci_ed */ +struct ed { + __u32 hwINFO; + __u32 hwTailP; + __u32 hwHeadP; + __u32 hwNextED; + + struct ed *ed_prev; + __u8 int_period; + __u8 int_branch; + __u8 int_load; + __u8 int_interval; + __u8 state; + __u8 type; + __u16 last_iso; + struct ed *ed_rm_list; + + struct usb_device *usb_dev; + __u32 unused[3]; +} __attribute((aligned(16))); +typedef struct ed ed_t; + + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >>28) & 0x0f) +#define TD_CC_SET(td_p, cc) (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28) +#define TD_EC 0x0C000000 +#define TD_T 0x03000000 +#define TD_T_DATA0 0x02000000 +#define TD_T_DATA1 0x03000000 +#define TD_T_TOGGLE 0x00000000 +#define TD_R 0x00040000 +#define TD_DI 0x00E00000 +#define TD_DI_SET(X) (((X) & 0x07)<< 21) +#define TD_DP 0x00180000 +#define TD_DP_SETUP 0x00000000 +#define TD_DP_IN 0x00100000 +#define TD_DP_OUT 0x00080000 + +#define TD_ISO 0x00010000 +#define TD_DEL 0x00020000 + +/* CC Codes */ +#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_DEVNOTRESP 0x05 +#define TD_PIDCHECKFAIL 0x06 +#define TD_UNEXPECTEDPID 0x07 +#define TD_DATAOVERRUN 0x08 +#define TD_DATAUNDERRUN 0x09 +#define TD_BUFFEROVERRUN 0x0C +#define TD_BUFFERUNDERRUN 0x0D +#define TD_NOTACCESSED 0x0F + + +#define MAXPSW 1 + +struct td { + __u32 hwINFO; + __u32 hwCBP; /* Current Buffer Pointer */ + __u32 hwNextTD; /* Next TD Pointer */ + __u32 hwBE; /* Memory Buffer End Pointer */ + + __u16 hwPSW[MAXPSW]; + __u8 unused; + __u8 index; + struct ed *ed; + struct td *next_dl_td; + struct usb_device *usb_dev; + int transfer_len; + __u32 data; + + __u32 unused2[2]; +} __attribute((aligned(32))); +typedef struct td td_t; + +#define OHCI_ED_SKIP (1 << 14) + +/* + * The HCCA (Host Controller Communications Area) is a 256 byte + * structure defined in the OHCI spec. that the host controller is + * told the base address of. It must be 256-byte aligned. + */ + +#define NUM_INTS 32 /* part of the OHCI standard */ +struct ohci_hcca { + __u32 int_table[NUM_INTS]; /* Interrupt ED table */ + __u16 frame_no; /* current frame number */ + __u16 pad1; /* set to 0 on each frame_no change */ + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute((aligned(256))); + + +/* + * Maximum number of root hub ports. + */ +#define MAX_ROOT_PORTS 15 /* maximum OHCI root hub ports */ + +/* + * This is the structure of the OHCI controller's memory mapped I/O + * region. This is Memory Mapped I/O. You must use the readl() and + * writel() macros defined in asm/io.h to access these!! + */ +struct ohci_regs { + /* control and status registers */ + __u32 revision; + __u32 control; + __u32 cmdstatus; + __u32 intrstatus; + __u32 intrenable; + __u32 intrdisable; + /* memory pointers */ + __u32 hcca; + __u32 ed_periodcurrent; + __u32 ed_controlhead; + __u32 ed_controlcurrent; + __u32 ed_bulkhead; + __u32 ed_bulkcurrent; + __u32 donehead; + /* frame counters */ + __u32 fminterval; + __u32 fmremaining; + __u32 fmnumber; + __u32 periodicstart; + __u32 lsthresh; + /* Root hub ports */ + struct ohci_roothub_regs { + __u32 a; + __u32 b; + __u32 status; + __u32 portstatus[MAX_ROOT_PORTS]; + } roothub; +} __attribute((aligned(32))); + + +/* OHCI CONTROL AND STATUS REGISTER MASKS */ + +/* + * HcControl (control) register masks + */ +#define OHCI_CTRL_CBSR (3 << 0) /* control/bulk service ratio */ +#define OHCI_CTRL_PLE (1 << 2) /* periodic list enable */ +#define OHCI_CTRL_IE (1 << 3) /* isochronous enable */ +#define OHCI_CTRL_CLE (1 << 4) /* control list enable */ +#define OHCI_CTRL_BLE (1 << 5) /* bulk list enable */ +#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ +#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ +#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ +#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ + +/* pre-shifted values for HCFS */ +# define OHCI_USB_RESET (0 << 6) +# define OHCI_USB_RESUME (1 << 6) +# define OHCI_USB_OPER (2 << 6) +# define OHCI_USB_SUSPEND (3 << 6) + +/* + * HcCommandStatus (cmdstatus) register masks + */ +#define OHCI_HCR (1 << 0) /* host controller reset */ +#define OHCI_CLF (1 << 1) /* control list filled */ +#define OHCI_BLF (1 << 2) /* bulk list filled */ +#define OHCI_OCR (1 << 3) /* ownership change request */ +#define OHCI_SOC (3 << 16) /* scheduling overrun count */ + +/* + * masks used with interrupt registers: + * HcInterruptStatus (intrstatus) + * HcInterruptEnable (intrenable) + * HcInterruptDisable (intrdisable) + */ +#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ +#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ +#define OHCI_INTR_SF (1 << 2) /* start frame */ +#define OHCI_INTR_RD (1 << 3) /* resume detect */ +#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ +#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ +#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ +#define OHCI_INTR_OC (1 << 30) /* ownership change */ +#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ + + +/* Virtual Root HUB */ +struct virt_root_hub { + int devnum; /* Address of Root Hub endpoint */ + void *dev; /* was urb */ + void *int_addr; + int send; + int interval; +}; + +/* USB HUB CONSTANTS (not OHCI-specific; see hub.h) */ + +/* destination of request */ +#define RH_INTERFACE 0x01 +#define RH_ENDPOINT 0x02 +#define RH_OTHER 0x03 + +#define RH_CLASS 0x20 +#define RH_VENDOR 0x40 + +/* Requests: bRequest << 8 | bmRequestType */ +#define RH_GET_STATUS 0x0080 +#define RH_CLEAR_FEATURE 0x0100 +#define RH_SET_FEATURE 0x0300 +#define RH_SET_ADDRESS 0x0500 +#define RH_GET_DESCRIPTOR 0x0680 +#define RH_SET_DESCRIPTOR 0x0700 +#define RH_GET_CONFIGURATION 0x0880 +#define RH_SET_CONFIGURATION 0x0900 +#define RH_GET_STATE 0x0280 +#define RH_GET_INTERFACE 0x0A80 +#define RH_SET_INTERFACE 0x0B00 +#define RH_SYNC_FRAME 0x0C80 +/* Our Vendor Specific Request */ +#define RH_SET_EP 0x2000 + + +/* Hub port features */ +#define RH_PORT_CONNECTION 0x00 +#define RH_PORT_ENABLE 0x01 +#define RH_PORT_SUSPEND 0x02 +#define RH_PORT_OVER_CURRENT 0x03 +#define RH_PORT_RESET 0x04 +#define RH_PORT_POWER 0x08 +#define RH_PORT_LOW_SPEED 0x09 + +#define RH_C_PORT_CONNECTION 0x10 +#define RH_C_PORT_ENABLE 0x11 +#define RH_C_PORT_SUSPEND 0x12 +#define RH_C_PORT_OVER_CURRENT 0x13 +#define RH_C_PORT_RESET 0x14 + +/* Hub features */ +#define RH_C_HUB_LOCAL_POWER 0x00 +#define RH_C_HUB_OVER_CURRENT 0x01 + +#define RH_DEVICE_REMOTE_WAKEUP 0x00 +#define RH_ENDPOINT_STALL 0x01 + +#define RH_ACK 0x01 +#define RH_REQ_ERR -1 +#define RH_NACK 0x00 + + +/* OHCI ROOT HUB REGISTER MASKS */ + +/* roothub.portstatus [i] bits */ +#define RH_PS_CCS 0x00000001 /* current connect status */ +#define RH_PS_PES 0x00000002 /* port enable status*/ +#define RH_PS_PSS 0x00000004 /* port suspend status */ +#define RH_PS_POCI 0x00000008 /* port over current indicator */ +#define RH_PS_PRS 0x00000010 /* port reset status */ +#define RH_PS_PPS 0x00000100 /* port power status */ +#define RH_PS_LSDA 0x00000200 /* low speed device attached */ +#define RH_PS_CSC 0x00010000 /* connect status change */ +#define RH_PS_PESC 0x00020000 /* port enable status change */ +#define RH_PS_PSSC 0x00040000 /* port suspend status change */ +#define RH_PS_OCIC 0x00080000 /* over current indicator change */ +#define RH_PS_PRSC 0x00100000 /* port reset status change */ + +/* roothub.status bits */ +#define RH_HS_LPS 0x00000001 /* local power status */ +#define RH_HS_OCI 0x00000002 /* over current indicator */ +#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ +#define RH_HS_LPSC 0x00010000 /* local power status change */ +#define RH_HS_OCIC 0x00020000 /* over current indicator change */ +#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ + +/* roothub.b masks */ +#define RH_B_DR 0x0000ffff /* device removable flags */ +#define RH_B_PPCM 0xffff0000 /* port power control mask */ + +/* roothub.a masks */ +#define RH_A_NDP (0xff << 0) /* number of downstream ports */ +#define RH_A_PSM (1 << 8) /* power switching mode */ +#define RH_A_NPS (1 << 9) /* no power switching */ +#define RH_A_DT (1 << 10) /* device type (mbz) */ +#define RH_A_OCPM (1 << 11) /* over current protection mode */ +#define RH_A_NOCP (1 << 12) /* no over current protection */ +#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ + +/* urb */ +#define N_URB_TD 48 +typedef struct +{ + ed_t *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + int state; + unsigned long pipe; + int actual_length; + td_t *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +} urb_priv_t; +#define URB_DEL 1 + +/* + * This is the full ohci controller description + * + * Note how the "proper" USB information is just + * a subset of what the full implementation needs. (Linus) + */ + + +typedef struct ohci { + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + int sleeping; + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + ed_t *ed_rm_list[2]; /* lists of all endpoints to be removed */ + ed_t *ed_bulktail; /* last endpoint of bulk list */ + ed_t *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct usb_device *dev[32]; + struct virt_root_hub rh; + + const char *slot_name; +} ohci_t; + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + ed_t ed[NUM_EDS]; + int ed_cnt; +}; + +/* hcd */ +/* endpoint */ +static int ep_link(ohci_t * ohci, ed_t * ed); +static int ep_unlink(ohci_t * ohci, ed_t * ed); +static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned long pipe); + +/*-------------------------------------------------------------------------*/ + +/* we need more TDs than EDs */ +#define NUM_TD 64 + +/* +1 so we can align the storage */ +td_t gtd[NUM_TD+1]; +/* pointers to aligned storage */ +td_t *ptd; + +/* TDs ... */ +static inline struct td * +td_alloc (struct usb_device *usb_dev) +{ + int i; + struct td *td; + + td = NULL; + for (i = 0; i < NUM_TD; i++) { + if (ptd[i].usb_dev == NULL) { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + return td; +} + +static inline void +ed_free (struct ed *ed) +{ + ed->usb_dev = NULL; +} diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/cache.S b/package/uboot-ifxmips/files/cpu/mips/danube/cache.S new file mode 100644 index 0000000000..9a39784476 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/cache.S @@ -0,0 +1,278 @@ +/* + * Cache-handling routined for MIPS 4K CPUs + * + * Copyright (c) 2003 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#include +#include +#if defined(CONFIG_IFX_MIPS) +# include "ifx_cache.S" +#endif + + /* 16KB is the maximum size of instruction and data caches on + * MIPS 4K. + */ +#define MIPS_MAX_CACHE_SIZE 0x4000 + + +/* + * cacheop macro to automate cache operations + * first some helpers... + */ +#define _mincache(size, maxsize) \ + bltu size,maxsize,9f ; \ + move size,maxsize ; \ +9: + +#define _align(minaddr, maxaddr, linesize) \ + .set noat ; \ + subu AT,linesize,1 ; \ + not AT ; \ + and minaddr,AT ; \ + addu maxaddr,-1 ; \ + and maxaddr,AT ; \ + .set at + +/* general operations */ +#define doop1(op1) \ + cache op1,0(a0) +#define doop2(op1, op2) \ + cache op1,0(a0) ; \ + nop ; \ + cache op2,0(a0) + +/* specials for cache initialisation */ +#define doop1lw(op1) \ + lw zero,0(a0) +#define doop1lw1(op1) \ + cache op1,0(a0) ; \ + lw zero,0(a0) ; \ + cache op1,0(a0) +#define doop121(op1,op2) \ + cache op1,0(a0) ; \ + nop; \ + cache op2,0(a0) ; \ + nop; \ + cache op1,0(a0) + +#define _oploopn(minaddr, maxaddr, linesize, tag, ops) \ + .set noreorder ; \ +10: doop##tag##ops ; \ + bne minaddr,maxaddr,10b ; \ + add minaddr,linesize ; \ + .set reorder + +/* finally the cache operation macros */ +#define vcacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \ + blez n,11f ; \ + addu n,kva ; \ + _align(kva, n, cacheLineSize) ; \ + _oploopn(kva, n, cacheLineSize, tag, ops) ; \ +11: + +#define icacheopn(kva, n, cacheSize, cacheLineSize, tag, ops) \ + _mincache(n, cacheSize); \ + blez n,11f ; \ + addu n,kva ; \ + _align(kva, n, cacheLineSize) ; \ + _oploopn(kva, n, cacheLineSize, tag, ops) ; \ +11: + +#define vcacheop(kva, n, cacheSize, cacheLineSize, op) \ + vcacheopn(kva, n, cacheSize, cacheLineSize, 1, (op)) + +#define icacheop(kva, n, cacheSize, cacheLineSize, op) \ + icacheopn(kva, n, cacheSize, cacheLineSize, 1, (op)) + +/******************************************************************************* +* +* mips_cache_reset - low level initialisation of the primary caches +* +* This routine initialises the primary caches to ensure that they +* have good parity. It must be called by the ROM before any cached locations +* are used to prevent the possibility of data with bad parity being written to +* memory. +* To initialise the instruction cache it is essential that a source of data +* with good parity is available. This routine +* will initialise an area of memory starting at location zero to be used as +* a source of parity. +* +* RETURNS: N/A +* +*/ + .globl mips_cache_reset + .ent mips_cache_reset +mips_cache_reset: + + li t2, CFG_ICACHE_SIZE + li t3, CFG_DCACHE_SIZE + li t4, CFG_CACHELINE_SIZE + move t5, t4 + + + li v0, MIPS_MAX_CACHE_SIZE + + /* Now clear that much memory starting from zero. + */ + + li a0, KSEG1 + addu a1, a0, v0 + +2: sw zero, 0(a0) + sw zero, 4(a0) + sw zero, 8(a0) + sw zero, 12(a0) + sw zero, 16(a0) + sw zero, 20(a0) + sw zero, 24(a0) + sw zero, 28(a0) + addu a0, 32 + bltu a0, a1, 2b + + /* Set invalid tag. + */ + + mtc0 zero, CP0_TAGLO +#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_INVALID_TAG) + IFX_CACHE_EXTRA_INVALID_TAG +#endif + + /* + * The caches are probably in an indeterminate state, + * so we force good parity into them by doing an + * invalidate, load/fill, invalidate for each line. + */ + + /* Assume bottom of RAM will generate good parity for the cache. + */ + + li a0, K0BASE + move a2, t2 # icacheSize + move a3, t4 # icacheLineSize + move a1, a2 + icacheopn(a0,a1,a2,a3,121,(Index_Store_Tag_I,Fill)) + +#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_EXTRA_OPERATION) + IFX_CACHE_EXTRA_OPERATION +#else + /* To support Orion/R4600, we initialise the data cache in 3 passes. + */ + + /* 1: initialise dcache tags. + */ + + li a0, K0BASE + move a2, t3 # dcacheSize + move a3, t5 # dcacheLineSize + move a1, a2 + icacheop(a0,a1,a2,a3,Index_Store_Tag_D) + + /* 2: fill dcache. + */ + + li a0, K0BASE + move a2, t3 # dcacheSize + move a3, t5 # dcacheLineSize + move a1, a2 + icacheopn(a0,a1,a2,a3,1lw,(dummy)) + + /* 3: clear dcache tags. + */ + + li a0, K0BASE + move a2, t3 # dcacheSize + move a3, t5 # dcacheLineSize + move a1, a2 + icacheop(a0,a1,a2,a3,Index_Store_Tag_D) +#endif + + j ra + .end mips_cache_reset + + +/******************************************************************************* +* +* dcache_status - get cache status +* +* RETURNS: 0 - cache disabled; 1 - cache enabled +* +*/ + .globl dcache_status + .ent dcache_status +dcache_status: + + mfc0 v0, CP0_CONFIG + andi v0, v0, 1 + j ra + + .end dcache_status + +/******************************************************************************* +* +* dcache_disable - disable cache +* +* RETURNS: N/A +* +*/ + .globl dcache_disable + .ent dcache_disable +dcache_disable: + + mfc0 t0, CP0_CONFIG + li t1, -8 + and t0, t0, t1 + ori t0, t0, CONF_CM_UNCACHED + mtc0 t0, CP0_CONFIG + j ra + + .end dcache_disable + + +/******************************************************************************* +* +* mips_cache_lock - lock RAM area pointed to by a0 in cache. +* +* RETURNS: N/A +* +*/ +#if defined(CONFIG_PURPLE) +# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE/2) +#else +# define CACHE_LOCK_SIZE (CFG_DCACHE_SIZE) +#endif + .globl mips_cache_lock + .ent mips_cache_lock +mips_cache_lock: + li a1, K0BASE - CACHE_LOCK_SIZE + addu a0, a1 + li a2, CACHE_LOCK_SIZE + li a3, CFG_CACHELINE_SIZE + move a1, a2 + icacheop(a0,a1,a2,a3,0x1d) + + j ra + .end mips_cache_lock diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/config.mk b/package/uboot-ifxmips/files/cpu/mips/danube/config.mk new file mode 100644 index 0000000000..3414ad8a73 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/config.mk @@ -0,0 +1,53 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 +# +v=$(shell \ +$(CROSS_COMPILE)as --version|grep "GNU assembler"|awk '{print $$3}'|awk -F . '{print $$2}') + +ifndef PLATFORM_CPU +PLATFORM_CPU = mips32r2 +endif + +MIPSFLAGS=$(shell \ +if [ "$v" -lt "14" ]; then \ + echo "-mcpu=$(PLATFORM_CPU)"; \ +else \ + echo "-march=$(PLATFORM_CPU) -mtune=$(PLATFORM_CPU)"; \ +fi) + +ifeq ($(CROSS_COMPILE_UCLIBC),1) +ifneq (,$(findstring mipsel,$(CROSS_COMIPLE))) +ENDIANNESS = -el +else +ENDIANNESS = -eb +endif +else +ifneq (,$(findstring 4KCle,$(CROSS_COMPILE))) +ENDIANNESS = -EL +else +ENDIANNESS = -EB +endif +endif + +MIPSFLAGS += $(ENDIANNESS) -mabicalls + +PLATFORM_CPPFLAGS += $(MIPSFLAGS) diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c b/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c new file mode 100644 index 0000000000..b9f90ce0cc --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/cpu.c @@ -0,0 +1,61 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#if defined(CONFIG_INCA_IP) +# include +#elif defined(CONFIG_IFX_MIPS) +# include +# include "ifx_cpu.c" +#endif +#include + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#if defined(CONFIG_INCA_IP) + *INCA_IP_WDT_RST_REQ = 0x3f; +#elif defined(CONFIG_PURPLE) || defined(CONFIG_TB0229) + void (*f)(void) = (void *) 0xbfc00000; + + f(); +#elif defined(CONFIG_IFX_MIPS) + IFX_CPU_RESET; +#endif + fprintf(stderr, "*** reset failed ***\n"); + return 0; +} + +void flush_cache (ulong start_addr, ulong size) +{ + +} + +void write_one_tlb( int index, u32 pagemask, u32 hi, u32 low0, u32 low1 ){ + write_32bit_cp0_register(CP0_ENTRYLO0, low0); + write_32bit_cp0_register(CP0_PAGEMASK, pagemask); + write_32bit_cp0_register(CP0_ENTRYLO1, low1); + write_32bit_cp0_register(CP0_ENTRYHI, hi); + write_32bit_cp0_register(CP0_INDEX, index); + tlb_write_indexed(); +} diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c new file mode 100644 index 0000000000..52c6cb2715 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_asc.c @@ -0,0 +1,257 @@ +/***************************************************************************** + * DANUBE BootROM + * Copyright (c) 2005, Infineon Technologies AG, All rights reserved + * IFAP DC COM SD + *****************************************************************************/ + +#include +//#include +#include +#include +#include + + +#define ASC_FIFO_PRESENT +#define SET_BIT(reg, mask) reg |= (mask) +#define CLEAR_BIT(reg, mask) reg &= (~mask) +#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask) +#define SET_BITS(reg, mask) SET_BIT(reg, mask) +#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);} + + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned long u32; +typedef signed long s32; +typedef unsigned int uint; +typedef unsigned long ulong; +typedef volatile unsigned short vuint; + + + +void serial_setbrg (void); + +/*TODO: undefine this !!!*/ +#undef DEBUG_ASC_RAW +#ifdef DEBUG_ASC_RAW +#define DEBUG_ASC_RAW_RX_BUF 0xA0800000 +#define DEBUG_ASC_RAW_TX_BUF 0xA0900000 +#endif + +static volatile DanubeAsc_t *pAsc = (DanubeAsc_t *)DANUBE_ASC1; + +typedef struct{ + u16 fdv; /* 0~511 fractional divider value*/ + u16 reload; /* 13 bit reload value*/ +} ifx_asc_baud_reg_t; + +#ifdef ON_VENUS +/*9600 @1.25M rel 00.08*/ +//#define FDV 503 +//#define RELOAD 7 +/*9600 @0.625M rel final00.01 & rtl_freeze*/ +#define FDV 503 +#define RELOAD 3 +/* first index is DDR_SEL, second index is FPI_SEL */ +#endif +static ifx_asc_baud_reg_t g_danube_asc_baud[4][2] = +{ +#ifdef ON_VENUS + {{503,3},{503,3}}, /* 1152000 @ 166.67M and half*/ + {{503,3},{503,3}}, /* 1152000 @ 133.3M and half*/ + {{503,3},{503,3}}, /* 1152000 @ 111.11M and half*/ + {{503.3},{503,3}} /* 1152000 @ 83.33M and half*/ +#else +/* TAPEOUT table */ + {{436,76},{419,36}}, /* 1152000 @ 166.67M and half*/ + {{453,63},{453,31}}, /* 1152000 @ 133.3M and half*/ + {{501,58},{510,29}}, /* 1152000 @ 111.11M and half*/ + {{419.36},{453,19}} /* 1152000 @ 83.33M and half*/ +#endif +}; +/****************************************************************************** +* +* asc_init - initialize a Danube ASC channel +* +* This routine initializes the number of data bits, parity +* and set the selected baud rate. Interrupts are disabled. +* Set the modem control signals if the option is selected. +* +* RETURNS: N/A +*/ + +int serial_init (void) +{ + + /* and we have to set CLC register*/ + CLEAR_BIT(pAsc->asc_clc, ASCCLC_DISS); + SET_BITFIELD(pAsc->asc_clc, ASCCLC_RMCMASK, ASCCLC_RMCOFFSET, 0x0001); + + /* initialy we are in async mode */ + pAsc->asc_con = ASCCON_M_8ASYNC; + + /* select input port */ + pAsc->asc_pisel = (CONSOLE_TTY & 0x1); + + /* TXFIFO's filling level */ + SET_BITFIELD(pAsc->asc_txfcon, ASCTXFCON_TXFITLMASK, + ASCTXFCON_TXFITLOFF, DANUBEASC_TXFIFO_FL); + /* enable TXFIFO */ + SET_BIT(pAsc->asc_txfcon, ASCTXFCON_TXFEN); + + /* RXFIFO's filling level */ + SET_BITFIELD(pAsc->asc_txfcon, ASCRXFCON_RXFITLMASK, + ASCRXFCON_RXFITLOFF, DANUBEASC_RXFIFO_FL); + /* enable RXFIFO */ + SET_BIT(pAsc->asc_rxfcon, ASCRXFCON_RXFEN); + + /* set baud rate */ + serial_setbrg(); + + /* enable error signals & Receiver enable */ + SET_BIT(pAsc->asc_whbstate, ASCWHBSTATE_SETREN|ASCCON_FEN|ASCCON_TOEN|ASCCON_ROEN); + + return 0; +} + +void serial_setbrg (void) +{ + u32 uiReloadValue, fdv; + +#if defined(ON_IKOS) + /*1200 @77K */ + fdv=472; + uiReloadValue=5; +#else + /*venus & tapeout */ + u32 ddr_sel,fpi_sel; + ddr_sel = (* DANUBE_CGU_SYS) & 0x3; + fpi_sel = ((* DANUBE_CGU_SYS) & 0x40)?1:0; + fdv= g_danube_asc_baud[ddr_sel][fpi_sel].fdv; + uiReloadValue=g_danube_asc_baud[ddr_sel][fpi_sel].reload; +#endif //ON_IKOS + /* Disable Baud Rate Generator; BG should only be written when R=0 */ + CLEAR_BIT(pAsc->asc_con, ASCCON_R); + + /* Enable Fractional Divider */ + SET_BIT(pAsc->asc_con, ASCCON_FDE); /* FDE = 1 */ + + /* Set fractional divider value */ + pAsc->asc_fdv = fdv & ASCFDV_VALUE_MASK; + + /* Set reload value in BG */ + pAsc->asc_bg = uiReloadValue; + + /* Enable Baud Rate Generator */ + SET_BIT(pAsc->asc_con, ASCCON_R); /* R = 1 */ +} + + +void serial_putc (const char c) +{ + u32 txFl = 0; +#ifdef DEBUG_ASC_RAW + static u8 * debug = (u8 *) DEBUG_ASC_RAW_TX_BUF; + *debug++=c; +#endif + if (c == '\n') + serial_putc ('\r'); + /* check do we have a free space in the TX FIFO */ + /* get current filling level */ + do + { + txFl = ( pAsc->asc_fstat & ASCFSTAT_TXFFLMASK ) >> ASCFSTAT_TXFFLOFF; + } + while ( txFl == DANUBEASC_TXFIFO_FULL ); + + pAsc->asc_tbuf = c; /* write char to Transmit Buffer Register */ + + /* check for errors */ + if ( pAsc->asc_state & ASCSTATE_TOE ) + { + SET_BIT(pAsc->asc_whbstate, ASCWHBSTATE_CLRTOE); + return; + } +} + +void serial_puts (const char *s) +{ + while (*s) + { + serial_putc (*s++); + } +} + +int asc_inb(int timeout) +{ + u32 symbol_mask; + char c; + while ((pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ) { + } + symbol_mask = ((ASC_OPTIONS & ASCOPT_CSIZE) == ASCOPT_CS7) ? (0x7f) : (0xff); + c = (char)(pAsc->asc_rbuf & symbol_mask); + return (c); +} + +int serial_getc (void) +{ + char c; + while ((pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ); + c = (char)(pAsc->asc_rbuf & 0xff); + +#ifdef DEBUG_ASC_RAW + static u8* debug=(u8*)(DEBUG_ASC_RAW_RX_BUF); + *debug++=c; +#endif + return c; +} + + + +int serial_tstc (void) +{ + int res = 1; + +#ifdef ASC_FIFO_PRESENT + if ( (pAsc->asc_fstat & ASCFSTAT_RXFFLMASK) == 0 ) + { + res = 0; + } +#else + if (!(*(volatile unsigned long*)(SFPI_INTCON_BASEADDR + FBS_ISR) & + FBS_ISR_AR)) + + { + res = 0; + } +#endif +#if 0 + else if ( pAsc->asc_con & ASCCON_FE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRFE); + res = 0; + } + else if ( pAsc->asc_con & ASCCON_PE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLRPE); + res = 0; + } + else if ( pAsc->asc_con & ASCCON_OE ) + { + SET_BIT(pAsc->asc_whbcon, ASCWHBCON_CLROE); + res = 0; + } +#endif + return res; +} + + +int serial_start(void) +{ + return 1; +} + +int serial_stop(void) +{ + return 1; +} diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S new file mode 100644 index 0000000000..fc482dcd61 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cache.S @@ -0,0 +1,60 @@ + +#define IFX_CACHE_EXTRA_INVALID_TAG \ + mtc0 zero, CP0_TAGLO, 1; \ + mtc0 zero, CP0_TAGLO, 2; \ + mtc0 zero, CP0_TAGLO, 3; \ + mtc0 zero, CP0_TAGLO, 4; + +#define IFX_CACHE_EXTRA_OPERATION \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t2; /* icacheSize */ \ + move a3, t4; /* icacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_I)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + /* 1: initialise dcache tags. */ \ + \ + /* cache line size */ \ + li a2, CFG_CACHELINE_SIZE; \ + /* kseg0 mem address */ \ + li a1, 0; \ + li a3, CFG_CACHE_SETS * CFG_CACHE_WAYS; \ +1: \ + /* store tag (invalid, not locked) */ \ + cache 0x8, 0(a1); \ + cache 0x9, 0(a1); \ + \ + add a3, -1; \ + bne a3, zero, 1b; \ + add a1, a2; \ + \ + /* set WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ECCF_WST; \ + or a0, a1; \ + mtc0 a0, CP0_ECC; \ + \ + li a0, K0BASE; \ + move a2, t3; /* dcacheSize */ \ + move a3, t5; /* dcacheLineSize */ \ + move a1, a2; \ + icacheop(a0,a1,a2,a3,(Index_Store_Tag_D)); \ + \ + /* clear WST bit */ \ + mfc0 a0, CP0_ECC; \ + li a1, ~ECCF_WST; \ + and a0, a1; \ + mtc0 a0, CP0_ECC; + diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c new file mode 100644 index 0000000000..3fe13dde28 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.c @@ -0,0 +1,1086 @@ +/* + * ######################################################################## + * + * This program is free software; you can distribute it and/or modify it + * under the terms of the GNU General Public License (Version 2) as + * published by the Free Software Foundation. + * + * This program is distributed in the hope 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. + * + * ######################################################################## + * + * danube_cgu.c + * + * Description: + * device driver of clock generation unit of Danube chip + * Author: + * Samuels Xu Liang + * Created: + * 19 Jul 2005 + * History & Modification Tag: + * ___________________________________________________________________________ + * | Tag | Comments | Modifier & Time | + * |--------+---------------------------------------------+------------------| + * | S0.0 | First version of this driver and the tag is | Samuels Xu Liang | + * | | implied. | 19 Jul 2005 | + * --------------------------------------------------------------------------- + * + */ + + +/* + * #################################### + * Head File + * #################################### + */ + +/* + * Common Head File + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Chip Specific Head File + */ +#include "ifx_cgu.h" + + +/* + * #################################### + * Definition + * #################################### + */ + +#define DEBUG_ON_AMAZON 1 +#define DEBUG_PRINT_INFO 1 + +/* + * Frequency of Clock Direct Feed from The Analog Line Driver Chip + */ +#define BASIC_INPUT_CLOCK_FREQUENCY 35328000 + +/* + * Bits Operation + */ +#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb)) +#define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb))) + +/* + * CGU Register Mapping + */ +#define DANUBE_CGU (KSEG1 + 0x1F103000) +#define DANUBE_CGU_DIV ((volatile u32*)(DANUBE_CGU + 0x0000)) +#define DANUBE_CGU_PLL_NMK0 ((volatile u32*)(DANUBE_CGU + 0x0004)) +#define DANUBE_CGU_PLL_SR0 ((volatile u32*)(DANUBE_CGU + 0x0008)) +#define DANUBE_CGU_PLL_NMK1 ((volatile u32*)(DANUBE_CGU + 0x000C)) +#define DANUBE_CGU_PLL_SR1 ((volatile u32*)(DANUBE_CGU + 0x0010)) +#define DANUBE_CGU_PLL_SR2 ((volatile u32*)(DANUBE_CGU + 0x0014)) +#define DANUBE_CGU_IF_CLK ((volatile u32*)(DANUBE_CGU + 0x0018)) +#define DANUBE_CGU_OSC_CTRL ((volatile u32*)(DANUBE_CGU + 0x001C)) +#define DANUBE_CGU_SMD ((volatile u32*)(DANUBE_CGU + 0x0020)) +#define DANUBE_CGU_CRD ((volatile u32*)(DANUBE_CGU + 0x0024)) +#define DANUBE_CGU_CT1SR ((volatile u32*)(DANUBE_CGU + 0x0028)) +#define DANUBE_CGU_CT2SR ((volatile u32*)(DANUBE_CGU + 0x002C)) +#define DANUBE_CGU_PCMCR ((volatile u32*)(DANUBE_CGU + 0x0030)) +#define DANUBE_CGU_MUX ((volatile u32*)(DANUBE_CGU + 0x0034)) + +/* + * CGU Divider Register + */ +#define CGU_DIV_SFTR (*DANUBE_CGU_DIV & (1 << 31)) +#define CGU_DIV_DIVE (*DANUBE_CGU_DIV & (1 << 16)) +#define CGU_DIV_IOR GET_BITS(*DANUBE_CGU_DIV, 5, 4) +#define CGU_DIV_FKS GET_BITS(*DANUBE_CGU_DIV, 3, 2) +#define CGU_DIV_FBS GET_BITS(*DANUBE_CGU_DIV, 1, 0) + +/* + * CGU PLL0 NMK Register + */ +#define CGU_PLL_NMK0_PLLN ((*DANUBE_CGU_PLL_NMK0 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24) +#define CGU_PLL_NMK0_PLLM GET_BITS(*DANUBE_CGU_PLL_NMK0, 23, 20) +#define CGU_PLL_NMK0_PLLK GET_BITS(*DANUBE_CGU_PLL_NMK0, 19, 0) + +/* + * CGU PLL0 Status Register + */ +#define CGU_PLL_SR0_PLLDIV ((*DANUBE_CGU_PLL_SR0 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28) +#define CGU_PLL_SR0_PLLDEN (*DANUBE_CGU_PLL_SR0 & (1 << 26)) +#define CGU_PLL_SR0_PLLPSE GET_BITS(*DANUBE_CGU_PLL_SR0, 5, 4) +#define CGU_PLL_SR0_PLLB (*DANUBE_CGU_PLL_SR0 & (1 << 2)) +#define CGU_PLL_SR0_PLLL (*DANUBE_CGU_PLL_SR0 & (1 << 1)) +#define CGU_PLL_SR0_PLLEN (*DANUBE_CGU_PLL_SR0 & (1 << 0)) + +#define CGU_PLL_SR0_DSMSEL 1 +#define CGU_PLL_SR0_PHASE_DIV_EN 1 + +/* + * CGU PLL1 NMK Register + */ +#define CGU_PLL_NMK1_PLLN ((*DANUBE_CGU_PLL_NMK1 & (0xFFFFFFFF ^ ((1 << 24) - 1))) >> 24) +#define CGU_PLL_NMK1_PLLM GET_BITS(*DANUBE_CGU_PLL_NMK1, 23, 20) +#define CGU_PLL_NMK1_PLLK GET_BITS(*DANUBE_CGU_PLL_NMK1, 19, 0) + +/* + * CGU PLL1 Status Register + */ +#define CGU_PLL_SR1_PLLDIV ((*DANUBE_CGU_PLL_SR1 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28) +#define CGU_PLL_SR1_PLLDEN (*DANUBE_CGU_PLL_SR1 & (1 << 26)) +#define CGU_PLL_SR1_PLLPSE GET_BITS(*DANUBE_CGU_PLL_SR1, 5, 4) +#define CGU_PLL_SR1_PLLB (*DANUBE_CGU_PLL_SR1 & (1 << 2)) +#define CGU_PLL_SR1_PLLL (*DANUBE_CGU_PLL_SR1 & (1 << 1)) +#define CGU_PLL_SR1_PLLEN (*DANUBE_CGU_PLL_SR1 & (1 << 0)) + +#define CGU_PLL_SR1_DSMSEL 1 +#define CGU_PLL_SR1_PHASE_DIV_EN 1 + +/* + * CGU PLL2 Status Register + */ +#define CGU_PLL_SR2_PLLDIV ((*DANUBE_CGU_PLL_SR2 & (0xFFFFFFFF ^ ((1 << 28) - 1))) >> 28) +#define CGU_PLL_SR2_PLLDEN (*DANUBE_CGU_PLL_SR2 & (1 << 27)) +#define CGU_PLL_SR2_PLLN GET_BITS(*DANUBE_CGU_PLL_SR2, 25, 20) +#define CGU_PLL_SR2_PLLM GET_BITS(*DANUBE_CGU_PLL_SR2, 19, 16) +#define CGU_PLL_SR2_PLLPS (*DANUBE_CGU_PLL_SR2 & (1 << 5)) +#define CGU_PLL_SR2_PLLPE (*DANUBE_CGU_PLL_SR2 & (1 << 4)) +#define CGU_PLL_SR2_PLLB (*DANUBE_CGU_PLL_SR2 & (1 << 2)) +#define CGU_PLL_SR2_PLLL (*DANUBE_CGU_PLL_SR2 & (1 << 1)) +#define CGU_PLL_SR2_PLLEN (*DANUBE_CGU_PLL_SR2 & (1 << 0)) + +/* + * CGU Interface Clock Register + */ +#define CGU_IF_CLK_CLKOD0 GET_BITS(*DANUBE_CGU_IF_CLK, 27, 26) +#define CGU_IF_CLK_CLKOD1 GET_BITS(*DANUBE_CGU_IF_CLK, 25, 24) +#define CGU_IF_CLK_CLKOD2 GET_BITS(*DANUBE_CGU_IF_CLK, 23, 22) +#define CGU_IF_CLK_CLKOD3 GET_BITS(*DANUBE_CGU_IF_CLK, 21, 20) +#define CGU_IF_CLK_PDA (*DANUBE_CGU_IF_CLK & (1 << 18)) +#define CGU_IF_CLK_PCI_B (*DANUBE_CGU_IF_CLK & (1 << 17)) +#define CGU_IF_CLK_PCIBM (*DANUBE_CGU_IF_CLK & (1 << 16)) +#define CGU_IF_CLK_MIICS (*DANUBE_CGU_IF_CLK & (1 << 3)) +#define CGU_IF_CLK_USBCS (*DANUBE_CGU_IF_CLK & (1 << 2)) +#define CGU_IF_CLK_PCIF (*DANUBE_CGU_IF_CLK & (1 << 1)) +#define CGU_IF_CLK_PCIS (*DANUBE_CGU_IF_CLK & (1 << 0)) + +/* + * CGU Oscillator Control Register + */ +#define CGU_OSC_CTRL GET_BITS(*DANUBE_CGU_OSC_CTRL, 1, 0) + +/* + * CGU SDRAM Memory Delay Register + */ +#define CGU_SMD_CLKI (*DANUBE_CGU_SMD & (1 << 31)) +#define CGU_SMD_MIDS GET_BITS(*DANUBE_CGU_SMD, 17, 12) +#define CGU_SMD_MODS GET_BITS(*DANUBE_CGU_SMD, 11, 6) +#define CGU_SMD_MDSEL GET_BITS(*DANUBE_CGU_SMD, 5, 0) + +/* + * CGU CPU Clock Reduction Register + */ +#define CGU_CRD_SFTR (*DANUBE_CGU_CRD & (1 << 31)) +#define CGU_CRD_DIVE (*DANUBE_CGU_CRD & (1 << 16)) +#define CGU_CRD_CRD1 GET_BITS(*DANUBE_CGU_CRD, 3, 2) +#define CGU_CRD_CRD GET_BITS(*DANUBE_CGU_CRD, 1, 0) + +/* + * CGU CT Status Register 1 + */ +#define CGU_CT1SR_PDOUT GET_BITS(*DANUBE_CGU_CT1SR, 13, 0) + +/* + * CGU CT Status Register 2 + */ +#define CGU_CT2SR_PLL1K GET_BITS(*DANUBE_CGU_CT2SR, 9, 0) + +/* + * CGU PCM Control Register + */ +#define CGU_PCMCR_DCL1 GET_BITS(*DANUBE_CGU_PCMCR, 27, 25) +#define CGU_PCMCR_MUXDCL (*DANUBE_CGU_PCMCR & (1 << 22)) +#define CGU_PCMCR_MUXFSC (*DANUBE_CGU_PCMCR & (1 << 18)) +#define CGU_PCMCR_PCM_SL (*DANUBE_CGU_PCMCR & (1 << 13)) +#define CGU_PCMCR_DNTR (*DANUBE_CGU_PCMCR & (1 << 12)) + +/* + * CGU Clock Mux Register + */ +#define CGU_MUX_MII_CLK (*DANUBE_CGU_MUX & (1 << 6)) +#define CGU_MUX_SUB_SYS GET_BITS(*DANUBE_CGU_MUX, 5, 3) +#define CGU_MUX_PP32 GET_BITS(*DANUBE_CGU_MUX, 1, 0) + + +/* + * #################################### + * Preparation of Debug on Amazon Chip + * #################################### + */ + +/* + * If try module on Amazon chip, prepare some tricks to prevent invalid memory write. + */ +#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON + u32 g_pFakeRegisters[0x0100]; + + #undef DANUBE_CGU + #define DANUBE_CGU ((u32)g_pFakeRegisters) +#endif // defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON + + +/* + * #################################### + * Data Type + * #################################### + */ + + +/* + * #################################### + * Declaration + * #################################### + */ + +/* + * Pre-declaration of File Operations + */ +static ssize_t cgu_read(struct file *, char *, size_t, loff_t *); +static ssize_t cgu_write(struct file *, const char *, size_t, loff_t *); +static int cgu_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +static int cgu_open(struct inode *, struct file *); +static int cgu_release(struct inode *, struct file *); + +/* + * Pre-declaration of 64-bit Unsigned Integer Operation + */ +static inline void uint64_multiply(unsigned int, unsigned int, unsigned int *); +static inline void uint64_divide(unsigned int *, unsigned int, unsigned int *, unsigned int *); + +/* + * Calculate PLL Frequency + */ +static inline u32 cal_dsm(u32, u32); +static inline u32 mash_dsm(u32, u32, u32); +static inline u32 ssff_dsm_1(u32, u32, u32); +static inline u32 ssff_dsm_2(u32, u32, u32); +static inline u32 dsm(u32 M, u32, u32, int, int); +static inline u32 cgu_get_pll0_fosc(void); +static inline u32 cgu_get_pll0_fps(void); +static inline u32 cgu_get_pll0_fdiv(void); +static inline u32 cgu_get_pll1_fosc(void); +static inline u32 cgu_get_pll1_fps(void); +static inline u32 cgu_get_pll1_fdiv(void); +static inline u32 cgu_get_pll2_fosc(void); +static inline u32 cgu_get_pll2_fps(void); + +/* + * Export Functions + */ +u32 cgu_get_mips_clock(int); +u32 cgu_get_cpu_clock(void); +u32 cgu_get_io_region_clock(void); +u32 cgu_get_fpi_bus_clock(int); +u32 cgu_get_pp32_clock(void); +u32 cgu_get_pci_clock(void); +u32 cgu_get_ethernet_clock(void); +u32 cgu_get_usb_clock(void); +u32 cgu_get_clockout(int); + + +/* + * #################################### + * Local Variable + * #################################### + */ + +static struct file_operations cgu_fops = { + owner: THIS_MODULE, + llseek: no_llseek, + read: cgu_read, + write: cgu_write, + ioctl: cgu_ioctl, + open: cgu_open, + release: cgu_release +}; + +static struct miscdevice cgu_miscdev = { + MISC_DYNAMIC_MINOR, + "danube_cgu_dev", + &cgu_fops +}; + + +/* + * #################################### + * Global Variable + * #################################### + */ + + +/* + * #################################### + * Local Function + * #################################### + */ + +static ssize_t cgu_read(struct file *file, char *buf, size_t count, loff_t *ppos) +{ + return -EPERM; +} + +static ssize_t cgu_write(struct file *file, const char *buf, size_t count, loff_t *ppos) +{ + return -EPERM; +} + +static int cgu_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + struct cgu_clock_rates rates; + + if ( _IOC_TYPE(cmd) != CGU_IOC_MAGIC + || _IOC_NR(cmd) >= CGU_IOC_MAXNR ) + return -ENOTTY; + + if ( _IOC_DIR(cmd) & _IOC_READ ) + ret = !access_ok(VERIFY_WRITE, arg, _IOC_SIZE(cmd)); + else if ( _IOC_DIR(cmd) & _IOC_WRITE ) + ret = !access_ok(VERIFY_READ, arg, _IOC_SIZE(cmd)); + if ( ret ) + return -EFAULT; + + switch ( cmd ) + { + case CGU_GET_CLOCK_RATES: + /* Calculate Clock Rates */ + rates.mips0 = cgu_get_mips_clock(0); + rates.mips1 = cgu_get_mips_clock(1); + rates.cpu = cgu_get_cpu_clock(); + rates.io_region = cgu_get_io_region_clock(); + rates.fpi_bus1 = cgu_get_fpi_bus_clock(1); + rates.fpi_bus2 = cgu_get_fpi_bus_clock(2); + rates.pp32 = cgu_get_pp32_clock(); + rates.pci = cgu_get_pci_clock(); + rates.ethernet = cgu_get_ethernet_clock(); + rates.usb = cgu_get_usb_clock(); + rates.clockout0 = cgu_get_clockout(0); + rates.clockout1 = cgu_get_clockout(1); + rates.clockout2 = cgu_get_clockout(2); + rates.clockout3 = cgu_get_clockout(3); + /* Copy to User Space */ + copy_to_user((char*)arg, (char*)&rates, sizeof(rates)); + + ret = 0; + break; + default: + ret = -ENOTTY; + } + + return ret; +} + +static int cgu_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int cgu_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* + * Description: + * calculate 64-bit multiplication result of two 32-bit unsigned integer + * Input: + * u32Multiplier1 --- u32 (32-bit), one of the multipliers + * u32Multiplier2 --- u32 (32-bit), the other multiplier + * u32Result --- u32[2], array to retrieve the multiplication result, + * index 0 is high word, index 1 is low word + * Output: +* none + */ +static inline void uint64_multiply(u32 u32Multiplier1, u32 u32Multiplier2, u32 u32Result[2]) +{ + u32 u32Multiplier1LowWord = u32Multiplier1 & 0xFFFF; + u32 u32Multiplier1HighWord = u32Multiplier1 >> 16; + u32 u32Multiplier2LowWord = u32Multiplier2 & 0xFFFF; + u32 u32Multiplier2HighWord = u32Multiplier2 >> 16; + u32 u32Combo1, u32Combo2, u32Combo3, u32Combo4; + u32 u32Word1, u32Word2, u32Word3, u32Word4; + + u32Combo1 = u32Multiplier1LowWord * u32Multiplier2LowWord; + u32Combo2 = u32Multiplier1HighWord * u32Multiplier2LowWord; + u32Combo3 = u32Multiplier1LowWord * u32Multiplier2HighWord; + u32Combo4 = u32Multiplier1HighWord * u32Multiplier2HighWord; + + u32Word1 = u32Combo1 & 0xFFFF; + u32Word2 = (u32Combo1 >> 16) + (u32Combo2 & 0xFFFF) + (u32Combo3 & 0xFFFF); + u32Word3 = (u32Combo2 >> 16) + (u32Combo3 >> 16) + (u32Combo4 & 0xFFFF) + (u32Word2 >> 16); + u32Word4 = (u32Combo4 >> 16) + (u32Word3 >> 16); + + u32Result[0] = (u32Word4 << 16) | u32Word3; + u32Result[1] = (u32Word2 << 16) | u32Word1; +} + +/* + * Description: + * divide 64-bit unsigned integer with 32-bit unsigned integer + * Input: + * u32Numerator --- u32[2], index 0 is high word of numerator, while + * index 1 is low word of numerator + * u32Denominator --- u32 (32-bit), the denominator in division, this + * parameter can not be zero, or lead to unpredictable + * result + * pu32Quotient --- u32 *, the pointer to retrieve 32-bit quotient, null + * pointer means ignore quotient + * pu32Residue --- u32 *, the pointer to retrieve 32-bit residue null + * pointer means ignore residue + * Output: + * none + */ +static inline void uint64_divide(u32 u32Numerator[2], u32 u32Denominator, u32 *pu32Quotient, u32 *pu32Residue) +{ + u32 u32DWord1, u32DWord2, u32DWord3; + u32 u32Quotient; + int i; + + u32DWord3 = 0; + u32DWord2 = u32Numerator[0]; + u32DWord1 = u32Numerator[1]; + + u32Quotient = 0; + + for ( i = 0; i < 64; i++ ) + { + u32DWord3 = (u32DWord3 << 1) | (u32DWord2 >> 31); + u32DWord2 = (u32DWord2 << 1) | (u32DWord1 >> 31); + u32DWord1 <<= 1; + u32Quotient <<= 1; + if ( u32DWord3 >= u32Denominator ) + { + u32DWord3 -= u32Denominator; + u32Quotient |= 1; + } + } + if ( pu32Quotient ) + *pu32Quotient = u32Quotient; + if ( pu32Residue ) + *pu32Residue = u32DWord3; +} + +/* + * Description: + * common routine to calculate PLL frequency + * Input: + * num --- u32, numerator + * den --- u32, denominator + * Output: + * u32 --- frequency the PLL output + */ +static inline u32 cal_dsm(u32 num, u32 den) +{ + u32 ret; + u32 temp[2]; + u32 residue; + + uint64_multiply(num, BASIC_INPUT_CLOCK_FREQUENCY, temp); + uint64_divide(temp, den, &ret, &residue); + if ( (residue << 1) >= den ) + ret++; + + return ret; +} + +/* + * Description: + * calculate PLL frequency following MASH-DSM + * Input: + * M --- u32, denominator coefficient + * N --- u32, numerator integer coefficient + * K --- u32, numerator fraction coefficient + * Output: + * u32 --- frequency the PLL output + */ +static inline u32 mash_dsm(u32 M, u32 N, u32 K) +{ + u32 num = ((N + 1) << 10) + K; + u32 den = (M + 1) << 10; + + return cal_dsm(num, den); +} + +/* + * Description: + * calculate PLL frequency following SSFF-DSM (0.25 < fraction < 0.75) + * Input: + * M --- u32, denominator coefficient + * N --- u32, numerator integer coefficient + * K --- u32, numerator fraction coefficient + * Output: + * u32 --- frequency the PLL output + */ +static inline u32 ssff_dsm_1(u32 M, u32 N, u32 K) +{ + u32 num = ((N + 1) << 11) + K + 512; + u32 den = (M + 1) << 11; + + return cal_dsm(num, den); +} + +/* + * Description: + * calculate PLL frequency following SSFF-DSM + * (fraction < 0.125 || fraction > 0.875) + * Input: + * M --- u32, denominator coefficient + * N --- u32, numerator integer coefficient + * K --- u32, numerator fraction coefficient + * Output: + * u32 --- frequency the PLL output + */ +static inline u32 ssff_dsm_2(u32 M, u32 N, u32 K) +{ + u32 num = K >= 512 ? ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584; + u32 den = (M + 1) << 12; + + return cal_dsm(num, den); +} + +/* + * Description: + * calculate PLL frequency + * Input: + * M --- u32, denominator coefficient + * N --- u32, numerator integer coefficient + * K --- u32, numerator fraction coefficient + * dsmsel --- int, 0: MASH-DSM, 1: SSFF-DSM + * phase_div_en --- int, 0: 0.25 < fraction < 0.75 + * 1: fraction < 0.125 || fraction > 0.875 + * Output: + * u32 --- frequency the PLL output + */ +static inline u32 dsm(u32 M, u32 N, u32 K, int dsmsel, int phase_div_en) +{ + if ( !dsmsel ) + return mash_dsm(M, N, K); + else + if ( !phase_div_en ) + return ssff_dsm_1(M, N, K); + else + return ssff_dsm_2(M, N, K); +} + +/* + * Description: + * get oscillate frequency of PLL0 + * Input: + * none + * Output: + * u32 --- frequency of PLL0 Fosc + */ +static inline u32 cgu_get_pll0_fosc(void) +{ + return CGU_PLL_SR0_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_DSMSEL, CGU_PLL_SR0_PHASE_DIV_EN); +} + +/* + * Description: + * get output frequency of PLL0 phase shifter + * Input: + * none + * Output: + * u32 --- frequency of PLL0 Fps + */ +static inline u32 cgu_get_pll0_fps(void) +{ + register u32 fps = cgu_get_pll0_fosc(); + + switch ( CGU_PLL_SR0_PLLPSE ) + { + case 1: + /* 1.5 */ + fps = ((fps << 1) + 1) / 3; break; + case 2: + /* 1.25 */ + fps = ((fps << 2) + 2) / 5; break; + case 3: + /* 3.5 */ + fps = ((fps << 1) + 3) / 7; + } + return fps; +} + +/* + * Description: + * get output frequency of PLL0 output divider + * Input: + * none + * Output: + * u32 --- frequency of PLL0 Fdiv + */ +static inline u32 cgu_get_pll0_fdiv(void) +{ + register u32 fdiv = cgu_get_pll0_fosc(); + + if ( CGU_PLL_SR0_PLLDEN ) + fdiv = (fdiv + (CGU_PLL_SR0_PLLDIV + 1) / 2) / (CGU_PLL_SR0_PLLDIV + 1); + return fdiv; +} + +/* + * Description: + * get oscillate frequency of PLL1 + * Input: + * none + * Output: + * u32 --- frequency of PLL1 Fosc + */ +static inline u32 cgu_get_pll1_fosc(void) +{ + return CGU_PLL_SR1_PLLB ? BASIC_INPUT_CLOCK_FREQUENCY : dsm(CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_DSMSEL, CGU_PLL_SR1_PHASE_DIV_EN); +} + +/* + * Description: + * get output frequency of PLL1 phase shifter + * Input: + * none + * Output: + * u32 --- frequency of PLL1 Fps + */ +static inline u32 cgu_get_pll1_fps(void) +{ + register u32 fps = cgu_get_pll1_fosc(); + + switch ( CGU_PLL_SR1_PLLPSE ) + { + case 1: + /* 1.5 */ + fps = ((fps << 1) + 1) / 3; break; + case 2: + /* 1.25 */ + fps = ((fps << 2) + 2) / 5; break; + case 3: + /* 3.5 */ + fps = ((fps << 1) + 3) / 7; + } + return fps; +} + +/* + * Description: + * get output frequency of PLL1 output divider + * Input: + * none + * Output: + * u32 --- frequency of PLL1 Fdiv + */ +static inline u32 cgu_get_pll1_fdiv(void) +{ + register u32 fdiv = cgu_get_pll1_fosc(); + + if ( CGU_PLL_SR1_PLLDEN ) + fdiv = (fdiv + (CGU_PLL_SR1_PLLDIV + 1) / 2) / (CGU_PLL_SR1_PLLDIV + 1); + return fdiv; +} + +/* + * Description: + * get oscillate frequency of PLL2 + * Input: + * none + * Output: + * u32 --- frequency of PLL2 Fosc + */ +static inline u32 cgu_get_pll2_fosc(void) +{ + u32 ret; + u32 temp[2]; + u32 residue; + + uint64_multiply((CGU_PLL_SR2_PLLN + 1) * 8, cgu_get_pll0_fdiv(), temp); + uint64_divide(temp, CGU_PLL_SR2_PLLM + 1, &ret, &residue); + if ( (residue << 1) >= CGU_PLL_SR2_PLLM ) + ret++; + + return ret; +} + +/* + * Description: + * get output frequency of PLL2 phase shifter + * Input: + * none + * Output: + * u32 --- frequency of PLL2 Fps + */ +static inline u32 cgu_get_pll2_fps(void) +{ + register u32 fps = cgu_get_pll2_fosc(); + + if ( CGU_PLL_SR2_PLLPE ) + { + if ( CGU_PLL_SR2_PLLPS ) + /* 1.25 */ + fps = ((fps << 3) + 4) / 9; + else + /* 1.125 */ + fps = ((fps << 2) + 2) / 5; + } + + return fps; +} + + +/* + * #################################### + * Global Function + * #################################### + */ + +/* + * Description: + * get frequency of MIPS (0: core, 1: DSP) + * Input: + * cpu --- int, 0: core, 1: DSP + * Output: + * u32 --- frequency of MIPS coprocessor (0: core, 1: DSP) + */ +u32 cgu_get_mips_clock(int cpu) +{ + register u32 ret = cgu_get_pll0_fosc(); + + if ( CGU_CRD_CRD ) + ret = (ret + (CGU_CRD_CRD >> 1)) / (CGU_CRD_CRD + 1); + if ( cpu == 0 && CGU_CRD_CRD1 ) + ret >>= CGU_CRD_CRD1; + return ret; +} + +/* + * Description: + * get frequency of MIPS core + * Input: + * none + * Output: + * u32 --- frequency of MIPS core + */ +u32 cgu_get_cpu_clock(void) +{ + return cgu_get_mips_clock(0); +} + +/* + * Description: + * get frequency of sub-system and memory controller + * Input: + * none + * Output: + * u32 --- frequency of sub-system and memory controller + */ +u32 cgu_get_io_region_clock(void) +{ + register u32 ret = (CGU_MUX_SUB_SYS > 4) ? cgu_get_pll0_fosc() : cgu_get_mips_clock(1); + + switch ( CGU_MUX_SUB_SYS ) + { + case 0: + break; + case 1: + default: + ret = (ret + 1) >> 1; break; + case 2: + ret = (ret + 1) / 3; break; + case 3: + ret = (ret + 2) >> 2; break; + case 5: + ret = ((ret << 1) + 1) / 3; break; + case 6: + ret = ((ret << 1) + 2) / 5; + } + + return ret; +} + +/* + * Description: + * get frequency of FPI bus + * Input: + * fpi --- int, 1: FPI bus 1 (FBS1/Fast FPI Bus), 2: FPI bus 2 (FBS2) + * Output: + * u32 --- frequency of FPI bus + */ +u32 cgu_get_fpi_bus_clock(int fpi) +{ + register u32 ret = cgu_get_io_region_clock(); + + if ( fpi == 2 ) + ret >>= 1; + return ret; +} + +/* + * Description: + * get frequency of PP32 processor + * Input: + * none + * Output: + * u32 --- frequency of PP32 processor + */ +u32 cgu_get_pp32_clock(void) +{ + register u32 ret; + + switch ( CGU_MUX_PP32 ) + { + case 0: + default: + ret = ((cgu_get_pll2_fosc() << 2) + 2) / 5; break; + case 1: + ret = ((cgu_get_pll2_fosc() << 3) + 4) / 9; break; + case 2: + ret = cgu_get_fpi_bus_clock(1); break; + case 3: + ret = cgu_get_mips_clock(1); + } + + return ret; +} + +/* + * Description: + * get frequency of PCI bus + * Input: + * none + * Output: + * u32 --- frequency of PCI bus + */ +u32 cgu_get_pci_clock(void) +{ + register u32 ret = 0; + + if ( !CGU_IF_CLK_PCIS ) + { + ret = cgu_get_pll2_fosc(); + if ( CGU_IF_CLK_PCIF ) + ret = (ret + 2) / 5; + else + ret = (ret + 4) / 9; + } + + return ret; +} + +/* + * Description: + * get frequency of ethernet module (MII) + * Input: + * none + * Output: + * u32 --- frequency of ethernet module + */ +u32 cgu_get_ethernet_clock(void) +{ + register u32 ret = 0; + + if ( !CGU_IF_CLK_MIICS ) + { + ret = cgu_get_pll2_fosc(); + if ( CGU_MUX_MII_CLK ) + ret = (ret + 3) / 6; + else + ret = (ret + 6) / 12; + } + + return ret; +} + +/* + * Description: + * get frequency of USB + * Input: + * none + * Output: + * u32 --- frequency of USB + */ +u32 cgu_get_usb_clock(void) +{ + return CGU_IF_CLK_USBCS ? 12000000 : (cgu_get_pll2_fosc() + 12) / 25; +} + +/* + * Description: + * get frequency of CLK_OUT pin + * Input: + * clkout --- int, clock out pin number + * Output: + * u32 --- frequency of CLK_OUT pin + */ +u32 cgu_get_clockout(int clkout) +{ + u32 fosc1 = cgu_get_pll1_fosc(); + u32 fosc2 = cgu_get_pll2_fosc(); + + if ( clkout > 3 || clkout < 0 ) + return 0; + + switch ( ((u32)clkout << 2) | GET_BITS(*DANUBE_CGU_IF_CLK, 21 + clkout * 2, 20 + clkout * 2) ) + { + case 0: /* 32.768KHz */ + case 14: + return (fosc1 + 6000) / 12000; + case 1: /* 1.536MHz */ + return (fosc1 + 128) / 256; + case 2: /* 2.5MHz */ + return (fosc2 + 60) / 120; + case 3: /* 12MHz */ + case 5: + case 12: + return (fosc2 + 12) / 25; + case 4: /* 40MHz */ + return (fosc2 * 2 + 7) / 15; + case 6: /* 24MHz */ + return (fosc2 * 2 + 12) / 25; + case 7: /* 48MHz */ + return (fosc2 * 4 + 12) / 25; + case 8: /* 25MHz */ + case 15: + return (fosc2 + 6) / 12; + case 9: /* 50MHz */ + case 13: + return (fosc2 + 3) / 6; + case 10:/* 30MHz */ + return (fosc2 + 5) / 10; + case 11:/* 60MHz */ + return (fosc2 + 2) / 5; + } + + return 0; +} + + +/* + * #################################### + * Init/Cleanup API + * #################################### + */ + +/* + * Description: + * register device + * Input: + * none + * Output: + * 0 --- successful + * else --- failure, usually it is negative value of error code + */ +int __init danube_cgu_init(void) +{ + int ret; + + ret = misc_register(&cgu_miscdev); + if ( ret ) + { + printk(KERN_ERR "cgu: can't misc_register\n"); + return ret; + } + else + printk(KERN_INFO "cgu: misc_register on minor = %d\n", cgu_miscdev.minor); + + /* + * initialize fake registers to do testing on Amazon + */ +#if defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON + #ifdef DEBUG_PRINT_INFO + #undef DEBUG_PRINT_INFO + #endif + #define DEBUG_PRINT_INFO 1 + + *DANUBE_CGU_DIV = 0x00010019; + *DANUBE_CGU_PLL_NMK0 = 0x416002C3; + *DANUBE_CGU_PLL_SR0 = 0x74000013; + *DANUBE_CGU_PLL_NMK1 = 0x4C60009C; + *DANUBE_CGU_PLL_SR1 = 0x54000013; + *DANUBE_CGU_PLL_SR2 = 0x58890013; + *DANUBE_CGU_IF_CLK = 0x00000000; + *DANUBE_CGU_OSC_CTRL = 0x00000000; + *DANUBE_CGU_SMD = 0x00000000; + *DANUBE_CGU_CRD = 0x00010000; + *DANUBE_CGU_CT1SR = 0x00000000; + *DANUBE_CGU_CT2SR = CGU_PLL_NMK1_PLLK; + *DANUBE_CGU_PCMCR = 0x00000000; + *DANUBE_CGU_MUX = 0x00000008; +#endif // defined(DEBUG_ON_AMAZON) && DEBUG_ON_AMAZON + + /* + * for testing only + */ +#if defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO + printk("pll0 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK0_PLLN, CGU_PLL_NMK0_PLLM, CGU_PLL_NMK0_PLLK, CGU_PLL_SR0_PLLDIV); + printk("pll1 N = %d, M = %d, K = %d, DIV = %d\n", CGU_PLL_NMK1_PLLN, CGU_PLL_NMK1_PLLM, CGU_PLL_NMK1_PLLK, CGU_PLL_SR1_PLLDIV); + printk("pll2 N = %d, M = %d, DIV = %d\n", CGU_PLL_SR2_PLLN, CGU_PLL_SR2_PLLM, CGU_PLL_SR2_PLLDIV); + printk("pll0_fosc = %d\n", cgu_get_pll0_fosc()); + printk("pll0_fps = %d\n", cgu_get_pll0_fps()); + printk("pll0_fdiv = %d\n", cgu_get_pll0_fdiv()); + printk("pll1_fosc = %d\n", cgu_get_pll1_fosc()); + printk("pll1_fps = %d\n", cgu_get_pll1_fps()); + printk("pll1_fdiv = %d\n", cgu_get_pll1_fdiv()); + printk("pll2_fosc = %d\n", cgu_get_pll2_fosc()); + printk("pll2_fps = %d\n", cgu_get_pll2_fps()); + printk("mips0 clock = %d\n", cgu_get_mips_clock(0)); + printk("mips1 clock = %d\n", cgu_get_mips_clock(1)); + printk("cpu clock = %d\n", cgu_get_cpu_clock()); + printk("IO region = %d\n", cgu_get_io_region_clock()); + printk("FPI bus 1 = %d\n", cgu_get_fpi_bus_clock(1)); + printk("FPI bus 2 = %d\n", cgu_get_fpi_bus_clock(2)); + printk("PP32 clock = %d\n", cgu_get_pp32_clock()); + printk("PCI clock = %d\n", cgu_get_pci_clock()); + printk("Ethernet = %d\n", cgu_get_ethernet_clock()); + printk("USB clock = %d\n", cgu_get_usb_clock()); + printk("Clockout0 = %d\n", cgu_get_clockout(0)); + printk("Clockout1 = %d\n", cgu_get_clockout(1)); + printk("Clockout2 = %d\n", cgu_get_clockout(2)); + printk("Clockout3 = %d\n", cgu_get_clockout(3)); +#endif // defined(DEBUG_PRINT_INFO) && DEBUG_PRINT_INFO + + return 0; +} + +/* + * Description: + * deregister device + * Input: + * none + * Output: + * none + */ +void __exit danube_cgu_exit(void) +{ + int ret; + + ret = misc_deregister(&cgu_miscdev); + if ( ret ) + printk(KERN_ERR "cgu: can't misc_deregister, get error number %d\n", -ret); + else + printk(KERN_INFO "cgu: misc_deregister successfully\n"); +} + +module_init(danube_cgu_init); +module_exit(danube_cgu_exit); diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h new file mode 100644 index 0000000000..78fe21d624 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cgu.h @@ -0,0 +1,91 @@ +#ifndef __DANUBE_CGU_DEV_H__2005_07_20__14_26__ +#define __DANUBE_CGU_DEV_H__2005_07_20__14_26__ + + +/****************************************************************************** + Copyright (c) 2002, Infineon Technologies. All rights reserved. + + No Warranty + Because the program is licensed free of charge, there is no warranty for + the program, to the extent permitted by applicable law. Except when + otherwise stated in writing the copyright holders and/or other parties + provide the program "as is" without warranty of any kind, either + expressed or implied, including, but not limited to, the implied + warranties of merchantability and fitness for a particular purpose. The + entire risk as to the quality and performance of the program is with + you. should the program prove defective, you assume the cost of all + necessary servicing, repair or correction. + + In no event unless required by applicable law or agreed to in writing + will any copyright holder, or any other party who may modify and/or + redistribute the program as permitted above, be liable to you for + damages, including any general, special, incidental or consequential + damages arising out of the use or inability to use the program + (including but not limited to loss of data or data being rendered + inaccurate or losses sustained by you or third parties or a failure of + the program to operate with any other programs), even if such holder or + other party has been advised of the possibility of such damages. +******************************************************************************/ + + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * ioctl Command + */ +#define CGU_IOC_MAGIC 'u' +#define CGU_GET_CLOCK_RATES _IOW(CGU_IOC_MAGIC, 0, struct cgu_clock_rates) +#define CGU_IOC_MAXNR 1 + + +/* + * #################################### + * Data Type + * #################################### + */ + +/* + * Data Type Used to Call ioctl(GET_CLOCK_RATES) + */ +struct cgu_clock_rates { + u32 mips0; + u32 mips1; + u32 cpu; + u32 io_region; + u32 fpi_bus1; + u32 fpi_bus2; + u32 pp32; + u32 pci; + u32 ethernet; + u32 usb; + u32 clockout0; + u32 clockout1; + u32 clockout2; + u32 clockout3; +}; + + +/* + * #################################### + * Declaration + * #################################### + */ + +#if defined(__KERNEL__) + extern u32 cgu_get_mips_clock(int); + extern u32 cgu_get_cpu_clock(void); + extern u32 cgu_get_io_region_clock(void); + extern u32 cgu_get_fpi_bus_clock(int); + extern u32 cgu_get_pp32_clock(void); + extern u32 cgu_get_pci_clock(void); + extern u32 cgu_get_ethernet_clock(void); + extern u32 cgu_get_usb_clock(void); + extern u32 cgu_get_clockout(int); +#endif // defined(__KERNEL__) + + +#endif // __DANUBE_CGU_DEV_H__2005_07_20__14_26__ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c new file mode 100644 index 0000000000..0a1cdacdc3 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_clock.c @@ -0,0 +1,91 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include + + + +/******************************************************************************* +* +* get_cpuclk - returns the frequency of the CPU. +* +* NOTE: +* This functions should be used by the hardware driver to get the correct +* frequency of the CPU. +*/ + +unsigned int danube_get_ddr_hz(void) +{ + switch((*DANUBE_CGU_SYS) & 0x3){ + case 0: + return 166666667; + case 1: + return 133333333; + case 2: + return 111111111; + case 3: + return 83333333; + } +} + + +uint danube_get_cpuclk(void) +{ +#ifdef CONFIG_USE_EMULATOR + return EMULATOR_CPU_SPEED; +#else //NOT CONFIG_USE_EMULATOR + unsigned int ddr_clock=danube_get_ddr_hz(); + switch((*DANUBE_CGU_SYS) & 0xc){ + case 0: + return 333333333; + case 4: + return ddr_clock; + case 8: + return ddr_clock << 1; + default: + break; + /*reserved*/ + } +#endif + +} + + +uint danube_get_fpiclk(void) +{ +#ifdef CONFIG_USE_EMULATOR + unsigned int clkCPU; + clkCPU = danube_get_cpu_hz(); + return clkCPU >> 2; +#else //NOT CONFIG_USE_EMULATOR + unsigned int ddr_clock=danube_get_ddr_hz(); + if ((*DANUBE_CGU_SYS) & 0x40){ + return ddr_clock >> 1; + } + return ddr_clock; +#endif + +} + + diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c new file mode 100644 index 0000000000..49355de55a --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_cpu.c @@ -0,0 +1,5 @@ + +#define IFX_CPU_RESET \ +{ *DANUBE_RCU_RST_REQ |=1<<30; \ +} + diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S new file mode 100644 index 0000000000..17c0b0ae55 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/ifx_start.S @@ -0,0 +1,51 @@ +/* + * IFX Platform Dependent CPU Initializations + * - for Danube + */ + +#define IFX_EBU_BOOTCFG_DWORD \ + .word INFINEON_EBU_BOOTCFG; /* EBU init code, fetched during booting */ \ + .word 0x00000000; /* phases of the flash */ + +#define IFX_MORE_RESERVED_VECTORS \ + XVECENT(romExcHandle,0x400); /* Int, CauseIV=1 */ \ + RVECENT(romReserved,129); \ + RVECENT(romReserved,130); \ + RVECENT(romReserved,131); \ + RVECENT(romReserved,132); \ + RVECENT(romReserved,133); \ + RVECENT(romReserved,134); \ + RVECENT(romReserved,135); \ + RVECENT(romReserved,136); \ + RVECENT(romReserved,137); \ + RVECENT(romReserved,138); \ + RVECENT(romReserved,139); \ + RVECENT(romReserved,140); \ + RVECENT(romReserved,141); \ + RVECENT(romReserved,142); \ + RVECENT(romReserved,143); \ + RVECENT(romExcHandle,0x480); /* EJTAG debug exception */ + +#define IFX_RESET_PRECHECK \ + mfc0 k0, CP0_EBASE; \ + and k0, EBASEF_CPUNUM; \ + bne k0, zero, ifx_mips_handler_1; \ + nop; + +#define IFX_CPU_EXTRA_INIT \ + mfc0 k0, CP0_CONFIG, 7; \ + li k1, 0x04; \ + or k0, k1; \ + mtc0 k0, CP0_CONFIG, 7; + +#define IFX_CACHE_OPER_MODE \ + li t0, CONF_CM_CACHABLE_NO_WA; + +/* + * Stop VCPU + */ +#define IFX_MIPS_HANDLER_1 \ + wait; \ + b ifx_mips_handler_1; \ + nop; + diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c new file mode 100644 index 0000000000..1b0a0fd399 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_clock.c @@ -0,0 +1,120 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#ifdef CONFIG_INCA_IP + +#include +#include + + +/******************************************************************************* +* +* get_cpuclk - returns the frequency of the CPU. +* +* Gets the value directly from the INCA-IP hardware. +* +* RETURNS: +* 150.000.000 for 150 MHz +* 133.333.333 for 133 Mhz (= 400MHz/3) +* 100.000.000 for 100 Mhz (= 400MHz/4) +* NOTE: +* This functions should be used by the hardware driver to get the correct +* frequency of the CPU. Don't use the macros, which are set to init the CPU +* frequency in the ROM code. +*/ +uint incaip_get_cpuclk (void) +{ + /*-------------------------------------------------------------------------*/ + /* CPU Clock Input Multiplexer (MUX I) */ + /* Multiplexer MUX I selects the maximum input clock to the CPU. */ + /*-------------------------------------------------------------------------*/ + if (*((volatile ulong *) INCA_IP_CGU_CGU_MUXCR) & + INCA_IP_CGU_CGU_MUXCR_MUXI) { + /* MUX I set to 150 MHz clock */ + return 150000000; + } else { + /* MUX I set to 100/133 MHz clock */ + if (*((volatile ulong *) INCA_IP_CGU_CGU_DIVCR) & 0x40) { + /* Division value is 1/3, maximum CPU operating */ + /* frequency is 133.3 MHz */ + return 133333333; + } else { + /* Division value is 1/4, maximum CPU operating */ + /* frequency is 100 MHz */ + return 100000000; + } + } +} + +/******************************************************************************* +* +* get_fpiclk - returns the frequency of the FPI bus. +* +* Gets the value directly from the INCA-IP hardware. +* +* RETURNS: Frquency in Hz +* +* NOTE: +* This functions should be used by the hardware driver to get the correct +* frequency of the CPU. Don't use the macros, which are set to init the CPU +* frequency in the ROM code. +* The calculation for the +*/ +uint incaip_get_fpiclk (void) +{ + uint clkCPU; + + clkCPU = incaip_get_cpuclk (); + + switch (*((volatile ulong *) INCA_IP_CGU_CGU_DIVCR) & 0xC) { + case 0x4: + return clkCPU >> 1; /* devided by 2 */ + break; + case 0x8: + return clkCPU >> 2; /* devided by 4 */ + break; + default: + return clkCPU; + break; + } +} + +int incaip_set_cpuclk (void) +{ + extern void ebu_init(long); + extern void cgu_init(long); + extern void sdram_init(long); + char tmp[64]; + ulong cpuclk; + + if (getenv_r ("cpuclk", tmp, sizeof (tmp)) > 0) { + cpuclk = simple_strtoul (tmp, NULL, 10) * 1000000; + cgu_init (cpuclk); + ebu_init (cpuclk); + sdram_init (cpuclk); + } + + return 0; +} + +#endif /* CONFIG_INCA_IP */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S new file mode 100644 index 0000000000..0c6b5e2015 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/incaip_wdt.S @@ -0,0 +1,75 @@ +/* + * INCA-IP Watchdog timer management code. + * + * Copyright (c) 2003 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include +#include +#include + +#ifdef CONFIG_INCA_IP + +#define WD_BASE 0xb8000000 +#define WD_CON0(value) 0x0020(value) +#define WD_CON1(value) 0x0024(value) +#define WD_DISABLE 0x00000008 +#define WD_ENABLE 0x00000000 +#define WD_WRITE_PW 0xFFFC00F8 +#define WD_WRITE_ENDINIT 0xFFFC00F3 +#define WD_WRITE_INIT 0xFFFC00F2 + + + .globl disable_incaip_wdt +disable_incaip_wdt: + li t0, WD_BASE + + /* Calculate password. + */ + lw t2, WD_CON1(t0) + and t2, 0xC + + lw t3, WD_CON0(t0) + and t3, 0xFFFFFF01 + + or t3, t2 + or t3, 0xF0 + + sw t3, WD_CON0(t0) /* write password */ + + /* Clear ENDINIT. + */ + li t1, WD_WRITE_INIT + sw t1, WD_CON0(t0) + + + li t1, WD_DISABLE + sw t1, WD_CON1(t0) /* disable watchdog */ + li t1, WD_WRITE_PW + sw t1, WD_CON0(t0) /* write password */ + li t1, WD_WRITE_ENDINIT + sw t1, WD_CON0(t0) /* end command */ + + j ra + nop + +#endif /* CONFIG_INCA_IP */ diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c b/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c new file mode 100644 index 0000000000..87f7a9f7e6 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/interrupts.c @@ -0,0 +1,33 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +void enable_interrupts(void) +{ +} + +int disable_interrupts(void) +{ + return 0; +} diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/start.S b/package/uboot-ifxmips/files/cpu/mips/danube/start.S new file mode 100644 index 0000000000..b1ee491d3b --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/start.S @@ -0,0 +1,442 @@ +/* + * Startup Code for MIPS32 CPU-core + * + * Copyright (c) 2003 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include +#include +#include +#include +#if defined(CONFIG_IFX_MIPS) +#include "ifx_start.S" +#endif + +#define RVECENT(f,n) \ + b f; nop +#define XVECENT(f,bev) \ + b f ; \ + li k0,bev + + .set noreorder + + .globl _start + .text +_start: + RVECENT(reset,0) /* U-boot entry point */ + RVECENT(reset,1) /* software reboot */ +#if defined(CONFIG_INCA_IP) + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word 0x00000000 /* phase of the flash */ +#elif defined(CONFIG_IFX_MIPS) && defined(IFX_EBU_BOOTCFG_DWORD) + IFX_EBU_BOOTCFG_DWORD +#elif defined(CONFIG_PURPLE) + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ +#else + RVECENT(romReserved,2) +#endif + RVECENT(romReserved,3) + RVECENT(romReserved,4) + RVECENT(romReserved,5) + RVECENT(romReserved,6) + RVECENT(romReserved,7) + RVECENT(romReserved,8) + RVECENT(romReserved,9) + RVECENT(romReserved,10) + RVECENT(romReserved,11) + RVECENT(romReserved,12) + RVECENT(romReserved,13) + RVECENT(romReserved,14) + RVECENT(romReserved,15) + RVECENT(romReserved,16) + RVECENT(romReserved,17) + RVECENT(romReserved,18) + RVECENT(romReserved,19) + RVECENT(romReserved,20) + RVECENT(romReserved,21) + RVECENT(romReserved,22) + RVECENT(romReserved,23) + RVECENT(romReserved,24) + RVECENT(romReserved,25) + RVECENT(romReserved,26) + RVECENT(romReserved,27) + RVECENT(romReserved,28) + RVECENT(romReserved,29) + RVECENT(romReserved,30) + RVECENT(romReserved,31) + RVECENT(romReserved,32) + RVECENT(romReserved,33) + RVECENT(romReserved,34) + RVECENT(romReserved,35) + RVECENT(romReserved,36) + RVECENT(romReserved,37) + RVECENT(romReserved,38) + RVECENT(romReserved,39) + RVECENT(romReserved,40) + RVECENT(romReserved,41) + RVECENT(romReserved,42) + RVECENT(romReserved,43) + RVECENT(romReserved,44) + RVECENT(romReserved,45) + RVECENT(romReserved,46) + RVECENT(romReserved,47) + RVECENT(romReserved,48) + RVECENT(romReserved,49) + RVECENT(romReserved,50) + RVECENT(romReserved,51) + RVECENT(romReserved,52) + RVECENT(romReserved,53) + RVECENT(romReserved,54) + RVECENT(romReserved,55) + RVECENT(romReserved,56) + RVECENT(romReserved,57) + RVECENT(romReserved,58) + RVECENT(romReserved,59) + RVECENT(romReserved,60) + RVECENT(romReserved,61) + RVECENT(romReserved,62) + RVECENT(romReserved,63) + XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */ + RVECENT(romReserved,65) + RVECENT(romReserved,66) + RVECENT(romReserved,67) + RVECENT(romReserved,68) + RVECENT(romReserved,69) + RVECENT(romReserved,70) + RVECENT(romReserved,71) + RVECENT(romReserved,72) + RVECENT(romReserved,73) + RVECENT(romReserved,74) + RVECENT(romReserved,75) + RVECENT(romReserved,76) + RVECENT(romReserved,77) + RVECENT(romReserved,78) + RVECENT(romReserved,79) + XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */ + RVECENT(romReserved,81) + RVECENT(romReserved,82) + RVECENT(romReserved,83) + RVECENT(romReserved,84) + RVECENT(romReserved,85) + RVECENT(romReserved,86) + RVECENT(romReserved,87) + RVECENT(romReserved,88) + RVECENT(romReserved,89) + RVECENT(romReserved,90) + RVECENT(romReserved,91) + RVECENT(romReserved,92) + RVECENT(romReserved,93) + RVECENT(romReserved,94) + RVECENT(romReserved,95) + XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */ + RVECENT(romReserved,97) + RVECENT(romReserved,98) + RVECENT(romReserved,99) + RVECENT(romReserved,100) + RVECENT(romReserved,101) + RVECENT(romReserved,102) + RVECENT(romReserved,103) + RVECENT(romReserved,104) + RVECENT(romReserved,105) + RVECENT(romReserved,106) + RVECENT(romReserved,107) + RVECENT(romReserved,108) + RVECENT(romReserved,109) + RVECENT(romReserved,110) + RVECENT(romReserved,111) + XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */ + RVECENT(romReserved,113) + RVECENT(romReserved,114) + RVECENT(romReserved,115) + RVECENT(romReserved,116) + RVECENT(romReserved,116) + RVECENT(romReserved,118) + RVECENT(romReserved,119) + RVECENT(romReserved,120) + RVECENT(romReserved,121) + RVECENT(romReserved,122) + RVECENT(romReserved,123) + RVECENT(romReserved,124) + RVECENT(romReserved,125) + RVECENT(romReserved,126) + RVECENT(romReserved,127) + + /* We hope there are no more reserved vectors! + * 128 * 8 == 1024 == 0x400 + * so this is address R_VEC+0x400 == 0xbfc00400 + */ +#if defined(CONFIG_IFX_MIPS) && defined(IFX_MORE_RESERVED_VECTORS) + IFX_MORE_RESERVED_VECTORS +#else +#ifdef CONFIG_PURPLE +/* 0xbfc00400 */ + .word 0xdc870000 + .word 0xfca70000 + .word 0x20840008 + .word 0x20a50008 + .word 0x20c6ffff + .word 0x14c0fffa + .word 0x00000000 + .word 0x03e00008 + .word 0x00000000 + .word 0x00000000 +/* 0xbfc00428 */ + .word 0xdc870000 + .word 0xfca70000 + .word 0x20840008 + .word 0x20a50008 + .word 0x20c6ffff + .word 0x14c0fffa + .word 0x00000000 + .word 0x03e00008 + .word 0x00000000 + .word 0x00000000 +#endif /* CONFIG_PURPLE */ +#endif /* CONFIG_IFX_MIPS */ + .align 4 +reset: +#if defined(CONFIG_IFX_MIPS) && defined(IFX_RESET_PRECHECK) + IFX_RESET_PRECHECK +#endif + /* Clear watch registers. + */ + mtc0 zero, CP0_WATCHLO + mtc0 zero, CP0_WATCHHI + + /* STATUS register */ +#ifdef CONFIG_TB0229 + li k0, ST0_CU0 +#else + mfc0 k0, CP0_STATUS +#endif + li k1, ~ST0_IE + and k0, k1 + mtc0 k0, CP0_STATUS + + /* CAUSE register */ + mtc0 zero, CP0_CAUSE + +#if defined(CONFIG_IFX_MIPS) && defined(IFX_CPU_EXTRA_INIT) + IFX_CPU_EXTRA_INIT +#endif + + /* Init Timer */ + mtc0 zero, CP0_COUNT + mtc0 zero, CP0_COMPARE + + /* CONFIG0 register */ + li t0, CONF_CM_UNCACHED + mtc0 t0, CP0_CONFIG + + /* Initialize GOT pointer. + */ + bal 1f + nop + .word _GLOBAL_OFFSET_TABLE_ + 1: + move gp, ra + lw t1, 0(ra) + move gp, t1 + +#ifdef CONFIG_INCA_IP + /* Disable INCA-IP Watchdog. + */ + la t9, disable_incaip_wdt + jalr t9 + nop +#endif + + /* Initialize any external memory. + */ + la t9, lowlevel_init + jalr t9 + nop + + /* Initialize caches... + */ + la t9, mips_cache_reset + jalr t9 + nop + + /* ... and enable them. + */ +#if defined(CONFIG_IFX_MIPS) && defined(IFX_CACHE_OPER_MODE) + IFX_CACHE_OPER_MODE +#else + li t0, CONF_CM_CACHABLE_NONCOHERENT +#endif + mtc0 t0, CP0_CONFIG + + + /* Set up temporary stack. + */ + li a0, CFG_INIT_SP_OFFSET + la t9, mips_cache_lock + jalr t9 + nop + + li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET + la sp, 0(t0) + + la t9, board_init_f + j t9 + nop + +#ifdef CFG_HEAD_CODE +/* + * void jump_unconditional (addr) + * This function simply jumps to the location pointed by a0. + * a0 = target_location + * + */ + .globl jump_unconditional + .ent jump_unconditional +jump_unconditional: + move t9, a0 + j t9 + nop + .end jump_unconditional + +#endif + +/* + * void relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * a0 = addr_sp + * a1 = gd + * a2 = destination address + */ + .globl relocate_code + .ent relocate_code +relocate_code: + move sp, a0 /* Set new stack pointer */ + +#ifdef CFG_HEAD_CODE + li t0, CFG_HEAD_BASE +#else + li t0, CFG_MONITOR_BASE +#endif + la t3, in_ram + lw t2, -12(t3) /* t2 <-- uboot_end_data */ + move t1, a2 + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - CFG_MONITOR_BASE) + Destination Address + */ + move t6, gp +#ifdef CFG_HEAD_CODE + sub gp, CFG_HEAD_BASE +#else + sub gp, CFG_MONITOR_BASE +#endif + add gp, a2 /* gp now adjusted */ + sub t6, gp, t6 /* t6 <-- relocation offset */ + + /* + * t0 = source address + * t1 = target address + * t2 = source end address + */ + /* On the purple board we copy the code earlier in a special way + * in order to solve flash problems + */ +#ifndef CONFIG_PURPLE +1: + lw t3, 0(t0) + sw t3, 0(t1) + addu t0, 4 + ble t0, t2, 1b + addu t1, 4 /* delay slot */ +#endif + + /* If caches were enabled, we would have to flush them here. + */ + + /* Jump to where we've relocated ourselves. + */ + addi t0, a2, in_ram - _start + j t0 + nop + + .word uboot_end_data + .word uboot_end + .word num_got_entries + +in_ram: + /* Now we want to update GOT. + */ + lw t3, -4(t0) /* t3 <-- num_got_entries */ + addi t4, gp, 8 /* Skipping first two entries. */ + li t2, 2 +1: + lw t1, 0(t4) + beqz t1, 2f + add t1, t6 + sw t1, 0(t4) +2: + addi t2, 1 + blt t2, t3, 1b + addi t4, 4 /* delay slot */ + + /* Clear BSS. + */ + lw t1, -12(t0) /* t1 <-- uboot_end_data */ + lw t2, -8(t0) /* t2 <-- uboot_end */ + add t1, t6 /* adjust pointers */ + add t2, t6 + + sub t1, 4 +1: addi t1, 4 + bltl t1, t2, 1b + sw zero, 0(t1) /* delay slot */ + + move a0, a1 + la t9, board_init_r + j t9 + move a1, a2 /* delay slot */ + + .end relocate_code + + + /* Exception handlers. + */ +romReserved: + b romReserved + +romExcHandle: + b romExcHandle + + /* Additional handlers. + */ +#if defined(CONFIG_IFX_MIPS) +#if defined(IFX_MIPS_HANDLER_1) +ifx_mips_handler_1: + IFX_MIPS_HANDLER_1 +#endif +#endif + diff --git a/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S b/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S new file mode 100644 index 0000000000..cd7a13fab5 --- /dev/null +++ b/package/uboot-ifxmips/files/cpu/mips/danube/start_bootstrap.S @@ -0,0 +1,428 @@ +/* + * Startup Code for MIPS32 CPU-core + * + * Copyright (c) 2003 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include +#include +#include +#include + + +#define RVECENT(f,n) \ + b f; nop +#define XVECENT(f,bev) \ + b f ; \ + li k0,bev + + .set noreorder + + .globl _start_bootstrap + .text +_start_bootstrap: + RVECENT(reset,0) /* U-boot entry point */ + RVECENT(reset,1) /* software reboot */ +#if defined(CONFIG_INCA_IP) || defined(CONFIG_INCA_IP2) + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word 0x00000000 /* phase of the flash */ +#elif defined(CONFIG_PURPLE) + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ +#elif defined(CONFIG_DANUBE) + + .org 0x10 + .word INFINEON_EBU_BOOTCFG /* EBU init code, fetched during booting */ + .word 0x00000000 /* phase of the flash */ + + .org 0x18 + .word 0x312E3000 /* version x.x */ + .word 0x00000000 /* phase of the flash */ +#else + RVECENT(romReserved,2) +#endif + RVECENT(romReserved,3) + RVECENT(romReserved,4) + RVECENT(romReserved,5) + RVECENT(romReserved,6) + RVECENT(romReserved,7) + RVECENT(romReserved,8) + RVECENT(romReserved,9) + RVECENT(romReserved,10) + RVECENT(romReserved,11) + RVECENT(romReserved,12) + RVECENT(romReserved,13) + RVECENT(romReserved,14) + RVECENT(romReserved,15) + RVECENT(romReserved,16) + RVECENT(romReserved,17) + RVECENT(romReserved,18) + RVECENT(romReserved,19) + RVECENT(romReserved,20) + RVECENT(romReserved,21) + RVECENT(romReserved,22) + RVECENT(romReserved,23) + RVECENT(romReserved,24) + RVECENT(romReserved,25) + RVECENT(romReserved,26) + RVECENT(romReserved,27) + RVECENT(romReserved,28) + RVECENT(romReserved,29) + RVECENT(romReserved,30) + RVECENT(romReserved,31) + RVECENT(romReserved,32) + RVECENT(romReserved,33) + RVECENT(romReserved,34) + RVECENT(romReserved,35) + RVECENT(romReserved,36) + RVECENT(romReserved,37) + RVECENT(romReserved,38) + RVECENT(romReserved,39) + RVECENT(romReserved,40) + RVECENT(romReserved,41) + RVECENT(romReserved,42) + RVECENT(romReserved,43) + RVECENT(romReserved,44) + RVECENT(romReserved,45) + RVECENT(romReserved,46) + RVECENT(romReserved,47) + RVECENT(romReserved,48) + RVECENT(romReserved,49) + RVECENT(romReserved,50) + RVECENT(romReserved,51) + RVECENT(romReserved,52) + RVECENT(romReserved,53) + RVECENT(romReserved,54) + RVECENT(romReserved,55) + RVECENT(romReserved,56) + RVECENT(romReserved,57) + RVECENT(romReserved,58) + RVECENT(romReserved,59) + RVECENT(romReserved,60) + RVECENT(romReserved,61) + RVECENT(romReserved,62) + RVECENT(romReserved,63) + XVECENT(romExcHandle,0x200) /* bfc00200: R4000 tlbmiss vector */ + RVECENT(romReserved,65) + RVECENT(romReserved,66) + RVECENT(romReserved,67) + RVECENT(romReserved,68) + RVECENT(romReserved,69) + RVECENT(romReserved,70) + RVECENT(romReserved,71) + RVECENT(romReserved,72) + RVECENT(romReserved,73) + RVECENT(romReserved,74) + RVECENT(romReserved,75) + RVECENT(romReserved,76) + RVECENT(romReserved,77) + RVECENT(romReserved,78) + RVECENT(romReserved,79) + XVECENT(romExcHandle,0x280) /* bfc00280: R4000 xtlbmiss vector */ + RVECENT(romReserved,81) + RVECENT(romReserved,82) + RVECENT(romReserved,83) + RVECENT(romReserved,84) + RVECENT(romReserved,85) + RVECENT(romReserved,86) + RVECENT(romReserved,87) + RVECENT(romReserved,88) + RVECENT(romReserved,89) + RVECENT(romReserved,90) + RVECENT(romReserved,91) + RVECENT(romReserved,92) + RVECENT(romReserved,93) + RVECENT(romReserved,94) + RVECENT(romReserved,95) + XVECENT(romExcHandle,0x300) /* bfc00300: R4000 cache vector */ + RVECENT(romReserved,97) + RVECENT(romReserved,98) + RVECENT(romReserved,99) + RVECENT(romReserved,100) + RVECENT(romReserved,101) + RVECENT(romReserved,102) + RVECENT(romReserved,103) + RVECENT(romReserved,104) + RVECENT(romReserved,105) + RVECENT(romReserved,106) + RVECENT(romReserved,107) + RVECENT(romReserved,108) + RVECENT(romReserved,109) + RVECENT(romReserved,110) + RVECENT(romReserved,111) + XVECENT(romExcHandle,0x380) /* bfc00380: R4000 general vector */ + RVECENT(romReserved,113) + RVECENT(romReserved,114) + RVECENT(romReserved,115) + RVECENT(romReserved,116) + RVECENT(romReserved,116) + RVECENT(romReserved,118) + RVECENT(romReserved,119) + RVECENT(romReserved,120) + RVECENT(romReserved,121) + RVECENT(romReserved,122) + RVECENT(romReserved,123) + RVECENT(romReserved,124) + RVECENT(romReserved,125) + RVECENT(romReserved,126) + RVECENT(romReserved,127) + + /* We hope there are no more reserved vectors! + * 128 * 8 == 1024 == 0x400 + * so this is address R_VEC+0x400 == 0xbfc00400 + */ +#ifdef CONFIG_PURPLE +/* 0xbfc00400 */ + .word 0xdc870000 + .word 0xfca70000 + .word 0x20840008 + .word 0x20a50008 + .word 0x20c6ffff + .word 0x14c0fffa + .word 0x00000000 + .word 0x03e00008 + .word 0x00000000 + .word 0x00000000 +/* 0xbfc00428 */ + .word 0xdc870000 + .word 0xfca70000 + .word 0x20840008 + .word 0x20a50008 + .word 0x20c6ffff + .word 0x14c0fffa + .word 0x00000000 + .word 0x03e00008 + .word 0x00000000 + .word 0x00000000 +#endif /* CONFIG_PURPLE */ + .align 4 +reset: +#ifdef CONFIG_INCA_IP2 + /* Check for Host or Voice CPU */ + + mfc0 k0, CP0_EBASE + and k0, EBASEF_CPUNUM + srl k0, EBASEB_CPUNUM + subu k0, EBASE_CPU_HOST + bne k0, zero, voice_reset_handler + nop + +#endif + + /* Clear watch registers. + */ + mtc0 zero, CP0_WATCHLO + mtc0 zero, CP0_WATCHHI + + /* STATUS register */ +#ifdef CONFIG_TB0229 + li k0, ST0_CU0 +#else + mfc0 k0, CP0_STATUS +#endif + li k1, ~ST0_IE + and k0, k1 + mtc0 k0, CP0_STATUS + + /* CAUSE register */ + mtc0 zero, CP0_CAUSE + +#ifdef CONFIG_INCA_IP2 + /* CONFIG7 register */ + mfc0 k0, CP0_CONFIG, 7 + li k1, 4 /* Disable RPS due to E83 bug of 24KEC */ + or k0, k1 + mtc0 k0, CP0_CONFIG, 7 +#endif + /* Init Timer */ + mtc0 zero, CP0_COUNT + mtc0 zero, CP0_COMPARE + + /* CONFIG0 register */ + li t0, CONF_CM_UNCACHED + mtc0 t0, CP0_CONFIG + + /* Initialize GOT pointer. + */ + bal 1f + nop + .word _GLOBAL_OFFSET_TABLE_ + 1: + move gp, ra + lw t1, 0(ra) + move gp, t1 + +#ifdef CONFIG_INCA_IP + /* Disable INCA-IP Watchdog. + */ + la t9, disable_incaip_wdt + jalr t9 + nop +#endif + + /* Initialize any external memory. + */ + la t9, lowlevel_init + jalr t9 + nop + + /* Initialize caches... + */ + la t9, mips_cache_reset + jalr t9 + nop + + /* ... and enable them. + */ +#ifdef CONFIG_MIPS_FORCE_CACHE_WRITE_THROUGH + li t0, CONF_CM_CACHABLE_NO_WA +#else + li t0, CONF_CM_CACHABLE_NONCOHERENT +#endif + mtc0 t0, CP0_CONFIG + + + /* Set up temporary stack. + */ + li a0, CFG_INIT_SP_OFFSET + la t9, mips_cache_lock + jalr t9 + nop + + li t0, CFG_SDRAM_BASE + CFG_INIT_SP_OFFSET + la sp, 0(t0) + + la t9, bootstrap_board_init_f + j t9 + nop + + +/* + * void bootstrap_relocate_code (addr_sp, gd, addr_moni) + * + * This "function" does not return, instead it continues in RAM + * after relocating the monitor code. + * + * a0 = addr_sp + * a1 = gd + * a2 = destination address + */ + .globl bootstrap_relocate_code + .ent bootstrap_relocate_code +bootstrap_relocate_code: + move sp, a0 /* Set new stack pointer */ + + li t0, BOOTSTRAP_CFG_MONITOR_BASE + la t3, in_ram + lw t2, -12(t3) /* t2 <-- uboot_end_data_bootsrap */ + move t1, a2 + + /* + * Fix GOT pointer: + * + * New GOT-PTR = (old GOT-PTR - BOOTSTRAP_CFG_MONITOR_BASE) + Destination Address + */ + move t6, gp + sub gp, BOOTSTRAP_CFG_MONITOR_BASE + add gp, a2 /* gp now adjusted */ + sub t6, gp, t6 /* t6 <-- relocation offset */ + + /* + * t0 = source address + * t1 = target address + * t2 = source end address + */ + /* On the purple board we copy the code earlier in a special way + * in order to solve flash problems + */ +#ifndef CONFIG_PURPLE +1: + lw t3, 0(t0) + sw t3, 0(t1) + addu t0, 4 + ble t0, t2, 1b + addu t1, 4 /* delay slot */ +#endif + + /* If caches were enabled, we would have to flush them here. + */ + + /* Jump to where we've relocated ourselves. + */ + addi t0, a2, in_ram - _start_bootstrap + j t0 + nop + + .word uboot_end_data_bootstrap + .word uboot_end_bootstrap + .word num_got_entries + +in_ram: + /* Now we want to update GOT. + */ + lw t3, -4(t0) /* t3 <-- num_got_entries */ + addi t4, gp, 8 /* Skipping first two entries. */ + li t2, 2 +1: + lw t1, 0(t4) + beqz t1, 2f + add t1, t6 + sw t1, 0(t4) +2: + addi t2, 1 + blt t2, t3, 1b + addi t4, 4 /* delay slot */ + + /* Clear BSS. + */ + lw t1, -12(t0) /* t1 <-- uboot_end_data_bootstrap */ + lw t2, -8(t0) /* t2 <-- uboot_end_bootstrap */ + add t1, t6 /* adjust pointers */ + add t2, t6 + + sub t1, 4 +1: addi t1, 4 + bltl t1, t2, 1b + sw zero, 0(t1) /* delay slot */ + + move a0, a1 + la t9, bootstrap_board_init_r + j t9 + move a1, a2 /* delay slot */ + + .end bootstrap_relocate_code + + + /* Exception handlers. + */ +romReserved: + b romReserved + +romExcHandle: + b romExcHandle + +#ifdef CONFIG_INCA_IP2 +voice_reset_handler: + wait + b voice_reset_handler + nop +#endif diff --git a/package/uboot-ifxmips/files/drivers/ifx_sw.c b/package/uboot-ifxmips/files/drivers/ifx_sw.c new file mode 100644 index 0000000000..ac8f1c866f --- /dev/null +++ b/package/uboot-ifxmips/files/drivers/ifx_sw.c @@ -0,0 +1,423 @@ +/* + * DANUBE internal switch ethernet driver. + * + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include + +#if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) \ + && defined(CONFIG_DANUBE_SWITCH) + +#include +#include +#include +#include +#include + +#define MII_MODE 1 +#define REV_MII_MODE 2 + +#define TX_CHAN_NO 7 +#define RX_CHAN_NO 6 + +#define NUM_RX_DESC PKTBUFSRX +#define NUM_TX_DESC 8 +#define MAX_PACKET_SIZE 1536 +#define TOUT_LOOP 100 +#define PHY0_ADDR 1 /*fixme: set the correct value here*/ + +#define DMA_WRITE_REG(reg, value) *((volatile u32 *)reg) = (u32)value +#define DMA_READ_REG(reg, value) value = (u32)*((volatile u32*)reg) + +#define SW_WRITE_REG(reg, value) *((volatile u32*)reg) = (u32)value +#define SW_READ_REG(reg, value) value = (u32)*((volatile u32*)reg) + +typedef struct +{ + union + { + struct + { + volatile u32 OWN :1; + volatile u32 C :1; + volatile u32 Sop :1; + volatile u32 Eop :1; + volatile u32 reserved :3; + volatile u32 Byteoffset :2; + volatile u32 reserve :7; + volatile u32 DataLen :16; + }field; + + volatile u32 word; + }status; + + volatile u32 DataPtr; +} danube_rx_descriptor_t; + +typedef struct +{ + union + { + struct + { + volatile u32 OWN :1; + volatile u32 C :1; + volatile u32 Sop :1; + volatile u32 Eop :1; + volatile u32 Byteoffset :5; + volatile u32 reserved :7; + volatile u32 DataLen :16; + }field; + + volatile u32 word; + }status; + + volatile u32 DataPtr; +} danube_tx_descriptor_t; + + + + +static danube_rx_descriptor_t rx_des_ring[NUM_RX_DESC] __attribute__ ((aligned(8))); +static danube_tx_descriptor_t tx_des_ring[NUM_TX_DESC] __attribute__ ((aligned(8))); +static int tx_num, rx_num; + +int danube_switch_init(struct eth_device *dev, bd_t * bis); +int danube_switch_send(struct eth_device *dev, volatile void *packet,int length); +int danube_switch_recv(struct eth_device *dev); +void danube_switch_halt(struct eth_device *dev); +static void danube_init_switch_chip(int mode); +static void danube_dma_init(void); + + + +int danube_switch_initialize(bd_t * bis) +{ + struct eth_device *dev; + +#if 0 + printf("Entered danube_switch_initialize()\n"); +#endif + + if (!(dev = (struct eth_device *) malloc (sizeof *dev))) + { + printf("Failed to allocate memory\n"); + return 0; + } + memset(dev, 0, sizeof(*dev)); + + danube_dma_init(); + danube_init_switch_chip(REV_MII_MODE); + +#ifdef CLK_OUT2_25MHZ + *DANUBE_GPIO_P0_DIR=0x0000ae78; + *DANUBE_GPIO_P0_ALTSEL0=0x00008078; + //joelin for Mii-1 *DANUBE_GPIO_P0_ALTSEL1=0x80000080; + *DANUBE_GPIO_P0_ALTSEL1=0x80000000; //joelin for Mii-1 + *DANUBE_CGU_IFCCR=0x00400010; + *DANUBE_GPIO_P0_OD=0x0000ae78; +#endif + + /*patch for 6996*/ + + *DANUBE_RCU_RST_REQ |=1; + mdelay(200); + *DANUBE_RCU_RST_REQ &=(unsigned long)~1; + mdelay(1); + /*while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602; + */ + /*while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602; + */ + /***************/ + sprintf(dev->name, "danube Switch"); + dev->init = danube_switch_init; + dev->halt = danube_switch_halt; + dev->send = danube_switch_send; + dev->recv = danube_switch_recv; + + eth_register(dev); + +#if 0 + printf("Leaving danube_switch_initialize()\n"); +#endif + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8001840F; + while((*DANUBE_PPE_ETOP_MDIO_ACC)&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8003840F; + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8005840F; + //while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + //*DANUBE_PPE_ETOP_MDIO_ACC =0x8006840F; + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8007840F; + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8008840F; + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x8001840F; + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x80123602; +#ifdef CLK_OUT2_25MHZ + while(*DANUBE_PPE_ETOP_MDIO_ACC&0x80000000); + *DANUBE_PPE_ETOP_MDIO_ACC =0x80334000; +#endif + + return 1; +} + +int danube_switch_init(struct eth_device *dev, bd_t * bis) +{ + int i; + + tx_num=0; + rx_num=0; + + /* Reset DMA + */ +// serial_puts("i \n\0"); + + *DANUBE_DMA_CS=RX_CHAN_NO; + *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/ + *DANUBE_DMA_CPOLL= 0x80000040; + /*set descriptor base*/ + *DANUBE_DMA_CDBA=(u32)rx_des_ring; + *DANUBE_DMA_CDLEN=NUM_RX_DESC; + *DANUBE_DMA_CIE = 0; + *DANUBE_DMA_CCTRL=0x30000; + + *DANUBE_DMA_CS=TX_CHAN_NO; + *DANUBE_DMA_CCTRL=0x2;/*fix me, need to reset this channel first?*/ + *DANUBE_DMA_CPOLL= 0x80000040; + *DANUBE_DMA_CDBA=(u32)tx_des_ring; + *DANUBE_DMA_CDLEN=NUM_TX_DESC; + *DANUBE_DMA_CIE = 0; + *DANUBE_DMA_CCTRL=0x30100; + + for(i=0;i < NUM_RX_DESC; i++) + { + danube_rx_descriptor_t * rx_desc = KSEG1ADDR(&rx_des_ring[i]); + rx_desc->status.word=0; + rx_desc->status.field.OWN=1; + rx_desc->status.field.DataLen=PKTSIZE_ALIGN; /* 1536 */ + rx_desc->DataPtr=(u32)KSEG1ADDR(NetRxPackets[i]); + } + + for(i=0;i < NUM_TX_DESC; i++) + { + danube_tx_descriptor_t * tx_desc = KSEG1ADDR(&tx_des_ring[i]); + memset(tx_desc, 0, sizeof(tx_des_ring[0])); + } + /* turn on DMA rx & tx channel + */ + *DANUBE_DMA_CS=RX_CHAN_NO; + *DANUBE_DMA_CCTRL|=1;/*reset and turn on the channel*/ + + return 0; +} + +void danube_switch_halt(struct eth_device *dev) +{ + int i; + for(i=0;i<8;i++) + { + *DANUBE_DMA_CS=i; + *DANUBE_DMA_CCTRL&=~1;/*stop the dma channel*/ + } +// udelay(1000000); +} + +int danube_switch_send(struct eth_device *dev, volatile void *packet,int length) +{ + + int i; + int res = -1; + + danube_tx_descriptor_t * tx_desc= KSEG1ADDR(&tx_des_ring[tx_num]); + + if (length <= 0) + { + printf ("%s: bad packet size: %d\n", dev->name, length); + goto Done; + } + + for(i=0; tx_desc->status.field.OWN==1; i++) + { + if(i>=TOUT_LOOP) + { + printf("NO Tx Descriptor..."); + goto Done; + } + } + + //serial_putc('s'); + + tx_desc->status.field.Sop=1; + tx_desc->status.field.Eop=1; + tx_desc->status.field.C=0; + tx_desc->DataPtr = (u32)KSEG1ADDR(packet); + if(length<60) + tx_desc->status.field.DataLen = 60; + else + tx_desc->status.field.DataLen = (u32)length; + + asm("SYNC"); + tx_desc->status.field.OWN=1; + + res=length; + tx_num++; + if(tx_num==NUM_TX_DESC) tx_num=0; + *DANUBE_DMA_CS=TX_CHAN_NO; + + if(!(*DANUBE_DMA_CCTRL & 1)) + *DANUBE_DMA_CCTRL|=1; + +Done: + return res; +} + +int danube_switch_recv(struct eth_device *dev) +{ + + int length = 0; + + danube_rx_descriptor_t * rx_desc; + int anchor_num=0; + int i; + for (;;) + { + rx_desc = KSEG1ADDR(&rx_des_ring[rx_num]); + + if ((rx_desc->status.field.C == 0) || (rx_desc->status.field.OWN == 1)) + { + break; + } + + + length = rx_desc->status.field.DataLen; + if (length) + { + NetReceive((void*)KSEG1ADDR(NetRxPackets[rx_num]), length - 4); + // serial_putc('*'); + } + else + { + printf("Zero length!!!\n"); + } + + rx_desc->status.field.Sop=0; + rx_desc->status.field.Eop=0; + rx_desc->status.field.C=0; + rx_desc->status.field.DataLen=PKTSIZE_ALIGN; + rx_desc->status.field.OWN=1; + rx_num++; + if(rx_num==NUM_RX_DESC) rx_num=0; + + } + + return length; +} + + +static void danube_init_switch_chip(int mode) +{ + int i; + /*get and set mac address for MAC*/ + static unsigned char addr[6]; + char *tmp,*end; + tmp = getenv ("ethaddr"); + if (NULL == tmp) { + printf("Can't get environment ethaddr!!!\n"); + // return NULL; + } else { + printf("ethaddr=%s\n", tmp); + } + *DANUBE_PMU_PWDCR = *DANUBE_PMU_PWDCR & 0xFFFFEFDF; + *DANUBE_PPE32_ETOP_MDIO_CFG &= ~0x6; + *DANUBE_PPE32_ENET_MAC_CFG = 0x187; + + // turn on port0, set to rmii and turn off port1. + if(mode==REV_MII_MODE) + { + *DANUBE_PPE32_ETOP_CFG = (*DANUBE_PPE32_ETOP_CFG & 0xfffffffc) | 0x0000000a; + } + else if (mode == MII_MODE) + { + *DANUBE_PPE32_ETOP_CFG = (*DANUBE_PPE32_ETOP_CFG & 0xfffffffc) | 0x00000008; + } + + *DANUBE_PPE32_ETOP_IG_PLEN_CTRL = 0x4005ee; // set packetlen. + *ENET_MAC_CFG|=1<<11;/*enable the crc*/ + return; +} + + +static void danube_dma_init(void) +{ + int i; +// serial_puts("d \n\0"); + + *DANUBE_PMU_PWDCR &=~(1<> 28) & ((1 << 4) - 1)) +#define DANUBE_MCD_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28) +#define DANUBE_MCD_CHIPID_PART_NUMBER_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define DANUBE_MCD_CHIPID_PART_NUMBER_SET(value) (((( 1 << 16) - 1) & (value)) << 12) +#define DANUBE_MCD_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 11) - 1)) +#define DANUBE_MCD_CHIPID_MANID_SET(value) (((( 1 << 11) - 1) & (value)) << 1) + +#define DANUBE_CHIPID_STANDARD 0x00EB +#define DANUBE_CHIPID_YANGTSE 0x00ED + +/***Redesign Tracing Identification Register***/ +#define DANUBE_MCD_RTID ((volatile u32*)(DANUBE_MCD+ 0x002C)) +#define DANUBE_MCD_RTID_LC (1 << 15) +#define DANUBE_MCD_RTID_RIX(value) (((( 1 << 3) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : EBU register address and bits */ +/***********************************************************************/ + +#define DANUBE_EBU (0xBE105300) +#define EBU_ADDR_SEL_0 (volatile u32*)(DANUBE_EBU + 0x20) +#define EBU_ADDR_SEL_1 (volatile u32*)(DANUBE_EBU + 0x24) +#define EBU_CON_0 (volatile u32*)(DANUBE_EBU + 0x60) +#define EBU_CON_1 (volatile u32*)(DANUBE_EBU + 0x64) +#define EBU_NAND_CON (volatile u32*)(DANUBE_EBU + 0xB0) +#define EBU_NAND_WAIT (volatile u32*)(DANUBE_EBU + 0xB4) +#define EBU_NAND_ECC0 (volatile u32*)(DANUBE_EBU + 0xB8) +#define EBU_NAND_ECC_AC (volatile u32*)(DANUBE_EBU + 0xBC) + +/***********************************************************************/ + + +/***EBU Clock Control Register***/ +#define DANUBE_EBU_CLC ((volatile u32*)(DANUBE_EBU+ 0x0000)) +#define DANUBE_EBU_CLC_DISS (1 << 1) +#define DANUBE_EBU_CLC_DISR (1 << 0) + +/***EBU Global Control Register***/ +#define DANUBE_EBU_CON ((volatile u32*)(DANUBE_EBU+ 0x0010)) +#define DANUBE_EBU_CON_DTACS (value) (((( 1 << 3) - 1) & (value)) << 20) +#define DANUBE_EBU_CON_DTARW (value) (((( 1 << 3) - 1) & (value)) << 16) +#define DANUBE_EBU_CON_TOUTC (value) (((( 1 << 8) - 1) & (value)) << 8) +#define DANUBE_EBU_CON_ARBMODE (value) (((( 1 << 2) - 1) & (value)) << 6) +#define DANUBE_EBU_CON_ARBSYNC (1 << 5) +#define DANUBE_EBU_CON_1 (1 << 3) + +/***EBU Address Select Register 0***/ +#define DANUBE_EBU_ADDSEL0 ((volatile u32*)(DANUBE_EBU+ 0x0020)) +#define DANUBE_EBU_ADDSEL0_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define DANUBE_EBU_ADDSEL0_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_EBU_ADDSEL0_MIRRORE (1 << 1) +#define DANUBE_EBU_ADDSEL0_REGEN (1 << 0) + +/***EBU Address Select Register 1***/ +#define DANUBE_EBU_ADDSEL1 ((volatile u32*)(DANUBE_EBU+ 0x0024)) +#define DANUBE_EBU_ADDSEL1_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define DANUBE_EBU_ADDSEL1_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_EBU_ADDSEL1_MIRRORE (1 << 1) +#define DANUBE_EBU_ADDSEL1_REGEN (1 << 0) + +/***EBU Address Select Register 2***/ +#define DANUBE_EBU_ADDSEL2 ((volatile u32*)(DANUBE_EBU+ 0x0028)) +#define DANUBE_EBU_ADDSEL2_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define DANUBE_EBU_ADDSEL2_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_EBU_ADDSEL2_MIRRORE (1 << 1) +#define DANUBE_EBU_ADDSEL2_REGEN (1 << 0) + +/***EBU Address Select Register 3***/ +#define DANUBE_EBU_ADDSEL3 ((volatile u32*)(DANUBE_EBU+ 0x0028)) +#define DANUBE_EBU_ADDSEL3_BASE (value) (((( 1 << 20) - 1) & (value)) << 12) +#define DANUBE_EBU_ADDSEL3_MASK (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_EBU_ADDSEL3_MIRRORE (1 << 1) +#define DANUBE_EBU_ADDSEL3_REGEN (1 << 0) + +/***EBU Bus Configuration Register 0***/ +#define DANUBE_EBU_BUSCON0 ((volatile u32*)(DANUBE_EBU+ 0x0060)) +#define DANUBE_EBU_BUSCON0_WRDIS (1 << 31) +#define DANUBE_EBU_BUSCON0_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define DANUBE_EBU_BUSCON0_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define DANUBE_EBU_BUSCON0_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define DANUBE_EBU_BUSCON0_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define DANUBE_EBU_BUSCON0_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define DANUBE_EBU_BUSCON0_WAITINV (1 << 19) +#define DANUBE_EBU_BUSCON0_SETUP (1 << 18) +#define DANUBE_EBU_BUSCON0_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define DANUBE_EBU_BUSCON0_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define DANUBE_EBU_BUSCON0_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define DANUBE_EBU_BUSCON0_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define DANUBE_EBU_BUSCON0_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define DANUBE_EBU_BUSCON0_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 1***/ +#define DANUBE_EBU_BUSCON1 ((volatile u32*)(DANUBE_EBU+ 0x0064)) +#define DANUBE_EBU_BUSCON1_WRDIS (1 << 31) +#define DANUBE_EBU_BUSCON1_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define DANUBE_EBU_BUSCON1_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define DANUBE_EBU_BUSCON1_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define DANUBE_EBU_BUSCON1_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define DANUBE_EBU_BUSCON1_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define DANUBE_EBU_BUSCON1_WAITINV (1 << 19) +#define DANUBE_EBU_BUSCON1_SETUP (1 << 18) +#define DANUBE_EBU_BUSCON1_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define DANUBE_EBU_BUSCON1_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define DANUBE_EBU_BUSCON1_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define DANUBE_EBU_BUSCON1_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define DANUBE_EBU_BUSCON1_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define DANUBE_EBU_BUSCON1_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***EBU Bus Configuration Register 2***/ +#define DANUBE_EBU_BUSCON2 ((volatile u32*)(DANUBE_EBU+ 0x0068)) +#define DANUBE_EBU_BUSCON2_WRDIS (1 << 31) +#define DANUBE_EBU_BUSCON2_ALEC (value) (((( 1 << 2) - 1) & (value)) << 29) +#define DANUBE_EBU_BUSCON2_BCGEN (value) (((( 1 << 2) - 1) & (value)) << 27) +#define DANUBE_EBU_BUSCON2_AGEN (value) (((( 1 << 2) - 1) & (value)) << 24) +#define DANUBE_EBU_BUSCON2_CMULTR (value) (((( 1 << 2) - 1) & (value)) << 22) +#define DANUBE_EBU_BUSCON2_WAIT (value) (((( 1 << 2) - 1) & (value)) << 20) +#define DANUBE_EBU_BUSCON2_WAITINV (1 << 19) +#define DANUBE_EBU_BUSCON2_SETUP (1 << 18) +#define DANUBE_EBU_BUSCON2_PORTW (value) (((( 1 << 2) - 1) & (value)) << 16) +#define DANUBE_EBU_BUSCON2_WAITRDC (value) (((( 1 << 7) - 1) & (value)) << 9) +#define DANUBE_EBU_BUSCON2_WAITWRC (value) (((( 1 << 3) - 1) & (value)) << 6) +#define DANUBE_EBU_BUSCON2_HOLDC (value) (((( 1 << 2) - 1) & (value)) << 4) +#define DANUBE_EBU_BUSCON2_RECOVC (value) (((( 1 << 2) - 1) & (value)) << 2) +#define DANUBE_EBU_BUSCON2_CMULT (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : SDRAM register address and bits */ +/***********************************************************************/ + +#define DANUBE_SDRAM (0xBF800000) +/***********************************************************************/ + + +/***MC Access Error Cause Register***/ +#define DANUBE_SDRAM_MC_ERRCAUSE ((volatile u32*)(DANUBE_SDRAM+ 0x0100)) +#define DANUBE_SDRAM_MC_ERRCAUSE_ERR (1 << 31) +#define DANUBE_SDRAM_MC_ERRCAUSE_PORT (value) (((( 1 << 4) - 1) & (value)) << 16) +#define DANUBE_SDRAM_MC_ERRCAUSE_CAUSE (value) (((( 1 << 2) - 1) & (value)) << 0) +#define DANUBE_SDRAM_MC_ERRCAUSE_Res (value) (((( 1 << NaN) - 1) & (value)) << NaN) + +/***MC Access Error Address Register***/ +#define DANUBE_SDRAM_MC_ERRADDR ((volatile u32*)(DANUBE_SDRAM+ 0x0108)) +#define DANUBE_SDRAM_MC_ERRADDR_ADDR + +/***MC I/O General Purpose Register***/ +#define DANUBE_SDRAM_MC_IOGP ((volatile u32*)(DANUBE_SDRAM+ 0x0800)) +#define DANUBE_SDRAM_MC_IOGP_GPR6 (value) (((( 1 << 4) - 1) & (value)) << 28) +#define DANUBE_SDRAM_MC_IOGP_GPR5 (value) (((( 1 << 4) - 1) & (value)) << 24) +#define DANUBE_SDRAM_MC_IOGP_GPR4 (value) (((( 1 << 4) - 1) & (value)) << 20) +#define DANUBE_SDRAM_MC_IOGP_GPR3 (value) (((( 1 << 4) - 1) & (value)) << 16) +#define DANUBE_SDRAM_MC_IOGP_GPR2 (value) (((( 1 << 4) - 1) & (value)) << 12) +#define DANUBE_SDRAM_MC_IOGP_CPS (1 << 11) +#define DANUBE_SDRAM_MC_IOGP_CLKDELAY (value) (((( 1 << 3) - 1) & (value)) << 8) +#define DANUBE_SDRAM_MC_IOGP_CLKRAT (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_SDRAM_MC_IOGP_RDDEL (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***MC Self Refresh Register***/ +#define DANUBE_SDRAM_MC_SELFRFSH ((volatile u32*)(DANUBE_SDRAM+ 0x0A00)) +#define DANUBE_SDRAM_MC_SELFRFSH_PWDS (1 << 1) +#define DANUBE_SDRAM_MC_SELFRFSH_PWD (1 << 0) +#define DANUBE_SDRAM_MC_SELFRFSH_Res (value) (((( 1 << 30) - 1) & (value)) << 2) + +/***MC Enable Register***/ +#define DANUBE_SDRAM_MC_CTRLENA ((volatile u32*)(DANUBE_SDRAM+ 0x1000)) +#define DANUBE_SDRAM_MC_CTRLENA_ENA (1 << 0) +#define DANUBE_SDRAM_MC_CTRLENA_Res (value) (((( 1 << 31) - 1) & (value)) << 1) + +/***MC Mode Register Setup Code***/ +#define DANUBE_SDRAM_MC_MRSCODE ((volatile u32*)(DANUBE_SDRAM+ 0x1008)) +#define DANUBE_SDRAM_MC_MRSCODE_UMC (value) (((( 1 << 5) - 1) & (value)) << 7) +#define DANUBE_SDRAM_MC_MRSCODE_CL (value) (((( 1 << 3) - 1) & (value)) << 4) +#define DANUBE_SDRAM_MC_MRSCODE_WT (1 << 3) +#define DANUBE_SDRAM_MC_MRSCODE_BL (value) (((( 1 << 3) - 1) & (value)) << 0) + +/***MC Configuration Data-word Width Register***/ +#define DANUBE_SDRAM_MC_CFGDW ((volatile u32*)(DANUBE_SDRAM+ 0x1010)) +#define DANUBE_SDRAM_MC_CFGDW_DW (value) (((( 1 << 4) - 1) & (value)) << 0) +#define DANUBE_SDRAM_MC_CFGDW_Res (value) (((( 1 << 28) - 1) & (value)) << 4) + +/***MC Configuration Physical Bank 0 Register***/ +#define DANUBE_SDRAM_MC_CFGPB0 ((volatile u32*)(DANUBE_SDRAM+ 0x1018)) +#define DANUBE_SDRAM_MC_CFGPB0_MCSEN0 (value) (((( 1 << 4) - 1) & (value)) << 12) +#define DANUBE_SDRAM_MC_CFGPB0_BANKN0 (value) (((( 1 << 4) - 1) & (value)) << 8) +#define DANUBE_SDRAM_MC_CFGPB0_ROWW0 (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_SDRAM_MC_CFGPB0_COLW0 (value) (((( 1 << 4) - 1) & (value)) << 0) +#define DANUBE_SDRAM_MC_CFGPB0_Res (value) (((( 1 << 16) - 1) & (value)) << 16) + +/***MC Latency Register***/ +#define DANUBE_SDRAM_MC_LATENCY ((volatile u32*)(DANUBE_SDRAM+ 0x1038)) +#define DANUBE_SDRAM_MC_LATENCY_TRP (value) (((( 1 << 4) - 1) & (value)) << 16) +#define DANUBE_SDRAM_MC_LATENCY_TRAS (value) (((( 1 << 4) - 1) & (value)) << 12) +#define DANUBE_SDRAM_MC_LATENCY_TRCD (value) (((( 1 << 4) - 1) & (value)) << 8) +#define DANUBE_SDRAM_MC_LATENCY_TDPL (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_SDRAM_MC_LATENCY_TDAL (value) (((( 1 << 4) - 1) & (value)) << 0) +#define DANUBE_SDRAM_MC_LATENCY_Res (value) (((( 1 << 12) - 1) & (value)) << 20) + +/***MC Refresh Cycle Time Register***/ +#define DANUBE_SDRAM_MC_TREFRESH ((volatile u32*)(DANUBE_SDRAM+ 0x1040)) +#define DANUBE_SDRAM_MC_TREFRESH_TREF (value) (((( 1 << 13) - 1) & (value)) << 0) +#define DANUBE_SDRAM_MC_TREFRESH_Res (value) (((( 1 << 19) - 1) & (value)) << 13) + + +/***********************************************************************/ +/* Module : GPTU register address and bits */ +/***********************************************************************/ + +#define DANUBE_GPTU (0xB8000300) +/***********************************************************************/ + + +/***GPT Clock Control Register***/ +#define DANUBE_GPTU_GPT_CLC ((volatile u32*)(DANUBE_GPTU+ 0x0000)) +#define DANUBE_GPTU_GPT_CLC_RMC (value) (((( 1 << 8) - 1) & (value)) << 8) +#define DANUBE_GPTU_GPT_CLC_DISS (1 << 1) +#define DANUBE_GPTU_GPT_CLC_DISR (1 << 0) + +/***GPT Timer 3 Control Register***/ +#define DANUBE_GPTU_GPT_T3CON ((volatile u32*)(DANUBE_GPTU+ 0x0014)) +#define DANUBE_GPTU_GPT_T3CON_T3RDIR (1 << 15) +#define DANUBE_GPTU_GPT_T3CON_T3CHDIR (1 << 14) +#define DANUBE_GPTU_GPT_T3CON_T3EDGE (1 << 13) +#define DANUBE_GPTU_GPT_T3CON_BPS1 (value) (((( 1 << 2) - 1) & (value)) << 11) +#define DANUBE_GPTU_GPT_T3CON_T3OTL (1 << 10) +#define DANUBE_GPTU_GPT_T3CON_T3UD (1 << 7) +#define DANUBE_GPTU_GPT_T3CON_T3R (1 << 6) +#define DANUBE_GPTU_GPT_T3CON_T3M (value) (((( 1 << 3) - 1) & (value)) << 3) +#define DANUBE_GPTU_GPT_T3CON_T3I (value) (((( 1 << 3) - 1) & (value)) << 0) + +/***GPT Write Hardware Modified Timer 3 Control Register +If set and clear bit are written concurrently with 1, the associated bit is not changed.***/ +#define DANUBE_GPTU_GPT_WHBT3CON ((volatile u32*)(DANUBE_GPTU+ 0x004C)) +#define DANUBE_GPTU_GPT_WHBT3CON_SETT3CHDIR (1 << 15) +#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3CHDIR (1 << 14) +#define DANUBE_GPTU_GPT_WHBT3CON_SETT3EDGE (1 << 13) +#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3EDGE (1 << 12) +#define DANUBE_GPTU_GPT_WHBT3CON_SETT3OTL (1 << 11) +#define DANUBE_GPTU_GPT_WHBT3CON_CLRT3OTL (1 << 10) + +/***GPT Timer 2 Control Register***/ +#define DANUBE_GPTU_GPT_T2CON ((volatile u32*)(DANUBE_GPTU+ 0x0010)) +#define DANUBE_GPTU_GPT_T2CON_TxRDIR (1 << 15) +#define DANUBE_GPTU_GPT_T2CON_TxCHDIR (1 << 14) +#define DANUBE_GPTU_GPT_T2CON_TxEDGE (1 << 13) +#define DANUBE_GPTU_GPT_T2CON_TxIRDIS (1 << 12) +#define DANUBE_GPTU_GPT_T2CON_TxRC (1 << 9) +#define DANUBE_GPTU_GPT_T2CON_TxUD (1 << 7) +#define DANUBE_GPTU_GPT_T2CON_TxR (1 << 6) +#define DANUBE_GPTU_GPT_T2CON_TxM (value) (((( 1 << 3) - 1) & (value)) << 3) +#define DANUBE_GPTU_GPT_T2CON_TxI (value) (((( 1 << 3) - 1) & (value)) << 0) + +/***GPT Timer 4 Control Register***/ +#define DANUBE_GPTU_GPT_T4CON ((volatile u32*)(DANUBE_GPTU+ 0x0018)) +#define DANUBE_GPTU_GPT_T4CON_TxRDIR (1 << 15) +#define DANUBE_GPTU_GPT_T4CON_TxCHDIR (1 << 14) +#define DANUBE_GPTU_GPT_T4CON_TxEDGE (1 << 13) +#define DANUBE_GPTU_GPT_T4CON_TxIRDIS (1 << 12) +#define DANUBE_GPTU_GPT_T4CON_TxRC (1 << 9) +#define DANUBE_GPTU_GPT_T4CON_TxUD (1 << 7) +#define DANUBE_GPTU_GPT_T4CON_TxR (1 << 6) +#define DANUBE_GPTU_GPT_T4CON_TxM (value) (((( 1 << 3) - 1) & (value)) << 3) +#define DANUBE_GPTU_GPT_T4CON_TxI (value) (((( 1 << 3) - 1) & (value)) << 0) + +/***GPT Write HW Modified Timer 2 Control Register If set + and clear bit are written concurrently with 1, the associated bit is not changed.***/ +#define DANUBE_GPTU_GPT_WHBT2CON ((volatile u32*)(DANUBE_GPTU+ 0x0048)) +#define DANUBE_GPTU_GPT_WHBT2CON_SETTxCHDIR (1 << 15) +#define DANUBE_GPTU_GPT_WHBT2CON_CLRTxCHDIR (1 << 14) +#define DANUBE_GPTU_GPT_WHBT2CON_SETTxEDGE (1 << 13) +#define DANUBE_GPTU_GPT_WHBT2CON_CLRTxEDGE (1 << 12) + +/***GPT Write HW Modified Timer 4 Control Register If set + and clear bit are written concurrently with 1, the associated bit is not changed.***/ +#define DANUBE_GPTU_GPT_WHBT4CON ((volatile u32*)(DANUBE_GPTU+ 0x0050)) +#define DANUBE_GPTU_GPT_WHBT4CON_SETTxCHDIR (1 << 15) +#define DANUBE_GPTU_GPT_WHBT4CON_CLRTxCHDIR (1 << 14) +#define DANUBE_GPTU_GPT_WHBT4CON_SETTxEDGE (1 << 13) +#define DANUBE_GPTU_GPT_WHBT4CON_CLRTxEDGE (1 << 12) + +/***GPT Capture Reload Register***/ +#define DANUBE_GPTU_GPT_CAPREL ((volatile u32*)(DANUBE_GPTU+ 0x0030)) +#define DANUBE_GPTU_GPT_CAPREL_CAPREL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 2 Register***/ +#define DANUBE_GPTU_GPT_T2 ((volatile u32*)(DANUBE_GPTU+ 0x0034)) +#define DANUBE_GPTU_GPT_T2_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 3 Register***/ +#define DANUBE_GPTU_GPT_T3 ((volatile u32*)(DANUBE_GPTU+ 0x0038)) +#define DANUBE_GPTU_GPT_T3_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 4 Register***/ +#define DANUBE_GPTU_GPT_T4 ((volatile u32*)(DANUBE_GPTU+ 0x003C)) +#define DANUBE_GPTU_GPT_T4_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 5 Register***/ +#define DANUBE_GPTU_GPT_T5 ((volatile u32*)(DANUBE_GPTU+ 0x0040)) +#define DANUBE_GPTU_GPT_T5_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 6 Register***/ +#define DANUBE_GPTU_GPT_T6 ((volatile u32*)(DANUBE_GPTU+ 0x0044)) +#define DANUBE_GPTU_GPT_T6_TVAL (value) (((( 1 << 16) - 1) & (value)) << 0) + +/***GPT Timer 6 Control Register***/ +#define DANUBE_GPTU_GPT_T6CON ((volatile u32*)(DANUBE_GPTU+ 0x0020)) +#define DANUBE_GPTU_GPT_T6CON_T6SR (1 << 15) +#define DANUBE_GPTU_GPT_T6CON_T6CLR (1 << 14) +#define DANUBE_GPTU_GPT_T6CON_BPS2 (value) (((( 1 << 2) - 1) & (value)) << 11) +#define DANUBE_GPTU_GPT_T6CON_T6OTL (1 << 10) +#define DANUBE_GPTU_GPT_T6CON_T6UD (1 << 7) +#define DANUBE_GPTU_GPT_T6CON_T6R (1 << 6) +#define DANUBE_GPTU_GPT_T6CON_T6M (value) (((( 1 << 3) - 1) & (value)) << 3) +#define DANUBE_GPTU_GPT_T6CON_T6I (value) (((( 1 << 3) - 1) & (value)) << 0) + +/***GPT Write HW Modified Timer 6 Control Register If set + and clear bit are written concurrently with 1, the associated bit is not changed.***/ +#define DANUBE_GPTU_GPT_WHBT6CON ((volatile u32*)(DANUBE_GPTU+ 0x0054)) +#define DANUBE_GPTU_GPT_WHBT6CON_SETT6OTL (1 << 11) +#define DANUBE_GPTU_GPT_WHBT6CON_CLRT6OTL (1 << 10) + +/***GPT Timer 5 Control Register***/ +#define DANUBE_GPTU_GPT_T5CON ((volatile u32*)(DANUBE_GPTU+ 0x001C)) +#define DANUBE_GPTU_GPT_T5CON_T5SC (1 << 15) +#define DANUBE_GPTU_GPT_T5CON_T5CLR (1 << 14) +#define DANUBE_GPTU_GPT_T5CON_CI (value) (((( 1 << 2) - 1) & (value)) << 12) +#define DANUBE_GPTU_GPT_T5CON_T5CC (1 << 11) +#define DANUBE_GPTU_GPT_T5CON_CT3 (1 << 10) +#define DANUBE_GPTU_GPT_T5CON_T5RC (1 << 9) +#define DANUBE_GPTU_GPT_T5CON_T5UDE (1 << 8) +#define DANUBE_GPTU_GPT_T5CON_T5UD (1 << 7) +#define DANUBE_GPTU_GPT_T5CON_T5R (1 << 6) +#define DANUBE_GPTU_GPT_T5CON_T5M (value) (((( 1 << 3) - 1) & (value)) << 3) +#define DANUBE_GPTU_GPT_T5CON_T5I (value) (((( 1 << 3) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : IOM register address and bits */ +/***********************************************************************/ + +#define DANUBE_IOM (0xBF105000) +/***********************************************************************/ + + +/***Receive FIFO***/ +#define DANUBE_IOM_RFIFO ((volatile u32*)(DANUBE_IOM+ 0x0000)) +#define DANUBE_IOM_RFIFO_RXD (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Transmit FIFO***/ +#define DANUBE_IOM_XFIFO ((volatile u32*)(DANUBE_IOM+ 0x0000)) +#define DANUBE_IOM_XFIFO_TXD (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Interrupt Status Register HDLC***/ +#define DANUBE_IOM_ISTAH ((volatile u32*)(DANUBE_IOM+ 0x0080)) +#define DANUBE_IOM_ISTAH_RME (1 << 7) +#define DANUBE_IOM_ISTAH_RPF (1 << 6) +#define DANUBE_IOM_ISTAH_RFO (1 << 5) +#define DANUBE_IOM_ISTAH_XPR (1 << 4) +#define DANUBE_IOM_ISTAH_XMR (1 << 3) +#define DANUBE_IOM_ISTAH_XDU (1 << 2) + +/***Interrupt Mask Register HDLC***/ +#define DANUBE_IOM_MASKH ((volatile u32*)(DANUBE_IOM+ 0x0080)) +#define DANUBE_IOM_MASKH_RME (1 << 7) +#define DANUBE_IOM_MASKH_RPF (1 << 6) +#define DANUBE_IOM_MASKH_RFO (1 << 5) +#define DANUBE_IOM_MASKH_XPR (1 << 4) +#define DANUBE_IOM_MASKH_XMR (1 << 3) +#define DANUBE_IOM_MASKH_XDU (1 << 2) + +/***Status Register***/ +#define DANUBE_IOM_STAR ((volatile u32*)(DANUBE_IOM+ 0x0084)) +#define DANUBE_IOM_STAR_XDOV (1 << 7) +#define DANUBE_IOM_STAR_XFW (1 << 6) +#define DANUBE_IOM_STAR_RACI (1 << 3) +#define DANUBE_IOM_STAR_XACI (1 << 1) + +/***Command Register***/ +#define DANUBE_IOM_CMDR ((volatile u32*)(DANUBE_IOM+ 0x0084)) +#define DANUBE_IOM_CMDR_RMC (1 << 7) +#define DANUBE_IOM_CMDR_RRES (1 << 6) +#define DANUBE_IOM_CMDR_XTF (1 << 3) +#define DANUBE_IOM_CMDR_XME (1 << 1) +#define DANUBE_IOM_CMDR_XRES (1 << 0) + +/***Mode Register***/ +#define DANUBE_IOM_MODEH ((volatile u32*)(DANUBE_IOM+ 0x0088)) +#define DANUBE_IOM_MODEH_MDS2 (1 << 7) +#define DANUBE_IOM_MODEH_MDS1 (1 << 6) +#define DANUBE_IOM_MODEH_MDS0 (1 << 5) +#define DANUBE_IOM_MODEH_RAC (1 << 3) +#define DANUBE_IOM_MODEH_DIM2 (1 << 2) +#define DANUBE_IOM_MODEH_DIM1 (1 << 1) +#define DANUBE_IOM_MODEH_DIM0 (1 << 0) + +/***Extended Mode Register***/ +#define DANUBE_IOM_EXMR ((volatile u32*)(DANUBE_IOM+ 0x008C)) +#define DANUBE_IOM_EXMR_XFBS (1 << 7) +#define DANUBE_IOM_EXMR_RFBS (value) (((( 1 << 2) - 1) & (value)) << 5) +#define DANUBE_IOM_EXMR_SRA (1 << 4) +#define DANUBE_IOM_EXMR_XCRC (1 << 3) +#define DANUBE_IOM_EXMR_RCRC (1 << 2) +#define DANUBE_IOM_EXMR_ITF (1 << 0) + +/***SAPI1 Register***/ +#define DANUBE_IOM_SAP1 ((volatile u32*)(DANUBE_IOM+ 0x0094)) +#define DANUBE_IOM_SAP1_SAPI1 (value) (((( 1 << 6) - 1) & (value)) << 2) +#define DANUBE_IOM_SAP1_MHA (1 << 0) + +/***Receive Frame Byte Count Low***/ +#define DANUBE_IOM_RBCL ((volatile u32*)(DANUBE_IOM+ 0x0098)) +#define DANUBE_IOM_RBCL_RBC(value) (1 << value) + + +/***SAPI2 Register***/ +#define DANUBE_IOM_SAP2 ((volatile u32*)(DANUBE_IOM+ 0x0098)) +#define DANUBE_IOM_SAP2_SAPI2 (value) (((( 1 << 6) - 1) & (value)) << 2) +#define DANUBE_IOM_SAP2_MLA (1 << 0) + +/***Receive Frame Byte Count High***/ +#define DANUBE_IOM_RBCH ((volatile u32*)(DANUBE_IOM+ 0x009C)) +#define DANUBE_IOM_RBCH_OV (1 << 4) +#define DANUBE_IOM_RBCH_RBC11 (1 << 3) +#define DANUBE_IOM_RBCH_RBC10 (1 << 2) +#define DANUBE_IOM_RBCH_RBC9 (1 << 1) +#define DANUBE_IOM_RBCH_RBC8 (1 << 0) + +/***TEI1 Register 1***/ +#define DANUBE_IOM_TEI1 ((volatile u32*)(DANUBE_IOM+ 0x009C)) +#define DANUBE_IOM_TEI1_TEI1 (value) (((( 1 << 7) - 1) & (value)) << 1) +#define DANUBE_IOM_TEI1_EA (1 << 0) + +/***Receive Status Register***/ +#define DANUBE_IOM_RSTA ((volatile u32*)(DANUBE_IOM+ 0x00A0)) +#define DANUBE_IOM_RSTA_VFR (1 << 7) +#define DANUBE_IOM_RSTA_RDO (1 << 6) +#define DANUBE_IOM_RSTA_CRC (1 << 5) +#define DANUBE_IOM_RSTA_RAB (1 << 4) +#define DANUBE_IOM_RSTA_SA1 (1 << 3) +#define DANUBE_IOM_RSTA_SA0 (1 << 2) +#define DANUBE_IOM_RSTA_TA (1 << 0) +#define DANUBE_IOM_RSTA_CR (1 << 1) + +/***TEI2 Register***/ +#define DANUBE_IOM_TEI2 ((volatile u32*)(DANUBE_IOM+ 0x00A0)) +#define DANUBE_IOM_TEI2_TEI2 (value) (((( 1 << 7) - 1) & (value)) << 1) +#define DANUBE_IOM_TEI2_EA (1 << 0) + +/***Test Mode Register HDLC***/ +#define DANUBE_IOM_TMH ((volatile u32*)(DANUBE_IOM+ 0x00A4)) +#define DANUBE_IOM_TMH_TLP (1 << 0) + +/***Command/Indication Receive 0***/ +#define DANUBE_IOM_CIR0 ((volatile u32*)(DANUBE_IOM+ 0x00B8)) +#define DANUBE_IOM_CIR0_CODR0 (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_IOM_CIR0_CIC0 (1 << 3) +#define DANUBE_IOM_CIR0_CIC1 (1 << 2) +#define DANUBE_IOM_CIR0_SG (1 << 1) +#define DANUBE_IOM_CIR0_BAS (1 << 0) + +/***Command/Indication Transmit 0***/ +#define DANUBE_IOM_CIX0 ((volatile u32*)(DANUBE_IOM+ 0x00B8)) +#define DANUBE_IOM_CIX0_CODX0 (value) (((( 1 << 4) - 1) & (value)) << 4) +#define DANUBE_IOM_CIX0_TBA2 (1 << 3) +#define DANUBE_IOM_CIX0_TBA1 (1 << 2) +#define DANUBE_IOM_CIX0_TBA0 (1 << 1) +#define DANUBE_IOM_CIX0_BAC (1 << 0) + +/***Command/Indication Receive 1***/ +#define DANUBE_IOM_CIR1 ((volatile u32*)(DANUBE_IOM+ 0x00BC)) +#define DANUBE_IOM_CIR1_CODR1 (value) (((( 1 << 6) - 1) & (value)) << 2) + +/***Command/Indication Transmit 1***/ +#define DANUBE_IOM_CIX1 ((volatile u32*)(DANUBE_IOM+ 0x00BC)) +#define DANUBE_IOM_CIX1_CODX1 (value) (((( 1 << 6) - 1) & (value)) << 2) +#define DANUBE_IOM_CIX1_CICW (1 << 1) +#define DANUBE_IOM_CIX1_CI1E (1 << 0) + +/***Controller Data Access Reg. (CH10)***/ +#define DANUBE_IOM_CDA10 ((volatile u32*)(DANUBE_IOM+ 0x0100)) +#define DANUBE_IOM_CDA10_CDA (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Controller Data Access Reg. (CH11)***/ +#define DANUBE_IOM_CDA11 ((volatile u32*)(DANUBE_IOM+ 0x0104)) +#define DANUBE_IOM_CDA11_CDA (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Controller Data Access Reg. (CH20)***/ +#define DANUBE_IOM_CDA20 ((volatile u32*)(DANUBE_IOM+ 0x0108)) +#define DANUBE_IOM_CDA20_CDA (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Controller Data Access Reg. (CH21)***/ +#define DANUBE_IOM_CDA21 ((volatile u32*)(DANUBE_IOM+ 0x010C)) +#define DANUBE_IOM_CDA21_CDA (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH10)***/ +#define DANUBE_IOM_CDA_TSDP10 ((volatile u32*)(DANUBE_IOM+ 0x0110)) +#define DANUBE_IOM_CDA_TSDP10_DPS (1 << 7) +#define DANUBE_IOM_CDA_TSDP10_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH11)***/ +#define DANUBE_IOM_CDA_TSDP11 ((volatile u32*)(DANUBE_IOM+ 0x0114)) +#define DANUBE_IOM_CDA_TSDP11_DPS (1 << 7) +#define DANUBE_IOM_CDA_TSDP11_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH20)***/ +#define DANUBE_IOM_CDA_TSDP20 ((volatile u32*)(DANUBE_IOM+ 0x0118)) +#define DANUBE_IOM_CDA_TSDP20_DPS (1 << 7) +#define DANUBE_IOM_CDA_TSDP20_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH21)***/ +#define DANUBE_IOM_CDA_TSDP21 ((volatile u32*)(DANUBE_IOM+ 0x011C)) +#define DANUBE_IOM_CDA_TSDP21_DPS (1 << 7) +#define DANUBE_IOM_CDA_TSDP21_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH10)***/ +#define DANUBE_IOM_CO_TSDP10 ((volatile u32*)(DANUBE_IOM+ 0x0120)) +#define DANUBE_IOM_CO_TSDP10_DPS (1 << 7) +#define DANUBE_IOM_CO_TSDP10_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH11)***/ +#define DANUBE_IOM_CO_TSDP11 ((volatile u32*)(DANUBE_IOM+ 0x0124)) +#define DANUBE_IOM_CO_TSDP11_DPS (1 << 7) +#define DANUBE_IOM_CO_TSDP11_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH20)***/ +#define DANUBE_IOM_CO_TSDP20 ((volatile u32*)(DANUBE_IOM+ 0x0128)) +#define DANUBE_IOM_CO_TSDP20_DPS (1 << 7) +#define DANUBE_IOM_CO_TSDP20_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Time Slot and Data Port Sel. (CH21)***/ +#define DANUBE_IOM_CO_TSDP21 ((volatile u32*)(DANUBE_IOM+ 0x012C)) +#define DANUBE_IOM_CO_TSDP21_DPS (1 << 7) +#define DANUBE_IOM_CO_TSDP21_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Ctrl. Reg. Contr. Data Access CH1x***/ +#define DANUBE_IOM_CDA1_CR ((volatile u32*)(DANUBE_IOM+ 0x0138)) +#define DANUBE_IOM_CDA1_CR_EN_TBM (1 << 5) +#define DANUBE_IOM_CDA1_CR_EN_I1 (1 << 4) +#define DANUBE_IOM_CDA1_CR_EN_I0 (1 << 3) +#define DANUBE_IOM_CDA1_CR_EN_O1 (1 << 2) +#define DANUBE_IOM_CDA1_CR_EN_O0 (1 << 1) +#define DANUBE_IOM_CDA1_CR_SWAP (1 << 0) + +/***Ctrl. Reg. Contr. Data Access CH1x***/ +#define DANUBE_IOM_CDA2_CR ((volatile u32*)(DANUBE_IOM+ 0x013C)) +#define DANUBE_IOM_CDA2_CR_EN_TBM (1 << 5) +#define DANUBE_IOM_CDA2_CR_EN_I1 (1 << 4) +#define DANUBE_IOM_CDA2_CR_EN_I0 (1 << 3) +#define DANUBE_IOM_CDA2_CR_EN_O1 (1 << 2) +#define DANUBE_IOM_CDA2_CR_EN_O0 (1 << 1) +#define DANUBE_IOM_CDA2_CR_SWAP (1 << 0) + +/***Control Register B-Channel Data***/ +#define DANUBE_IOM_BCHA_CR ((volatile u32*)(DANUBE_IOM+ 0x0144)) +#define DANUBE_IOM_BCHA_CR_EN_BC2 (1 << 4) +#define DANUBE_IOM_BCHA_CR_EN_BC1 (1 << 3) + +/***Control Register B-Channel Data***/ +#define DANUBE_IOM_BCHB_CR ((volatile u32*)(DANUBE_IOM+ 0x0148)) +#define DANUBE_IOM_BCHB_CR_EN_BC2 (1 << 4) +#define DANUBE_IOM_BCHB_CR_EN_BC1 (1 << 3) + +/***Control Reg. for HDLC and CI1 Data***/ +#define DANUBE_IOM_DCI_CR ((volatile u32*)(DANUBE_IOM+ 0x014C)) +#define DANUBE_IOM_DCI_CR_DPS_CI1 (1 << 7) +#define DANUBE_IOM_DCI_CR_EN_CI1 (1 << 6) +#define DANUBE_IOM_DCI_CR_EN_D (1 << 5) + +/***Control Reg. for HDLC and CI1 Data***/ +#define DANUBE_IOM_DCIC_CR ((volatile u32*)(DANUBE_IOM+ 0x014C)) +#define DANUBE_IOM_DCIC_CR_DPS_CI0 (1 << 7) +#define DANUBE_IOM_DCIC_CR_EN_CI0 (1 << 6) +#define DANUBE_IOM_DCIC_CR_DPS_D (1 << 5) + +/***Control Reg. Serial Data Strobe x***/ +#define DANUBE_IOM_SDS_CR ((volatile u32*)(DANUBE_IOM+ 0x0154)) +#define DANUBE_IOM_SDS_CR_ENS_TSS (1 << 7) +#define DANUBE_IOM_SDS_CR_ENS_TSS_1 (1 << 6) +#define DANUBE_IOM_SDS_CR_ENS_TSS_3 (1 << 5) +#define DANUBE_IOM_SDS_CR_TSS (value) (((( 1 << 4) - 1) & (value)) << 0) + +/***Control Register IOM Data***/ +#define DANUBE_IOM_IOM_CR ((volatile u32*)(DANUBE_IOM+ 0x015C)) +#define DANUBE_IOM_IOM_CR_SPU (1 << 7) +#define DANUBE_IOM_IOM_CR_CI_CS (1 << 5) +#define DANUBE_IOM_IOM_CR_TIC_DIS (1 << 4) +#define DANUBE_IOM_IOM_CR_EN_BCL (1 << 3) +#define DANUBE_IOM_IOM_CR_CLKM (1 << 2) +#define DANUBE_IOM_IOM_CR_Res (1 << 1) +#define DANUBE_IOM_IOM_CR_DIS_IOM (1 << 0) + +/***Synchronous Transfer Interrupt***/ +#define DANUBE_IOM_STI ((volatile u32*)(DANUBE_IOM+ 0x0160)) +#define DANUBE_IOM_STI_STOV21 (1 << 7) +#define DANUBE_IOM_STI_STOV20 (1 << 6) +#define DANUBE_IOM_STI_STOV11 (1 << 5) +#define DANUBE_IOM_STI_STOV10 (1 << 4) +#define DANUBE_IOM_STI_STI21 (1 << 3) +#define DANUBE_IOM_STI_STI20 (1 << 2) +#define DANUBE_IOM_STI_STI11 (1 << 1) +#define DANUBE_IOM_STI_STI10 (1 << 0) + +/***Acknowledge Synchronous Transfer Interrupt***/ +#define DANUBE_IOM_ASTI ((volatile u32*)(DANUBE_IOM+ 0x0160)) +#define DANUBE_IOM_ASTI_ACK21 (1 << 3) +#define DANUBE_IOM_ASTI_ACK20 (1 << 2) +#define DANUBE_IOM_ASTI_ACK11 (1 << 1) +#define DANUBE_IOM_ASTI_ACK10 (1 << 0) + +/***Mask Synchronous Transfer Interrupt***/ +#define DANUBE_IOM_MSTI ((volatile u32*)(DANUBE_IOM+ 0x0164)) +#define DANUBE_IOM_MSTI_STOV21 (1 << 7) +#define DANUBE_IOM_MSTI_STOV20 (1 << 6) +#define DANUBE_IOM_MSTI_STOV11 (1 << 5) +#define DANUBE_IOM_MSTI_STOV10 (1 << 4) +#define DANUBE_IOM_MSTI_STI21 (1 << 3) +#define DANUBE_IOM_MSTI_STI20 (1 << 2) +#define DANUBE_IOM_MSTI_STI11 (1 << 1) +#define DANUBE_IOM_MSTI_STI10 (1 << 0) + +/***Configuration Register for Serial Data Strobes***/ +#define DANUBE_IOM_SDS_CONF ((volatile u32*)(DANUBE_IOM+ 0x0168)) +#define DANUBE_IOM_SDS_CONF_SDS_BCL (1 << 0) + +/***Monitoring CDA Bits***/ +#define DANUBE_IOM_MCDA ((volatile u32*)(DANUBE_IOM+ 0x016C)) +#define DANUBE_IOM_MCDA_MCDA21 (value) (((( 1 << 2) - 1) & (value)) << 6) +#define DANUBE_IOM_MCDA_MCDA20 (value) (((( 1 << 2) - 1) & (value)) << 4) +#define DANUBE_IOM_MCDA_MCDA11 (value) (((( 1 << 2) - 1) & (value)) << 2) +#define DANUBE_IOM_MCDA_MCDA10 (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : ASC0 register address and bits */ +/***********************************************************************/ +#define DANUBE_ASC0 (KSEG1+0x1E100400) +/***********************************************************************/ +#define DANUBE_ASC0_TBUF ((volatile u32*)(DANUBE_ASC0 + 0x0020)) +#define DANUBE_ASC0_RBUF ((volatile u32*)(DANUBE_ASC0 + 0x0024)) +#define DANUBE_ASC0_FSTAT ((volatile u32*)(DANUBE_ASC0 + 0x0048)) +#define DANUBE_ASC0_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1)) +#define DANUBE_ASC0_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24) +#define DANUBE_ASC0_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1)) +#define DANUBE_ASC0_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16) +#define DANUBE_ASC0_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1)) +#define DANUBE_ASC0_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8) +#define DANUBE_ASC0_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1)) +#define DANUBE_ASC0_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : ASC1 register address and bits */ +/***********************************************************************/ + +#define DANUBE_ASC1 (KSEG1+0x1E100C00) + /***********************************************************************/ + +#define DANUBE_ASC1_TBUF ((volatile u32*)(DANUBE_ASC1 + 0x0020)) +#define DANUBE_ASC1_RBUF ((volatile u32*)(DANUBE_ASC1 + 0x0024)) +#define DANUBE_ASC1_FSTAT ((volatile u32*)(DANUBE_ASC1 + 0x0048)) +#define DANUBE_ASC1_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1)) +#define DANUBE_ASC1_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24) +#define DANUBE_ASC1_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1)) +#define DANUBE_ASC1_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16) +#define DANUBE_ASC1_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1)) +#define DANUBE_ASC1_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8) +#define DANUBE_ASC1_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1)) +#define DANUBE_ASC1_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : DMA register address and bits */ +/***********************************************************************/ +/***********************************************************************/ +/* Module : DMA register address and bits */ +/***********************************************************************/ + +#define DANUBE_DMA (0xBE104100) +/***********************************************************************/ + +#define DANUBE_DMA_BASE DANUBE_DMA +#define DANUBE_DMA_CLC (volatile u32*)DANUBE_DMA_BASE +#define DANUBE_DMA_ID (volatile u32*)(DANUBE_DMA_BASE+0x08) +#define DANUBE_DMA_CTRL (volatile u32*)(DANUBE_DMA_BASE+0x10) +#define DANUBE_DMA_CPOLL (volatile u32*)(DANUBE_DMA_BASE+0x14) +#define DANUBE_DMA_CS (volatile u32*)(DANUBE_DMA_BASE+0x18) +#define DANUBE_DMA_CCTRL (volatile u32*)(DANUBE_DMA_BASE+0x1C) +#define DANUBE_DMA_CDBA (volatile u32*)(DANUBE_DMA_BASE+0x20) +#define DANUBE_DMA_CDLEN (volatile u32*)(DANUBE_DMA_BASE+0x24) +#define DANUBE_DMA_CIS (volatile u32*)(DANUBE_DMA_BASE+0x28) +#define DANUBE_DMA_CIE (volatile u32*)(DANUBE_DMA_BASE+0x2C) + +#define DANUBE_DMA_PS (volatile u32*)(DANUBE_DMA_BASE+0x40) +#define DANUBE_DMA_PCTRL (volatile u32*)(DANUBE_DMA_BASE+0x44) + +#define DANUBE_DMA_IRNEN (volatile u32*)(DANUBE_DMA_BASE+0xf4) +#define DANUBE_DMA_IRNCR (volatile u32*)(DANUBE_DMA_BASE+0xf8) +#define DANUBE_DMA_IRNICR (volatile u32*)(DANUBE_DMA_BASE+0xfc) +/***********************************************************************/ +/* Module : Debug register address and bits */ +/***********************************************************************/ + +#define DANUBE_Debug (0xBF106000) +/***********************************************************************/ + + +/***MCD Break Bus Switch Register***/ +#define DANUBE_Debug_MCD_BBS ((volatile u32*)(DANUBE_Debug+ 0x0000)) +#define DANUBE_Debug_MCD_BBS_BTP1 (1 << 19) +#define DANUBE_Debug_MCD_BBS_BTP0 (1 << 18) +#define DANUBE_Debug_MCD_BBS_BSP1 (1 << 17) +#define DANUBE_Debug_MCD_BBS_BSP0 (1 << 16) +#define DANUBE_Debug_MCD_BBS_BT5EN (1 << 15) +#define DANUBE_Debug_MCD_BBS_BT4EN (1 << 14) +#define DANUBE_Debug_MCD_BBS_BT5 (1 << 13) +#define DANUBE_Debug_MCD_BBS_BT4 (1 << 12) +#define DANUBE_Debug_MCD_BBS_BS5EN (1 << 7) +#define DANUBE_Debug_MCD_BBS_BS4EN (1 << 6) +#define DANUBE_Debug_MCD_BBS_BS5 (1 << 5) +#define DANUBE_Debug_MCD_BBS_BS4 (1 << 4) + +/***MCD Multiplexer Control Register***/ +#define DANUBE_Debug_MCD_MCR ((volatile u32*)(DANUBE_Debug+ 0x0008)) +#define DANUBE_Debug_MCD_MCR_MUX5 (1 << 4) +#define DANUBE_Debug_MCD_MCR_MUX4 (1 << 3) +#define DANUBE_Debug_MCD_MCR_MUX1 (1 << 0) + + +/***********************************************************************/ +/* Module : SRAM register address and bits */ +/***********************************************************************/ + +#define DANUBE_SRAM (0xBF980000) +/***********************************************************************/ + + +/***SRAM Size Register***/ +#define DANUBE_SRAM_SRAM_SIZE ((volatile u32*)(DANUBE_SRAM+ 0x0800)) +#define DANUBE_SRAM_SRAM_SIZE_SIZE (value) (((( 1 << 23) - 1) & (value)) << 0) + +/***********************************************************************/ +/* Module : BIU register address and bits */ +/***********************************************************************/ + +#define DANUBE_BIU (0xBFA80000) +/***********************************************************************/ + + +/***BIU Identification Register***/ +#define DANUBE_BIU_BIU_ID ((volatile u32*)(DANUBE_BIU+ 0x0000)) +#define DANUBE_BIU_BIU_ID_ARCH (1 << 16) +#define DANUBE_BIU_BIU_ID_ID (value) (((( 1 << 8) - 1) & (value)) << 8) +#define DANUBE_BIU_BIU_ID_REV (value) (((( 1 << 8) - 1) & (value)) << 0) + +/***BIU Access Error Cause Register***/ +#define DANUBE_BIU_BIU_ERRCAUSE ((volatile u32*)(DANUBE_BIU+ 0x0100)) +#define DANUBE_BIU_BIU_ERRCAUSE_ERR (1 << 31) +#define DANUBE_BIU_BIU_ERRCAUSE_PORT (value) (((( 1 << 4) - 1) & (value)) << 16) +#define DANUBE_BIU_BIU_ERRCAUSE_CAUSE (value) (((( 1 << 2) - 1) & (value)) << 0) + +/***BIU Access Error Address Register***/ +#define DANUBE_BIU_BIU_ERRADDR ((volatile u32*)(DANUBE_BIU+ 0x0108)) +#define DANUBE_BIU_BIU_ERRADDR_ADDR + + +/***********************************************************************/ +/* Module : ICU register address and bits */ +/***********************************************************************/ + +#define DANUBE_ICU (0xBF880200) +#define DANUBE_ICU (0xBF880200) +#define DANUBE_ICU_EXI (0xBF101000) +/***********************************************************************/ + + +/***IM0 Interrupt Status Register***/ +#define DANUBE_ICU_IM0_ISR ((volatile u32*)(DANUBE_ICU+ 0x0000)) +#define DANUBE_ICU_IM0_ISR_IR(value) (1 << (value)) + + +/***IM1 Interrupt Status Register***/ +#define DANUBE_ICU_IM1_ISR ((volatile u32*)(DANUBE_ICU+ 0x0020)) +#define DANUBE_ICU_IM1_ISR_IR(value) (1 << (value)) + + +/***IM2 Interrupt Status Register***/ +#define DANUBE_ICU_IM2_ISR ((volatile u32*)(DANUBE_ICU+ 0x0040)) +#define DANUBE_ICU_IM2_ISR_IR(value) (1 << (value)) + +/***IM3 Interrupt Status Register***/ +#define DANUBE_ICU_IM3_ISR ((volatile u32*)(DANUBE_ICU+ 0x0060)) +#define DANUBE_ICU_IM3_ISR_IR(value) (1 << (value)) + +/***IM4 Interrupt Status Register***/ +#define DANUBE_ICU_IM4_ISR ((volatile u32*)(DANUBE_ICU+ 0x0080)) +#define DANUBE_ICU_IM4_ISR_IR(value) (1 << (value)) + + +/***IM0 Interrupt Enable Register***/ +#define DANUBE_ICU_IM0_IER ((volatile u32*)(DANUBE_ICU+ 0x0008)) +#define DANUBE_ICU_IM0_IER_IR(value) (1 << (value)) + + +/***IM1 Interrupt Enable Register***/ +#define DANUBE_ICU_IM1_IER ((volatile u32*)(DANUBE_ICU+ 0x0028)) +#define DANUBE_ICU_IM1_IER_IR(value) (1 << (value)) + + +/***IM2 Interrupt Enable Register***/ +#define DANUBE_ICU_IM2_IER ((volatile u32*)(DANUBE_ICU+ 0x0048)) +#define DANUBE_ICU_IM2_IER_IR(value) (1 << (value)8 + +/***IM3 Interrupt Enable Register***/ +#define DANUBE_ICU_IM3_IER ((volatile u32*)(DANUBE_ICU+ 0x0068)) +#define DANUBE_ICU_IM3_IER_IR(value) (1 << (value)) + +/***IM4 Interrupt Enable Register***/ +#define DANUBE_ICU_IM4_IER ((volatile u32*)(DANUBE_ICU+ 0x0088)) +#define DANUBE_ICU_IM4_IER_IR(value) (1 << (value)) + + +/***IM0 Interrupt Output Status Register***/ +#define DANUBE_ICU_IM0_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0010)) +#define DANUBE_ICU_IM0_IOSR_IR(value) (1 << (value)) + + +/***IM1 Interrupt Output Status Register***/ +#define DANUBE_ICU_IM1_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0030)) +#define DANUBE_ICU_IM1_IOSR_IR(value) (1 << (value)) + + +/***IM2 Interrupt Output Status Register***/ +#define DANUBE_ICU_IM2_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0050)) +#define DANUBE_ICU_IM2_IOSR_IR(value) (1 << (value)) + +/***IM3 Interrupt Output Status Register***/ +#define DANUBE_ICU_IM3_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0070)) +#define DANUBE_ICU_IM3_IOSR_IR(value) (1 << (value)) + +/***IM4 Interrupt Output Status Register***/ +#define DANUBE_ICU_IM4_IOSR ((volatile u32*)(DANUBE_ICU+ 0x0090)) +#define DANUBE_ICU_IM4_IOSR_IR(value) (1 << (value)) + + +/***IM0 Interrupt Request Set Register***/ +#define DANUBE_ICU_IM0_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0018)) +#define DANUBE_ICU_IM0_IRSR_IR(value) (1 << (value)) + + +/***IM1 Interrupt Request Set Register***/ +#define DANUBE_ICU_IM1_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0038)) +#define DANUBE_ICU_IM1_IRSR_IR(value) (1 << (value)) + + +/***IM2 Interrupt Request Set Register***/ +#define DANUBE_ICU_IM2_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0058)) +#define DANUBE_ICU_IM2_IRSR_IR(value) (1 << (value)) + +/***IM3 Interrupt Request Set Register***/ +#define DANUBE_ICU_IM3_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0078)) +#define DANUBE_ICU_IM3_IRSR_IR(value) (1 << (value)) + +/***IM4 Interrupt Request Set Register***/ +#define DANUBE_ICU_IM4_IRSR ((volatile u32*)(DANUBE_ICU+ 0x0098)) +#define DANUBE_ICU_IM4_IRSR_IR(value) (1 << (value)) + +/***Interrupt Vector Value Register***/ +#define DANUBE_ICU_IM_VEC ((volatile u32*)(DANUBE_ICU+ 0x0060)) + +/***Interrupt Vector Value Mask***/ +#define DANUBE_ICU_IM0_VEC_MASK 0x0000001f +#define DANUBE_ICU_IM1_VEC_MASK 0x000003e0 +#define DANUBE_ICU_IM2_VEC_MASK 0x00007c00 +#define DANUBE_ICU_IM3_VEC_MASK 0x000f8000 +#define DANUBE_ICU_IM4_VEC_MASK 0x01f00000 + +/***DMA Interrupt Mask Value***/ +#define DANUBE_DMA_H_MASK 0x00000fff + +/***External Interrupt Control Register***/ +#define DANUBE_ICU_EXTINTCR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0000)) +#define DANUBE_ICU_IRNICR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0004)) +#define DANUBE_ICU_IRNCR ((volatile u32*)(DANUBE_ICU_EXI+ 0x0008)) +#define DANUBE_ICU_IRNEN ((volatile u32*)(DANUBE_ICU_EXI+ 0x000c)) +#define DANUBE_ICU_NMI_CR ((volatile u32*)(DANUBE_ICU_EXI+ 0x00f0)) +#define DANUBE_ICU_NMI_SR ((volatile u32*)(DANUBE_ICU_EXI+ 0x00f4)) + +/***********************************************************************/ +/* Module : MPS register address and bits */ +/***********************************************************************/ + +#define DANUBE_MPS (KSEG1+0x1F107000) +/***********************************************************************/ + +#define DANUBE_MPS_CHIPID ((volatile u32*)(DANUBE_MPS + 0x0344)) +#define DANUBE_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) +#define DANUBE_MPS_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28) +#define DANUBE_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define DANUBE_MPS_CHIPID_PARTNUM_SET(value) (((( 1 << 16) - 1) & (value)) << 12) +#define DANUBE_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) +#define DANUBE_MPS_CHIPID_MANID_SET(value) (((( 1 << 10) - 1) & (value)) << 1) + + +/* voice channel 0 ... 3 interrupt enable register */ +#define DANUBE_MPS_VC0ENR ((volatile u32*)(DANUBE_MPS + 0x0000)) +#define DANUBE_MPS_VC1ENR ((volatile u32*)(DANUBE_MPS + 0x0004)) +#define DANUBE_MPS_VC2ENR ((volatile u32*)(DANUBE_MPS + 0x0008)) +#define DANUBE_MPS_VC3ENR ((volatile u32*)(DANUBE_MPS + 0x000C)) +/* voice channel 0 ... 3 interrupt status read register */ +#define DANUBE_MPS_RVC0SR ((volatile u32*)(DANUBE_MPS + 0x0010)) +#define DANUBE_MPS_RVC1SR ((volatile u32*)(DANUBE_MPS + 0x0014)) +#define DANUBE_MPS_RVC2SR ((volatile u32*)(DANUBE_MPS + 0x0018)) +#define DANUBE_MPS_RVC3SR ((volatile u32*)(DANUBE_MPS + 0x001C)) +/* voice channel 0 ... 3 interrupt status set register */ +#define DANUBE_MPS_SVC0SR ((volatile u32*)(DANUBE_MPS + 0x0020)) +#define DANUBE_MPS_SVC1SR ((volatile u32*)(DANUBE_MPS + 0x0024)) +#define DANUBE_MPS_SVC2SR ((volatile u32*)(DANUBE_MPS + 0x0028)) +#define DANUBE_MPS_SVC3SR ((volatile u32*)(DANUBE_MPS + 0x002C)) +/* voice channel 0 ... 3 interrupt status clear register */ +#define DANUBE_MPS_CVC0SR ((volatile u32*)(DANUBE_MPS + 0x0030)) +#define DANUBE_MPS_CVC1SR ((volatile u32*)(DANUBE_MPS + 0x0034)) +#define DANUBE_MPS_CVC2SR ((volatile u32*)(DANUBE_MPS + 0x0038)) +#define DANUBE_MPS_CVC3SR ((volatile u32*)(DANUBE_MPS + 0x003C)) +/* common status 0 and 1 read register */ +#define DANUBE_MPS_RAD0SR ((volatile u32*)(DANUBE_MPS + 0x0040)) +#define DANUBE_MPS_RAD1SR ((volatile u32*)(DANUBE_MPS + 0x0044)) +/* common status 0 and 1 set register */ +#define DANUBE_MPS_SAD0SR ((volatile u32*)(DANUBE_MPS + 0x0048)) +#define DANUBE_MPS_SAD1SR ((volatile u32*)(DANUBE_MPS + 0x004C)) +/* common status 0 and 1 clear register */ +#define DANUBE_MPS_CAD0SR ((volatile u32*)(DANUBE_MPS + 0x0050)) +#define DANUBE_MPS_CAD1SR ((volatile u32*)(DANUBE_MPS + 0x0054)) +/* common status 0 and 1 enable register */ +#define DANUBE_MPS_AD0ENR ((volatile u32*)(DANUBE_MPS + 0x0058)) +#define DANUBE_MPS_AD1ENR ((volatile u32*)(DANUBE_MPS + 0x005C)) +/* notification enable register */ +#define DANUBE_MPS_CPU0_NFER ((volatile u32*)(DANUBE_MPS + 0x0060)) +#define DANUBE_MPS_CPU1_NFER ((volatile u32*)(DANUBE_MPS + 0x0064)) +/* CPU to CPU interrup request register */ +#define DANUBE_MPS_CPU0_2_CPU1_IRR ((volatile u32*)(DANUBE_MPS + 0x0070)) +#define DANUBE_MPS_CPU0_2_CPU1_IER ((volatile u32*)(DANUBE_MPS + 0x0074)) +/* Global interrupt request and request enable register */ +#define DANUBE_MPS_GIRR ((volatile u32*)(DANUBE_MPS + 0x0078)) +#define DANUBE_MPS_GIER ((volatile u32*)(DANUBE_MPS + 0x007C)) + + +#define DANUBE_MPS_CPU0_SMP0 ((volatile u32*)(DANUBE_MPS + 0x00100)) + +#define DANUBE_MPS_CPU1_SMP0 ((volatile u32*)(DANUBE_MPS + 0x00200)) + +/************************************************************************/ +/* Module : DEU register address and bits */ +/************************************************************************/ +#define DANUBE_DEU_BASE_ADDR (0xBE102000) +/* DEU Control Register */ +#define DANUBE_DEU_CLK ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0000)) +#define DANUBE_DEU_ID ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0008)) + +/* DEU control register */ +#define DANUBE_DEU_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0010)) +#define DANUBE_DEU_IHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0014)) +#define DANUBE_DEU_ILR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0018)) +#define DANUBE_DEU_K1HR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x001C)) +#define DANUBE_DEU_K1LR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0020)) +#define DANUBE_DEU_K3HR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0024)) +#define DANUBE_DEU_K3LR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0028)) +#define DANUBE_DEU_IVHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x002C)) +#define DANUBE_DEU_IVLR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0030)) +#define DANUBE_DEU_OHR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0040)) +#define DANUBE_DEU_OLR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0050)) + +/* AES DEU register */ +#define DANUBE_AES_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0050)) +#define DANUBE_AES_ID3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0054)) +#define DANUBE_AES_ID2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0058)) +#define DANUBE_AES_ID1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x005C)) +#define DANUBE_AES_ID0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0060)) + +/* AES Key register */ +#define DANUBE_AES_K7R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0064)) +#define DANUBE_AES_K6R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0068)) +#define DANUBE_AES_K5R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x006C)) +#define DANUBE_AES_K4R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0070)) +#define DANUBE_AES_K3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0074)) +#define DANUBE_AES_K2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0078)) +#define DANUBE_AES_K1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x007C)) +#define DANUBE_AES_K0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0080)) + +/* AES vector register */ +#define DANUBE_AES_IV3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0084)) +#define DANUBE_AES_IV2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0088)) +#define DANUBE_AES_IV1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x008C)) +#define DANUBE_AES_IV0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0090)) +#define DANUBE_AES_0D3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0094)) +#define DANUBE_AES_0D2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x0098)) +#define DANUBE_AES_OD1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x009C)) +#define DANUBE_AES_OD0R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00A0)) + +/* hash control registe */ +#define DANUBE_HASH_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B0)) +#define DANUBE_HASH_MR ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B4)) +#define DANUBE_HASH_D1R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00B8 )) +#define DANUBE_HASH_D2R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00BC )) +#define DANUBE_HASH_D3R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C0 )) +#define DANUBE_HASH_D4R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C4)) +#define DANUBE_HASH_D5R ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00C8)) + +#define DANUBE_CON ((volatile u32 *)(DANUBE_DEU_BASE_ADDR + 0x00EC)) + + + + +/************************************************************************/ +/* Module : PPE register address and bits */ +/************************************************************************/ +#define DANUBE_PPE_BASE_ADDR (KSEG1 + 0x1E180000) +#define DANUBE_PPE_PP32_DEBUG_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0000) << 2))) +#define DANUBE_PPE_PPM_INT_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0030) << 2))) +#define DANUBE_PPE_PP32_INTERNAL_RES_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0040) << 2))) +#define DANUBE_PPE_PPE_CLOCK_CONTROL_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x0100) << 2))) +#define DANUBE_PPE_CDM_CODE_MEMORY_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x1000) << 2))) +#define DANUBE_PPE_CDM_CODE_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x2000) << 2))) +#define DANUBE_PPE_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x4000) << 2))) +#define DANUBE_PPE_PP32_DATA_MEMORY_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x5000) << 2))) +#define DANUBE_PPE_PPM_INT_UNIT_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6000) << 2))) +#define DANUBE_PPE_PPM_TIMER0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6100) << 2))) +#define DANUBE_PPE_PPM_TASK_IND_REG_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6200) << 2))) +#define DANUBE_PPE_PPS_BRK_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6300) << 2))) +#define DANUBE_PPE_PPM_TIMER1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x6400) << 2))) +#define DANUBE_PPE_SB_RAM0_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8000) << 2))) +#define DANUBE_PPE_SB_RAM1_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8400) << 2))) +#define DANUBE_PPE_SB_RAM2_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x8C00) << 2))) +#define DANUBE_PPE_SB_RAM3_ADDR(x) ((volatile u32*)(DANUBE_PPE_BASE_ADDR + (((x) + 0x9600) << 2))) + +#define DANUBE_PPE_PP32_SLEEP DANUBE_PPE_REG_ADDR(0x0010) /* PP32 Power Saving Register */ +#define DANUBE_PPE_CDM_CFG DANUBE_PPE_REG_ADDR(0x0100) /* Code/Data Memory (CDM) Register */ + +/* Mailbox Registers */ +#define DANUBE_PPE_MBOX_IGU0_ISRS DANUBE_PPE_REG_ADDR(0x0200) +#define DANUBE_PPE_MBOX_IGU0_ISRC DANUBE_PPE_REG_ADDR(0x0201) +#define DANUBE_PPE_MBOX_IGU0_ISR DANUBE_PPE_REG_ADDR(0x0202) +#define DANUBE_PPE_MBOX_IGU0_IER DANUBE_PPE_REG_ADDR(0x0203) +#define DANUBE_PPE_MBOX_IGU1_ISRS0 DANUBE_PPE_REG_ADDR(0x0204) +#define DANUBE_PPE_MBOX_IGU1_ISRC0 DANUBE_PPE_REG_ADDR(0x0205) +#define DANUBE_PPE_MBOX_IGU1_ISR0 DANUBE_PPE_REG_ADDR(0x0206) +#define DANUBE_PPE_MBOX_IGU1_IER0 DANUBE_PPE_REG_ADDR(0x0207) +#define DANUBE_PPE_MBOX_IGU1_ISRS1 DANUBE_PPE_REG_ADDR(0x0208) +#define DANUBE_PPE_MBOX_IGU1_ISRC1 DANUBE_PPE_REG_ADDR(0x0209) +#define DANUBE_PPE_MBOX_IGU1_ISR1 DANUBE_PPE_REG_ADDR(0x020A) +#define DANUBE_PPE_MBOX_IGU1_IER1 DANUBE_PPE_REG_ADDR(0x020B) +#define DANUBE_PPE_MBOX_IGU1_ISRS2 DANUBE_PPE_REG_ADDR(0x020C) +#define DANUBE_PPE_MBOX_IGU1_ISRC2 DANUBE_PPE_REG_ADDR(0x020D) +#define DANUBE_PPE_MBOX_IGU1_ISR2 DANUBE_PPE_REG_ADDR(0x020E) +#define DANUBE_PPE_MBOX_IGU1_IER2 DANUBE_PPE_REG_ADDR(0x020F) +#define DANUBE_PPE_MBOX_IGU2_ISRS DANUBE_PPE_REG_ADDR(0x0210) +#define DANUBE_PPE_MBOX_IGU2_ISRC DANUBE_PPE_REG_ADDR(0x0211) +#define DANUBE_PPE_MBOX_IGU2_ISR DANUBE_PPE_REG_ADDR(0x0212) +#define DANUBE_PPE_MBOX_IGU2_IER DANUBE_PPE_REG_ADDR(0x0213) +#define DANUBE_PPE_MBOX_IGU3_ISRS DANUBE_PPE_REG_ADDR(0x0214) +#define DANUBE_PPE_MBOX_IGU3_ISRC DANUBE_PPE_REG_ADDR(0x0215) +#define DANUBE_PPE_MBOX_IGU3_ISR DANUBE_PPE_REG_ADDR(0x0216) +#define DANUBE_PPE_MBOX_IGU3_IER DANUBE_PPE_REG_ADDR(0x0217) +#define DANUBE_PPE_MBOX_IGU4_ISRS DANUBE_PPE_REG_ADDR(0x0218) +#define DANUBE_PPE_MBOX_IGU4_ISRC DANUBE_PPE_REG_ADDR(0x0219) +#define DANUBE_PPE_MBOX_IGU4_ISR DANUBE_PPE_REG_ADDR(0x021A) +#define DANUBE_PPE_MBOX_IGU4_IER DANUBE_PPE_REG_ADDR(0x021B) +/* + * Shared Buffer (SB) Registers + */ +#define DANUBE_PPE_SB_MST_PRI0 DANUBE_PPE_REG_ADDR(0x0300) +#define DANUBE_PPE_SB_MST_PRI1 DANUBE_PPE_REG_ADDR(0x0301) +#define DANUBE_PPE_SB_MST_PRI2 DANUBE_PPE_REG_ADDR(0x0302) +#define DANUBE_PPE_SB_MST_PRI3 DANUBE_PPE_REG_ADDR(0x0303) +#define DANUBE_PPE_SB_MST_PRI4 DANUBE_PPE_REG_ADDR(0x0304) +#define DANUBE_PPE_SB_MST_SEL DANUBE_PPE_REG_ADDR(0x0305) +/* + * RTHA Registers + */ +#define DANUBE_PPE_RFBI_CFG DANUBE_PPE_REG_ADDR(0x0400) +#define DANUBE_PPE_RBA_CFG0 DANUBE_PPE_REG_ADDR(0x0404) +#define DANUBE_PPE_RBA_CFG1 DANUBE_PPE_REG_ADDR(0x0405) +#define DANUBE_PPE_RCA_CFG0 DANUBE_PPE_REG_ADDR(0x0408) +#define DANUBE_PPE_RCA_CFG1 DANUBE_PPE_REG_ADDR(0x0409) +#define DANUBE_PPE_RDES_CFG0 DANUBE_PPE_REG_ADDR(0x040C) +#define DANUBE_PPE_RDES_CFG1 DANUBE_PPE_REG_ADDR(0x040D) +#define DANUBE_PPE_SFSM_STATE0 DANUBE_PPE_REG_ADDR(0x0410) +#define DANUBE_PPE_SFSM_STATE1 DANUBE_PPE_REG_ADDR(0x0411) +#define DANUBE_PPE_SFSM_DBA0 DANUBE_PPE_REG_ADDR(0x0412) +#define DANUBE_PPE_SFSM_DBA1 DANUBE_PPE_REG_ADDR(0x0413) +#define DANUBE_PPE_SFSM_CBA0 DANUBE_PPE_REG_ADDR(0x0414) +#define DANUBE_PPE_SFSM_CBA1 DANUBE_PPE_REG_ADDR(0x0415) +#define DANUBE_PPE_SFSM_CFG0 DANUBE_PPE_REG_ADDR(0x0416) +#define DANUBE_PPE_SFSM_CFG1 DANUBE_PPE_REG_ADDR(0x0417) +#define DANUBE_PPE_SFSM_PGCNT0 DANUBE_PPE_REG_ADDR(0x041C) +#define DANUBE_PPE_SFSM_PGCNT1 DANUBE_PPE_REG_ADDR(0x041D) +/* + * TTHA Registers + */ +#define DANUBE_PPE_FFSM_DBA0 DANUBE_PPE_REG_ADDR(0x0508) +#define DANUBE_PPE_FFSM_DBA1 DANUBE_PPE_REG_ADDR(0x0509) +#define DANUBE_PPE_FFSM_CFG0 DANUBE_PPE_REG_ADDR(0x050A) +#define DANUBE_PPE_FFSM_CFG1 DANUBE_PPE_REG_ADDR(0x050B) +#define DANUBE_PPE_FFSM_IDLE_HEAD_BC0 DANUBE_PPE_REG_ADDR(0x050E) +#define DANUBE_PPE_FFSM_IDLE_HEAD_BC1 DANUBE_PPE_REG_ADDR(0x050F) +#define DANUBE_PPE_FFSM_PGCNT0 DANUBE_PPE_REG_ADDR(0x0514) +#define DANUBE_PPE_FFSM_PGCNT1 DANUBE_PPE_REG_ADDR(0x0515) +/* + * ETOP MDIO Registers + */ +#define DANUBE_PPE_ETOP_MDIO_CFG DANUBE_PPE_REG_ADDR(0x0600) +#define DANUBE_PPE_ETOP_MDIO_ACC DANUBE_PPE_REG_ADDR(0x0601) +#define DANUBE_PPE_ETOP_CFG DANUBE_PPE_REG_ADDR(0x0602) +#define DANUBE_PPE_ETOP_IG_VLAN_COS DANUBE_PPE_REG_ADDR(0x0603) +#define DANUBE_PPE_ETOP_IG_DSCP_COS3 DANUBE_PPE_REG_ADDR(0x0604) +#define DANUBE_PPE_ETOP_IG_DSCP_COS2 DANUBE_PPE_REG_ADDR(0x0605) +#define DANUBE_PPE_ETOP_IG_DSCP_COS1 DANUBE_PPE_REG_ADDR(0x0606) +#define DANUBE_PPE_ETOP_IG_DSCP_COS0 DANUBE_PPE_REG_ADDR(0x0607) +#define DANUBE_PPE_ETOP_IG_PLEN_CTRL0 DANUBE_PPE_REG_ADDR(0x0608) +#define DANUBE_PPE_ETOP_IG_PLEN_CTRL1 DANUBE_PPE_REG_ADDR(0x0609) +#define DANUBE_PPE_ETOP_ISR DANUBE_PPE_REG_ADDR(0x060A) +#define DANUBE_PPE_ETOP_IER DANUBE_PPE_REG_ADDR(0x060B) +#define DANUBE_PPE_ETOP_VPID DANUBE_PPE_REG_ADDR(0x060C) +#define DANUBE_PPE_ENET_MAC_CFG DANUBE_PPE_REG_ADDR(0x0610) +#define DANUBE_PPE_ENETS_DBA DANUBE_PPE_REG_ADDR(0x0612) +#define DANUBE_PPE_ENETS_CBA DANUBE_PPE_REG_ADDR(0x0613) +#define DANUBE_PPE_ENETS_CFG DANUBE_PPE_REG_ADDR(0x0614) +#define DANUBE_PPE_ENETS_PGCNT DANUBE_PPE_REG_ADDR(0x0615) +#define DANUBE_PPE_ENETS_PGCNT_DSRC_PP32 (0x00020000) +#define DANUBE_PPE_ENETS_PGCNT_DVAL_SHIFT (9) +#define DANUBE_PPE_ENETS_PGCNT_DCMD (0x00000100) +#define DANUBE_PPE_ENETS_PKTCNT DANUBE_PPE_REG_ADDR(0x0616) +#define DANUBE_PPE_ENETS_PKTCNT_DSRC_PP32 (0x00000200) +#define DANUBE_PPE_ENETS_PKTCNT_DCMD (0x00000100) +#define DANUBE_PPE_ENETS_PKTCNT_UPKT (0x000000FF) +#define DANUBE_PPE_ENETS_BUF_CTRL DANUBE_PPE_REG_ADDR(0x0617) +#define DANUBE_PPE_ENETS_COS_CFG DANUBE_PPE_REG_ADDR(0x0618) +#define DANUBE_PPE_ENETS_IGDROP DANUBE_PPE_REG_ADDR(0x0619) +#define DANUBE_PPE_ENETF_DBA DANUBE_PPE_REG_ADDR(0x0630) +#define DANUBE_PPE_ENETF_CBA DANUBE_PPE_REG_ADDR(0x0631) +#define DANUBE_PPE_ENETF_CFG DANUBE_PPE_REG_ADDR(0x0632) +#define DANUBE_PPE_ENETF_PGCNT DANUBE_PPE_REG_ADDR(0x0633) +#define DANUBE_PPE_ENETF_PGCNT_ISRC_PP32 (0x00020000) +#define DANUBE_PPE_ENETF_PGCNT_IVAL_SHIFT (9) +#define DANUBE_PPE_ENETF_PGCNT_ICMD (0x00000100) +#define DANUBE_PPE_ENETF_PKTCNT DANUBE_PPE_REG_ADDR(0x0634) +#define DANUBE_PPE_ENETF_PKTCNT_ISRC_PP32 (0x00000200) +#define DANUBE_PPE_ENETF_PKTCNT_ICMD (0x00000100) +#define DANUBE_PPE_ENETF_PKTCNT_VPKT (0x000000FF) +#define DANUBE_PPE_ENETF_HFCTRL DANUBE_PPE_REG_ADDR(0x0635) +#define DANUBE_PPE_ENETF_TXCTRL DANUBE_PPE_REG_ADDR(0x0636) +#define DANUBE_PPE_ENETF_VLCOS0 DANUBE_PPE_REG_ADDR(0x0638) +#define DANUBE_PPE_ENETF_VLCOS1 DANUBE_PPE_REG_ADDR(0x0639) +#define DANUBE_PPE_ENETF_VLCOS2 DANUBE_PPE_REG_ADDR(0x063A) +#define DANUBE_PPE_ENETF_VLCOS3 DANUBE_PPE_REG_ADDR(0x063B) +#define DANUBE_PPE_ENETF_EGERR DANUBE_PPE_REG_ADDR(0x063C) +#define DANUBE_PPE_ENETF_EGDROP DANUBE_PPE_REG_ADDR(0x063D) +/* + * DPLUS Registers + */ +#define DANUBE_PPE_DPLUS_TXDB DANUBE_PPE_REG_ADDR(0x0700) +#define DANUBE_PPE_DPLUS_TXCB DANUBE_PPE_REG_ADDR(0x0701) +#define DANUBE_PPE_DPLUS_TXCFG DANUBE_PPE_REG_ADDR(0x0702) +#define DANUBE_PPE_DPLUS_TXPGCNT DANUBE_PPE_REG_ADDR(0x0703) +#define DANUBE_PPE_DPLUS_RXDB DANUBE_PPE_REG_ADDR(0x0710) +#define DANUBE_PPE_DPLUS_RXCB DANUBE_PPE_REG_ADDR(0x0711) +#define DANUBE_PPE_DPLUS_RXCFG DANUBE_PPE_REG_ADDR(0x0712) +#define DANUBE_PPE_DPLUS_RXPGCNT DANUBE_PPE_REG_ADDR(0x0713) +/* + * BMC Registers + */ +#define DANUBE_PPE_BMC_CMD3 DANUBE_PPE_REG_ADDR(0x0800) +#define DANUBE_PPE_BMC_CMD2 DANUBE_PPE_REG_ADDR(0x0801) +#define DANUBE_PPE_BMC_CMD1 DANUBE_PPE_REG_ADDR(0x0802) +#define DANUBE_PPE_BMC_CMD0 DANUBE_PPE_REG_ADDR(0x0803) +#define DANUBE_PPE_BMC_CFG0 DANUBE_PPE_REG_ADDR(0x0804) +#define DANUBE_PPE_BMC_CFG1 DANUBE_PPE_REG_ADDR(0x0805) +#define DANUBE_PPE_BMC_POLY0 DANUBE_PPE_REG_ADDR(0x0806) +#define DANUBE_PPE_BMC_POLY1 DANUBE_PPE_REG_ADDR(0x0807) +#define DANUBE_PPE_BMC_CRC0 DANUBE_PPE_REG_ADDR(0x0808) +#define DANUBE_PPE_BMC_CRC1 DANUBE_PPE_REG_ADDR(0x0809) +/* + * SLL Registers + */ +#define DANUBE_PPE_SLL_CMD1 DANUBE_PPE_REG_ADDR(0x0900) +#define DANUBE_PPE_SLL_CMD0 DANUBE_PPE_REG_ADDR(0x0901) +#define DANUBE_PPE_SLL_KEY0 DANUBE_PPE_REG_ADDR(0x0910) +#define DANUBE_PPE_SLL_KEY1 DANUBE_PPE_REG_ADDR(0x0911) +#define DANUBE_PPE_SLL_KEY2 DANUBE_PPE_REG_ADDR(0x0912) +#define DANUBE_PPE_SLL_KEY3 DANUBE_PPE_REG_ADDR(0x0913) +#define DANUBE_PPE_SLL_KEY4 DANUBE_PPE_REG_ADDR(0x0914) +#define DANUBE_PPE_SLL_KEY5 DANUBE_PPE_REG_ADDR(0x0915) +#define DANUBE_PPE_SLL_RESULT DANUBE_PPE_REG_ADDR(0x0920) +/* + * EMA Registers + */ +#define DANUBE_PPE_EMA_CMD2 DANUBE_PPE_REG_ADDR(0x0A00) +#define DANUBE_PPE_EMA_CMD1 DANUBE_PPE_REG_ADDR(0x0A01) +#define DANUBE_PPE_EMA_CMD0 DANUBE_PPE_REG_ADDR(0x0A02) +#define DANUBE_PPE_EMA_ISR DANUBE_PPE_REG_ADDR(0x0A04) +#define DANUBE_PPE_EMA_IER DANUBE_PPE_REG_ADDR(0x0A05) +#define DANUBE_PPE_EMA_CFG DANUBE_PPE_REG_ADDR(0x0A06) +/* + * UTPS Registers + */ +#define DANUBE_PPE_UTP_TXCA0 DANUBE_PPE_REG_ADDR(0x0B00) +#define DANUBE_PPE_UTP_TXNA0 DANUBE_PPE_REG_ADDR(0x0B01) +#define DANUBE_PPE_UTP_TXCA1 DANUBE_PPE_REG_ADDR(0x0B02) +#define DANUBE_PPE_UTP_TXNA1 DANUBE_PPE_REG_ADDR(0x0B03) +#define DANUBE_PPE_UTP_RXCA0 DANUBE_PPE_REG_ADDR(0x0B10) +#define DANUBE_PPE_UTP_RXNA0 DANUBE_PPE_REG_ADDR(0x0B11) +#define DANUBE_PPE_UTP_RXCA1 DANUBE_PPE_REG_ADDR(0x0B12) +#define DANUBE_PPE_UTP_RXNA1 DANUBE_PPE_REG_ADDR(0x0B13) +#define DANUBE_PPE_UTP_CFG DANUBE_PPE_REG_ADDR(0x0B20) +#define DANUBE_PPE_UTP_ISR DANUBE_PPE_REG_ADDR(0x0B30) +#define DANUBE_PPE_UTP_IER DANUBE_PPE_REG_ADDR(0x0B31) +/* + * QSB Registers + */ +#define DANUBE_PPE_QSB_RELOG DANUBE_PPE_REG_ADDR(0x0C00) +#define DANUBE_PPE_QSB_EMIT0 DANUBE_PPE_REG_ADDR(0x0C01) +#define DANUBE_PPE_QSB_EMIT1 DANUBE_PPE_REG_ADDR(0x0C02) +#define DANUBE_PPE_QSB_ICDV DANUBE_PPE_REG_ADDR(0x0C07) +#define DANUBE_PPE_QSB_SBL DANUBE_PPE_REG_ADDR(0x0C09) +#define DANUBE_PPE_QSB_CFG DANUBE_PPE_REG_ADDR(0x0C0A) +#define DANUBE_PPE_QSB_RTM DANUBE_PPE_REG_ADDR(0x0C0B) +#define DANUBE_PPE_QSB_RTD DANUBE_PPE_REG_ADDR(0x0C0C) +#define DANUBE_PPE_QSB_RAMAC DANUBE_PPE_REG_ADDR(0x0C0D) +#define DANUBE_PPE_QSB_ISTAT DANUBE_PPE_REG_ADDR(0x0C0E) +#define DANUBE_PPE_QSB_IMR DANUBE_PPE_REG_ADDR(0x0C0F) +#define DANUBE_PPE_QSB_SRC DANUBE_PPE_REG_ADDR(0x0C10) +/* + * DSP User Registers + */ +#define DANUBE_PPE_DREG_A_VERSION DANUBE_PPE_REG_ADDR(0x0D00) +#define DANUBE_PPE_DREG_A_CFG DANUBE_PPE_REG_ADDR(0x0D01) +#define DANUBE_PPE_DREG_AT_CTRL DANUBE_PPE_REG_ADDR(0x0D02) +#define DANUBE_PPE_DREG_AR_CTRL DANUBE_PPE_REG_ADDR(0x0D08) +#define DANUBE_PPE_DREG_A_UTPCFG DANUBE_PPE_REG_ADDR(0x0D0E) +#define DANUBE_PPE_DREG_A_STATUS DANUBE_PPE_REG_ADDR(0x0D0F) +#define DANUBE_PPE_DREG_AT_CFG0 DANUBE_PPE_REG_ADDR(0x0D20) +#define DANUBE_PPE_DREG_AT_CFG1 DANUBE_PPE_REG_ADDR(0x0D21) +#define DANUBE_PPE_DREG_FB_SIZE0 DANUBE_PPE_REG_ADDR(0x0D22) +#define DANUBE_PPE_DREG_FB_SIZE1 DANUBE_PPE_REG_ADDR(0x0D23) +#define DANUBE_PPE_DREG_AT_CELL0 DANUBE_PPE_REG_ADDR(0x0D24) +#define DANUBE_PPE_DREG_AT_CELL1 DANUBE_PPE_REG_ADDR(0x0D25) +#define DANUBE_PPE_DREG_AT_IDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D26) +#define DANUBE_PPE_DREG_AT_IDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D27) +#define DANUBE_PPE_DREG_AT_IDLE0 DANUBE_PPE_REG_ADDR(0x0D28) +#define DANUBE_PPE_DREG_AT_IDLE1 DANUBE_PPE_REG_ADDR(0x0D29) +#define DANUBE_PPE_DREG_AR_CFG0 DANUBE_PPE_REG_ADDR(0x0D60) +#define DANUBE_PPE_DREG_AR_CFG1 DANUBE_PPE_REG_ADDR(0x0D61) +#define DANUBE_PPE_DREG_AR_FB_START0 DANUBE_PPE_REG_ADDR(0x0D62) +#define DANUBE_PPE_DREG_AR_FB_START1 DANUBE_PPE_REG_ADDR(0x0D63) +#define DANUBE_PPE_DREG_AR_FB_END0 DANUBE_PPE_REG_ADDR(0x0D64) +#define DANUBE_PPE_DREG_AR_FB_END1 DANUBE_PPE_REG_ADDR(0x0D65) +#define DANUBE_PPE_DREG_AR_ATM_STAT0 DANUBE_PPE_REG_ADDR(0x0D66) +#define DANUBE_PPE_DREG_AR_ATM_STAT1 DANUBE_PPE_REG_ADDR(0x0D67) +#define DANUBE_PPE_DREG_AR_CELL0 DANUBE_PPE_REG_ADDR(0x0D68) +#define DANUBE_PPE_DREG_AR_CELL1 DANUBE_PPE_REG_ADDR(0x0D69) +#define DANUBE_PPE_DREG_AR_IDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6A) +#define DANUBE_PPE_DREG_AR_IDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6B) +#define DANUBE_PPE_DREG_AR_AIIDLE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6C) +#define DANUBE_PPE_DREG_AR_AIIDLE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6D) +#define DANUBE_PPE_DREG_AR_BE_CNT0 DANUBE_PPE_REG_ADDR(0x0D6E) +#define DANUBE_PPE_DREG_AR_BE_CNT1 DANUBE_PPE_REG_ADDR(0x0D6F) +#define DANUBE_PPE_DREG_AR_HEC_CNT0 DANUBE_PPE_REG_ADDR(0x0D70) +#define DANUBE_PPE_DREG_AR_HEC_CNT1 DANUBE_PPE_REG_ADDR(0x0D71) +#define DANUBE_PPE_DREG_AR_CD_CNT0 DANUBE_PPE_REG_ADDR(0x0D72) +#define DANUBE_PPE_DREG_AR_CD_CNT1 DANUBE_PPE_REG_ADDR(0x0D73) +#define DANUBE_PPE_DREG_AR_IDLE0 DANUBE_PPE_REG_ADDR(0x0D74) +#define DANUBE_PPE_DREG_AR_IDLE1 DANUBE_PPE_REG_ADDR(0x0D75) +#define DANUBE_PPE_DREG_AR_DELIN0 DANUBE_PPE_REG_ADDR(0x0D76) +#define DANUBE_PPE_DREG_AR_DELIN1 DANUBE_PPE_REG_ADDR(0x0D77) +#define DANUBE_PPE_DREG_RESV0 DANUBE_PPE_REG_ADDR(0x0D78) +#define DANUBE_PPE_DREG_RESV1 DANUBE_PPE_REG_ADDR(0x0D79) +#define DANUBE_PPE_DREG_RX_MIB_CMD0 DANUBE_PPE_REG_ADDR(0x0D80) +#define DANUBE_PPE_DREG_RX_MIB_CMD1 DANUBE_PPE_REG_ADDR(0x0D81) +#define DANUBE_PPE_DREG_AR_OVDROP_CNT0 DANUBE_PPE_REG_ADDR(0x0D98) +#define DANUBE_PPE_DREG_AR_OVDROP_CNT1 DANUBE_PPE_REG_ADDR(0x0D99) + + +/************************************************************************/ +/* Module : PPE register address and bits */ +/************************************************************************/ +#define DANUBE_PPE32_BASE 0xBE180000 +#define DANUBE_PPE32_DEBUG_BREAK_TRACE_REG (DANUBE_PPE32_BASE + (0x0000 * 4)) +#define DANUBE_PPE32_INT_MASK_STATUS_REG (DANUBE_PPE32_BASE + (0x0030 * 4)) +#define DANUBE_PPE32_INT_RESOURCE_REG (DANUBE_PPE32_BASE + (0x0040 * 4)) +#define DANUBE_PPE32_CDM_CODE_MEM_B0 (DANUBE_PPE32_BASE + (0x1000 * 4)) +#define DANUBE_PPE32_CDM_CODE_MEM_B1 (DANUBE_PPE32_BASE + (0x2000 * 4)) +#define DANUBE_PPE32_DATA_MEM_MAP_REG_BASE (DANUBE_PPE32_BASE + (0x4000 * 4)) + +/************************************************************************/ +/* Module : PPE register address and bits */ +/************************************************************************/ +#define DANUBE_PPE32_BASE 0xBE180000 +#define DANUBE_PPE32_DEBUG_BREAK_TRACE_REG (DANUBE_PPE32_BASE + (0x0000 * 4)) +#define DANUBE_PPE32_INT_MASK_STATUS_REG (DANUBE_PPE32_BASE + (0x0030 * 4)) +#define DANUBE_PPE32_INT_RESOURCE_REG (DANUBE_PPE32_BASE + (0x0040 * 4)) +#define DANUBE_PPE32_CDM_CODE_MEM_B0 (DANUBE_PPE32_BASE + (0x1000 * 4)) +#define DANUBE_PPE32_CDM_CODE_MEM_B1 (DANUBE_PPE32_BASE + (0x2000 * 4)) +#define DANUBE_PPE32_DATA_MEM_MAP_REG_BASE (DANUBE_PPE32_BASE + (0x4000 * 4)) + +/* + * ETOP MDIO Registers + */ +#define ETOP_MDIO_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0600 * 4))) +#define ETOP_MDIO_ACC ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0601 * 4))) +#define ETOP_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0602 * 4))) +#define ETOP_IG_VLAN_COS ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0603 * 4))) +#define ETOP_IG_DSCP_COS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0604 * 4))) +#define ETOP_IG_DSCP_COS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0605 * 4))) +#define ETOP_IG_DSCP_COS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0606 * 4))) +#define ETOP_IG_DSCP_COS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0607 * 4))) +#define ETOP_IG_PLEN_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0608 * 4))) +#define ETOP_ISR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060A * 4))) +#define ETOP_IER ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060B * 4))) +#define ETOP_VPID ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060C * 4))) +#define ENET_MAC_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0610 * 4))) +#define ENETS_DBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0612 * 4))) +#define ENETS_CBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0613 * 4))) +#define ENETS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0614 * 4))) +#define ENETS_PGCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0615 * 4))) +#define ENETS_PKTCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0616 * 4))) +#define ENETS_BUF_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0617 * 4))) +#define ENETS_COS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0618 * 4))) +#define ENETS_IGDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0619 * 4))) +#define ENETS_IGERR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061A * 4))) +#define ENET_MAC_DA0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061B * 4))) +#define ENET_MAC_DA1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x061C * 4))) + +#define ENETF_DBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0630 * 4))) +#define ENETF_CBA ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0631 * 4))) +#define ENETF_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0632 * 4))) +#define ENETF_PGCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0633 * 4))) +#define ENETF_PKTCNT ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0634 * 4))) +#define ENETF_HFCTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0635 * 4))) +#define ENETF_TXCTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0636 * 4))) + +#define ENETF_VLCOS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0638 * 4))) +#define ENETF_VLCOS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0639 * 4))) +#define ENETF_VLCOS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063A * 4))) +#define ENETF_VLCOS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063B * 4))) +#define ENETF_EGERR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063C * 4))) +#define ENETF_EGDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x063D * 4))) + + +/* + * ETOP MDIO Registers + */ +#define DANUBE_PPE32_ETOP_MDIO_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0600 * 4))) +#define DANUBE_PPE32_ETOP_MDIO_ACC ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0601 * 4))) +#define DANUBE_PPE32_ETOP_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0602 * 4))) +#define DANUBE_PPE32_ETOP_IG_VLAN_COS ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0603 * 4))) +#define DANUBE_PPE32_ETOP_IG_DSCP_COS3 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0604 * 4))) +#define DANUBE_PPE32_ETOP_IG_DSCP_COS2 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0605 * 4))) +#define DANUBE_PPE32_ETOP_IG_DSCP_COS1 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0606 * 4))) +#define DANUBE_PPE32_ETOP_IG_DSCP_COS0 ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0607 * 4))) +#define DANUBE_PPE32_ETOP_IG_PLEN_CTRL ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0608 * 4))) +#define DANUBE_PPE32_ETOP_ISR ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060A * 4))) +#define DANUBE_PPE32_ETOP_IER ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060B * 4))) +#define DANUBE_PPE32_ETOP_VPID ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x060C * 4))) + + +/* ENET Register */ +#define DANUBE_PPE32_ENET_MAC_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0610 * 4))) +#define DANUBE_PPE32_ENET_IG_PKTDROP ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0619 * 4))) +#define DANUBE_PPE32_ENET_CoS_CFG ((volatile u32 *)(DANUBE_PPE32_DATA_MEM_MAP_REG_BASE + (0x0618 * 4))) + +/*********LED register definition****************/ + +#define DANUBE_LED 0xBE100BB0 +#define DANUBE_LED_CON0 ((volatile u32*)(DANUBE_LED + 0x0000)) +#define DANUBE_LED_CON1 ((volatile u32*)(DANUBE_LED + 0x0004)) +#define DANUBE_LED_CPU0 ((volatile u32*)(DANUBE_LED + 0x0008)) +#define DANUBE_LED_CPU1 ((volatile u32*)(DANUBE_LED + 0x000C)) +#define DANUBE_LED_AR ((volatile u32*)(DANUBE_LED + 0x0010)) + + + + +/***********************************************************************/ +#define DANUBE_REG32(addr) *((volatile u32 *)(addr)) +/***********************************************************************/ +#endif //DANUBE_H diff --git a/package/uboot-ifxmips/files/include/asm-mips/errno.h b/package/uboot-ifxmips/files/include/asm-mips/errno.h new file mode 100644 index 0000000000..134a8fc99c --- /dev/null +++ b/package/uboot-ifxmips/files/include/asm-mips/errno.h @@ -0,0 +1,138 @@ +#ifndef _ARM_ERRNO_H +#define _ARM_ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define ENXIO 6 /* No such device or address */ +#define E2BIG 7 /* Arg list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file number */ +#define ECHILD 10 /* No child processes */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* No such device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* File table overflow */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Not a typewriter */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only file system */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ +#define EDOM 33 /* Math argument out of domain of func */ +#define ERANGE 34 /* Math result not representable */ +#define EDEADLK 35 /* Resource deadlock would occur */ +#define ENAMETOOLONG 36 /* File name too long */ +#define ENOLCK 37 /* No record locks available */ +#define ENOSYS 38 /* Function not implemented */ +#define ENOTEMPTY 39 /* Directory not empty */ +#define ELOOP 40 /* Too many symbolic links encountered */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define ENOMSG 42 /* No message of desired type */ +#define EIDRM 43 /* Identifier removed */ +#define ECHRNG 44 /* Channel number out of range */ +#define EL2NSYNC 45 /* Level 2 not synchronized */ +#define EL3HLT 46 /* Level 3 halted */ +#define EL3RST 47 /* Level 3 reset */ +#define ELNRNG 48 /* Link number out of range */ +#define EUNATCH 49 /* Protocol driver not attached */ +#define ENOCSI 50 /* No CSI structure available */ +#define EL2HLT 51 /* Level 2 halted */ +#define EBADE 52 /* Invalid exchange */ +#define EBADR 53 /* Invalid request descriptor */ +#define EXFULL 54 /* Exchange full */ +#define ENOANO 55 /* No anode */ +#define EBADRQC 56 /* Invalid request code */ +#define EBADSLT 57 /* Invalid slot */ +#define EDEADLOCK 58 /* File locking deadlock error */ +#define EBFONT 59 /* Bad font file format */ +#define ENOSTR 60 /* Device not a stream */ +#define ENODATA 61 /* No data available */ +#define ETIME 62 /* Timer expired */ +#define ENOSR 63 /* Out of streams resources */ +#define ENONET 64 /* Machine is not on the network */ +#define ENOPKG 65 /* Package not installed */ +#define EREMOTE 66 /* Object is remote */ +#define ENOLINK 67 /* Link has been severed */ +#define EADV 68 /* Advertise error */ +#define ESRMNT 69 /* Srmount error */ +#define ECOMM 70 /* Communication error on send */ +#define EPROTO 71 /* Protocol error */ +#define EMULTIHOP 72 /* Multihop attempted */ +#define EDOTDOT 73 /* RFS specific error */ +#define EBADMSG 74 /* Not a data message */ +#define EOVERFLOW 75 /* Value too large for defined data type */ +#define ENOTUNIQ 76 /* Name not unique on network */ +#define EBADFD 77 /* File descriptor in bad state */ +#define EREMCHG 78 /* Remote address changed */ +#define ELIBACC 79 /* Can not access a needed shared library */ +#define ELIBBAD 80 /* Accessing a corrupted shared library */ +#define ELIBSCN 81 /* .lib section in a.out corrupted */ +#define ELIBMAX 82 /* Attempting to link in too many shared libraries */ +#define ELIBEXEC 83 /* Cannot exec a shared library directly */ +#define EILSEQ 84 /* Illegal byte sequence */ +#define ERESTART 85 /* Interrupted system call should be restarted */ +#define ESTRPIPE 86 /* Streams pipe error */ +#define EUSERS 87 /* Too many users */ +#define ENOTSOCK 88 /* Socket operation on non-socket */ +#define EDESTADDRREQ 89 /* Destination address required */ +#define EMSGSIZE 90 /* Message too long */ +#define EPROTOTYPE 91 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 92 /* Protocol not available */ +#define EPROTONOSUPPORT 93 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 94 /* Socket type not supported */ +#define EOPNOTSUPP 95 /* Operation not supported on transport endpoint */ +#define EPFNOSUPPORT 96 /* Protocol family not supported */ +#define EAFNOSUPPORT 97 /* Address family not supported by protocol */ +#define EADDRINUSE 98 /* Address already in use */ +#define EADDRNOTAVAIL 99 /* Cannot assign requested address */ +#define ENETDOWN 100 /* Network is down */ +#define ENETUNREACH 101 /* Network is unreachable */ +#define ENETRESET 102 /* Network dropped connection because of reset */ +#define ECONNABORTED 103 /* Software caused connection abort */ +#define ECONNRESET 104 /* Connection reset by peer */ +#define ENOBUFS 105 /* No buffer space available */ +#define EISCONN 106 /* Transport endpoint is already connected */ +#define ENOTCONN 107 /* Transport endpoint is not connected */ +#define ESHUTDOWN 108 /* Cannot send after transport endpoint shutdown */ +#define ETOOMANYREFS 109 /* Too many references: cannot splice */ +#define ETIMEDOUT 110 /* Connection timed out */ +#define ECONNREFUSED 111 /* Connection refused */ +#define EHOSTDOWN 112 /* Host is down */ +#define EHOSTUNREACH 113 /* No route to host */ +#define EALREADY 114 /* Operation already in progress */ +#define EINPROGRESS 115 /* Operation now in progress */ +#define ESTALE 116 /* Stale NFS file handle */ +#define EUCLEAN 117 /* Structure needs cleaning */ +#define ENOTNAM 118 /* Not a XENIX named type file */ +#define ENAVAIL 119 /* No XENIX semaphores available */ +#define EISNAM 120 /* Is a named type file */ +#define EREMOTEIO 121 /* Remote I/O error */ +#define EDQUOT 122 /* Quota exceeded */ + +#define ENOMEDIUM 123 /* No medium found */ +#define EMEDIUMTYPE 124 /* Wrong medium type */ + +/* Should never be seen by user programs */ +#define ERESTARTSYS 512 +#define ERESTARTNOINTR 513 +#define ERESTARTNOHAND 514 /* restart if no handler.. */ +#define ENOIOCTLCMD 515 /* No ioctl command */ + +#define _LAST_ERRNO 515 + +#endif diff --git a/package/uboot-ifxmips/files/include/asm-mips/ifx_asc.h b/package/uboot-ifxmips/files/include/asm-mips/ifx_asc.h new file mode 100644 index 0000000000..51abc950e1 --- /dev/null +++ b/package/uboot-ifxmips/files/include/asm-mips/ifx_asc.h @@ -0,0 +1,220 @@ +/***************************************************************************** + * DANUBE BootROM + * Copyright (c) 2005, Infineon Technologies AG, All rights reserved + * IFAP DC COM SD + *****************************************************************************/ +#ifndef __ASC_H +#define __ASC_H + +#define DANUBEASC_TXFIFO_FL 1 +#define DANUBEASC_RXFIFO_FL 1 +#define DANUBEASC_TXFIFO_FULL 16 + +/* channel operating modes */ +#define ASCOPT_CSIZE 0x00000003 +#define ASCOPT_CS7 0x00000001 +#define ASCOPT_CS8 0x00000002 +#define ASCOPT_PARENB 0x00000004 +#define ASCOPT_STOPB 0x00000008 +#define ASCOPT_PARODD 0x00000010 +#define ASCOPT_CREAD 0x00000020 + +#define ASC_OPTIONS (ASCOPT_CREAD | ASCOPT_CS8) + +/* ASC input select (0 or 1) */ +#define CONSOLE_TTY 0 + +#define DANUBEASC_TXFIFO_FL 1 +#define DANUBEASC_RXFIFO_FL 1 +#define DANUBEASC_TXFIFO_FULL 16 + +/* interrupt lines masks for the ASC device interrupts*/ +/* change these macroses if it's necessary */ +#define DANUBEASC_IRQ_LINE_ALL 0x0000007f /* all IRQs */ + +#define DANUBEASC_IRQ_LINE_TIR 0x00000001 /* Tx Int */ +#define DANUBEASC_IRQ_LINE_TBIR 0x00000002 /* Tx Buffer Int */ +#define DANUBEASC_IRQ_LINE_RIR 0x00000004 /* Rx Int */ +#define DANUBEASC_IRQ_LINE_EIR 0x00000008 /* Error Int */ +#define DANUBEASC_IRQ_LINE_ABSTIR 0x00000010 /* Autobaud Start Int */ +#define DANUBEASC_IRQ_LINE_ABDETIP 0x00000020 /* Autobaud Detection Int */ +#define DANUBEASC_IRQ_LINE_SFCIR 0x00000040 /* Software Flow Control Int */ + +/* interrupt controller access macros */ +#define ASC_INTERRUPTS_ENABLE(X) \ +*((volatile unsigned int*) DANUBE_ICU_IM0_IER) |= X; +#define ASC_INTERRUPTS_DISABLE(X) \ +*((volatile unsigned int*) DANUBE_ICU_IM0_IER) &= ~X; +#define ASC_INTERRUPTS_CLEAR(X) \ +*((volatile unsigned int*) DANUBE_ICU_IM0_ISR) = X; + +/* CLC register's bits and bitfields */ +#define ASCCLC_DISR 0x00000001 +#define ASCCLC_DISS 0x00000002 +#define ASCCLC_RMCMASK 0x0000FF00 +#define ASCCLC_RMCOFFSET 8 + +/* CON register's bits and bitfields */ +#define ASCCON_MODEMASK 0x0000000f +#define ASCCON_M_8ASYNC 0x0 +#define ASCCON_M_8IRDA 0x1 +#define ASCCON_M_7ASYNC 0x2 +#define ASCCON_M_7IRDA 0x3 +#define ASCCON_WLSMASK 0x0000000c +#define ASCCON_WLSOFFSET 2 +#define ASCCON_WLS_8BIT 0x0 +#define ASCCON_WLS_7BIT 0x1 +#define ASCCON_PEN 0x00000010 +#define ASCCON_ODD 0x00000020 +#define ASCCON_SP 0x00000040 +#define ASCCON_STP 0x00000080 +#define ASCCON_BRS 0x00000100 +#define ASCCON_FDE 0x00000200 +#define ASCCON_ERRCLK 0x00000400 +#define ASCCON_EMMASK 0x00001800 +#define ASCCON_EMOFFSET 11 +#define ASCCON_EM_ECHO_OFF 0x0 +#define ASCCON_EM_ECHO_AB 0x1 +#define ASCCON_EM_ECHO_ON 0x2 +#define ASCCON_LB 0x00002000 +#define ASCCON_ACO 0x00004000 +#define ASCCON_R 0x00008000 +#define ASCCON_PAL 0x00010000 +#define ASCCON_FEN 0x00020000 +#define ASCCON_RUEN 0x00040000 +#define ASCCON_ROEN 0x00080000 +#define ASCCON_TOEN 0x00100000 +#define ASCCON_BEN 0x00200000 +#define ASCCON_TXINV 0x01000000 +#define ASCCON_RXINV 0x02000000 +#define ASCCON_TXMSB 0x04000000 +#define ASCCON_RXMSB 0x08000000 + +/* STATE register's bits and bitfields */ +#define ASCSTATE_REN 0x00000001 +#define ASCSTATE_PE 0x00010000 +#define ASCSTATE_FE 0x00020000 +#define ASCSTATE_RUE 0x00040000 +#define ASCSTATE_ROE 0x00080000 +#define ASCSTATE_TOE 0x00100000 +#define ASCSTATE_BE 0x00200000 +#define ASCSTATE_TXBVMASK 0x07000000 +#define ASCSTATE_TXBVOFFSET 24 +#define ASCSTATE_TXEOM 0x08000000 +#define ASCSTATE_RXBVMASK 0x70000000 +#define ASCSTATE_RXBVOFFSET 28 +#define ASCSTATE_RXEOM 0x80000000 + +/* WHBSTATE register's bits and bitfields */ +#define ASCWHBSTATE_CLRREN 0x00000001 +#define ASCWHBSTATE_SETREN 0x00000002 +#define ASCWHBSTATE_CLRPE 0x00000004 +#define ASCWHBSTATE_CLRFE 0x00000008 +#define ASCWHBSTATE_CLRRUE 0x00000010 +#define ASCWHBSTATE_CLRROE 0x00000020 +#define ASCWHBSTATE_CLRTOE 0x00000040 +#define ASCWHBSTATE_CLRBE 0x00000080 +#define ASCWHBSTATE_SETPE 0x00000100 +#define ASCWHBSTATE_SETFE 0x00000200 +#define ASCWHBSTATE_SETRUE 0x00000400 +#define ASCWHBSTATE_SETROE 0x00000800 +#define ASCWHBSTATE_SETTOE 0x00001000 +#define ASCWHBSTATE_SETBE 0x00002000 + +/* ABCON register's bits and bitfields */ +#define ASCABCON_ABEN 0x0001 +#define ASCABCON_AUREN 0x0002 +#define ASCABCON_ABSTEN 0x0004 +#define ASCABCON_ABDETEN 0x0008 +#define ASCABCON_FCDETEN 0x0010 + +/* FDV register mask, offset and bitfields*/ +#define ASCFDV_VALUE_MASK 0x000001FF + +/* WHBABCON register's bits and bitfields */ +#define ASCWHBABCON_CLRABEN 0x0001 +#define ASCWHBABCON_SETABEN 0x0002 + +/* ABSTAT register's bits and bitfields */ +#define ASCABSTAT_FCSDET 0x0001 +#define ASCABSTAT_FCCDET 0x0002 +#define ASCABSTAT_SCSDET 0x0004 +#define ASCABSTAT_SCCDET 0x0008 +#define ASCABSTAT_DETWAIT 0x0010 + +/* WHBABSTAT register's bits and bitfields */ +#define ASCWHBABSTAT_CLRFCSDET 0x0001 +#define ASCWHBABSTAT_SETFCSDET 0x0002 +#define ASCWHBABSTAT_CLRFCCDET 0x0004 +#define ASCWHBABSTAT_SETFCCDET 0x0008 +#define ASCWHBABSTAT_CLRSCSDET 0x0010 +#define ASCWHBABSTAT_SETSCSDET 0x0020 +#define ASCWHBABSTAT_CLRSCCDET 0x0040 +#define ASCWHBABSTAT_SETSCCDET 0x0080 +#define ASCWHBABSTAT_CLRDETWAIT 0x0100 +#define ASCWHBABSTAT_SETDETWAIT 0x0200 + +/* TXFCON register's bits and bitfields */ +#define ASCTXFCON_TXFIFO1 0x00000400 +#define ASCTXFCON_TXFEN 0x0001 +#define ASCTXFCON_TXFFLU 0x0002 +#define ASCTXFCON_TXFITLMASK 0x3F00 +#define ASCTXFCON_TXFITLOFF 8 + +/* RXFCON register's bits and bitfields */ +#define ASCRXFCON_RXFIFO1 0x00000400 +#define ASCRXFCON_RXFEN 0x0001 +#define ASCRXFCON_RXFFLU 0x0002 +#define ASCRXFCON_RXFITLMASK 0x3F00 +#define ASCRXFCON_RXFITLOFF 8 + +/* FSTAT register's bits and bitfields */ +#define ASCFSTAT_RXFFLMASK 0x003F +#define ASCFSTAT_TXFFLMASK 0x3F00 +#define ASCFSTAT_TXFFLOFF 8 + +typedef struct /* DanubeAsc_t */ +{ + volatile unsigned long asc_clc; /*0x0000*/ + volatile unsigned long asc_pisel; /*0x0004*/ + volatile unsigned long asc_id; /*0x0008*/ + volatile unsigned long asc_rsvd1[1]; /* for mapping */ /*0x000C*/ + volatile unsigned long asc_con; /*0x0010*/ + volatile unsigned long asc_state; /*0x0014*/ + volatile unsigned long asc_whbstate; /*0x0018*/ + volatile unsigned long asc_rsvd2[1]; /* for mapping */ /*0x001C*/ + volatile unsigned long asc_tbuf; /*0x0020*/ + volatile unsigned long asc_rbuf; /*0x0024*/ + volatile unsigned long asc_rsvd3[2]; /* for mapping */ /*0x0028*/ + volatile unsigned long asc_abcon; /*0x0030*/ + volatile unsigned long asc_abstat; /* not used */ /*0x0034*/ + volatile unsigned long asc_whbabcon; /*0x0038*/ + volatile unsigned long asc_whbabstat; /* not used */ /*0x003C*/ + volatile unsigned long asc_rxfcon; /*0x0040*/ + volatile unsigned long asc_txfcon; /*0x0044*/ + volatile unsigned long asc_fstat; /*0x0048*/ + volatile unsigned long asc_rsvd4[1]; /* for mapping */ /*0x004C*/ + volatile unsigned long asc_bg; /*0x0050*/ + volatile unsigned long asc_bg_timer; /*0x0054*/ + volatile unsigned long asc_fdv; /*0x0058*/ + volatile unsigned long asc_pmw; /*0x005C*/ + volatile unsigned long asc_modcon; /*0x0060*/ + volatile unsigned long asc_modstat; /*0x0064*/ + volatile unsigned long asc_rsvd5[2]; /* for mapping */ /*0x0068*/ + volatile unsigned long asc_sfcc; /*0x0070*/ + volatile unsigned long asc_rsvd6[3]; /* for mapping */ /*0x0074*/ + volatile unsigned long asc_eomcon; /*0x0080*/ + volatile unsigned long asc_rsvd7[26]; /* for mapping */ /*0x0084*/ + volatile unsigned long asc_dmacon; /*0x00EC*/ + volatile unsigned long asc_rsvd8[1]; /* for mapping */ /*0x00F0*/ + volatile unsigned long asc_irnen; /*0x00F4*/ + volatile unsigned long asc_irnicr; /*0x00F8*/ + volatile unsigned long asc_irncr; /*0x00FC*/ +} DanubeAsc_t; + +int asc_init (void); +void asc_puts (const char *s); +void asc_putc (const char c); +int asc_getc (void); + +#endif /* __ASC_H */ diff --git a/package/uboot-ifxmips/files/include/asm-mips/inca-ip2.h b/package/uboot-ifxmips/files/include/asm-mips/inca-ip2.h new file mode 100644 index 0000000000..19c8ceb5cb --- /dev/null +++ b/package/uboot-ifxmips/files/include/asm-mips/inca-ip2.h @@ -0,0 +1,634 @@ +/************************************************************************ + * + * Copyright (c) 2005 + * Infineon Technologies AG + * St. Martin Strasse 53; 81669 Muenchen; Germany + * + * 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. + * + ************************************************************************/ + +/***********************************************************************/ +/* Module : DMA register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_DMA (KSEG1+0x14101000) +/***********************************************************************/ +#define CONFIGURATION_REGISTERS_CLC (INCA_IP2_DMA + 0x00) +#define CONFIGURATION_REGISTERS_ID (INCA_IP2_DMA + 0x08) +#define GENERAL_REGISTERS_DMA_CTRL (INCA_IP2_DMA + 0x10) +#define CHANNEL_RELATED_REGISTERS_DMA_CS (INCA_IP2_DMA + 0x18) +#define CHANNEL_RELATED_REGISTERS_DMA_CCTRL (INCA_IP2_DMA + 0x1C) +#define CHANNEL_RELATED_REGISTERS_DMA_CDBA (INCA_IP2_DMA + 0x20) +#define CHANNEL_RELATED_REGISTERS_DMA_CDLEN (INCA_IP2_DMA + 0x24) +#define CHANNEL_RELATED_REGISTERS_DMA_CIE (INCA_IP2_DMA + 0x2C) +#define CHANNEL_RELATED_REGISTERS_DMA_CIS (INCA_IP2_DMA + 0x28) +#define CHANNEL_RELATED_REGISTERS_DMA_CPOLL (INCA_IP2_DMA + 0x14) + +#define PORT_RELATED_REGISTERS_DMA_PS (INCA_IP2_DMA + 0x40) +#define PORT_RELATED_REGISTERS_DMA_PCTRL (INCA_IP2_DMA + 0x44) + +#define INTERRUPT_NODE_REGISTERS_DMA_IRNEN (INCA_IP2_DMA + 0xF4) +#define INTERRUPT_NODE_REGISTERS_DMA_IRNCR (INCA_IP2_DMA + 0xF8) +#define INTERRUPT_NODE_REGISTERS_DMA_IRNICR (INCA_IP2_DMA + 0xFC) + +#if 0 +/* ISR */ +#define DMA_ISR_RDERR 0x20 +#define DMA_ISR_CMDCPT 0x10 +#define DMA_ISR_CPT 0x8 +#define DMA_ISR_DURR 0x4 +#define DMA_ISR_EOP 0x2 +#endif +#define DMA_RESET_CHANNEL 0x00000002 +#define DMA_ENABLE_CHANNEL 0x00000001 +#define DMA_DESC_BYTEOFF_SHIFT 22 + +#define DMA_POLLING_ENABLE 0x80000000 +#define DMA_POLLING_CNT 0x50 /*minimum 0x10, max 0xfff0*/ + +/***********************************************************************/ +/* Module : ICU register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_ICU (KSEG1+0x1F880200) +/***********************************************************************/ + +#define INCA_IP2_ICU_IM0_ISR ((volatile u32*)(INCA_IP2_ICU + 0x0000)) +#define INCA_IP2_ICU_IM0_IER ((volatile u32*)(INCA_IP2_ICU + 0x0008)) +#define INCA_IP2_ICU_IM0_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x0010)) +#define INCA_IP2_ICU_IM0_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x0018)) +#define INCA_IP2_ICU_IM0_IMR ((volatile u32*)(INCA_IP2_ICU + 0x0020)) +#define INCA_IP2_ICU_IM0_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM0_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM0_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM0_IR(value) (1 << (value)) + +#define INCA_IP2_ICU_IM1_ISR ((volatile u32*)(INCA_IP2_ICU + 0x0028)) +#define INCA_IP2_ICU_IM1_IER ((volatile u32*)(INCA_IP2_ICU + 0x0030)) +#define INCA_IP2_ICU_IM1_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x0038)) +#define INCA_IP2_ICU_IM1_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x0040)) +#define INCA_IP2_ICU_IM1_IMR ((volatile u32*)(INCA_IP2_ICU + 0x0048)) +#define INCA_IP2_ICU_IM1_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM1_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM1_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM1_IR(value) (1 << (value)) + +#define INCA_IP2_ICU_IM2_ISR ((volatile u32*)(INCA_IP2_ICU + 0x0050)) +#define INCA_IP2_ICU_IM2_IER ((volatile u32*)(INCA_IP2_ICU + 0x0058)) +#define INCA_IP2_ICU_IM2_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x0060)) +#define INCA_IP2_ICU_IM2_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x0068)) +#define INCA_IP2_ICU_IM2_IMR ((volatile u32*)(INCA_IP2_ICU + 0x0070)) +#define INCA_IP2_ICU_IM2_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM2_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM2_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM2_IR(value) (1 << (value)) + +#define INCA_IP2_ICU_IM3_ISR ((volatile u32*)(INCA_IP2_ICU + 0x0078)) +#define INCA_IP2_ICU_IM3_IER ((volatile u32*)(INCA_IP2_ICU + 0x0080)) +#define INCA_IP2_ICU_IM3_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x0088)) +#define INCA_IP2_ICU_IM3_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x0090)) +#define INCA_IP2_ICU_IM3_IMR ((volatile u32*)(INCA_IP2_ICU + 0x0098)) +#define INCA_IP2_ICU_IM3_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM3_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM3_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM3_IR(value) (1 << (value)) + +#define INCA_IP2_ICU_IM4_ISR ((volatile u32*)(INCA_IP2_ICU + 0x00A0)) +#define INCA_IP2_ICU_IM4_IER ((volatile u32*)(INCA_IP2_ICU + 0x00A8)) +#define INCA_IP2_ICU_IM4_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x00B0)) +#define INCA_IP2_ICU_IM4_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x00B8)) +#define INCA_IP2_ICU_IM4_IMR ((volatile u32*)(INCA_IP2_ICU + 0x00C0)) +#define INCA_IP2_ICU_IM4_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM4_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM4_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM4_IR(value) (1 << (value)) + +#define INCA_IP2_ICU_IM5_ISR ((volatile u32*)(INCA_IP2_ICU + 0x00C8)) +#define INCA_IP2_ICU_IM5_IER ((volatile u32*)(INCA_IP2_ICU + 0x00D0)) +#define INCA_IP2_ICU_IM5_IOSR ((volatile u32*)(INCA_IP2_ICU + 0x00D8)) +#define INCA_IP2_ICU_IM5_IRSR ((volatile u32*)(INCA_IP2_ICU + 0x00E0)) +#define INCA_IP2_ICU_IM5_IMR ((volatile u32*)(INCA_IP2_ICU + 0x00E8)) +#define INCA_IP2_ICU_IM5_IMR_IID (1 << 31) +#define INCA_IP2_ICU_IM5_IMR_IN_GET(value) (((value) >> 0) & ((1 << 5) - 1)) +#define INCA_IP2_ICU_IM5_IMR_IN_SET(value) (((( 1 << 5) - 1) & (value)) << 0) +#define INCA_IP2_ICU_IM5_IR(value) (1 << (value)) + + +/***********************************************************************/ +/* Module : CGU register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_CGU (KSEG1+0x1F100800) +/***********************************************************************/ + +#define INCA_IP2_CGU_PLL2CR ((volatile u32*)(INCA_IP2_CGU + 0x0008)) +#define INCA_IP2_CGU_FBSCR ((volatile u32*)(INCA_IP2_CGU + 0x0018)) +#define INCA_IP2_CGU_FBSCR_LPBSDIV_GET(value) (((value) >> 6) & ((1 << 2) - 1)) +#define INCA_IP2_CGU_FBSCR_DIV0_GET(value) (((value) >> 0) & ((1 << 3) - 1)) +#define INCA_IP2_CGU_FBSCR_DIV1_GET(value) (((value) >> 4) & ((1 << 2) - 1)) + +/***********************************************************************/ +/* Module : MPS register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_MPS (KSEG1+0x1F101400) +/***********************************************************************/ + +#define INCA_IP2_MPS_CHIPID ((volatile u32*)(INCA_IP2_MPS + 0x0344)) +#define INCA_IP2_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) +#define INCA_IP2_MPS_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28) +#define INCA_IP2_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define INCA_IP2_MPS_CHIPID_PARTNUM_SET(value) (((( 1 << 16) - 1) & (value)) << 12) +#define INCA_IP2_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) +#define INCA_IP2_MPS_CHIPID_MANID_SET(value) (((( 1 << 10) - 1) & (value)) << 1) + + +/* voice channel 0 ... 3 interrupt enable register */ +#define INCA_IP2_MPS_VC0ENR ((volatile u32*)(INCA_IP2_MPS + 0x0000)) +#define INCA_IP2_MPS_VC1ENR ((volatile u32*)(INCA_IP2_MPS + 0x0004)) +#define INCA_IP2_MPS_VC2ENR ((volatile u32*)(INCA_IP2_MPS + 0x0008)) +#define INCA_IP2_MPS_VC3ENR ((volatile u32*)(INCA_IP2_MPS + 0x000C)) +/* voice channel 0 ... 3 interrupt status read register */ +#define INCA_IP2_MPS_RVC0SR ((volatile u32*)(INCA_IP2_MPS + 0x0010)) +#define INCA_IP2_MPS_RVC1SR ((volatile u32*)(INCA_IP2_MPS + 0x0014)) +#define INCA_IP2_MPS_RVC2SR ((volatile u32*)(INCA_IP2_MPS + 0x0018)) +#define INCA_IP2_MPS_RVC3SR ((volatile u32*)(INCA_IP2_MPS + 0x001C)) +/* voice channel 0 ... 3 interrupt status set register */ +#define INCA_IP2_MPS_SVC0SR ((volatile u32*)(INCA_IP2_MPS + 0x0020)) +#define INCA_IP2_MPS_SVC1SR ((volatile u32*)(INCA_IP2_MPS + 0x0024)) +#define INCA_IP2_MPS_SVC2SR ((volatile u32*)(INCA_IP2_MPS + 0x0028)) +#define INCA_IP2_MPS_SVC3SR ((volatile u32*)(INCA_IP2_MPS + 0x002C)) +/* voice channel 0 ... 3 interrupt status clear register */ +#define INCA_IP2_MPS_CVC0SR ((volatile u32*)(INCA_IP2_MPS + 0x0030)) +#define INCA_IP2_MPS_CVC1SR ((volatile u32*)(INCA_IP2_MPS + 0x0034)) +#define INCA_IP2_MPS_CVC2SR ((volatile u32*)(INCA_IP2_MPS + 0x0038)) +#define INCA_IP2_MPS_CVC3SR ((volatile u32*)(INCA_IP2_MPS + 0x003C)) +/* common status 0 and 1 read register */ +#define INCA_IP2_MPS_RAD0SR ((volatile u32*)(INCA_IP2_MPS + 0x0040)) +#define INCA_IP2_MPS_RAD1SR ((volatile u32*)(INCA_IP2_MPS + 0x0044)) +/* common status 0 and 1 set register */ +#define INCA_IP2_MPS_SAD0SR ((volatile u32*)(INCA_IP2_MPS + 0x0048)) +#define INCA_IP2_MPS_SAD1SR ((volatile u32*)(INCA_IP2_MPS + 0x004C)) +/* common status 0 and 1 clear register */ +#define INCA_IP2_MPS_CAD0SR ((volatile u32*)(INCA_IP2_MPS + 0x0050)) +#define INCA_IP2_MPS_CAD1SR ((volatile u32*)(INCA_IP2_MPS + 0x0054)) +/* notification enable register */ +#define INCA_IP2_MPS_CPU0_NFER ((volatile u32*)(INCA_IP2_MPS + 0x0060)) +#define INCA_IP2_MPS_CPU1_NFER ((volatile u32*)(INCA_IP2_MPS + 0x0064)) +/* CPU to CPU interrup request register */ +#define INCA_IP2_MPS_CPU0_2_CPU1_IRR ((volatile u32*)(INCA_IP2_MPS + 0x0070)) +#define INCA_IP2_MPS_CPU0_2_CPU1_IER ((volatile u32*)(INCA_IP2_MPS + 0x0074)) +/* Global interrupt request and request enable register */ +#define INCA_IP2_MPS_GIRR ((volatile u32*)(INCA_IP2_MPS + 0x0078)) +#define INCA_IP2_MPS_GIER ((volatile u32*)(INCA_IP2_MPS + 0x007C)) + +/* Addresses of enable registers not yet defined +#define INCA_IP2_MPS_AD0ENR ((volatile u32*)(INCA_IP2_MPS + 0x????)) +#define INCA_IP2_MPS_AD1ENR ((volatile u32*)(INCA_IP2_MPS + 0x????)) +*/ + + +/***********************************************************************/ +/* Module : ASC0 register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_ASC0 (KSEG1+0x1E000400) +/***********************************************************************/ + +#define INCA_IP2_ASC0_TBUF ((volatile u32*)(INCA_IP2_ASC0 + 0x0020)) +#define INCA_IP2_ASC0_RBUF ((volatile u32*)(INCA_IP2_ASC0 + 0x0024)) +#define INCA_IP2_ASC0_FSTAT ((volatile u32*)(INCA_IP2_ASC0 + 0x0048)) +#define INCA_IP2_ASC0_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1)) +#define INCA_IP2_ASC0_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24) +#define INCA_IP2_ASC0_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1)) +#define INCA_IP2_ASC0_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16) +#define INCA_IP2_ASC0_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1)) +#define INCA_IP2_ASC0_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8) +#define INCA_IP2_ASC0_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1)) +#define INCA_IP2_ASC0_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : ASC1 register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_ASC1 (KSEG1+0x1E000800) +/***********************************************************************/ + +#define INCA_IP2_ASC1_TBUF ((volatile u32*)(INCA_IP2_ASC1 + 0x0020)) +#define INCA_IP2_ASC1_RBUF ((volatile u32*)(INCA_IP2_ASC1 + 0x0024)) +#define INCA_IP2_ASC1_FSTAT ((volatile u32*)(INCA_IP2_ASC1 + 0x0048)) +#define INCA_IP2_ASC1_FSTAT_TXFREE_GET(value) (((value) >> 24) & ((1 << 6) - 1)) +#define INCA_IP2_ASC1_FSTAT_TXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 24) +#define INCA_IP2_ASC1_FSTAT_RXFREE_GET(value) (((value) >> 16) & ((1 << 6) - 1)) +#define INCA_IP2_ASC1_FSTAT_RXFREE_SET(value) (((( 1 << 6) - 1) & (value)) << 16) +#define INCA_IP2_ASC1_FSTAT_TXFFL_GET(value) (((value) >> 8) & ((1 << 6) - 1)) +#define INCA_IP2_ASC1_FSTAT_TXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 8) +#define INCA_IP2_ASC1_FSTAT_RXFFL_GET(value) (((value) >> 0) & ((1 << 6) - 1)) +#define INCA_IP2_ASC1_FSTAT_RXFFL_SET(value) (((( 1 << 6) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : RCU register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_RCU (KSEG1+0x1E001C00) +/***********************************************************************/ + +/***Reset Request Register***/ +#define INCA_IP2_RCU_RST_REQ ((volatile u32*)(INCA_IP2_RCU + 0x0000)) +#define INCA_IP2_RCU_RST_REQ_CPU0 (1 << 31) +#define INCA_IP2_RCU_RST_REQ_CPU1 (1 << 30) +#define INCA_IP2_RCU_RST_REQ_CPUSUB (1 << 29) +#define INCA_IP2_RCU_RST_REQ_HRST (1 << 28) +#define INCA_IP2_RCU_RST_REQ_WDT0 (1 << 27) +#define INCA_IP2_RCU_RST_REQ_WDT1 (1 << 26) +#define INCA_IP2_RCU_RST_REQ_CFG_GET(value) (((value) >> 23) & ((1 << 3) - 1)) +#define INCA_IP2_RCU_RST_REQ_CFG_SET(value) (((( 1 << 3) - 1) & (value)) << 23) +#define INCA_IP2_RCU_RST_REQ_SWTBOOT (1 << 22) +#define INCA_IP2_RCU_RST_REQ_DMA (1 << 21) +#define INCA_IP2_RCU_RST_REQ_ETHPHY1 (1 << 20) +#define INCA_IP2_RCU_RST_REQ_ETHPHY0 (1 << 19) +#define INCA_IP2_RCU_RST_REQ_CPU0_BR (1 << 18) + +/* CPU0, CPU1, CPUSUB, HRST, WDT0, WDT1, DMA, ETHPHY1, ETHPHY0 */ +#define INCA_IP2_RCU_RST_REQ_ALL 0xFC380000 + +/***NMI Status Register***/ +#define INCA_IP2_RCU_NMISR ((volatile u32*)(INCA_IP2_RCU + 0x00F4)) +#define INCA_IP2_RCU_NMISR_NMIEXT (1 << 2) +#define INCA_IP2_RCU_NMISR_NMIPLL2 (1 << 1) +#define INCA_IP2_RCU_NMISR_NMIPLL1 (1 << 0) + + +/***********************************************************************/ +/* Module : WDT register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_WDT (KSEG1+0x1F880000) +/***********************************************************************/ + +/***Watchdog Timer Control Register ***/ +#define INCA_IP2_WDT_BIU_WDT_CR ((volatile u32*)(INCA_IP2_WDT + 0x03F0)) +#define INCA_IP2_WDT_BIU_WDT_CR_GEN (1 << 31) +#define INCA_IP2_WDT_BIU_WDT_CR_DSEN (1 << 30) +#define INCA_IP2_WDT_BIU_WDT_CR_LPEN (1 << 29) +#define INCA_IP2_WDT_BIU_WDT_CR_PWL_GET(value) (((value) >> 26) & ((1 << 2) - 1)) +#define INCA_IP2_WDT_BIU_WDT_CR_PWL_SET(value) (((( 1 << 2) - 1) & (value)) << 26) +#define INCA_IP2_WDT_BIU_WDT_CR_CLKDIV_GET(value) (((value) >> 24) & ((1 << 2) - 1)) +#define INCA_IP2_WDT_BIU_WDT_CR_CLKDIV_SET(value) (((( 1 << 2) - 1) & (value)) << 24) +#define INCA_IP2_WDT_BIU_WDT_CR_PW_GET(value) (((value) >> 16) & ((1 << 8) - 1)) +#define INCA_IP2_WDT_BIU_WDT_CR_PW_SET(value) (((( 1 << 8) - 1) & (value)) << 16) +#define INCA_IP2_WDT_BIU_WDT_CR_RELOAD_GET(value) (((value) >> 0) & ((1 << 16) - 1)) +#define INCA_IP2_WDT_BIU_WDT_CR_RELOAD_SET(value) (((( 1 << 16) - 1) & (value)) << 0) + +/***Watchdog Timer Status Register***/ +#define INCA_IP2_WDT_BIU_WDT_SR ((volatile u32*)(INCA_IP2_WDT + 0x03F8)) +#define INCA_IP2_WDT_BIU_WDT_SR_EN (1 << 31) +#define INCA_IP2_WDT_BIU_WDT_SR_AE (1 << 30) +#define INCA_IP2_WDT_BIU_WDT_SR_PRW (1 << 29) +#define INCA_IP2_WDT_BIU_WDT_SR_EXP (1 << 28) +#define INCA_IP2_WDT_BIU_WDT_SR_PWD (1 << 27) +#define INCA_IP2_WDT_BIU_WDT_SR_DS (1 << 26) +#define INCA_IP2_WDT_BIU_WDT_SR_VALUE_GET(value) (((value) >> 0) & ((1 << 16) - 1)) +#define INCA_IP2_WDT_BIU_WDT_SR_VALUE_SET(value) (((( 1 << 16) - 1) & (value)) << 0) + + +/***********************************************************************/ +/* Module : BCU0 register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_BCU0 (KSEG1+0x14100000) +/***********************************************************************/ + +#define INCA_IP2_BCU0_CON ((volatile u32*)(INCA_IP2_BCU0 + 0x0010)) +#define INCA_IP2_BCU0_ECON ((volatile u32*)(INCA_IP2_BCU0 + 0x0020)) +#define INCA_IP2_BCU0_EADD ((volatile u32*)(INCA_IP2_BCU0 + 0x0024)) +#define INCA_IP2_BCU0_EDAT ((volatile u32*)(INCA_IP2_BCU0 + 0x0028)) +#define INCA_IP2_BCU0_IRNCR1 ((volatile u32*)(INCA_IP2_BCU0 + 0x00F8)) +#define INCA_IP2_BCU0_IRNCR0 ((volatile u32*)(INCA_IP2_BCU0 + 0x00FC)) + + +/***********************************************************************/ +/* Module : BCU1 register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_BCU1 (KSEG1+0x1E000000) +/***********************************************************************/ + +#define INCA_IP2_BCU1_CON ((volatile u32*)(INCA_IP2_BCU1 + 0x0010)) +#define INCA_IP2_BCU1_ECON ((volatile u32*)(INCA_IP2_BCU1 + 0x0020)) +#define INCA_IP2_BCU1_EADD ((volatile u32*)(INCA_IP2_BCU1 + 0x0024)) +#define INCA_IP2_BCU1_EDAT ((volatile u32*)(INCA_IP2_BCU1 + 0x0028)) +#define INCA_IP2_BCU1_IRNCR1 ((volatile u32*)(INCA_IP2_BCU1 + 0x00F8)) +#define INCA_IP2_BCU1_IRNCR0 ((volatile u32*)(INCA_IP2_BCU1 + 0x00FC)) + + +/***********************************************************************/ +/* Module : MC register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_MC (KSEG1+0x1F800000) +/***********************************************************************/ + +#define INCA_IP2_MC_ERRCAUSE ((volatile u32*)(INCA_IP2_MC + 0x0010)) +#define INCA_IP2_MC_ERRADDR ((volatile u32*)(INCA_IP2_MC + 0x0020)) +#define INCA_IP2_MC_CON ((volatile u32*)(INCA_IP2_MC + 0x0060)) + +/***********************************************************************/ +/* Module : MC SDRAM register address and bits */ +/***********************************************************************/ +#define INCA_IP2_SDRAM (KSEG1+0x1F800200) +/***********************************************************************/ +#define INCA_IP2_SDRAM_MC_CFGPB0 ((volatile u32*)(INCA_IP2_SDRAM + 0x0040)) + +/***********************************************************************/ +/* Module : MC DDR register address and bits */ +/***********************************************************************/ +#define INCA_IP2_DDR (KSEG1+0x1F801000) +/***********************************************************************/ +#define INCA_IP2_DDR_MC_DC19 ((volatile u32*)(INCA_IP2_DDR + 0x0130)) +#define INCA_IP2_DDR_MC_DC20 ((volatile u32*)(INCA_IP2_DDR + 0x0140)) + + +/***********************************************************************/ +/* Module : PMS register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_PMS (KSEG1 + 0x1F100C00) + +#define INCA_IP2_PMS_PMS_SR ((volatile u32*) (INCA_IP2_PMS + 0x0000)) +#define INCA_IP2_PMS_PMS_SR_ASC1 (1 << 14) +#define INCA_IP2_PMS_PMS_SR_ASC0 (1 << 13) +#define INCA_IP2_PMS_PMS_GEN ((volatile u32*) (INCA_IP2_PMS + 0x0004)) +#define INCA_IP2_PMS_PMS_GEN_DMA (1 << 16) +#define INCA_IP2_PMS_PMS_GEN_ASC1 (1 << 14) +#define INCA_IP2_PMS_PMS_GEN_ASC0 (1 << 13) +#define INCA_IP2_PMS_PMS_GEN_SPI0 (1 << 11) +#define INCA_IP2_PMS_PMS_GEN_SPI1 (1 << 12) +#define INCA_IP2_PMS_PMS_CFG ((volatile u32*) (INCA_IP2_PMS + 0x0008)) + + +/***********************************************************************/ +/* Module : GPIO register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_GPIO (KSEG1 + 0x1F102600) + +#define INCA_IP2_GPIO_OUT ((volatile u32*) (INCA_IP2_GPIO + 0x0000)) +#define INCA_IP2_GPIO_IN ((volatile u32*) (INCA_IP2_GPIO + 0x0004)) +#define INCA_IP2_GPIO_DIR ((volatile u32*) (INCA_IP2_GPIO + 0x0008)) +#define INCA_IP2_GPIO_ALTSEL1 ((volatile u32*) (INCA_IP2_GPIO + 0x000C)) +#define INCA_IP2_GPIO_ALTSEL2 ((volatile u32*) (INCA_IP2_GPIO + 0x0010)) +#define INCA_IP2_GPIO_STOFF ((volatile u32*) (INCA_IP2_GPIO + 0x0014)) +#define INCA_IP2_GPIO_OD ((volatile u32*) (INCA_IP2_GPIO + 0x0018)) +#define INCA_IP2_GPIO_PUDEB ((volatile u32*) (INCA_IP2_GPIO + 0x001C)) + +/***********************************************************************/ +/* Module : RCU register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_RCU (KSEG1+0x1E001C00) +/***********************************************************************/ + +/***Reset Request Register***/ +#define INCA_IP2_RCU_RST_REQ ((volatile u32*)(INCA_IP2_RCU + 0x0000)) +#define INCA_IP2_RCU_RST_REQ_CPU0 (1 << 31) +#define INCA_IP2_RCU_RST_REQ_CPU1 (1 << 30) +#define INCA_IP2_RCU_RST_REQ_CPUSUB (1 << 29) +#define INCA_IP2_RCU_RST_REQ_HRST (1 << 28) +#define INCA_IP2_RCU_RST_REQ_WDT0 (1 << 27) +#define INCA_IP2_RCU_RST_REQ_WDT1 (1 << 26) +#define INCA_IP2_RCU_RST_REQ_CFG_GET(value) (((value) >> 23) & ((1 << 3) - 1)) +#define INCA_IP2_RCU_RST_REQ_CFG_SET(value) (((( 1 << 3) - 1) & (value)) << 23) +#define INCA_IP2_RCU_RST_REQ_SWTBOOT (1 << 22) +#define INCA_IP2_RCU_RST_REQ_DMA (1 << 21) +#define INCA_IP2_RCU_RST_REQ_ETHPHY1 (1 << 20) +#define INCA_IP2_RCU_RST_REQ_ETHPHY0 (1 << 19) +#define INCA_IP2_RCU_RST_REQ_CPU0_BR (1 << 18) + +/* CPU0, CPU1, CPUSUB, HRST, WDT0, WDT1, DMA, ETHPHY1, ETHPHY0 */ +#define INCA_IP2_RCU_RST_REQ_ALL 0xFC380000 + +/***Reset Status Register***/ +#define INCA_IP2_RCU_SR ((volatile u32*)(INCA_IP2_RCU + 0x0008)) + +/***NMI Status Register***/ +#define INCA_IP2_RCU_NMISR ((volatile u32*)(INCA_IP2_RCU + 0x00F4)) +#define INCA_IP2_RCU_NMISR_NMIEXT (1 << 2) +#define INCA_IP2_RCU_NMISR_NMIPLL2 (1 << 1) +#define INCA_IP2_RCU_NMISR_NMIPLL1 (1 << 0) + +/***********************************************************************/ +/* Module : EBU register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_EBU (KSEG1+0x14102000) +/***********************************************************************/ + +#define INCA_IP2_EBU_ADDSEL0 ((volatile u32*)(INCA_IP2_EBU + 0x0020)) +#define INCA_IP2_EBU_ADDSEL1 ((volatile u32*)(INCA_IP2_EBU + 0x0024)) +#define INCA_IP2_EBU_ADDSEL2 ((volatile u32*)(INCA_IP2_EBU + 0x0028)) +#define INCA_IP2_EBU_ADDSEL3 ((volatile u32*)(INCA_IP2_EBU + 0x002C)) +#define INCA_IP2_EBU_CON0 ((volatile u32*)(INCA_IP2_EBU + 0x0060)) +#define INCA_IP2_EBU_CON1 ((volatile u32*)(INCA_IP2_EBU + 0x0064)) +#define INCA_IP2_EBU_CON2 ((volatile u32*)(INCA_IP2_EBU + 0x0068)) +#define INCA_IP2_EBU_CON3 ((volatile u32*)(INCA_IP2_EBU + 0x006C)) +#define INCA_IP2_EBU_CON_WRDIS (1 << 31) + + + + +/***********************************************************************/ +/* Module : SWITCH register address and bits */ +/***********************************************************************/ + +#define INCA_IP2_SWITCH (KSEG1+0x18000000) +/***********************************************************************/ + +/* PR Base address */ +#define PR_BASE (INCA_IP2_SWITCH + 0x00008000) + +/* SE Base Address */ +#define SE_BASE (INCA_IP2_SWITCH + 0x00009000) + +#define PR_CTRL_REG (PR_BASE + 0x0000) +#define MA_LEARN_REG (PR_BASE + 0x0004) +#define DST_LOOKUP_REG (PR_BASE + 0x0008) + +#define COS_SEL_REG (PR_BASE + 0x000c) +#define PRI2_COS_REG (PR_BASE + 0x0010) +#define UNKNOWN_DEST_REG (PR_BASE + 0x0014) + +#define CPU_ACS_CTRL_REG (PR_BASE + 0x0018) +#define CPU_ACS_DATA_REG (PR_BASE + 0x001c) + +#define MA_READ_REG (PR_BASE + 0x0020) +#define TB_CTRL_REG (PR_BASE + 0x0024) +#define RATE_REG (PR_BASE + 0x0028) +#define BURST_REG (PR_BASE + 0x0048) +#define EBURST_REG (PR_BASE + 0x0068) + +#define RULE_SEL_REG (PR_BASE + 0x0088) + +#define GEN_SFT_AGE_STB (PR_BASE + 0x008C) +#define PR_ISR_REG (PR_BASE + 0x0090) +#define PR_IMR_REG (PR_BASE + 0x0094) +#define PR_IPR_REG (PR_BASE + 0x0098) +#define BPDU_REG (PR_BASE + 0x00A4) + +/* Switching Engine Register Description */ +#define QLL_CMD_REG (SE_BASE) +#define QLL_DATA_REG0 (SE_BASE + 0x0004) +#define QLL_DATA_REG1 (SE_BASE + 0x0008) + +#define VLAN_MIBS_CMD_REG (SE_BASE + 0x000c) +#define VLAN_MIBS_DATA_REG (SE_BASE + 0x0010) + +#define SD_CMD_REG (SE_BASE + 0x0014) +#define SD_DATA_REGS0 (SE_BASE + 0x0018) +#define SD_DATA_REGS1 (SE_BASE + 0x001C) +#define SD_DATA_REGS2 (SE_BASE + 0x0020) + +#define VLAN_TBL_CMD_REG (SE_BASE + 0x0024) +#define VLAN_TBL_DATA_REG (SE_BASE + 0x0028) + +#define FD_TBL_CMD_REG (SE_BASE + 0x002c) +#define FD_TBL_DATA_REG (SE_BASE + 0x0030) + +#define SYMM_VLAN_REG (SE_BASE + 0x0038) +#define PORT_AUTH (SE_BASE + 0x0048) +#define CPU_LINK_OK_REG (SE_BASE + 0x0050) +/* #define TRUNK_CTRL_REGS (SE_BASE + 0x0054) */ +#define MIRROR_PORT_REG (SE_BASE + 0x0064) + +#define ST_PT_REG (SE_BASE + 0x0068) +#define JUMBO_ENABLE_REG (SE_BASE + 0x006C) +#define STACK_PORT_REG (SE_BASE + 0x0074) +#define EG_MON_REG (SE_BASE + 0x007C) +#define VR_MIB_REG (SE_BASE + 0x0080) +#define QUEUE_CMD_REGS (SE_BASE + 0x0090) + +#define GLOBAL_RX_WM_REG (SE_BASE + 0x0200) +#define PORT0_RX_WM_REG0 (SE_BASE + 0x0204) +#define PORT1_RX_WM_REG0 (SE_BASE + 0x0208) +#define PORT2_RX_WM_REG0 (SE_BASE + 0x020C) + +#define PORT_RX_WM_REGS (SE_BASE + 0x0200) +#define PORT_TX_WM_REGS (SE_BASE + 0x0300) +#define PORT0_TX_WM_REG0 (SE_BASE + 0x0330) +#define PORT1_TX_WM_REG0 (SE_BASE + 0x0338) +#define PORT2_TX_WM_REG0 (SE_BASE + 0x0340) +#define PORT0_TX_WM_REG1 (SE_BASE + 0x0334) +#define PORT1_TX_WM_REG1 (SE_BASE + 0x033C) +#define PORT2_TX_WM_REG1 (SE_BASE + 0x0344) + + +#define QUEUE_STATUS_REGS (SE_BASE + 0x0400) + +#define SE_INT_STS_REG (SE_BASE + 0x08e0) +#define SE_INT_MSK_REG_RD (SE_BASE + 0x08e4) +#define SE_INT_MSK_REG_WR (SE_BASE + 0x08e8) +#define SE_INT_PRI_REG_RD (SE_BASE + 0x08ec) +#define SE_INT_PRI_REG_WR (SE_BASE + 0x08f0) /* address too be defined*/ + +/***********************************************************************/ +/* Module : Ethernet Switch port related addresses and bits */ +/***********************************************************************/ +#define GPORT0_BASE (KSEG1+0x18006000) +#define GPORT1_BASE (KSEG1+0x18007000) +#define GPORT2_BASE (KSEG1+0x1800C000) + +#define PORTREG_BASE GPORT0_BASE + +#define SWITCH_P0_GMAC_REG (GPORT0_BASE + 0x0004) +#define SWITCH_P0_GMAC_CTRL (GPORT0_BASE + 0x000C) +#define SWITCH_P0_RTX_INT_STATUS (GPORT0_BASE + 0x0010) +#define SWITCH_P0_RTX_INT_MASK (GPORT0_BASE + 0x0014) +#define SWITCH_P0_INT_PRIORITY (GPORT0_BASE + 0x0018) +#define SWITCH_P0_RX_CONF (GPORT0_BASE + 0x0400) +#define SWITCH_P0_OFFSET0_REG (GPORT0_BASE + 0x0404) +#define SWITCH_P0_OFFSET1_REG (GPORT0_BASE + 0x0408) +#define SWITCH_P0_PORT_MASK0_REG (GPORT0_BASE + 0x0420) +#define SWITCH_P0_PORT_MASK1_REG (GPORT0_BASE + 0x0424) +#define SWITCH_P0_PORT_MASK2_REG (GPORT0_BASE + 0x0428) +#define SWITCH_P0_PORT_MASK3_REG (GPORT0_BASE + 0x042C) +#define SWITCH_P0_PORT_RULE0_REG (GPORT0_BASE + 0x0430) +#define SWITCH_P0_PORT_RULE1_REG (GPORT0_BASE + 0x0434) +#define SWITCH_P0_PORT_RULE2_REG (GPORT0_BASE + 0x0438) +#define SWITCH_P0_PORT_RULE3_REG (GPORT0_BASE + 0x043C) +#define SWITCH_P0_PORT_IKEY_SEL (GPORT0_BASE + 0x0440) +#define SWITCH_P0_PORT_RX_VLAN_ID (GPORT0_BASE + 0x0450) +#define SWITCH_P0_TX_CONF (GPORT0_BASE + 0x0800) +#define SWITCH_P0_PORT_TX_VLAN_ID (GPORT0_BASE + 0x0804) +#define SWITCH_P0_PORT_MIB_REG_0 (GPORT0_BASE + 0x0C00) +#define SWITCH_P0_GMAC_MIB_REG_0 (GPORT0_BASE + 0x0C54) + +#define SWITCH_P1_GMAC_REG (GPORT1_BASE + 0x0004) +#define SWITCH_P1_GMAC_CTRL (GPORT1_BASE + 0x000C) +#define SWITCH_P1_RTX_INT_STATUS (GPORT1_BASE + 0x0010) +#define SWITCH_P1_RTX_INT_MASK (GPORT1_BASE + 0x0014) +#define SWITCH_P1_INT_PRIORITY (GPORT1_BASE + 0x0018) +#define SWITCH_P1_RX_CONF (GPORT1_BASE + 0x0400) +#define SWITCH_P1_OFFSET0_REG (GPORT1_BASE + 0x0404) +#define SWITCH_P1_OFFSET1_REG (GPORT1_BASE + 0x0408) +#define SWITCH_P1_PORT_MASK0_REG (GPORT1_BASE + 0x0420) +#define SWITCH_P1_PORT_MASK1_REG (GPORT1_BASE + 0x0424) +#define SWITCH_P1_PORT_MASK2_REG (GPORT1_BASE + 0x0428) +#define SWITCH_P1_PORT_MASK3_REG (GPORT1_BASE + 0x042C) +#define SWITCH_P1_PORT_RULE0_REG (GPORT1_BASE + 0x0430) +#define SWITCH_P1_PORT_RULE1_REG (GPORT1_BASE + 0x0434) +#define SWITCH_P1_PORT_RULE2_REG (GPORT1_BASE + 0x0438) +#define SWITCH_P1_PORT_RULE3_REG (GPORT1_BASE + 0x043C) +#define SWITCH_P1_PORT_IKEY_SEL (GPORT1_BASE + 0x0440) +#define SWITCH_P1_PORT_RX_VLAN_ID (GPORT1_BASE + 0x0450) +#define SWITCH_P1_TX_CONF (GPORT1_BASE + 0x0800) +#define SWITCH_P1_PORT_TX_VLAN_ID (GPORT1_BASE + 0x0804) +#define SWITCH_P1_PORT_MIB_REG_0 (GPORT1_BASE + 0x0C00) +#define SWITCH_P1_GMAC_MIB_REG_0 (GPORT1_BASE + 0x0C54) + +#define SWITCH_P2_GMAC_REG (GPORT2_BASE + 0x0004) +#define SWITCH_P2_GMAC_CTRL (GPORT2_BASE + 0x000C) +#define SWITCH_P2_RTX_INT_STATUS (GPORT2_BASE + 0x0010) +#define SWITCH_P2_RTX_INT_MASK (GPORT2_BASE + 0x0014) +#define SWITCH_P2_INT_PRIORITY (GPORT2_BASE + 0x0018) +#define SWITCH_P2_MDIO_ID_1 (GPORT2_BASE + 0x00A8) +#define SWITCH_P2_PAUSE_CTL_1 (GPORT2_BASE + 0x00B0) +#define SWITCH_P2_MDIO_MOD_SEL (GPORT2_BASE + 0x00B4) +#define SWITCH_P2_MDIO_ACC_0 (GPORT2_BASE + 0x00B8) +#define SWITCH_P2_RX_CONF (GPORT2_BASE + 0x0400) +#define SWITCH_P2_OFFSET0_REG (GPORT2_BASE + 0x0404) +#define SWITCH_P2_OFFSET1_REG (GPORT2_BASE + 0x0408) +#define SWITCH_P2_PORT_MASK0_REG (GPORT2_BASE + 0x0420) +#define SWITCH_P2_PORT_MASK1_REG (GPORT2_BASE + 0x0424) +#define SWITCH_P2_PORT_MASK2_REG (GPORT2_BASE + 0x0428) +#define SWITCH_P2_PORT_MASK3_REG (GPORT2_BASE + 0x042C) +#define SWITCH_P2_PORT_RULE0_REG (GPORT2_BASE + 0x0430) +#define SWITCH_P2_PORT_RULE1_REG (GPORT2_BASE + 0x0434) +#define SWITCH_P2_PORT_RULE2_REG (GPORT2_BASE + 0x0438) +#define SWITCH_P2_PORT_RULE3_REG (GPORT2_BASE + 0x043C) +#define SWITCH_P2_PORT_IKEY_SEL (GPORT2_BASE + 0x0440) +#define SWITCH_P2_PORT_RX_VLAN_ID (GPORT2_BASE + 0x0450) +#define SWITCH_P2_TX_CONF (GPORT2_BASE + 0x0800) +#define SWITCH_P2_PORT_TX_VLAN_ID (GPORT2_BASE + 0x0804) +#define SWITCH_P2_PORT_MIB_REG_0 (GPORT2_BASE + 0x0C00) +#define SWITCH_P2_GMAC_MIB_REG_0 (GPORT2_BASE + 0x0C54) + +#define MDIO_MOD_SEL SWITCH_P2_MDIO_MOD_SEL +#define SWITCH_MDIO_ACC SWITCH_P2_MDIO_ACC_0 +#define SWITCH_MDIO_ID SWITCH_P2_MDIO_ID_1 +/* #define TX_CONFIG_REG SWITCH_P0_TX_CONF */ + +#define SWITCH_PMAC_HD_CTL (GPORT2_BASE + 0x0070) +#define SWITCH_PMAC_SA1 (GPORT2_BASE + 0x0074) +#define SWITCH_PMAC_SA2 (GPORT2_BASE + 0x0078) +#define SWITCH_PMAC_DA1 (GPORT2_BASE + 0x007C) +#define SWITCH_PMAC_DA2 (GPORT2_BASE + 0x0080) +#define SWITCH_PMAC_VLAN (GPORT2_BASE + 0x0084) +#define SWITCH_PMAC_TX_IPG (GPORT2_BASE + 0x0088) +#define SWITCH_PMAC_RX_IPG (GPORT2_BASE + 0x008C) + diff --git a/package/uboot-ifxmips/files/include/asm-mips/pinstrap.h b/package/uboot-ifxmips/files/include/asm-mips/pinstrap.h new file mode 100644 index 0000000000..1a446fa916 --- /dev/null +++ b/package/uboot-ifxmips/files/include/asm-mips/pinstrap.h @@ -0,0 +1,12 @@ +#define FLASH_STRAP 0x1 +#define MII_0_STRAP 0x2 +#define MII_1_STRAP 0x3 +#define ASC_STRAP 0x4 +#define SFLASH_STRAP 0x5 +#define RESERVE_STRAP 0x6 +#define PRODUCT_TEST_STRAP 0x7 +#define PIN_STRAP_MASK 0x001C0000 +#define PIN_STRAP_SHIFT 18 +#define PIN_STRAP 0xB0100914 +#define SDRAM_WIDTH_MASK 0x400000 +#define SDRAM_WIDTH_SHIFT 22 diff --git a/package/uboot-ifxmips/files/include/asm-mips/romconfig.h b/package/uboot-ifxmips/files/include/asm-mips/romconfig.h new file mode 100644 index 0000000000..8951b3aaa1 --- /dev/null +++ b/package/uboot-ifxmips/files/include/asm-mips/romconfig.h @@ -0,0 +1,66 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * This file contains the configuration parameters for the DANUBE board. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + + +#define EXCEPTION_BASE 0x200 + +/***************************************************************************** + * DANUBE + *****************************************************************************/ +/* lock cache for C program stack */ +/* points to ROM */ +/* stack size is 16K */ +#define LOCK_DCACHE_ADDR 0x9FC00000 +#define LOCK_DCACHE_SIZE 0x1000 +#define CFG_EBU_BOOTWORD 0x688c688c + +#define CFG_HZ (danube_get_cpuclk() / 2) + + +/* + * Memory layout + */ +//#define CFG_SDRAM_BASE 0x80080000 +#define CFG_CACHE_LOCK_SIZE LOCK_DCACHE_SIZE +#define CFG_INIT_SP_OFFSET CFG_CACHE_LOCK_SIZE + +/* + * Cache settings + */ +#define CFG_CACHE_SIZE 16384 +#define CFG_CACHE_LINES 32 +#define CFG_CACHE_WAYS 4 +#define CFG_CACHE_SETS 128 + +#define CFG_ICACHE_SIZE CFG_CACHE_SIZE +#define CFG_DCACHE_SIZE CFG_CACHE_SIZE +#define CFG_CACHELINE_SIZE CFG_CACHE_LINES + +#endif /* __CONFIG_H */ diff --git a/package/uboot-ifxmips/files/include/boot.h b/package/uboot-ifxmips/files/include/boot.h new file mode 100644 index 0000000000..8f70ebb43d --- /dev/null +++ b/package/uboot-ifxmips/files/include/boot.h @@ -0,0 +1,86 @@ +#ifndef _BOOT_H +#define _BOOT_H + +/* All this should be defined somewhere in danube.h later... */ + +#define MPS_SRAM_BASE_ADDRESS 0xBF200000 +#define MPS_SRAM_BOOT_OFFSET 0x1C0 + +/* Offset for CPU1 (both CPUs have same register set) */ +#define BOOT_BASE_ADDRESS (MPS_SRAM_BASE_ADDRESS + MPS_SRAM_BOOT_OFFSET) +#define BOOT_CPU_OFFSET 0x20 + + +#ifdef __ASSEMBLY__ +#define BOOT_RVEC (BOOT_BASE_ADDRESS + 0x00) +#define BOOT_NVEC (BOOT_BASE_ADDRESS + 0x04) +#define BOOT_EVEC (BOOT_BASE_ADDRESS + 0x08) +#define BOOT_CP0_CAUSE (BOOT_BASE_ADDRESS + 0x0C) +#define BOOT_CP0_EPC (BOOT_BASE_ADDRESS + 0x10) +#define BOOT_CP0_EEPC (BOOT_BASE_ADDRESS + 0x14) +#define BOOT_SIZE (BOOT_BASE_ADDRESS + 0x18) /* for CPU1 */ +#define BOOT_RCU_SR (BOOT_BASE_ADDRESS + 0x18) /* for CPU0 */ +#define BOOT_CFG_STAT (BOOT_BASE_ADDRESS + 0x1C) +#else +#define BOOT_RVEC(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x00) +#define BOOT_NVEC(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x04) +#define BOOT_EVEC(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x08) +#define BOOT_CP0_STATUS(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x0C) +#define BOOT_CP0_EPC(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x10) +#define BOOT_CP0_EEPC(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x14) +#define BOOT_SIZE(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x18) /* for CPU1 */ +#define BOOT_RCU_SR(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x18) /* for CPU0 */ +#define BOOT_CFG_STAT(cpu) (volatile u32*)(BOOT_BASE_ADDRESS + (cpu * BOOT_CPU_OFFSET) + 0x1C) +#endif + +#define BOOT_CFG_NOR 0x01 +#define BOOT_CFG_MII 0x02 +#define BOOT_CFG_PCI 0x03 +#define BOOT_CFG_ASC 0x04 +#define BOOT_CFG_SFLASH 0x05 +#define BOOT_CFG_NAND 0x06 +#define BOOT_CFG_RMII 0x07 +#define BOOT_CFG_TEST 0x00 + +#define BOOT_NUM_RETRY 3 + +#define BOOT_STAT_MASK_ALL 0x0000FFFF +#define BOOT_STAT_MASK_STAT 0x0000F000 +#define BOOT_STAT_MASK_BERR 0x00000F00 +#define BOOT_STAT_MASK_BSTRAP 0x000000F0 +#define BOOT_STAT_MASK_BMODULE 0x0000000F + +#define BOOT_STAT_INIT 0x00000000 +#define BOOT_STAT_BSTRAP 0x00001000 +#define BOOT_STAT_RETRY 0x00002000 +#define BOOT_STAT_START 0x00003000 +#define BOOT_STAT_HALT 0x0000F000 + +#define BOOT_ERR_NO_RVEC 0x00000100 +#define BOOT_ERR_NO_NVEC 0x00000200 +#define BOOT_ERR_NO_EVEC 0x00000300 +#define BOOT_ERR_BSTRAP 0x00000400 +#define BOOT_ERR_EXC 0x00000800 + +#ifndef __ASSEMBLY__ +void boot_set_status( u32 status, u32 mask); +void boot_set_config( u32 config); +void boot_set_rvec( u32 vector); +void boot_set_size( u32 size); +void boot_sdbg( u8* string, u32 value); +void boot_error( u32 berr); +int boot_from_ebu(void); +void _boot_rvec(void); +typedef struct +{ + u32 cpu; /** CPU number */ + u32 config; /** Boot configuration */ + u32 endian; /** CPU endianess */ + u32 debug; /** Debug mode */ + u32 (*exit)(void); /** application vector */ +} boot_data; + +extern boot_data bootrom; +#endif + +#endif /* #ifdef _BOOT_H */ diff --git a/package/uboot-ifxmips/files/include/configs/danube.h b/package/uboot-ifxmips/files/include/configs/danube.h new file mode 100644 index 0000000000..12cca11082 --- /dev/null +++ b/package/uboot-ifxmips/files/include/configs/danube.h @@ -0,0 +1,262 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * This file contains the configuration parameters for the danube board. + */ + +#ifndef __CONFIG_H +#define __CONFIG_H + +#include + +#define USE_REFERENCE_BOARD +//#define USE_EVALUATION_BOARD + +#define DANUBE_BOOT_FROM_EBU +#define DANUBE_USE_DDR_RAM + +#ifdef DANUBE_USE_DDR_RAM +//#define DANUBE_DDR_RAM_111M +#define DANUBE_DDR_RAM_166M +//#define PROMOSDDR400 +//#define DDR_SAMSUNG_166M +//#define DDR_PSC_166M +//#define DANUBE_DDR_RAM_133M +#define DANUBE_DDR_RAM_SIZE 32 /* 32M DDR-DRAM for reference board */ +#endif +#define CLK_OUT2_25MHZ +#define CONFIG_MIPS32 1 /* MIPS 4Kc CPU core */ +#define CONFIG_DANUBE 1 /* on a danube Board */ +#define RAM_SIZE 0x2000000 /*32M ram*/ + +#define CPU_CLOCK_RATE 235000000 /* 235 MHz clock for the MIPS core */ + +#define INFINEON_EBU_BOOTCFG 0x688C688C /* CMULT = 8 for 150 MHz */ + +#define CONFIG_BOOTDELAY 3 /* autoboot after 3 seconds */ + +#define CONFIG_BAUDRATE 115200 + +#define DEBUG_PARSER 2 + +/* valid baudrates */ +#define CFG_BAUDRATE_TABLE { 300, 9600, 19200, 38400, 57600, 115200 } + +#ifndef CFG_HEAD_CODE +#define CONFIG_TIMESTAMP /* Print image info with timestamp */ +#endif + +#define CONFIG_PREBOOT "echo;" \ + "echo Type \"run flash_nfs\" to mount root filesystem over NFS;" \ + "echo" + +#undef CONFIG_BOOTARGS +/* by MarsLin 2005/05/10, to support different hardware configuations */ +//#define CONFIG_EXTRA_ENV_SETTINGS +#define CONFIG_EXTRA_ENV_SETTINGS \ + "ethaddr=11:22:33:44:55:66\0" \ + "serverip=192.168.45.100\0" \ + "ipaddr=192.168.45.108\0" \ + "update_uboot=tftp 0x80500000 u-boot.ifx;era 1:0-10; cp.b 0x80500000 0xb0000000 0x10000\0" \ + "update_openwrt=tftp 0x80500000 openwrt-ifxmips-squashfs.image; era 1:10-120; cp.b 0x80500000 0xb0030000 0x300000\0" \ + "bootargs=console=ttyS1,115200 rootfstype=squashfs,jffs2 init=/etc/preinit\0" + +#define CONFIG_BOOTCOMMAND "bootm 0xb0030000" + +#define CONFIG_COMMANDS_YES (CONFIG_CMD_DFL | \ + CFG_CMD_ASKENV | \ + CFG_CMD_DHRYSTONE | \ + CFG_CMD_NET ) + +#define CONFIG_COMMANDS_NO (CFG_CMD_NFS | \ + CFG_CMD_FPGA | \ + CFG_CMD_IMLS | \ + CFG_CMD_ITEST | \ + CFG_CMD_XING | \ + CFG_CMD_IMI | \ + CFG_CMD_BMP | \ + CFG_CMD_BOOTD | \ + CFG_CMD_CONSOLE | \ + CFG_CMD_LOADS | \ + CFG_CMD_LOADB ) + +#define CONFIG_COMMANDS (CONFIG_COMMANDS_YES & ~CONFIG_COMMANDS_NO) + +#if 0 + CFG_CMD_DHCP + CFG_CMD_ELF + CFG_CMD_NAND +#endif + +#include + +/* + * Miscellaneous configurable options + */ +#define CFG_LONGHELP /* undef to save memory */ +#define CFG_PROMPT "DANUBE # " /* Monitor Command Prompt */ +#define CFG_CBSIZE 256 /* Console I/O Buffer Size */ +#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */ +#define CFG_MAXARGS 16 /* max number of command args*/ + +#define CFG_MALLOC_LEN 128*1024 + +#define CFG_BOOTPARAMS_LEN 128*1024 + +#define CFG_HZ (CPU_CLOCK_RATE / 2) + +#define CFG_LOAD_ADDR 0x80100000 /* default load address */ + +#define CFG_MEMTEST_START 0x80100000 +#define CFG_MEMTEST_END 0x80400000 + +/*----------------------------------------------------------------------- + * FLASH and environment organization + */ +#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */ +#define CFG_MAX_FLASH_SECT (135) /* max number of sectors on one chip */ + +#define PHYS_FLASH_1 0xB0000000 /* Flash Bank #1 */ +#define PHYS_FLASH_2 0xB4000000 /* Flash Bank #2 */ + +#define BOOTSTRAP_TEXT_BASE 0xb0000000 + +/* The following #defines are needed to get flash environment right */ +#define CFG_MONITOR_BASE UBOOT_RAM_TEXT_BASE /* board/danube/config.mk. = 0xA0800000 */ +#define BOOTSTRAP_CFG_MONITOR_BASE BOOTSTRAP_TEXT_BASE /* board/danube/config.mk. = 0xA0800000 */ +#define CFG_MONITOR_LEN (256 << 10) + +#define CFG_INIT_SP_OFFSET 0x400000 + +#define CFG_FLASH_BASE PHYS_FLASH_1 + +/* timeout values are in ticks */ +#define CFG_FLASH_ERASE_TOUT (20 * CFG_HZ) /* Timeout for Flash Erase */ +#define CFG_FLASH_WRITE_TOUT (20 * CFG_HZ) /* Timeout for Flash Write */ + +#define CFG_ENV_IS_IN_FLASH 1 +//#define CFG_ENV_IS_NOWHERE 1 +//#define CFG_ENV_IS_IN_NVRAM 1 +/* Address and size of Primary Environment Sector */ +#define CFG_ENV_ADDR IFX_CFG_FLASH_UBOOT_CFG_START_ADDR +#define CFG_ENV_SIZE IFX_CFG_FLASH_UBOOT_CFG_SIZE + +#define CONFIG_FLASH_16BIT + +#define CONFIG_NR_DRAM_BANKS 1 + +#define CONFIG_DANUBE_SWITCH +#define CONFIG_NET_MULTI +#define CONFIG_ENV_OVERWRITE + +#define EXCEPTION_BASE 0x200 + +/** + *\brief definition for nand + * + */ +#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */ +#define NAND_ChipID_UNKNOWN 0x00 +#define SECTORSIZE 512 +#define NAND_MAX_FLOORS 1 +#define NAND_MAX_CHIPS 1 + + +#define ADDR_COLUMN 1 +#define ADDR_PAGE 2 +#define ADDR_COLUMN_PAGE 3 + + +#define AT91_SMART_MEDIA_ALE (1 << 22) /* our ALE is AD22 */ +#define AT91_SMART_MEDIA_CLE (1 << 21) /* our CLE is AD21 */ + +#define NAND_DISABLE_CE(nand) +#define NAND_ENABLE_CE(nand) +#define NAND_WAIT_READY(nand) +#define WRITE_NAND_COMMAND(d, adr) +#define WRITE_NAND_ADDRESS(d, adr) +#define WRITE_NAND(d, adr) +#define READ_NAND(adr) +/* the following are NOP's in our implementation */ +#define NAND_CTL_CLRALE(nandptr) +#define NAND_CTL_SETALE(nandptr) +#define NAND_CTL_CLRCLE(nandptr) +#define NAND_CTL_SETCLE(nandptr) + + + +#define NAND_BASE_ADDRESS 0xB4000000 + +#define NAND_WRITE(addr, val) *((u8*)(NAND_BASE_ADDRESS | (addr))) = val;while((*EBU_NAND_WAIT & 0x08) == 0); +#define NAND_READ(addr, val) val = *((u8*)(NAND_BASE_ADDRESS | (addr))) +#define NAND_CE_SET +#define NAND_CE_CLEAR +#define NAND_READY ( ((*EBU_NAND_WAIT)&0x07) == 7) +#define NAND_READY_CLEAR *EBU_NAND_WAIT = 0; +#define WRITE_CMD 0x18 +#define WRITE_ADDR 0x14 +#define WRITE_LADDR 0x10 +#define WRITE_DATA 0x10 +#define READ_DATA 0x10 +#define READ_LDATA 0x00 +#define ACCESS_WAIT +#define IFX_ATC_NAND 0xc176 +#define IFX_BTC_NAND 0xc166 +#define ST_512WB2_NAND 0x2076 + +#define NAND_OK 0x00000000 /* Bootstrap succesful, start address in BOOT_RVEC */ +#define NAND_ERR 0x80000000 +#define NAND_ACC_TIMEOUT (NAND_ERR | 0x00000001) +#define NAND_ACC_ERR (NAND_ERR | 0x00000002) + + +/***************************************************************************** + * DANUBE + *****************************************************************************/ +/* lock cache for C program stack */ +/* points to ROM */ +/* stack size is 16K */ +#define LOCK_DCACHE_ADDR 0x9FC00000 +#define LOCK_DCACHE_SIZE 0x1000 + +/* + * Memory layout + */ +#define CFG_SDRAM_BASE 0x80000000 +#define CFG_SDRAM_BASE_UNCACHE 0xA0000000 +#define CFG_CACHE_LOCK_SIZE LOCK_DCACHE_SIZE + +/* + * Cache settings + */ +#define CFG_CACHE_SIZE 16384 +#define CFG_CACHE_LINES 32 +#define CFG_CACHE_WAYS 4 +#define CFG_CACHE_SETS 128 + +#define CFG_ICACHE_SIZE CFG_CACHE_SIZE +#define CFG_DCACHE_SIZE CFG_CACHE_SIZE +#define CFG_CACHELINE_SIZE CFG_CACHE_LINES + +#endif /* __CONFIG_H */ diff --git a/package/uboot-ifxmips/files/include/configs/ifx_cfg.h b/package/uboot-ifxmips/files/include/configs/ifx_cfg.h new file mode 100644 index 0000000000..101f2ac0f9 --- /dev/null +++ b/package/uboot-ifxmips/files/include/configs/ifx_cfg.h @@ -0,0 +1,249 @@ +/* ============================================================================ + * Copyright (C) 2003[- 2004] ? Infineon Technologies AG. + * + * All rights reserved. + * ============================================================================ + * + * ============================================================================ + * + * This document contains proprietary information belonging to Infineon + * Technologies AG. Passing on and copying of this document, and communication + * of its contents is not permitted without prior written authorisation. + * + * ============================================================================ + * + * File Name: ifx_cfg.h + * Author : Mars Lin (mars.lin@infineon.com) + * Date: + * + * =========================================================================== + * + * Project: + * Block: + * + * =========================================================================== + * Contents: This file contains the data structures and definitions used + * by the core iptables and the sip alg modules. + * =========================================================================== + * References: + */ + +/* + * This file contains the configuration parameters for the IFX board. + */ +#ifndef _DANUBE_CFG_H_ +#define _DANUBE_CFG_H_ + +/*----------------------------------------------------------------------- + * U-Boot/Kernel configurations + */ +#define IFX_CFG_UBOOT_DEFAULT_CFG_IPADDR "172.20.80.100" +#define IFX_CFG_UBOOT_DEFAULT_CFG_SERVERIP "172.20.80.2" +#define IFX_CFG_UBOOT_DEFAULT_CFG_ETHADDR "00:E0:92:00:01:40" +#define IFX_CFG_UBOOT_DEFAULT_CFG_NETDEV "eth1" +#define IFX_CFG_UBOOT_DEFAULT_CFG_BAUDRATE "115200" +#define IFX_CFG_UBOOT_LOAD_ADDRESS "0x80800000" + +/* End of U-Boot/Kernel configurations + *----------------------------------------------------------------------- + */ + +/*----------------------------------------------------------------------- + * Board specific configurations + */ +#ifdef IFX_CONFIG_MEMORY_SIZE + #define IFX_CFG_MEM_SIZE 31 +#else + #error "ERROR!! Define memory size first!" +#endif + +//2MB flash partition +#if (IFX_CONFIG_FLASH_SIZE == 2) +#define IFX_CFG_FLASH_PARTITIONS_INFO \ + "part0_begin=0xB0000000\0" \ + "part1_begin=0xB0010000\0" \ + "part2_begin=0xB0050000\0" \ + "total_part=3\0" + +#define IFX_CFG_FLASH_DATA_BLOCKS_INFO \ + "data_block0=" IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "\0" \ + "data_block1=" IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "\0" \ + "data_block2=" IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "\0" \ + "data_block3=" IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "\0" \ + "data_block4=" IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "\0" \ + "data_block5=" IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "\0" \ + "data_block6=" IFX_CFG_FLASH_FIRMWARE_DIAG_BLOCK_NAME "\0" \ + "data_block7=" IFX_CFG_FLASH_CALIBRATION_CFG_BLOCK_NAME "\0" \ + "total_db=8\0" + + #define IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "uboot" + #define IFX_CFG_FLASH_UBOOT_IMAGE_START_ADDR 0xB0000000 + #define IFX_CFG_FLASH_UBOOT_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_UBOOT_IMAGE_MTDBLOCK_NAME "/dev/mtdblock0" + + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "firmware" + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_START_ADDR 0xB0010000 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_MTDBLOCK_NAME "/dev/mtdblock1" + + #define IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "rootfs" + #define IFX_CFG_FLASH_ROOTFS_IMAGE_START_ADDR 0xB0050000 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_MTDBLOCK_NAME "/dev/mtdblock2" + + #define IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "kernel" + #define IFX_CFG_FLASH_KERNEL_IMAGE_START_ADDR 0xB01FCFFF + #define IFX_CFG_FLASH_KERNEL_IMAGE_SIZE 0 + + #define IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "sysconfig" + #define IFX_CFG_FLASH_SYSTEM_CFG_START_ADDR 0xB01FD000 + #define IFX_CFG_FLASH_SYSTEM_CFG_SIZE 0 + #define IFX_CFG_FLASH_SYSTEM_CFG_END_ADDR 0xB01FEFFF + + #define IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "ubootconfig" + #define IFX_CFG_FLASH_UBOOT_CFG_START_ADDR 0xB01FF000 + #define IFX_CFG_FLASH_UBOOT_CFG_SIZE 0x0C00 + #define IFX_CFG_FLASH_UBOOT_CFG_END_ADDR 0xB01FFBFF + + #define IFX_CFG_FLASH_FIRMWARE_DIAG_BLOCK_NAME "fwdiag" + #define IFX_CFG_FLASH_FIRMWARE_DIAG_START_ADDR 0xB31FFC00 + #define IFX_CFG_FLASH_FIRMWARE_DIAG_SIZE 0x0200 + #define IFX_CFG_FLASH_FIRMWARE_DIAG_END_ADDR 0xB01FFDFF + + #define IFX_CFG_FLASH_CALIBRATION_CFG_BLOCK_NAME "calibration" + #define IFX_CFG_FLASH_CALIBRATION_CFG_START_ADDR 0xB01FFE00 + #define IFX_CFG_FLASH_CALIBRATION_CFG_SIZE 0x0200 + #define IFX_CFG_FLASH_CALIBRATION_CFG_END_ADDR 0xB01FFFFF + + #define IFX_CFG_FLASH_END_ADDR 0xB01FFFFF + +//4MB flash partition +#elif (IFX_CONFIG_FLASH_SIZE == 4) +#define IFX_CFG_FLASH_PARTITIONS_INFO \ + "part0_begin=0xB0000000\0" \ + "part1_begin=0xB0020000\0" \ + "part2_begin=0xB0060000\0" \ + "total_part=3\0" + +#define IFX_CFG_FLASH_DATA_BLOCKS_INFO \ + "data_block0=" IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "\0" \ + "data_block1=" IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "\0" \ + "data_block2=" IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "\0" \ + "data_block3=" IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "\0" \ + "data_block4=" IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "\0" \ + "data_block5=" IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "\0" \ + "data_block6=" IFX_CFG_FLASH_VOIP_CFG_BLOCK_NAME "\0" \ + "data_block7=" IFX_CFG_FLASH_FIRMWARE_DIAG_BLOCK_NAME "\0" \ + "data_block8=" IFX_CFG_FLASH_CALIBRATION_CFG_BLOCK_NAME "\0" \ + "total_db=9\0" + + #define IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "uboot" + #define IFX_CFG_FLASH_UBOOT_IMAGE_START_ADDR 0xB0000000 + #define IFX_CFG_FLASH_UBOOT_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_UBOOT_IMAGE_MTDBLOCK_NAME "/dev/mtdblock0" + + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "firmware" + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_START_ADDR 0xB0020000 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_MTDBLOCK_NAME "/dev/mtdblock1" + + #define IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "rootfs" + #define IFX_CFG_FLASH_ROOTFS_IMAGE_START_ADDR 0xB0060000 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_SIZE 0 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_MTDBLOCK_NAME "/dev/mtdblock2" + + #define IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "kernel" + #define IFX_CFG_FLASH_KERNEL_IMAGE_START_ADDR 0xB03F4FFF + #define IFX_CFG_FLASH_KERNEL_IMAGE_SIZE 0 + + #define IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "sysconfig" + #define IFX_CFG_FLASH_SYSTEM_CFG_START_ADDR 0xB03F5000 + #define IFX_CFG_FLASH_SYSTEM_CFG_SIZE 0x2000 + #define IFX_CFG_FLASH_SYSTEM_CFG_END_ADDR 0xB03F6FFF + + #define IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "ubootconfig" + #define IFX_CFG_FLASH_UBOOT_CFG_START_ADDR 0xB03F7000 + #define IFX_CFG_FLASH_UBOOT_CFG_SIZE 0x0C00 + #define IFX_CFG_FLASH_UBOOT_CFG_END_ADDR 0xB03F7BFF + + #define IFX_CFG_FLASH_VOIP_CFG_BLOCK_NAME "voip" + #define IFX_CFG_FLASH_VOIP_CFG_START_ADDR 0xB03F7C00 + #define IFX_CFG_FLASH_VOIP_CFG_SIZE 0x8000 + #define IFX_CFG_FLASH_VOIP_CFG_END_ADDR 0xB03FFBFF + + #define IFX_CFG_FLASH_FIRMWARE_DIAG_BLOCK_NAME "fwdiag" + #define IFX_CFG_FLASH_FIRMWARE_DIAG_START_ADDR 0xB03FFC00 + #define IFX_CFG_FLASH_FIRMWARE_DIAG_SIZE 0x0200 + #define IFX_CFG_FLASH_FIRMWARE_DIAG_END_ADDR 0xB03FFDFF + + #define IFX_CFG_FLASH_CALIBRATION_CFG_BLOCK_NAME "calibration" + #define IFX_CFG_FLASH_CALIBRATION_CFG_START_ADDR 0xB03FFE00 + #define IFX_CFG_FLASH_CALIBRATION_CFG_SIZE 0x0200 + #define IFX_CFG_FLASH_CALIBRATION_CFG_END_ADDR 0xB03FFFFF + + #define IFX_CFG_FLASH_END_ADDR 0xB03FFFFF +//8MB flash definition +#elif (IFX_CONFIG_FLASH_SIZE == 8) +#define IFX_CFG_FLASH_PARTITIONS_INFO \ + "part0_begin=0xB0000000\0" \ + "part1_begin=0xB0080000\0" \ + "part2_begin=0xB0280000\0" \ + "part3_begin=0xB0790000\0" \ + "part4_begin=0xB07A0000\0" \ + "part5_begin=0xB07E0000\0" \ + "total_part=6\0" + +#define IFX_CFG_FLASH_DATA_BLOCKS_INFO \ + "data_block0=" IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "\0" \ + "data_block1=" IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "\0" \ + "data_block2=" IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "\0" \ + "data_block3=" IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "\0" \ + "data_block4=" IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "\0" \ + "data_block5=" IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "\0" \ + "total_db=6\0" + + #define IFX_CFG_FLASH_UBOOT_IMAGE_BLOCK_NAME "uboot" + #define IFX_CFG_FLASH_UBOOT_IMAGE_START_ADDR 0xB0000000 + #define IFX_CFG_FLASH_UBOOT_IMAGE_END_ADDR 0xB007FFFF + #define IFX_CFG_FLASH_UBOOT_IMAGE_SIZE 0x00080000 + #define IFX_CFG_FLASH_UBOOT_IMAGE_MTDBLOCK_NAME "/dev/mtdblock0" + + #define IFX_CFG_FLASH_KERNEL_IMAGE_BLOCK_NAME "kernel" + #define IFX_CFG_FLASH_KERNEL_IMAGE_START_ADDR 0xB0080000 + #define IFX_CFG_FLASH_KERNEL_IMAGE_SIZE 0x200000 + #define IFX_CFG_FLASH_KERNEL_IMAGE_END_ADDR 0xB017FFFF + #define IFX_CFG_FLASH_KERNEL_IMAGE_MTDBLOCK_NAME "/dev/mtdblock1" + + #define IFX_CFG_FLASH_ROOTFS_IMAGE_BLOCK_NAME "rootfs" + #define IFX_CFG_FLASH_ROOTFS_IMAGE_START_ADDR 0xB0280000 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_SIZE 0x00510000 + #define IFX_CFG_FLASH_ROOTFS_IMAGE_END_ADDR 0xB078FFFF + #define IFX_CFG_FLASH_ROOTFS_IMAGE_MTDBLOCK_NAME "/dev/mtdblock2" + + #define IFX_CFG_FLASH_SYSTEM_CFG_BLOCK_NAME "sysconfig" + #define IFX_CFG_FLASH_SYSTEM_CFG_START_ADDR 0xB0790000 + #define IFX_CFG_FLASH_SYSTEM_CFG_SIZE 0x10000 + #define IFX_CFG_FLASH_SYSTEM_CFG_END_ADDR 0xB079FFFF + #define IFX_CFG_FLASH_SYSTEM_CFG_MTDBLOCK_NAME "/dev/mtdblock3" + + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_BLOCK_NAME "firmware" + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_START_ADDR 0xB07A0000 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_SIZE 0x40000 + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_END_ADDR 0xB07DFFFF + #define IFX_CFG_FLASH_FIRMWARE_IMAGE_MTDBLOCK_NAME "/dev/mtdblock4" + + #define IFX_CFG_FLASH_UBOOT_CFG_BLOCK_NAME "ubootconfig" + #define IFX_CFG_FLASH_UBOOT_CFG_START_ADDR 0xB0020000 + #define IFX_CFG_FLASH_UBOOT_CFG_END_ADDR 0xB002FFFF + #define IFX_CFG_FLASH_UBOOT_CFG_SIZE 0x10000 + #define IFX_CFG_FLASH_UBOOT_CFG_MTDBLOCK_NAME "/dev/mtdblock5" + + #define IFX_CFG_FLASH_END_ADDR 0xB07FFFFF +#else + #error "ERROR!! Define flash size first!" +#endif +/* End of Board specific configurations + *----------------------------------------------------------------------- + */ + +#endif diff --git a/package/uboot-ifxmips/files/include/configs/ifx_extra_env.h b/package/uboot-ifxmips/files/include/configs/ifx_extra_env.h new file mode 100644 index 0000000000..a03d836218 --- /dev/null +++ b/package/uboot-ifxmips/files/include/configs/ifx_extra_env.h @@ -0,0 +1,94 @@ +/* ============================================================================ + * Copyright (C) 2003[- 2004] ? Infineon Technologies AG. + * + * All rights reserved. + * ============================================================================ + * + * ============================================================================ + * + * This document contains proprietary information belonging to Infineon + * Technologies AG. Passing on and copying of this document, and communication + * of its contents is not permitted without prior written authorisation. + * + * ============================================================================ + * + * File Name: ifx_extra_env.h + * Author : Mars Lin (mars.lin@infineon.com) + * Date: + * + * =========================================================================== + * + * Project: + * Block: + * + * =========================================================================== + * Contents: This file contains the data structures and definitions used + * by the core iptables and the sip alg modules. + * =========================================================================== + * References: + */ + "mem=" MK_STR(IFX_CONFIG_MEMORY_SIZE) "M\0" + "ipaddr=" IFX_CFG_UBOOT_DEFAULT_CFG_IPADDR "\0" + "serverip=" IFX_CFG_UBOOT_DEFAULT_CFG_SERVERIP "\0" + "ethaddr=" IFX_CFG_UBOOT_DEFAULT_CFG_ETHADDR "\0" + "netdev=eth0\0" + "baudrate=" IFX_CFG_UBOOT_DEFAULT_CFG_BAUDRATE "\0" + "loadaddr=" IFX_CFG_UBOOT_LOAD_ADDRESS "\0" + "rootpath=/tftpboot/nfsrootfs\0" + "nfsargs=setenv bootargs root=/dev/nfs rw nfsroot=$(serverip):$(rootpath)\0" + "ramargs=setenv bootargs root=/dev/ram rw\0" + "addip=setenv bootargs $(bootargs) ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname):$(netdev):on\0" + "addmisc=setenv bootargs $(bootargs) console=ttyS1,$(baudrate) ethaddr=$(ethaddr) mem=$(mem) panic=1\0" + "flash_nfs=run nfsargs addip addmisc;bootm $(kernel_addr)\0" + "ramdisk_addr=B0100000\0" + "flash_self=run ramargs addip addmisc;bootm $(kernel_addr) $(ramdisk_addr)\0" + "bootfile=uImage\0" + "net_nfs=tftp $(loadaddr) $(bootfile);run nfsargs addip addmisc;bootm\0" + "net_flash=tftp $(loadaddr) $(bootfile); run flashargs addip addmisc; bootm\0" + "u-boot=u-boot.ifx\0" + "jffs2fs=jffs2.img\0" + "rootfs=rootfs.img\0" + "firmware=firmware.img\0" + "load=tftp $(loadaddr) $(u-boot)\0" + "update=protect off 1:0-2;era 1:0-2;cp.b $(loadaddr) B0000000 $(filesize)\0" + "flashargs=setenv bootargs root=/dev/mtdblock2 ro rootfstype=squashfs\0" + "mtdargs=setenv bootargs root=/dev/mtdblock2 rw rootfstype=jffs2\0" + "flash_flash=run flashargs addip addmisc; bootm $(f_kernel_addr)\0" + "net_mtd=tftp $(loadaddr) $(bootfile); run mtdargs addip addmisc; bootm\0" + "flash_mtd=run mtdargs addip addmisc; bootm $(f_kernel_addr)\0" + "update_uboot=tftpboot $(loadaddr) $(u-boot);upgrade uboot $(loadaddr) $(filesize) 0\0" + "update_kernel=tftpboot $(loadaddr) $(bootfile);upgrade kernel $(loadaddr) $(filesize) 0\0" + "update_rootfs=tftpboot $(loadaddr) $(rootfs); upgrade rootfs $(loadaddr) $(filesize) 0\0" + "update_rootfs_1=tftpboot $(loadaddr) $(rootfs); erase 1:47-132; cp.b $(loadaddr) $(f_rootfs_addr) $(filesize)\0" + "update_jffs2=tftpboot $(loadaddr) $(rootfs); upgrade rootfs $(loadaddr) $(filesize) 0\0" + "update_jffs2_1=tftpboot $(loadaddr) $(jffs2fs); erase 1:47-132; cp.b $(loadaddr) $(f_rootfs_addr) $(filesize)\0" + "update_firmware=tftpboot $(loadaddr) $(firmware);upgrade firmware $(loadaddr) $(filesize) 0\0" + "reset_uboot_config=erase " MK_STR(IFX_CFG_FLASH_UBOOT_CFG_START_ADDR) " " MK_STR(IFX_CFG_FLASH_UBOOT_CFG_END_ADDR) "\0" + IFX_CFG_FLASH_PARTITIONS_INFO + "flash_end=" MK_STR(IFX_CFG_FLASH_END_ADDR) "\0" + IFX_CFG_FLASH_DATA_BLOCKS_INFO + "f_uboot_addr=" MK_STR(IFX_CFG_FLASH_UBOOT_IMAGE_START_ADDR) "\0" + "f_uboot_size=" MK_STR(IFX_CFG_FLASH_UBOOT_IMAGE_SIZE) "\0" + "f_ubootconfig_addr=" MK_STR(IFX_CFG_FLASH_UBOOT_CFG_START_ADDR) "\0" + "f_ubootconfig_size=" MK_STR(IFX_CFG_FLASH_UBOOT_CFG_SIZE) "\0" + "f_ubootconfig_end=" MK_STR(IFX_CFG_FLASH_UBOOT_CFG_END_ADDR) "\0" + "f_kernel_addr=" MK_STR(IFX_CFG_FLASH_KERNEL_IMAGE_START_ADDR) "\0" + "f_kernel_size=" MK_STR(IFX_CFG_FLASH_KERNEL_IMAGE_SIZE) "\0" + "f_kernel_end=" MK_STR(IFX_CFG_FLASH_KERNEL_IMAGE_END_ADDR) "\0" + "f_rootfs_addr=" MK_STR(IFX_CFG_FLASH_ROOTFS_IMAGE_START_ADDR) "\0" + "f_rootfs_size=" MK_STR(IFX_CFG_FLASH_ROOTFS_IMAGE_SIZE) "\0" + "f_rootfs_end=" MK_STR(IFX_CFG_FLASH_ROOTFS_IMAGE_END_ADDR) "\0" + "f_firmware_addr=" MK_STR(IFX_CFG_FLASH_FIRMWARE_IMAGE_START_ADDR) "\0" + "f_firmware_size=" MK_STR(IFX_CFG_FLASH_FIRMWARE_IMAGE_SIZE) "\0" + "f_sysconfig_addr=" MK_STR(IFX_CFG_FLASH_SYSTEM_CFG_START_ADDR) "\0" + "f_sysconfig_size=" MK_STR(IFX_CFG_FLASH_SYSTEM_CFG_SIZE) "\0" + /* + "f_fwdiag_addr=" MK_STR(IFX_CFG_FLASH_FIRMWARE_DIAG_START_ADDR) "\0" + "f_fwdiag_size=" MK_STR(IFX_CFG_FLASH_FIRMWARE_DIAG_SIZE) "\0" + "f_calibration_addr=" MK_STR(IFX_CFG_FLASH_CALIBRATION_CFG_START_ADDR) "\0" + "f_calibration_size=" MK_STR(IFX_CFG_FLASH_CALIBRATION_CFG_SIZE) "\0" +#if (IFX_CONFIG_FLASH_SIZE == 4) || (IFX_CONFIG_FLASH_SIZE == 8) + "f_voip_addr=" MK_STR(IFX_CFG_FLASH_VOIP_CFG_START_ADDR) "\0" + "f_voip_size=" MK_STR(IFX_CFG_FLASH_VOIP_CFG_SIZE) "\0" +#endif + */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.c b/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.c new file mode 100644 index 0000000000..28263e64c0 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.c @@ -0,0 +1,622 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifdef CONFIG_LZMA + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + + +#if 0 +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return result; } \ + BufferLim = Buffer + size; if (size == 0) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }} +#else + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { return result; } \ + BufferLim = Buffer + size; if (size == 0) { return LZMA_RESULT_DATA_ERROR; } }} +#endif + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#if 0 +#define RC_TEST { if (Buffer == BufferLim) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } } +#else +#define RC_TEST { if (Buffer == BufferLim) { return LZMA_RESULT_DATA_ERROR; } } +#endif + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("ERROR: %s, %d\n", __FILE__, __LINE__); +#endif + return LZMA_RESULT_DATA_ERROR; + } + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("ERROR: %s, %d\n", __FILE__, __LINE__); +#endif + return LZMA_RESULT_DATA_ERROR; + } + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("ERROR: %s, %d\n", __FILE__, __LINE__); +#endif + return LZMA_RESULT_DATA_ERROR; + } + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("ERROR: %s, %d\n", __FILE__, __LINE__); +#endif + return LZMA_RESULT_DATA_ERROR; + } + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} + +#endif /* CONFIG_LZMA */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.h b/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.h new file mode 100644 index 0000000000..2870eeb9c9 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/LzmaDecode.h @@ -0,0 +1,113 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff --git a/package/uboot-ifxmips/files/lib_bootstrap/LzmaTypes.h b/package/uboot-ifxmips/files/lib_bootstrap/LzmaTypes.h new file mode 100644 index 0000000000..288c5e45d7 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/LzmaTypes.h @@ -0,0 +1,45 @@ +/* +LzmaTypes.h + +Types for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.40 (2006-05-01) +*/ + +#ifndef __LZMATYPES_H +#define __LZMATYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +#endif diff --git a/package/uboot-ifxmips/files/lib_bootstrap/LzmaWrapper.c b/package/uboot-ifxmips/files/lib_bootstrap/LzmaWrapper.c new file mode 100644 index 0000000000..955b911c91 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/LzmaWrapper.c @@ -0,0 +1,223 @@ +/****************************************************************************** +** +** FILE NAME : LzmaWrapper.c +** PROJECT : bootloader +** MODULES : U-boot +** +** DATE : 2 Nov 2006 +** AUTHOR : Lin Mars +** DESCRIPTION : LZMA decoder support for U-boot 1.1.5 +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Date $Author $Comment +** 2 Nov 2006 Lin Mars init version which derived from LzmaTest.c from +** LZMA v4.43 SDK +*******************************************************************************/ +#define LZMA_NO_STDIO +#ifndef LZMA_NO_STDIO +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_LZMA + +#include "LzmaDecode.h" +#include "LzmaWrapper.h" + +static const char *kCantReadMessage = "Can not read from source buffer"; +static const char *kCantAllocateMessage = "Not enough buffer for decompression"; + +static size_t rpos=0, dpos=0; + +static int MyReadFileAndCheck(unsigned char *src, void *dest, size_t size) +{ + if (size == 0) + return 0; + memcpy(dest, src + rpos, size); + rpos += size; + return 1; +} + +int lzma_inflate(unsigned char *source, int s_len, unsigned char *dest, int *d_len) +{ + /* We use two 32-bit integers to construct 64-bit integer for file size. + You can remove outSizeHigh, if you don't need >= 4GB supporting, + or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ + UInt32 outSize = 0; + UInt32 outSizeHigh = 0; + SizeT outSizeFull; + unsigned char *outStream; + + int waitEOS = 1; + /* waitEOS = 1, if there is no uncompressed size in headers, + so decoder will wait EOS (End of Stream Marker) in compressed stream */ + + SizeT compressedSize; + unsigned char *inStream; + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + unsigned char properties[LZMA_PROPERTIES_SIZE]; + + int res; + + if (sizeof(UInt32) < 4) + { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("LZMA decoder needs correct UInt32\n"); +#endif + return LZMA_RESULT_DATA_ERROR; + } + + { + long length=s_len; + if ((long)(SizeT)length != length) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("Too big compressed stream\n"); +#endif + return LZMA_RESULT_DATA_ERROR; + } + compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); + } + + /* Read LZMA properties for compressed stream */ + + if (!MyReadFileAndCheck(source, properties, sizeof(properties))) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("%s\n", kCantReadMessage); +#endif + return LZMA_RESULT_DATA_ERROR; + } + + /* Read uncompressed size */ + { + int i; + for (i = 0; i < 8; i++) + { + unsigned char b; + if (!MyReadFileAndCheck(source, &b, 1)) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("%s\n", kCantReadMessage); +#endif + return LZMA_RESULT_DATA_ERROR; + } + if (b != 0xFF) + waitEOS = 0; + if (i < 4) + outSize += (UInt32)(b) << (i * 8); + else + outSizeHigh += (UInt32)(b) << ((i - 4) * 8); + } + + if (waitEOS) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("Stream with EOS marker is not supported"); +#endif + return LZMA_RESULT_DATA_ERROR; + } + outSizeFull = (SizeT)outSize; + if (sizeof(SizeT) >= 8) + outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); + else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("Too big uncompressed stream"); +#endif + return LZMA_RESULT_DATA_ERROR; + } + } + + /* Decode LZMA properties and allocate memory */ + if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("Incorrect stream properties"); +#endif + return LZMA_RESULT_DATA_ERROR; + } + state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + + if (outSizeFull == 0) + outStream = 0; + else + { + if (outSizeFull > d_len) + outStream = 0; + else + outStream = dest; + } + + if (compressedSize == 0) + inStream = 0; + else + { + if ((compressedSize+rpos) > s_len ) + inStream = 0; + else + inStream = source + rpos; + } + + if (state.Probs == 0 + || (outStream == 0 && outSizeFull != 0) + || (inStream == 0 && compressedSize != 0) + ) + { + free(state.Probs); + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("%s\n", kCantAllocateMessage); +#endif + return LZMA_RESULT_DATA_ERROR; + } + + /* Decompress */ + { + SizeT inProcessed; + SizeT outProcessed; + res = LzmaDecode(&state, + inStream, compressedSize, &inProcessed, + outStream, outSizeFull, &outProcessed); + if (res != 0) + { + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("\nDecoding error = %d\n", res); +#endif + res = 1; + } + else + { + *d_len = outProcessed; + } + } + + free(state.Probs); + return res; +} + +#endif /* CONFIG_LZMA */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/Makefile b/package/uboot-ifxmips/files/lib_bootstrap/Makefile new file mode 100644 index 0000000000..e650be0e47 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/Makefile @@ -0,0 +1,52 @@ +# +# (C) Copyright 2003 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB = libbootstrap.a + +#OBJS_PRINTF_ENABLED = bootstrap_board.o time.o console.o LzmaWrapper.o LzmaDecode.o crc32.o ctype.o display_options.o string.o vsprintf.o lists.o devices.o +#OBJS_PRINTF_DISBALED = bootstrap_board.o LzmaDecode.o string.o crc32.o LzmaWrapper.o + +OBJS = bootstrap_board_$(BOARDDIR).o LzmaDecode.o string.o crc32.o LzmaWrapper.o + +ifeq ($(BOOTSTRAP_PRINTF_STATUS), BOOTSTRAP_PRINTF_ENABLED) +#overwrite objs +OBJS = bootstrap_board_$(BOARDDIR).o time.o console.o LzmaWrapper.o LzmaDecode.o crc32.o ctype.o display_options.o string.o vsprintf.o lists.o devices.o +CFLAGS += -DDEBUG_ENABLE_BOOTSTRAP_PRINTF +endif + +all: .depend $(LIB) + +$(LIB): $(OBJS) + $(AR) crv $@ $(OBJS) + +######################################################################### + +.depend: Makefile $(OBJS:.o=.c) + echo "make libbootstrap.a with HEAD_SIZE $(HEAD_SIZE)" + $(CC) -M $(CFLAGS) $(OBJS:.o=.c) > $@ + +sinclude .depend + +######################################################################### diff --git a/package/uboot-ifxmips/files/lib_bootstrap/bootstrap_board_danube.c b/package/uboot-ifxmips/files/lib_bootstrap/bootstrap_board_danube.c new file mode 100644 index 0000000000..22f0a5aea8 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/bootstrap_board_danube.c @@ -0,0 +1,501 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_DANUBE +#include +#include +#endif +#include "LzmaWrapper.h" + +//#define DEBUG_ENABLE_BOOTSTRAP_PRINTF + +DECLARE_GLOBAL_DATA_PTR; + +#if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < BOOTSTRAP_CFG_MONITOR_BASE) || \ + (CFG_ENV_ADDR >= (BOOTSTRAP_CFG_MONITOR_BASE + CFG_MONITOR_LEN)) ) || \ + defined(CFG_ENV_IS_IN_NVRAM) +#define TOTAL_MALLOC_LEN (CFG_MALLOC_LEN + CFG_ENV_SIZE) +#else +#define TOTAL_MALLOC_LEN CFG_MALLOC_LEN +#endif + +#undef DEBUG + +#if (CONFIG_COMMANDS & CFG_CMD_NAND) +extern unsigned long nand_init(void); +#endif + +#ifdef CONFIG_SERIAL_FLASH +extern int serial_flash_init (void); +#endif + +extern int timer_init(void); + +extern int incaip_set_cpuclk(void); + +extern ulong uboot_end_data_bootstrap; +extern ulong uboot_end_bootstrap; + +ulong monitor_flash_len; + +const char version_string[] = + U_BOOT_VERSION" (" __DATE__ " - " __TIME__ ")"; + +static char *failed = "*** failed ***\n"; + +/* + * Begin and End of memory area for malloc(), and current "brk" + */ +static ulong mem_malloc_start; +static ulong mem_malloc_end; +static ulong mem_malloc_brk; + + +/* + * The Malloc area is immediately below the monitor copy in DRAM + */ +static void mem_malloc_init (ulong dest_addr) +{ +// ulong dest_addr = BOOTSTRAP_CFG_MONITOR_BASE + gd->reloc_off; + + mem_malloc_end = dest_addr; + mem_malloc_start = dest_addr - TOTAL_MALLOC_LEN; + mem_malloc_brk = mem_malloc_start; + + memset ((void *) mem_malloc_start, + 0, + mem_malloc_end - mem_malloc_start); +} + +void *malloc(unsigned int size) +{ + if(size < (mem_malloc_end - mem_malloc_start)) + { + mem_malloc_start += size; + return (void *)(mem_malloc_start - size); + } + return NULL; +} + +void *realloc(void *src,unsigned int size) +{ + return NULL; +} + +void free(void *src) +{ + return; +} + + +void *sbrk (ptrdiff_t increment) +{ + ulong old = mem_malloc_brk; + ulong new = old + increment; + + if ((new < mem_malloc_start) || (new > mem_malloc_end)) { + return (NULL); + } + mem_malloc_brk = new; + return ((void *) old); +} + + +static int init_func_ram (void) +{ +#ifdef CONFIG_BOARD_TYPES + int board_type = gd->board_type; +#else + int board_type = 0; /* use dummy arg */ +#endif + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + puts ("DRAM: "); +#endif + + if ((gd->ram_size = initdram (board_type)) > 0) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + print_size (gd->ram_size, "\n"); +#endif + return (0); + } +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + puts (failed); +#endif + return (1); +} + +static int display_banner(void) +{ +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("\n\n%s\n\n", version_string); +#endif + return (0); +} + +static int init_baudrate (void) +{ +#if 0 + char tmp[64]; /* long enough for environment variables */ + int i = getenv_r ("baudrate", tmp, sizeof (tmp)); + + gd->baudrate = (i > 0) + ? (int) simple_strtoul (tmp, NULL, 10) + : CONFIG_BAUDRATE; +#endif + + gd->baudrate = CONFIG_BAUDRATE; + + return (0); +} +#ifdef CONFIG_DANUBE +static void init_led(void) +{ + + *(unsigned long *)0xBE100B18 |= 0x70; + *(unsigned long *)0xBE100B1C |= 0x70; + *(unsigned long *)0xBE100B20 &= ~0x70; + *(unsigned long *)0xBE100B24 |= 0x70; +#ifdef USE_REFERENCE_BOARD + + *DANUBE_LED_CON1 = 0x00000003; + *DANUBE_LED_CPU0 = 0x0000010; + *DANUBE_LED_CPU1 = 0x00000000; + *DANUBE_LED_AR = 0x00000000; + *DANUBE_LED_CON0 = 0x84000000; + +#else + + *DANUBE_LED_CON1 = 0x00000007; + *DANUBE_LED_CPU0 = 0x00001000; + *DANUBE_LED_CPU1 = 0x00000000; + *DANUBE_LED_AR = 0x00000000; + *DANUBE_LED_CON0 = 0x84000000; + +#endif + +} +#endif +/* + * Breath some life into the board... + * + * The first part of initialization is running from Flash memory; + * its main purpose is to initialize the RAM so that we + * can relocate the monitor code to RAM. + */ + +/* + * All attempts to come up with a "common" initialization sequence + * that works for all boards and architectures failed: some of the + * requirements are just _too_ different. To get rid of the resulting + * mess of board dependend #ifdef'ed code we now make the whole + * initialization sequence configurable to the user. + * + * The requirements for any new initalization function is simple: it + * receives a pointer to the "global data" structure as it's only + * argument, and returns an integer return code, where 0 means + * "continue" and != 0 means "fatal error, hang the system". + */ +typedef int (init_fnc_t) (void); + +init_fnc_t *init_sequence[] = { + //timer_init, + //env_init, /* initialize environment */ +#ifdef CONFIG_INCA_IP + incaip_set_cpuclk, /* set cpu clock according to environment variable */ +#endif +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + init_baudrate, /* initialze baudrate settings */ + serial_init, /* serial communications setup */ + console_init_f, + display_banner, /* say that we are here */ +#endif + init_func_ram, + //checkboard, + NULL, +}; + + +void bootstrap_board_init_f(ulong bootflag) +{ + gd_t gd_data, *id; + bd_t *bd; + init_fnc_t **init_fnc_ptr; + ulong addr, addr_sp, len = (ulong)&uboot_end_bootstrap - BOOTSTRAP_CFG_MONITOR_BASE; + ulong *s; + ulong lzmaImageaddr = 0; +#ifdef CONFIG_PURPLE + void copy_code (ulong); +#endif + + /* Pointer is writable since we allocated a register for it. + */ + gd = &gd_data; + /* compiler optimization barrier needed for GCC >= 3.4 */ + __asm__ __volatile__("": : :"memory"); + + memset ((void *)gd, 0, sizeof (gd_t)); + + for (init_fnc_ptr = init_sequence; *init_fnc_ptr; ++init_fnc_ptr) { + if ((*init_fnc_ptr)() != 0) { + hang (); + } + } + + /* + * Now that we have DRAM mapped and working, we can + * relocate the code and continue running from DRAM. + */ + addr = CFG_SDRAM_BASE + gd->ram_size; + + /* We can reserve some RAM "on top" here. + */ + + /* round down to next 4 kB limit. + */ + addr &= ~(4096 - 1); + debug ("Top of RAM usable for U-Boot at: %08lx\n", addr); + + /* Reserve memory for U-Boot code, data & bss + * round down to next 16 kB limit + */ + addr -= len; + addr &= ~(16 * 1024 - 1); + + debug ("Reserving %ldk for U-Boot at: %08lx\n", len >> 10, addr); + + /* Reserve memory for malloc() arena. + */ + addr_sp = addr - TOTAL_MALLOC_LEN; + debug ("Reserving %dk for malloc() at: %08lx\n", + TOTAL_MALLOC_LEN >> 10, addr_sp); + + /* + * (permanently) allocate a Board Info struct + * and a permanent copy of the "global" data + */ + addr_sp -= sizeof(bd_t); + bd = (bd_t *)addr_sp; + gd->bd = bd; + debug ("Reserving %d Bytes for Board Info at: %08lx\n", + sizeof(bd_t), addr_sp); + + addr_sp -= sizeof(gd_t); + id = (gd_t *)addr_sp; + debug ("Reserving %d Bytes for Global Data at: %08lx\n", + sizeof (gd_t), addr_sp); + + /* Reserve memory for boot params. + */ + addr_sp -= CFG_BOOTPARAMS_LEN; + bd->bi_boot_params = addr_sp; + debug ("Reserving %dk for boot params() at: %08lx\n", + CFG_BOOTPARAMS_LEN >> 10, addr_sp); + + /* + * Finally, we set up a new (bigger) stack. + * + * Leave some safety gap for SP, force alignment on 16 byte boundary + * Clear initial stack frame + */ + addr_sp -= 16; + addr_sp &= ~0xF; + s = (ulong *)addr_sp; + *s-- = 0; + *s-- = 0; + addr_sp = (ulong)s; + debug ("Stack Pointer at: %08lx\n", addr_sp); + + /* + * Save local variables to board info struct + */ + bd->bi_memstart = CFG_SDRAM_BASE; /* start of DRAM memory */ + bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */ + bd->bi_baudrate = gd->baudrate; /* Console Baudrate */ + + memcpy (id, (void *)gd, sizeof (gd_t)); + + /* On the purple board we copy the code in a special way + * in order to solve flash problems + */ +#ifdef CONFIG_PURPLE + copy_code(addr); +#endif + + lzmaImageaddr = (ulong)&uboot_end_data_bootstrap; + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("\n relocating to address %08x ", addr); +#endif + + bootstrap_relocate_code (addr_sp, id, addr); + + /* NOTREACHED - relocate_code() does not return */ +} +/************************************************************************ + * + * This is the next part if the initialization sequence: we are now + * running from RAM and have a "normal" C environment, i. e. global + * data can be written, BSS has been cleared, the stack size in not + * that critical any more, etc. + * + ************************************************************************ + */ +#define CONFIG_LZMA + +void bootstrap_board_init_r (gd_t *id, ulong dest_addr) +{ + int i; + + ulong addr; + ulong data, len, checksum; + ulong *len_ptr; + image_header_t header; + image_header_t *hdr = &header; + unsigned int destLen; + int (*fn)(); + +#if 1 +#endif + + + + /* initialize malloc() area */ + mem_malloc_init(dest_addr); + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf("\n Compressed Image at %08x \n ", (BOOTSTRAP_CFG_MONITOR_BASE + ((ulong)&uboot_end_data_bootstrap - dest_addr))); +#endif + + addr = (char *)(BOOTSTRAP_CFG_MONITOR_BASE + ((ulong)&uboot_end_data_bootstrap - dest_addr)); + memmove (&header, (char *)addr, sizeof(image_header_t)); + + if (ntohl(hdr->ih_magic) != IH_MAGIC) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("Bad Magic Number at address 0x%08lx\n",addr); +#endif + return; + } + + data = (ulong)&header; + len = sizeof(image_header_t); + + checksum = ntohl(hdr->ih_hcrc); + hdr->ih_hcrc = 0; + if (crc32 (0, (char *)data, len) != checksum) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("Bad Header Checksum\n"); +#endif + return; + } + + data = addr + sizeof(image_header_t); + len = ntohl(hdr->ih_size); + + len_ptr = (ulong *)data; + + + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("Disabling all the interrupts\n"); +#endif + disable_interrupts(); +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf (" Uncompressing UBoot Image ... \n" ); +#endif + + /* + * If we've got less than 4 MB of malloc() space, + * use slower decompression algorithm which requires + * at most 2300 KB of memory. + */ + destLen = 0x0; + +#ifdef CONFIG_BZIP2 + i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), + 0x400000, (char *)data, len, + CFG_MALLOC_LEN < (4096 * 1024), 0); + if (i != BZ_OK) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); +#endif + return; + } +#endif /* CONFIG_BZIP2 */ + +#ifdef CONFIG_MICROBZIP2 + i = micro_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), + &destLen, (char *)data, len, + CFG_MALLOC_LEN < (4096 * 1024), 0); + if (i != RETVAL_OK) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("MICRO_BUNZIP2 ERROR %d - must RESET board to recover\n", i); +#endif + //do_reset (cmdtp, flag, argc, argv); + return; + } +#endif + +#ifdef CONFIG_LZMA +#if 0 + i = lzmaBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), + &destLen, (char *)data, len); +#endif + + i = lzma_inflate ((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), &destLen); + if (i != LZMA_RESULT_OK) { +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf ("LZMA ERROR %d - must RESET board to recover\n", i); +#endif + //do_reset (cmdtp, flag, argc, argv); + return; + } +#endif + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + printf (" Uncompression completed successfully with destLen %d\n ",destLen ); +#endif + + fn = ntohl(hdr->ih_load); + + (*fn)(); + + hang (); + +} + +void hang (void) +{ + +#ifdef DEBUG_ENABLE_BOOTSTRAP_PRINTF + puts ("### ERROR ### Please RESET the board ###\n"); +#endif + for (;;); +} diff --git a/package/uboot-ifxmips/files/lib_bootstrap/console.c b/package/uboot-ifxmips/files/lib_bootstrap/console.c new file mode 100644 index 0000000000..a8fcd2a53f --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/console.c @@ -0,0 +1,573 @@ +/* + * (C) Copyright 2000 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#ifdef CONFIG_AMIGAONEG3SE +int console_changed = 0; +#endif + +#ifdef CFG_CONSOLE_IS_IN_ENV +/* + * if overwrite_console returns 1, the stdin, stderr and stdout + * are switched to the serial port, else the settings in the + * environment are used + */ +#ifdef CFG_CONSOLE_OVERWRITE_ROUTINE +extern int overwrite_console (void); +#define OVERWRITE_CONSOLE overwrite_console () +#else +#define OVERWRITE_CONSOLE 0 +#endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */ + +#endif /* CFG_CONSOLE_IS_IN_ENV */ + +static int console_setfile (int file, device_t * dev) +{ + int error = 0; + + if (dev == NULL) + return -1; + + switch (file) { + case stdin: + case stdout: + case stderr: + /* Start new device */ + if (dev->start) { + error = dev->start (); + /* If it's not started dont use it */ + if (error < 0) + break; + } + + /* Assign the new device (leaving the existing one started) */ + stdio_devices[file] = dev; + + /* + * Update monitor functions + * (to use the console stuff by other applications) + */ + switch (file) { + case stdin: + gd->jt[XF_getc] = dev->getc; + gd->jt[XF_tstc] = dev->tstc; + break; + case stdout: + gd->jt[XF_putc] = dev->putc; + gd->jt[XF_puts] = dev->puts; + gd->jt[XF_printf] = printf; + break; + } + break; + + default: /* Invalid file ID */ + error = -1; + } + return error; +} + +/** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ + +void serial_printf (const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start (args, fmt); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf (printbuffer, fmt, args); + va_end (args); + + serial_puts (printbuffer); +} + +int fgetc (int file) +{ + if (file < MAX_FILES) + return stdio_devices[file]->getc (); + + return -1; +} + +int ftstc (int file) +{ + if (file < MAX_FILES) + return stdio_devices[file]->tstc (); + + return -1; +} + +void fputc (int file, const char c) +{ + if (file < MAX_FILES) + stdio_devices[file]->putc (c); +} + +void fputs (int file, const char *s) +{ + if (file < MAX_FILES) + stdio_devices[file]->puts (s); +} + +void fprintf (int file, const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start (args, fmt); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf (printbuffer, fmt, args); + va_end (args); + + /* Send to desired file */ + fputs (file, printbuffer); +} + +/** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ + +int getc (void) +{ + if (gd->flags & GD_FLG_DEVINIT) { + /* Get from the standard input */ + return fgetc (stdin); + } + + /* Send directly to the handler */ + return serial_getc (); +} + +int tstc (void) +{ + if (gd->flags & GD_FLG_DEVINIT) { + /* Test the standard input */ + return ftstc (stdin); + } + + /* Send directly to the handler */ + return serial_tstc (); +} + +void putc (const char c) +{ +#ifdef CONFIG_SILENT_CONSOLE + if (gd->flags & GD_FLG_SILENT) + return; +#endif + + if (gd->flags & GD_FLG_DEVINIT) { + /* Send to the standard output */ + fputc (stdout, c); + } else { + /* Send directly to the handler */ + serial_putc (c); + } +} + +void puts (const char *s) +{ +#ifdef CONFIG_SILENT_CONSOLE + if (gd->flags & GD_FLG_SILENT) + return; +#endif + + if (gd->flags & GD_FLG_DEVINIT) { + /* Send to the standard output */ + fputs (stdout, s); + } else { + /* Send directly to the handler */ + serial_puts (s); + } +} + +void printf (const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + va_start (args, fmt); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf (printbuffer, fmt, args); + va_end (args); + + /* Print the string */ + puts (printbuffer); +} + +void vprintf (const char *fmt, va_list args) +{ + uint i; + char printbuffer[CFG_PBSIZE]; + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf (printbuffer, fmt, args); + + /* Print the string */ + puts (printbuffer); +} + +/* test if ctrl-c was pressed */ +static int ctrlc_disabled = 0; /* see disable_ctrl() */ +static int ctrlc_was_pressed = 0; +int ctrlc (void) +{ + if (!ctrlc_disabled && gd->have_console) { + if (tstc ()) { + switch (getc ()) { + case 0x03: /* ^C - Control C */ + ctrlc_was_pressed = 1; + return 1; + default: + break; + } + } + } + return 0; +} + +/* pass 1 to disable ctrlc() checking, 0 to enable. + * returns previous state + */ +int disable_ctrlc (int disable) +{ + int prev = ctrlc_disabled; /* save previous state */ + + ctrlc_disabled = disable; + return prev; +} + +int had_ctrlc (void) +{ + return ctrlc_was_pressed; +} + +void clear_ctrlc (void) +{ + ctrlc_was_pressed = 0; +} + +#ifdef CONFIG_MODEM_SUPPORT_DEBUG +char screen[1024]; +char *cursor = screen; +int once = 0; +inline void dbg(const char *fmt, ...) +{ + va_list args; + uint i; + char printbuffer[CFG_PBSIZE]; + + if (!once) { + memset(screen, 0, sizeof(screen)); + once++; + } + + va_start(args, fmt); + + /* For this to work, printbuffer must be larger than + * anything we ever want to print. + */ + i = vsprintf(printbuffer, fmt, args); + va_end(args); + + if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) { + memset(screen, 0, sizeof(screen)); + cursor = screen; + } + sprintf(cursor, printbuffer); + cursor += strlen(printbuffer); + +} +#else +inline void dbg(const char *fmt, ...) +{ +} +#endif + +/** U-Boot INIT FUNCTIONS *************************************************/ + +int console_assign (int file, char *devname) +{ + int flag, i; + + /* Check for valid file */ + switch (file) { + case stdin: + flag = DEV_FLAGS_INPUT; + break; + case stdout: + case stderr: + flag = DEV_FLAGS_OUTPUT; + break; + default: + return -1; + } + + /* Check for valid device name */ + + for (i = 1; i <= ListNumItems (devlist); i++) { + device_t *dev = ListGetPtrToItem (devlist, i); + + if (strcmp (devname, dev->name) == 0) { + if (dev->flags & flag) + return console_setfile (file, dev); + + return -1; + } + } + + return -1; +} + +/* Called before relocation - use serial functions */ +int console_init_f (void) +{ + gd->have_console = 1; + +#ifdef CONFIG_SILENT_CONSOLE + if (getenv("silent") != NULL) + gd->flags |= GD_FLG_SILENT; +#endif + + return (0); +} + +#if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SPLASH_SCREEN) || defined(CONFIG_SILENT_CONSOLE) +/* search a device */ +device_t *search_device (int flags, char *name) +{ + int i, items; + device_t *dev = NULL; + + items = ListNumItems (devlist); + if (name == NULL) + return dev; + + for (i = 1; i <= items; i++) { + dev = ListGetPtrToItem (devlist, i); + if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) { + break; + } + } + return dev; +} +#endif /* CFG_CONSOLE_IS_IN_ENV || CONFIG_SPLASH_SCREEN */ + +#ifdef CFG_CONSOLE_IS_IN_ENV +/* Called after the relocation - use desired console functions */ +int console_init_r (void) +{ + char *stdinname, *stdoutname, *stderrname; + device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL; +#ifdef CFG_CONSOLE_ENV_OVERWRITE + int i; +#endif /* CFG_CONSOLE_ENV_OVERWRITE */ + + /* set default handlers at first */ + gd->jt[XF_getc] = serial_getc; + gd->jt[XF_tstc] = serial_tstc; + gd->jt[XF_putc] = serial_putc; + gd->jt[XF_puts] = serial_puts; + gd->jt[XF_printf] = serial_printf; + + /* stdin stdout and stderr are in environment */ + /* scan for it */ + stdinname = getenv ("stdin"); + stdoutname = getenv ("stdout"); + stderrname = getenv ("stderr"); + + if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ + inputdev = search_device (DEV_FLAGS_INPUT, stdinname); + outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname); + errdev = search_device (DEV_FLAGS_OUTPUT, stderrname); + } + /* if the devices are overwritten or not found, use default device */ + if (inputdev == NULL) { + inputdev = search_device (DEV_FLAGS_INPUT, "serial"); + } + if (outputdev == NULL) { + outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); + } + if (errdev == NULL) { + errdev = search_device (DEV_FLAGS_OUTPUT, "serial"); + } + /* Initializes output console first */ + if (outputdev != NULL) { + console_setfile (stdout, outputdev); + } + if (errdev != NULL) { + console_setfile (stderr, errdev); + } + if (inputdev != NULL) { + console_setfile (stdin, inputdev); + } + + gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ + +#ifndef CFG_CONSOLE_INFO_QUIET + /* Print information */ + puts ("In: "); + if (stdio_devices[stdin] == NULL) { + puts ("No input devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdin]->name); + } + + puts ("Out: "); + if (stdio_devices[stdout] == NULL) { + puts ("No output devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdout]->name); + } + + puts ("Err: "); + if (stdio_devices[stderr] == NULL) { + puts ("No error devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stderr]->name); + } +#endif /* CFG_CONSOLE_INFO_QUIET */ + +#ifdef CFG_CONSOLE_ENV_OVERWRITE + /* set the environment variables (will overwrite previous env settings) */ + for (i = 0; i < 3; i++) { + setenv (stdio_names[i], stdio_devices[i]->name); + } +#endif /* CFG_CONSOLE_ENV_OVERWRITE */ + +#if 0 + /* If nothing usable installed, use only the initial console */ + if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) + return (0); +#endif + return (0); +} + +#else /* CFG_CONSOLE_IS_IN_ENV */ +#if 0 +/* Called after the relocation - use desired console functions */ +int console_init_r (void) +{ + device_t *inputdev = NULL, *outputdev = NULL; + int i, items = ListNumItems (devlist); + +#ifdef CONFIG_SPLASH_SCREEN + /* suppress all output if splash screen is enabled and we have + a bmp to display */ + if (getenv("splashimage") != NULL) + outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); +#endif + +#ifdef CONFIG_SILENT_CONSOLE + /* Suppress all output if "silent" mode requested */ + if (gd->flags & GD_FLG_SILENT) + outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); +#endif + + /* Scan devices looking for input and output devices */ + for (i = 1; + (i <= items) && ((inputdev == NULL) || (outputdev == NULL)); + i++ + ) { + device_t *dev = ListGetPtrToItem (devlist, i); + + if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { + inputdev = dev; + } + if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { + outputdev = dev; + } + } + + /* Initializes output console first */ + if (outputdev != NULL) { + console_setfile (stdout, outputdev); + console_setfile (stderr, outputdev); + } + + /* Initializes input console */ + if (inputdev != NULL) { + console_setfile (stdin, inputdev); + } + + gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ + +#ifndef CFG_CONSOLE_INFO_QUIET + /* Print information */ + puts ("In: "); + if (stdio_devices[stdin] == NULL) { + puts ("No input devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdin]->name); + } + + puts ("Out: "); + if (stdio_devices[stdout] == NULL) { + puts ("No output devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stdout]->name); + } + + puts ("Err: "); + if (stdio_devices[stderr] == NULL) { + puts ("No error devices available!\n"); + } else { + printf ("%s\n", stdio_devices[stderr]->name); + } +#endif /* CFG_CONSOLE_INFO_QUIET */ + + /* Setting environment variables */ + for (i = 0; i < 3; i++) { + setenv (stdio_names[i], stdio_devices[i]->name); + } + +#if 0 + /* If nothing usable installed, use only the initial console */ + if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) + return (0); +#endif + + return (0); +} +#endif + +#endif /* CFG_CONSOLE_IS_IN_ENV */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/crc32.c b/package/uboot-ifxmips/files/lib_bootstrap/crc32.c new file mode 100644 index 0000000000..50ca4ffd38 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/crc32.c @@ -0,0 +1,197 @@ +/* + * This file is derived from crc32.c from the zlib-1.1.3 distribution + * by Jean-loup Gailly and Mark Adler. + */ + +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef USE_HOSTCC /* Shut down "ANSI does not permit..." warnings */ +#include /* to get command definitions like CFG_CMD_JFFS2 */ +#endif + +#include "zlib.h" + +#define local static +#define ZEXPORT /* empty */ +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +#if 0 +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} +#endif + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) + +/* No ones complement version. JFFS2 (and other things ?) + * don't use ones compliment in their CRC calculations. + */ +uLong ZEXPORT crc32_no_comp(uLong crc, const Bytef *buf, uInt len) +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + + return crc; +} + +#endif /* CFG_CMD_JFFS2 */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/ctype.c b/package/uboot-ifxmips/files/lib_bootstrap/ctype.c new file mode 100644 index 0000000000..6ed0468a21 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/ctype.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +/* + * linux/lib/ctype.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include + +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/devices.c b/package/uboot-ifxmips/files/lib_bootstrap/devices.c new file mode 100644 index 0000000000..ddf8f8ee2d --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/devices.c @@ -0,0 +1,216 @@ +/* + * (C) Copyright 2000 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#ifdef CONFIG_LOGBUFFER +#include +#endif +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) +#include +#endif + +DECLARE_GLOBAL_DATA_PTR; + +list_t devlist = 0; +device_t *stdio_devices[] = { NULL, NULL, NULL }; +char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" }; + +#if defined(CONFIG_SPLASH_SCREEN) && !defined(CFG_DEVICE_NULLDEV) +#define CFG_DEVICE_NULLDEV 1 +#endif + + +#ifdef CFG_DEVICE_NULLDEV +void nulldev_putc(const char c) +{ + /* nulldev is empty! */ +} + +void nulldev_puts(const char *s) +{ + /* nulldev is empty! */ +} + +int nulldev_input(void) +{ + /* nulldev is empty! */ + return 0; +} +#endif + +/************************************************************************** + * SYSTEM DRIVERS + ************************************************************************** + */ + +static void drv_system_init (void) +{ + device_t dev; + + memset (&dev, 0, sizeof (dev)); + + strcpy (dev.name, "serial"); + dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; +#ifdef CONFIG_SERIAL_SOFTWARE_FIFO + dev.putc = serial_buffered_putc; + dev.puts = serial_buffered_puts; + dev.getc = serial_buffered_getc; + dev.tstc = serial_buffered_tstc; +#else + dev.putc = serial_putc; + dev.puts = serial_puts; + dev.getc = serial_getc; + dev.tstc = serial_tstc; +#endif + + device_register (&dev); + +#ifdef CFG_DEVICE_NULLDEV + memset (&dev, 0, sizeof (dev)); + + strcpy (dev.name, "nulldev"); + dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM; + dev.putc = nulldev_putc; + dev.puts = nulldev_puts; + dev.getc = nulldev_input; + dev.tstc = nulldev_input; + + device_register (&dev); +#endif +} + +/************************************************************************** + * DEVICES + ************************************************************************** + */ + +int device_register (device_t * dev) +{ + ListInsertItem (devlist, dev, LIST_END); + return 0; +} + +/* deregister the device "devname". + * returns 0 if success, -1 if device is assigned and 1 if devname not found + */ +#ifdef CFG_DEVICE_DEREGISTER +int device_deregister(char *devname) +{ + int i,l,dev_index; + device_t *dev = NULL; + char temp_names[3][8]; + + dev_index=-1; + for (i=1; i<=ListNumItems(devlist); i++) { + dev = ListGetPtrToItem (devlist, i); + if(strcmp(dev->name,devname)==0) { + dev_index=i; + break; + } + } + if(dev_index<0) /* device not found */ + return 0; + /* get stdio devices (ListRemoveItem changes the dev list) */ + for (l=0 ; l< MAX_FILES; l++) { + if (stdio_devices[l] == dev) { + /* Device is assigned -> report error */ + return -1; + } + memcpy (&temp_names[l][0], + stdio_devices[l]->name, + sizeof(stdio_devices[l]->name)); + } + ListRemoveItem(devlist,NULL,dev_index); + /* reassign Device list */ + for (i=1; i<=ListNumItems(devlist); i++) { + dev = ListGetPtrToItem (devlist, i); + for (l=0 ; l< MAX_FILES; l++) { + if(strcmp(dev->name,temp_names[l])==0) { + stdio_devices[l] = dev; + } + } + } + return 0; +} +#endif /* CFG_DEVICE_DEREGISTER */ + +int devices_init (void) +{ +#ifndef CONFIG_ARM /* already relocated for current ARM implementation */ + ulong relocation_offset = gd->reloc_off; + int i; + + /* relocate device name pointers */ + for (i = 0; i < (sizeof (stdio_names) / sizeof (char *)); ++i) { + stdio_names[i] = (char *) (((ulong) stdio_names[i]) + + relocation_offset); + } +#endif + + /* Initialize the list */ + devlist = ListCreate (sizeof (device_t)); + + if (devlist == NULL) { + eputs ("Cannot initialize the list of devices!\n"); + return -1; + } +#if defined(CONFIG_HARD_I2C) || defined(CONFIG_SOFT_I2C) + i2c_init (CFG_I2C_SPEED, CFG_I2C_SLAVE); +#endif +#ifdef CONFIG_LCD + drv_lcd_init (); +#endif +#if defined(CONFIG_VIDEO) || defined(CONFIG_CFB_CONSOLE) + drv_video_init (); +#endif +#ifdef CONFIG_KEYBOARD + drv_keyboard_init (); +#endif +#ifdef CONFIG_LOGBUFFER + drv_logbuff_init (); +#endif + drv_system_init (); +#ifdef CONFIG_SERIAL_MULTI + serial_devices_init (); +#endif +#ifdef CONFIG_USB_TTY + drv_usbtty_init (); +#endif +#ifdef CONFIG_NETCONSOLE + drv_nc_init (); +#endif + + return (0); +} + +int devices_done (void) +{ + ListDispose (devlist); + + return 0; +} diff --git a/package/uboot-ifxmips/files/lib_bootstrap/display_options.c b/package/uboot-ifxmips/files/lib_bootstrap/display_options.c new file mode 100644 index 0000000000..512e8980d9 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/display_options.c @@ -0,0 +1,67 @@ +/* + * (C) Copyright 2000-2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +int display_options (void) +{ + extern char version_string[]; + +#if defined(BUILD_TAG) + printf ("\n\n%s, Build: %s\n\n", version_string, BUILD_TAG); +#else + printf ("\n\n%s\n\n", version_string); +#endif + return 0; +} + +/* + * print sizes as "xxx kB", "xxx.y kB", "xxx MB" or "xxx.y MB" as needed; + * allow for optional trailing string (like "\n") + */ +void print_size (ulong size, const char *s) +{ + ulong m, n; + ulong d = 1 << 20; /* 1 MB */ + char c = 'M'; + + if (size < d) { /* print in kB */ + c = 'k'; + d = 1 << 10; + } + + n = size / d; + + m = (10 * (size - (n * d)) + (d / 2) ) / d; + + if (m >= 10) { + m -= 10; + n += 1; + } + + printf ("%2ld", n); + if (m) { + printf (".%ld", m); + } + printf (" %cB%s", c, s); +} diff --git a/package/uboot-ifxmips/files/lib_bootstrap/lists.c b/package/uboot-ifxmips/files/lib_bootstrap/lists.c new file mode 100644 index 0000000000..3f117b568e --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/lists.c @@ -0,0 +1,734 @@ +#include +#include +#include + +#define MAX(a,b) (((a)>(b)) ? (a) : (b)) +#define MIN(a,b) (((a)<(b)) ? (a) : (b)) +#define CAT4CHARS(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | d) + +/* increase list size by 10% every time it is full */ +#define kDefaultAllocationPercentIncrease 10 + +/* always increase list size by 4 items when it is full */ +#define kDefaultAllocationminNumItemsIncrease 4 + +/* + * how many items to expand the list by when it becomes full + * = current listSize (in items) + (hiword percent of list size) + loword + */ +#define NUMITEMSPERALLOC(list) MAX(((*list)->listSize * \ + ((*list)->percentIncrease + 100)) / 100, \ + (*list)->minNumItemsIncrease ) + +#define ITEMPTR(list,item) &(((char *)&(*list)->itemList)[(*(list))->itemSize * (item)]) + +#define LIST_SIGNATURE CAT4CHARS('L', 'I', 'S', 'T'); + +#define calloc(size,num) malloc(size*num) + +/********************************************************************/ + +Handle NewHandle (unsigned int numBytes) +{ + void *memPtr; + HandleRecord *hanPtr; + + memPtr = calloc (numBytes, 1); + hanPtr = (HandleRecord *) calloc (sizeof (HandleRecord), 1); + if (hanPtr && (memPtr || numBytes == 0)) { + hanPtr->ptr = memPtr; + hanPtr->size = numBytes; + return (Handle) hanPtr; + } else { + free (memPtr); + free (hanPtr); + return NULL; + } +} +/********************************************************************/ + +void DisposeHandle (Handle handle) +{ + if (handle) { + free (*handle); + free ((void *) handle); + } +} +/********************************************************************/ + +unsigned int GetHandleSize (Handle handle) +{ + return ((HandleRecord *) handle)->size; +} +/********************************************************************/ + +int SetHandleSize (Handle handle, unsigned int newSize) +{ + HandleRecord *hanRecPtr = (HandleRecord *) handle; + void *newPtr, *oldPtr; + unsigned int oldSize; + + + oldPtr = hanRecPtr->ptr; + oldSize = hanRecPtr->size; + + if (oldSize == newSize) + return 1; + + if (oldPtr == NULL) { + newPtr = malloc (newSize); + } else { + newPtr = realloc (oldPtr, newSize); + } + if (newPtr || (newSize == 0)) { + hanRecPtr->ptr = newPtr; + hanRecPtr->size = newSize; + if (newSize > oldSize) + memset ((char *) newPtr + oldSize, 0, newSize - oldSize); + return 1; + } else + return 0; +} + +#ifdef CFG_ALL_LIST_FUNCTIONS + +/* Used to compare list elements by their raw data contents */ +static int ListMemBlockCmp (void *a, void *b, int size) +{ + return memcmp (a, b, size); +} + +/***************************************************************************/ + +/* + * Binary search numElements of size elementSize in array for a match + * to the. item. Return the index of the element that matches + * (0 - numElements - 1). If no match is found return the -i-1 where + * i is the index (0 - numElements) where the item should be placed. + * (*theCmp)(a,b) should return <0 if a0 if a>b. + * + * This function is like the C-Library function bsearch() except that + * this function returns the index where the item should be placed if + * it is not found. + */ +int BinSearch ( void *array, int numElements, int elementSize, + void *itemPtr, CompareFunction compareFunction) +{ + int low, high, mid, cmp; + void *arrayItemPtr; + + for (low = 0, high = numElements - 1, mid = 0, cmp = -1; low <= high;) { + mid = (low + high) >> 1; + + arrayItemPtr = (void *) (((char *) array) + (mid * elementSize)); + cmp = compareFunction + ? compareFunction (itemPtr, arrayItemPtr) + : ListMemBlockCmp (itemPtr, arrayItemPtr, elementSize); + if (cmp == 0) { + return mid; + } else if (cmp < 0) { + high = mid - 1; + } else { + low = mid + 1; + } + } + if (cmp > 0) + mid++; + + return -mid - 1; +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ + +/*******************************************************************************/ + +/* + * If numNewItems == 0 then expand the list by the number of items + * indicated by its allocation policy. + * If numNewItems > 0 then expand the list by exactly the number of + * items indicated. + * If numNewItems < 0 then expand the list by the absolute value of + * numNewItems plus the number of items indicated by its allocation + * policy. + * Returns 1 for success, 0 if out of memory +*/ +static int ExpandListSpace (list_t list, int numNewItems) +{ + if (numNewItems == 0) { + numNewItems = NUMITEMSPERALLOC (list); + } else if (numNewItems < 0) { + numNewItems = (-numNewItems) + NUMITEMSPERALLOC (list); + } + + if (SetHandleSize ((Handle) list, + sizeof (ListStruct) + + ((*list)->listSize + + numNewItems) * (*list)->itemSize)) { + (*list)->listSize += numNewItems; + return 1; + } else { + return 0; + } +} + +/*******************************/ + +#ifdef CFG_ALL_LIST_FUNCTIONS + +/* + * This function reallocate the list, minus any currently unused + * portion of its allotted memory. + */ +void ListCompact (list_t list) +{ + + if (!SetHandleSize ((Handle) list, + sizeof (ListStruct) + + (*list)->numItems * (*list)->itemSize)) { + return; + } + + (*list)->listSize = (*list)->numItems; +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ + +/*******************************/ + +list_t ListCreate (int elementSize) +{ + list_t list; + + list = (list_t) (NewHandle (sizeof (ListStruct))); /* create empty list */ + if (list) { + (*list)->signature = LIST_SIGNATURE; + (*list)->numItems = 0; + (*list)->listSize = 0; + (*list)->itemSize = elementSize; + (*list)->percentIncrease = kDefaultAllocationPercentIncrease; + (*list)->minNumItemsIncrease = + kDefaultAllocationminNumItemsIncrease; + } + + return list; +} + +/*******************************/ + +void ListSetAllocationPolicy (list_t list, int minItemsPerAlloc, + int percentIncreasePerAlloc) +{ + (*list)->percentIncrease = percentIncreasePerAlloc; + (*list)->minNumItemsIncrease = minItemsPerAlloc; +} + +/*******************************/ + +void ListDispose (list_t list) +{ + DisposeHandle ((Handle) list); +} +/*******************************/ + +#ifdef CFG_ALL_LIST_FUNCTIONS + +void ListDisposePtrList (list_t list) +{ + int index; + int numItems; + + if (list) { + numItems = ListNumItems (list); + + for (index = 1; index <= numItems; index++) + free (*(void **) ListGetPtrToItem (list, index)); + + ListDispose (list); + } +} + +/*******************************/ + +/* + * keeps memory, resets the number of items to 0 + */ +void ListClear (list_t list) +{ + if (!list) + return; + (*list)->numItems = 0; +} + +/*******************************/ + +/* + * copy is only as large as necessary + */ +list_t ListCopy (list_t originalList) +{ + list_t tempList = NULL; + int numItems; + + if (!originalList) + return NULL; + + tempList = ListCreate ((*originalList)->itemSize); + if (tempList) { + numItems = ListNumItems (originalList); + + if (!SetHandleSize ((Handle) tempList, + sizeof (ListStruct) + + numItems * (*tempList)->itemSize)) { + ListDispose (tempList); + return NULL; + } + + (*tempList)->numItems = (*originalList)->numItems; + (*tempList)->listSize = (*originalList)->numItems; + (*tempList)->itemSize = (*originalList)->itemSize; + (*tempList)->percentIncrease = (*originalList)->percentIncrease; + (*tempList)->minNumItemsIncrease = + (*originalList)->minNumItemsIncrease; + + memcpy (ITEMPTR (tempList, 0), ITEMPTR (originalList, 0), + numItems * (*tempList)->itemSize); + } + + return tempList; +} + +/********************************/ + +/* + * list1 = list1 + list2 + */ +int ListAppend (list_t list1, list_t list2) +{ + int numItemsL1, numItemsL2; + + if (!list2) + return 1; + + if (!list1) + return 0; + if ((*list1)->itemSize != (*list2)->itemSize) + return 0; + + numItemsL1 = ListNumItems (list1); + numItemsL2 = ListNumItems (list2); + + if (numItemsL2 == 0) + return 1; + + if (!SetHandleSize ((Handle) list1, + sizeof (ListStruct) + (numItemsL1 + numItemsL2) * + (*list1)->itemSize)) { + return 0; + } + + (*list1)->numItems = numItemsL1 + numItemsL2; + (*list1)->listSize = numItemsL1 + numItemsL2; + + memmove (ITEMPTR (list1, numItemsL1), + ITEMPTR (list2, 0), + numItemsL2 * (*list2)->itemSize); + + return 1; +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ + +/*******************************/ + +/* + * returns 1 if the item is inserted, returns 0 if out of memory or + * bad arguments were passed. + */ +int ListInsertItem (list_t list, void *ptrToItem, int itemPosition) +{ + return ListInsertItems (list, ptrToItem, itemPosition, 1); +} + +/*******************************/ + +int ListInsertItems (list_t list, void *ptrToItems, int firstItemPosition, + int numItemsToInsert) +{ + int numItems = (*list)->numItems; + + if (firstItemPosition == numItems + 1) + firstItemPosition = LIST_END; + else if (firstItemPosition > numItems) + return 0; + + if ((*list)->numItems >= (*list)->listSize) { + if (!ExpandListSpace (list, -numItemsToInsert)) + return 0; + } + + if (firstItemPosition == LIST_START) { + if (numItems == 0) { + /* special case for empty list */ + firstItemPosition = LIST_END; + } else { + firstItemPosition = 1; + } + } + + if (firstItemPosition == LIST_END) { /* add at the end of the list */ + if (ptrToItems) + memcpy (ITEMPTR (list, numItems), ptrToItems, + (*list)->itemSize * numItemsToInsert); + else + memset (ITEMPTR (list, numItems), 0, + (*list)->itemSize * numItemsToInsert); + + (*list)->numItems += numItemsToInsert; + } else { /* move part of list up to make room for new item */ + memmove (ITEMPTR (list, firstItemPosition - 1 + numItemsToInsert), + ITEMPTR (list, firstItemPosition - 1), + (numItems + 1 - firstItemPosition) * (*list)->itemSize); + + if (ptrToItems) + memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems, + (*list)->itemSize * numItemsToInsert); + else + memset (ITEMPTR (list, firstItemPosition - 1), 0, + (*list)->itemSize * numItemsToInsert); + + (*list)->numItems += numItemsToInsert; + } + + return 1; +} + +#ifdef CFG_ALL_LIST_FUNCTIONS + +/*******************************/ + +int ListEqual (list_t list1, list_t list2) +{ + if (list1 == list2) + return 1; + + if (list1 == NULL || list2 == NULL) + return 0; + + if ((*list1)->itemSize == (*list1)->itemSize) { + if ((*list1)->numItems == (*list2)->numItems) { + return (memcmp (ITEMPTR (list1, 0), ITEMPTR (list2, 0), + (*list1)->itemSize * (*list1)->numItems) == 0); + } + } + + return 0; +} + +/*******************************/ + +/* + * The item pointed to by ptrToItem is copied over the current item + * at itemPosition + */ +void ListReplaceItem (list_t list, void *ptrToItem, int itemPosition) +{ + ListReplaceItems (list, ptrToItem, itemPosition, 1); +} + +/*******************************/ + +/* + * The item pointed to by ptrToItems is copied over the current item + * at itemPosition + */ +void ListReplaceItems ( list_t list, void *ptrToItems, + int firstItemPosition, int numItemsToReplace) +{ + + if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; + else if (firstItemPosition == LIST_START) + firstItemPosition = 1; + + memmove (ITEMPTR (list, firstItemPosition - 1), ptrToItems, + (*list)->itemSize * numItemsToReplace); +} + +/*******************************/ + +void ListGetItem (list_t list, void *itemDestination, int itemPosition) +{ + ListGetItems (list, itemDestination, itemPosition, 1); +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ + +/*******************************/ + +#if defined(CFG_ALL_LIST_FUNCTIONS) || defined(CFG_DEVICE_DEREGISTER) + +void ListRemoveItem (list_t list, void *itemDestination, int itemPosition) +{ + ListRemoveItems (list, itemDestination, itemPosition, 1); +} + +/*******************************/ + +void ListRemoveItems (list_t list, void *itemsDestination, + int firstItemPosition, int numItemsToRemove) +{ + int firstItemAfterChunk, numToMove; + + if (firstItemPosition == LIST_START) + firstItemPosition = 1; + else if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; + + if (itemsDestination != NULL) + memcpy (itemsDestination, ITEMPTR (list, firstItemPosition - 1), + (*list)->itemSize * numItemsToRemove); + + firstItemAfterChunk = firstItemPosition + numItemsToRemove; + numToMove = (*list)->numItems - (firstItemAfterChunk - 1); + + if (numToMove > 0) { + /* + * move part of list down to cover hole left by removed item + */ + memmove (ITEMPTR (list, firstItemPosition - 1), + ITEMPTR (list, firstItemAfterChunk - 1), + (*list)->itemSize * numToMove); + } + + (*list)->numItems -= numItemsToRemove; +} +#endif /* CFG_ALL_LIST_FUNCTIONS || CFG_DEVICE_DEREGISTER */ + +/*******************************/ + +void ListGetItems (list_t list, void *itemsDestination, + int firstItemPosition, int numItemsToGet) +{ + + if (firstItemPosition == LIST_START) + firstItemPosition = 1; + else if (firstItemPosition == LIST_END) + firstItemPosition = (*list)->numItems; + + memcpy (itemsDestination, + ITEMPTR (list, firstItemPosition - 1), + (*list)->itemSize * numItemsToGet); +} + +/*******************************/ + +/* + * Returns a pointer to the item at itemPosition. returns null if an + * errors occurred. + */ +void *ListGetPtrToItem (list_t list, int itemPosition) +{ + if (itemPosition == LIST_START) + itemPosition = 1; + else if (itemPosition == LIST_END) + itemPosition = (*list)->numItems; + + return ITEMPTR (list, itemPosition - 1); +} + +/*******************************/ + +/* + * returns a pointer the lists data (abstraction violation for + * optimization) + */ +void *ListGetDataPtr (list_t list) +{ + return &((*list)->itemList[0]); +} + +/********************************/ + +#ifdef CFG_ALL_LIST_FUNCTIONS + +int ListApplyToEach (list_t list, int ascending, + ListApplicationFunc funcToApply, + void *callbackData) +{ + int result = 0, index; + + if (!list || !funcToApply) + goto Error; + + if (ascending) { + for (index = 1; index <= ListNumItems (list); index++) { + result = funcToApply (index, + ListGetPtrToItem (list, index), + callbackData); + if (result < 0) + goto Error; + } + } else { + for (index = ListNumItems (list); + index > 0 && index <= ListNumItems (list); + index--) { + result = funcToApply (index, + ListGetPtrToItem (list, index), + callbackData); + if (result < 0) + goto Error; + } + } + +Error: + return result; +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ + +/********************************/ + +int ListGetItemSize (list_t list) +{ + return (*list)->itemSize; +} + +/********************************/ + +int ListNumItems (list_t list) +{ + return (*list)->numItems; +} + +/*******************************/ + +#ifdef CFG_ALL_LIST_FUNCTIONS + +void ListRemoveDuplicates (list_t list, CompareFunction compareFunction) +{ + int numItems, index, startIndexForFind, duplicatesIndex; + + numItems = ListNumItems (list); + + for (index = 1; index < numItems; index++) { + startIndexForFind = index + 1; + while (startIndexForFind <= numItems) { + duplicatesIndex = + ListFindItem (list, + ListGetPtrToItem (list, index), + startIndexForFind, + compareFunction); + if (duplicatesIndex > 0) { + ListRemoveItem (list, NULL, duplicatesIndex); + numItems--; + startIndexForFind = duplicatesIndex; + } else { + break; + } + } + } +} + +/*******************************/ + + +/*******************************/ + +int ListFindItem (list_t list, void *ptrToItem, int startingPosition, + CompareFunction compareFunction) +{ + int numItems, size, index, cmp; + void *listItemPtr; + + if ((numItems = (*list)->numItems) == 0) + return 0; + + size = (*list)->itemSize; + + if (startingPosition == LIST_START) + startingPosition = 1; + else if (startingPosition == LIST_END) + startingPosition = numItems; + + for (index = startingPosition; index <= numItems; index++) { + listItemPtr = ITEMPTR (list, index - 1); + cmp = compareFunction + ? compareFunction (ptrToItem, listItemPtr) + : ListMemBlockCmp (ptrToItem, listItemPtr, size); + if (cmp == 0) + return index; + } + + return 0; +} + +/*******************************/ + +int ShortCompare (void *a, void *b) +{ + if (*(short *) a < *(short *) b) + return -1; + if (*(short *) a > *(short *) b) + return 1; + return 0; +} + +/*******************************/ + +int IntCompare (void *a, void *b) +{ + if (*(int *) a < *(int *) b) + return -1; + if (*(int *) a > *(int *) b) + return 1; + return 0; +} + +/*******************************/ + +int CStringCompare (void *a, void *b) +{ + return strcmp (*(char **) a, *(char **) b); +} + +/*******************************/ + + +int ListBinSearch (list_t list, void *ptrToItem, + CompareFunction compareFunction) +{ + int index; + + index = BinSearch (ITEMPTR (list, 0), + (int) (*list)->numItems, + (int) (*list)->itemSize, ptrToItem, + compareFunction); + + if (index >= 0) + index++; /* lists start from 1 */ + else + index = 0; /* item not found */ + + return index; +} + +/**************************************************************************/ + +/* + * Reserves memory for numItems in the list. If it succeeds then + * numItems items can be inserted without possibility of an out of + * memory error (useful to simplify error recovery in complex + * functions). Returns 1 if success, 0 if out of memory. + */ +int ListPreAllocate (list_t list, int numItems) +{ + if ((*list)->listSize - (*list)->numItems < numItems) { + return ExpandListSpace (list, + numItems - ((*list)->listSize - + (*list)->numItems)); + } else { + return 1; /* enough items are already pre-allocated */ + } +} + +#endif /* CFG_ALL_LIST_FUNCTIONS */ diff --git a/package/uboot-ifxmips/files/lib_bootstrap/string.c b/package/uboot-ifxmips/files/lib_bootstrap/string.c new file mode 100644 index 0000000000..e0b793abbe --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/string.c @@ -0,0 +1,578 @@ +/* + * linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in + * + * These are buggy as well.. + * + * * Fri Jun 25 1999, Ingo Oeser + * - Added strsep() which will replace strtok() soon (because strsep() is + * reentrant and should be faster). Use only strsep() in new code, please. + */ + +#include +#include +#include +#include + + +#if 0 /* not used - was: #ifndef __HAVE_ARCH_STRNICMP */ +/** + * strnicmp - Case insensitive, length-limited string comparison + * @s1: One string + * @s2: The other string + * @len: the maximum number of characters to compare + */ +int strnicmp(const char *s1, const char *s2, size_t len) +{ + /* Yes, Virginia, it had better be unsigned */ + unsigned char c1, c2; + + c1 = 0; c2 = 0; + if (len) { + do { + c1 = *s1; c2 = *s2; + s1++; s2++; + if (!c1) + break; + if (!c2) + break; + if (c1 == c2) + continue; + c1 = tolower(c1); + c2 = tolower(c2); + if (c1 != c2) + break; + } while (--len); + } + return (int)c1 - (int)c2; +} +#endif + +char * ___strtok; + +#ifndef __HAVE_ARCH_STRCPY +/** + * strcpy - Copy a %NUL terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + */ +char * strcpy(char * dest,const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCPY +/** + * strncpy - Copy a length-limited, %NUL-terminated string + * @dest: Where to copy the string to + * @src: Where to copy the string from + * @count: The maximum number of bytes to copy + * + * Note that unlike userspace strncpy, this does not %NUL-pad the buffer. + * However, the result is not %NUL-terminated if the source exceeds + * @count bytes. + */ +char * strncpy(char * dest,const char *src,size_t count) +{ + char *tmp = dest; + + while (count-- && (*dest++ = *src++) != '\0') + /* nothing */; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCAT +/** + * strcat - Append one %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + */ +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCAT +/** + * strncat - Append a length-limited, %NUL-terminated string to another + * @dest: The string to be appended to + * @src: The string to append to it + * @count: The maximum numbers of bytes to copy + * + * Note that in contrast to strncpy, strncat ensures the result is + * terminated. + */ +char * strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) { + *dest = '\0'; + break; + } + } + } + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCMP +/** + * strcmp - Compare two strings + * @cs: One string + * @ct: Another string + */ +int strcmp(const char * cs,const char * ct) +{ + register signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRNCMP +/** + * strncmp - Compare two length-limited strings + * @cs: One string + * @ct: Another string + * @count: The maximum number of bytes to compare + */ +int strncmp(const char * cs,const char * ct,size_t count) +{ + register signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRCHR +/** + * strchr - Find the first occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_STRRCHR +/** + * strrchr - Find the last occurrence of a character in a string + * @s: The string to be searched + * @c: The character to search for + */ +char * strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRLEN +/** + * strlen - Find the length of a string + * @s: The string to be sized + */ +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRNLEN +/** + * strnlen - Find the length of a length-limited string + * @s: The string to be sized + * @count: The maximum number of bytes to search + */ +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRDUP +char * strdup(const char *s) +{ + char *new; + + if ((s == NULL) || + ((new = malloc (strlen(s) + 1)) == NULL) ) { + return NULL; + } + + strcpy (new, s); + return new; +} +#endif + +#ifndef __HAVE_ARCH_STRSPN +/** + * strspn - Calculate the length of the initial substring of @s which only + * contain letters in @accept + * @s: The string to be searched + * @accept: The string to search for + */ +size_t strspn(const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) { + if (*p == *a) + break; + } + if (*a == '\0') + return count; + ++count; + } + + return count; +} +#endif + +#ifndef __HAVE_ARCH_STRPBRK +/** + * strpbrk - Find the first occurrence of a set of characters + * @cs: The string to be searched + * @ct: The characters to search for + */ +char * strpbrk(const char * cs,const char * ct) +{ + const char *sc1,*sc2; + + for( sc1 = cs; *sc1 != '\0'; ++sc1) { + for( sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *) sc1; + } + } + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRTOK +/** + * strtok - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * WARNING: strtok is deprecated, use strsep instead. + */ +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} +#endif + +#ifndef __HAVE_ARCH_STRSEP +/** + * strsep - Split a string into tokens + * @s: The string to be searched + * @ct: The characters to search for + * + * strsep() updates @s to point after the token, ready for the next call. + * + * It returns empty tokens, too, behaving exactly like the libc function + * of that name. In fact, it was stolen from glibc2 and de-fancy-fied. + * Same semantics, slimmer shape. ;) + */ +char * strsep(char **s, const char *ct) +{ + char *sbegin = *s, *end; + + if (sbegin == NULL) + return NULL; + + end = strpbrk(sbegin, ct); + if (end) + *end++ = '\0'; + *s = end; + + return sbegin; +} +#endif + +#ifndef __HAVE_ARCH_STRSWAB +/** + * strswab - swap adjacent even and odd bytes in %NUL-terminated string + * s: address of the string + * + * returns the address of the swapped string or NULL on error. If + * string length is odd, last byte is untouched. + */ +char *strswab(const char *s) +{ + char *p, *q; + + if ((NULL == s) || ('\0' == *s)) { + return (NULL); + } + + for (p=(char *)s, q=p+1; (*p != '\0') && (*q != '\0'); p+=2, q+=2) { + char tmp; + + tmp = *p; + *p = *q; + *q = tmp; + } + + return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_MEMSET +/** + * memset - Fill a region of memory with the given value + * @s: Pointer to the start of the area. + * @c: The byte to fill the area with + * @count: The size of the area. + * + * Do not use memset() to access IO space, use memset_io() instead. + */ +void * memset(void * s,int c,size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} +#endif + +#ifndef __HAVE_ARCH_BCOPY +/** + * bcopy - Copy one area of memory to another + * @src: Where to copy from + * @dest: Where to copy to + * @count: The size of the area. + * + * Note that this is the same as memcpy(), with the arguments reversed. + * memcpy() is the standard, bcopy() is a legacy BSD function. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +char * bcopy(const char * src, char * dest, int count) +{ + char *tmp = dest; + + while (count--) + *tmp++ = *src++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCPY +/** + * memcpy - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * You should not use this function to access IO space, use memcpy_toio() + * or memcpy_fromio() instead. + */ +void * memcpy(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMMOVE +/** + * memmove - Copy one area of memory to another + * @dest: Where to copy to + * @src: Where to copy from + * @count: The size of the area. + * + * Unlike memcpy(), memmove() copes with overlapping areas. + */ +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCMP +/** + * memcmp - Compare two areas of memory + * @cs: One area of memory + * @ct: Another area of memory + * @count: The size of the area. + */ +int memcmp(const void * cs,const void * ct,size_t count) +{ + const unsigned char *su1, *su2; + int res = 0; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} +#endif + +#ifndef __HAVE_ARCH_MEMSCAN +/** + * memscan - Find a character in an area of memory. + * @addr: The memory area + * @c: The byte to search for + * @size: The size of the area. + * + * returns the address of the first occurrence of @c, or 1 byte past + * the area if @c is not found + */ +void * memscan(void * addr, int c, size_t size) +{ + unsigned char * p = (unsigned char *) addr; + + while (size) { + if (*p == c) + return (void *) p; + p++; + size--; + } + return (void *) p; +} +#endif + +#ifndef __HAVE_ARCH_STRSTR +/** + * strstr - Find the first substring in a %NUL terminated string + * @s1: The string to be searched + * @s2: The string to search for + */ +char * strstr(const char * s1,const char * s2) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *) s1; + s1++; + } + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_MEMCHR +/** + * memchr - Find a character in an area of memory. + * @s: The memory area + * @c: The byte to search for + * @n: The size of the area. + * + * returns the address of the first occurrence of @c, or %NULL + * if @c is not found + */ +void *memchr(const void *s, int c, size_t n) +{ + const unsigned char *p = s; + while (n-- != 0) { + if ((unsigned char)c == *p++) { + return (void *)(p-1); + } + } + return NULL; +} + +#endif diff --git a/package/uboot-ifxmips/files/lib_bootstrap/time.c b/package/uboot-ifxmips/files/lib_bootstrap/time.c new file mode 100644 index 0000000000..cd8dc721e2 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/time.c @@ -0,0 +1,99 @@ +/* + * (C) Copyright 2003 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + + +static inline void mips_compare_set(u32 v) +{ + asm volatile ("mtc0 %0, $11" : : "r" (v)); +} + +static inline void mips_count_set(u32 v) +{ + asm volatile ("mtc0 %0, $9" : : "r" (v)); +} + + +static inline u32 mips_count_get(void) +{ + u32 count; + + asm volatile ("mfc0 %0, $9" : "=r" (count) :); + return count; +} + +/* + * timer without interrupts + */ + +int timer_init(void) +{ + mips_compare_set(0); + mips_count_set(0); + + return 0; +} + +void reset_timer(void) +{ + mips_count_set(0); +} + +ulong get_timer(ulong base) +{ + return mips_count_get() - base; +} + +void set_timer(ulong t) +{ + mips_count_set(t); +} + +void udelay (unsigned long usec) +{ + ulong tmo; + ulong start = get_timer(0); + + tmo = usec * (CFG_HZ / 1000000); + while ((ulong)((mips_count_get() - start)) < tmo) + /*NOP*/; +} + +/* + * This function is derived from PowerPC code (read timebase as long long). + * On MIPS it just returns the timer value. + */ +unsigned long long get_ticks(void) +{ + return mips_count_get(); +} + +/* + * This function is derived from PowerPC code (timebase clock frequency). + * On MIPS it returns the number of timer ticks per second. + */ +ulong get_tbclk(void) +{ + return CFG_HZ; +} diff --git a/package/uboot-ifxmips/files/lib_bootstrap/vsprintf.c b/package/uboot-ifxmips/files/lib_bootstrap/vsprintf.c new file mode 100644 index 0000000000..2740f2e769 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_bootstrap/vsprintf.c @@ -0,0 +1,385 @@ +/* + * linux/lib/vsprintf.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* vsprintf.c -- Lars Wirzenius & Linus Torvalds. */ +/* + * Wirzenius wrote this portably, Torvalds fucked it up :-) + */ + +#include +#include +#include +#include + +#include +#if !defined (CONFIG_PANIC_HANG) +#include +/*cmd_boot.c*/ +extern int do_reset (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]); +#endif + +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + +#ifdef CFG_64BIT_STRTOUL +unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int base) +{ + unsigned long long result = 0, value; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit (cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + while (isxdigit (*cp) && (value = isdigit (*cp) + ? *cp - '0' + : (islower (*cp) ? toupper (*cp) : *cp) - 'A' + 10) < base) { + result = result * base + value; + cp++; + } + if (endp) + *endp = (char *) cp; + return result; +} +#endif /* CFG_64BIT_STRTOUL */ + +/* we use this so that we can do without the ctype library */ +#define is_digit(c) ((c) >= '0' && (c) <= '9') + +static int skip_atoi(const char **s) +{ + int i=0; + + while (is_digit(**s)) + i = i*10 + *((*s)++) - '0'; + return i; +} + +#define ZEROPAD 1 /* pad with zero */ +#define SIGN 2 /* unsigned/signed long */ +#define PLUS 4 /* show plus */ +#define SPACE 8 /* space if plus */ +#define LEFT 16 /* left justified */ +#define SPECIAL 32 /* 0x */ +#define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ + +#define do_div(n,base) ({ \ + int __res; \ + __res = ((unsigned long) n) % (unsigned) base; \ + n = ((unsigned long) n) / (unsigned) base; \ + __res; \ +}) + +#ifdef CFG_64BIT_VSPRINTF +static char * number(char * str, long long num, int base, int size, int precision ,int type) +#else +static char * number(char * str, long num, int base, int size, int precision ,int type) +#endif +{ + char c,sign,tmp[66]; + const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; + int i; + + if (type & LARGE) + digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + if (type & LEFT) + type &= ~ZEROPAD; + if (base < 2 || base > 36) + return 0; + c = (type & ZEROPAD) ? '0' : ' '; + sign = 0; + if (type & SIGN) { + if (num < 0) { + sign = '-'; + num = -num; + size--; + } else if (type & PLUS) { + sign = '+'; + size--; + } else if (type & SPACE) { + sign = ' '; + size--; + } + } + if (type & SPECIAL) { + if (base == 16) + size -= 2; + else if (base == 8) + size--; + } + i = 0; + if (num == 0) + tmp[i++]='0'; + else while (num != 0) + tmp[i++] = digits[do_div(num,base)]; + if (i > precision) + precision = i; + size -= precision; + if (!(type&(ZEROPAD+LEFT))) + while(size-->0) + *str++ = ' '; + if (sign) + *str++ = sign; + if (type & SPECIAL) { + if (base==8) + *str++ = '0'; + else if (base==16) { + *str++ = '0'; + *str++ = digits[33]; + } + } + if (!(type & LEFT)) + while (size-- > 0) + *str++ = c; + while (i < precision--) + *str++ = '0'; + while (i-- > 0) + *str++ = tmp[i]; + while (size-- > 0) + *str++ = ' '; + return str; +} + +/* Forward decl. needed for IP address printing stuff... */ +int sprintf(char * buf, const char *fmt, ...); + +int vsprintf(char *buf, const char *fmt, va_list args) +{ + int len; +#ifdef CFG_64BIT_VSPRINTF + unsigned long long num; +#else + unsigned long num; +#endif + int i, base; + char * str; + const char *s; + + int flags; /* flags to number() */ + + int field_width; /* width of output field */ + int precision; /* min. # of digits for integers; max + number of chars for from string */ + int qualifier; /* 'h', 'l', or 'q' for integer fields */ + + for (str=buf ; *fmt ; ++fmt) { + if (*fmt != '%') { + *str++ = *fmt; + continue; + } + + /* process flags */ + flags = 0; + repeat: + ++fmt; /* this also skips first '%' */ + switch (*fmt) { + case '-': flags |= LEFT; goto repeat; + case '+': flags |= PLUS; goto repeat; + case ' ': flags |= SPACE; goto repeat; + case '#': flags |= SPECIAL; goto repeat; + case '0': flags |= ZEROPAD; goto repeat; + } + + /* get field width */ + field_width = -1; + if (is_digit(*fmt)) + field_width = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + field_width = va_arg(args, int); + if (field_width < 0) { + field_width = -field_width; + flags |= LEFT; + } + } + + /* get the precision */ + precision = -1; + if (*fmt == '.') { + ++fmt; + if (is_digit(*fmt)) + precision = skip_atoi(&fmt); + else if (*fmt == '*') { + ++fmt; + /* it's the next argument */ + precision = va_arg(args, int); + } + if (precision < 0) + precision = 0; + } + + /* get the conversion qualifier */ + qualifier = -1; + if (*fmt == 'h' || *fmt == 'l' || *fmt == 'q') { + qualifier = *fmt; + ++fmt; + } + + /* default base */ + base = 10; + + switch (*fmt) { + case 'c': + if (!(flags & LEFT)) + while (--field_width > 0) + *str++ = ' '; + *str++ = (unsigned char) va_arg(args, int); + while (--field_width > 0) + *str++ = ' '; + continue; + + case 's': + s = va_arg(args, char *); + if (!s) + s = ""; + + len = strnlen(s, precision); + + if (!(flags & LEFT)) + while (len < field_width--) + *str++ = ' '; + for (i = 0; i < len; ++i) + *str++ = *s++; + while (len < field_width--) + *str++ = ' '; + continue; + + case 'p': + if (field_width == -1) { + field_width = 2*sizeof(void *); + flags |= ZEROPAD; + } + str = number(str, + (unsigned long) va_arg(args, void *), 16, + field_width, precision, flags); + continue; + + + case 'n': + if (qualifier == 'l') { + long * ip = va_arg(args, long *); + *ip = (str - buf); + } else { + int * ip = va_arg(args, int *); + *ip = (str - buf); + } + continue; + + case '%': + *str++ = '%'; + continue; + + /* integer number formats - set up the flags and "break" */ + case 'o': + base = 8; + break; + + case 'X': + flags |= LARGE; + case 'x': + base = 16; + break; + + case 'd': + case 'i': + flags |= SIGN; + case 'u': + break; + + default: + *str++ = '%'; + if (*fmt) + *str++ = *fmt; + else + --fmt; + continue; + } +#ifdef CFG_64BIT_VSPRINTF + if (qualifier == 'q') /* "quad" for 64 bit variables */ + num = va_arg(args, unsigned long long); + else +#endif + if (qualifier == 'l') + num = va_arg(args, unsigned long); + else if (qualifier == 'h') { + num = (unsigned short) va_arg(args, int); + if (flags & SIGN) + num = (short) num; + } else if (flags & SIGN) + num = va_arg(args, int); + else + num = va_arg(args, unsigned int); + str = number(str, num, base, field_width, precision, flags); + } + *str = '\0'; + return str-buf; +} + +int sprintf(char * buf, const char *fmt, ...) +{ + va_list args; + int i; + + va_start(args, fmt); + i=vsprintf(buf,fmt,args); + va_end(args); + return i; +} + +void panic(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vprintf(fmt, args); + putc('\n'); + va_end(args); +#if defined (CONFIG_PANIC_HANG) + hang(); +#else + udelay (100000); /* allow messages to go out */ + do_reset (NULL, 0, 0, NULL); +#endif +} diff --git a/package/uboot-ifxmips/files/lib_generic/LzmaDecode.c b/package/uboot-ifxmips/files/lib_generic/LzmaDecode.c new file mode 100644 index 0000000000..99d1117701 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_generic/LzmaDecode.c @@ -0,0 +1,600 @@ +/* + LzmaDecode.c + LZMA Decoder (optimized for Speed version) + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this Code, expressly permits you to + statically or dynamically link your Code (or bind by name) to the + interfaces of this file without subjecting your linked Code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifdef CONFIG_LZMA + +#include "LzmaDecode.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_READ_BYTE (*Buffer++) + +#define RC_INIT2 Code = 0; Range = 0xFFFFFFFF; \ + { int i; for(i = 0; i < 5; i++) { RC_TEST; Code = (Code << 8) | RC_READ_BYTE; }} + +#ifdef _LZMA_IN_CB + +#define RC_TEST { if (Buffer == BufferLim) \ + { SizeT size; int result = InCallback->Read(InCallback, &Buffer, &size); if (result != LZMA_RESULT_OK) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return result; } \ + BufferLim = Buffer + size; if (size == 0) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } }} + +#define RC_INIT Buffer = BufferLim = 0; RC_INIT2 + +#else + +#define RC_TEST { if (Buffer == BufferLim) { printf("ERROR, %s, %d\n", __FILE__, __LINE__); return LZMA_RESULT_DATA_ERROR; } } + +#define RC_INIT(buffer, bufferSize) Buffer = buffer; BufferLim = buffer + bufferSize; RC_INIT2 + +#endif + +#define RC_NORMALIZE if (Range < kTopValue) { RC_TEST; Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; } + +#define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound) +#define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits; +#define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits; + +#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \ + { UpdateBit0(p); mi <<= 1; A0; } else \ + { UpdateBit1(p); mi = (mi + mi) + 1; A1; } + +#define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;) + +#define RangeDecoderBitTreeDecode(probs, numLevels, res) \ + { int i = numLevels; res = 1; \ + do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \ + res -= (1 << numLevels); } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumMidBits 3 +#define kLenNumMidSymbols (1 << kLenNumMidBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenChoice 0 +#define LenChoice2 (LenChoice + 1) +#define LenLow (LenChoice2 + 1) +#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) +#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + + +#define kNumStates 12 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 + +#define IsMatch 0 +#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define IsRep0Long (IsRepG2 + kNumStates) +#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) +#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) +#define LenCoder (Align + kAlignTableSize) +#define RepLenCoder (LenCoder + kNumLenProbs) +#define Literal (RepLenCoder + kNumLenProbs) + +#if Literal != LZMA_BASE_SIZE +StopCompilingDueBUG +#endif + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size) +{ + unsigned char prop0; + if (size < LZMA_PROPERTIES_SIZE) + { + printf("ERROR: %s, %d\n", __FILE__, __LINE__); + return LZMA_RESULT_DATA_ERROR; + } + prop0 = propsData[0]; + if (prop0 >= (9 * 5 * 5)) + { + printf("ERROR: %s, %d\n", __FILE__, __LINE__); + return LZMA_RESULT_DATA_ERROR; + } + { + for (propsRes->pb = 0; prop0 >= (9 * 5); propsRes->pb++, prop0 -= (9 * 5)); + for (propsRes->lp = 0; prop0 >= 9; propsRes->lp++, prop0 -= 9); + propsRes->lc = prop0; + /* + unsigned char remainder = (unsigned char)(prop0 / 9); + propsRes->lc = prop0 % 9; + propsRes->pb = remainder / 5; + propsRes->lp = remainder % 5; + */ + } + + #ifdef _LZMA_OUT_READ + { + int i; + propsRes->DictionarySize = 0; + for (i = 0; i < 4; i++) + propsRes->DictionarySize += (UInt32)(propsData[1 + i]) << (i * 8); + if (propsRes->DictionarySize == 0) + propsRes->DictionarySize = 1; + } + #endif + return LZMA_RESULT_OK; +} + +#define kLzmaStreamWasFinishedId (-1) + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *InCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed) +{ + CProb *p = vs->Probs; + SizeT nowPos = 0; + Byte previousByte = 0; + UInt32 posStateMask = (1 << (vs->Properties.pb)) - 1; + UInt32 literalPosMask = (1 << (vs->Properties.lp)) - 1; + int lc = vs->Properties.lc; + + #ifdef _LZMA_OUT_READ + + UInt32 Range = vs->Range; + UInt32 Code = vs->Code; + #ifdef _LZMA_IN_CB + const Byte *Buffer = vs->Buffer; + const Byte *BufferLim = vs->BufferLim; + #else + const Byte *Buffer = inStream; + const Byte *BufferLim = inStream + inSize; + #endif + int state = vs->State; + UInt32 rep0 = vs->Reps[0], rep1 = vs->Reps[1], rep2 = vs->Reps[2], rep3 = vs->Reps[3]; + int len = vs->RemainLen; + UInt32 globalPos = vs->GlobalPos; + UInt32 distanceLimit = vs->DistanceLimit; + + Byte *dictionary = vs->Dictionary; + UInt32 dictionarySize = vs->Properties.DictionarySize; + UInt32 dictionaryPos = vs->DictionaryPos; + + Byte tempDictionary[4]; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + if (len == kLzmaStreamWasFinishedId) + return LZMA_RESULT_OK; + + if (dictionarySize == 0) + { + dictionary = tempDictionary; + dictionarySize = 1; + tempDictionary[0] = vs->TempDictionary[0]; + } + + if (len == kLzmaNeedInitId) + { + { + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + UInt32 i; + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + rep0 = rep1 = rep2 = rep3 = 1; + state = 0; + globalPos = 0; + distanceLimit = 0; + dictionaryPos = 0; + dictionary[dictionarySize - 1] = 0; + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + } + len = 0; + } + while(len != 0 && nowPos < outSize) + { + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + outStream[nowPos++] = dictionary[dictionaryPos] = dictionary[pos]; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + len--; + } + if (dictionaryPos == 0) + previousByte = dictionary[dictionarySize - 1]; + else + previousByte = dictionary[dictionaryPos - 1]; + + #else /* if !_LZMA_OUT_READ */ + + int state = 0; + UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1; + int len = 0; + const Byte *Buffer; + const Byte *BufferLim; + UInt32 Range; + UInt32 Code; + + #ifndef _LZMA_IN_CB + *inSizeProcessed = 0; + #endif + *outSizeProcessed = 0; + + { + UInt32 i; + UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (lc + vs->Properties.lp)); + for (i = 0; i < numProbs; i++) + p[i] = kBitModelTotal >> 1; + } + + #ifdef _LZMA_IN_CB + RC_INIT; + #else + RC_INIT(inStream, inSize); + #endif + + #endif /* _LZMA_OUT_READ */ + + while(nowPos < outSize) + { + CProb *prob; + UInt32 bound; + int posState = (int)( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & posStateMask); + + prob = p + IsMatch + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + int symbol = 1; + UpdateBit0(prob) + prob = p + Literal + (LZMA_LIT_SIZE * + ((( + (nowPos + #ifdef _LZMA_OUT_READ + + globalPos + #endif + ) + & literalPosMask) << lc) + (previousByte >> (8 - lc)))); + + if (state >= kNumLitStates) + { + int matchByte; + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + matchByte = dictionary[pos]; + #else + matchByte = outStream[nowPos - rep0]; + #endif + do + { + int bit; + CProb *probLit; + matchByte <<= 1; + bit = (matchByte & 0x100); + probLit = prob + 0x100 + bit + symbol; + RC_GET_BIT2(probLit, symbol, if (bit != 0) break, if (bit == 0) break) + } + while (symbol < 0x100); + } + while (symbol < 0x100) + { + CProb *probLit = prob + symbol; + RC_GET_BIT(probLit, symbol) + } + previousByte = (Byte)symbol; + + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #endif + if (state < 4) state = 0; + else if (state < 10) state -= 3; + else state -= 6; + } + else + { + UpdateBit1(prob); + prob = p + IsRep + state; + IfBit0(prob) + { + UpdateBit0(prob); + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + state = state < kNumLitStates ? 0 : 3; + prob = p + LenCoder; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG0 + state; + IfBit0(prob) + { + UpdateBit0(prob); + prob = p + IsRep0Long + (state << kNumPosBitsMax) + posState; + IfBit0(prob) + { + #ifdef _LZMA_OUT_READ + UInt32 pos; + #endif + UpdateBit0(prob); + + #ifdef _LZMA_OUT_READ + if (distanceLimit == 0) + #else + if (nowPos == 0) + #endif + { + printf("ERROR: %s, %d\n", __FILE__, __LINE__); + return LZMA_RESULT_DATA_ERROR; + } + + state = state < kNumLitStates ? 9 : 11; + #ifdef _LZMA_OUT_READ + pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + outStream[nowPos++] = previousByte; + #ifdef _LZMA_OUT_READ + if (distanceLimit < dictionarySize) + distanceLimit++; + #endif + + continue; + } + else + { + UpdateBit1(prob); + } + } + else + { + UInt32 distance; + UpdateBit1(prob); + prob = p + IsRepG1 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep1; + } + else + { + UpdateBit1(prob); + prob = p + IsRepG2 + state; + IfBit0(prob) + { + UpdateBit0(prob); + distance = rep2; + } + else + { + UpdateBit1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = p + RepLenCoder; + } + { + int numBits, offset; + CProb *probLen = prob + LenChoice; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenLow + (posState << kLenNumLowBits); + offset = 0; + numBits = kLenNumLowBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenChoice2; + IfBit0(probLen) + { + UpdateBit0(probLen); + probLen = prob + LenMid + (posState << kLenNumMidBits); + offset = kLenNumLowSymbols; + numBits = kLenNumMidBits; + } + else + { + UpdateBit1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols + kLenNumMidSymbols; + numBits = kLenNumHighBits; + } + } + RangeDecoderBitTreeDecode(probLen, numBits, len); + len += offset; + } + + if (state < 4) + { + int posSlot; + state += kNumLitStates; + prob = p + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + RangeDecoderBitTreeDecode(prob, kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + int numDirectBits = ((posSlot >> 1) - 1); + rep0 = (2 | ((UInt32)posSlot & 1)); + if (posSlot < kEndPosModelIndex) + { + rep0 <<= numDirectBits; + prob = p + SpecPos + rep0 - posSlot - 1; + } + else + { + numDirectBits -= kNumAlignBits; + do + { + RC_NORMALIZE + Range >>= 1; + rep0 <<= 1; + if (Code >= Range) + { + Code -= Range; + rep0 |= 1; + } + } + while (--numDirectBits != 0); + prob = p + Align; + rep0 <<= kNumAlignBits; + numDirectBits = kNumAlignBits; + } + { + int i = 1; + int mi = 1; + do + { + CProb *prob3 = prob + mi; + RC_GET_BIT2(prob3, mi, ; , rep0 |= i); + i <<= 1; + } + while(--numDirectBits != 0); + } + } + else + rep0 = posSlot; + if (++rep0 == (UInt32)(0)) + { + /* it's for stream version */ + len = kLzmaStreamWasFinishedId; + break; + } + } + + len += kMatchMinLen; + #ifdef _LZMA_OUT_READ + if (rep0 > distanceLimit) + #else + if (rep0 > nowPos) + #endif + { + printf("ERROR: %s, %d\n", __FILE__, __LINE__); + return LZMA_RESULT_DATA_ERROR; + } + + #ifdef _LZMA_OUT_READ + if (dictionarySize - distanceLimit > (UInt32)len) + distanceLimit += len; + else + distanceLimit = dictionarySize; + #endif + + do + { + #ifdef _LZMA_OUT_READ + UInt32 pos = dictionaryPos - rep0; + if (pos >= dictionarySize) + pos += dictionarySize; + previousByte = dictionary[pos]; + dictionary[dictionaryPos] = previousByte; + if (++dictionaryPos == dictionarySize) + dictionaryPos = 0; + #else + previousByte = outStream[nowPos - rep0]; + #endif + len--; + outStream[nowPos++] = previousByte; + } + while(len != 0 && nowPos < outSize); + } + } + RC_NORMALIZE; + + #ifdef _LZMA_OUT_READ + vs->Range = Range; + vs->Code = Code; + vs->DictionaryPos = dictionaryPos; + vs->GlobalPos = globalPos + (UInt32)nowPos; + vs->DistanceLimit = distanceLimit; + vs->Reps[0] = rep0; + vs->Reps[1] = rep1; + vs->Reps[2] = rep2; + vs->Reps[3] = rep3; + vs->State = state; + vs->RemainLen = len; + vs->TempDictionary[0] = tempDictionary[0]; + #endif + + #ifdef _LZMA_IN_CB + vs->Buffer = Buffer; + vs->BufferLim = BufferLim; + #else + *inSizeProcessed = (SizeT)(Buffer - inStream); + #endif + *outSizeProcessed = nowPos; + return LZMA_RESULT_OK; +} + +#endif /* CONFIG_LZMA */ diff --git a/package/uboot-ifxmips/files/lib_generic/LzmaDecode.h b/package/uboot-ifxmips/files/lib_generic/LzmaDecode.h new file mode 100644 index 0000000000..2870eeb9c9 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_generic/LzmaDecode.h @@ -0,0 +1,113 @@ +/* + LzmaDecode.h + LZMA Decoder interface + + LZMA SDK 4.40 Copyright (c) 1999-2006 Igor Pavlov (2006-05-01) + http://www.7-zip.org/ + + LZMA SDK is licensed under two licenses: + 1) GNU Lesser General Public License (GNU LGPL) + 2) Common Public License (CPL) + It means that you can select one of these two licenses and + follow rules of that license. + + SPECIAL EXCEPTION: + Igor Pavlov, as the author of this code, expressly permits you to + statically or dynamically link your code (or bind by name) to the + interfaces of this file without subjecting your linked code to the + terms of the CPL or GNU LGPL. Any modifications or additions + to this file, however, are subject to the LGPL or CPL terms. +*/ + +#ifndef __LZMADECODE_H +#define __LZMADECODE_H + +#include "LzmaTypes.h" + +/* #define _LZMA_IN_CB */ +/* Use callback for input data */ + +/* #define _LZMA_OUT_READ */ +/* Use read function for output data */ + +/* #define _LZMA_PROB32 */ +/* It can increase speed on some 32-bit CPUs, + but memory usage will be doubled in that case */ + +/* #define _LZMA_LOC_OPT */ +/* Enable local speed optimizations inside code */ + +#ifdef _LZMA_PROB32 +#define CProb UInt32 +#else +#define CProb UInt16 +#endif + +#define LZMA_RESULT_OK 0 +#define LZMA_RESULT_DATA_ERROR 1 + +#ifdef _LZMA_IN_CB +typedef struct _ILzmaInCallback +{ + int (*Read)(void *object, const unsigned char **buffer, SizeT *bufferSize); +} ILzmaInCallback; +#endif + +#define LZMA_BASE_SIZE 1846 +#define LZMA_LIT_SIZE 768 + +#define LZMA_PROPERTIES_SIZE 5 + +typedef struct _CLzmaProperties +{ + int lc; + int lp; + int pb; + #ifdef _LZMA_OUT_READ + UInt32 DictionarySize; + #endif +}CLzmaProperties; + +int LzmaDecodeProperties(CLzmaProperties *propsRes, const unsigned char *propsData, int size); + +#define LzmaGetNumProbs(Properties) (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((Properties)->lc + (Properties)->lp))) + +#define kLzmaNeedInitId (-2) + +typedef struct _CLzmaDecoderState +{ + CLzmaProperties Properties; + CProb *Probs; + + #ifdef _LZMA_IN_CB + const unsigned char *Buffer; + const unsigned char *BufferLim; + #endif + + #ifdef _LZMA_OUT_READ + unsigned char *Dictionary; + UInt32 Range; + UInt32 Code; + UInt32 DictionaryPos; + UInt32 GlobalPos; + UInt32 DistanceLimit; + UInt32 Reps[4]; + int State; + int RemainLen; + unsigned char TempDictionary[4]; + #endif +} CLzmaDecoderState; + +#ifdef _LZMA_OUT_READ +#define LzmaDecoderInit(vs) { (vs)->RemainLen = kLzmaNeedInitId; } +#endif + +int LzmaDecode(CLzmaDecoderState *vs, + #ifdef _LZMA_IN_CB + ILzmaInCallback *inCallback, + #else + const unsigned char *inStream, SizeT inSize, SizeT *inSizeProcessed, + #endif + unsigned char *outStream, SizeT outSize, SizeT *outSizeProcessed); + +#endif diff --git a/package/uboot-ifxmips/files/lib_generic/LzmaTypes.h b/package/uboot-ifxmips/files/lib_generic/LzmaTypes.h new file mode 100644 index 0000000000..288c5e45d7 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_generic/LzmaTypes.h @@ -0,0 +1,45 @@ +/* +LzmaTypes.h + +Types for LZMA Decoder + +This file written and distributed to public domain by Igor Pavlov. +This file is part of LZMA SDK 4.40 (2006-05-01) +*/ + +#ifndef __LZMATYPES_H +#define __LZMATYPES_H + +#ifndef _7ZIP_BYTE_DEFINED +#define _7ZIP_BYTE_DEFINED +typedef unsigned char Byte; +#endif + +#ifndef _7ZIP_UINT16_DEFINED +#define _7ZIP_UINT16_DEFINED +typedef unsigned short UInt16; +#endif + +#ifndef _7ZIP_UINT32_DEFINED +#define _7ZIP_UINT32_DEFINED +#ifdef _LZMA_UINT32_IS_ULONG +typedef unsigned long UInt32; +#else +typedef unsigned int UInt32; +#endif +#endif + +/* #define _LZMA_SYSTEM_SIZE_T */ +/* Use system's size_t. You can use it to enable 64-bit sizes supporting */ + +#ifndef _7ZIP_SIZET_DEFINED +#define _7ZIP_SIZET_DEFINED +#ifdef _LZMA_SYSTEM_SIZE_T +#include +typedef size_t SizeT; +#else +typedef UInt32 SizeT; +#endif +#endif + +#endif diff --git a/package/uboot-ifxmips/files/lib_generic/LzmaWrapper.c b/package/uboot-ifxmips/files/lib_generic/LzmaWrapper.c new file mode 100644 index 0000000000..6c3d702461 --- /dev/null +++ b/package/uboot-ifxmips/files/lib_generic/LzmaWrapper.c @@ -0,0 +1,197 @@ +/****************************************************************************** +** +** FILE NAME : LzmaWrapper.c +** PROJECT : bootloader +** MODULES : U-boot +** +** DATE : 2 Nov 2006 +** AUTHOR : Lin Mars +** DESCRIPTION : LZMA decoder support for U-boot 1.1.5 +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Date $Author $Comment +** 2 Nov 2006 Lin Mars init version which derived from LzmaTest.c from +** LZMA v4.43 SDK +*******************************************************************************/ +#define LZMA_NO_STDIO +#ifndef LZMA_NO_STDIO +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_LZMA + +#include "LzmaDecode.h" +#include "LzmaWrapper.h" + +static const char *kCantReadMessage = "Can not read from source buffer"; +static const char *kCantAllocateMessage = "Not enough buffer for decompression"; + +static size_t rpos=0, dpos=0; + +static int MyReadFileAndCheck(unsigned char *src, void *dest, size_t size) +{ + if (size == 0) + return 0; + memcpy(dest, src + rpos, size); + rpos += size; + return 1; +} + +int lzma_inflate(unsigned char *source, int s_len, unsigned char *dest, int *d_len) +{ + /* We use two 32-bit integers to construct 64-bit integer for file size. + You can remove outSizeHigh, if you don't need >= 4GB supporting, + or you can use UInt64 outSize, if your compiler supports 64-bit integers*/ + UInt32 outSize = 0; + UInt32 outSizeHigh = 0; + SizeT outSizeFull; + unsigned char *outStream; + + int waitEOS = 1; + /* waitEOS = 1, if there is no uncompressed size in headers, + so decoder will wait EOS (End of Stream Marker) in compressed stream */ + + SizeT compressedSize; + unsigned char *inStream; + + CLzmaDecoderState state; /* it's about 24-80 bytes structure, if int is 32-bit */ + unsigned char properties[LZMA_PROPERTIES_SIZE]; + + int res; + + if (sizeof(UInt32) < 4) + { + printf("LZMA decoder needs correct UInt32\n"); + return LZMA_RESULT_DATA_ERROR; + } + + { + long length=s_len; + if ((long)(SizeT)length != length) + { + printf("Too big compressed stream\n"); + return LZMA_RESULT_DATA_ERROR; + } + compressedSize = (SizeT)(length - (LZMA_PROPERTIES_SIZE + 8)); + } + + /* Read LZMA properties for compressed stream */ + + if (!MyReadFileAndCheck(source, properties, sizeof(properties))) + { + printf("%s\n", kCantReadMessage); + return LZMA_RESULT_DATA_ERROR; + } + + /* Read uncompressed size */ + { + int i; + for (i = 0; i < 8; i++) + { + unsigned char b; + if (!MyReadFileAndCheck(source, &b, 1)) + { + printf("%s\n", kCantReadMessage); + return LZMA_RESULT_DATA_ERROR; + } + if (b != 0xFF) + waitEOS = 0; + if (i < 4) + outSize += (UInt32)(b) << (i * 8); + else + outSizeHigh += (UInt32)(b) << ((i - 4) * 8); + } + + if (waitEOS) + { + printf("Stream with EOS marker is not supported"); + return LZMA_RESULT_DATA_ERROR; + } + outSizeFull = (SizeT)outSize; + if (sizeof(SizeT) >= 8) + outSizeFull |= (((SizeT)outSizeHigh << 16) << 16); + else if (outSizeHigh != 0 || (UInt32)(SizeT)outSize != outSize) + { + printf("Too big uncompressed stream"); + return LZMA_RESULT_DATA_ERROR; + } + } + + /* Decode LZMA properties and allocate memory */ + if (LzmaDecodeProperties(&state.Properties, properties, LZMA_PROPERTIES_SIZE) != LZMA_RESULT_OK) + { + printf("Incorrect stream properties"); + return LZMA_RESULT_DATA_ERROR; + } + state.Probs = (CProb *)malloc(LzmaGetNumProbs(&state.Properties) * sizeof(CProb)); + + if (outSizeFull == 0) + outStream = 0; + else + { + if (outSizeFull > d_len) + outStream = 0; + else + outStream = dest; + } + + if (compressedSize == 0) + inStream = 0; + else + { + if ((compressedSize+rpos) > s_len ) + inStream = 0; + else + inStream = source + rpos; + } + + if (state.Probs == 0 + || (outStream == 0 && outSizeFull != 0) + || (inStream == 0 && compressedSize != 0) + ) + { + free(state.Probs); + printf("%s\n", kCantAllocateMessage); + return LZMA_RESULT_DATA_ERROR; + } + + /* Decompress */ + { + SizeT inProcessed; + SizeT outProcessed; + res = LzmaDecode(&state, + inStream, compressedSize, &inProcessed, + outStream, outSizeFull, &outProcessed); + if (res != 0) + { + printf("\nDecoding error = %d\n", res); + res = 1; + } + else + { + *d_len = outProcessed; + } + } + + free(state.Probs); + return res; +} + +#endif /* CONFIG_LZMA */ diff --git a/package/uboot-ifxmips/files/net/ifx_eth.c b/package/uboot-ifxmips/files/net/ifx_eth.c new file mode 100644 index 0000000000..02e72aef3d --- /dev/null +++ b/package/uboot-ifxmips/files/net/ifx_eth.c @@ -0,0 +1,4 @@ + +#define IFX_ETH_INITIALIZE_EXTERN extern int danube_switch_initialize(bd_t *); +#define IFX_ETH_INITIALIZE(bd_t) danube_switch_initialize(bd_t); + diff --git a/package/uboot-ifxmips/files/net/net_danube.c b/package/uboot-ifxmips/files/net/net_danube.c new file mode 100644 index 0000000000..1d1c98f3c2 --- /dev/null +++ b/package/uboot-ifxmips/files/net/net_danube.c @@ -0,0 +1,1754 @@ +/* + * Copied from Linux Monitor (LiMon) - Networking. + * + * Copyright 1994 - 2000 Neil Russell. + * (See License) + * Copyright 2000 Roland Borde + * Copyright 2000 Paolo Scaffardi + * Copyright 2000-2002 Wolfgang Denk, wd@denx.de + */ + +/* + * General Desription: + * + * The user interface supports commands for BOOTP, RARP, and TFTP. + * Also, we support ARP internally. Depending on available data, + * these interact as follows: + * + * BOOTP: + * + * Prerequisites: - own ethernet address + * We want: - own IP address + * - TFTP server IP address + * - name of bootfile + * Next step: ARP + * + * RARP: + * + * Prerequisites: - own ethernet address + * We want: - own IP address + * - TFTP server IP address + * Next step: ARP + * + * ARP: + * + * Prerequisites: - own ethernet address + * - own IP address + * - TFTP server IP address + * We want: - TFTP server ethernet address + * Next step: TFTP + * + * DHCP: + * + * Prerequisites: - own ethernet address + * We want: - IP, Netmask, ServerIP, Gateway IP + * - bootfilename, lease time + * Next step: - TFTP + * + * TFTP: + * + * Prerequisites: - own ethernet address + * - own IP address + * - TFTP server IP address + * - TFTP server ethernet address + * - name of bootfile (if unknown, we use a default name + * derived from our own IP address) + * We want: - load the boot file + * Next step: none + * + * NFS: + * + * Prerequisites: - own ethernet address + * - own IP address + * - name of bootfile (if unknown, we use a default name + * derived from our own IP address) + * We want: - load the boot file + * Next step: none + * + * SNTP: + * + * Prerequisites: - own ethernet address + * - own IP address + * We want: - network time + * Next step: none + */ + + +#include +#include +#include +#include +#include "bootp.h" +#include "tftp.h" +#include "rarp.h" +#include "nfs.h" +#ifdef CONFIG_STATUS_LED +#include +#include +#endif +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) +#include "sntp.h" +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +DECLARE_GLOBAL_DATA_PTR; + +#define ARP_TIMEOUT 5 /* Seconds before trying ARP again */ +#ifndef CONFIG_NET_RETRY_COUNT +# define ARP_TIMEOUT_COUNT 5 /* # of timeouts before giving up */ +#else +# define ARP_TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT) +#endif + +#if 0 +#define ET_DEBUG +#endif + +/** BOOTP EXTENTIONS **/ + +IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */ +IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */ +IPaddr_t NetOurDNSIP=0; /* Our DNS IP address */ +#if (CONFIG_BOOTP_MASK & CONFIG_BOOTP_DNS2) +IPaddr_t NetOurDNS2IP=0; /* Our 2nd DNS IP address */ +#endif +char NetOurNISDomain[32]={0,}; /* Our NIS domain */ +char NetOurHostName[32]={0,}; /* Our hostname */ +char NetOurRootPath[64]={0,}; /* Our bootpath */ +ushort NetBootFileSize=0; /* Our bootfile size in blocks */ + +/** END OF BOOTP EXTENTIONS **/ + +ulong NetBootFileXferSize; /* The actual transferred size of the bootfile (in bytes) */ +uchar NetOurEther[6]; /* Our ethernet address */ +uchar NetServerEther[6] = /* Boot server enet address */ + { 0, 0, 0, 0, 0, 0 }; +IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */ +IPaddr_t NetServerIP; /* Our IP addr (0 = unknown) */ +volatile uchar *NetRxPkt; /* Current receive packet */ +int NetRxPktLen; /* Current rx packet length */ +unsigned NetIPID; /* IP packet ID */ +uchar NetBcastAddr[6] = /* Ethernet bcast address */ + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; +uchar NetEtherNullAddr[6] = + { 0, 0, 0, 0, 0, 0 }; +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +uchar NetCDPAddr[6] = /* Ethernet bcast address */ + { 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc }; +#endif +int NetState; /* Network loop state */ +#ifdef CONFIG_NET_MULTI +int NetRestartWrap = 0; /* Tried all network devices */ +static int NetRestarted = 0; /* Network loop restarted */ +static int NetDevExists = 0; /* At least one device configured */ +#endif + +/* XXX in both little & big endian machines 0xFFFF == ntohs(-1) */ +ushort NetOurVLAN = 0xFFFF; /* default is without VLAN */ +ushort NetOurNativeVLAN = 0xFFFF; /* ditto */ + +char BootFile[128]; /* Boot File name */ + +#if (CONFIG_COMMANDS & CFG_CMD_PING) +IPaddr_t NetPingIP; /* the ip address to ping */ + +static void PingStart(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_CDP) +static void CDPStart(void); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) +IPaddr_t NetNtpServerIP; /* NTP server IP address */ +int NetTimeOffset=0; /* offset time from UTC */ +#endif + +#ifdef CONFIG_NETCONSOLE +void NcStart(void); +int nc_input_packet(uchar *pkt, unsigned dest, unsigned src, unsigned len); +#endif + +volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN]; + +volatile uchar *NetRxPackets[PKTBUFSRX]; /* Receive packets */ + +static rxhand_f *packetHandler; /* Current RX packet handler */ +static thand_f *timeHandler; /* Current timeout handler */ +static ulong timeStart; /* Time base value */ +static ulong timeDelta; /* Current timeout value */ +volatile uchar *NetTxPacket = 0; /* THE transmit packet */ + +static int net_check_prereq (proto_t protocol); + +/**********************************************************************/ + +IPaddr_t NetArpWaitPacketIP; +IPaddr_t NetArpWaitReplyIP; +uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */ +uchar *NetArpWaitTxPacket; /* THE transmit packet */ +int NetArpWaitTxPacketSize; +uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN]; +ulong NetArpWaitTimerStart; +int NetArpWaitTry; + +void ArpRequest (void) +{ + int i; + volatile uchar *pkt; + ARP_t *arp; + +#ifdef ET_DEBUG + printf ("ARP broadcast %d\n", NetArpWaitTry); +#endif + pkt = NetTxPacket; + + pkt += NetSetEther (pkt, NetBcastAddr, PROT_ARP); + + arp = (ARP_t *) pkt; + + arp->ar_hrd = htons (ARP_ETHER); + arp->ar_pro = htons (PROT_IP); + arp->ar_hln = 6; + arp->ar_pln = 4; + arp->ar_op = htons (ARPOP_REQUEST); + + memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */ + NetWriteIP ((uchar *) & arp->ar_data[6], NetOurIP); /* source IP addr */ + for (i = 10; i < 16; ++i) { + arp->ar_data[i] = 0; /* dest ET addr = 0 */ + } + + if ((NetArpWaitPacketIP & NetOurSubnetMask) != + (NetOurIP & NetOurSubnetMask)) { + if (NetOurGatewayIP == 0) { + puts ("## Warning: gatewayip needed but not set\n"); + NetArpWaitReplyIP = NetArpWaitPacketIP; + } else { + NetArpWaitReplyIP = NetOurGatewayIP; + } + } else { + NetArpWaitReplyIP = NetArpWaitPacketIP; + } + + NetWriteIP ((uchar *) & arp->ar_data[16], NetArpWaitReplyIP); + (void) eth_send (NetTxPacket, (pkt - NetTxPacket) + ARP_HDR_SIZE); +} + +void ArpTimeoutCheck(void) +{ + ulong t; + + if (!NetArpWaitPacketIP) + return; + + t = get_timer(0); + + /* check for arp timeout */ + if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ) { + NetArpWaitTry++; + + if (NetArpWaitTry >= ARP_TIMEOUT_COUNT) { + puts ("\nARP Retry count exceeded; starting again\n"); + NetArpWaitTry = 0; + NetStartAgain(); + } else { + NetArpWaitTimerStart = t; + ArpRequest(); + } + } +} + +/**********************************************************************/ +/* + * Main network processing loop. + */ + +int +NetLoop(proto_t protocol) +{ + bd_t *bd = gd->bd; + +#ifdef CONFIG_NET_MULTI + NetRestarted = 0; + NetDevExists = 0; +#endif + + /* XXX problem with bss workaround */ + NetArpWaitPacketMAC = NULL; + NetArpWaitTxPacket = NULL; + NetArpWaitPacketIP = 0; + NetArpWaitReplyIP = 0; + NetArpWaitTxPacket = NULL; + NetTxPacket = NULL; + + if (!NetTxPacket) { + int i; + /* + * Setup packet buffers, aligned correctly. + */ + NetTxPacket = &PktBuf[0] + (PKTALIGN - 1); + NetTxPacket -= (ulong)NetTxPacket % PKTALIGN; + for (i = 0; i < PKTBUFSRX; i++) { + NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN; + } + } + + if (!NetArpWaitTxPacket) { + NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1); + NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN; + NetArpWaitTxPacketSize = 0; + } + + eth_halt(); +#ifdef CONFIG_NET_MULTI + eth_set_current(); +#endif + if (eth_init(bd) < 0) { + eth_halt(); + return(-1); + } + +restart: +#ifdef CONFIG_NET_MULTI + memcpy (NetOurEther, eth_get_dev()->enetaddr, 6); +#else + memcpy (NetOurEther, bd->bi_enetaddr, 6); +#endif + + NetState = NETLOOP_CONTINUE; + + /* + * Start the ball rolling with the given start function. From + * here on, this code is a state machine driven by received + * packets and timer events. + */ + + switch (protocol) { +#if (CONFIG_COMMANDS & CFG_CMD_NFS) + case NFS: +#endif +#if (CONFIG_COMMANDS & CFG_CMD_PING) + case PING: +#endif +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) + case SNTP: +#endif + case NETCONS: + case TFTP: + NetCopyIP(&NetOurIP, &bd->bi_ip_addr); + NetOurGatewayIP = getenv_IPaddr ("gatewayip"); + NetOurSubnetMask= getenv_IPaddr ("netmask"); + NetOurVLAN = getenv_VLAN("vlan"); + NetOurNativeVLAN = getenv_VLAN("nvlan"); + + switch (protocol) { +#if (CONFIG_COMMANDS & CFG_CMD_NFS) + case NFS: +#endif + case NETCONS: + case TFTP: + NetServerIP = getenv_IPaddr ("serverip"); + break; +#if (CONFIG_COMMANDS & CFG_CMD_PING) + case PING: + /* nothing */ + break; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) + case SNTP: + /* nothing */ + break; +#endif + default: + break; + } + + break; + case BOOTP: + case RARP: + /* + * initialize our IP addr to 0 in order to accept ANY + * IP addr assigned to us by the BOOTP / RARP server + */ + NetOurIP = 0; + NetServerIP = getenv_IPaddr ("serverip"); + NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ + NetOurNativeVLAN = getenv_VLAN("nvlan"); + case CDP: + NetOurVLAN = getenv_VLAN("vlan"); /* VLANs must be read */ + NetOurNativeVLAN = getenv_VLAN("nvlan"); + break; + default: + break; + } + + switch (net_check_prereq (protocol)) { + case 1: + /* network not configured */ + eth_halt(); + return (-1); + +#ifdef CONFIG_NET_MULTI + case 2: + /* network device not configured */ + break; +#endif /* CONFIG_NET_MULTI */ + + case 0: +#ifdef CONFIG_NET_MULTI + NetDevExists = 1; +#endif + switch (protocol) { + case TFTP: + /* always use ARP to get server ethernet address */ + TftpStart(); + break; + +#if (CONFIG_COMMANDS & CFG_CMD_DHCP) + case DHCP: + /* Start with a clean slate... */ + BootpTry = 0; + NetOurIP = 0; + NetServerIP = getenv_IPaddr ("serverip"); + DhcpRequest(); /* Basically same as BOOTP */ + break; +#endif /* CFG_CMD_DHCP */ + + case BOOTP: + BootpTry = 0; + BootpRequest (); + break; + + case RARP: + RarpTry = 0; + RarpRequest (); + break; +#if (CONFIG_COMMANDS & CFG_CMD_PING) + case PING: + PingStart(); + break; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_NFS) + case NFS: + NfsStart(); + break; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + case CDP: + CDPStart(); + break; +#endif +#ifdef CONFIG_NETCONSOLE + case NETCONS: + NcStart(); + break; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) + case SNTP: + SntpStart(); + break; +#endif + default: + break; + } + + NetBootFileXferSize = 0; + break; + } + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +#if defined(CFG_FAULT_ECHO_LINK_DOWN) && defined(CONFIG_STATUS_LED) && defined(STATUS_LED_RED) + /* + * Echo the inverted link state to the fault LED. + */ + if(miiphy_link(eth_get_dev()->name, CFG_FAULT_MII_ADDR)) { + status_led_set (STATUS_LED_RED, STATUS_LED_OFF); + } else { + status_led_set (STATUS_LED_RED, STATUS_LED_ON); + } +#endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */ +#endif /* CONFIG_MII, ... */ + + /* + * Main packet reception loop. Loop receiving packets until + * someone sets `NetState' to a state that terminates. + */ + for (;;) { + WATCHDOG_RESET(); +#ifdef CONFIG_SHOW_ACTIVITY + { + extern void show_activity(int arg); + show_activity(1); + } +#endif + /* + * Check the ethernet for a new packet. The ethernet + * receive routine will process it. + */ + eth_rx(); + + /* + * Abort if ctrl-c was pressed. + */ + if (ctrlc()) { + eth_halt(); + puts ("\nAbort\n"); + return (-1); + } + + ArpTimeoutCheck(); + + /* + * Check for a timeout, and run the timeout handler + * if we have one. + */ + if (timeHandler && ((get_timer(0) - timeStart) > timeDelta)) { + thand_f *x; + +#if defined(CONFIG_MII) || (CONFIG_COMMANDS & CFG_CMD_MII) +# if defined(CFG_FAULT_ECHO_LINK_DOWN) && \ + defined(CONFIG_STATUS_LED) && \ + defined(STATUS_LED_RED) + /* + * Echo the inverted link state to the fault LED. + */ + if(miiphy_link(eth_get_dev()->name, CFG_FAULT_MII_ADDR)) { + status_led_set (STATUS_LED_RED, STATUS_LED_OFF); + } else { + status_led_set (STATUS_LED_RED, STATUS_LED_ON); + } +# endif /* CFG_FAULT_ECHO_LINK_DOWN, ... */ +#endif /* CONFIG_MII, ... */ + x = timeHandler; + timeHandler = (thand_f *)0; + (*x)(); + } + + + switch (NetState) { + + case NETLOOP_RESTART: +#ifdef CONFIG_NET_MULTI + NetRestarted = 1; +#endif + goto restart; + + case NETLOOP_SUCCESS: + if (NetBootFileXferSize > 0) { + char buf[10]; + printf("Bytes transferred = %ld (%lx hex)\n", + NetBootFileXferSize, + NetBootFileXferSize); + sprintf(buf, "%lx", NetBootFileXferSize); + setenv("filesize", buf); + + sprintf(buf, "%lX", (unsigned long)load_addr); + setenv("fileaddr", buf); + } + eth_halt(); + return NetBootFileXferSize; + + case NETLOOP_FAIL: + return (-1); + } + } +} + +/**********************************************************************/ + +static void +startAgainTimeout(void) +{ + NetState = NETLOOP_RESTART; +} + +static void +startAgainHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + /* Totally ignore the packet */ +} + +void NetStartAgain (void) +{ + char *nretry; + int noretry = 0, once = 0; + + if ((nretry = getenv ("netretry")) != NULL) { + noretry = (strcmp (nretry, "no") == 0); + once = (strcmp (nretry, "once") == 0); + } + if (noretry) { + eth_halt (); + NetState = NETLOOP_FAIL; + return; + } +#ifndef CONFIG_NET_MULTI + NetSetTimeout (10 * CFG_HZ, startAgainTimeout); + NetSetHandler (startAgainHandler); +#else /* !CONFIG_NET_MULTI*/ + eth_halt (); + eth_try_another (!NetRestarted); + eth_init (gd->bd); + if (NetRestartWrap) { + NetRestartWrap = 0; + if (NetDevExists && !once) { + NetSetTimeout (10 * CFG_HZ, startAgainTimeout); + NetSetHandler (startAgainHandler); + } else { + NetState = NETLOOP_FAIL; + } + } else { + NetState = NETLOOP_RESTART; + } +#endif /* CONFIG_NET_MULTI */ +} + +/**********************************************************************/ +/* + * Miscelaneous bits. + */ + +void +NetSetHandler(rxhand_f * f) +{ + packetHandler = f; +} + + +void +NetSetTimeout(ulong iv, thand_f * f) +{ + if (iv == 0) { + timeHandler = (thand_f *)0; + } else { + timeHandler = f; + timeStart = get_timer(0); + timeDelta = iv; + } +} + + +void +NetSendPacket(volatile uchar * pkt, int len) +{ + (void) eth_send(pkt, len); +} + +int +NetSendUDPPacket(uchar *ether, IPaddr_t dest, int dport, int sport, int len) +{ + uchar *pkt; + + /* convert to new style broadcast */ + if (dest == 0) + dest = 0xFFFFFFFF; + + /* if broadcast, make the ether address a broadcast and don't do ARP */ + if (dest == 0xFFFFFFFF) + ether = NetBcastAddr; + + /* if MAC address was not discovered yet, save the packet and do an ARP request */ + if (memcmp(ether, NetEtherNullAddr, 6) == 0) { + +#ifdef ET_DEBUG + printf("sending ARP for %08lx\n", dest); +#endif + NetArpWaitPacketIP = dest; + NetArpWaitPacketMAC = ether; + + pkt = NetArpWaitTxPacket; + pkt += NetSetEther (pkt, NetArpWaitPacketMAC, PROT_IP); + + NetSetIP (pkt, dest, dport, sport, len); + memcpy(pkt + IP_HDR_SIZE, (uchar *)NetTxPacket + (pkt - (uchar *)NetArpWaitTxPacket) + IP_HDR_SIZE, len); + + /* size of the waiting packet */ + NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE + len; + + /* and do the ARP request */ + NetArpWaitTry = 1; + NetArpWaitTimerStart = get_timer(0); + ArpRequest(); + return 1; /* waiting */ + } + +#ifdef ET_DEBUG + printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n", + dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]); +#endif + + pkt = (uchar *)NetTxPacket; + pkt += NetSetEther (pkt, ether, PROT_IP); + NetSetIP (pkt, dest, dport, sport, len); + (void) eth_send(NetTxPacket, (pkt - NetTxPacket) + IP_HDR_SIZE + len); + + return 0; /* transmitted */ +} + +#if (CONFIG_COMMANDS & CFG_CMD_PING) +static ushort PingSeqNo; + +int PingSend(void) +{ + static uchar mac[6]; + volatile IP_t *ip; + volatile ushort *s; + uchar *pkt; + + /* XXX always send arp request */ + + memcpy(mac, NetEtherNullAddr, 6); + +#ifdef ET_DEBUG + printf("sending ARP for %08lx\n", NetPingIP); +#endif + + NetArpWaitPacketIP = NetPingIP; + NetArpWaitPacketMAC = mac; + + pkt = NetArpWaitTxPacket; + pkt += NetSetEther(pkt, mac, PROT_IP); + + ip = (volatile IP_t *)pkt; + + /* + * Construct an IP and ICMP header. (need to set no fragment bit - XXX) + */ + ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */ + ip->ip_tos = 0; + ip->ip_len = htons(IP_HDR_SIZE_NO_UDP + 8); + ip->ip_id = htons(NetIPID++); + ip->ip_off = htons(0x4000); /* No fragmentation */ + ip->ip_ttl = 255; + ip->ip_p = 0x01; /* ICMP */ + ip->ip_sum = 0; + NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ + NetCopyIP((void*)&ip->ip_dst, &NetPingIP); /* - "" - */ + ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); + + s = &ip->udp_src; /* XXX ICMP starts here */ + s[0] = htons(0x0800); /* echo-request, code */ + s[1] = 0; /* checksum */ + s[2] = 0; /* identifier */ + s[3] = htons(PingSeqNo++); /* sequence number */ + s[1] = ~NetCksum((uchar *)s, 8/2); + + /* size of the waiting packet */ + NetArpWaitTxPacketSize = (pkt - NetArpWaitTxPacket) + IP_HDR_SIZE_NO_UDP + 8; + + /* and do the ARP request */ + NetArpWaitTry = 1; + NetArpWaitTimerStart = get_timer(0); + ArpRequest(); + return 1; /* waiting */ +} + +static void +PingTimeout (void) +{ + eth_halt(); + NetState = NETLOOP_FAIL; /* we did not get the reply */ +} + +static void +PingHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + IPaddr_t tmp; + volatile IP_t *ip = (volatile IP_t *)pkt; + + tmp = NetReadIP((void *)&ip->ip_src); + if (tmp != NetPingIP) + return; + + NetState = NETLOOP_SUCCESS; +} + +static void PingStart(void) +{ +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif /* CONFIG_NET_MULTI */ + NetSetTimeout (10 * CFG_HZ, PingTimeout); + NetSetHandler (PingHandler); + + PingSend(); +} +#endif /* CFG_CMD_PING */ + +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + +#define CDP_DEVICE_ID_TLV 0x0001 +#define CDP_ADDRESS_TLV 0x0002 +#define CDP_PORT_ID_TLV 0x0003 +#define CDP_CAPABILITIES_TLV 0x0004 +#define CDP_VERSION_TLV 0x0005 +#define CDP_PLATFORM_TLV 0x0006 +#define CDP_NATIVE_VLAN_TLV 0x000a +#define CDP_APPLIANCE_VLAN_TLV 0x000e +#define CDP_TRIGGER_TLV 0x000f +#define CDP_POWER_CONSUMPTION_TLV 0x0010 +#define CDP_SYSNAME_TLV 0x0014 +#define CDP_SYSOBJECT_TLV 0x0015 +#define CDP_MANAGEMENT_ADDRESS_TLV 0x0016 + +#define CDP_TIMEOUT (CFG_HZ/4) /* one packet every 250ms */ + +static int CDPSeq; +static int CDPOK; + +ushort CDPNativeVLAN; +ushort CDPApplianceVLAN; + +static const uchar CDP_SNAP_hdr[8] = { 0xAA, 0xAA, 0x03, 0x00, 0x00, 0x0C, 0x20, 0x00 }; + +static ushort CDP_compute_csum(const uchar *buff, ushort len) +{ + ushort csum; + int odd; + ulong result = 0; + ushort leftover; + ushort *p; + + if (len > 0) { + odd = 1 & (ulong)buff; + if (odd) { + result = *buff << 8; + len--; + buff++; + } + while (len > 1) { + p = (ushort *)buff; + result += *p++; + buff = (uchar *)p; + if (result & 0x80000000) + result = (result & 0xFFFF) + (result >> 16); + len -= 2; + } + if (len) { + leftover = (signed short)(*(const signed char *)buff); + /* CISCO SUCKS big time! (and blows too): + * CDP uses the IP checksum algorithm with a twist; + * for the last byte it *sign* extends and sums. + */ + result = (result & 0xffff0000) | ((result + leftover) & 0x0000ffff); + } + while (result >> 16) + result = (result & 0xFFFF) + (result >> 16); + + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); + } + + /* add up 16-bit and 17-bit words for 17+c bits */ + result = (result & 0xffff) + (result >> 16); + /* add up 16-bit and 2-bit for 16+c bit */ + result = (result & 0xffff) + (result >> 16); + /* add up carry.. */ + result = (result & 0xffff) + (result >> 16); + + /* negate */ + csum = ~(ushort)result; + + /* run time endian detection */ + if (csum != htons(csum)) /* little endian */ + csum = htons(csum); + + return csum; +} + +int CDPSendTrigger(void) +{ + volatile uchar *pkt; + volatile ushort *s; + volatile ushort *cp; + Ethernet_t *et; + int len; + ushort chksum; +#if defined(CONFIG_CDP_DEVICE_ID) || defined(CONFIG_CDP_PORT_ID) || \ + defined(CONFIG_CDP_VERSION) || defined(CONFIG_CDP_PLATFORM) + char buf[32]; +#endif + + pkt = NetTxPacket; + et = (Ethernet_t *)pkt; + + /* NOTE: trigger sent not on any VLAN */ + + /* form ethernet header */ + memcpy(et->et_dest, NetCDPAddr, 6); + memcpy(et->et_src, NetOurEther, 6); + + pkt += ETHER_HDR_SIZE; + + /* SNAP header */ + memcpy((uchar *)pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)); + pkt += sizeof(CDP_SNAP_hdr); + + /* CDP header */ + *pkt++ = 0x02; /* CDP version 2 */ + *pkt++ = 180; /* TTL */ + s = (volatile ushort *)pkt; + cp = s; + *s++ = htons(0); /* checksum (0 for later calculation) */ + + /* CDP fields */ +#ifdef CONFIG_CDP_DEVICE_ID + *s++ = htons(CDP_DEVICE_ID_TLV); + *s++ = htons(CONFIG_CDP_DEVICE_ID); + memset(buf, 0, sizeof(buf)); + sprintf(buf, CONFIG_CDP_DEVICE_ID_PREFIX "%02X%02X%02X%02X%02X%02X", + NetOurEther[0] & 0xff, NetOurEther[1] & 0xff, + NetOurEther[2] & 0xff, NetOurEther[3] & 0xff, + NetOurEther[4] & 0xff, NetOurEther[5] & 0xff); + memcpy((uchar *)s, buf, 16); + s += 16 / 2; +#endif + +#ifdef CONFIG_CDP_PORT_ID + *s++ = htons(CDP_PORT_ID_TLV); + memset(buf, 0, sizeof(buf)); + sprintf(buf, CONFIG_CDP_PORT_ID, eth_get_dev_index()); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_CAPABILITIES + *s++ = htons(CDP_CAPABILITIES_TLV); + *s++ = htons(8); + *(ulong *)s = htonl(CONFIG_CDP_CAPABILITIES); + s += 2; +#endif + +#ifdef CONFIG_CDP_VERSION + *s++ = htons(CDP_VERSION_TLV); + memset(buf, 0, sizeof(buf)); + strcpy(buf, CONFIG_CDP_VERSION); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_PLATFORM + *s++ = htons(CDP_PLATFORM_TLV); + memset(buf, 0, sizeof(buf)); + strcpy(buf, CONFIG_CDP_PLATFORM); + len = strlen(buf); + if (len & 1) /* make it even */ + len++; + *s++ = htons(len + 4); + memcpy((uchar *)s, buf, len); + s += len / 2; +#endif + +#ifdef CONFIG_CDP_TRIGGER + *s++ = htons(CDP_TRIGGER_TLV); + *s++ = htons(8); + *(ulong *)s = htonl(CONFIG_CDP_TRIGGER); + s += 2; +#endif + +#ifdef CONFIG_CDP_POWER_CONSUMPTION + *s++ = htons(CDP_POWER_CONSUMPTION_TLV); + *s++ = htons(6); + *s++ = htons(CONFIG_CDP_POWER_CONSUMPTION); +#endif + + /* length of ethernet packet */ + len = (uchar *)s - ((uchar *)NetTxPacket + ETHER_HDR_SIZE); + et->et_protlen = htons(len); + + len = ETHER_HDR_SIZE + sizeof(CDP_SNAP_hdr); + chksum = CDP_compute_csum((uchar *)NetTxPacket + len, (uchar *)s - (NetTxPacket + len)); + if (chksum == 0) + chksum = 0xFFFF; + *cp = htons(chksum); + + (void) eth_send(NetTxPacket, (uchar *)s - NetTxPacket); + return 0; +} + +static void +CDPTimeout (void) +{ + CDPSeq++; + + if (CDPSeq < 3) { + NetSetTimeout (CDP_TIMEOUT, CDPTimeout); + CDPSendTrigger(); + return; + } + + /* if not OK try again */ + if (!CDPOK) + NetStartAgain(); + else + NetState = NETLOOP_SUCCESS; +} + +static void +CDPDummyHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + /* nothing */ +} + +static void +CDPHandler(const uchar * pkt, unsigned len) +{ + const uchar *t; + const ushort *ss; + ushort type, tlen; + uchar applid; + ushort vlan, nvlan; + + /* minimum size? */ + if (len < sizeof(CDP_SNAP_hdr) + 4) + goto pkt_short; + + /* check for valid CDP SNAP header */ + if (memcmp(pkt, CDP_SNAP_hdr, sizeof(CDP_SNAP_hdr)) != 0) + return; + + pkt += sizeof(CDP_SNAP_hdr); + len -= sizeof(CDP_SNAP_hdr); + + /* Version of CDP protocol must be >= 2 and TTL != 0 */ + if (pkt[0] < 0x02 || pkt[1] == 0) + return; + + /* if version is greater than 0x02 maybe we'll have a problem; output a warning */ + if (pkt[0] != 0x02) + printf("** WARNING: CDP packet received with a protocol version %d > 2\n", + pkt[0] & 0xff); + + if (CDP_compute_csum(pkt, len) != 0) + return; + + pkt += 4; + len -= 4; + + vlan = htons(-1); + nvlan = htons(-1); + while (len > 0) { + if (len < 4) + goto pkt_short; + + ss = (const ushort *)pkt; + type = ntohs(ss[0]); + tlen = ntohs(ss[1]); + if (tlen > len) { + goto pkt_short; + } + + pkt += tlen; + len -= tlen; + + ss += 2; /* point ss to the data of the TLV */ + tlen -= 4; + + switch (type) { + case CDP_DEVICE_ID_TLV: + break; + case CDP_ADDRESS_TLV: + break; + case CDP_PORT_ID_TLV: + break; + case CDP_CAPABILITIES_TLV: + break; + case CDP_VERSION_TLV: + break; + case CDP_PLATFORM_TLV: + break; + case CDP_NATIVE_VLAN_TLV: + nvlan = *ss; + break; + case CDP_APPLIANCE_VLAN_TLV: + t = (const uchar *)ss; + while (tlen > 0) { + if (tlen < 3) + goto pkt_short; + + applid = t[0]; + ss = (const ushort *)(t + 1); + +#ifdef CONFIG_CDP_APPLIANCE_VLAN_TYPE + if (applid == CONFIG_CDP_APPLIANCE_VLAN_TYPE) + vlan = *ss; +#else + vlan = ntohs(*ss); /* XXX will this work; dunno */ +#endif + t += 3; tlen -= 3; + } + break; + case CDP_TRIGGER_TLV: + break; + case CDP_POWER_CONSUMPTION_TLV: + break; + case CDP_SYSNAME_TLV: + break; + case CDP_SYSOBJECT_TLV: + break; + case CDP_MANAGEMENT_ADDRESS_TLV: + break; + } + } + + CDPApplianceVLAN = vlan; + CDPNativeVLAN = nvlan; + + CDPOK = 1; + return; + + pkt_short: + printf("** CDP packet is too short\n"); + return; +} + +static void CDPStart(void) +{ +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif + CDPSeq = 0; + CDPOK = 0; + + CDPNativeVLAN = htons(-1); + CDPApplianceVLAN = htons(-1); + + NetSetTimeout (CDP_TIMEOUT, CDPTimeout); + NetSetHandler (CDPDummyHandler); + + CDPSendTrigger(); +} +#endif /* CFG_CMD_CDP */ + + +void +NetReceive(volatile uchar * inpkt, int len) +{ + Ethernet_t *et; + IP_t *ip; + ARP_t *arp; + IPaddr_t tmp; + int x; + uchar *pkt; +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + int iscdp; +#endif + ushort cti = 0, vlanid = VLAN_NONE, myvlanid, mynvlanid; + +#ifdef ET_DEBUG + printf("packet received\n"); +#endif + + NetRxPkt = inpkt; + NetRxPktLen = len; + et = (Ethernet_t *)inpkt; + + /* too small packet? */ + if (len < ETHER_HDR_SIZE) + return; + +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + /* keep track if packet is CDP */ + iscdp = memcmp(et->et_dest, NetCDPAddr, 6) == 0; +#endif + + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; + mynvlanid = ntohs(NetOurNativeVLAN); + if (mynvlanid == (ushort)-1) + mynvlanid = VLAN_NONE; + + x = ntohs(et->et_protlen); + +#ifdef ET_DEBUG + printf("packet received\n"); +#endif + + if (x < 1514) { + /* + * Got a 802 packet. Check the other protocol field. + */ + x = ntohs(et->et_prot); + + ip = (IP_t *)(inpkt + E802_HDR_SIZE); + len -= E802_HDR_SIZE; + + } else if (x != PROT_VLAN) { /* normal packet */ + ip = (IP_t *)(inpkt + ETHER_HDR_SIZE); + len -= ETHER_HDR_SIZE; + + } else { /* VLAN packet */ + VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)et; + +#ifdef ET_DEBUG + printf("VLAN packet received\n"); +#endif + /* too small packet? */ + if (len < VLAN_ETHER_HDR_SIZE) + return; + + /* if no VLAN active */ + if ((ntohs(NetOurVLAN) & VLAN_IDMASK) == VLAN_NONE +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + && iscdp == 0 +#endif + ) + return; + + cti = ntohs(vet->vet_tag); + vlanid = cti & VLAN_IDMASK; + x = ntohs(vet->vet_type); + + ip = (IP_t *)(inpkt + VLAN_ETHER_HDR_SIZE); + len -= VLAN_ETHER_HDR_SIZE; + } + +#ifdef ET_DEBUG + printf("Receive from protocol 0x%x\n", x); +#endif + +#if (CONFIG_COMMANDS & CFG_CMD_CDP) + if (iscdp) { + CDPHandler((uchar *)ip, len); + return; + } +#endif + + if ((myvlanid & VLAN_IDMASK) != VLAN_NONE) { + if (vlanid == VLAN_NONE) + vlanid = (mynvlanid & VLAN_IDMASK); + /* not matched? */ + if (vlanid != (myvlanid & VLAN_IDMASK)) + return; + } + + switch (x) { + + case PROT_ARP: + /* + * We have to deal with two types of ARP packets: + * - REQUEST packets will be answered by sending our + * IP address - if we know it. + * - REPLY packates are expected only after we asked + * for the TFTP server's or the gateway's ethernet + * address; so if we receive such a packet, we set + * the server ethernet address + */ +#ifdef ET_DEBUG + puts ("Got ARP\n"); +#endif + arp = (ARP_t *)ip; + if (len < ARP_HDR_SIZE) { + printf("bad length %d < %d\n", len, ARP_HDR_SIZE); + return; + } + if (ntohs(arp->ar_hrd) != ARP_ETHER) { + return; + } + if (ntohs(arp->ar_pro) != PROT_IP) { + return; + } + if (arp->ar_hln != 6) { + return; + } + if (arp->ar_pln != 4) { + return; + } + + if (NetOurIP == 0) { + return; + } + + if (NetReadIP(&arp->ar_data[16]) != NetOurIP) { + return; + } + + switch (ntohs(arp->ar_op)) { + case ARPOP_REQUEST: /* reply with our IP address */ +#ifdef ET_DEBUG + puts ("Got ARP REQUEST, return our IP\n"); +#endif + pkt = (uchar *)et; + pkt += NetSetEther(pkt, et->et_src, PROT_ARP); + arp->ar_op = htons(ARPOP_REPLY); + memcpy (&arp->ar_data[10], &arp->ar_data[0], 6); + NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]); + memcpy (&arp->ar_data[ 0], NetOurEther, 6); + NetCopyIP(&arp->ar_data[ 6], &NetOurIP); + (void) eth_send((uchar *)et, (pkt - (uchar *)et) + ARP_HDR_SIZE); + return; + + case ARPOP_REPLY: /* arp reply */ + /* are we waiting for a reply */ + if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC) + break; +#ifdef ET_DEBUG + printf("Got ARP REPLY, set server/gtwy eth addr (%02x:%02x:%02x:%02x:%02x:%02x)\n", + arp->ar_data[0], arp->ar_data[1], + arp->ar_data[2], arp->ar_data[3], + arp->ar_data[4], arp->ar_data[5]); +#endif + + tmp = NetReadIP(&arp->ar_data[6]); + + /* matched waiting packet's address */ + if (tmp == NetArpWaitReplyIP) { +#ifdef ET_DEBUG + puts ("Got it\n"); +#endif + /* save address for later use */ + memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6); + +#ifdef CONFIG_NETCONSOLE + (*packetHandler)(0,0,0,0); +#endif + /* modify header, and transmit it */ + memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6); + (void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize); + + /* no arp request pending now */ + NetArpWaitPacketIP = 0; + NetArpWaitTxPacketSize = 0; + NetArpWaitPacketMAC = NULL; + + } + return; + default: +#ifdef ET_DEBUG + printf("Unexpected ARP opcode 0x%x\n", ntohs(arp->ar_op)); +#endif + return; + } + break; + + case PROT_RARP: +#ifdef ET_DEBUG + puts ("Got RARP\n"); +#endif + arp = (ARP_t *)ip; + if (len < ARP_HDR_SIZE) { + printf("bad length %d < %d\n", len, ARP_HDR_SIZE); + return; + } + + if ((ntohs(arp->ar_op) != RARPOP_REPLY) || + (ntohs(arp->ar_hrd) != ARP_ETHER) || + (ntohs(arp->ar_pro) != PROT_IP) || + (arp->ar_hln != 6) || (arp->ar_pln != 4)) { + + puts ("invalid RARP header\n"); + } else { + NetCopyIP(&NetOurIP, &arp->ar_data[16]); + if (NetServerIP == 0) + NetCopyIP(&NetServerIP, &arp->ar_data[ 6]); + memcpy (NetServerEther, &arp->ar_data[ 0], 6); + + (*packetHandler)(0,0,0,0); + } + break; + + case PROT_IP: +#ifdef ET_DEBUG + puts ("Got IP\n"); +#endif + if (len < IP_HDR_SIZE) { + debug ("len bad %d < %d\n", len, IP_HDR_SIZE); + return; + } + if (len < ntohs(ip->ip_len)) { + printf("len bad %d < %d\n", len, ntohs(ip->ip_len)); + return; + } + len = ntohs(ip->ip_len); +#ifdef ET_DEBUG + printf("len=%d, v=%02x\n", len, ip->ip_hl_v & 0xff); +#endif + if ((ip->ip_hl_v & 0xf0) != 0x40) { + return; + } + if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */ + return; + } + if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) { + puts ("checksum bad\n"); + return; + } + tmp = NetReadIP(&ip->ip_dst); + if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF) { + return; + } + /* + * watch for ICMP host redirects + * + * There is no real handler code (yet). We just watch + * for ICMP host redirect messages. In case anybody + * sees these messages: please contact me + * (wd@denx.de), or - even better - send me the + * necessary fixes :-) + * + * Note: in all cases where I have seen this so far + * it was a problem with the router configuration, + * for instance when a router was configured in the + * BOOTP reply, but the TFTP server was on the same + * subnet. So this is probably a warning that your + * configuration might be wrong. But I'm not really + * sure if there aren't any other situations. + */ + if (ip->ip_p == IPPROTO_ICMP) { + ICMP_t *icmph = (ICMP_t *)&(ip->udp_src); + + switch (icmph->type) { + case ICMP_REDIRECT: + if (icmph->code != ICMP_REDIR_HOST) + return; + puts (" ICMP Host Redirect to "); + print_IPaddr(icmph->un.gateway); + putc(' '); + return; +#if (CONFIG_COMMANDS & CFG_CMD_PING) + case ICMP_ECHO_REPLY: + /* + * IP header OK. Pass the packet to the current handler. + */ + /* XXX point to ip packet */ + (*packetHandler)((uchar *)ip, 0, 0, 0); + return; +#endif + default: + return; + } + } else if (ip->ip_p != IPPROTO_UDP) { /* Only UDP packets */ + return; + } + +#ifdef CONFIG_UDP_CHECKSUM + if (ip->udp_xsum != 0) { + ulong xsum; + ushort *sumptr; + ushort sumlen; + + xsum = ip->ip_p; + xsum += (ntohs(ip->udp_len)); + xsum += (ntohl(ip->ip_src) >> 16) & 0x0000ffff; + xsum += (ntohl(ip->ip_src) >> 0) & 0x0000ffff; + xsum += (ntohl(ip->ip_dst) >> 16) & 0x0000ffff; + xsum += (ntohl(ip->ip_dst) >> 0) & 0x0000ffff; + + sumlen = ntohs(ip->udp_len); + sumptr = (ushort *) &(ip->udp_src); + + while (sumlen > 1) { + ushort sumdata; + + sumdata = *sumptr++; + xsum += ntohs(sumdata); + sumlen -= 2; + } + if (sumlen > 0) { + ushort sumdata; + + sumdata = *(unsigned char *) sumptr; + sumdata = (sumdata << 8) & 0xff00; + xsum += sumdata; + } + while ((xsum >> 16) != 0) { + xsum = (xsum & 0x0000ffff) + ((xsum >> 16) & 0x0000ffff); + } + if ((xsum != 0x00000000) && (xsum != 0x0000ffff)) { + printf(" UDP wrong checksum %08x %08x\n", xsum, ntohs(ip->udp_xsum)); + return; + } + } +#endif + +#ifdef CONFIG_NETCONSOLE + nc_input_packet((uchar *)ip +IP_HDR_SIZE, + ntohs(ip->udp_dst), + ntohs(ip->udp_src), + ntohs(ip->udp_len) - 8); +#endif + /* + * IP header OK. Pass the packet to the current handler. + */ + (*packetHandler)((uchar *)ip +IP_HDR_SIZE, + ntohs(ip->udp_dst), + ntohs(ip->udp_src), + ntohs(ip->udp_len) - 8); + break; + } +} + + +/**********************************************************************/ + +static int net_check_prereq (proto_t protocol) +{ + switch (protocol) { + /* Fall through */ +#if (CONFIG_COMMANDS & CFG_CMD_PING) + case PING: + if (NetPingIP == 0) { + puts ("*** ERROR: ping address not given\n"); + return (1); + } + goto common; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_SNTP) + case SNTP: + if (NetNtpServerIP == 0) { + puts ("*** ERROR: NTP server address not given\n"); + return (1); + } + goto common; +#endif +#if (CONFIG_COMMANDS & CFG_CMD_NFS) + case NFS: +#endif + case NETCONS: + case TFTP: + if (NetServerIP == 0) { + puts ("*** ERROR: `serverip' not set\n"); + return (1); + } +#if (CONFIG_COMMANDS & (CFG_CMD_PING | CFG_CMD_SNTP)) + common: +#endif + + if (NetOurIP == 0) { + puts ("*** ERROR: `ipaddr' not set\n"); + return (1); + } + /* Fall through */ + + case DHCP: + case RARP: + case BOOTP: + case CDP: + if (memcmp (NetOurEther, "\0\0\0\0\0\0", 6) == 0) { +#ifdef CONFIG_NET_MULTI + extern int eth_get_dev_index (void); + int num = eth_get_dev_index (); + + switch (num) { + case -1: + puts ("*** ERROR: No ethernet found.\n"); + return (1); + case 0: + puts ("*** ERROR: `ethaddr' not set\n"); + break; + default: + printf ("*** ERROR: `eth%daddr' not set\n", + num); + break; + } + + NetStartAgain (); + return (2); +#else + puts ("*** ERROR: `ethaddr' not set\n"); + return (1); +#endif + } + /* Fall through */ + default: + return (0); + } + return (0); /* OK */ +} +/**********************************************************************/ + +int +NetCksumOk(uchar * ptr, int len) +{ + return !((NetCksum(ptr, len) + 1) & 0xfffe); +} + + +unsigned +NetCksum(uchar * ptr, int len) +{ + ulong xsum; + ushort *p = (ushort *)ptr; + + xsum = 0; + while (len-- > 0) + xsum += *p++; + xsum = (xsum & 0xffff) + (xsum >> 16); + xsum = (xsum & 0xffff) + (xsum >> 16); + return (xsum & 0xffff); +} + +int +NetEthHdrSize(void) +{ + ushort myvlanid; + + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; + + return ((myvlanid & VLAN_IDMASK) == VLAN_NONE) ? ETHER_HDR_SIZE : VLAN_ETHER_HDR_SIZE; +} + +int +NetSetEther(volatile uchar * xet, uchar * addr, uint prot) +{ + Ethernet_t *et = (Ethernet_t *)xet; + ushort myvlanid; + + myvlanid = ntohs(NetOurVLAN); + if (myvlanid == (ushort)-1) + myvlanid = VLAN_NONE; + + memcpy (et->et_dest, addr, 6); + memcpy (et->et_src, NetOurEther, 6); + if ((myvlanid & VLAN_IDMASK) == VLAN_NONE) { + et->et_protlen = htons(prot); + return ETHER_HDR_SIZE; + } else { + VLAN_Ethernet_t *vet = (VLAN_Ethernet_t *)xet; + + vet->vet_vlan_type = htons(PROT_VLAN); + vet->vet_tag = htons((0 << 5) | (myvlanid & VLAN_IDMASK)); + vet->vet_type = htons(prot); + return VLAN_ETHER_HDR_SIZE; + } +} + +void +NetSetIP(volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len) +{ + volatile IP_t *ip = (IP_t *)xip; + + /* + * If the data is an odd number of bytes, zero the + * byte after the last byte so that the checksum + * will work. + */ + if (len & 1) + xip[IP_HDR_SIZE + len] = 0; + + /* + * Construct an IP and UDP header. + * (need to set no fragment bit - XXX) + */ + ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */ + ip->ip_tos = 0; + ip->ip_len = htons(IP_HDR_SIZE + len); + ip->ip_id = htons(NetIPID++); + ip->ip_off = htons(0x4000); /* No fragmentation */ + ip->ip_ttl = 255; + ip->ip_p = 17; /* UDP */ + ip->ip_sum = 0; + NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */ + NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */ + ip->udp_src = htons(sport); + ip->udp_dst = htons(dport); + ip->udp_len = htons(8 + len); + ip->udp_xsum = 0; + ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2); +} + +void copy_filename (char *dst, char *src, int size) +{ + if (*src && (*src == '"')) { + ++src; + --size; + } + + while ((--size > 0) && *src && (*src != '"')) { + *dst++ = *src++; + } + *dst = '\0'; +} + +#endif /* CFG_CMD_NET */ + +void ip_to_string (IPaddr_t x, char *s) +{ + x = ntohl (x); + sprintf (s, "%d.%d.%d.%d", + (int) ((x >> 24) & 0xff), + (int) ((x >> 16) & 0xff), + (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff) + ); +} + +IPaddr_t string_to_ip(char *s) +{ + IPaddr_t addr; + char *e; + int i; + + if (s == NULL) + return(0); + + for (addr=0, i=0; i<4; ++i) { + ulong val = s ? simple_strtoul(s, &e, 10) : 0; + addr <<= 8; + addr |= (val & 0xFF); + if (s) { + s = (*e) ? e+1 : e; + } + } + + return (htonl(addr)); +} + +void VLAN_to_string(ushort x, char *s) +{ + x = ntohs(x); + + if (x == (ushort)-1) + x = VLAN_NONE; + + if (x == VLAN_NONE) + strcpy(s, "none"); + else + sprintf(s, "%d", x & VLAN_IDMASK); +} + +ushort string_to_VLAN(char *s) +{ + ushort id; + + if (s == NULL) + return htons(VLAN_NONE); + + if (*s < '0' || *s > '9') + id = VLAN_NONE; + else + id = (ushort)simple_strtoul(s, NULL, 10); + + return htons(id); +} + +void print_IPaddr (IPaddr_t x) +{ + char tmp[16]; + + ip_to_string (x, tmp); + + puts (tmp); +} + +IPaddr_t getenv_IPaddr (char *var) +{ + return (string_to_ip(getenv(var))); +} + +ushort getenv_VLAN(char *var) +{ + return (string_to_VLAN(getenv(var))); +} diff --git a/package/uboot-ifxmips/files/net/nfs_danube.c b/package/uboot-ifxmips/files/net/nfs_danube.c new file mode 100644 index 0000000000..de789e1f84 --- /dev/null +++ b/package/uboot-ifxmips/files/net/nfs_danube.c @@ -0,0 +1,778 @@ +/* + * NFS support driver - based on etherboot and U-BOOT's tftp.c + * + * Masami Komiya 2004 + * + */ + +/* NOTE: the NFS code is heavily inspired by the NetBSD netboot code (read: + * large portions are copied verbatim) as distributed in OSKit 0.97. A few + * changes were necessary to adapt the code to Etherboot and to fix several + * inconsistencies. Also the RPC message preparation is done "by hand" to + * avoid adding netsprintf() which I find hard to understand and use. */ + +/* NOTE 2: Etherboot does not care about things beyond the kernel image, so + * it loads the kernel image off the boot server (ARP_SERVER) and does not + * access the client root disk (root-path in dhcpd.conf), which would use + * ARP_ROOTSERVER. The root disk is something the operating system we are + * about to load needs to use. This is different from the OSKit 0.97 logic. */ + +/* NOTE 3: Symlink handling introduced by Anselm M Hoffmeister, 2003-July-14 + * If a symlink is encountered, it is followed as far as possible (recursion + * possible, maximum 16 steps). There is no clearing of ".."'s inside the + * path, so please DON'T DO THAT. thx. */ + +#include +#include +#include +#include +#include "nfs.h" +#include "bootp.h" + +/*#define NFS_DEBUG*/ + +#if ((CONFIG_COMMANDS & CFG_CMD_NET) && (CONFIG_COMMANDS & CFG_CMD_NFS)) + +#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */ +#define NFS_TIMEOUT 60 + +static int fs_mounted = 0; +static unsigned long rpc_id = 0; +static int nfs_offset = -1; +static int nfs_len; + +static char dirfh[NFS_FHSIZE]; /* file handle of directory */ +static char filefh[NFS_FHSIZE]; /* file handle of kernel image */ + +static int NfsDownloadState; +static IPaddr_t NfsServerIP; +static int NfsSrvMountPort; +static int NfsSrvNfsPort; +static int NfsOurPort; +static int NfsTimeoutCount; +static int NfsState; +#define STATE_PRCLOOKUP_PROG_MOUNT_REQ 1 +#define STATE_PRCLOOKUP_PROG_NFS_REQ 2 +#define STATE_MOUNT_REQ 3 +#define STATE_UMOUNT_REQ 4 +#define STATE_LOOKUP_REQ 5 +#define STATE_READ_REQ 6 +#define STATE_READLINK_REQ 7 + +static char default_filename[64]; +static char *nfs_filename; +static char *nfs_path; +static char nfs_path_buff[2048]; + +static __inline__ int +store_block (uchar * src, unsigned offset, unsigned len) +{ + ulong newsize = offset + len; +#ifdef CFG_DIRECT_FLASH_NFS + int i, rc = 0; + + for (i=0; i= flash_info[i].start[0]) { + rc = 1; + break; + } + } + + if (rc) { /* Flash is destination for this packet */ + rc = flash_write ((uchar *)src, (ulong)(load_addr+offset), len); + if (rc) { + flash_perror (rc); + return -1; + } + } else +#endif /* CFG_DIRECT_FLASH_NFS */ + { + (void)memcpy ((void *)(load_addr + offset), src, len); + } + + if (NetBootFileXferSize < (offset+len)) + NetBootFileXferSize = newsize; + return 0; +} + +static char* +basename (char *path) +{ + char *fname; + + fname = path + strlen(path) - 1; + while (fname >= path) { + if (*fname == '/') { + fname++; + break; + } + fname--; + } + return fname; +} + +static char* +dirname (char *path) +{ + char *fname; + + fname = basename (path); + --fname; + *fname = '\0'; + return path; +} + +/************************************************************************** +RPC_ADD_CREDENTIALS - Add RPC authentication/verifier entries +**************************************************************************/ +static long *rpc_add_credentials (long *p) +{ + int hl; + int hostnamelen; + char hostname[256]; + + strcpy (hostname, ""); + hostnamelen=strlen (hostname); + + /* Here's the executive summary on authentication requirements of the + * various NFS server implementations: Linux accepts both AUTH_NONE + * and AUTH_UNIX authentication (also accepts an empty hostname field + * in the AUTH_UNIX scheme). *BSD refuses AUTH_NONE, but accepts + * AUTH_UNIX (also accepts an empty hostname field in the AUTH_UNIX + * scheme). To be safe, use AUTH_UNIX and pass the hostname if we have + * it (if the BOOTP/DHCP reply didn't give one, just use an empty + * hostname). */ + + hl = (hostnamelen + 3) & ~3; + + /* Provide an AUTH_UNIX credential. */ + *p++ = htonl(1); /* AUTH_UNIX */ + *p++ = htonl(hl+20); /* auth length */ + *p++ = htonl(0); /* stamp */ + *p++ = htonl(hostnamelen); /* hostname string */ + if (hostnamelen & 3) { + *(p + hostnamelen / 4) = 0; /* add zero padding */ + } + memcpy (p, hostname, hostnamelen); + p += hl / 4; + *p++ = 0; /* uid */ + *p++ = 0; /* gid */ + *p++ = 0; /* auxiliary gid list */ + + /* Provide an AUTH_NONE verifier. */ + *p++ = 0; /* AUTH_NONE */ + *p++ = 0; /* auth length */ + + return p; +} + +/************************************************************************** +RPC_LOOKUP - Lookup RPC Port numbers +**************************************************************************/ +static void +rpc_req (int rpc_prog, int rpc_proc, uint32_t *data, int datalen) +{ + struct rpc_t pkt; + unsigned long id; + uint32_t *p; + int pktlen; + int sport; + + id = ++rpc_id; + pkt.u.call.id = htonl(id); + pkt.u.call.type = htonl(MSG_CALL); + pkt.u.call.rpcvers = htonl(2); /* use RPC version 2 */ + pkt.u.call.prog = htonl(rpc_prog); + pkt.u.call.vers = htonl(2); /* portmapper is version 2 */ + pkt.u.call.proc = htonl(rpc_proc); + p = (uint32_t *)&(pkt.u.call.data); + + if (datalen) + memcpy ((char *)p, (char *)data, datalen*sizeof(uint32_t)); + + pktlen = (char *)p + datalen*sizeof(uint32_t) - (char *)&pkt; + + memcpy ((char *)NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE, (char *)&pkt, pktlen); + + if (rpc_prog == PROG_PORTMAP) + sport = SUNRPC_PORT; + else if (rpc_prog == PROG_MOUNT) + sport = NfsSrvMountPort; + else + sport = NfsSrvNfsPort; + + NetSendUDPPacket (NetServerEther, NfsServerIP, sport, NfsOurPort, pktlen); +} + +/************************************************************************** +RPC_LOOKUP - Lookup RPC Port numbers +**************************************************************************/ +static void +rpc_lookup_req (int prog, int ver) +{ + uint32_t data[16]; + + data[0] = 0; data[1] = 0; /* auth credential */ + data[2] = 0; data[3] = 0; /* auth verifier */ + data[4] = htonl(prog); + data[5] = htonl(ver); + data[6] = htonl(17); /* IP_UDP */ + data[7] = 0; + + rpc_req (PROG_PORTMAP, PORTMAP_GETPORT, data, 8); +} + +/************************************************************************** +NFS_MOUNT - Mount an NFS Filesystem +**************************************************************************/ +static void +nfs_mount_req (char *path) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + int pathlen; + + pathlen = strlen (path); + + p = &(data[0]); + p = (uint32_t *)rpc_add_credentials((long *)p); + + *p++ = htonl(pathlen); + if (pathlen & 3) *(p + pathlen / 4) = 0; + memcpy (p, path, pathlen); + p += (pathlen + 3) / 4; + + len = (uint32_t *)p - (uint32_t *)&(data[0]); + + rpc_req (PROG_MOUNT, MOUNT_ADDENTRY, data, len); +} + +/************************************************************************** +NFS_UMOUNTALL - Unmount all our NFS Filesystems on the Server +**************************************************************************/ +static void +nfs_umountall_req (void) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + + if ((NfsSrvMountPort == -1) || (!fs_mounted)) { + /* Nothing mounted, nothing to umount */ + return; + } + + p = &(data[0]); + p = (uint32_t *)rpc_add_credentials ((long *)p); + + len = (uint32_t *)p - (uint32_t *)&(data[0]); + + rpc_req (PROG_MOUNT, MOUNT_UMOUNTALL, data, len); +} + +/*************************************************************************** + * NFS_READLINK (AH 2003-07-14) + * This procedure is called when read of the first block fails - + * this probably happens when it's a directory or a symlink + * In case of successful readlink(), the dirname is manipulated, + * so that inside the nfs() function a recursion can be done. + **************************************************************************/ +static void +nfs_readlink_req (void) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + + p = &(data[0]); + p = (uint32_t *)rpc_add_credentials ((long *)p); + + memcpy (p, filefh, NFS_FHSIZE); + p += (NFS_FHSIZE / 4); + + len = (uint32_t *)p - (uint32_t *)&(data[0]); + + rpc_req (PROG_NFS, NFS_READLINK, data, len); +} + +/************************************************************************** +NFS_LOOKUP - Lookup Pathname +**************************************************************************/ +static void +nfs_lookup_req (char *fname) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + int fnamelen; + + fnamelen = strlen (fname); + + p = &(data[0]); + p = (uint32_t *)rpc_add_credentials ((long *)p); + + memcpy (p, dirfh, NFS_FHSIZE); + p += (NFS_FHSIZE / 4); + *p++ = htonl(fnamelen); + if (fnamelen & 3) *(p + fnamelen / 4) = 0; + memcpy (p, fname, fnamelen); + p += (fnamelen + 3) / 4; + + len = (uint32_t *)p - (uint32_t *)&(data[0]); + + rpc_req (PROG_NFS, NFS_LOOKUP, data, len); +} + +/************************************************************************** +NFS_READ - Read File on NFS Server +**************************************************************************/ +static void +nfs_read_req (int offset, int readlen) +{ + uint32_t data[1024]; + uint32_t *p; + int len; + + p = &(data[0]); + p = (uint32_t *)rpc_add_credentials ((long *)p); + + memcpy (p, filefh, NFS_FHSIZE); + p += (NFS_FHSIZE / 4); + *p++ = htonl(offset); + *p++ = htonl(readlen); + *p++ = 0; + + len = (uint32_t *)p - (uint32_t *)&(data[0]); + + rpc_req (PROG_NFS, NFS_READ, data, len); +} + +/************************************************************************** +RPC request dispatcher +**************************************************************************/ + +static void +NfsSend (void) +{ +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + switch (NfsState) { + case STATE_PRCLOOKUP_PROG_MOUNT_REQ: + rpc_lookup_req (PROG_MOUNT, 1); + break; + case STATE_PRCLOOKUP_PROG_NFS_REQ: + rpc_lookup_req (PROG_NFS, 2); + break; + case STATE_MOUNT_REQ: + nfs_mount_req (nfs_path); + break; + case STATE_UMOUNT_REQ: + nfs_umountall_req (); + break; + case STATE_LOOKUP_REQ: + nfs_lookup_req (nfs_filename); + break; + case STATE_READ_REQ: + nfs_read_req (nfs_offset, nfs_len); + break; + case STATE_READLINK_REQ: + nfs_readlink_req (); + break; + } +} + +/************************************************************************** +Handlers for the reply from server +**************************************************************************/ + +static int +rpc_lookup_reply (int prog, uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + + memcpy ((unsigned char *)&rpc_pkt, pkt, len); + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus || + rpc_pkt.u.reply.astatus) { + return -1; + } + + switch (prog) { + case PROG_MOUNT: + NfsSrvMountPort = ntohl(rpc_pkt.u.reply.data[0]); + break; + case PROG_NFS: + NfsSrvNfsPort = ntohl(rpc_pkt.u.reply.data[0]); + break; + } + + return 0; +} + +static int +nfs_mount_reply (uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + memcpy ((unsigned char *)&rpc_pkt, pkt, len); + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus || + rpc_pkt.u.reply.data[0]) { + return -1; + } + + fs_mounted = 1; + memcpy (dirfh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE); + + return 0; +} + +static int +nfs_umountall_reply (uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + memcpy ((unsigned char *)&rpc_pkt, pkt, len); + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus) { + return -1; + } + + fs_mounted = 0; + memset (dirfh, 0, sizeof(dirfh)); + + return 0; +} + +static int +nfs_lookup_reply (uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + memcpy ((unsigned char *)&rpc_pkt, pkt, len); + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus || + rpc_pkt.u.reply.data[0]) { + return -1; + } + + memcpy (filefh, rpc_pkt.u.reply.data + 1, NFS_FHSIZE); + + return 0; +} + +static int +nfs_readlink_reply (uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + int rlen; + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + memcpy ((unsigned char *)&rpc_pkt, pkt, len); + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus || + rpc_pkt.u.reply.data[0]) { + return -1; + } + + rlen = ntohl (rpc_pkt.u.reply.data[1]); /* new path length */ + + if (*((char *)&(rpc_pkt.u.reply.data[2])) != '/') { + int pathlen; + strcat (nfs_path, "/"); + pathlen = strlen(nfs_path); + memcpy (nfs_path+pathlen, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen); + nfs_path[pathlen+rlen+1] = 0; + } else { + memcpy (nfs_path, (uchar *)&(rpc_pkt.u.reply.data[2]), rlen); + nfs_path[rlen] = 0; + } + return 0; +} + +static int +nfs_read_reply (uchar *pkt, unsigned len) +{ + struct rpc_t rpc_pkt; + int rlen; + +#ifdef NFS_DEBUG_nop + printf ("%s\n", __FUNCTION__); +#endif + + memcpy ((uchar *)&rpc_pkt, pkt, sizeof(rpc_pkt.u.reply)); + + if (ntohl(rpc_pkt.u.reply.id) != rpc_id) + return -1; + + if (rpc_pkt.u.reply.rstatus || + rpc_pkt.u.reply.verifier || + rpc_pkt.u.reply.astatus || + rpc_pkt.u.reply.data[0]) { + if (rpc_pkt.u.reply.rstatus) { + return -9999; + } + if (rpc_pkt.u.reply.astatus) { + return -9999; + } + return -ntohl(rpc_pkt.u.reply.data[0]);; + } + + if ((nfs_offset!=0) && !((nfs_offset) % (NFS_READ_SIZE/2*10*HASHES_PER_LINE))) { + puts ("\n\t "); + } + if (!(nfs_offset % ((NFS_READ_SIZE/2)*10))) { + putc ('#'); + } + + rlen = ntohl(rpc_pkt.u.reply.data[18]); + if ( store_block ((uchar *)pkt+sizeof(rpc_pkt.u.reply), nfs_offset, rlen) ) + return -9999; + + return rlen; +} + +/************************************************************************** +Interfaces of U-BOOT +**************************************************************************/ + +static void +NfsTimeout (void) +{ + puts ("Timeout\n"); + NetState = NETLOOP_FAIL; + return; +} + +static void +NfsHandler (uchar *pkt, unsigned dest, unsigned src, unsigned len) +{ + int rlen; + +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + + if (dest != NfsOurPort) return; + + switch (NfsState) { + case STATE_PRCLOOKUP_PROG_MOUNT_REQ: + rpc_lookup_reply (PROG_MOUNT, pkt, len); + NfsState = STATE_PRCLOOKUP_PROG_NFS_REQ; + NfsSend (); + break; + + case STATE_PRCLOOKUP_PROG_NFS_REQ: + rpc_lookup_reply (PROG_NFS, pkt, len); + NfsState = STATE_MOUNT_REQ; + NfsSend (); + break; + + case STATE_MOUNT_REQ: + if (nfs_mount_reply(pkt, len)) { + puts ("*** ERROR: Cannot mount\n"); + /* just to be sure... */ + NfsState = STATE_UMOUNT_REQ; + NfsSend (); + } else { + NfsState = STATE_LOOKUP_REQ; + NfsSend (); + } + break; + + case STATE_UMOUNT_REQ: + if (nfs_umountall_reply(pkt, len)) { + puts ("*** ERROR: Cannot umount\n"); + NetState = NETLOOP_FAIL; + } else { + puts ("\ndone\n"); + NetState = NfsDownloadState; + } + break; + + case STATE_LOOKUP_REQ: + if (nfs_lookup_reply(pkt, len)) { + puts ("*** ERROR: File lookup fail\n"); + NfsState = STATE_UMOUNT_REQ; + NfsSend (); + } else { + NfsState = STATE_READ_REQ; + nfs_offset = 0; + nfs_len = NFS_READ_SIZE; + NfsSend (); + } + break; + + case STATE_READLINK_REQ: + if (nfs_readlink_reply(pkt, len)) { + puts ("*** ERROR: Symlink fail\n"); + NfsState = STATE_UMOUNT_REQ; + NfsSend (); + } else { +#ifdef NFS_DEBUG + printf ("Symlink --> %s\n", nfs_path); +#endif + nfs_filename = basename (nfs_path); + nfs_path = dirname (nfs_path); + + NfsState = STATE_MOUNT_REQ; + NfsSend (); + } + break; + + case STATE_READ_REQ: + rlen = nfs_read_reply (pkt, len); + NetSetTimeout (NFS_TIMEOUT * CFG_HZ, NfsTimeout); + if (rlen > 0) { + nfs_offset += rlen; + NfsSend (); + } + else if ((rlen == -NFSERR_ISDIR)||(rlen == -NFSERR_INVAL)) { + /* symbolic link */ + NfsState = STATE_READLINK_REQ; + NfsSend (); + } else { + if ( ! rlen ) NfsDownloadState = NETLOOP_SUCCESS; + NfsState = STATE_UMOUNT_REQ; + NfsSend (); + } + break; + } +} + + +void +NfsStart (void) +{ +#ifdef NFS_DEBUG + printf ("%s\n", __FUNCTION__); +#endif + NfsDownloadState = NETLOOP_FAIL; + + NfsServerIP = NetServerIP; + nfs_path = (char *)nfs_path_buff; + + if (nfs_path == NULL) { + NetState = NETLOOP_FAIL; + puts ("*** ERROR: Fail allocate memory\n"); + return; + } + + if (BootFile[0] == '\0') { + sprintf (default_filename, "/nfsroot/%02lX%02lX%02lX%02lX.img", + NetOurIP & 0xFF, + (NetOurIP >> 8) & 0xFF, + (NetOurIP >> 16) & 0xFF, + (NetOurIP >> 24) & 0xFF ); + strcpy (nfs_path, default_filename); + + printf ("*** Warning: no boot file name; using '%s'\n", + nfs_path); + } else { + char *p=BootFile; + + p = strchr (p, ':'); + + if (p != NULL) { + NfsServerIP = string_to_ip (BootFile); + ++p; + strcpy (nfs_path, p); + } else { + strcpy (nfs_path, BootFile); + } + } + + nfs_filename = basename (nfs_path); + nfs_path = dirname (nfs_path); + +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif + + puts ("File transfer via NFS from server "); print_IPaddr (NfsServerIP); + puts ("; our IP address is "); print_IPaddr (NetOurIP); + + /* Check if we need to send across this subnet */ + if (NetOurGatewayIP && NetOurSubnetMask) { + IPaddr_t OurNet = NetOurIP & NetOurSubnetMask; + IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask; + + if (OurNet != ServerNet) { + puts ("; sending through gateway "); + print_IPaddr (NetOurGatewayIP) ; + } + } + printf ("\nFilename '%s/%s'.", nfs_path, nfs_filename); + + if (NetBootFileSize) { + printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9); + print_size (NetBootFileSize<<9, ""); + } + printf ("\nLoad address: 0x%lx\n" + "Loading: *\b", load_addr); + + NetSetTimeout (NFS_TIMEOUT * CFG_HZ, NfsTimeout); + NetSetHandler (NfsHandler); + + NfsTimeoutCount = 0; + NfsState = STATE_PRCLOOKUP_PROG_MOUNT_REQ; + + /*NfsOurPort = 4096 + (get_ticks() % 3072);*/ + /*FIX ME !!!*/ + NfsOurPort = 1000; + + /* zero out server ether in case the server ip has changed */ + memset (NetServerEther, 0, 6); + + NfsSend (); +} + +#endif /* CONFIG_COMMANDS & CFG_CMD_NFS */ diff --git a/package/uboot-ifxmips/files/net/tftp_danube.c b/package/uboot-ifxmips/files/net/tftp_danube.c new file mode 100644 index 0000000000..f3a5471483 --- /dev/null +++ b/package/uboot-ifxmips/files/net/tftp_danube.c @@ -0,0 +1,389 @@ +/* + * Copyright 1994, 1995, 2000 Neil Russell. + * (See License) + * Copyright 2000, 2001 DENX Software Engineering, Wolfgang Denk, wd@denx.de + */ + +#include +#include +#include +#include "tftp.h" +#include "bootp.h" + +#undef ET_DEBUG + +#if (CONFIG_COMMANDS & CFG_CMD_NET) + +#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ +#define TIMEOUT 5 /* Seconds to timeout for a lost pkt */ +#ifndef CONFIG_NET_RETRY_COUNT +# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */ +#else +# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2) +#endif + /* (for checking the image size) */ +#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */ + +/* + * TFTP operations. + */ +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + + +static int TftpServerPort; /* The UDP port at their end */ +static int TftpOurPort; /* The UDP port at our end */ +static int TftpTimeoutCount; +static ulong TftpBlock; /* packet sequence number */ +static ulong TftpLastBlock; /* last packet sequence number received */ +static ulong TftpBlockWrap; /* count of sequence number wraparounds */ +static ulong TftpBlockWrapOffset; /* memory offset due to wrapping */ +static int TftpState; + +#define STATE_RRQ 1 +#define STATE_DATA 2 +#define STATE_TOO_LARGE 3 +#define STATE_BAD_MAGIC 4 +#define STATE_OACK 5 + +#define TFTP_BLOCK_SIZE 512 /* default TFTP block size */ +#define TFTP_SEQUENCE_SIZE ((ulong)(1<<16)) /* sequence number is 16 bit */ + +#define DEFAULT_NAME_LEN (8 + 4 + 1) +static char default_filename[DEFAULT_NAME_LEN]; +static char *tftp_filename; + +#ifdef CFG_DIRECT_FLASH_TFTP +extern flash_info_t flash_info[]; +#endif + +static __inline__ void +store_block (unsigned block, uchar * src, unsigned len) +{ + ulong offset = block * TFTP_BLOCK_SIZE + TftpBlockWrapOffset; + ulong newsize = offset + len; +#ifdef CFG_DIRECT_FLASH_TFTP + int i, rc = 0; + + for (i=0; i= flash_info[i].start[0]) { + rc = 1; + break; + } + } + + if (rc) { /* Flash is destination for this packet */ + rc = flash_write ((char *)src, (ulong)(load_addr+offset), len); + if (rc) { + flash_perror (rc); + NetState = NETLOOP_FAIL; + return; + } + } + else +#endif /* CFG_DIRECT_FLASH_TFTP */ + { + (void)memcpy((void *)(load_addr + offset), src, len); + } + + if (NetBootFileXferSize < newsize) + NetBootFileXferSize = newsize; +} + +static void TftpSend (void); +static void TftpTimeout (void); + +/**********************************************************************/ + +static void +TftpSend (void) +{ + volatile uchar * pkt; + volatile uchar * xp; + int len = 0; + volatile ushort *s; + + /* + * We will always be sending some sort of packet, so + * cobble together the packet headers now. + */ + pkt = NetTxPacket + NetEthHdrSize() + IP_HDR_SIZE; + + switch (TftpState) { + + case STATE_RRQ: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_RRQ); + pkt = (uchar *)s; + strcpy ((char *)pkt, tftp_filename); + pkt += strlen(tftp_filename) + 1; + strcpy ((char *)pkt, "octet"); + pkt += 5 /*strlen("octet")*/ + 1; + strcpy ((char *)pkt, "timeout"); + pkt += 7 /*strlen("timeout")*/ + 1; + sprintf((char *)pkt, "%d", TIMEOUT); +#ifdef ET_DEBUG + printf("send option \"timeout %s\"\n", (char *)pkt); +#endif + pkt += strlen((char *)pkt) + 1; + len = pkt - xp; + break; + + case STATE_DATA: + case STATE_OACK: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_ACK); + *s++ = htons(TftpBlock); + pkt = (uchar *)s; + len = pkt - xp; + break; + + case STATE_TOO_LARGE: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(3); + pkt = (uchar *)s; + strcpy ((char *)pkt, "File too large"); + pkt += 14 /*strlen("File too large")*/ + 1; + len = pkt - xp; + break; + + case STATE_BAD_MAGIC: + xp = pkt; + s = (ushort *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(2); + pkt = (uchar *)s; + strcpy ((char *)pkt, "File has bad magic"); + pkt += 18 /*strlen("File has bad magic")*/ + 1; + len = pkt - xp; + break; + } + + NetSendUDPPacket(NetServerEther, NetServerIP, TftpServerPort, TftpOurPort, len); +} + + +static void +TftpHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len) +{ + ushort proto; + ushort *s; + + if (dest != TftpOurPort) { + return; + } + if (TftpState != STATE_RRQ && src != TftpServerPort) { + return; + } + + if (len < 2) { + return; + } + len -= 2; + /* warning: don't use increment (++) in ntohs() macros!! */ + s = (ushort *)pkt; + proto = *s++; + pkt = (uchar *)s; + switch (ntohs(proto)) { + + case TFTP_RRQ: + case TFTP_WRQ: + case TFTP_ACK: + break; + default: + break; + + case TFTP_OACK: +#ifdef ET_DEBUG + printf("Got OACK: %s %s\n", pkt, pkt+strlen(pkt)+1); +#endif + TftpState = STATE_OACK; + TftpServerPort = src; + TftpSend (); /* Send ACK */ + break; + case TFTP_DATA: + if (len < 2) + return; + len -= 2; + TftpBlock = ntohs(*(ushort *)pkt); + + /* + * RFC1350 specifies that the first data packet will + * have sequence number 1. If we receive a sequence + * number of 0 this means that there was a wrap + * around of the (16 bit) counter. + */ + if (TftpBlock == 0) { + TftpBlockWrap++; + TftpBlockWrapOffset += TFTP_BLOCK_SIZE * TFTP_SEQUENCE_SIZE; + printf ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset>>20); + } else { + if (((TftpBlock - 1) % 10) == 0) { + putc ('#'); + } else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) { + puts ("\n\t "); + } + } + +#ifdef ET_DEBUG + if (TftpState == STATE_RRQ) { + puts ("Server did not acknowledge timeout option!\n"); + } +#endif + + if (TftpState == STATE_RRQ || TftpState == STATE_OACK) { + /* first block received */ + TftpState = STATE_DATA; + TftpServerPort = src; + TftpLastBlock = 0; + TftpBlockWrap = 0; + TftpBlockWrapOffset = 0; + + if (TftpBlock != 1) { /* Assertion */ + printf ("\nTFTP error: " + "First block is not block 1 (%ld)\n" + "Starting again\n\n", + TftpBlock); + NetStartAgain (); + break; + } + } + + if (TftpBlock == TftpLastBlock) { + /* + * Same block again; ignore it. + */ + break; + } + + TftpLastBlock = TftpBlock; + NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + + store_block (TftpBlock - 1, pkt + 2, len); + + /* + * Acknoledge the block just received, which will prompt + * the server for the next one. + */ + TftpSend (); + + if (len < TFTP_BLOCK_SIZE) { + /* + * We received the whole thing. Try to + * run it. + */ + puts ("\ndone\n"); + NetState = NETLOOP_SUCCESS; + } + break; + + case TFTP_ERROR: + printf ("\nTFTP error: '%s' (%d)\n", + pkt + 2, ntohs(*(ushort *)pkt)); + puts ("Starting again\n\n"); + NetStartAgain (); + break; + } +} + + +static void +TftpTimeout (void) +{ + if (++TftpTimeoutCount > TIMEOUT_COUNT) { + puts ("\nRetry count exceeded; starting again\n"); + NetStartAgain (); + } else { + puts ("T "); + NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + TftpSend (); + } +} + + +void +TftpStart (void) +{ +#ifdef CONFIG_TFTP_PORT + char *ep; /* Environment pointer */ +#endif + + if (BootFile[0] == '\0') { + sprintf(default_filename, "%02lX%02lX%02lX%02lX.img", + NetOurIP & 0xFF, + (NetOurIP >> 8) & 0xFF, + (NetOurIP >> 16) & 0xFF, + (NetOurIP >> 24) & 0xFF ); + tftp_filename = default_filename; + + printf ("*** Warning: no boot file name; using '%s'\n", + tftp_filename); + } else { + tftp_filename = BootFile; + } + +#if defined(CONFIG_NET_MULTI) + printf ("Using %s device\n", eth_get_name()); +#endif + puts ("TFTP from server "); print_IPaddr (NetServerIP); + puts ("; our IP address is "); print_IPaddr (NetOurIP); + + /* Check if we need to send across this subnet */ + if (NetOurGatewayIP && NetOurSubnetMask) { + IPaddr_t OurNet = NetOurIP & NetOurSubnetMask; + IPaddr_t ServerNet = NetServerIP & NetOurSubnetMask; + + if (OurNet != ServerNet) { + puts ("; sending through gateway "); + print_IPaddr (NetOurGatewayIP) ; + } + } + putc ('\n'); + + printf ("Filename '%s'.", tftp_filename); + + if (NetBootFileSize) { + printf (" Size is 0x%x Bytes = ", NetBootFileSize<<9); + print_size (NetBootFileSize<<9, ""); + } + + putc ('\n'); + + printf ("Load address: 0x%lx\n", load_addr); + + puts ("Loading: *\b"); + + NetSetTimeout (TIMEOUT * CFG_HZ, TftpTimeout); + NetSetHandler (TftpHandler); + + TftpServerPort = WELL_KNOWN_PORT; + TftpTimeoutCount = 0; + TftpState = STATE_RRQ; + /* Use a pseudo-random port unless a specific port is set */ + TftpOurPort = 1024 + (get_timer(0) % 3072); +#ifdef CONFIG_TFTP_PORT + if ((ep = getenv("tftpdstp")) != NULL) { + TftpServerPort = simple_strtol(ep, NULL, 10); + } + if ((ep = getenv("tftpsrcp")) != NULL) { + TftpOurPort= simple_strtol(ep, NULL, 10); + } +#endif + TftpBlock = 0; + + /* zero out server ether in case the server ip has changed */ + memset(NetServerEther, 0, 6); + + TftpSend (); +} + +#endif /* CFG_CMD_NET */ diff --git a/package/uboot-ifxmips/files/tools/crc32_danube.c b/package/uboot-ifxmips/files/tools/crc32_danube.c new file mode 100644 index 0000000000..3d99b69296 --- /dev/null +++ b/package/uboot-ifxmips/files/tools/crc32_danube.c @@ -0,0 +1,198 @@ +/* + * This file is derived from crc32.c from the zlib-1.1.3 distribution + * by Jean-loup Gailly and Mark Adler. + */ + +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-1998 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#ifndef USE_HOSTCC /* Shut down "ANSI does not permit..." warnings */ +#include /* to get command definitions like CFG_CMD_JFFS2 */ +#endif + +#include "zlib.h" + +#define local static +#define ZEXPORT /* empty */ +unsigned long crc32 (unsigned long, const unsigned char *, unsigned int); + +#ifdef DYNAMIC_CRC_TABLE + +local int crc_table_empty = 1; +local uLongf crc_table[256]; +local void make_crc_table OF((void)); + +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. +*/ +local void make_crc_table() +{ + uLong c; + int n, k; + uLong poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* make exclusive-or pattern from polynomial (0xedb88320L) */ + poly = 0L; + for (n = 0; n < sizeof(p)/sizeof(Byte); n++) + poly |= 1L << (31 - p[n]); + + for (n = 0; n < 256; n++) + { + c = (uLong)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[n] = c; + } + crc_table_empty = 0; +} +#else +/* ======================================================================== + * Table of CRC-32's of all single-byte values (made by make_crc_table) + */ +local const uLongf crc_table[256] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL +}; +#endif + +#if 0 +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const uLongf * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) make_crc_table(); +#endif + return (const uLongf *)crc_table; +} +#endif + +/* ========================================================================= */ +#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8); +#define DO2(buf) DO1(buf); DO1(buf); +#define DO4(buf) DO2(buf); DO2(buf); +#define DO8(buf) DO4(buf); DO4(buf); + +/* ========================================================================= */ +uLong ZEXPORT crc32(crc, buf, len) + uLong crc; + const Bytef *buf; + uInt len; +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + crc = crc ^ 0xffffffffL; + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + return crc ^ 0xffffffffL; +} + +#if (CONFIG_COMMANDS & CFG_CMD_JFFS2) || \ + ((CONFIG_COMMANDS & CFG_CMD_NAND) && !defined(CFG_NAND_LEGACY)) + +/* No ones complement version. JFFS2 (and other things ?) + * don't use ones compliment in their CRC calculations. + */ +uLong ZEXPORT crc32_no_comp(uLong crc, const Bytef *buf, uInt len) +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif + while (len >= 8) + { + DO8(buf); + len -= 8; + } + if (len) do { + DO1(buf); + } while (--len); + + return crc; +} + +#endif /* CFG_CMD_JFFS2 */ diff --git a/package/uboot-ifxmips/files/tools/environment_danube.c b/package/uboot-ifxmips/files/tools/environment_danube.c new file mode 100644 index 0000000000..19bdeb0f62 --- /dev/null +++ b/package/uboot-ifxmips/files/tools/environment_danube.c @@ -0,0 +1,213 @@ +/* + * (C) Copyright 2001 + * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 + */ + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ /* Dirty trick to get only #defines */ +#endif +#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ +#include +#undef __ASSEMBLY__ +#include + +/* + * Handle HOSTS that have prepended + * crap on symbol names, not TARGETS. + */ +#if defined(__APPLE__) +/* Leading underscore on symbols */ +# define SYM_CHAR "_" +#else /* No leading character on symbols */ +# define SYM_CHAR +#endif + +/* + * Generate embedded environment table + * inside U-Boot image, if needed. + */ +#if defined(ENV_IS_EMBEDDED) +/* + * Only put the environment in it's own section when we are building + * U-Boot proper. The host based program "tools/envcrc" does not need + * a seperate section. Note that ENV_CRC is only defined when building + * U-Boot itself. + */ +#if (defined(CONFIG_CMI) || \ + defined(CONFIG_FADS) || \ + defined(CONFIG_HYMOD) || \ + defined(CONFIG_ICU862) || \ + defined(CONFIG_R360MPI) || \ + defined(CONFIG_TQM8xxL) || \ + defined(CONFIG_RRVISION) || \ + defined(CONFIG_TRAB) || \ + defined(CONFIG_PPCHAMELEONEVB) || \ + defined(CONFIG_M5271EVB) || \ + defined(CONFIG_NAND_U_BOOT)) && \ + defined(ENV_CRC) /* Environment embedded in U-Boot .ppcenv section */ +/* XXX - This only works with GNU C */ +# define __PPCENV__ __attribute__ ((section(".ppcenv"))) +# define __PPCTEXT__ __attribute__ ((section(".text"))) + +#elif defined(USE_HOSTCC) /* Native for 'tools/envcrc' */ +# define __PPCENV__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ +# define __PPCTEXT__ /*XXX DO_NOT_DEL_THIS_COMMENT*/ + +#else /* Environment is embedded in U-Boot's .text section */ +/* XXX - This only works with GNU C */ +# define __PPCENV__ __attribute__ ((section(".text"))) +# define __PPCTEXT__ __attribute__ ((section(".text"))) +#endif + +/* + * Macros to generate global absolutes. + */ +#define GEN_SYMNAME(str) SYM_CHAR #str +#define GEN_VALUE(str) #str +#define GEN_ABS(name, value) \ + asm (".globl " GEN_SYMNAME(name)); \ + asm (GEN_SYMNAME(name) " = " GEN_VALUE(value)) + +/* + * Macros to transform values + * into environment strings. + */ +#define XMK_STR(x) #x +#define MK_STR(x) XMK_STR(x) + +/* + * Check to see if we are building with a + * computed CRC. Otherwise define it as ~0. + */ +#if !defined(ENV_CRC) +# define ENV_CRC ~0 +#endif + +env_t environment __PPCENV__ = { + ENV_CRC, /* CRC Sum */ +#ifdef CFG_REDUNDAND_ENVIRONMENT + 1, /* Flags: valid */ +#endif + { +#if defined(CONFIG_BOOTARGS) + "bootargs=" CONFIG_BOOTARGS "\0" +#endif +#if defined(CONFIG_BOOTCOMMAND) + "bootcmd=" CONFIG_BOOTCOMMAND "\0" +#endif +#if defined(CONFIG_RAMBOOTCOMMAND) + "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_NFSBOOTCOMMAND) + "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + "bootdelay=" MK_STR(CONFIG_BOOTDELAY) "\0" +#endif +#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) + "baudrate=" MK_STR(CONFIG_BAUDRATE) "\0" +#endif +#ifdef CONFIG_LOADS_ECHO + "loads_echo=" MK_STR(CONFIG_LOADS_ECHO) "\0" +#endif +#ifdef CONFIG_ETHADDR + "ethaddr=" MK_STR(CONFIG_ETHADDR) "\0" +#endif +#ifdef CONFIG_ETH1ADDR + "eth1addr=" MK_STR(CONFIG_ETH1ADDR) "\0" +#endif +#ifdef CONFIG_ETH2ADDR + "eth2addr=" MK_STR(CONFIG_ETH2ADDR) "\0" +#endif +#ifdef CONFIG_ETH3ADDR + "eth3addr=" MK_STR(CONFIG_ETH3ADDR) "\0" +#endif +#ifdef CONFIG_ETHPRIME + "ethprime=" CONFIG_ETHPRIME "\0" +#endif +#ifdef CONFIG_IPADDR + "ipaddr=" MK_STR(CONFIG_IPADDR) "\0" +#endif +#ifdef CONFIG_SERVERIP + "serverip=" MK_STR(CONFIG_SERVERIP) "\0" +#endif +#ifdef CFG_AUTOLOAD + "autoload=" CFG_AUTOLOAD "\0" +#endif +#ifdef CONFIG_ROOTPATH + "rootpath=" MK_STR(CONFIG_ROOTPATH) "\0" +#endif +#ifdef CONFIG_GATEWAYIP + "gatewayip=" MK_STR(CONFIG_GATEWAYIP) "\0" +#endif +#ifdef CONFIG_NETMASK + "netmask=" MK_STR(CONFIG_NETMASK) "\0" +#endif +#ifdef CONFIG_HOSTNAME + "hostname=" MK_STR(CONFIG_HOSTNAME) "\0" +#endif +#ifdef CONFIG_BOOTFILE + "bootfile=" MK_STR(CONFIG_BOOTFILE) "\0" +#endif +#ifdef CONFIG_LOADADDR + "loadaddr=" MK_STR(CONFIG_LOADADDR) "\0" +#endif +#ifdef CONFIG_PREBOOT + "preboot=" CONFIG_PREBOOT "\0" +#endif +#ifdef CONFIG_CLOCKS_IN_MHZ + "clocks_in_mhz=" "1" "\0" +#endif +#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0) + "pcidelay=" MK_STR(CONFIG_PCI_BOOTDELAY) "\0" +#endif +#ifdef CONFIG_EXTRA_ENV_SETTINGS + CONFIG_EXTRA_ENV_SETTINGS +#endif + "\0" /* Term. env_t.data with 2 NULs */ + } +}; +#ifdef CFG_ENV_ADDR_REDUND +env_t redundand_environment __PPCENV__ = { + 0, /* CRC Sum: invalid */ + 0, /* Flags: invalid */ + { + "\0" + } +}; +#endif /* CFG_ENV_ADDR_REDUND */ + +/* + * These will end up in the .text section + * if the environment strings are embedded + * in the image. When this is used for + * tools/envcrc, they are placed in the + * .data/.sdata section. + * + */ +unsigned long env_size __PPCTEXT__ = sizeof(env_t); + +/* + * Add in absolutes. + */ +GEN_ABS(env_offset, CFG_ENV_OFFSET); + +#endif /* ENV_IS_EMBEDDED */ diff --git a/package/uboot-ifxmips/patches/100-ifx.patch b/package/uboot-ifxmips/patches/100-ifx.patch new file mode 100644 index 0000000000..566132032c --- /dev/null +++ b/package/uboot-ifxmips/patches/100-ifx.patch @@ -0,0 +1,1773 @@ +--- a/Makefile ++++ b/Makefile +@@ -24,7 +24,7 @@ + VERSION = 1 + PATCHLEVEL = 1 + SUBLEVEL = 5 +-EXTRAVERSION = ++EXTRAVERSION = -IFX-LXDB + U_BOOT_VERSION = $(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION) + VERSION_FILE = $(obj)include/version_autogenerated.h + +@@ -44,6 +44,25 @@ + # Deal with colliding definitions from tcsh etc. + VENDOR= + ++# Default algorithm form compressing u-boot.bin ++ifndef COMPRESS ++COMPRESS=none ++COMPRESS_FILE=$(obj)u-boot.img ++else ++ifeq ($(COMPRESS),lzma) ++COMPRESS_FILE=$(obj)u-boot.limg ++endif ++ifeq ($(COMPRESS),bz2) ++COMPRESS_FILE=$(obj)u-boot.bzimg ++endif ++ifeq ($(COMPRESS),gzip) ++COMPRESS_FILE=$(obj)u-boot.zimg ++endif ++ifeq ($(COMPRESS),none) ++COMPRESS_FILE=$(obj)u-boot.img ++endif ++endif ++ + ######################################################################### + # + # U-boot build supports producing a object files to the separate external +@@ -155,6 +174,11 @@ + endif + endif + ++ ++ ++ ++ ++ + export CROSS_COMPILE + + # load other configuration +@@ -163,7 +187,9 @@ + ######################################################################### + # U-Boot objects....order is important (i.e. start must be first) + +-OBJS = cpu/$(CPU)/start.o ++OBJS = cpu/$(CPU)/$(BOARDDIR)/start.o ++OBJS_BOOTSTRAP = cpu/$(CPU)/$(BOARDDIR)/start_bootstrap.o ++ + ifeq ($(CPU),i386) + OBJS += cpu/$(CPU)/start16.o + OBJS += cpu/$(CPU)/reset.o +@@ -186,11 +212,11 @@ + + LIBS = lib_generic/libgeneric.a + LIBS += board/$(BOARDDIR)/lib$(BOARD).a +-LIBS += cpu/$(CPU)/lib$(CPU).a ++LIBS += cpu/$(CPU)/$(BOARDDIR)/lib$(CPU).a + ifdef SOC + LIBS += cpu/$(CPU)/$(SOC)/lib$(SOC).a + endif +-LIBS += lib_$(ARCH)/lib$(ARCH).a ++LIBS += lib_$(ARCH)/$(BOARDIR)/lib$(ARCH).a + LIBS += fs/cramfs/libcramfs.a fs/fat/libfat.a fs/fdos/libfdos.a fs/jffs2/libjffs2.a \ + fs/reiserfs/libreiserfs.a fs/ext2/libext2fs.a + LIBS += net/libnet.a +@@ -198,27 +224,54 @@ + LIBS += rtc/librtc.a + LIBS += dtt/libdtt.a + LIBS += drivers/libdrivers.a +-LIBS += drivers/nand/libnand.a +-LIBS += drivers/nand_legacy/libnand_legacy.a ++#LIBS += drivers/nand_$(BOARDDIR)/libnand.a ++#LIBS += drivers/nand_legacy/libnand_legacy.a + LIBS += drivers/sk98lin/libsk98lin.a + LIBS += post/libpost.a post/cpu/libcpu.a + LIBS += common/libcommon.a + LIBS += $(BOARDLIBS) + + LIBS := $(addprefix $(obj),$(LIBS)) ++ ++ ++LIBS_BOOTSTRAP = lib_bootstrap/libbootstrap.a ++LIBS_BOOTSTRAP+= board/$(BOARDDIR)/lib$(BOARD).a ++#LIBS_BOOTSTRAP+= board/ifx/libifx.a ++LIBS_BOOTSTRAP+= cpu/$(CPU)/$(BOARDDIR)/lib$(CPU).a ++ ++#HEAD_OBJS = cpu/$(CPU)/$(BOARDDIR)/start.o lib_$(ARCH)/board.o ++ ++#HEAD_LIBS = board/$(BOARDDIR)/lib$(BOARD).a ++#HEAD_LIBS += cpu/$(CPU)/$(BOARDDIR)/lib$(CPU).a ++#HEAD_LIBS += lib_$(ARCH)/lib$(ARCH).a ++#HEAD_LIBS += lib_generic/libgeneric.a ++#HEAD_LIBS += common/console.o ++#HEAD_LIBS += common/devices.o ++#HEAD_LIBS += common/cmd_bootm.o ++ ++#.PHONY : $(LIBS) $(HEAD_LIBS) + .PHONY : $(LIBS) ++.PHONY : $(LIBS_BOOTSTRAP) + + # Add GCC lib + PLATFORM_LIBS += -L $(shell dirname `$(CC) $(CFLAGS) -print-libgcc-file-name`) -lgcc + + # The "tools" are needed early, so put this first + # Don't include stuff already done in $(LIBS) ++ #examples + SUBDIRS = tools \ +- examples \ + post \ + post/cpu + .PHONY : $(SUBDIRS) + ++# HEAD_SUBDIRS = tools ++#HEAD_SUBDIRS = lib_generic \ ++# cpu/$(CPU) \ ++# board/$(BOARDDIR) \ ++# common \ ++# lib_$(ARCH) ++#.PHONY : $(HEAD_SUBDIRS) ++ + ifeq ($(CONFIG_NAND_U_BOOT),y) + NAND_SPL = nand_spl + U_BOOT_NAND = $(obj)u-boot-nand.bin +@@ -227,13 +280,76 @@ + __OBJS := $(subst $(obj),,$(OBJS)) + __LIBS := $(subst $(obj),,$(LIBS)) + ++#__HEAD_OBJS := $(subst $(obj),,$(HEAD_OBJS)) ++#__HEAD_LIBS := $(subst $(obj),,$(HEAD_LIBS)) ++ + ######################################################################### + ######################################################################### + + ALL = $(obj)u-boot.srec $(obj)u-boot.bin $(obj)System.map $(U_BOOT_NAND) ++#IFX_ALL = $(obj)u-boot.ifx $(obj)head.srec $(obj)head.bin $(obj)head $(obj)head.map $(COMPRESS_FILE) $(obj)u-boot.srec ++IFX_ALL = $(obj)u-boot.srec $(obj)u-boot.ifx $(obj)u-boot.lzimg $(obj)System.map $(obj)bootstrap.bin + + all: $(ALL) + ++ifx_all: $(IFX_ALL) ++ ++ ++$(obj)u-boot.ifx: $(obj)System.map $(obj)bootstrap.bin $(obj)u-boot.lzimg ++ @cat $(obj)bootstrap.bin > $(obj)u-boot.ifx ++ @cat $(obj)u-boot.lzimg >> $(obj)u-boot.ifx ++ ++$(obj)u-boot.lzimg: $(obj)u-boot.bin System.map ++# @lzma -f -z --best -v $(obj)u-boot.bin ++ @lzma e $(obj)u-boot.bin $(obj)u-boot.bin.lzma ++ @./tools/mkimage -A mips -T firmware -C lzma \ ++ -a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -n 'u-boot image' -d $(obj)u-boot.bin.lzma $@ ++ ++$(obj)ld_uboot.img: $(obj)u-boot.ifx $(obj)u-boot.lzimg $(obj)System.map $(obj)bootstrap.bin ++ @ cp -f $(obj)u-boot.ifx $(obj)u-boot.bin ++ @ ./mkbootimg.incaip2 $(obj)ld_uboot.img < ld_uboot.conf ++ ++ ++ ++ ++$(obj)u-boot.zimg: $(obj)u-boot.bin $(obj)System.map ++ gzip $(obj)u-boot.bin ++ ./tools/mkimage -A $(ARCH) -T firmware -C gzip \ ++ -a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ ++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ ++ -d u-boot.gz $@ ++ ++$(obj)u-boot.bzimg: $(obj)u-boot.bin $(obj)System.map ++ bzip $(obj)u-boot.bin ++ ./tools/mkimage -A $(ARCH) -T firmware -C bzip2 \ ++ -a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ ++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ ++ -d u-boot.bz2 $@ ++ ++$(obj)u-boot.limg: $(obj)u-boot.bin $(obj)System.map ++# @lzma -f -z --best -v $(obj)u-boot.bin ++ @lzma e $(obj)u-boot.bin $(obj)u-boot.bin.lzma ++ ./tools/mkimage -A $(ARCH) -T firmware -C lzma \ ++ -a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ ++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ ++ -d u-boot.bin.lzma $@ ++ ++$(obj)u-boot.img: $(obj)u-boot.bin $(obj)System.map ++ ./tools/mkimage -A $(ARCH) -T firmware -C none \ ++ -a 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -e 0x$(shell grep "T _start" $(TOPDIR)/System.map | awk '{ printf "%s", $$1 }') \ ++ -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ ++ sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ ++ -d u-boot.bin $@ ++ + $(obj)u-boot.hex: $(obj)u-boot + $(OBJCOPY) ${OBJCFLAGS} -O ihex $< $@ + +@@ -243,28 +359,36 @@ + $(obj)u-boot.bin: $(obj)u-boot + $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ + +-$(obj)u-boot.img: $(obj)u-boot.bin +- ./tools/mkimage -A $(ARCH) -T firmware -C none \ +- -a $(TEXT_BASE) -e 0 \ +- -n $(shell sed -n -e 's/.*U_BOOT_VERSION//p' $(VERSION_FILE) | \ +- sed -e 's/"[ ]*$$/ for $(BOARD) board"/') \ +- -d $< $@ +- + $(obj)u-boot.dis: $(obj)u-boot + $(OBJDUMP) -d $< > $@ + +-$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) ++$(obj)u-boot: depend version $(SUBDIRS) $(OBJS) $(LIBS) $(LDSCRIPT) + UNDEF_SYM=`$(OBJDUMP) -x $(LIBS) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ + cd $(LNDIR) && $(LD) $(LDFLAGS) $$UNDEF_SYM $(__OBJS) \ + --start-group $(__LIBS) --end-group $(PLATFORM_LIBS) \ + -Map u-boot.map -o u-boot + ++ ++ ++$(obj)bootstrap.bin: $(obj)bootstrap ++ $(OBJCOPY) ${OBJCFLAGS} -O binary $< $@ ++ ++$(obj)bootstrap : depend version $(SUBDIRS) $(OBJS_BOOTSTRAP) $(LIBS_BOOTSTRAP) $(LDSCRIPT_BOOTSTRAP) ++ UNDEF_SYM=`$(OBJDUMP) -x $(LIBS_BOOTSTRAP) |sed -n -e 's/.*\(__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ ++ $(LD) $(LDFLAGS_BOOTSTRAP) $$UNDEF_SYM $(OBJS_BOOTSTRAP) \ ++ --start-group $(LIBS_BOOTSTRAP) --end-group $(PLATFORM_LIBS) \ ++ -Map bootstrap.map -o bootstrap ++ + $(OBJS): +- $(MAKE) -C cpu/$(CPU) $(if $(REMOTE_BUILD),$@,$(notdir $@)) ++ $(MAKE) -C cpu/$(CPU)/$(BOARDDIR) $(if $(REMOTE_BUILD),$@,$(notdir $@)) + + $(LIBS): + $(MAKE) -C $(dir $(subst $(obj),,$@)) + ++ ++$(LIBS_BOOTSTRAP): ++ $(MAKE) -C `dirname $@` ++ + $(SUBDIRS): + $(MAKE) -C $@ all + +@@ -295,14 +419,14 @@ + + tags ctags: + ctags -w -o $(OBJTREE)/ctags `find $(SUBDIRS) include \ +- lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \ ++ lib_generic board/$(BOARDDIR) cpu/$(CPU)/$(BOARDDIR) lib_$(ARCH) \ + fs/cramfs fs/fat fs/fdos fs/jffs2 \ + net disk rtc dtt drivers drivers/sk98lin common \ + \( -name CVS -prune \) -o \( -name '*.[ch]' -print \)` + + etags: + etags -a -o $(OBJTREE)/etags `find $(SUBDIRS) include \ +- lib_generic board/$(BOARDDIR) cpu/$(CPU) lib_$(ARCH) \ ++ lib_generic board/$(BOARDDIR) cpu/$(CPU)/$(BOARDDIR) lib_$(ARCH) \ + fs/cramfs fs/fat fs/fdos fs/jffs2 \ + net disk rtc dtt drivers drivers/sk98lin common \ + \( -name CVS -prune \) -o \( -name '*.[ch]' -print \)` +@@ -2032,7 +2156,20 @@ + # MIPS + #======================================================================== + ######################################################################### +-## MIPS32 4Kc ++## Infineon MIPS generic u-boot config ++######################################################################### ++danube_config: unconfig ++ @$(MKCONFIG) $(@:_config=) mips mips danube ++ ++amazon_config: unconfig ++ @$(MKCONFIG) $(@:_config=) mips mips amazon ++ ++ ++incaip2_config: unconfig ++ @$(MKCONFIG) $(@:_config=) mips mips incaip2 ++ ++######################################################################### ++## MIPS32 4kc + ######################################################################### + + xtract_incaip = $(subst _100MHz,,$(subst _133MHz,,$(subst _150MHz,,$(subst _config,,$1)))) +@@ -2246,6 +2383,8 @@ + rm -f $(obj)include/bmp_logo.h + find nand_spl -lname "*" -print | xargs rm -f + rm -f nand_spl/u-boot-spl nand_spl/u-boot-spl.map ++ rm -f lib_bootstrap/*.o ++ rm -f lib_bootstrap/*.a + + clobber: clean + find $(OBJTREE) -type f \( -name .depend \ +@@ -2254,7 +2393,7 @@ + | xargs -0 rm -f + rm -f $(OBJS) $(obj)*.bak $(obj)ctags $(obj)etags $(obj)TAGS $(obj)include/version_autogenerated.h + rm -fr $(obj)*.*~ +- rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL) ++ rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL) $(IFX_ALL) + rm -f $(obj)tools/crc32.c $(obj)tools/environment.c $(obj)tools/env/crc32.c + rm -f $(obj)tools/inca-swap-bytes $(obj)cpu/mpc824x/bedbug_603e.c + rm -f $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm +--- /dev/null ++++ b/build_danube.sh +@@ -0,0 +1,28 @@ ++#!/bin/sh ++IFX_CONFIG_FLASH_SIZE=8 ++IFX_CONFIG_MEMORY_SIZE=30 ++CONFIG_RAM_TEXT_BASE=0xA0400000 ++ ++#prepare_headers() ++#{ ++# cp -f include/flash_$1.h \ ++# include/flash.h ++# cp -f include/net_$1.h \ ++# include/net.h ++# cp -f include/asm-mips/cacheops_$1.h \ ++# include/asm-mips/cacheops.h ++# cp -f include/asm-mips/mipsregs_$1.h \ ++# include/asm-mips/mipsregs.h ++#} ++#prepare_headers "danube" ++UBOOT_COMPRESS=lzma ++UBOOT_CFLAGS="-DCONFIG_IFX_MIPS -DCONFIG_LZMA -DIFX_CONFIG_MEMORY_SIZE=${IFX_CONFIG_MEMORY_SIZE} -DIFX_CONFIG_FLASH_SIZE=${IFX_CONFIG_FLASH_SIZE}" ++ ++rm -f .config_ok ++ ++make CROSS_COMPILE="mips-linux-uclibc-" CROSS_COMPILE_UCLIBC=1 COMPRESS=${UBOOT_COMPRESS} PLATFORM_CPU=mips32r2 IFX_CFLAGS="${UBOOT_CFLAGS}" UBOOT_RAM_TEXT_BASE=${CONFIG_RAM_TEXT_BASE} CPU_TYPE=${IFX_CONFIG_CPU} danube_config distclean ++ ++CROSS_COMPILE="mips-linux-uclibc-" CROSS_COMPILE_UCLIBC=1 COMPRESS=${UBOOT_COMPRESS} PLATFORM_CPU=mips32r2 IFX_CFLAGS="${UBOOT_CFLAGS}" make UBOOT_RAM_TEXT_BASE=${CONFIG_RAM_TEXT_BASE} CPU_TYPE=${IFX_CONFIG_CPU} danube_config ++ echo -n > .config_ok ++ ++CROSS_COMPILE="mips-linux-uclibc-" CROSS_COMPILE_UCLIBC=1 COMPRESS=${UBOOT_COMPRESS} PLATFORM_CPU=mips32r2 IFX_CFLAGS="${UBOOT_CFLAGS}" make UBOOT_RAM_TEXT_BASE=${CONFIG_RAM_TEXT_BASE} BOOTSTRAP_PRINTF_STATUS=$2 CPU_TYPE=${IFX_CONFIG_CPU} ifx_all +--- a/common/Makefile ++++ b/common/Makefile +@@ -46,7 +46,7 @@ + env_nand.o env_dataflash.o env_flash.o env_eeprom.o \ + env_nvram.o env_nowhere.o \ + exports.o \ +- flash.o fpga.o ft_build.o \ ++ flash_$(BOARD).o fpga.o ft_build.o \ + hush.o kgdb.o lcd.o lists.o lynxkdi.o \ + memsize.o miiphybb.o miiphyutil.o \ + s_record.o serial.o soft_i2c.o soft_spi.o spartan2.o spartan3.o \ +@@ -60,7 +60,7 @@ + + all: $(LIB) $(AOBJS) + +-$(LIB): $(obj).depend $(OBJS) ++$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + + $(obj)environment.o: $(src)environment.c $(obj)../tools/envcrc +--- a/common/cmd_bootm.c ++++ b/common/cmd_bootm.c +@@ -31,6 +31,7 @@ + #include + #include + #include ++#include + #include + #include + +@@ -79,6 +80,8 @@ + # define CHUNKSZ (64 * 1024) + #endif + ++#ifndef CFG_HEAD_CODE ++ + int gunzip (void *, int, unsigned char *, unsigned long *); + + static void *zalloc(void *, unsigned, unsigned); +@@ -341,6 +344,7 @@ + #endif /* CONFIG_HW_WATCHDOG || CONFIG_WATCHDOG */ + } + break; ++#ifndef CONFIG_REMOVE_GZIP + case IH_COMP_GZIP: + printf (" Uncompressing %s ... ", name); + if (gunzip ((void *)ntohl(hdr->ih_load), unc_len, +@@ -350,6 +354,7 @@ + do_reset (cmdtp, flag, argc, argv); + } + break; ++#endif /* CONFIG_REMOVE_GZIP */ + #ifdef CONFIG_BZIP2 + case IH_COMP_BZIP2: + printf (" Uncompressing %s ... ", name); +@@ -369,6 +374,18 @@ + } + break; + #endif /* CONFIG_BZIP2 */ ++#ifdef CONFIG_LZMA ++ case IH_COMP_LZMA: ++ printf (" Uncompressing %s ... ", name); ++ i = lzma_inflate ((unsigned char *)data, len, (unsigned char*)ntohl(hdr->ih_load), &unc_len); ++ if (i != LZMA_RESULT_OK) { ++ printf ("LZMA ERROR %d - must RESET board to recover\n", i); ++ SHOW_BOOT_PROGRESS (-6); ++ udelay(100000); ++ do_reset (cmdtp, flag, argc, argv); ++ } ++ break; ++#endif /* CONFIG_LZMA */ + default: + if (iflag) + enable_interrupts(); +@@ -1176,6 +1193,8 @@ + ); + #endif /* CFG_CMD_IMLS */ + ++#endif /* ! CFG_HEAD_CODE */ ++ + void + print_image_hdr (image_header_t *hdr) + { +@@ -1270,12 +1289,15 @@ + case IH_COMP_NONE: comp = "uncompressed"; break; + case IH_COMP_GZIP: comp = "gzip compressed"; break; + case IH_COMP_BZIP2: comp = "bzip2 compressed"; break; ++ case IH_COMP_LZMA: comp = "lzma compressed"; break; + default: comp = "unknown compression"; break; + } + + printf ("%s %s %s (%s)", arch, os, type, comp); + } + ++#ifndef CFG_HEAD_CODE ++ + #define ZALLOC_ALIGNMENT 16 + + static void *zalloc(void *x, unsigned items, unsigned size) +@@ -1427,3 +1449,5 @@ + } + + #endif /* CONFIG_LYNXKDI */ ++ ++#endif /* ! CFG_HEAD_CODE */ +--- a/common/cmd_flash.c ++++ b/common/cmd_flash.c +@@ -196,9 +196,17 @@ + } + + static int +-flash_fill_sect_ranges (ulong addr_first, ulong addr_last, +- int *s_first, int *s_last, +- int *s_count ) ++flash_fill_sect_ranges( ++ ulong *addr_first_sect_start, ++ ulong addr_first, ++ ulong *addr_last_sect_end, ++ ulong addr_last, ++ int *s_first, ++ int *s_last, ++ int *bPartialStart, ++ int *bPartialEnd, ++ int *s_count, ++ unsigned int bPartialErase) + { + flash_info_t *info; + ulong bank; +@@ -211,9 +219,7 @@ + s_last [bank] = -1; /* last sector to erase */ + } + +- for (bank=0,info=&flash_info[0]; +- (bank < CFG_MAX_FLASH_BANKS) && (addr_first <= addr_last); +- ++bank, ++info) { ++ for (bank=0, info=&flash_info[0]; (bank < CFG_MAX_FLASH_BANKS) && (addr_first <= addr_last); ++bank, ++info) { + ulong b_end; + int sect; + short s_end; +@@ -225,7 +231,6 @@ + b_end = info->start[0] + info->size - 1; /* bank end addr */ + s_end = info->sector_count - 1; /* last sector */ + +- + for (sect=0; sect < info->sector_count; ++sect) { + ulong end; /* last address in current sect */ + +@@ -238,11 +243,21 @@ + + if (addr_first == info->start[sect]) { + s_first[bank] = sect; ++ } else if (addr_first > info->start[sect] && addr_first <= end && bPartialErase) { ++ *addr_first_sect_start = info->start[sect]; ++ s_first[bank] = sect; ++ *bPartialStart = 1; + } ++ + if (addr_last == end) { + s_last[bank] = sect; ++ } else if (addr_last >= info->start[sect] && addr_last < end && bPartialErase) { ++ *addr_last_sect_end = end; ++ s_last[bank] = sect; ++ *bPartialEnd = 1; + } + } ++ + if (s_first[bank] >= 0) { + if (s_last[bank] < 0) { + if (addr_last > b_end) { +@@ -316,6 +331,8 @@ + struct part_info *part; + u8 dev_type, dev_num, pnum; + #endif ++ unsigned int bPartialErase = 0; ++ + int rcode = 0; + + if (argc < 2) { +@@ -368,8 +385,8 @@ + } + } + #endif +- +- if (argc != 3) { ++ ++ if (argc != 4) { + printf ("Usage:\n%s\n", cmdtp->usage); + return 1; + } +@@ -397,11 +414,117 @@ + return 1; + } + +- rcode = flash_sect_erase(addr_first, addr_last); ++ printf ("Erase Flash from 0x%08lx to 0x%08lx\n", addr_first, addr_last); ++ if(argc == 4) { ++ bPartialErase = simple_strtoul(argv[3], NULL, 10); ++ } ++ ++ rcode = flash_sect_erase(addr_first, addr_last, bPartialErase); + return rcode; + } + +-int flash_sect_erase (ulong addr_first, ulong addr_last) ++int flerase_Partial( ++ ulong addr_first_sect_start, ++ ulong addr_first, ++ ulong addr_last_sect_end, ++ ulong addr_last, ++ flash_info_t *info, ++ int first_sect, ++ int last_sect, ++ int bFirstPartial, ++ int bLastPartial) { ++ unsigned int firstMemLen = 0; ++ unsigned int lastMemLen = 0; ++ unsigned int sectMemLen = 0; ++ uchar *pSavedFirstMem = NULL; ++ uchar *pSavedLastMem = NULL; ++ uchar *pSavedSectMem = NULL; ++ int bSectPartial = 0; ++ int rt_code = 0; ++ ++ debug("%s ... 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%p, %d, %d, %d, %d\n", __FUNCTION__, addr_first_sect_start, addr_first, addr_last_sect_end, addr_last, info, first_sect, last_sect, bFirstPartial, bLastPartial); ++ ++ if (bFirstPartial && bLastPartial && (first_sect == last_sect)) ++ { ++ ulong b_end = info->start[0] + info->size - 1; ++ ulong end = (first_sect == (info->sector_count - 1)) ? b_end : info->start[first_sect + 1] - 1; ++ sectMemLen = end - info->start[first_sect] + 1; ++ pSavedSectMem = (uchar *)calloc(sectMemLen, sizeof(char)); ++ if (pSavedSectMem == NULL) ++ { ++ debug("calloc %u FAILED\n", sectMemLen); ++ rt_code = 1; ++ goto ret; ++ } ++ memset(pSavedSectMem, 0xff, sectMemLen); ++ bSectPartial = 1; ++ memcpy(pSavedSectMem, (uchar *)addr_first_sect_start, addr_first - addr_first_sect_start); ++ memcpy(pSavedSectMem + (addr_last - info->start[first_sect]) + 1, addr_last + 1, end - addr_last); ++ } ++ else ++ { ++ if (bFirstPartial){ ++ firstMemLen = addr_first - addr_first_sect_start + 1; ++ pSavedFirstMem = (uchar *)calloc(firstMemLen,sizeof(char)); ++ memcpy(pSavedFirstMem,(uchar *)addr_first_sect_start,firstMemLen - 1); ++ } ++ if (bLastPartial){ ++ lastMemLen = addr_last_sect_end - addr_last + 1; ++ pSavedLastMem = (uchar *)calloc(lastMemLen,sizeof(char)); ++ memcpy(pSavedLastMem,(uchar *)addr_last + 1,lastMemLen - 1); ++ } ++ } ++ ++ if (bFirstPartial){ ++ if(flash_erase (info, first_sect, first_sect)) { ++ printf("%s ... Couldn't erase sector %d\n", __FUNCTION__, first_sect); ++ rt_code = 1; ++ goto ret; ++ } ++ debug("%s ... erase sector %d done!\n", __FUNCTION__, first_sect); ++ } ++ ++ if (bLastPartial && first_sect != last_sect){ ++ if(flash_erase (info, last_sect, last_sect)) { ++ printf("%s ... Couldn't erase sector %d\n", __FUNCTION__, last_sect); ++ rt_code = 1; ++ goto ret; ++ } ++ debug("%s ... erase sector %d done!\n", __FUNCTION__, last_sect); ++ } ++ ++ if (bFirstPartial && bLastPartial && (first_sect == last_sect)) ++ { ++ flash_write(pSavedSectMem, (uchar *)addr_first_sect_start, sectMemLen); ++ debug("flash_write from 0x%08x with len %u\n", addr_first_sect_start, sectMemLen); ++ } ++ else ++ { ++ if (bFirstPartial){ ++ if(flash_write(pSavedFirstMem,(uchar *)addr_first_sect_start,firstMemLen - 1)) { ++ printf("%s ... Couldn't write at 0x%08lx length %d\n", __FUNCTION__, addr_first_sect_start,firstMemLen - 1); ++ rt_code = 1; ++ goto ret; ++ } ++ } ++ if (bLastPartial){ ++ if(flash_write(pSavedLastMem,(uchar *)addr_last + 1,lastMemLen - 1)) { ++ printf("%s ... Couldn't write at 0x%08lx length %d\n", __FUNCTION__, addr_last, lastMemLen - 1); ++ rt_code = 1; ++ } ++ } ++ } ++ret: ++ if (bFirstPartial) ++ free(pSavedFirstMem); ++ if (bLastPartial) ++ free(pSavedLastMem); ++ if (bSectPartial) ++ free(pSavedSectMem); ++ return rt_code; ++} ++ ++int flash_sect_erase (ulong addr_first, ulong addr_last, unsigned int bPartialErase) + { + flash_info_t *info; + ulong bank; +@@ -413,27 +536,66 @@ + int erased = 0; + int planned; + int rcode = 0; +- +- rcode = flash_fill_sect_ranges (addr_first, addr_last, +- s_first, s_last, &planned ); ++ int bPartialStart = 0; // Start sector has to be erased partially ++ int bPartialEnd = 0; // End sector has to be erased partially ++ ulong addr_first_sect_start = 0;// Sector start address of location addr_start ++ ulong addr_last_sect_end = 0; // Sector end address of location addr_last ++ ++ rcode = flash_fill_sect_ranges ( ++ &addr_first_sect_start, ++ addr_first, ++ &addr_last_sect_end, ++ addr_last, ++ s_first, ++ s_last, ++ &bPartialStart, ++ &bPartialEnd, ++ &planned, ++ bPartialErase ); + + if (planned && (rcode == 0)) { +- for (bank=0,info=&flash_info[0]; +- (bank < CFG_MAX_FLASH_BANKS) && (rcode == 0); +- ++bank, ++info) { ++ for (bank=0, info=&flash_info[0]; (bank < CFG_MAX_FLASH_BANKS) && (rcode == 0); ++bank, ++info) { ++ ulong b_end = info->start[0] + info->size - 1; /* bank end addr */ + if (s_first[bank]>=0) { +- erased += s_last[bank] - s_first[bank] + 1; +- debug ("Erase Flash from 0x%08lx to 0x%08lx " +- "in Bank # %ld ", +- info->start[s_first[bank]], +- (s_last[bank] == info->sector_count) ? +- info->start[0] + info->size - 1: +- info->start[s_last[bank]+1] - 1, +- bank+1); +- rcode = flash_erase (info, s_first[bank], s_last[bank]); ++ if(bPartialErase) { ++ rcode = flerase_Partial( ++ addr_first_sect_start, ++ addr_first, ++ addr_last_sect_end, ++ addr_last, ++ info, ++ s_first[bank], ++ s_last[bank], ++ bPartialStart, ++ bPartialEnd); ++ } ++ ++ //Erase full sectores ++ if (bPartialStart) ++ s_first[bank] += 1; ++ if (bPartialEnd) ++ s_last[bank] -= 1; ++ if (s_last[bank] >= s_first[bank]) { ++ erased += s_last[bank] - s_first[bank] + 1; ++ debug ("Erase Flash from 0x%08lx to 0x%08lx in Bank # %ld ", ++ info->start[s_first[bank]], ++ (s_last[bank] == info->sector_count) ? ++ info->start[0] + info->size - 1: ++ info->start[s_last[bank]+1] - 1, ++ bank + 1); ++ rcode = flash_erase (info, s_first[bank], s_last[bank]); ++ } + } + } +- printf ("Erased %d sectors\n", erased); ++ ++ if (erased && !bPartialErase) { ++ printf ("Erased %d sectors\n", erased); ++ } else if (bPartialErase){ ++ printf ("Partial erased from 0x%08lx to 0x%08lx\n", addr_first, addr_last); ++ } else { ++ printf ("Error: start and/or end address not on sector boundary\n"); ++ rcode = 1; ++ } + } else if (rcode == 0) { + puts ("Error: start and/or end address" + " not on sector boundary\n"); +@@ -629,8 +791,22 @@ + int protected, i; + int planned; + int rcode; +- +- rcode = flash_fill_sect_ranges( addr_first, addr_last, s_first, s_last, &planned ); ++ int bPartialStart = 0; // Start sector has to be erased partially ++ int bPartialEnd = 0; // End sector has to be erased partially ++ ulong addr_first_sect_start = 0;// Sector start address of location addr_start ++ ulong addr_last_sect_end = 0; // Sector end address of location addr_last ++ ++ rcode = flash_fill_sect_ranges ( ++ &addr_first_sect_start, ++ addr_first, ++ &addr_last_sect_end, ++ addr_last, ++ s_first, ++ s_last, ++ &bPartialStart, ++ &bPartialEnd, ++ &planned, ++ 1 ); + + protected = 0; + +@@ -690,7 +866,7 @@ + ); + + U_BOOT_CMD( +- erase, 3, 1, do_flerase, ++ erase, 4, 1, do_flerase, + "erase - erase FLASH memory\n", + "start end\n" + " - erase FLASH from addr 'start' to addr 'end'\n" +--- a/common/cmd_nvedit.c ++++ b/common/cmd_nvedit.c +@@ -540,8 +540,19 @@ + extern char * env_name_spec; + + printf ("Saving Environment to %s...\n", env_name_spec); +- ++#if 1 ++ if(saveenv() == 0) { ++#ifdef UBOOT_ENV_COPY ++ saveenv_copy(); ++#else ++ ; ++#endif //UBOOT_ENV_COPY ++ } else ++ return 1; ++ return 0; ++#else + return (saveenv() ? 1 : 0); ++#endif + } + + +--- a/common/console.c ++++ b/common/console.c +@@ -324,7 +324,7 @@ + #endif + + /** U-Boot INIT FUNCTIONS *************************************************/ +- ++#ifndef CFG_HEAD_CODE + int console_assign (int file, char *devname) + { + int flag, i; +@@ -357,7 +357,7 @@ + + return -1; + } +- ++#endif //CFG_HEAD_CODE + /* Called before relocation - use serial functions */ + int console_init_f (void) + { +@@ -392,6 +392,7 @@ + } + #endif /* CFG_CONSOLE_IS_IN_ENV || CONFIG_SPLASH_SCREEN */ + ++#ifndef CFG_HEAD_CODE + #ifdef CFG_CONSOLE_IS_IN_ENV + /* Called after the relocation - use desired console functions */ + int console_init_r (void) +@@ -570,3 +571,4 @@ + } + + #endif /* CFG_CONSOLE_IS_IN_ENV */ ++#endif //CFG_HEAD_CODE +--- a/common/devices.c ++++ b/common/devices.c +@@ -39,6 +39,7 @@ + list_t devlist = 0; + device_t *stdio_devices[] = { NULL, NULL, NULL }; + char *stdio_names[MAX_FILES] = { "stdin", "stdout", "stderr" }; ++#ifndef CFG_HEAD_CODE + + #if defined(CONFIG_SPLASH_SCREEN) && !defined(CFG_DEVICE_NULLDEV) + #define CFG_DEVICE_NULLDEV 1 +@@ -214,3 +215,5 @@ + + return 0; + } ++#endif //CFG_HEAD_CODE ++ +--- a/common/env_common.c ++++ b/common/env_common.c +@@ -219,7 +219,9 @@ + * We must allocate a buffer for the environment + */ + env_ptr = (env_t *)malloc (CFG_ENV_SIZE); +- DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__,__LINE__,env_ptr); ++ if(!env_ptr) ++ DEBUGF ("malloc env_ptr error!!\n"); ++ DEBUGF ("%s[%d] malloced ENV at %p\n", __FUNCTION__, __LINE__, env_ptr); + #endif + + /* +@@ -227,6 +229,10 @@ + */ + env_get_char = env_get_char_memory; + ++ //leejack ++ DEBUGF ("%s[%d] gd->env_valid=%d\n", __FUNCTION__, __LINE__, gd->env_valid); ++ DEBUGF ("%s[%d] CFG_ENV_SIZE=%d\n", __FUNCTION__, __LINE__, CFG_ENV_SIZE); ++ + if (gd->env_valid == 0) { + #if defined(CONFIG_GTH) || defined(CFG_ENV_IS_NOWHERE) /* Environment not changable */ + puts ("Using default environment\n\n"); +@@ -242,18 +248,17 @@ + } + + memset (env_ptr, 0, sizeof(env_t)); +- memcpy (env_ptr->data, +- default_environment, +- sizeof(default_environment)); ++ memcpy (env_ptr->data, default_environment, sizeof(default_environment)); ++ + #ifdef CFG_REDUNDAND_ENVIRONMENT + env_ptr->flags = 0xFF; + #endif + env_crc_update (); + gd->env_valid = 1; +- } +- else { ++ } else { + env_relocate_spec (); + } ++ + gd->env_addr = (ulong)&(env_ptr->data); + + #ifdef CONFIG_AMIGAONEG3SE +--- a/common/env_flash.c ++++ b/common/env_flash.c +@@ -66,7 +66,6 @@ + #endif + + #else /* ! ENV_IS_EMBEDDED */ +- + env_t *env_ptr = (env_t *)CFG_ENV_ADDR; + #ifdef CMD_SAVEENV + static env_t *flash_addr = (env_t *)CFG_ENV_ADDR; +@@ -201,6 +200,7 @@ + debug (" %08lX ... %08lX ...", + (ulong)&(flash_addr_new->data), + sizeof(env_ptr->data)+(ulong)&(flash_addr_new->data)); ++ + if ((rc = flash_write((char *)env_ptr->data, + (ulong)&(flash_addr_new->data), + sizeof(env_ptr->data))) || +@@ -256,7 +256,6 @@ + #endif /* CMD_SAVEENV */ + + #else /* ! CFG_ENV_ADDR_REDUND */ +- + int env_init(void) + { + #ifdef CONFIG_OMAP2420H4 +@@ -280,8 +279,55 @@ + + #ifdef CMD_SAVEENV + ++#ifdef UBOOT_ENV_COPY ++int saveenv_copy(void) { ++ uchar *env_buffer = (char *)env_ptr; ++ char *kernel_addr; ++ char *rootfs_addr; ++ char *rootfs_size; ++ ulong start_addr,end_addr,rootfs_end_addr; ++ ulong flash_start; ++ ++ kernel_addr = getenv("f_kernel_addr"); ++ end_addr = simple_strtoul(kernel_addr,NULL,16) - 1; ++ start_addr = end_addr - CFG_ENV_SIZE - sizeof(UBOOTCONFIG_COPY_HEADER) + 1; ++ ++ rootfs_addr = getenv("f_rootfs_addr"); ++ rootfs_size = getenv("f_rootfs_size"); ++ rootfs_end_addr = simple_strtoul(rootfs_addr,NULL,16) + simple_strtoul(rootfs_size,NULL,16); ++ ++ if(rootfs_end_addr >= start_addr) ++ { ++ printf("Can not copy the environment at 0x%08lx as no space left.\nf_kernel_addr = 0x%08lx while rootfs_end_addr = 0x%08lx\n",start_addr,end_addr,rootfs_end_addr); ++ return 1; ++ } ++ ++ debug ("Protect off %08lX ... %08lX\n", (ulong)rootfs_end_addr, end_addr); ++ if (flash_sect_protect (0, rootfs_end_addr, end_addr)) ++ return 1; ++ ++ //delete the old environment copy, if found ++ flash_start = rootfs_end_addr; ++ while(flash_start + sizeof(UBOOTCONFIG_COPY_HEADER) + ENV_SIZE < end_addr) ++ { ++ if(strncmp((char *)flash_start,UBOOTCONFIG_COPY_HEADER,sizeof(UBOOTCONFIG_COPY_HEADER)) == 0) ++ { ++ flash_sect_erase(flash_start,flash_start + sizeof(UBOOTCONFIG_COPY_HEADER),1); ++ } ++ flash_start += 1; ++ } ++ flash_sect_erase(start_addr,end_addr,1); ++ flash_write(UBOOTCONFIG_COPY_HEADER,start_addr,sizeof(UBOOTCONFIG_COPY_HEADER)); ++ flash_write(env_buffer,start_addr + sizeof(UBOOTCONFIG_COPY_HEADER), CFG_ENV_SIZE); ++ flash_sect_protect (1, rootfs_end_addr, end_addr); ++ printf("saved copy of the env at 0x%08lx\n",start_addr); ++ return 0; ++} ++#endif //UBOOT_ENV_COPY ++ + int saveenv(void) + { ++#define debug printf + int len, rc; + ulong end_addr; + ulong flash_sect_addr; +@@ -331,7 +377,7 @@ + return 1; + + puts ("Erasing Flash..."); +- if (flash_sect_erase (flash_sect_addr, end_addr)) ++ if (flash_sect_erase (flash_sect_addr, end_addr, 1)) + return 1; + + puts ("Writing to Flash... "); +--- a/common/hush.c ++++ b/common/hush.c +@@ -3167,9 +3167,11 @@ + int code = 0; + #endif + do { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + ctx.type = flag; + initialize_context(&ctx); + update_ifs_map(); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + if (!(flag & FLAG_PARSE_SEMICOLON) || (flag & FLAG_REPARSING)) mapset((uchar *)";$&|", 0); + inp->promptmode=1; + rcode = parse_stream(&temp, &ctx, inp, '\n'); +@@ -3180,9 +3182,12 @@ + syntax(); + #ifdef __U_BOOT__ + flag_repeat = 0; ++printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + #endif ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + } + if (rcode != 1 && ctx.old_flag == 0) { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + done_word(&temp, &ctx); + done_pipe(&ctx,PIPE_SEQ); + #ifndef __U_BOOT__ +@@ -3202,6 +3207,7 @@ + if (code == -1) + flag_repeat = 0; + #endif ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + } else { + if (ctx.old_flag != 0) { + free(ctx.stack); +@@ -3215,6 +3221,7 @@ + temp.quote = 0; + inp->p = NULL; + free_pipe_list(ctx.list_head,0); ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + } + b_free(&temp); + } while (rcode != -1 && !(flag & FLAG_EXIT_FROM_LOOP)); /* loop on syntax errors, return on EOF */ +@@ -3235,9 +3242,12 @@ + #ifdef __U_BOOT__ + char *p = NULL; + int rcode; ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + if ( !s || !*s) + return 1; ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + if (!(p = strchr(s, '\n')) || *++p) { ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + p = xmalloc(strlen(s) + 2); + strcpy(p, s); + strcat(p, "\n"); +@@ -3247,6 +3257,7 @@ + return rcode; + } else { + #endif ++ printf("%s:%s[%d]\n", __FILE__, __func__, __LINE__); + setup_string_in_str(&input, s); + return parse_stream_outer(&input, flag); + #ifdef __U_BOOT__ +--- a/config.mk ++++ b/config.mk +@@ -77,7 +77,7 @@ + sinclude $(TOPDIR)/$(ARCH)_config.mk # include architecture dependend rules + endif + ifdef CPU +-sinclude $(TOPDIR)/cpu/$(CPU)/config.mk # include CPU specific rules ++sinclude $(TOPDIR)/cpu/$(CPU)/$(BOARD)/config.mk # include CPU specific rules + endif + ifdef SOC + sinclude $(TOPDIR)/cpu/$(CPU)/$(SOC)/config.mk # include SoC specific rules +@@ -130,7 +130,8 @@ + ARFLAGS = crv + RELFLAGS= $(PLATFORM_RELFLAGS) + DBGFLAGS= -g # -DDEBUG +-OPTFLAGS= -Os #-fomit-frame-pointer ++OPTFLAGS= -Os ++#-O2 #-fomit-frame-pointer + ifndef LDSCRIPT + #LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds.debug + ifeq ($(CONFIG_NAND_U_BOOT),y) +@@ -139,12 +140,15 @@ + LDSCRIPT := $(TOPDIR)/board/$(BOARDDIR)/u-boot.lds + endif + endif ++ ++LDSCRIPT_BOOTSTRAP := $(TOPDIR)/board/$(BOARDDIR)/u-boot-bootstrap.lds ++ + OBJCFLAGS += --gap-fill=0xff + + gccincdir := $(shell $(CC) -print-file-name=include) + + CPPFLAGS := $(DBGFLAGS) $(OPTFLAGS) $(RELFLAGS) \ +- -D__KERNEL__ -DTEXT_BASE=$(TEXT_BASE) \ ++ -D__KERNEL__ -DUBOOT_RAM_TEXT_BASE=$(UBOOT_RAM_TEXT_BASE) \ + + ifneq ($(OBJTREE),$(SRCTREE)) + CPPFLAGS += -I$(OBJTREE)/include2 -I$(OBJTREE)/include +@@ -180,7 +184,10 @@ + + AFLAGS := $(AFLAGS_DEBUG) -D__ASSEMBLY__ $(CPPFLAGS) + +-LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(TEXT_BASE) $(PLATFORM_LDFLAGS) ++LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(UBOOT_RAM_TEXT_BASE) $(PLATFORM_LDFLAGS) ++LDFLAGS_BOOTSTRAP += -Bstatic -T $(LDSCRIPT_BOOTSTRAP) -Ttext $(BOOTSTRAP_TEXT_BASE) $(PLATFORM_LDFLAGS) ++ ++#HEAD_LDFLAGS += -Bstatic -T $(LDSCRIPT) -Ttext $(HEAD_FLASH_TEXT_BASE) $(PLATFORM_LDFLAGS) + + # Location of a usable BFD library, where we define "usable" as + # "built for ${HOST}, supports ${TARGET}". Sensible values are +@@ -211,10 +218,17 @@ + + ######################################################################### + ++AFLAGS := $(AFLAGS) $(IFX_CFLAGS) ++CFLAGS := $(CFLAGS) $(IFX_CFLAGS) ++CPPFLAGS := $(CPPFLAGS) $(IFX_CFLAGS) ++ ++######################################################################### ++ + export CONFIG_SHELL HPATH HOSTCC HOSTCFLAGS CROSS_COMPILE \ + AS LD CC CPP AR NM STRIP OBJCOPY OBJDUMP \ + MAKE +-export TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS ++#export UBOOT_RAM_TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS ++export UBOOT_RAM_TEXT_BASE BOOTSTRAP_TEXT_BASE PLATFORM_CPPFLAGS PLATFORM_RELFLAGS CPPFLAGS CFLAGS AFLAGS + + ######################################################################### + +--- a/drivers/Makefile ++++ b/drivers/Makefile +@@ -50,14 +50,14 @@ + videomodes.o w83c553f.o \ + ks8695eth.o \ + pxa_pcmcia.o mpc8xx_pcmcia.o tqm8xx_pcmcia.o \ +- rpx_pcmcia.o ++ rpx_pcmcia.o ifx_sw.o + + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) + + all: $(LIB) + +-$(LIB): $(obj).depend $(OBJS) ++$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + + ######################################################################### +--- a/include/asm-mips/mipsregs.h ++++ b/include/asm-mips/mipsregs.h +@@ -48,6 +48,7 @@ + #define CP0_CAUSE $13 + #define CP0_EPC $14 + #define CP0_PRID $15 ++#define CP0_EBASE $15,1 + #define CP0_CONFIG $16 + #define CP0_LLADDR $17 + #define CP0_WATCHLO $18 +@@ -330,11 +331,32 @@ + # define KSU_USER 0x00000010 + # define KSU_SUPERVISOR 0x00000008 + # define KSU_KERNEL 0x00000000 ++#ifdef CONFIG_DANUBE /* MIPS 24KE */ ++/* bits 5 & 6 & 7: reserved */ ++/* bits 8~15: IM0~7 */ ++/* bits 16: reserved */ ++#define ST0_CEE 0x00020000 ++/* bits 18: always 0 */ ++#define ST0_NMI 0x00080000 ++#define ST0_SR 0x00100000 ++#define ST0_TS 0x00200000 ++#define ST0_BEV 0x00400000 ++/* bits 23: reserved */ ++#define ST0_MX 0x01000000 ++#define ST0_RE 0x02000000 ++#define ST0_FR 0x04000000 ++#define ST0_RP 0x08000000 ++#define ST0_CU0 0x10000000 ++#define ST0_CU1 0x20000000 ++#define ST0_CU2 0x40000000 ++#define ST0_CU3 0x80000000 ++#else + #define ST0_UX 0x00000020 + #define ST0_SX 0x00000040 + #define ST0_KX 0x00000080 + #define ST0_DE 0x00010000 + #define ST0_CE 0x00020000 ++#endif + + /* + * Bitfields in the R[23]000 cp0 status register. +@@ -471,6 +493,14 @@ + #define CAUSEF_BD (1 << 31) + + /* ++ * Bits in the coprocessor 0 EBase register ++ */ ++#define EBASEB_CPUNUM 0 ++#define EBASEF_CPUNUM (0x3ff << EBASEB_CPUNUM) ++#define EBASEB_EXPBASE 12 ++#define EBASEF_EXPBASE (0x3ffff << EBASEB_EXPBASE) ++ ++/* + * Bits in the coprozessor 0 config register. + */ + #define CONF_CM_CACHABLE_NO_WA 0 +@@ -544,4 +574,10 @@ + #define CEB_KERNEL 2 /* Count events in kernel mode EXL = ERL = 0 */ + #define CEB_EXL 1 /* Count events with EXL = 1, ERL = 0 */ + ++/* ++ * Bits in ErrCtl register ++ */ ++#define ECCB_WST 29 ++#define ECCF_WST (0x1 << ECCB_WST) ++ + #endif /* _ASM_MIPSREGS_H */ +--- a/include/cmd_confdefs.h ++++ b/include/cmd_confdefs.h +@@ -94,6 +94,7 @@ + #define CFG_CMD_EXT2 0x1000000000000000ULL /* EXT2 Support */ + #define CFG_CMD_SNTP 0x2000000000000000ULL /* SNTP support */ + #define CFG_CMD_DISPLAY 0x4000000000000000ULL /* Display support */ ++#define CFG_CMD_DHRYSTONE 0x8000000000000000ULL /* Dhrystone benchmark support */ + + #define CFG_CMD_ALL 0xFFFFFFFFFFFFFFFFULL /* ALL commands */ + +@@ -141,6 +142,7 @@ + CFG_CMD_SPI | \ + CFG_CMD_UNIVERSE | \ + CFG_CMD_USB | \ ++ CFG_CMD_DHRYSTONE | \ + CFG_CMD_VFD ) + + /* Default configuration +--- /dev/null ++++ b/include/config.h +@@ -0,0 +1,2 @@ ++/* Automatically generated - do not edit */ ++#include +--- /dev/null ++++ b/include/config.mk +@@ -0,0 +1,3 @@ ++ARCH = mips ++CPU = mips ++BOARD = danube +--- a/include/flash.h ++++ b/include/flash.h +@@ -79,7 +79,7 @@ + extern unsigned long flash_init (void); + extern void flash_print_info (flash_info_t *); + extern int flash_erase (flash_info_t *, int, int); +-extern int flash_sect_erase (ulong addr_first, ulong addr_last); ++extern int flash_sect_erase (ulong addr_first, ulong addr_last, unsigned int bPartialErase); + extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last); + + /* common/flash.c */ +@@ -299,6 +299,10 @@ + #define TOSH_ID_FVT160 0xC2 /* TC58FVT160 ID (16 M, top ) */ + #define TOSH_ID_FVB160 0x43 /* TC58FVT160 ID (16 M, bottom ) */ + ++#define MX_ID_29LV320AB 0x22A822A8 /* MXIC MX29LV320AB ID (32 M, bottom ) joelin */ ++#define MX_ID_29LV160BB 0x22492249 /* MXIC MX29LV160BB ID (16 M, bottom ) joelin */ ++#define MX_ID_29LV640BB 0x22cb22cb /* MXIC MX29LV640BB ID (64 M, bottom ) joelin */ ++ + /*----------------------------------------------------------------------- + * Internal FLASH identification codes + * +@@ -422,6 +426,10 @@ + #define FLASH_S29GL064M 0x00F0 /* Spansion S29GL064M-R6 */ + #define FLASH_S29GL128N 0x00F1 /* Spansion S29GL128N */ + ++#define FLASH_29LV320AB 0x00B0 /* MXIC MX29LV320AB( 32M = 4M x 16 ) joelin 10/07/2004*/ ++#define FLASH_29LV160BB 0x00B1 /* MXIC MX29LV160BB( 16M = 2M x 16 ) joelin 11/22/2004*/ ++#define FLASH_29LV640BB 0x00B2 /* MXIC MX29LV640BB( 64M = 8M x 16 ) liupeng*/ ++ + #define FLASH_UNKNOWN 0xFFFF /* unknown flash type */ + + +--- a/include/image.h ++++ b/include/image.h +@@ -132,6 +132,7 @@ + #define IH_COMP_NONE 0 /* No Compression Used */ + #define IH_COMP_GZIP 1 /* gzip Compression Used */ + #define IH_COMP_BZIP2 2 /* bzip2 Compression Used */ ++#define IH_COMP_LZMA 3 /* lzma Compression Used */ + + #define IH_MAGIC 0x27051956 /* Image Magic Number */ + #define IH_NMLEN 32 /* Image Name Length */ +--- /dev/null ++++ b/include/syscall.h +@@ -0,0 +1,42 @@ ++#ifndef __MON_SYS_CALL_H__ ++#define __MON_SYS_CALL_H__ ++ ++#ifndef __ASSEMBLY__ ++ ++#include ++ ++/* These are declarations of system calls available in C code */ ++int mon_getc(void); ++int mon_tstc(void); ++void mon_putc(const char); ++void mon_puts(const char*); ++void mon_printf(const char* fmt, ...); ++void mon_install_hdlr(int, interrupt_handler_t*, void*); ++void mon_free_hdlr(int); ++void *mon_malloc(size_t); ++void mon_free(void*); ++void mon_udelay(unsigned long); ++unsigned long mon_get_timer(unsigned long); ++ ++#endif /* ifndef __ASSEMBLY__ */ ++ ++#define NR_SYSCALLS 11 /* number of syscalls */ ++ ++ ++/* ++ * Make sure these functions are in the same order as they ++ * appear in the "examples/syscall.S" file !!! ++ */ ++#define SYSCALL_GETC 0 ++#define SYSCALL_TSTC 1 ++#define SYSCALL_PUTC 2 ++#define SYSCALL_PUTS 3 ++#define SYSCALL_PRINTF 4 ++#define SYSCALL_INSTALL_HDLR 5 ++#define SYSCALL_FREE_HDLR 6 ++#define SYSCALL_MALLOC 7 ++#define SYSCALL_FREE 8 ++#define SYSCALL_UDELAY 9 ++#define SYSCALL_GET_TIMER 10 ++ ++#endif +--- /dev/null ++++ b/include/version_autogenerated.h +@@ -0,0 +1 @@ ++#define U_BOOT_VERSION "U-Boot 1.1.5-IFX-LXDB-g71af1545" +--- /dev/null ++++ b/ld_uboot.conf +@@ -0,0 +1,8 @@ ++TAG_DWNLD() ++{ ++ 0xA0B00000 "u-boot.bin" /* Download u-boot image */ ++}; ++TAG_START() ++{ ++ 0xA0B00000 ++}; /* Start u-boot image */ +--- a/lib_generic/Makefile ++++ b/lib_generic/Makefile +@@ -28,7 +28,7 @@ + COBJS = bzlib.o bzlib_crctable.o bzlib_decompress.o \ + bzlib_randtable.o bzlib_huffman.o \ + crc32.o ctype.o display_options.o ldiv.o \ +- string.o vsprintf.o zlib.o ++ string.o vsprintf.o zlib.o LzmaDecode.o LzmaWrapper.o + + SRCS := $(COBJS:.o=.c) + OBJS := $(addprefix $(obj),$(COBJS)) +--- a/lib_mips/board.c ++++ b/lib_mips/board.c +@@ -29,6 +29,25 @@ + #include + #include + ++#ifdef CFG_HEAD_CODE ++#undef CONFIG_MICROBZIP2 ++ ++#ifdef CONFIG_BZIP2 ++#include ++#endif ++ ++#ifdef CONFIG_MICROBZIP2 ++#include ++#endif ++ ++#ifdef CONFIG_LZMA ++#include ++#endif ++ ++#include ++#include "head.h" ++#endif //CFG_HEAD_CODE ++ + DECLARE_GLOBAL_DATA_PTR; + + #if ( ((CFG_ENV_ADDR+CFG_ENV_SIZE) < CFG_MONITOR_BASE) || \ +@@ -39,8 +58,6 @@ + #define TOTAL_MALLOC_LEN CFG_MALLOC_LEN + #endif + +-#undef DEBUG +- + extern int timer_init(void); + + extern int incaip_set_cpuclk(void); +@@ -79,6 +96,25 @@ + mem_malloc_end - mem_malloc_start); + } + ++#ifdef CFG_HEAD_CODE ++void *malloc(unsigned int size) { ++ if(size < (mem_malloc_end - mem_malloc_start)) { ++ mem_malloc_start += size; ++ //printf("malloc : size required = 0x%08lx and pointer = 0x%08lx\n",size,mem_malloc_start - size); ++ return (void *)(mem_malloc_start - size); ++ } ++ return NULL; ++} ++ ++void *realloc(void *src,unsigned int size) { ++ return NULL; ++} ++ ++void free(void *src) { ++ return; ++} ++#endif //CFG_HEAD_CODE ++ + void *sbrk (ptrdiff_t increment) + { + ulong old = mem_malloc_brk; +@@ -99,7 +135,11 @@ + #else + int board_type = 0; /* use dummy arg */ + #endif ++#ifdef CONFIG_USE_DDR_RAM ++ puts ("DDR-DRAM: "); ++#else + puts ("DRAM: "); ++#endif + + if ((gd->ram_size = initdram (board_type)) > 0) { + print_size (gd->ram_size, "\n"); +@@ -116,26 +156,29 @@ + return (0); + } + ++#ifndef CFG_HEAD_CODE + static void display_flash_config(ulong size) + { + puts ("Flash: "); + print_size (size, "\n"); + } +- ++#endif + + static int init_baudrate (void) + { ++#ifndef CFG_HEAD_CODE + char tmp[64]; /* long enough for environment variables */ + int i = getenv_r ("baudrate", tmp, sizeof (tmp)); + + gd->baudrate = (i > 0) + ? (int) simple_strtoul (tmp, NULL, 10) + : CONFIG_BAUDRATE; +- ++#else //CFG_HEAD_CODE ++ gd->baudrate = CONFIG_BAUDRATE; ++#endif //CFG_HEAD_CODE + return (0); + } + +- + /* + * Breath some life into the board... + * +@@ -160,7 +203,9 @@ + + init_fnc_t *init_sequence[] = { + timer_init, ++#ifndef CFG_HEAD_CODE + env_init, /* initialize environment */ ++#endif //CFG_HEAD_CODE + #ifdef CONFIG_INCA_IP + incaip_set_cpuclk, /* set cpu clock according to environment variable */ + #endif +@@ -179,7 +224,11 @@ + gd_t gd_data, *id; + bd_t *bd; + init_fnc_t **init_fnc_ptr; ++#ifdef CFG_HEAD_CODE ++ ulong addr, addr_sp, len = (ulong)&uboot_end - CFG_HEAD_BASE; ++#else //CFG_HEAD_CODE + ulong addr, addr_sp, len = (ulong)&uboot_end - CFG_MONITOR_BASE; ++#endif //CFG_HEAD_CODE + ulong *s; + #ifdef CONFIG_PURPLE + void copy_code (ulong); +@@ -278,7 +327,8 @@ + #ifdef CONFIG_PURPLE + copy_code(addr); + #endif +- ++ ++ puts("\n relocate_code start"); + relocate_code (addr_sp, id, addr); + + /* NOTREACHED - relocate_code() does not return */ +@@ -292,7 +342,93 @@ + * + ************************************************************************ + */ ++#ifdef CFG_HEAD_CODE ++ ++extern void print_image_hdr (image_header_t *hdr); ++extern void jump_unconditional (ulong addr); ++ ++void board_init_r (gd_t *id, ulong dest_addr) { ++ int i; ++ ulong addr; ++ ulong data, len, checksum; ++ ulong *len_ptr; ++ image_header_t header; ++ image_header_t *hdr = &header; ++ unsigned int destLen; + ++ puts("\n relocate code finish.\n"); ++ ++ /* initialize malloc() area */ ++ mem_malloc_init(); ++ ++ addr = CFG_HEAD_BASE + CFG_UBOOT_OFFSET; ++ memmove (&header, (char *)addr, sizeof(image_header_t)); ++ ++ if (ntohl(hdr->ih_magic) != IH_MAGIC) { ++ printf ("Bad Magic Number at address 0x%08lx\n",addr); ++ return; ++ } ++ ++ data = (ulong)&header; ++ len = sizeof(image_header_t); ++ ++ checksum = ntohl(hdr->ih_hcrc); ++ hdr->ih_hcrc = 0; ++ if (crc32 (0, (char *)data, len) != checksum) { ++ printf ("Bad Header Checksum\n"); ++ return; ++ } ++ ++ print_image_hdr (hdr); ++ ++ data = addr + sizeof(image_header_t); ++ len = ntohl(hdr->ih_size); ++ len_ptr = (ulong *)data; ++ ++ debug ("Disabling all the interrupts\n"); ++ disable_interrupts(); ++ ++ debug (" Uncompressing UBoot Image ... \n" ); ++ /* ++ * If we've got less than 4 MB of malloc() space, ++ * use slower decompression algorithm which requires ++ * at most 2300 KB of memory. ++ */ ++ destLen = 0x0; ++ ++#ifdef CONFIG_BZIP2 ++ i = BZ2_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), ++ 0x400000, (char *)data, len, ++ CFG_MALLOC_LEN < (4096 * 1024), 0); ++ if (i != BZ_OK) { ++ printf ("BUNZIP2 ERROR %d - must RESET board to recover\n", i); ++ return; ++ } ++#elif CONFIG_MICROBZIP2 ++ i = micro_bzBuffToBuffDecompress ((char*)ntohl(hdr->ih_load), ++ &destLen, (char *)data, len, ++ CFG_MALLOC_LEN < (4096 * 1024), 0); ++ if (i != RETVAL_OK) { ++ printf ("MICRO_BUNZIP2 ERROR %d - must RESET board to recover\n", i); ++ return; ++ } ++#elif CONFIG_LZMA ++ i = lzma_inflate ((char *)data, len, (char*)ntohl(hdr->ih_load), &destLen); ++ if (i != LZMA_RESULT_OK) { ++ printf ("LZMA ERROR %d - must RESET board to recover\n", i); ++ return; ++ } ++#else ++ printf ("NONE Compressing u-boot body!!\n"); ++ memmove ((void *)ntohl(hdr->ih_load), (uchar *)data, len); ++ destLen = len; ++#endif ++ debug (" Uncompression completed successfully with destLen %d.\n ",destLen ); ++ debug ("Head: Jumping to u-boot in the ram at 0x%08lx\n", CFG_MONITOR_BASE); ++ ++ jump_unconditional(CFG_MONITOR_BASE); ++} ++#else //CFG_HEAD_CODE + void board_init_r (gd_t *id, ulong dest_addr) + { + cmd_tbl_t *cmdtp; +@@ -305,6 +441,8 @@ + bd_t *bd; + int i; + ++ puts("\n relocate code finish.\n"); ++ + gd = id; + gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ + +@@ -321,10 +459,10 @@ + ulong addr; + + addr = (ulong) (cmdtp->cmd) + gd->reloc_off; +-#if 0 +- printf ("Command \"%s\": 0x%08lx => 0x%08lx\n", ++ ++ debug ("Command \"%s\": 0x%08lx => 0x%08lx\n", + cmdtp->name, (ulong) (cmdtp->cmd), addr); +-#endif ++ + cmdtp->cmd = + (int (*)(struct cmd_tbl_s *, int, int, char *[]))addr; + +@@ -424,6 +562,7 @@ + + /* NOTREACHED - no way out of command loop except booting */ + } ++#endif //CFG_HEAD_CODE + + void hang (void) + { +--- /dev/null ++++ b/lib_mips/head.h +@@ -0,0 +1,3 @@ ++ ++//#define CFG_HEAD_LEN 0x00006000 ++#define CFG_UBOOT_OFFSET CFG_HEAD_LEN +--- a/lib_mips/time.c ++++ b/lib_mips/time.c +@@ -80,6 +80,17 @@ + /*NOP*/; + } + ++void mdelay (unsigned long msec) ++{ ++ int i,j; ++ for(i=0;i + #include + #include ++#if defined(CONFIG_IFX_MIPS) ++# include "ifx_eth.c" ++#endif + + #if (CONFIG_COMMANDS & CFG_CMD_NET) && defined(CONFIG_NET_MULTI) + +@@ -54,6 +57,9 @@ + extern int skge_initialize(bd_t*); + extern int tsec_initialize(bd_t*, int, char *); + extern int npe_initialize(bd_t *); ++#if defined(CONFIG_IFX_MIPS) ++ IFX_ETH_INITIALIZE_EXTERN ++#endif + + static struct eth_device *eth_devices, *eth_current; + +@@ -235,7 +241,9 @@ + #if defined(CONFIG_RTL8169) + rtl8169_initialize(bis); + #endif +- ++#if defined(CONFIG_IFX_MIPS) ++ IFX_ETH_INITIALIZE(bis) ++#endif + if (!eth_devices) { + puts ("No ethernet found.\n"); + } else { +--- a/tools/Makefile ++++ b/tools/Makefile +@@ -23,7 +23,7 @@ + + BIN_FILES = img2srec$(SFX) mkimage$(SFX) envcrc$(SFX) gen_eth_addr$(SFX) bmp_logo$(SFX) + +-OBJ_LINKS = environment.o crc32.o ++OBJ_LINKS = environment_$(BOARDDIR).o crc32_$(BOARDDIR).o + OBJ_FILES = img2srec.o mkimage.o envcrc.o gen_eth_addr.o bmp_logo.o + + ifeq ($(ARCH),mips) +@@ -117,7 +117,7 @@ + CPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ +- -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC ++ -DTEXT_BASE=$(TEXT_BASE) -DUSE_HOSTCC $(IFX_CFLAGS) + CFLAGS = $(HOST_CFLAGS) $(CPPFLAGS) -O + AFLAGS = -D__ASSEMBLY__ $(CPPFLAGS) + CC = $(HOSTCC) +@@ -126,14 +126,14 @@ + + all: $(obj).depend $(BINS) $(LOGO_H) subdirs + +-$(obj)envcrc$(SFX): $(obj)envcrc.o $(obj)crc32.o $(obj)environment.o ++$(obj)envcrc$(SFX): $(obj)envcrc.o $(obj)crc32_$(BOARDDIR).o $(obj)environment_$(BOARDDIR).o + $(CC) $(CFLAGS) -o $@ $^ + + $(obj)img2srec$(SFX): $(obj)img2srec.o + $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ + $(STRIP) $@ + +-$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32.o ++$(obj)mkimage$(SFX): $(obj)mkimage.o $(obj)crc32_$(BOARDDIR).o + $(CC) $(CFLAGS) $(HOST_LDFLAGS) -o $@ $^ + $(STRIP) $@ + +@@ -160,7 +160,7 @@ + $(obj)envcrc.o: $(src)envcrc.c + $(CC) -g $(CFLAGS) -c -o $@ $< + +-$(obj)crc32.o: $(obj)crc32.c ++$(obj)crc32_$(BOARDDIR).o: $(obj)crc32_$(BOARDDIR).c + $(CC) -g $(CFLAGS) -c -o $@ $< + + $(obj)mkimage.o: $(src)mkimage.c +@@ -192,16 +192,16 @@ + done + endif + +-$(obj)environment.c: +- @rm -f $(obj)environment.c +- ln -s $(src)../common/environment.c $(obj)environment.c ++$(obj)environment_$(BOARDDIR).c: ++ @rm -f $(obj)environment_$(BOARDDIR).c ++ ln -s $(src)../common/environment_$(BOARDDIR).c $(obj)environment_$(BOARDDIR).c + +-$(obj)environment.o: $(obj)environment.c ++$(obj)environment_$(BOARDDIR).o: $(obj)environment_$(BOARDDIR).c + $(CC) -g $(HOST_ENVIRO_CFLAGS) $(CPPFLAGS) -c -o $@ $< + +-$(obj)crc32.c: +- @rm -f $(obj)crc32.c +- ln -s $(src)../lib_generic/crc32.c $(obj)crc32.c ++$(obj)crc32_$(BOARDDIR).c: ++ @rm -f $(obj)crc32_$(BOARDDIR).c ++ ln -s $(src)../lib_generic/crc32_$(BOARDDIR).c $(obj)crc32_$(BOARDDIR).c + + $(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) + $(obj)./bmp_logo $(LOGO_BMP) >$@ +--- a/tools/mkimage.c ++++ b/tools/mkimage.c +@@ -28,6 +28,7 @@ + #ifndef __WIN32__ + #include /* for host / network byte order conversions */ + #endif ++#include + #include + #include + #include +@@ -138,6 +139,7 @@ + { IH_COMP_NONE, "none", "uncompressed", }, + { IH_COMP_BZIP2, "bzip2", "bzip2 compressed", }, + { IH_COMP_GZIP, "gzip", "gzip compressed", }, ++ { IH_COMP_LZMA, "lzma", "lzma compressed", }, + { -1, "", "", }, + }; + +@@ -445,7 +447,7 @@ + } + + /* We're a bit of paranoid */ +-#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) ++#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) + (void) fdatasync (ifd); + #else + (void) fsync (ifd); +@@ -495,7 +497,7 @@ + (void) munmap((void *)ptr, sbuf.st_size); + + /* We're a bit of paranoid */ +-#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) ++#if defined(_POSIX_SYNCHRONIZED_IO) && !defined(__sun__) && !defined(__FreeBSD__) && !defined(__APPLE__) + (void) fdatasync (ifd); + #else + (void) fsync (ifd); diff --git a/target/linux/etrax/config-default b/target/linux/etrax/config-default deleted file mode 100644 index f869b8ae31..0000000000 --- a/target/linux/etrax/config-default +++ /dev/null @@ -1,257 +0,0 @@ -# CONFIG_ARCH_HAS_ILOG2_U32 is not set -# CONFIG_ARCH_HAS_ILOG2_U64 is not set -CONFIG_BASE_SMALL=0 -CONFIG_BITREVERSE=y -CONFIG_BOUNCE=y -CONFIG_CLASSIC_RCU=y -CONFIG_CRIS=y -# CONFIG_CRIS_MACH_ARTPEC3 is not set -CONFIG_CRYPTO_AEAD=m -CONFIG_CRYPTO_ALGAPI=y -CONFIG_CRYPTO_ARC4=y -CONFIG_CRYPTO_AUTHENC=m -CONFIG_CRYPTO_BLKCIPHER=y -CONFIG_CRYPTO_ECB=y -CONFIG_CRYPTO_GF128MUL=m -CONFIG_CRYPTO_MANAGER=y -# CONFIG_ETRAX100LX is not set -CONFIG_ETRAX100LX_V2=y -# CONFIG_ETRAXFS is not set -CONFIG_ETRAX_ARCH_V10=y -# CONFIG_ETRAX_ARCH_V32 is not set -CONFIG_ETRAX_AXISFLASHMAP=y -CONFIG_ETRAX_CMDLINE="root=/dev/mtdblock1 rootfstype=squashfs,jffs2 init=/etc/preinit noinitrd console=ttyS0,115200" -# CONFIG_ETRAX_CSP0_LEDS is not set -# CONFIG_ETRAX_DEBUG_PORT0 is not set -# CONFIG_ETRAX_DEBUG_PORT1 is not set -# CONFIG_ETRAX_DEBUG_PORT2 is not set -# CONFIG_ETRAX_DEBUG_PORT3 is not set -CONFIG_ETRAX_DEBUG_PORT_NULL=y -CONFIG_ETRAX_DEF_R_BUS_CONFIG=0x4 -CONFIG_ETRAX_DEF_R_PORT_PA_DATA=0xf0 -CONFIG_ETRAX_DEF_R_PORT_PA_DIR=0x1c -CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=0x00 -CONFIG_ETRAX_DEF_R_PORT_PB_DATA=0x03 -CONFIG_ETRAX_DEF_R_PORT_PB_DIR=0xce -CONFIG_ETRAX_DEF_R_SDRAM_CONFIG=0x09603737 -CONFIG_ETRAX_DEF_R_SDRAM_TIMING=0x80008002 -CONFIG_ETRAX_DEF_R_WAITSTATES=0x95f8 -CONFIG_ETRAX_DRAM_SIZE=32 -CONFIG_ETRAX_DRAM_VIRTUAL_BASE=c0000000 -CONFIG_ETRAX_DS1302=y -CONFIG_ETRAX_DS1302_RSTBIT=2 -CONFIG_ETRAX_DS1302_RST_ON_GENERIC_PORT=y -CONFIG_ETRAX_DS1302_SCLBIT=1 -CONFIG_ETRAX_DS1302_SDABIT=0 -CONFIG_ETRAX_DS1302_TRICKLE_CHARGE=0 -CONFIG_ETRAX_ETHERNET=y -CONFIG_ETRAX_FAST_TIMER=y -CONFIG_ETRAX_FLASH1_SIZE=0 -CONFIG_ETRAX_FLASH_BUSWIDTH=2 -CONFIG_ETRAX_GPIO=y -CONFIG_ETRAX_I2C=y -CONFIG_ETRAX_I2C_CLK_PORT=1 -CONFIG_ETRAX_I2C_DATA_PORT=0 -# CONFIG_ETRAX_I2C_EEPROM is not set -CONFIG_ETRAX_I2C_USES_PB_NOT_PB_I2C=y -# CONFIG_ETRAX_KMALLOCED_MODULES is not set -CONFIG_ETRAX_LED1G=2 -CONFIG_ETRAX_LED1R=2 -CONFIG_ETRAX_LED2G=3 -CONFIG_ETRAX_LED2R=3 -CONFIG_ETRAX_LED3G=2 -CONFIG_ETRAX_LED3R=2 -CONFIG_ETRAX_NANDFLASH_BUSWIDTH=1 -CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY=y -# CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK is not set -# CONFIG_ETRAX_NO_LEDS is not set -CONFIG_ETRAX_PA_BUTTON_BITMASK=02 -CONFIG_ETRAX_PA_CHANGEABLE_BITS=0xFF -CONFIG_ETRAX_PA_CHANGEABLE_DIR=0xFF -CONFIG_ETRAX_PA_LEDS=y -CONFIG_ETRAX_PB_CHANGEABLE_BITS=0xFF -CONFIG_ETRAX_PB_CHANGEABLE_DIR=0xFF -# CONFIG_ETRAX_PB_LEDS is not set -# CONFIG_ETRAX_PCF8563 is not set -CONFIG_ETRAX_PTABLE_SECTOR=0 -CONFIG_ETRAX_RESCUE_SER0=y -# CONFIG_ETRAX_RESCUE_SER1 is not set -# CONFIG_ETRAX_RESCUE_SER2 is not set -# CONFIG_ETRAX_RESCUE_SER3 is not set -# CONFIG_ETRAX_RS485 is not set -CONFIG_ETRAX_RTC=y -CONFIG_ETRAX_SDRAM=y -CONFIG_ETRAX_SER0_CD_ON_PA_BIT=-1 -CONFIG_ETRAX_SER0_CD_ON_PB_BIT=-1 -CONFIG_ETRAX_SER0_DSR_ON_PA_BIT=-1 -CONFIG_ETRAX_SER0_DSR_ON_PB_BIT=-1 -CONFIG_ETRAX_SER0_DTR_ON_PA_BIT=-1 -CONFIG_ETRAX_SER0_DTR_ON_PB_BIT=-1 -# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_MIXED is not set -CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_NONE=y -# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PA is not set -# CONFIG_ETRAX_SER0_DTR_RI_DSR_CD_ON_PB is not set -CONFIG_ETRAX_SER0_RI_ON_PA_BIT=-1 -CONFIG_ETRAX_SER0_RI_ON_PB_BIT=-1 -CONFIG_ETRAX_SER2_CD_ON_PA_BIT=7 -CONFIG_ETRAX_SER2_CD_ON_PB_BIT=-1 -CONFIG_ETRAX_SER2_DSR_ON_PA_BIT=6 -CONFIG_ETRAX_SER2_DSR_ON_PB_BIT=-1 -CONFIG_ETRAX_SER2_DTR_ON_PA_BIT=4 -CONFIG_ETRAX_SER2_DTR_ON_PB_BIT=-1 -# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_MIXED is not set -# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_NONE is not set -CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PA=y -# CONFIG_ETRAX_SER2_DTR_RI_DSR_CD_ON_PB is not set -CONFIG_ETRAX_SER2_RI_ON_PA_BIT=5 -CONFIG_ETRAX_SER2_RI_ON_PB_BIT=-1 -CONFIG_ETRAX_SER3_CD_ON_PA_BIT=-1 -CONFIG_ETRAX_SER3_CD_ON_PB_BIT=-1 -CONFIG_ETRAX_SER3_DSR_ON_PA_BIT=-1 -CONFIG_ETRAX_SER3_DSR_ON_PB_BIT=-1 -CONFIG_ETRAX_SER3_DTR_ON_PA_BIT=-1 -CONFIG_ETRAX_SER3_DTR_ON_PB_BIT=-1 -# CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_MIXED is not set -CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_ON_NONE=y -# CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_ON_PA is not set -# CONFIG_ETRAX_SER3_DTR_RI_DSR_CD_ON_PB is not set -CONFIG_ETRAX_SER3_RI_ON_PA_BIT=-1 -CONFIG_ETRAX_SER3_RI_ON_PB_BIT=-1 -CONFIG_ETRAX_SERIAL=y -# CONFIG_ETRAX_SERIAL_FAST_TIMER is not set -# CONFIG_ETRAX_SERIAL_FLUSH_DMA_FAST is not set -CONFIG_ETRAX_SERIAL_PORT0=y -# CONFIG_ETRAX_SERIAL_PORT0_DMA0_OUT is not set -# CONFIG_ETRAX_SERIAL_PORT0_DMA1_IN is not set -# CONFIG_ETRAX_SERIAL_PORT0_DMA6_OUT is not set -# CONFIG_ETRAX_SERIAL_PORT0_DMA7_IN is not set -CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_IN=y -CONFIG_ETRAX_SERIAL_PORT0_NO_DMA_OUT=y -# CONFIG_ETRAX_SERIAL_PORT1 is not set -CONFIG_ETRAX_SERIAL_PORT2=y -CONFIG_ETRAX_SERIAL_PORT2_DMA2_OUT=y -CONFIG_ETRAX_SERIAL_PORT2_DMA3_IN=y -# CONFIG_ETRAX_SERIAL_PORT2_DMA6_OUT is not set -# CONFIG_ETRAX_SERIAL_PORT2_DMA7_IN is not set -# CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_IN is not set -# CONFIG_ETRAX_SERIAL_PORT2_NO_DMA_OUT is not set -CONFIG_ETRAX_SERIAL_PORT3=y -# CONFIG_ETRAX_SERIAL_PORT3_DMA2_OUT is not set -# CONFIG_ETRAX_SERIAL_PORT3_DMA3_IN is not set -CONFIG_ETRAX_SERIAL_PORT3_DMA4_OUT=y -CONFIG_ETRAX_SERIAL_PORT3_DMA5_IN=y -# CONFIG_ETRAX_SERIAL_PORT3_DMA8_OUT is not set -# CONFIG_ETRAX_SERIAL_PORT3_DMA9_IN is not set -# CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_IN is not set -# CONFIG_ETRAX_SERIAL_PORT3_NO_DMA_OUT is not set -CONFIG_ETRAX_SERIAL_RX_TIMEOUT_TICKS=1 -# CONFIG_ETRAX_SOFT_SHUTDOWN is not set -# CONFIG_ETRAX_SYNCHRONOUS_SERIAL is not set -CONFIG_ETRAX_USB_HOST=y -CONFIG_ETRAX_USB_HOST_PORT1=y -CONFIG_ETRAX_USB_HOST_PORT2=y -# CONFIG_ETRAX_VCS_SIM is not set -# CONFIG_ETRAX_WATCHDOG is not set -CONFIG_FAT_FS=y -CONFIG_FORCE_MAX_ZONEORDER=6 -CONFIG_FS_POSIX_ACL=y -CONFIG_GENERIC_FIND_NEXT_BIT=y -CONFIG_GENERIC_IOMAP=y -# CONFIG_GEN_RTC is not set -CONFIG_HAS_DMA=y -CONFIG_HAS_IOMEM=y -CONFIG_HAVE_IDE=y -# CONFIG_HAVE_KPROBES is not set -# CONFIG_HAVE_KRETPROBES is not set -# CONFIG_HAVE_OPROFILE is not set -# CONFIG_HOSTAP is not set -# CONFIG_HW_RANDOM is not set -# CONFIG_I2C is not set -# CONFIG_IBM_NEW_EMAC_EMAC4 is not set -# CONFIG_IBM_NEW_EMAC_RGMII is not set -# CONFIG_IBM_NEW_EMAC_TAH is not set -# CONFIG_IBM_NEW_EMAC_ZMII is not set -# CONFIG_IDE is not set -CONFIG_IEEE80211=y -# CONFIG_IEEE80211_CRYPT_CCMP is not set -# CONFIG_IEEE80211_CRYPT_TKIP is not set -CONFIG_IEEE80211_CRYPT_WEP=y -CONFIG_IEEE80211_DEBUG=y -CONFIG_IEEE80211_SOFTMAC=y -CONFIG_IEEE80211_SOFTMAC_DEBUG=y -CONFIG_INITRAMFS_SOURCE="" -CONFIG_LZO_COMPRESS=m -CONFIG_LZO_DECOMPRESS=m -CONFIG_MSDOS_FS=y -CONFIG_MTD=y -CONFIG_MTDRAM_ABS_POS=0x0 -CONFIG_MTDRAM_ERASE_SIZE=128 -CONFIG_MTDRAM_TOTAL_SIZE=0 -# CONFIG_MTD_ABSENT 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=y -CONFIG_MTD_CFI_AMDSTD=y -# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set -# CONFIG_MTD_CFI_GEOMETRY is not set -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_LE_BYTE_SWAP is not set -CONFIG_MTD_CFI_NOSWAP=y -# CONFIG_MTD_CFI_STAA is not set -CONFIG_MTD_CFI_UTIL=y -CONFIG_MTD_CHAR=y -# CONFIG_MTD_CMDLINE_PARTS is not set -CONFIG_MTD_COMPLEX_MAPPINGS=y -CONFIG_MTD_CONCAT=y -# CONFIG_MTD_DEBUG is not set -# CONFIG_MTD_DOC2000 is not set -# CONFIG_MTD_DOC2001 is not set -# CONFIG_MTD_DOC2001PLUS 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=y -# CONFIG_MTD_ONENAND is not set -# CONFIG_MTD_OTP is not set -CONFIG_MTD_PARTITIONS=y -# CONFIG_MTD_PHRAM is not set -# CONFIG_MTD_PHYSMAP is not set -# CONFIG_MTD_PLATRAM 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_NLS=y -CONFIG_NLS_CODEPAGE_437=y -CONFIG_NLS_ISO8859_1=y -CONFIG_NO_IOPORT=y -# CONFIG_OOM_REBOOT is not set -# CONFIG_RTC is not set -CONFIG_RWSEM_GENERIC_SPINLOCK=y -# CONFIG_SERIAL_8250 is not set -CONFIG_SLABINFO=y -# CONFIG_SPARSEMEM_STATIC is not set -# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set -# CONFIG_SVINTO_SIM is not set -# CONFIG_SYSTEM_PROFILER is not set -CONFIG_SYSVIPC_SYSCTL=y -CONFIG_UID16=y -CONFIG_USB=y -# CONFIG_USB_ARCH_HAS_EHCI is not set -# CONFIG_USB_ARCH_HAS_HCD is not set -# CONFIG_USB_ARCH_HAS_OHCI is not set -# CONFIG_USB_R8A66597_HCD is not set -CONFIG_USB_SUPPORT=y -CONFIG_VFAT_FS=y -# CONFIG_VLAN_8021Q is not set diff --git a/target/linux/etrax/files/drivers/usb/host/hc_crisv10.c b/target/linux/etrax/files/drivers/usb/host/hc_crisv10.c deleted file mode 100644 index 32f7caf247..0000000000 --- a/target/linux/etrax/files/drivers/usb/host/hc_crisv10.c +++ /dev/null @@ -1,4550 +0,0 @@ -/* - * usb-host.c: ETRAX 100LX USB Host Controller Driver (HCD) - * - * Copyright (c) 2002, 2003 Axis Communications AB. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -/* Ugly include because we don't live with the other host drivers. */ -#include <../drivers/usb/core/hcd.h> -#include <../drivers/usb/core/usb.h> - -#include "hc_crisv10.h" - -#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR -#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR -#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR - -static const char *usb_hcd_version = "$Revision: 1.2 $"; - -#undef KERN_DEBUG -#define KERN_DEBUG "" - - -#undef USB_DEBUG_RH -#undef USB_DEBUG_EPID -#undef USB_DEBUG_SB -#undef USB_DEBUG_DESC -#undef USB_DEBUG_URB -#undef USB_DEBUG_TRACE -#undef USB_DEBUG_BULK -#undef USB_DEBUG_CTRL -#undef USB_DEBUG_INTR -#undef USB_DEBUG_ISOC - -#ifdef USB_DEBUG_RH -#define dbg_rh(format, arg...) printk(KERN_DEBUG __FILE__ ": (RH) " format "\n" , ## arg) -#else -#define dbg_rh(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_EPID -#define dbg_epid(format, arg...) printk(KERN_DEBUG __FILE__ ": (EPID) " format "\n" , ## arg) -#else -#define dbg_epid(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_SB -#define dbg_sb(format, arg...) printk(KERN_DEBUG __FILE__ ": (SB) " format "\n" , ## arg) -#else -#define dbg_sb(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_CTRL -#define dbg_ctrl(format, arg...) printk(KERN_DEBUG __FILE__ ": (CTRL) " format "\n" , ## arg) -#else -#define dbg_ctrl(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_BULK -#define dbg_bulk(format, arg...) printk(KERN_DEBUG __FILE__ ": (BULK) " format "\n" , ## arg) -#else -#define dbg_bulk(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_INTR -#define dbg_intr(format, arg...) printk(KERN_DEBUG __FILE__ ": (INTR) " format "\n" , ## arg) -#else -#define dbg_intr(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_ISOC -#define dbg_isoc(format, arg...) printk(KERN_DEBUG __FILE__ ": (ISOC) " format "\n" , ## arg) -#else -#define dbg_isoc(format, arg...) do {} while (0) -#endif - -#ifdef USB_DEBUG_TRACE -#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__)) -#define DBFEXIT (printk(": Exiting: %s\n", __FUNCTION__)) -#else -#define DBFENTER do {} while (0) -#define DBFEXIT do {} while (0) -#endif - -#define usb_pipeslow(pipe) (((pipe) >> 26) & 1) - -/*------------------------------------------------------------------- - Virtual Root Hub - -------------------------------------------------------------------*/ - -static __u8 root_hub_dev_des[] = -{ - 0x12, /* __u8 bLength; */ - 0x01, /* __u8 bDescriptorType; Device */ - 0x00, /* __le16 bcdUSB; v1.0 */ - 0x01, - 0x09, /* __u8 bDeviceClass; HUB_CLASSCODE */ - 0x00, /* __u8 bDeviceSubClass; */ - 0x00, /* __u8 bDeviceProtocol; */ - 0x08, /* __u8 bMaxPacketSize0; 8 Bytes */ - 0x00, /* __le16 idVendor; */ - 0x00, - 0x00, /* __le16 idProduct; */ - 0x00, - 0x00, /* __le16 bcdDevice; */ - 0x00, - 0x00, /* __u8 iManufacturer; */ - 0x02, /* __u8 iProduct; */ - 0x01, /* __u8 iSerialNumber; */ - 0x01 /* __u8 bNumConfigurations; */ -}; - -/* Configuration descriptor */ -static __u8 root_hub_config_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x02, /* __u8 bDescriptorType; Configuration */ - 0x19, /* __le16 wTotalLength; */ - 0x00, - 0x01, /* __u8 bNumInterfaces; */ - 0x01, /* __u8 bConfigurationValue; */ - 0x00, /* __u8 iConfiguration; */ - 0x40, /* __u8 bmAttributes; Bit 7: Bus-powered */ - 0x00, /* __u8 MaxPower; */ - - /* interface */ - 0x09, /* __u8 if_bLength; */ - 0x04, /* __u8 if_bDescriptorType; Interface */ - 0x00, /* __u8 if_bInterfaceNumber; */ - 0x00, /* __u8 if_bAlternateSetting; */ - 0x01, /* __u8 if_bNumEndpoints; */ - 0x09, /* __u8 if_bInterfaceClass; HUB_CLASSCODE */ - 0x00, /* __u8 if_bInterfaceSubClass; */ - 0x00, /* __u8 if_bInterfaceProtocol; */ - 0x00, /* __u8 if_iInterface; */ - - /* endpoint */ - 0x07, /* __u8 ep_bLength; */ - 0x05, /* __u8 ep_bDescriptorType; Endpoint */ - 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ - 0x03, /* __u8 ep_bmAttributes; Interrupt */ - 0x08, /* __le16 ep_wMaxPacketSize; 8 Bytes */ - 0x00, - 0xff /* __u8 ep_bInterval; 255 ms */ -}; - -static __u8 root_hub_hub_des[] = -{ - 0x09, /* __u8 bLength; */ - 0x29, /* __u8 bDescriptorType; Hub-descriptor */ - 0x02, /* __u8 bNbrPorts; */ - 0x00, /* __u16 wHubCharacteristics; */ - 0x00, - 0x01, /* __u8 bPwrOn2pwrGood; 2ms */ - 0x00, /* __u8 bHubContrCurrent; 0 mA */ - 0x00, /* __u8 DeviceRemovable; *** 7 Ports max *** */ - 0xff /* __u8 PortPwrCtrlMask; *** 7 ports max *** */ -}; - -static DEFINE_TIMER(bulk_start_timer, NULL, 0, 0); -static DEFINE_TIMER(bulk_eot_timer, NULL, 0, 0); - -/* We want the start timer to expire before the eot timer, because the former might start - traffic, thus making it unnecessary for the latter to time out. */ -#define BULK_START_TIMER_INTERVAL (HZ/10) /* 100 ms */ -#define BULK_EOT_TIMER_INTERVAL (HZ/10+2) /* 120 ms */ - -#define OK(x) len = (x); dbg_rh("OK(%d): line: %d", x, __LINE__); break -#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \ -{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);} - -#define SLAB_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) -#define KMALLOC_FLAG (in_interrupt() ? GFP_ATOMIC : GFP_KERNEL) - -/* Most helpful debugging aid */ -#define assert(expr) ((void) ((expr) ? 0 : (err("assert failed at line %d",__LINE__)))) - -/* Alternative assert define which stops after a failed assert. */ -/* -#define assert(expr) \ -{ \ - if (!(expr)) { \ - err("assert failed at line %d",__LINE__); \ - while (1); \ - } \ -} -*/ - - -/* FIXME: Should RX_BUF_SIZE be a config option, or maybe we should adjust it dynamically? - To adjust it dynamically we would have to get an interrupt when we reach the end - of the rx descriptor list, or when we get close to the end, and then allocate more - descriptors. */ - -#define NBR_OF_RX_DESC 512 -#define RX_DESC_BUF_SIZE 1024 -#define RX_BUF_SIZE (NBR_OF_RX_DESC * RX_DESC_BUF_SIZE) - -/* The number of epids is, among other things, used for pre-allocating - ctrl, bulk and isoc EP descriptors (one for each epid). - Assumed to be > 1 when initiating the DMA lists. */ -#define NBR_OF_EPIDS 32 - -/* Support interrupt traffic intervals up to 128 ms. */ -#define MAX_INTR_INTERVAL 128 - -/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP table - must be "invalid". By this we mean that we shouldn't care about epid attentions - for this epid, or at least handle them differently from epid attentions for "valid" - epids. This define determines which one to use (don't change it). */ -#define INVALID_EPID 31 -/* A special epid for the bulk dummys. */ -#define DUMMY_EPID 30 - -/* This is just a software cache for the valid entries in R_USB_EPT_DATA. */ -static __u32 epid_usage_bitmask; - -/* A bitfield to keep information on in/out traffic is needed to uniquely identify - an endpoint on a device, since the most significant bit which indicates traffic - direction is lacking in the ep_id field (ETRAX epids can handle both in and - out traffic on endpoints that are otherwise identical). The USB framework, however, - relies on them to be handled separately. For example, bulk IN and OUT urbs cannot - be queued in the same list, since they would block each other. */ -static __u32 epid_out_traffic; - -/* DMA IN cache bug. Align the DMA IN buffers to 32 bytes, i.e. a cache line. - Since RX_DESC_BUF_SIZE is 1024 is a multiple of 32, all rx buffers will be cache aligned. */ -static volatile unsigned char RxBuf[RX_BUF_SIZE] __attribute__ ((aligned (32))); -static volatile USB_IN_Desc_t RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4))); - -/* Pointers into RxDescList. */ -static volatile USB_IN_Desc_t *myNextRxDesc; -static volatile USB_IN_Desc_t *myLastRxDesc; -static volatile USB_IN_Desc_t *myPrevRxDesc; - -/* EP descriptors must be 32-bit aligned. */ -static volatile USB_EP_Desc_t TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -static volatile USB_EP_Desc_t TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -/* After each enabled bulk EP (IN or OUT) we put two disabled EP descriptors with the eol flag set, - causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which - gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the - EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors - in each frame. */ -static volatile USB_EP_Desc_t TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4))); - -static volatile USB_EP_Desc_t TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -static volatile USB_SB_Desc_t TxIsocSB_zout __attribute__ ((aligned (4))); - -static volatile USB_EP_Desc_t TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4))); -static volatile USB_SB_Desc_t TxIntrSB_zout __attribute__ ((aligned (4))); - -/* A zout transfer makes a memory access at the address of its buf pointer, which means that setting - this buf pointer to 0 will cause an access to the flash. In addition to this, setting sw_len to 0 - results in a 16/32 bytes (depending on DMA burst size) transfer. Instead, we set it to 1, and point - it to this buffer. */ -static int zout_buffer[4] __attribute__ ((aligned (4))); - -/* Cache for allocating new EP and SB descriptors. */ -static struct kmem_cache *usb_desc_cache; - -/* Cache for the registers allocated in the top half. */ -static struct kmem_cache *top_half_reg_cache; - -/* Cache for the data allocated in the isoc descr top half. */ -static struct kmem_cache *isoc_compl_cache; - -static struct usb_bus *etrax_usb_bus; - -/* This is a circular (double-linked) list of the active urbs for each epid. - The head is never removed, and new urbs are linked onto the list as - urb_entry_t elements. Don't reference urb_list directly; use the wrapper - functions instead. Note that working with these lists might require spinlock - protection. */ -static struct list_head urb_list[NBR_OF_EPIDS]; - -/* Read about the need and usage of this lock in submit_ctrl_urb. */ -static spinlock_t urb_list_lock; - -/* Used when unlinking asynchronously. */ -static struct list_head urb_unlink_list; - -/* for returning string descriptors in UTF-16LE */ -static int ascii2utf (char *ascii, __u8 *utf, int utfmax) -{ - int retval; - - for (retval = 0; *ascii && utfmax > 1; utfmax -= 2, retval += 2) { - *utf++ = *ascii++ & 0x7f; - *utf++ = 0; - } - return retval; -} - -static int usb_root_hub_string (int id, int serial, char *type, __u8 *data, int len) -{ - char buf [30]; - - // assert (len > (2 * (sizeof (buf) + 1))); - // assert (strlen (type) <= 8); - - // language ids - if (id == 0) { - *data++ = 4; *data++ = 3; /* 4 bytes data */ - *data++ = 0; *data++ = 0; /* some language id */ - return 4; - - // serial number - } else if (id == 1) { - sprintf (buf, "%x", serial); - - // product description - } else if (id == 2) { - sprintf (buf, "USB %s Root Hub", type); - - // id 3 == vendor description - - // unsupported IDs --> "stall" - } else - return 0; - - data [0] = 2 + ascii2utf (buf, data + 2, len - 2); - data [1] = 3; - return data [0]; -} - -/* Wrappers around the list functions (include/linux/list.h). */ - -static inline int urb_list_empty(int epid) -{ - return list_empty(&urb_list[epid]); -} - -/* Returns first urb for this epid, or NULL if list is empty. */ -static inline struct urb *urb_list_first(int epid) -{ - struct urb *first_urb = 0; - - if (!urb_list_empty(epid)) { - /* Get the first urb (i.e. head->next). */ - urb_entry_t *urb_entry = list_entry((&urb_list[epid])->next, urb_entry_t, list); - first_urb = urb_entry->urb; - } - return first_urb; -} - -/* Adds an urb_entry last in the list for this epid. */ -static inline void urb_list_add(struct urb *urb, int epid) -{ - urb_entry_t *urb_entry = kmalloc(sizeof(urb_entry_t), KMALLOC_FLAG); - assert(urb_entry); - - urb_entry->urb = urb; - list_add_tail(&urb_entry->list, &urb_list[epid]); -} - -/* Search through the list for an element that contains this urb. (The list - is expected to be short and the one we are about to delete will often be - the first in the list.) */ -static inline urb_entry_t *__urb_list_entry(struct urb *urb, int epid) -{ - struct list_head *entry; - struct list_head *tmp; - urb_entry_t *urb_entry; - - list_for_each_safe(entry, tmp, &urb_list[epid]) { - urb_entry = list_entry(entry, urb_entry_t, list); - assert(urb_entry); - assert(urb_entry->urb); - - if (urb_entry->urb == urb) { - return urb_entry; - } - } - return 0; -} - -/* Delete an urb from the list. */ -static inline void urb_list_del(struct urb *urb, int epid) -{ - urb_entry_t *urb_entry = __urb_list_entry(urb, epid); - assert(urb_entry); - - /* Delete entry and free. */ - list_del(&urb_entry->list); - kfree(urb_entry); -} - -/* Move an urb to the end of the list. */ -static inline void urb_list_move_last(struct urb *urb, int epid) -{ - urb_entry_t *urb_entry = __urb_list_entry(urb, epid); - assert(urb_entry); - - list_move_tail(&urb_entry->list, &urb_list[epid]); -} - -/* Get the next urb in the list. */ -static inline struct urb *urb_list_next(struct urb *urb, int epid) -{ - urb_entry_t *urb_entry = __urb_list_entry(urb, epid); - - assert(urb_entry); - - if (urb_entry->list.next != &urb_list[epid]) { - struct list_head *elem = urb_entry->list.next; - urb_entry = list_entry(elem, urb_entry_t, list); - return urb_entry->urb; - } else { - return NULL; - } -} - - - -/* For debug purposes only. */ -static inline void urb_list_dump(int epid) -{ - struct list_head *entry; - struct list_head *tmp; - urb_entry_t *urb_entry; - int i = 0; - - info("Dumping urb list for epid %d", epid); - - list_for_each_safe(entry, tmp, &urb_list[epid]) { - urb_entry = list_entry(entry, urb_entry_t, list); - info(" entry %d, urb = 0x%lx", i, (unsigned long)urb_entry->urb); - } -} - -static void init_rx_buffers(void); -static int etrax_rh_unlink_urb(struct urb *urb); -static void etrax_rh_send_irq(struct urb *urb); -static void etrax_rh_init_int_timer(struct urb *urb); -static void etrax_rh_int_timer_do(unsigned long ptr); - -static int etrax_usb_setup_epid(struct urb *urb); -static int etrax_usb_lookup_epid(struct urb *urb); -static int etrax_usb_allocate_epid(void); -static void etrax_usb_free_epid(int epid); - -static int etrax_remove_from_sb_list(struct urb *urb); - -static void* etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size, - unsigned mem_flags, dma_addr_t *dma); -static void etrax_usb_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma); - -static void etrax_usb_add_to_bulk_sb_list(struct urb *urb, int epid); -static void etrax_usb_add_to_ctrl_sb_list(struct urb *urb, int epid); -static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid); -static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid); - -static int etrax_usb_submit_bulk_urb(struct urb *urb); -static int etrax_usb_submit_ctrl_urb(struct urb *urb); -static int etrax_usb_submit_intr_urb(struct urb *urb); -static int etrax_usb_submit_isoc_urb(struct urb *urb); - -static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags); -static int etrax_usb_unlink_urb(struct urb *urb, int status); -static int etrax_usb_get_frame_number(struct usb_device *usb_dev); - -static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc); -static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc); -static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc); -static void etrax_usb_hc_interrupt_bottom_half(void *data); - -static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data); - - -/* The following is a list of interrupt handlers for the host controller interrupts we use. - They are called from etrax_usb_hc_interrupt_bottom_half. */ -static void etrax_usb_hc_isoc_eof_interrupt(void); -static void etrax_usb_hc_bulk_eot_interrupt(int timer_induced); -static void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg); -static void etrax_usb_hc_port_status_interrupt(usb_interrupt_registers_t *reg); -static void etrax_usb_hc_ctl_status_interrupt(usb_interrupt_registers_t *reg); - -static int etrax_rh_submit_urb (struct urb *urb); - -/* Forward declaration needed because they are used in the rx interrupt routine. */ -static void etrax_usb_complete_urb(struct urb *urb, int status); -static void etrax_usb_complete_bulk_urb(struct urb *urb, int status); -static void etrax_usb_complete_ctrl_urb(struct urb *urb, int status); -static void etrax_usb_complete_intr_urb(struct urb *urb, int status); -static void etrax_usb_complete_isoc_urb(struct urb *urb, int status); - -static int etrax_usb_hc_init(void); -static void etrax_usb_hc_cleanup(void); - -static struct usb_operations etrax_usb_device_operations = -{ - .get_frame_number = etrax_usb_get_frame_number, - .submit_urb = etrax_usb_submit_urb, - .unlink_urb = etrax_usb_unlink_urb, - .buffer_alloc = etrax_usb_buffer_alloc, - .buffer_free = etrax_usb_buffer_free -}; - -/* Note that these functions are always available in their "__" variants, for use in - error situations. The "__" missing variants are controlled by the USB_DEBUG_DESC/ - USB_DEBUG_URB macros. */ -static void __dump_urb(struct urb* purb) -{ - printk("\nurb :0x%08lx\n", (unsigned long)purb); - printk("dev :0x%08lx\n", (unsigned long)purb->dev); - printk("pipe :0x%08x\n", purb->pipe); - printk("status :%d\n", purb->status); - printk("transfer_flags :0x%08x\n", purb->transfer_flags); - printk("transfer_buffer :0x%08lx\n", (unsigned long)purb->transfer_buffer); - printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length); - printk("actual_length :%d\n", purb->actual_length); - printk("setup_packet :0x%08lx\n", (unsigned long)purb->setup_packet); - printk("start_frame :%d\n", purb->start_frame); - printk("number_of_packets :%d\n", purb->number_of_packets); - printk("interval :%d\n", purb->interval); - printk("error_count :%d\n", purb->error_count); - printk("context :0x%08lx\n", (unsigned long)purb->context); - printk("complete :0x%08lx\n\n", (unsigned long)purb->complete); -} - -static void __dump_in_desc(volatile USB_IN_Desc_t *in) -{ - printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in); - printk(" sw_len : 0x%04x (%d)\n", in->sw_len, in->sw_len); - printk(" command : 0x%04x\n", in->command); - printk(" next : 0x%08lx\n", in->next); - printk(" buf : 0x%08lx\n", in->buf); - printk(" hw_len : 0x%04x (%d)\n", in->hw_len, in->hw_len); - printk(" status : 0x%04x\n\n", in->status); -} - -static void __dump_sb_desc(volatile USB_SB_Desc_t *sb) -{ - char tt = (sb->command & 0x30) >> 4; - char *tt_string; - - switch (tt) { - case 0: - tt_string = "zout"; - break; - case 1: - tt_string = "in"; - break; - case 2: - tt_string = "out"; - break; - case 3: - tt_string = "setup"; - break; - default: - tt_string = "unknown (weird)"; - } - - printk("\n USB_SB_Desc at 0x%08lx\n", (unsigned long)sb); - printk(" command : 0x%04x\n", sb->command); - printk(" rem : %d\n", (sb->command & 0x3f00) >> 8); - printk(" full : %d\n", (sb->command & 0x40) >> 6); - printk(" tt : %d (%s)\n", tt, tt_string); - printk(" intr : %d\n", (sb->command & 0x8) >> 3); - printk(" eot : %d\n", (sb->command & 0x2) >> 1); - printk(" eol : %d\n", sb->command & 0x1); - printk(" sw_len : 0x%04x (%d)\n", sb->sw_len, sb->sw_len); - printk(" next : 0x%08lx\n", sb->next); - printk(" buf : 0x%08lx\n\n", sb->buf); -} - - -static void __dump_ep_desc(volatile USB_EP_Desc_t *ep) -{ - printk("\nUSB_EP_Desc at 0x%08lx\n", (unsigned long)ep); - printk(" command : 0x%04x\n", ep->command); - printk(" ep_id : %d\n", (ep->command & 0x1f00) >> 8); - printk(" enable : %d\n", (ep->command & 0x10) >> 4); - printk(" intr : %d\n", (ep->command & 0x8) >> 3); - printk(" eof : %d\n", (ep->command & 0x2) >> 1); - printk(" eol : %d\n", ep->command & 0x1); - printk(" hw_len : 0x%04x (%d)\n", ep->hw_len, ep->hw_len); - printk(" next : 0x%08lx\n", ep->next); - printk(" sub : 0x%08lx\n\n", ep->sub); -} - -static inline void __dump_ep_list(int pipe_type) -{ - volatile USB_EP_Desc_t *ep; - volatile USB_EP_Desc_t *first_ep; - volatile USB_SB_Desc_t *sb; - - switch (pipe_type) - { - case PIPE_BULK: - first_ep = &TxBulkEPList[0]; - break; - case PIPE_CONTROL: - first_ep = &TxCtrlEPList[0]; - break; - case PIPE_INTERRUPT: - first_ep = &TxIntrEPList[0]; - break; - case PIPE_ISOCHRONOUS: - first_ep = &TxIsocEPList[0]; - break; - default: - warn("Cannot dump unknown traffic type"); - return; - } - ep = first_ep; - - printk("\n\nDumping EP list...\n\n"); - - do { - __dump_ep_desc(ep); - /* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */ - sb = ep->sub ? phys_to_virt(ep->sub) : 0; - while (sb) { - __dump_sb_desc(sb); - sb = sb->next ? phys_to_virt(sb->next) : 0; - } - ep = (volatile USB_EP_Desc_t *)(phys_to_virt(ep->next)); - - } while (ep != first_ep); -} - -static inline void __dump_ept_data(int epid) -{ - unsigned long flags; - __u32 r_usb_ept_data; - - if (epid < 0 || epid > 31) { - printk("Cannot dump ept data for invalid epid %d\n", epid); - return; - } - - save_flags(flags); - cli(); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); - - printk("\nR_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid); - if (r_usb_ept_data == 0) { - /* No need for more detailed printing. */ - return; - } - printk(" valid : %d\n", (r_usb_ept_data & 0x80000000) >> 31); - printk(" hold : %d\n", (r_usb_ept_data & 0x40000000) >> 30); - printk(" error_count_in : %d\n", (r_usb_ept_data & 0x30000000) >> 28); - printk(" t_in : %d\n", (r_usb_ept_data & 0x08000000) >> 27); - printk(" low_speed : %d\n", (r_usb_ept_data & 0x04000000) >> 26); - printk(" port : %d\n", (r_usb_ept_data & 0x03000000) >> 24); - printk(" error_code : %d\n", (r_usb_ept_data & 0x00c00000) >> 22); - printk(" t_out : %d\n", (r_usb_ept_data & 0x00200000) >> 21); - printk(" error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19); - printk(" max_len : %d\n", (r_usb_ept_data & 0x0003f800) >> 11); - printk(" ep : %d\n", (r_usb_ept_data & 0x00000780) >> 7); - printk(" dev : %d\n", (r_usb_ept_data & 0x0000003f)); -} - -static inline void __dump_ept_data_list(void) -{ - int i; - - printk("Dumping the whole R_USB_EPT_DATA list\n"); - - for (i = 0; i < 32; i++) { - __dump_ept_data(i); - } -} -#ifdef USB_DEBUG_DESC -#define dump_in_desc(...) __dump_in_desc(...) -#define dump_sb_desc(...) __dump_sb_desc(...) -#define dump_ep_desc(...) __dump_ep_desc(...) -#else -#define dump_in_desc(...) do {} while (0) -#define dump_sb_desc(...) do {} while (0) -#define dump_ep_desc(...) do {} while (0) -#endif - -#ifdef USB_DEBUG_URB -#define dump_urb(x) __dump_urb(x) -#else -#define dump_urb(x) do {} while (0) -#endif - -static void init_rx_buffers(void) -{ - int i; - - DBFENTER; - - for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) { - RxDescList[i].sw_len = RX_DESC_BUF_SIZE; - RxDescList[i].command = 0; - RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]); - RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE)); - RxDescList[i].hw_len = 0; - RxDescList[i].status = 0; - - /* DMA IN cache bug. (struct etrax_dma_descr has the same layout as USB_IN_Desc - for the relevant fields.) */ - prepare_rx_descriptor((struct etrax_dma_descr*)&RxDescList[i]); - - } - - RxDescList[i].sw_len = RX_DESC_BUF_SIZE; - RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes); - RxDescList[i].next = virt_to_phys(&RxDescList[0]); - RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE)); - RxDescList[i].hw_len = 0; - RxDescList[i].status = 0; - - myNextRxDesc = &RxDescList[0]; - myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; - myPrevRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; - - *R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc); - *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start); - - DBFEXIT; -} - -static void init_tx_bulk_ep(void) -{ - int i; - - DBFENTER; - - for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { - CHECK_ALIGN(&TxBulkEPList[i]); - TxBulkEPList[i].hw_len = 0; - TxBulkEPList[i].command = IO_FIELD(USB_EP_command, epid, i); - TxBulkEPList[i].sub = 0; - TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[i + 1]); - - /* Initiate two EPs, disabled and with the eol flag set. No need for any - preserved epid. */ - - /* The first one has the intr flag set so we get an interrupt when the DMA - channel is about to become disabled. */ - CHECK_ALIGN(&TxBulkDummyEPList[i][0]); - TxBulkDummyEPList[i][0].hw_len = 0; - TxBulkDummyEPList[i][0].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) | - IO_STATE(USB_EP_command, eol, yes) | - IO_STATE(USB_EP_command, intr, yes)); - TxBulkDummyEPList[i][0].sub = 0; - TxBulkDummyEPList[i][0].next = virt_to_phys(&TxBulkDummyEPList[i][1]); - - /* The second one. */ - CHECK_ALIGN(&TxBulkDummyEPList[i][1]); - TxBulkDummyEPList[i][1].hw_len = 0; - TxBulkDummyEPList[i][1].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) | - IO_STATE(USB_EP_command, eol, yes)); - TxBulkDummyEPList[i][1].sub = 0; - /* The last dummy's next pointer is the same as the current EP's next pointer. */ - TxBulkDummyEPList[i][1].next = virt_to_phys(&TxBulkEPList[i + 1]); - } - - /* Configure the last one. */ - CHECK_ALIGN(&TxBulkEPList[i]); - TxBulkEPList[i].hw_len = 0; - TxBulkEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) | - IO_FIELD(USB_EP_command, epid, i)); - TxBulkEPList[i].sub = 0; - TxBulkEPList[i].next = virt_to_phys(&TxBulkEPList[0]); - - /* No need configuring dummy EPs for the last one as it will never be used for - bulk traffic (i == INVALD_EPID at this point). */ - - /* Set up to start on the last EP so we will enable it when inserting traffic - for the first time (imitating the situation where the DMA has stopped - because there was no more traffic). */ - *R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[i]); - /* No point in starting the bulk channel yet. - *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */ - DBFEXIT; -} - -static void init_tx_ctrl_ep(void) -{ - int i; - - DBFENTER; - - for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { - CHECK_ALIGN(&TxCtrlEPList[i]); - TxCtrlEPList[i].hw_len = 0; - TxCtrlEPList[i].command = IO_FIELD(USB_EP_command, epid, i); - TxCtrlEPList[i].sub = 0; - TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[i + 1]); - } - - CHECK_ALIGN(&TxCtrlEPList[i]); - TxCtrlEPList[i].hw_len = 0; - TxCtrlEPList[i].command = (IO_STATE(USB_EP_command, eol, yes) | - IO_FIELD(USB_EP_command, epid, i)); - - TxCtrlEPList[i].sub = 0; - TxCtrlEPList[i].next = virt_to_phys(&TxCtrlEPList[0]); - - *R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[0]); - *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start); - - DBFEXIT; -} - - -static void init_tx_intr_ep(void) -{ - int i; - - DBFENTER; - - /* Read comment at zout_buffer declaration for an explanation to this. */ - TxIntrSB_zout.sw_len = 1; - TxIntrSB_zout.next = 0; - TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[0]); - TxIntrSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, zout) | - IO_STATE(USB_SB_command, full, yes) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) { - CHECK_ALIGN(&TxIntrEPList[i]); - TxIntrEPList[i].hw_len = 0; - TxIntrEPList[i].command = - (IO_STATE(USB_EP_command, eof, yes) | - IO_STATE(USB_EP_command, enable, yes) | - IO_FIELD(USB_EP_command, epid, INVALID_EPID)); - TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout); - TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]); - } - - CHECK_ALIGN(&TxIntrEPList[i]); - TxIntrEPList[i].hw_len = 0; - TxIntrEPList[i].command = - (IO_STATE(USB_EP_command, eof, yes) | - IO_STATE(USB_EP_command, eol, yes) | - IO_STATE(USB_EP_command, enable, yes) | - IO_FIELD(USB_EP_command, epid, INVALID_EPID)); - TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout); - TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[0]); - - *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]); - *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start); - DBFEXIT; -} - -static void init_tx_isoc_ep(void) -{ - int i; - - DBFENTER; - - /* Read comment at zout_buffer declaration for an explanation to this. */ - TxIsocSB_zout.sw_len = 1; - TxIsocSB_zout.next = 0; - TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]); - TxIsocSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, zout) | - IO_STATE(USB_SB_command, full, yes) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - /* The last isochronous EP descriptor is a dummy. */ - - for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { - CHECK_ALIGN(&TxIsocEPList[i]); - TxIsocEPList[i].hw_len = 0; - TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i); - TxIsocEPList[i].sub = 0; - TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]); - } - - CHECK_ALIGN(&TxIsocEPList[i]); - TxIsocEPList[i].hw_len = 0; - - /* Must enable the last EP descr to get eof interrupt. */ - TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) | - IO_STATE(USB_EP_command, eof, yes) | - IO_STATE(USB_EP_command, eol, yes) | - IO_FIELD(USB_EP_command, epid, INVALID_EPID)); - TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout); - TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]); - - *R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]); - *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start); - - DBFEXIT; -} - -static void etrax_usb_unlink_intr_urb(struct urb *urb) -{ - volatile USB_EP_Desc_t *first_ep; /* First EP in the list. */ - volatile USB_EP_Desc_t *curr_ep; /* Current EP, the iterator. */ - volatile USB_EP_Desc_t *next_ep; /* The EP after current. */ - volatile USB_EP_Desc_t *unlink_ep; /* The one we should remove from the list. */ - - int epid; - - /* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the List". */ - - DBFENTER; - - epid = ((etrax_urb_priv_t *)urb->hcpriv)->epid; - - first_ep = &TxIntrEPList[0]; - curr_ep = first_ep; - - - /* Note that this loop removes all EP descriptors with this epid. This assumes - that all EP descriptors belong to the one and only urb for this epid. */ - - do { - next_ep = (USB_EP_Desc_t *)phys_to_virt(curr_ep->next); - - if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) { - - dbg_intr("Found EP to unlink for epid %d", epid); - - /* This is the one we should unlink. */ - unlink_ep = next_ep; - - /* Actually unlink the EP from the DMA list. */ - curr_ep->next = unlink_ep->next; - - /* Wait until the DMA is no longer at this descriptor. */ - while (*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep)); - - /* Now we are free to remove it and its SB descriptor. - Note that it is assumed here that there is only one sb in the - sb list for this ep. */ - kmem_cache_free(usb_desc_cache, phys_to_virt(unlink_ep->sub)); - kmem_cache_free(usb_desc_cache, (USB_EP_Desc_t *)unlink_ep); - } - - curr_ep = phys_to_virt(curr_ep->next); - - } while (curr_ep != first_ep); - urb->hcpriv = NULL; -} - -void etrax_usb_do_intr_recover(int epid) -{ - USB_EP_Desc_t *first_ep, *tmp_ep; - - DBFENTER; - - first_ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB2_EP); - tmp_ep = first_ep; - - /* What this does is simply to walk the list of interrupt - ep descriptors and enable those that are disabled. */ - - do { - if (IO_EXTRACT(USB_EP_command, epid, tmp_ep->command) == epid && - !(tmp_ep->command & IO_MASK(USB_EP_command, enable))) { - tmp_ep->command |= IO_STATE(USB_EP_command, enable, yes); - } - - tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next); - - } while (tmp_ep != first_ep); - - - DBFEXIT; -} - -static int etrax_rh_unlink_urb (struct urb *urb) -{ - etrax_hc_t *hc; - - DBFENTER; - - hc = urb->dev->bus->hcpriv; - - if (hc->rh.urb == urb) { - hc->rh.send = 0; - del_timer(&hc->rh.rh_int_timer); - } - - DBFEXIT; - return 0; -} - -static void etrax_rh_send_irq(struct urb *urb) -{ - __u16 data = 0; - etrax_hc_t *hc = urb->dev->bus->hcpriv; - DBFENTER; - -/* - dbg_rh("R_USB_FM_NUMBER : 0x%08X", *R_USB_FM_NUMBER); - dbg_rh("R_USB_FM_REMAINING: 0x%08X", *R_USB_FM_REMAINING); -*/ - - data |= (hc->rh.wPortChange_1) ? (1 << 1) : 0; - data |= (hc->rh.wPortChange_2) ? (1 << 2) : 0; - - *((__u16 *)urb->transfer_buffer) = cpu_to_le16(data); - /* FIXME: Why is actual_length set to 1 when data is 2 bytes? - Since only 1 byte is used, why not declare data as __u8? */ - urb->actual_length = 1; - urb->status = 0; - - if (hc->rh.send && urb->complete) { - dbg_rh("wPortChange_1: 0x%04X", hc->rh.wPortChange_1); - dbg_rh("wPortChange_2: 0x%04X", hc->rh.wPortChange_2); - - urb->complete(urb, NULL); - } - - DBFEXIT; -} - -static void etrax_rh_init_int_timer(struct urb *urb) -{ - etrax_hc_t *hc; - - DBFENTER; - - hc = urb->dev->bus->hcpriv; - hc->rh.interval = urb->interval; - init_timer(&hc->rh.rh_int_timer); - hc->rh.rh_int_timer.function = etrax_rh_int_timer_do; - hc->rh.rh_int_timer.data = (unsigned long)urb; - /* FIXME: Is the jiffies resolution enough? All intervals < 10 ms will be mapped - to 0, and the rest to the nearest lower 10 ms. */ - hc->rh.rh_int_timer.expires = jiffies + ((HZ * hc->rh.interval) / 1000); - add_timer(&hc->rh.rh_int_timer); - - DBFEXIT; -} - -static void etrax_rh_int_timer_do(unsigned long ptr) -{ - struct urb *urb; - etrax_hc_t *hc; - - DBFENTER; - - urb = (struct urb*)ptr; - hc = urb->dev->bus->hcpriv; - - if (hc->rh.send) { - etrax_rh_send_irq(urb); - } - - DBFEXIT; -} - -static int etrax_usb_setup_epid(struct urb *urb) -{ - int epid; - char devnum, endpoint, out_traffic, slow; - int maxlen; - unsigned long flags; - - DBFENTER; - - epid = etrax_usb_lookup_epid(urb); - if ((epid != -1)){ - /* An epid that fits this urb has been found. */ - DBFEXIT; - return epid; - } - - /* We must find and initiate a new epid for this urb. */ - epid = etrax_usb_allocate_epid(); - - if (epid == -1) { - /* Failed to allocate a new epid. */ - DBFEXIT; - return epid; - } - - /* We now have a new epid to use. Initiate it. */ - set_bit(epid, (void *)&epid_usage_bitmask); - - devnum = usb_pipedevice(urb->pipe); - endpoint = usb_pipeendpoint(urb->pipe); - slow = usb_pipeslow(urb->pipe); - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - /* We want both IN and OUT control traffic to be put on the same EP/SB list. */ - out_traffic = 1; - } else { - out_traffic = usb_pipeout(urb->pipe); - } - - save_flags(flags); - cli(); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - *R_USB_EPT_DATA_ISO = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) | - /* FIXME: Change any to the actual port? */ - IO_STATE(R_USB_EPT_DATA_ISO, port, any) | - IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) | - IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) | - IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum); - } else { - *R_USB_EPT_DATA = IO_STATE(R_USB_EPT_DATA, valid, yes) | - IO_FIELD(R_USB_EPT_DATA, low_speed, slow) | - /* FIXME: Change any to the actual port? */ - IO_STATE(R_USB_EPT_DATA, port, any) | - IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) | - IO_FIELD(R_USB_EPT_DATA, ep, endpoint) | - IO_FIELD(R_USB_EPT_DATA, dev, devnum); - } - - restore_flags(flags); - - if (out_traffic) { - set_bit(epid, (void *)&epid_out_traffic); - } else { - clear_bit(epid, (void *)&epid_out_traffic); - } - - dbg_epid("Setting up epid %d with devnum %d, endpoint %d and max_len %d (%s)", - epid, devnum, endpoint, maxlen, out_traffic ? "OUT" : "IN"); - - DBFEXIT; - return epid; -} - -static void etrax_usb_free_epid(int epid) -{ - unsigned long flags; - - DBFENTER; - - if (!test_bit(epid, (void *)&epid_usage_bitmask)) { - warn("Trying to free unused epid %d", epid); - DBFEXIT; - return; - } - - save_flags(flags); - cli(); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - while (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)); - /* This will, among other things, set the valid field to 0. */ - *R_USB_EPT_DATA = 0; - restore_flags(flags); - - clear_bit(epid, (void *)&epid_usage_bitmask); - - - dbg_epid("Freed epid %d", epid); - - DBFEXIT; -} - -static int etrax_usb_lookup_epid(struct urb *urb) -{ - int i; - __u32 data; - char devnum, endpoint, slow, out_traffic; - int maxlen; - unsigned long flags; - - DBFENTER; - - devnum = usb_pipedevice(urb->pipe); - endpoint = usb_pipeendpoint(urb->pipe); - slow = usb_pipeslow(urb->pipe); - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - /* We want both IN and OUT control traffic to be put on the same EP/SB list. */ - out_traffic = 1; - } else { - out_traffic = usb_pipeout(urb->pipe); - } - - /* Step through att epids. */ - for (i = 0; i < NBR_OF_EPIDS; i++) { - if (test_bit(i, (void *)&epid_usage_bitmask) && - test_bit(i, (void *)&epid_out_traffic) == out_traffic) { - - save_flags(flags); - cli(); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, i); - nop(); - - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - data = *R_USB_EPT_DATA_ISO; - restore_flags(flags); - - if ((IO_MASK(R_USB_EPT_DATA_ISO, valid) & data) && - (IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, data) == devnum) && - (IO_EXTRACT(R_USB_EPT_DATA_ISO, ep, data) == endpoint) && - (IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len, data) == maxlen)) { - dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)", - i, devnum, endpoint, out_traffic ? "OUT" : "IN"); - DBFEXIT; - return i; - } - } else { - data = *R_USB_EPT_DATA; - restore_flags(flags); - - if ((IO_MASK(R_USB_EPT_DATA, valid) & data) && - (IO_EXTRACT(R_USB_EPT_DATA, dev, data) == devnum) && - (IO_EXTRACT(R_USB_EPT_DATA, ep, data) == endpoint) && - (IO_EXTRACT(R_USB_EPT_DATA, low_speed, data) == slow) && - (IO_EXTRACT(R_USB_EPT_DATA, max_len, data) == maxlen)) { - dbg_epid("Found epid %d for devnum %d, endpoint %d (%s)", - i, devnum, endpoint, out_traffic ? "OUT" : "IN"); - DBFEXIT; - return i; - } - } - } - } - - DBFEXIT; - return -1; -} - -static int etrax_usb_allocate_epid(void) -{ - int i; - - DBFENTER; - - for (i = 0; i < NBR_OF_EPIDS; i++) { - if (!test_bit(i, (void *)&epid_usage_bitmask)) { - dbg_epid("Found free epid %d", i); - DBFEXIT; - return i; - } - } - - dbg_epid("Found no free epids"); - DBFEXIT; - return -1; -} - -static int etrax_usb_submit_urb(struct urb *urb, unsigned mem_flags) -{ - etrax_hc_t *hc; - int ret = -EINVAL; - - DBFENTER; - - if (!urb->dev || !urb->dev->bus) { - return -ENODEV; - } - if (usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)) <= 0) { - info("Submit urb to pipe with maxpacketlen 0, pipe 0x%X\n", urb->pipe); - return -EMSGSIZE; - } - - if (urb->timeout) { - /* FIXME. */ - warn("urb->timeout specified, ignoring."); - } - - hc = (etrax_hc_t*)urb->dev->bus->hcpriv; - - if (usb_pipedevice(urb->pipe) == hc->rh.devnum) { - /* This request is for the Virtual Root Hub. */ - ret = etrax_rh_submit_urb(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { - - ret = etrax_usb_submit_bulk_urb(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - - ret = etrax_usb_submit_ctrl_urb(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { - int bustime; - - if (urb->bandwidth == 0) { - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) { - ret = bustime; - } else { - ret = etrax_usb_submit_intr_urb(urb); - if (ret == 0) - usb_claim_bandwidth(urb->dev, urb, bustime, 0); - } - } else { - /* Bandwidth already set. */ - ret = etrax_usb_submit_intr_urb(urb); - } - - } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - int bustime; - - if (urb->bandwidth == 0) { - bustime = usb_check_bandwidth(urb->dev, urb); - if (bustime < 0) { - ret = bustime; - } else { - ret = etrax_usb_submit_isoc_urb(urb); - if (ret == 0) - usb_claim_bandwidth(urb->dev, urb, bustime, 0); - } - } else { - /* Bandwidth already set. */ - ret = etrax_usb_submit_isoc_urb(urb); - } - } - - DBFEXIT; - - if (ret != 0) - printk("Submit URB error %d\n", ret); - - return ret; -} - -static int etrax_usb_unlink_urb(struct urb *urb, int status) -{ - etrax_hc_t *hc; - etrax_urb_priv_t *urb_priv; - int epid; - unsigned int flags; - - DBFENTER; - - if (!urb) { - return -EINVAL; - } - - /* Disable interrupts here since a descriptor interrupt for the isoc epid - will modify the sb list. This could possibly be done more granular, but - unlink_urb should not be used frequently anyway. - */ - - save_flags(flags); - cli(); - - if (!urb->dev || !urb->dev->bus) { - restore_flags(flags); - return -ENODEV; - } - if (!urb->hcpriv) { - /* This happens if a device driver calls unlink on an urb that - was never submitted (lazy driver) or if the urb was completed - while unlink was being called. */ - restore_flags(flags); - return 0; - } - if (urb->transfer_flags & URB_ASYNC_UNLINK) { - /* FIXME. */ - /* If URB_ASYNC_UNLINK is set: - unlink - move to a separate urb list - call complete at next sof with ECONNRESET - - If not: - wait 1 ms - unlink - call complete with ENOENT - */ - warn("URB_ASYNC_UNLINK set, ignoring."); - } - - /* One might think that urb->status = -EINPROGRESS would be a requirement for unlinking, - but that doesn't work for interrupt and isochronous traffic since they are completed - repeatedly, and urb->status is set then. That may in itself be a bug though. */ - - hc = urb->dev->bus->hcpriv; - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - epid = urb_priv->epid; - - /* Set the urb status (synchronous unlink). */ - urb->status = -ENOENT; - urb_priv->urb_state = UNLINK; - - if (usb_pipedevice(urb->pipe) == hc->rh.devnum) { - int ret; - ret = etrax_rh_unlink_urb(urb); - DBFEXIT; - restore_flags(flags); - return ret; - - } else if (usb_pipetype(urb->pipe) == PIPE_BULK) { - - dbg_bulk("Unlink of bulk urb (0x%lx)", (unsigned long)urb); - - if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) { - /* The EP was enabled, disable it and wait. */ - TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); - - /* Ah, the luxury of busy-wait. */ - while (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[epid])); - } - /* Kicking dummy list out of the party. */ - TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]); - - } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - - dbg_ctrl("Unlink of ctrl urb (0x%lx)", (unsigned long)urb); - - if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) { - /* The EP was enabled, disable it and wait. */ - TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); - - /* Ah, the luxury of busy-wait. */ - while (*R_DMA_CH8_SUB1_EP == virt_to_phys(&TxCtrlEPList[epid])); - } - - } else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { - - dbg_intr("Unlink of intr urb (0x%lx)", (unsigned long)urb); - - /* Separate function because it's a tad more complicated. */ - etrax_usb_unlink_intr_urb(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - - dbg_isoc("Unlink of isoc urb (0x%lx)", (unsigned long)urb); - - if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) { - /* The EP was enabled, disable it and wait. */ - TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); - - /* Ah, the luxury of busy-wait. */ - while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])); - } - } - - /* Note that we need to remove the urb from the urb list *before* removing its SB - descriptors. (This means that the isoc eof handler might get a null urb when we - are unlinking the last urb.) */ - - if (usb_pipetype(urb->pipe) == PIPE_BULK) { - - urb_list_del(urb, epid); - TxBulkEPList[epid].sub = 0; - etrax_remove_from_sb_list(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - - urb_list_del(urb, epid); - TxCtrlEPList[epid].sub = 0; - etrax_remove_from_sb_list(urb); - - } else if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { - - urb_list_del(urb, epid); - /* Sanity check (should never happen). */ - assert(urb_list_empty(epid)); - - /* Release allocated bandwidth. */ - usb_release_bandwidth(urb->dev, urb, 0); - - } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - - if (usb_pipeout(urb->pipe)) { - - USB_SB_Desc_t *iter_sb, *prev_sb, *next_sb; - - if (__urb_list_entry(urb, epid)) { - - urb_list_del(urb, epid); - iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0; - prev_sb = 0; - while (iter_sb && (iter_sb != urb_priv->first_sb)) { - prev_sb = iter_sb; - iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; - } - - if (iter_sb == 0) { - /* Unlink of the URB currently being transmitted. */ - prev_sb = 0; - iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0; - } - - while (iter_sb && (iter_sb != urb_priv->last_sb)) { - iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; - } - if (iter_sb) { - next_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; - } else { - /* This should only happen if the DMA has completed - processing the SB list for this EP while interrupts - are disabled. */ - dbg_isoc("Isoc urb not found, already sent?"); - next_sb = 0; - } - if (prev_sb) { - prev_sb->next = next_sb ? virt_to_phys(next_sb) : 0; - } else { - TxIsocEPList[epid].sub = next_sb ? virt_to_phys(next_sb) : 0; - } - - etrax_remove_from_sb_list(urb); - if (urb_list_empty(epid)) { - TxIsocEPList[epid].sub = 0; - dbg_isoc("Last isoc out urb epid %d", epid); - } else if (next_sb || prev_sb) { - dbg_isoc("Re-enable isoc out epid %d", epid); - - TxIsocEPList[epid].hw_len = 0; - TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - } else { - TxIsocEPList[epid].sub = 0; - dbg_isoc("URB list non-empty and no SB list, EP disabled"); - } - } else { - dbg_isoc("Urb 0x%p not found, completed already?", urb); - } - } else { - - urb_list_del(urb, epid); - - /* For in traffic there is only one SB descriptor for each EP even - though there may be several urbs (all urbs point at the same SB). */ - if (urb_list_empty(epid)) { - /* No more urbs, remove the SB. */ - TxIsocEPList[epid].sub = 0; - etrax_remove_from_sb_list(urb); - } else { - TxIsocEPList[epid].hw_len = 0; - TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - } - } - /* Release allocated bandwidth. */ - usb_release_bandwidth(urb->dev, urb, 1); - } - /* Free the epid if urb list is empty. */ - if (urb_list_empty(epid)) { - etrax_usb_free_epid(epid); - } - restore_flags(flags); - - /* Must be done before calling completion handler. */ - kfree(urb_priv); - urb->hcpriv = 0; - - if (urb->complete) { - urb->complete(urb, NULL); - } - - DBFEXIT; - return 0; -} - -static int etrax_usb_get_frame_number(struct usb_device *usb_dev) -{ - DBFENTER; - DBFEXIT; - return (*R_USB_FM_NUMBER & 0x7ff); -} - -static irqreturn_t etrax_usb_tx_interrupt(int irq, void *vhc) -{ - DBFENTER; - - /* This interrupt handler could be used when unlinking EP descriptors. */ - - if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) { - USB_EP_Desc_t *ep; - - //dbg_bulk("dma8_sub0_descr (BULK) intr."); - - /* It should be safe clearing the interrupt here, since we don't expect to get a new - one until we restart the bulk channel. */ - *R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do); - - /* Wait while the DMA is running (though we don't expect it to be). */ - while (*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd)); - - /* Advance the DMA to the next EP descriptor. */ - ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP); - - //dbg_bulk("descr intr: DMA is at 0x%lx", (unsigned long)ep); - - /* ep->next is already a physical address; no need for a virt_to_phys. */ - *R_DMA_CH8_SUB0_EP = ep->next; - - /* Start the DMA bulk channel again. */ - *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); - } - if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) { - struct urb *urb; - int epid; - etrax_urb_priv_t *urb_priv; - unsigned long int flags; - - dbg_ctrl("dma8_sub1_descr (CTRL) intr."); - *R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do); - - /* The complete callback gets called so we cli. */ - save_flags(flags); - cli(); - - for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { - if ((TxCtrlEPList[epid].sub == 0) || - (epid == DUMMY_EPID) || - (epid == INVALID_EPID)) { - /* Nothing here to see. */ - continue; - } - - /* Get the first urb (if any). */ - urb = urb_list_first(epid); - - if (urb) { - - /* Sanity check. */ - assert(usb_pipetype(urb->pipe) == PIPE_CONTROL); - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - if (urb_priv->urb_state == WAITING_FOR_DESCR_INTR) { - assert(!(TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable))); - - etrax_usb_complete_urb(urb, 0); - } - } - } - restore_flags(flags); - } - if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) { - dbg_intr("dma8_sub2_descr (INTR) intr."); - *R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do); - } - if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) { - struct urb *urb; - int epid; - int epid_done; - etrax_urb_priv_t *urb_priv; - USB_SB_Desc_t *sb_desc; - - usb_isoc_complete_data_t *comp_data = NULL; - - /* One or more isoc out transfers are done. */ - dbg_isoc("dma8_sub3_descr (ISOC) intr."); - - /* For each isoc out EP search for the first sb_desc with the intr flag - set. This descriptor must be the last packet from an URB. Then - traverse the URB list for the EP until the URB with urb_priv->last_sb - matching the intr-marked sb_desc is found. All URBs before this have - been sent. - */ - - for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { - /* Skip past epids with no SB lists, epids used for in traffic, - and special (dummy, invalid) epids. */ - if ((TxIsocEPList[epid].sub == 0) || - (test_bit(epid, (void *)&epid_out_traffic) == 0) || - (epid == DUMMY_EPID) || - (epid == INVALID_EPID)) { - /* Nothing here to see. */ - continue; - } - sb_desc = phys_to_virt(TxIsocEPList[epid].sub); - - /* Find the last descriptor of the currently active URB for this ep. - This is the first descriptor in the sub list marked for a descriptor - interrupt. */ - while (sb_desc && !IO_EXTRACT(USB_SB_command, intr, sb_desc->command)) { - sb_desc = sb_desc->next ? phys_to_virt(sb_desc->next) : 0; - } - assert(sb_desc); - - dbg_isoc("Check epid %d, sub 0x%p, SB 0x%p", - epid, - phys_to_virt(TxIsocEPList[epid].sub), - sb_desc); - - epid_done = 0; - - /* Get the first urb (if any). */ - urb = urb_list_first(epid); - assert(urb); - - while (urb && !epid_done) { - - /* Sanity check. */ - assert(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS); - - if (!usb_pipeout(urb->pipe)) { - /* descr interrupts are generated only for out pipes. */ - epid_done = 1; - continue; - } - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - if (sb_desc != urb_priv->last_sb) { - - /* This urb has been sent. */ - dbg_isoc("out URB 0x%p sent", urb); - - urb_priv->urb_state = TRANSFER_DONE; - - } else if ((sb_desc == urb_priv->last_sb) && - !(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) { - - assert((sb_desc->command & IO_MASK(USB_SB_command, eol)) == IO_STATE(USB_SB_command, eol, yes)); - assert(sb_desc->next == 0); - - dbg_isoc("out URB 0x%p last in list, epid disabled", urb); - TxIsocEPList[epid].sub = 0; - TxIsocEPList[epid].hw_len = 0; - urb_priv->urb_state = TRANSFER_DONE; - - epid_done = 1; - - } else { - epid_done = 1; - } - if (!epid_done) { - urb = urb_list_next(urb, epid); - } - } - - } - - *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do); - - comp_data = (usb_isoc_complete_data_t*)kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC); - assert(comp_data != NULL); - - INIT_WORK(&comp_data->usb_bh, etrax_usb_isoc_descr_interrupt_bottom_half, comp_data); - schedule_work(&comp_data->usb_bh); - } - - DBFEXIT; - return IRQ_HANDLED; -} - -static void etrax_usb_isoc_descr_interrupt_bottom_half(void *data) -{ - usb_isoc_complete_data_t *comp_data = (usb_isoc_complete_data_t*)data; - - struct urb *urb; - int epid; - int epid_done; - etrax_urb_priv_t *urb_priv; - - DBFENTER; - - dbg_isoc("dma8_sub3_descr (ISOC) bottom half."); - - for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { - unsigned long flags; - - save_flags(flags); - cli(); - - epid_done = 0; - - /* The descriptor interrupt handler has marked all transmitted isoch. out - URBs with TRANSFER_DONE. Now we traverse all epids and for all that - have isoch. out traffic traverse its URB list and complete the - transmitted URB. - */ - - while (!epid_done) { - - /* Get the first urb (if any). */ - urb = urb_list_first(epid); - if (urb == 0) { - epid_done = 1; - continue; - } - - if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) { - epid_done = 1; - continue; - } - - if (!usb_pipeout(urb->pipe)) { - /* descr interrupts are generated only for out pipes. */ - epid_done = 1; - continue; - } - - dbg_isoc("Check epid %d, SB 0x%p", epid, (char*)TxIsocEPList[epid].sub); - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - if (urb_priv->urb_state == TRANSFER_DONE) { - int i; - struct usb_iso_packet_descriptor *packet; - - /* This urb has been sent. */ - dbg_isoc("Completing isoc out URB 0x%p", urb); - - for (i = 0; i < urb->number_of_packets; i++) { - packet = &urb->iso_frame_desc[i]; - packet->status = 0; - packet->actual_length = packet->length; - } - - etrax_usb_complete_isoc_urb(urb, 0); - - if (urb_list_empty(epid)) { - etrax_usb_free_epid(epid); - epid_done = 1; - } - } else { - epid_done = 1; - } - } - restore_flags(flags); - - } - kmem_cache_free(isoc_compl_cache, comp_data); - - DBFEXIT; -} - - - -static irqreturn_t etrax_usb_rx_interrupt(int irq, void *vhc) -{ - struct urb *urb; - etrax_urb_priv_t *urb_priv; - int epid = 0; - unsigned long flags; - - /* Isoc diagnostics. */ - static int curr_fm = 0; - static int prev_fm = 0; - - DBFENTER; - - /* Clear this interrupt. */ - *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do); - - /* Note that this while loop assumes that all packets span only - one rx descriptor. */ - - /* The reason we cli here is that we call the driver's callback functions. */ - save_flags(flags); - cli(); - - while (myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) { - - epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status); - urb = urb_list_first(epid); - - //printk("eop for epid %d, first urb 0x%lx\n", epid, (unsigned long)urb); - - if (!urb) { - err("No urb for epid %d in rx interrupt", epid); - __dump_ept_data(epid); - goto skip_out; - } - - /* Note that we cannot indescriminately assert(usb_pipein(urb->pipe)) since - ctrl pipes are not. */ - - if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) { - __u32 r_usb_ept_data; - int no_error = 0; - - assert(test_bit(epid, (void *)&epid_usage_bitmask)); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - r_usb_ept_data = *R_USB_EPT_DATA_ISO; - - if ((r_usb_ept_data & IO_MASK(R_USB_EPT_DATA_ISO, valid)) && - (IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data) == 0) && - (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata))) { - /* Not an error, just a failure to receive an expected iso - in packet in this frame. This is not documented - in the designers reference. - */ - no_error++; - } else { - warn("R_USB_EPT_DATA_ISO for epid %d = 0x%x", epid, r_usb_ept_data); - } - } else { - r_usb_ept_data = *R_USB_EPT_DATA; - warn("R_USB_EPT_DATA for epid %d = 0x%x", epid, r_usb_ept_data); - } - - if (!no_error){ - warn("error in rx desc->status, epid %d, first urb = 0x%lx", - epid, (unsigned long)urb); - __dump_in_desc(myNextRxDesc); - - warn("R_USB_STATUS = 0x%x", *R_USB_STATUS); - - /* Check that ept was disabled when error occurred. */ - switch (usb_pipetype(urb->pipe)) { - case PIPE_BULK: - assert(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))); - break; - case PIPE_CONTROL: - assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))); - break; - case PIPE_INTERRUPT: - assert(!(TxIntrEPList[epid].command & IO_MASK(USB_EP_command, enable))); - break; - case PIPE_ISOCHRONOUS: - assert(!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))); - break; - default: - warn("etrax_usb_rx_interrupt: bad pipetype %d in urb 0x%p", - usb_pipetype(urb->pipe), - urb); - } - etrax_usb_complete_urb(urb, -EPROTO); - goto skip_out; - } - } - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - if ((usb_pipetype(urb->pipe) == PIPE_BULK) || - (usb_pipetype(urb->pipe) == PIPE_CONTROL) || - (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { - - if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) { - /* We get nodata for empty data transactions, and the rx descriptor's - hw_len field is not valid in that case. No data to copy in other - words. */ - } else { - /* Make sure the data fits in the buffer. */ - assert(urb_priv->rx_offset + myNextRxDesc->hw_len - <= urb->transfer_buffer_length); - - memcpy(urb->transfer_buffer + urb_priv->rx_offset, - phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len); - urb_priv->rx_offset += myNextRxDesc->hw_len; - } - - if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) { - if ((usb_pipetype(urb->pipe) == PIPE_CONTROL) && - ((TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable)) == - IO_STATE(USB_EP_command, enable, yes))) { - /* The EP is still enabled, so the OUT packet used to ack - the in data is probably not processed yet. If the EP - sub pointer has not moved beyond urb_priv->last_sb mark - it for a descriptor interrupt and complete the urb in - the descriptor interrupt handler. - */ - USB_SB_Desc_t *sub = TxCtrlEPList[urb_priv->epid].sub ? phys_to_virt(TxCtrlEPList[urb_priv->epid].sub) : 0; - - while ((sub != NULL) && (sub != urb_priv->last_sb)) { - sub = sub->next ? phys_to_virt(sub->next) : 0; - } - if (sub != NULL) { - /* The urb has not been fully processed. */ - urb_priv->urb_state = WAITING_FOR_DESCR_INTR; - } else { - warn("(CTRL) epid enabled and urb (0x%p) processed, ep->sub=0x%p", urb, (char*)TxCtrlEPList[urb_priv->epid].sub); - etrax_usb_complete_urb(urb, 0); - } - } else { - etrax_usb_complete_urb(urb, 0); - } - } - - } else if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - - struct usb_iso_packet_descriptor *packet; - - if (urb_priv->urb_state == UNLINK) { - info("Ignoring rx data for urb being unlinked."); - goto skip_out; - } else if (urb_priv->urb_state == NOT_STARTED) { - info("What? Got rx data for urb that isn't started?"); - goto skip_out; - } - - packet = &urb->iso_frame_desc[urb_priv->isoc_packet_counter]; - packet->status = 0; - - if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) { - /* We get nodata for empty data transactions, and the rx descriptor's - hw_len field is not valid in that case. We copy 0 bytes however to - stay in synch. */ - packet->actual_length = 0; - } else { - packet->actual_length = myNextRxDesc->hw_len; - /* Make sure the data fits in the buffer. */ - assert(packet->actual_length <= packet->length); - memcpy(urb->transfer_buffer + packet->offset, - phys_to_virt(myNextRxDesc->buf), packet->actual_length); - } - - /* Increment the packet counter. */ - urb_priv->isoc_packet_counter++; - - /* Note that we don't care about the eot field in the rx descriptor's status. - It will always be set for isoc traffic. */ - if (urb->number_of_packets == urb_priv->isoc_packet_counter) { - - /* Out-of-synch diagnostics. */ - curr_fm = (*R_USB_FM_NUMBER & 0x7ff); - if (((prev_fm + urb_priv->isoc_packet_counter) % (0x7ff + 1)) != curr_fm) { - /* This test is wrong, if there is more than one isoc - in endpoint active it will always calculate wrong - since prev_fm is shared by all endpoints. - - FIXME Make this check per URB using urb->start_frame. - */ - dbg_isoc("Out of synch? Previous frame = %d, current frame = %d", - prev_fm, curr_fm); - - } - prev_fm = curr_fm; - - /* Complete the urb with status OK. */ - etrax_usb_complete_isoc_urb(urb, 0); - } - } - - skip_out: - - /* DMA IN cache bug. Flush the DMA IN buffer from the cache. (struct etrax_dma_descr - has the same layout as USB_IN_Desc for the relevant fields.) */ - prepare_rx_descriptor((struct etrax_dma_descr*)myNextRxDesc); - - myPrevRxDesc = myNextRxDesc; - myPrevRxDesc->command |= IO_MASK(USB_IN_command, eol); - myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol); - myLastRxDesc = myPrevRxDesc; - - myNextRxDesc->status = 0; - myNextRxDesc = phys_to_virt(myNextRxDesc->next); - } - - restore_flags(flags); - - DBFEXIT; - - return IRQ_HANDLED; -} - - -/* This function will unlink the SB descriptors associated with this urb. */ -static int etrax_remove_from_sb_list(struct urb *urb) -{ - USB_SB_Desc_t *next_sb, *first_sb, *last_sb; - etrax_urb_priv_t *urb_priv; - int i = 0; - - DBFENTER; - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - /* Just a sanity check. Since we don't fiddle with the DMA list the EP descriptor - doesn't really need to be disabled, it's just that we expect it to be. */ - if (usb_pipetype(urb->pipe) == PIPE_BULK) { - assert(!(TxBulkEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable))); - } else if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { - assert(!(TxCtrlEPList[urb_priv->epid].command & IO_MASK(USB_EP_command, enable))); - } - - first_sb = urb_priv->first_sb; - last_sb = urb_priv->last_sb; - - assert(first_sb); - assert(last_sb); - - while (first_sb != last_sb) { - next_sb = (USB_SB_Desc_t *)phys_to_virt(first_sb->next); - kmem_cache_free(usb_desc_cache, first_sb); - first_sb = next_sb; - i++; - } - kmem_cache_free(usb_desc_cache, last_sb); - i++; - dbg_sb("%d SB descriptors freed", i); - /* Compare i with urb->number_of_packets for Isoc traffic. - Should be same when calling unlink_urb */ - - DBFEXIT; - - return i; -} - -static int etrax_usb_submit_bulk_urb(struct urb *urb) -{ - int epid; - int empty; - unsigned long flags; - etrax_urb_priv_t *urb_priv; - - DBFENTER; - - /* Epid allocation, empty check and list add must be protected. - Read about this in etrax_usb_submit_ctrl_urb. */ - - spin_lock_irqsave(&urb_list_lock, flags); - epid = etrax_usb_setup_epid(urb); - if (epid == -1) { - DBFEXIT; - spin_unlock_irqrestore(&urb_list_lock, flags); - return -ENOMEM; - } - empty = urb_list_empty(epid); - urb_list_add(urb, epid); - spin_unlock_irqrestore(&urb_list_lock, flags); - - dbg_bulk("Adding bulk %s urb 0x%lx to %s list, epid %d", - usb_pipein(urb->pipe) ? "IN" : "OUT", (unsigned long)urb, empty ? "empty" : "", epid); - - /* Mark the urb as being in progress. */ - urb->status = -EINPROGRESS; - - /* Setup the hcpriv data. */ - urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); - /* This sets rx_offset to 0. */ - urb_priv->urb_state = NOT_STARTED; - urb->hcpriv = urb_priv; - - if (empty) { - etrax_usb_add_to_bulk_sb_list(urb, epid); - } - - DBFEXIT; - - return 0; -} - -static void etrax_usb_add_to_bulk_sb_list(struct urb *urb, int epid) -{ - USB_SB_Desc_t *sb_desc; - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - unsigned long flags; - char maxlen; - - DBFENTER; - - dbg_bulk("etrax_usb_add_to_bulk_sb_list, urb 0x%lx", (unsigned long)urb); - - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - - sb_desc = kmem_cache_zalloc(usb_desc_cache, SLAB_FLAG); - assert(sb_desc != NULL); - - - if (usb_pipeout(urb->pipe)) { - - dbg_bulk("Grabbing bulk OUT, urb 0x%lx, epid %d", (unsigned long)urb, epid); - - /* This is probably a sanity check of the bulk transaction length - not being larger than 64 kB. */ - if (urb->transfer_buffer_length > 0xffff) { - panic("urb->transfer_buffer_length > 0xffff"); - } - - sb_desc->sw_len = urb->transfer_buffer_length; - - /* The rem field is don't care if it's not a full-length transfer, so setting - it shouldn't hurt. Also, rem isn't used for OUT traffic. */ - sb_desc->command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, out) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - /* The full field is set to yes, even if we don't actually check that this is - a full-length transfer (i.e., that transfer_buffer_length % maxlen = 0). - Setting full prevents the USB controller from sending an empty packet in - that case. However, if URB_ZERO_PACKET was set we want that. */ - if (!(urb->transfer_flags & URB_ZERO_PACKET)) { - sb_desc->command |= IO_STATE(USB_SB_command, full, yes); - } - - sb_desc->buf = virt_to_phys(urb->transfer_buffer); - sb_desc->next = 0; - - } else if (usb_pipein(urb->pipe)) { - - dbg_bulk("Grabbing bulk IN, urb 0x%lx, epid %d", (unsigned long)urb, epid); - - sb_desc->sw_len = urb->transfer_buffer_length ? - (urb->transfer_buffer_length - 1) / maxlen + 1 : 0; - - /* The rem field is don't care if it's not a full-length transfer, so setting - it shouldn't hurt. */ - sb_desc->command = - (IO_FIELD(USB_SB_command, rem, - urb->transfer_buffer_length % maxlen) | - IO_STATE(USB_SB_command, tt, in) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - sb_desc->buf = 0; - sb_desc->next = 0; - } - - urb_priv->first_sb = sb_desc; - urb_priv->last_sb = sb_desc; - urb_priv->epid = epid; - - urb->hcpriv = urb_priv; - - /* Reset toggle bits and reset error count. */ - save_flags(flags); - cli(); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - - /* FIXME: Is this a special case since the hold field is checked, - or should we check hold in a lot of other cases as well? */ - if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) { - panic("Hold was set in %s", __FUNCTION__); - } - - /* Reset error counters (regardless of which direction this traffic is). */ - *R_USB_EPT_DATA &= - ~(IO_MASK(R_USB_EPT_DATA, error_count_in) | - IO_MASK(R_USB_EPT_DATA, error_count_out)); - - /* Software must preset the toggle bits. */ - if (usb_pipeout(urb->pipe)) { - char toggle = - usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out); - *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle); - } else { - char toggle = - usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe)); - *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in); - *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle); - } - - /* Assert that the EP descriptor is disabled. */ - assert(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))); - - /* The reason we set the EP's sub pointer directly instead of - walking the SB list and linking it last in the list is that we only - have one active urb at a time (the rest are queued). */ - - /* Note that we cannot have interrupts running when we have set the SB descriptor - but the EP is not yet enabled. If a bulk eot happens for another EP, we will - find this EP disabled and with a SB != 0, which will make us think that it's done. */ - TxBulkEPList[epid].sub = virt_to_phys(sb_desc); - TxBulkEPList[epid].hw_len = 0; - /* Note that we don't have to fill in the ep_id field since this - was done when we allocated the EP descriptors in init_tx_bulk_ep. */ - - /* Check if the dummy list is already with us (if several urbs were queued). */ - if (TxBulkEPList[epid].next != virt_to_phys(&TxBulkDummyEPList[epid][0])) { - - dbg_bulk("Inviting dummy list to the party for urb 0x%lx, epid %d", - (unsigned long)urb, epid); - - /* The last EP in the dummy list already has its next pointer set to - TxBulkEPList[epid].next. */ - - /* We don't need to check if the DMA is at this EP or not before changing the - next pointer, since we will do it in one 32-bit write (EP descriptors are - 32-bit aligned). */ - TxBulkEPList[epid].next = virt_to_phys(&TxBulkDummyEPList[epid][0]); - } - /* Enable the EP descr. */ - dbg_bulk("Enabling bulk EP for urb 0x%lx, epid %d", (unsigned long)urb, epid); - TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - - /* Everything is set up, safe to enable interrupts again. */ - restore_flags(flags); - - /* If the DMA bulk channel isn't running, we need to restart it if it - has stopped at the last EP descriptor (DMA stopped because there was - no more traffic) or if it has stopped at a dummy EP with the intr flag - set (DMA stopped because we were too slow in inserting new traffic). */ - if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) { - - USB_EP_Desc_t *ep; - ep = (USB_EP_Desc_t *)phys_to_virt(*R_DMA_CH8_SUB0_EP); - dbg_bulk("DMA channel not running in add"); - dbg_bulk("DMA is at 0x%lx", (unsigned long)ep); - - if (*R_DMA_CH8_SUB0_EP == virt_to_phys(&TxBulkEPList[NBR_OF_EPIDS - 1]) || - (ep->command & 0x8) >> 3) { - *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); - /* Update/restart the bulk start timer since we just started the channel. */ - mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL); - /* Update/restart the bulk eot timer since we just inserted traffic. */ - mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); - } - } - - DBFEXIT; -} - -static void etrax_usb_complete_bulk_urb(struct urb *urb, int status) -{ - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - int epid = urb_priv->epid; - unsigned long flags; - - DBFENTER; - - if (status) - warn("Completing bulk urb with status %d.", status); - - dbg_bulk("Completing bulk urb 0x%lx for epid %d", (unsigned long)urb, epid); - - /* Update the urb list. */ - urb_list_del(urb, epid); - - /* For an IN pipe, we always set the actual length, regardless of whether there was - an error or not (which means the device driver can use the data if it wants to). */ - if (usb_pipein(urb->pipe)) { - urb->actual_length = urb_priv->rx_offset; - } else { - /* Set actual_length for OUT urbs also; the USB mass storage driver seems - to want that. We wouldn't know of any partial writes if there was an error. */ - if (status == 0) { - urb->actual_length = urb->transfer_buffer_length; - } else { - urb->actual_length = 0; - } - } - - /* FIXME: Is there something of the things below we shouldn't do if there was an error? - Like, maybe we shouldn't toggle the toggle bits, or maybe we shouldn't insert more traffic. */ - - save_flags(flags); - cli(); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - - /* We need to fiddle with the toggle bits because the hardware doesn't do it for us. */ - if (usb_pipeout(urb->pipe)) { - char toggle = - IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA); - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); - } else { - char toggle = - IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA); - usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), - usb_pipeout(urb->pipe), toggle); - } - restore_flags(flags); - - /* Remember to free the SBs. */ - etrax_remove_from_sb_list(urb); - kfree(urb_priv); - urb->hcpriv = 0; - - /* If there are any more urb's in the list we'd better start sending */ - if (!urb_list_empty(epid)) { - - struct urb *new_urb; - - /* Get the first urb. */ - new_urb = urb_list_first(epid); - assert(new_urb); - - dbg_bulk("More bulk for epid %d", epid); - - etrax_usb_add_to_bulk_sb_list(new_urb, epid); - } - - urb->status = status; - - /* We let any non-zero status from the layer above have precedence. */ - if (status == 0) { - /* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length) - is to be treated as an error. */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - if (usb_pipein(urb->pipe) && - (urb->actual_length != - usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) { - urb->status = -EREMOTEIO; - } - } - } - - if (urb->complete) { - urb->complete(urb, NULL); - } - - if (urb_list_empty(epid)) { - /* This means that this EP is now free, deconfigure it. */ - etrax_usb_free_epid(epid); - - /* No more traffic; time to clean up. - Must set sub pointer to 0, since we look at the sub pointer when handling - the bulk eot interrupt. */ - - dbg_bulk("No bulk for epid %d", epid); - - TxBulkEPList[epid].sub = 0; - - /* Unlink the dummy list. */ - - dbg_bulk("Kicking dummy list out of party for urb 0x%lx, epid %d", - (unsigned long)urb, epid); - - /* No need to wait for the DMA before changing the next pointer. - The modulo NBR_OF_EPIDS isn't actually necessary, since we will never use - the last one (INVALID_EPID) for actual traffic. */ - TxBulkEPList[epid].next = - virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]); - } - - DBFEXIT; -} - -static int etrax_usb_submit_ctrl_urb(struct urb *urb) -{ - int epid; - int empty; - unsigned long flags; - etrax_urb_priv_t *urb_priv; - - DBFENTER; - - /* FIXME: Return -ENXIO if there is already a queued urb for this endpoint? */ - - /* Epid allocation, empty check and list add must be protected. - - Epid allocation because if we find an existing epid for this endpoint an urb might be - completed (emptying the list) before we add the new urb to the list, causing the epid - to be de-allocated. We would then start the transfer with an invalid epid -> epid attn. - - Empty check and add because otherwise we might conclude that the list is not empty, - after which it becomes empty before we add the new urb to the list, causing us not to - insert the new traffic into the SB list. */ - - spin_lock_irqsave(&urb_list_lock, flags); - epid = etrax_usb_setup_epid(urb); - if (epid == -1) { - spin_unlock_irqrestore(&urb_list_lock, flags); - DBFEXIT; - return -ENOMEM; - } - empty = urb_list_empty(epid); - urb_list_add(urb, epid); - spin_unlock_irqrestore(&urb_list_lock, flags); - - dbg_ctrl("Adding ctrl urb 0x%lx to %s list, epid %d", - (unsigned long)urb, empty ? "empty" : "", epid); - - /* Mark the urb as being in progress. */ - urb->status = -EINPROGRESS; - - /* Setup the hcpriv data. */ - urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); - /* This sets rx_offset to 0. */ - urb_priv->urb_state = NOT_STARTED; - urb->hcpriv = urb_priv; - - if (empty) { - etrax_usb_add_to_ctrl_sb_list(urb, epid); - } - - DBFEXIT; - - return 0; -} - -static void etrax_usb_add_to_ctrl_sb_list(struct urb *urb, int epid) -{ - USB_SB_Desc_t *sb_desc_setup; - USB_SB_Desc_t *sb_desc_data; - USB_SB_Desc_t *sb_desc_status; - - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - - unsigned long flags; - char maxlen; - - DBFENTER; - - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - - sb_desc_setup = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - assert(sb_desc_setup != NULL); - sb_desc_status = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - assert(sb_desc_status != NULL); - - /* Initialize the mandatory setup SB descriptor (used only in control transfers) */ - sb_desc_setup->sw_len = 8; - sb_desc_setup->command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, setup) | - IO_STATE(USB_SB_command, full, yes) | - IO_STATE(USB_SB_command, eot, yes)); - - sb_desc_setup->buf = virt_to_phys(urb->setup_packet); - - if (usb_pipeout(urb->pipe)) { - dbg_ctrl("Transfer for epid %d is OUT", epid); - - /* If this Control OUT transfer has an optional data stage we add an OUT token - before the mandatory IN (status) token, hence the reordered SB list */ - - sb_desc_setup->next = virt_to_phys(sb_desc_status); - if (urb->transfer_buffer) { - - dbg_ctrl("This OUT transfer has an extra data stage"); - - sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - assert(sb_desc_data != NULL); - - sb_desc_setup->next = virt_to_phys(sb_desc_data); - - sb_desc_data->sw_len = urb->transfer_buffer_length; - sb_desc_data->command = (IO_STATE(USB_SB_command, tt, out) | - IO_STATE(USB_SB_command, full, yes) | - IO_STATE(USB_SB_command, eot, yes)); - sb_desc_data->buf = virt_to_phys(urb->transfer_buffer); - sb_desc_data->next = virt_to_phys(sb_desc_status); - } - - sb_desc_status->sw_len = 1; - sb_desc_status->command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, in) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, intr, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - sb_desc_status->buf = 0; - sb_desc_status->next = 0; - - } else if (usb_pipein(urb->pipe)) { - - dbg_ctrl("Transfer for epid %d is IN", epid); - dbg_ctrl("transfer_buffer_length = %d", urb->transfer_buffer_length); - dbg_ctrl("rem is calculated to %d", urb->transfer_buffer_length % maxlen); - - sb_desc_data = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - assert(sb_desc_data != NULL); - - sb_desc_setup->next = virt_to_phys(sb_desc_data); - - sb_desc_data->sw_len = urb->transfer_buffer_length ? - (urb->transfer_buffer_length - 1) / maxlen + 1 : 0; - dbg_ctrl("sw_len got %d", sb_desc_data->sw_len); - - sb_desc_data->command = - (IO_FIELD(USB_SB_command, rem, - urb->transfer_buffer_length % maxlen) | - IO_STATE(USB_SB_command, tt, in) | - IO_STATE(USB_SB_command, eot, yes)); - - sb_desc_data->buf = 0; - sb_desc_data->next = virt_to_phys(sb_desc_status); - - /* Read comment at zout_buffer declaration for an explanation to this. */ - sb_desc_status->sw_len = 1; - sb_desc_status->command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, zout) | - IO_STATE(USB_SB_command, full, yes) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, intr, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - sb_desc_status->buf = virt_to_phys(&zout_buffer[0]); - sb_desc_status->next = 0; - } - - urb_priv->first_sb = sb_desc_setup; - urb_priv->last_sb = sb_desc_status; - urb_priv->epid = epid; - - urb_priv->urb_state = STARTED; - - /* Reset toggle bits and reset error count, remember to di and ei */ - /* Warning: it is possible that this locking doesn't work with bottom-halves */ - - save_flags(flags); - cli(); - - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - if (*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) { - panic("Hold was set in %s", __FUNCTION__); - } - - - /* FIXME: Compare with etrax_usb_add_to_bulk_sb_list where the toggle bits - are set to a specific value. Why the difference? Read "Transfer and Toggle Bits - in Designer's Reference, p. 8 - 11. */ - *R_USB_EPT_DATA &= - ~(IO_MASK(R_USB_EPT_DATA, error_count_in) | - IO_MASK(R_USB_EPT_DATA, error_count_out) | - IO_MASK(R_USB_EPT_DATA, t_in) | - IO_MASK(R_USB_EPT_DATA, t_out)); - - /* Since we use the rx interrupt to complete ctrl urbs, we can enable interrupts now - (i.e. we don't check the sub pointer on an eot interrupt like we do for bulk traffic). */ - restore_flags(flags); - - /* Assert that the EP descriptor is disabled. */ - assert(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))); - - /* Set up and enable the EP descriptor. */ - TxCtrlEPList[epid].sub = virt_to_phys(sb_desc_setup); - TxCtrlEPList[epid].hw_len = 0; - TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - - /* We start the DMA sub channel without checking if it's running or not, because: - 1) If it's already running, issuing the start command is a nop. - 2) We avoid a test-and-set race condition. */ - *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start); - - DBFEXIT; -} - -static void etrax_usb_complete_ctrl_urb(struct urb *urb, int status) -{ - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - int epid = urb_priv->epid; - - DBFENTER; - - if (status) - warn("Completing ctrl urb with status %d.", status); - - dbg_ctrl("Completing ctrl epid %d, urb 0x%lx", epid, (unsigned long)urb); - - /* Remove this urb from the list. */ - urb_list_del(urb, epid); - - /* For an IN pipe, we always set the actual length, regardless of whether there was - an error or not (which means the device driver can use the data if it wants to). */ - if (usb_pipein(urb->pipe)) { - urb->actual_length = urb_priv->rx_offset; - } - - /* FIXME: Is there something of the things below we shouldn't do if there was an error? - Like, maybe we shouldn't insert more traffic. */ - - /* Remember to free the SBs. */ - etrax_remove_from_sb_list(urb); - kfree(urb_priv); - urb->hcpriv = 0; - - /* If there are any more urbs in the list we'd better start sending. */ - if (!urb_list_empty(epid)) { - struct urb *new_urb; - - /* Get the first urb. */ - new_urb = urb_list_first(epid); - assert(new_urb); - - dbg_ctrl("More ctrl for epid %d, first urb = 0x%lx", epid, (unsigned long)new_urb); - - etrax_usb_add_to_ctrl_sb_list(new_urb, epid); - } - - urb->status = status; - - /* We let any non-zero status from the layer above have precedence. */ - if (status == 0) { - /* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length) - is to be treated as an error. */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - if (usb_pipein(urb->pipe) && - (urb->actual_length != - usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))) { - urb->status = -EREMOTEIO; - } - } - } - - if (urb->complete) { - urb->complete(urb, NULL); - } - - if (urb_list_empty(epid)) { - /* No more traffic. Time to clean up. */ - etrax_usb_free_epid(epid); - /* Must set sub pointer to 0. */ - dbg_ctrl("No ctrl for epid %d", epid); - TxCtrlEPList[epid].sub = 0; - } - - DBFEXIT; -} - -static int etrax_usb_submit_intr_urb(struct urb *urb) -{ - - int epid; - - DBFENTER; - - if (usb_pipeout(urb->pipe)) { - /* Unsupported transfer type. - We don't support interrupt out traffic. (If we do, we can't support - intervals for neither in or out traffic, but are forced to schedule all - interrupt traffic in one frame.) */ - return -EINVAL; - } - - epid = etrax_usb_setup_epid(urb); - if (epid == -1) { - DBFEXIT; - return -ENOMEM; - } - - if (!urb_list_empty(epid)) { - /* There is already a queued urb for this endpoint. */ - etrax_usb_free_epid(epid); - return -ENXIO; - } - - urb->status = -EINPROGRESS; - - dbg_intr("Add intr urb 0x%lx, to list, epid %d", (unsigned long)urb, epid); - - urb_list_add(urb, epid); - etrax_usb_add_to_intr_sb_list(urb, epid); - - return 0; - - DBFEXIT; -} - -static void etrax_usb_add_to_intr_sb_list(struct urb *urb, int epid) -{ - - volatile USB_EP_Desc_t *tmp_ep; - volatile USB_EP_Desc_t *first_ep; - - char maxlen; - int interval; - int i; - - etrax_urb_priv_t *urb_priv; - - DBFENTER; - - maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - interval = urb->interval; - - urb_priv = kzalloc(sizeof(etrax_urb_priv_t), KMALLOC_FLAG); - assert(urb_priv != NULL); - urb->hcpriv = urb_priv; - - first_ep = &TxIntrEPList[0]; - - /* Round of the interval to 2^n, it is obvious that this code favours - smaller numbers, but that is actually a good thing */ - /* FIXME: The "rounding error" for larger intervals will be quite - large. For in traffic this shouldn't be a problem since it will only - mean that we "poll" more often. */ - for (i = 0; interval; i++) { - interval = interval >> 1; - } - interval = 1 << (i - 1); - - dbg_intr("Interval rounded to %d", interval); - - tmp_ep = first_ep; - i = 0; - do { - if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) { - if ((i % interval) == 0) { - /* Insert the traffic ep after tmp_ep */ - USB_EP_Desc_t *ep_desc; - USB_SB_Desc_t *sb_desc; - - dbg_intr("Inserting EP for epid %d", epid); - - ep_desc = (USB_EP_Desc_t *) - kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - sb_desc = (USB_SB_Desc_t *) - kmem_cache_alloc(usb_desc_cache, SLAB_FLAG); - assert(ep_desc != NULL); - CHECK_ALIGN(ep_desc); - assert(sb_desc != NULL); - - ep_desc->sub = virt_to_phys(sb_desc); - ep_desc->hw_len = 0; - ep_desc->command = (IO_FIELD(USB_EP_command, epid, epid) | - IO_STATE(USB_EP_command, enable, yes)); - - - /* Round upwards the number of packets of size maxlen - that this SB descriptor should receive. */ - sb_desc->sw_len = urb->transfer_buffer_length ? - (urb->transfer_buffer_length - 1) / maxlen + 1 : 0; - sb_desc->next = 0; - sb_desc->buf = 0; - sb_desc->command = - (IO_FIELD(USB_SB_command, rem, urb->transfer_buffer_length % maxlen) | - IO_STATE(USB_SB_command, tt, in) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - ep_desc->next = tmp_ep->next; - tmp_ep->next = virt_to_phys(ep_desc); - } - i++; - } - tmp_ep = (USB_EP_Desc_t *)phys_to_virt(tmp_ep->next); - } while (tmp_ep != first_ep); - - - /* Note that first_sb/last_sb doesn't apply to interrupt traffic. */ - urb_priv->epid = epid; - - /* We start the DMA sub channel without checking if it's running or not, because: - 1) If it's already running, issuing the start command is a nop. - 2) We avoid a test-and-set race condition. */ - *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start); - - DBFEXIT; -} - - - -static void etrax_usb_complete_intr_urb(struct urb *urb, int status) -{ - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - int epid = urb_priv->epid; - - DBFENTER; - - if (status) - warn("Completing intr urb with status %d.", status); - - dbg_intr("Completing intr epid %d, urb 0x%lx", epid, (unsigned long)urb); - - urb->status = status; - urb->actual_length = urb_priv->rx_offset; - - dbg_intr("interrupt urb->actual_length = %d", urb->actual_length); - - /* We let any non-zero status from the layer above have precedence. */ - if (status == 0) { - /* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's max length) - is to be treated as an error. */ - if (urb->transfer_flags & URB_SHORT_NOT_OK) { - if (urb->actual_length != - usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) { - urb->status = -EREMOTEIO; - } - } - } - - /* The driver will resubmit the URB so we need to remove it first */ - etrax_usb_unlink_urb(urb, 0); - if (urb->complete) { - urb->complete(urb, NULL); - } - - DBFEXIT; -} - - -static int etrax_usb_submit_isoc_urb(struct urb *urb) -{ - int epid; - unsigned long flags; - - DBFENTER; - - dbg_isoc("Submitting isoc urb = 0x%lx", (unsigned long)urb); - - /* Epid allocation, empty check and list add must be protected. - Read about this in etrax_usb_submit_ctrl_urb. */ - - spin_lock_irqsave(&urb_list_lock, flags); - /* Is there an active epid for this urb ? */ - epid = etrax_usb_setup_epid(urb); - if (epid == -1) { - DBFEXIT; - spin_unlock_irqrestore(&urb_list_lock, flags); - return -ENOMEM; - } - - /* Ok, now we got valid endpoint, lets insert some traffic */ - - urb->status = -EINPROGRESS; - - /* Find the last urb in the URB_List and add this urb after that one. - Also add the traffic, that is do an etrax_usb_add_to_isoc_sb_list. This - is important to make this in "real time" since isochronous traffic is - time sensitive. */ - - dbg_isoc("Adding isoc urb to (possibly empty) list"); - urb_list_add(urb, epid); - etrax_usb_add_to_isoc_sb_list(urb, epid); - spin_unlock_irqrestore(&urb_list_lock, flags); - - DBFEXIT; - - return 0; -} - -static void etrax_usb_check_error_isoc_ep(const int epid) -{ - unsigned long int flags; - int error_code; - __u32 r_usb_ept_data; - - /* We can't read R_USB_EPID_ATTN here since it would clear the iso_eof, - bulk_eot and epid_attn interrupts. So we just check the status of - the epid without testing if for it in R_USB_EPID_ATTN. */ - - - save_flags(flags); - cli(); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - /* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO - registers, they are located at the same address and are of the same size. - In other words, this read should be ok for isoc also. */ - r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); - - error_code = IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data); - - if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) { - warn("Hold was set for epid %d.", epid); - return; - } - - if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, no_error)) { - - /* This indicates that the SB list of the ept was completed before - new data was appended to it. This is not an error, but indicates - large system or USB load and could possibly cause trouble for - very timing sensitive USB device drivers so we log it. - */ - info("Isoc. epid %d disabled with no error", epid); - return; - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, stall)) { - /* Not really a protocol error, just says that the endpoint gave - a stall response. Note that error_code cannot be stall for isoc. */ - panic("Isoc traffic cannot stall"); - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA_ISO, error_code, bus_error)) { - /* Two devices responded to a transaction request. Must be resolved - by software. FIXME: Reset ports? */ - panic("Bus error for epid %d." - " Two devices responded to transaction request", - epid); - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) { - /* DMA overrun or underrun. */ - warn("Buffer overrun/underrun for epid %d. DMA too busy?", epid); - - /* It seems that error_code = buffer_error in - R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS - are the same error. */ - } -} - - -static void etrax_usb_add_to_isoc_sb_list(struct urb *urb, int epid) -{ - - int i = 0; - - etrax_urb_priv_t *urb_priv; - USB_SB_Desc_t *prev_sb_desc, *next_sb_desc, *temp_sb_desc; - - DBFENTER; - - prev_sb_desc = next_sb_desc = temp_sb_desc = NULL; - - urb_priv = kzalloc(sizeof(etrax_urb_priv_t), GFP_ATOMIC); - assert(urb_priv != NULL); - - urb->hcpriv = urb_priv; - urb_priv->epid = epid; - - if (usb_pipeout(urb->pipe)) { - - if (urb->number_of_packets == 0) panic("etrax_usb_add_to_isoc_sb_list 0 packets\n"); - - dbg_isoc("Transfer for epid %d is OUT", epid); - dbg_isoc("%d packets in URB", urb->number_of_packets); - - /* Create one SB descriptor for each packet and link them together. */ - for (i = 0; i < urb->number_of_packets; i++) { - if (!urb->iso_frame_desc[i].length) - continue; - - next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC); - assert(next_sb_desc != NULL); - - if (urb->iso_frame_desc[i].length > 0) { - - next_sb_desc->command = (IO_STATE(USB_SB_command, tt, out) | - IO_STATE(USB_SB_command, eot, yes)); - - next_sb_desc->sw_len = urb->iso_frame_desc[i].length; - next_sb_desc->buf = virt_to_phys((char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset); - - /* Check if full length transfer. */ - if (urb->iso_frame_desc[i].length == - usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) { - next_sb_desc->command |= IO_STATE(USB_SB_command, full, yes); - } - } else { - dbg_isoc("zero len packet"); - next_sb_desc->command = (IO_FIELD(USB_SB_command, rem, 0) | - IO_STATE(USB_SB_command, tt, zout) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, full, yes)); - - next_sb_desc->sw_len = 1; - next_sb_desc->buf = virt_to_phys(&zout_buffer[0]); - } - - /* First SB descriptor that belongs to this urb */ - if (i == 0) - urb_priv->first_sb = next_sb_desc; - else - prev_sb_desc->next = virt_to_phys(next_sb_desc); - - prev_sb_desc = next_sb_desc; - } - - next_sb_desc->command |= (IO_STATE(USB_SB_command, intr, yes) | - IO_STATE(USB_SB_command, eol, yes)); - next_sb_desc->next = 0; - urb_priv->last_sb = next_sb_desc; - - } else if (usb_pipein(urb->pipe)) { - - dbg_isoc("Transfer for epid %d is IN", epid); - dbg_isoc("transfer_buffer_length = %d", urb->transfer_buffer_length); - dbg_isoc("rem is calculated to %d", urb->iso_frame_desc[urb->number_of_packets - 1].length); - - /* Note that in descriptors for periodic traffic are not consumed. This means that - the USB controller never propagates in the SB list. In other words, if there already - is an SB descriptor in the list for this EP we don't have to do anything. */ - if (TxIsocEPList[epid].sub == 0) { - dbg_isoc("Isoc traffic not already running, allocating SB"); - - next_sb_desc = (USB_SB_Desc_t*)kmem_cache_alloc(usb_desc_cache, GFP_ATOMIC); - assert(next_sb_desc != NULL); - - next_sb_desc->command = (IO_STATE(USB_SB_command, tt, in) | - IO_STATE(USB_SB_command, eot, yes) | - IO_STATE(USB_SB_command, eol, yes)); - - next_sb_desc->next = 0; - next_sb_desc->sw_len = 1; /* Actual number of packets is not relevant - for periodic in traffic as long as it is more - than zero. Set to 1 always. */ - next_sb_desc->buf = 0; - - /* The rem field is don't care for isoc traffic, so we don't set it. */ - - /* Only one SB descriptor that belongs to this urb. */ - urb_priv->first_sb = next_sb_desc; - urb_priv->last_sb = next_sb_desc; - - } else { - - dbg_isoc("Isoc traffic already running, just setting first/last_sb"); - - /* Each EP for isoc in will have only one SB descriptor, setup when submitting the - already active urb. Note that even though we may have several first_sb/last_sb - pointing at the same SB descriptor, they are freed only once (when the list has - become empty). */ - urb_priv->first_sb = phys_to_virt(TxIsocEPList[epid].sub); - urb_priv->last_sb = phys_to_virt(TxIsocEPList[epid].sub); - return; - } - - } - - /* Find the spot to insert this urb and add it. */ - if (TxIsocEPList[epid].sub == 0) { - /* First SB descriptor inserted in this list (in or out). */ - dbg_isoc("Inserting SB desc first in list"); - TxIsocEPList[epid].hw_len = 0; - TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb); - - } else { - /* Isochronous traffic is already running, insert new traffic last (only out). */ - dbg_isoc("Inserting SB desc last in list"); - temp_sb_desc = phys_to_virt(TxIsocEPList[epid].sub); - while ((temp_sb_desc->command & IO_MASK(USB_SB_command, eol)) != - IO_STATE(USB_SB_command, eol, yes)) { - assert(temp_sb_desc->next); - temp_sb_desc = phys_to_virt(temp_sb_desc->next); - } - dbg_isoc("Appending list on desc 0x%p", temp_sb_desc); - - /* Next pointer must be set before eol is removed. */ - temp_sb_desc->next = virt_to_phys(urb_priv->first_sb); - /* Clear the previous end of list flag since there is a new in the - added SB descriptor list. */ - temp_sb_desc->command &= ~IO_MASK(USB_SB_command, eol); - - if (!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) { - /* 8.8.5 in Designer's Reference says we should check for and correct - any errors in the EP here. That should not be necessary if epid_attn - is handled correctly, so we assume all is ok. */ - dbg_isoc("EP disabled"); - etrax_usb_check_error_isoc_ep(epid); - - /* The SB list was exhausted. */ - if (virt_to_phys(urb_priv->last_sb) != TxIsocEPList[epid].sub) { - /* The new sublist did not get processed before the EP was - disabled. Setup the EP again. */ - dbg_isoc("Set EP sub to new list"); - TxIsocEPList[epid].hw_len = 0; - TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb); - } - } - } - - if (urb->transfer_flags & URB_ISO_ASAP) { - /* The isoc transfer should be started as soon as possible. The start_frame - field is a return value if URB_ISO_ASAP was set. Comparing R_USB_FM_NUMBER - with a USB Chief trace shows that the first isoc IN token is sent 2 frames - later. I'm not sure how this affects usage of the start_frame field by the - device driver, or how it affects things when USB_ISO_ASAP is not set, so - therefore there's no compensation for the 2 frame "lag" here. */ - urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff); - TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - urb_priv->urb_state = STARTED; - dbg_isoc("URB_ISO_ASAP set, urb->start_frame set to %d", urb->start_frame); - } else { - /* Not started yet. */ - urb_priv->urb_state = NOT_STARTED; - dbg_isoc("urb_priv->urb_state set to NOT_STARTED"); - } - - /* We start the DMA sub channel without checking if it's running or not, because: - 1) If it's already running, issuing the start command is a nop. - 2) We avoid a test-and-set race condition. */ - *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start); - - DBFEXIT; -} - -static void etrax_usb_complete_isoc_urb(struct urb *urb, int status) -{ - etrax_urb_priv_t *urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - int epid = urb_priv->epid; - int auto_resubmit = 0; - - DBFENTER; - dbg_isoc("complete urb 0x%p, status %d", urb, status); - - if (status) - warn("Completing isoc urb with status %d.", status); - - if (usb_pipein(urb->pipe)) { - int i; - - /* Make that all isoc packets have status and length set before - completing the urb. */ - for (i = urb_priv->isoc_packet_counter; i < urb->number_of_packets; i++) { - urb->iso_frame_desc[i].actual_length = 0; - urb->iso_frame_desc[i].status = -EPROTO; - } - - urb_list_del(urb, epid); - - if (!list_empty(&urb_list[epid])) { - ((etrax_urb_priv_t *)(urb_list_first(epid)->hcpriv))->urb_state = STARTED; - } else { - unsigned long int flags; - if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) { - /* The EP was enabled, disable it and wait. */ - TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); - - /* Ah, the luxury of busy-wait. */ - while (*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])); - } - - etrax_remove_from_sb_list(urb); - TxIsocEPList[epid].sub = 0; - TxIsocEPList[epid].hw_len = 0; - - save_flags(flags); - cli(); - etrax_usb_free_epid(epid); - restore_flags(flags); - } - - urb->hcpriv = 0; - kfree(urb_priv); - - /* Release allocated bandwidth. */ - usb_release_bandwidth(urb->dev, urb, 0); - } else if (usb_pipeout(urb->pipe)) { - int freed_descr; - - dbg_isoc("Isoc out urb complete 0x%p", urb); - - /* Update the urb list. */ - urb_list_del(urb, epid); - - freed_descr = etrax_remove_from_sb_list(urb); - dbg_isoc("freed %d descriptors of %d packets", freed_descr, urb->number_of_packets); - assert(freed_descr == urb->number_of_packets); - urb->hcpriv = 0; - kfree(urb_priv); - - /* Release allocated bandwidth. */ - usb_release_bandwidth(urb->dev, urb, 0); - } - - urb->status = status; - if (urb->complete) { - urb->complete(urb, NULL); - } - - if (auto_resubmit) { - /* Check that urb was not unlinked by the complete callback. */ - if (__urb_list_entry(urb, epid)) { - /* Move this one down the list. */ - urb_list_move_last(urb, epid); - - /* Mark the now first urb as started (may already be). */ - ((etrax_urb_priv_t *)(urb_list_first(epid)->hcpriv))->urb_state = STARTED; - - /* Must set this to 0 since this urb is still active after - completion. */ - urb_priv->isoc_packet_counter = 0; - } else { - warn("(ISOC) automatic resubmit urb 0x%p removed by complete.", urb); - } - } - - DBFEXIT; -} - -static void etrax_usb_complete_urb(struct urb *urb, int status) -{ - switch (usb_pipetype(urb->pipe)) { - case PIPE_BULK: - etrax_usb_complete_bulk_urb(urb, status); - break; - case PIPE_CONTROL: - etrax_usb_complete_ctrl_urb(urb, status); - break; - case PIPE_INTERRUPT: - etrax_usb_complete_intr_urb(urb, status); - break; - case PIPE_ISOCHRONOUS: - etrax_usb_complete_isoc_urb(urb, status); - break; - default: - err("Unknown pipetype"); - } -} - - - -static irqreturn_t etrax_usb_hc_interrupt_top_half(int irq, void *vhc) -{ - usb_interrupt_registers_t *reg; - unsigned long flags; - __u32 irq_mask; - __u8 status; - __u32 epid_attn; - __u16 port_status_1; - __u16 port_status_2; - __u32 fm_number; - - DBFENTER; - - /* Read critical registers into local variables, do kmalloc afterwards. */ - save_flags(flags); - cli(); - - irq_mask = *R_USB_IRQ_MASK_READ; - /* Reading R_USB_STATUS clears the ctl_status interrupt. Note that R_USB_STATUS - must be read before R_USB_EPID_ATTN since reading the latter clears the - ourun and perror fields of R_USB_STATUS. */ - status = *R_USB_STATUS; - - /* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn interrupts. */ - epid_attn = *R_USB_EPID_ATTN; - - /* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the - port_status interrupt. */ - port_status_1 = *R_USB_RH_PORT_STATUS_1; - port_status_2 = *R_USB_RH_PORT_STATUS_2; - - /* Reading R_USB_FM_NUMBER clears the sof interrupt. */ - /* Note: the lower 11 bits contain the actual frame number, sent with each sof. */ - fm_number = *R_USB_FM_NUMBER; - - restore_flags(flags); - - reg = (usb_interrupt_registers_t *)kmem_cache_alloc(top_half_reg_cache, GFP_ATOMIC); - - assert(reg != NULL); - - reg->hc = (etrax_hc_t *)vhc; - - /* Now put register values into kmalloc'd area. */ - reg->r_usb_irq_mask_read = irq_mask; - reg->r_usb_status = status; - reg->r_usb_epid_attn = epid_attn; - reg->r_usb_rh_port_status_1 = port_status_1; - reg->r_usb_rh_port_status_2 = port_status_2; - reg->r_usb_fm_number = fm_number; - - INIT_WORK(®->usb_bh, etrax_usb_hc_interrupt_bottom_half, reg); - schedule_work(®->usb_bh); - - DBFEXIT; - - return IRQ_HANDLED; -} - -static void etrax_usb_hc_interrupt_bottom_half(void *data) -{ - usb_interrupt_registers_t *reg = (usb_interrupt_registers_t *)data; - __u32 irq_mask = reg->r_usb_irq_mask_read; - - DBFENTER; - - /* Interrupts are handled in order of priority. */ - if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) { - etrax_usb_hc_epid_attn_interrupt(reg); - } - if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) { - etrax_usb_hc_port_status_interrupt(reg); - } - if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) { - etrax_usb_hc_ctl_status_interrupt(reg); - } - if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) { - etrax_usb_hc_isoc_eof_interrupt(); - } - if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) { - /* Update/restart the bulk start timer since obviously the channel is running. */ - mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL); - /* Update/restart the bulk eot timer since we just received an bulk eot interrupt. */ - mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); - - etrax_usb_hc_bulk_eot_interrupt(0); - } - - kmem_cache_free(top_half_reg_cache, reg); - - DBFEXIT; -} - - -void etrax_usb_hc_isoc_eof_interrupt(void) -{ - struct urb *urb; - etrax_urb_priv_t *urb_priv; - int epid; - unsigned long flags; - - DBFENTER; - - /* Do not check the invalid epid (it has a valid sub pointer). */ - for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { - - /* Do not check the invalid epid (it has a valid sub pointer). */ - if ((epid == DUMMY_EPID) || (epid == INVALID_EPID)) - continue; - - /* Disable interrupts to block the isoc out descriptor interrupt handler - from being called while the isoc EPID list is being checked. - */ - save_flags(flags); - cli(); - - if (TxIsocEPList[epid].sub == 0) { - /* Nothing here to see. */ - restore_flags(flags); - continue; - } - - /* Get the first urb (if any). */ - urb = urb_list_first(epid); - if (urb == 0) { - warn("Ignoring NULL urb"); - restore_flags(flags); - continue; - } - if (usb_pipein(urb->pipe)) { - - /* Sanity check. */ - assert(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS); - - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - if (urb_priv->urb_state == NOT_STARTED) { - - /* If ASAP is not set and urb->start_frame is the current frame, - start the transfer. */ - if (!(urb->transfer_flags & URB_ISO_ASAP) && - (urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) { - - dbg_isoc("Enabling isoc IN EP descr for epid %d", epid); - TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); - - /* This urb is now active. */ - urb_priv->urb_state = STARTED; - continue; - } - } - } - restore_flags(flags); - } - - DBFEXIT; - -} - -void etrax_usb_hc_bulk_eot_interrupt(int timer_induced) -{ - int epid; - - /* The technique is to run one urb at a time, wait for the eot interrupt at which - point the EP descriptor has been disabled. */ - - DBFENTER; - dbg_bulk("bulk eot%s", timer_induced ? ", called by timer" : ""); - - for (epid = 0; epid < NBR_OF_EPIDS; epid++) { - - if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) && - (TxBulkEPList[epid].sub != 0)) { - - struct urb *urb; - etrax_urb_priv_t *urb_priv; - unsigned long flags; - __u32 r_usb_ept_data; - - /* Found a disabled EP descriptor which has a non-null sub pointer. - Verify that this ctrl EP descriptor got disabled no errors. - FIXME: Necessary to check error_code? */ - dbg_bulk("for epid %d?", epid); - - /* Get the first urb. */ - urb = urb_list_first(epid); - - /* FIXME: Could this happen for valid reasons? Why did it disappear? Because of - wrong unlinking? */ - if (!urb) { - warn("NULL urb for epid %d", epid); - continue; - } - - assert(urb); - urb_priv = (etrax_urb_priv_t *)urb->hcpriv; - assert(urb_priv); - - /* Sanity checks. */ - assert(usb_pipetype(urb->pipe) == PIPE_BULK); - if (phys_to_virt(TxBulkEPList[epid].sub) != urb_priv->last_sb) { - err("bulk endpoint got disabled before reaching last sb"); - } - - /* For bulk IN traffic, there seems to be a race condition between - between the bulk eot and eop interrupts, or rather an uncertainty regarding - the order in which they happen. Normally we expect the eop interrupt from - DMA channel 9 to happen before the eot interrupt. - - Therefore, we complete the bulk IN urb in the rx interrupt handler instead. */ - - if (usb_pipein(urb->pipe)) { - dbg_bulk("in urb, continuing"); - continue; - } - - save_flags(flags); - cli(); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); - - if (IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data) == - IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { - /* This means that the endpoint has no error, is disabled - and had inserted traffic, i.e. transfer successfully completed. */ - etrax_usb_complete_bulk_urb(urb, 0); - } else { - /* Shouldn't happen. We expect errors to be caught by epid attention. */ - err("Found disabled bulk EP desc, error_code != no_error"); - } - } - } - - /* Normally, we should find (at least) one disabled EP descriptor with a valid sub pointer. - However, because of the uncertainty in the deliverance of the eop/eot interrupts, we may - not. Also, we might find two disabled EPs when handling an eot interrupt, and then find - none the next time. */ - - DBFEXIT; - -} - -void etrax_usb_hc_epid_attn_interrupt(usb_interrupt_registers_t *reg) -{ - /* This function handles the epid attention interrupt. There are a variety of reasons - for this interrupt to happen (Designer's Reference, p. 8 - 22 for the details): - - invalid ep_id - Invalid epid in an EP (EP disabled). - stall - Not strictly an error condition (EP disabled). - 3rd error - Three successive transaction errors (EP disabled). - buffer ourun - Buffer overrun or underrun (EP disabled). - past eof1 - Intr or isoc transaction proceeds past EOF1. - near eof - Intr or isoc transaction would not fit inside the frame. - zout transfer - If zout transfer for a bulk endpoint (EP disabled). - setup transfer - If setup transfer for a non-ctrl endpoint (EP disabled). */ - - int epid; - - - DBFENTER; - - assert(reg != NULL); - - /* Note that we loop through all epids. We still want to catch errors for - the invalid one, even though we might handle them differently. */ - for (epid = 0; epid < NBR_OF_EPIDS; epid++) { - - if (test_bit(epid, (void *)®->r_usb_epid_attn)) { - - struct urb *urb; - __u32 r_usb_ept_data; - unsigned long flags; - int error_code; - - save_flags(flags); - cli(); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); - nop(); - /* Note that although there are separate R_USB_EPT_DATA and R_USB_EPT_DATA_ISO - registers, they are located at the same address and are of the same size. - In other words, this read should be ok for isoc also. */ - r_usb_ept_data = *R_USB_EPT_DATA; - restore_flags(flags); - - /* First some sanity checks. */ - if (epid == INVALID_EPID) { - /* FIXME: What if it became disabled? Could seriously hurt interrupt - traffic. (Use do_intr_recover.) */ - warn("Got epid_attn for INVALID_EPID (%d).", epid); - err("R_USB_EPT_DATA = 0x%x", r_usb_ept_data); - err("R_USB_STATUS = 0x%x", reg->r_usb_status); - continue; - } else if (epid == DUMMY_EPID) { - /* We definitely don't care about these ones. Besides, they are - always disabled, so any possible disabling caused by the - epid attention interrupt is irrelevant. */ - warn("Got epid_attn for DUMMY_EPID (%d).", epid); - continue; - } - - /* Get the first urb in the urb list for this epid. We blatantly assume - that only the first urb could have caused the epid attention. - (For bulk and ctrl, only one urb is active at any one time. For intr - and isoc we remove them once they are completed.) */ - urb = urb_list_first(epid); - - if (urb == NULL) { - err("Got epid_attn for epid %i with no urb.", epid); - err("R_USB_EPT_DATA = 0x%x", r_usb_ept_data); - err("R_USB_STATUS = 0x%x", reg->r_usb_status); - continue; - } - - switch (usb_pipetype(urb->pipe)) { - case PIPE_BULK: - warn("Got epid attn for bulk endpoint, epid %d", epid); - break; - case PIPE_CONTROL: - warn("Got epid attn for control endpoint, epid %d", epid); - break; - case PIPE_INTERRUPT: - warn("Got epid attn for interrupt endpoint, epid %d", epid); - break; - case PIPE_ISOCHRONOUS: - warn("Got epid attn for isochronous endpoint, epid %d", epid); - break; - } - - if (usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) { - if (r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, hold)) { - warn("Hold was set for epid %d.", epid); - continue; - } - } - - /* Even though error_code occupies bits 22 - 23 in both R_USB_EPT_DATA and - R_USB_EPT_DATA_ISOC, we separate them here so we don't forget in other places. */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - error_code = IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data); - } else { - error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code, r_usb_ept_data); - } - - /* Using IO_STATE_VALUE on R_USB_EPT_DATA should be ok for isoc also. */ - if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { - - /* Isoc traffic doesn't have error_count_in/error_count_out. */ - if ((usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) && - (IO_EXTRACT(R_USB_EPT_DATA, error_count_in, r_usb_ept_data) == 3 || - IO_EXTRACT(R_USB_EPT_DATA, error_count_out, r_usb_ept_data) == 3)) { - /* 3rd error. */ - warn("3rd error for epid %i", epid); - etrax_usb_complete_urb(urb, -EPROTO); - - } else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) { - - warn("Perror for epid %d", epid); - - if (!(r_usb_ept_data & IO_MASK(R_USB_EPT_DATA, valid))) { - /* invalid ep_id */ - panic("Perror because of invalid epid." - " Deconfigured too early?"); - } else { - /* past eof1, near eof, zout transfer, setup transfer */ - - /* Dump the urb and the relevant EP descriptor list. */ - - __dump_urb(urb); - __dump_ept_data(epid); - __dump_ep_list(usb_pipetype(urb->pipe)); - - panic("Something wrong with DMA descriptor contents." - " Too much traffic inserted?"); - } - } else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) { - /* buffer ourun */ - panic("Buffer overrun/underrun for epid %d. DMA too busy?", epid); - } - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, stall)) { - /* Not really a protocol error, just says that the endpoint gave - a stall response. Note that error_code cannot be stall for isoc. */ - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - panic("Isoc traffic cannot stall"); - } - - warn("Stall for epid %d", epid); - etrax_usb_complete_urb(urb, -EPIPE); - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, bus_error)) { - /* Two devices responded to a transaction request. Must be resolved - by software. FIXME: Reset ports? */ - panic("Bus error for epid %d." - " Two devices responded to transaction request", - epid); - - } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, buffer_error)) { - /* DMA overrun or underrun. */ - warn("Buffer overrun/underrun for epid %d. DMA too busy?", epid); - - /* It seems that error_code = buffer_error in - R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS - are the same error. */ - etrax_usb_complete_urb(urb, -EPROTO); - } - } - } - - DBFEXIT; - -} - -void etrax_usb_bulk_start_timer_func(unsigned long dummy) -{ - - /* We might enable an EP descriptor behind the current DMA position when it's about - to decide that there are no more bulk traffic and it should stop the bulk channel. - Therefore we periodically check if the bulk channel is stopped and there is an - enabled bulk EP descriptor, in which case we start the bulk channel. */ - dbg_bulk("bulk_start_timer timed out."); - - if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) { - int epid; - - dbg_bulk("Bulk DMA channel not running."); - - for (epid = 0; epid < NBR_OF_EPIDS; epid++) { - if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) { - dbg_bulk("Found enabled EP for epid %d, starting bulk channel.\n", - epid); - *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); - - /* Restart the bulk eot timer since we just started the bulk channel. */ - mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); - - /* No need to search any further. */ - break; - } - } - } else { - dbg_bulk("Bulk DMA channel running."); - } -} - -void etrax_usb_hc_port_status_interrupt(usb_interrupt_registers_t *reg) -{ - etrax_hc_t *hc = reg->hc; - __u16 r_usb_rh_port_status_1 = reg->r_usb_rh_port_status_1; - __u16 r_usb_rh_port_status_2 = reg->r_usb_rh_port_status_2; - - DBFENTER; - - /* The Etrax RH does not include a wPortChange register, so this has to be handled in software - (by saving the old port status value for comparison when the port status interrupt happens). - See section 11.16.2.6.2 in the USB 1.1 spec for details. */ - - dbg_rh("hc->rh.prev_wPortStatus_1 = 0x%x", hc->rh.prev_wPortStatus_1); - dbg_rh("hc->rh.prev_wPortStatus_2 = 0x%x", hc->rh.prev_wPortStatus_2); - dbg_rh("r_usb_rh_port_status_1 = 0x%x", r_usb_rh_port_status_1); - dbg_rh("r_usb_rh_port_status_2 = 0x%x", r_usb_rh_port_status_2); - - /* C_PORT_CONNECTION is set on any transition. */ - hc->rh.wPortChange_1 |= - ((r_usb_rh_port_status_1 & (1 << RH_PORT_CONNECTION)) != - (hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_CONNECTION))) ? - (1 << RH_PORT_CONNECTION) : 0; - - hc->rh.wPortChange_2 |= - ((r_usb_rh_port_status_2 & (1 << RH_PORT_CONNECTION)) != - (hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_CONNECTION))) ? - (1 << RH_PORT_CONNECTION) : 0; - - /* C_PORT_ENABLE is _only_ set on a one to zero transition, i.e. when - the port is disabled, not when it's enabled. */ - hc->rh.wPortChange_1 |= - ((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_ENABLE)) - && !(r_usb_rh_port_status_1 & (1 << RH_PORT_ENABLE))) ? - (1 << RH_PORT_ENABLE) : 0; - - hc->rh.wPortChange_2 |= - ((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_ENABLE)) - && !(r_usb_rh_port_status_2 & (1 << RH_PORT_ENABLE))) ? - (1 << RH_PORT_ENABLE) : 0; - - /* C_PORT_SUSPEND is set to one when the device has transitioned out - of the suspended state, i.e. when suspend goes from one to zero. */ - hc->rh.wPortChange_1 |= - ((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_SUSPEND)) - && !(r_usb_rh_port_status_1 & (1 << RH_PORT_SUSPEND))) ? - (1 << RH_PORT_SUSPEND) : 0; - - hc->rh.wPortChange_2 |= - ((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_SUSPEND)) - && !(r_usb_rh_port_status_2 & (1 << RH_PORT_SUSPEND))) ? - (1 << RH_PORT_SUSPEND) : 0; - - - /* C_PORT_RESET is set when reset processing on this port is complete. */ - hc->rh.wPortChange_1 |= - ((hc->rh.prev_wPortStatus_1 & (1 << RH_PORT_RESET)) - && !(r_usb_rh_port_status_1 & (1 << RH_PORT_RESET))) ? - (1 << RH_PORT_RESET) : 0; - - hc->rh.wPortChange_2 |= - ((hc->rh.prev_wPortStatus_2 & (1 << RH_PORT_RESET)) - && !(r_usb_rh_port_status_2 & (1 << RH_PORT_RESET))) ? - (1 << RH_PORT_RESET) : 0; - - /* Save the new values for next port status change. */ - hc->rh.prev_wPortStatus_1 = r_usb_rh_port_status_1; - hc->rh.prev_wPortStatus_2 = r_usb_rh_port_status_2; - - dbg_rh("hc->rh.wPortChange_1 set to 0x%x", hc->rh.wPortChange_1); - dbg_rh("hc->rh.wPortChange_2 set to 0x%x", hc->rh.wPortChange_2); - - DBFEXIT; - -} - -void etrax_usb_hc_ctl_status_interrupt(usb_interrupt_registers_t *reg) -{ - DBFENTER; - - /* FIXME: What should we do if we get ourun or perror? Dump the EP and SB - list for the corresponding epid? */ - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) { - panic("USB controller got ourun."); - } - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) { - - /* Before, etrax_usb_do_intr_recover was called on this epid if it was - an interrupt pipe. I don't see how re-enabling all EP descriptors - will help if there was a programming error. */ - panic("USB controller got perror."); - } - - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, device_mode)) { - /* We should never operate in device mode. */ - panic("USB controller in device mode."); - } - - /* These if-statements could probably be nested. */ - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, host_mode)) { - info("USB controller in host mode."); - } - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, started)) { - info("USB controller started."); - } - if (reg->r_usb_status & IO_MASK(R_USB_STATUS, running)) { - info("USB controller running."); - } - - DBFEXIT; - -} - - -static int etrax_rh_submit_urb(struct urb *urb) -{ - struct usb_device *usb_dev = urb->dev; - etrax_hc_t *hc = usb_dev->bus->hcpriv; - unsigned int pipe = urb->pipe; - struct usb_ctrlrequest *cmd = (struct usb_ctrlrequest *) urb->setup_packet; - void *data = urb->transfer_buffer; - int leni = urb->transfer_buffer_length; - int len = 0; - int stat = 0; - - __u16 bmRType_bReq; - __u16 wValue; - __u16 wIndex; - __u16 wLength; - - DBFENTER; - - /* FIXME: What is this interrupt urb that is sent to the root hub? */ - if (usb_pipetype (pipe) == PIPE_INTERRUPT) { - dbg_rh("Root-Hub submit IRQ: every %d ms", urb->interval); - hc->rh.urb = urb; - hc->rh.send = 1; - /* FIXME: We could probably remove this line since it's done - in etrax_rh_init_int_timer. (Don't remove it from - etrax_rh_init_int_timer though.) */ - hc->rh.interval = urb->interval; - etrax_rh_init_int_timer(urb); - DBFEXIT; - - return 0; - } - - bmRType_bReq = cmd->bRequestType | (cmd->bRequest << 8); - wValue = le16_to_cpu(cmd->wValue); - wIndex = le16_to_cpu(cmd->wIndex); - wLength = le16_to_cpu(cmd->wLength); - - dbg_rh("bmRType_bReq : 0x%04x (%d)", bmRType_bReq, bmRType_bReq); - dbg_rh("wValue : 0x%04x (%d)", wValue, wValue); - dbg_rh("wIndex : 0x%04x (%d)", wIndex, wIndex); - dbg_rh("wLength : 0x%04x (%d)", wLength, wLength); - - switch (bmRType_bReq) { - - /* Request Destination: - without flags: Device, - RH_INTERFACE: interface, - RH_ENDPOINT: endpoint, - RH_CLASS means HUB here, - RH_OTHER | RH_CLASS almost ever means HUB_PORT here - */ - - case RH_GET_STATUS: - *(__u16 *) data = cpu_to_le16 (1); - OK (2); - - case RH_GET_STATUS | RH_INTERFACE: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - - case RH_GET_STATUS | RH_ENDPOINT: - *(__u16 *) data = cpu_to_le16 (0); - OK (2); - - case RH_GET_STATUS | RH_CLASS: - *(__u32 *) data = cpu_to_le32 (0); - OK (4); /* hub power ** */ - - case RH_GET_STATUS | RH_OTHER | RH_CLASS: - if (wIndex == 1) { - *((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_1); - *((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_1); - } else if (wIndex == 2) { - *((__u16*)data) = cpu_to_le16(hc->rh.prev_wPortStatus_2); - *((__u16*)data + 1) = cpu_to_le16(hc->rh.wPortChange_2); - } else { - dbg_rh("RH_GET_STATUS whith invalid wIndex!"); - OK(0); - } - - OK(4); - - case RH_CLEAR_FEATURE | RH_ENDPOINT: - switch (wValue) { - case (RH_ENDPOINT_STALL): - OK (0); - } - break; - - case RH_CLEAR_FEATURE | RH_CLASS: - switch (wValue) { - case (RH_C_HUB_OVER_CURRENT): - OK (0); /* hub power over current ** */ - } - break; - - case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_ENABLE): - if (wIndex == 1) { - - dbg_rh("trying to do disable port 1"); - - *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes); - - while (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)); - *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no); - dbg_rh("Port 1 is disabled"); - - } else if (wIndex == 2) { - - dbg_rh("trying to do disable port 2"); - - *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes); - - while (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes)); - *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no); - dbg_rh("Port 2 is disabled"); - - } else { - dbg_rh("RH_CLEAR_FEATURE->RH_PORT_ENABLE " - "with invalid wIndex == %d!", wIndex); - } - - OK (0); - case (RH_PORT_SUSPEND): - /* Opposite to suspend should be resume, so we'll do a resume. */ - /* FIXME: USB 1.1, 11.16.2.2 says: - "Clearing the PORT_SUSPEND feature causes a host-initiated resume - on the specified port. If the port is not in the Suspended state, - the hub should treat this request as a functional no-operation." - Shouldn't we check if the port is in a suspended state before - resuming? */ - - /* Make sure the controller isn't busy. */ - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - if (wIndex == 1) { - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port1) | - IO_STATE(R_USB_COMMAND, port_cmd, resume) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - } else if (wIndex == 2) { - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port2) | - IO_STATE(R_USB_COMMAND, port_cmd, resume) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - } else { - dbg_rh("RH_CLEAR_FEATURE->RH_PORT_SUSPEND " - "with invalid wIndex == %d!", wIndex); - } - - OK (0); - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_C_PORT_CONNECTION): - if (wIndex == 1) { - hc->rh.wPortChange_1 &= ~(1 << RH_PORT_CONNECTION); - } else if (wIndex == 2) { - hc->rh.wPortChange_2 &= ~(1 << RH_PORT_CONNECTION); - } else { - dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_CONNECTION " - "with invalid wIndex == %d!", wIndex); - } - - OK (0); - case (RH_C_PORT_ENABLE): - if (wIndex == 1) { - hc->rh.wPortChange_1 &= ~(1 << RH_PORT_ENABLE); - } else if (wIndex == 2) { - hc->rh.wPortChange_2 &= ~(1 << RH_PORT_ENABLE); - } else { - dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_ENABLE " - "with invalid wIndex == %d!", wIndex); - } - OK (0); - case (RH_C_PORT_SUSPEND): -/*** WR_RH_PORTSTAT(RH_PS_PSSC); */ - OK (0); - case (RH_C_PORT_OVER_CURRENT): - OK (0); /* port power over current ** */ - case (RH_C_PORT_RESET): - if (wIndex == 1) { - hc->rh.wPortChange_1 &= ~(1 << RH_PORT_RESET); - } else if (wIndex == 2) { - hc->rh.wPortChange_2 &= ~(1 << RH_PORT_RESET); - } else { - dbg_rh("RH_CLEAR_FEATURE->RH_C_PORT_RESET " - "with invalid index == %d!", wIndex); - } - - OK (0); - - } - break; - - case RH_SET_FEATURE | RH_OTHER | RH_CLASS: - switch (wValue) { - case (RH_PORT_SUSPEND): - - /* Make sure the controller isn't busy. */ - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - if (wIndex == 1) { - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port1) | - IO_STATE(R_USB_COMMAND, port_cmd, suspend) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - } else if (wIndex == 2) { - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port2) | - IO_STATE(R_USB_COMMAND, port_cmd, suspend) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - } else { - dbg_rh("RH_SET_FEATURE->RH_PORT_SUSPEND " - "with invalid wIndex == %d!", wIndex); - } - - OK (0); - case (RH_PORT_RESET): - if (wIndex == 1) { - - port_1_reset: - dbg_rh("Doing reset of port 1"); - - /* Make sure the controller isn't busy. */ - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port1) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - - /* We must wait at least 10 ms for the device to recover. - 15 ms should be enough. */ - udelay(15000); - - /* Wait for reset bit to go low (should be done by now). */ - while (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, reset, yes)); - - /* If the port status is - 1) connected and enabled then there is a device and everything is fine - 2) neither connected nor enabled then there is no device, also fine - 3) connected and not enabled then we try again - (Yes, there are other port status combinations besides these.) */ - - if ((hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) && - (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no))) { - dbg_rh("Connected device on port 1, but port not enabled?" - " Trying reset again."); - goto port_2_reset; - } - - /* Diagnostic printouts. */ - if ((hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, connected, no)) && - (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no))) { - dbg_rh("No connected device on port 1"); - } else if ((hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) && - (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes))) { - dbg_rh("Connected device on port 1, port 1 enabled"); - } - - } else if (wIndex == 2) { - - port_2_reset: - dbg_rh("Doing reset of port 2"); - - /* Make sure the controller isn't busy. */ - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - /* Issue the reset command. */ - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, port2) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, nop); - - /* We must wait at least 10 ms for the device to recover. - 15 ms should be enough. */ - udelay(15000); - - /* Wait for reset bit to go low (should be done by now). */ - while (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, reset, yes)); - - /* If the port status is - 1) connected and enabled then there is a device and everything is fine - 2) neither connected nor enabled then there is no device, also fine - 3) connected and not enabled then we try again - (Yes, there are other port status combinations besides these.) */ - - if ((hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, connected, yes)) && - (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no))) { - dbg_rh("Connected device on port 2, but port not enabled?" - " Trying reset again."); - goto port_2_reset; - } - - /* Diagnostic printouts. */ - if ((hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, connected, no)) && - (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no))) { - dbg_rh("No connected device on port 2"); - } else if ((hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, connected, yes)) && - (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, yes))) { - dbg_rh("Connected device on port 2, port 2 enabled"); - } - - } else { - dbg_rh("RH_SET_FEATURE->RH_PORT_RESET with invalid wIndex = %d", wIndex); - } - - /* Make sure the controller isn't busy. */ - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - /* If all enabled ports were disabled the host controller goes down into - started mode, so we need to bring it back into the running state. - (This is safe even if it's already in the running state.) */ - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, nop) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run); - - dbg_rh("...Done"); - OK(0); - - case (RH_PORT_POWER): - OK (0); /* port power ** */ - case (RH_PORT_ENABLE): - /* There is no port enable command in the host controller, so if the - port is already enabled, we do nothing. If not, we reset the port - (with an ugly goto). */ - - if (wIndex == 1) { - if (hc->rh.prev_wPortStatus_1 & - IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, no)) { - goto port_1_reset; - } - } else if (wIndex == 2) { - if (hc->rh.prev_wPortStatus_2 & - IO_STATE(R_USB_RH_PORT_STATUS_2, enabled, no)) { - goto port_2_reset; - } - } else { - dbg_rh("RH_SET_FEATURE->RH_GET_STATUS with invalid wIndex = %d", wIndex); - } - OK (0); - } - break; - - case RH_SET_ADDRESS: - hc->rh.devnum = wValue; - dbg_rh("RH address set to: %d", hc->rh.devnum); - OK (0); - - case RH_GET_DESCRIPTOR: - switch ((wValue & 0xff00) >> 8) { - case (0x01): /* device descriptor */ - len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_dev_des), wLength)); - memcpy (data, root_hub_dev_des, len); - OK (len); - case (0x02): /* configuration descriptor */ - len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_config_des), wLength)); - memcpy (data, root_hub_config_des, len); - OK (len); - case (0x03): /* string descriptors */ - len = usb_root_hub_string (wValue & 0xff, - 0xff, "ETRAX 100LX", - data, wLength); - if (len > 0) { - OK(min(leni, len)); - } else { - stat = -EPIPE; - } - - } - break; - - case RH_GET_DESCRIPTOR | RH_CLASS: - root_hub_hub_des[2] = hc->rh.numports; - len = min_t(unsigned int, leni, min_t(unsigned int, sizeof (root_hub_hub_des), wLength)); - memcpy (data, root_hub_hub_des, len); - OK (len); - - case RH_GET_CONFIGURATION: - *(__u8 *) data = 0x01; - OK (1); - - case RH_SET_CONFIGURATION: - OK (0); - - default: - stat = -EPIPE; - } - - urb->actual_length = len; - urb->status = stat; - urb->dev = NULL; - if (urb->complete) { - urb->complete(urb, NULL); - } - DBFEXIT; - - return 0; -} - -static void -etrax_usb_bulk_eot_timer_func(unsigned long dummy) -{ - /* Because of a race condition in the top half, we might miss a bulk eot. - This timer "simulates" a bulk eot if we don't get one for a while, hopefully - correcting the situation. */ - dbg_bulk("bulk_eot_timer timed out."); - etrax_usb_hc_bulk_eot_interrupt(1); -} - -static void* -etrax_usb_buffer_alloc(struct usb_bus* bus, size_t size, - unsigned mem_flags, dma_addr_t *dma) -{ - return kmalloc(size, mem_flags); -} - -static void -etrax_usb_buffer_free(struct usb_bus *bus, size_t size, void *addr, dma_addr_t dma) -{ - kfree(addr); -} - - -static struct device fake_device; - -static int __init etrax_usb_hc_init(void) -{ - static etrax_hc_t *hc; - struct usb_bus *bus; - struct usb_device *usb_rh; - int i; - - DBFENTER; - - info("ETRAX 100LX USB-HCD %s (c) 2001-2003 Axis Communications AB\n", usb_hcd_version); - - hc = kmalloc(sizeof(etrax_hc_t), GFP_KERNEL); - assert(hc != NULL); - - /* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */ - /* Note that we specify sizeof(USB_EP_Desc_t) as the size, but also allocate - SB descriptors from this cache. This is ok since sizeof(USB_EP_Desc_t) == - sizeof(USB_SB_Desc_t). */ - - usb_desc_cache = kmem_cache_create("usb_desc_cache", sizeof(USB_EP_Desc_t), 0, - SLAB_HWCACHE_ALIGN, 0, 0); - assert(usb_desc_cache != NULL); - - top_half_reg_cache = kmem_cache_create("top_half_reg_cache", - sizeof(usb_interrupt_registers_t), - 0, SLAB_HWCACHE_ALIGN, 0, 0); - assert(top_half_reg_cache != NULL); - - isoc_compl_cache = kmem_cache_create("isoc_compl_cache", - sizeof(usb_isoc_complete_data_t), - 0, SLAB_HWCACHE_ALIGN, 0, 0); - assert(isoc_compl_cache != NULL); - - etrax_usb_bus = bus = usb_alloc_bus(&etrax_usb_device_operations); - hc->bus = bus; - bus->bus_name="ETRAX 100LX"; - bus->hcpriv = hc; - - /* Initialize RH to the default address. - And make sure that we have no status change indication */ - hc->rh.numports = 2; /* The RH has two ports */ - hc->rh.devnum = 1; - hc->rh.wPortChange_1 = 0; - hc->rh.wPortChange_2 = 0; - - /* Also initate the previous values to zero */ - hc->rh.prev_wPortStatus_1 = 0; - hc->rh.prev_wPortStatus_2 = 0; - - /* Initialize the intr-traffic flags */ - /* FIXME: This isn't used. (Besides, the error field isn't initialized.) */ - hc->intr.sleeping = 0; - hc->intr.wq = NULL; - - epid_usage_bitmask = 0; - epid_out_traffic = 0; - - /* Mark the invalid epid as being used. */ - set_bit(INVALID_EPID, (void *)&epid_usage_bitmask); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, INVALID_EPID); - nop(); - /* The valid bit should still be set ('invalid' is in our world; not the hardware's). */ - *R_USB_EPT_DATA = (IO_STATE(R_USB_EPT_DATA, valid, yes) | - IO_FIELD(R_USB_EPT_DATA, max_len, 1)); - - /* Mark the dummy epid as being used. */ - set_bit(DUMMY_EPID, (void *)&epid_usage_bitmask); - *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, DUMMY_EPID); - nop(); - *R_USB_EPT_DATA = (IO_STATE(R_USB_EPT_DATA, valid, no) | - IO_FIELD(R_USB_EPT_DATA, max_len, 1)); - - /* Initialize the urb list by initiating a head for each list. */ - for (i = 0; i < NBR_OF_EPIDS; i++) { - INIT_LIST_HEAD(&urb_list[i]); - } - spin_lock_init(&urb_list_lock); - - INIT_LIST_HEAD(&urb_unlink_list); - - - /* Initiate the bulk start timer. */ - init_timer(&bulk_start_timer); - bulk_start_timer.expires = jiffies + BULK_START_TIMER_INTERVAL; - bulk_start_timer.function = etrax_usb_bulk_start_timer_func; - add_timer(&bulk_start_timer); - - - /* Initiate the bulk eot timer. */ - init_timer(&bulk_eot_timer); - bulk_eot_timer.expires = jiffies + BULK_EOT_TIMER_INTERVAL; - bulk_eot_timer.function = etrax_usb_bulk_eot_timer_func; - add_timer(&bulk_eot_timer); - - /* Set up the data structures for USB traffic. Note that this must be done before - any interrupt that relies on sane DMA list occurrs. */ - init_rx_buffers(); - init_tx_bulk_ep(); - init_tx_ctrl_ep(); - init_tx_intr_ep(); - init_tx_isoc_ep(); - - device_initialize(&fake_device); - kobject_set_name(&fake_device.kobj, "etrax_usb"); - kobject_add(&fake_device.kobj); - kobject_uevent(&fake_device.kobj, KOBJ_ADD); - hc->bus->controller = &fake_device; - usb_register_bus(hc->bus); - - *R_IRQ_MASK2_SET = - /* Note that these interrupts are not used. */ - IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) | - /* Sub channel 1 (ctrl) descr. interrupts are used. */ - IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) | - IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) | - /* Sub channel 3 (isoc) descr. interrupts are used. */ - IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set); - - /* Note that the dma9_descr interrupt is not used. */ - *R_IRQ_MASK2_SET = - IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) | - IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set); - - /* FIXME: Enable iso_eof only when isoc traffic is running. */ - *R_USB_IRQ_MASK_SET = - IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set) | - IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) | - IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) | - IO_STATE(R_USB_IRQ_MASK_SET, port_status, set) | - IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set); - - - if (request_irq(ETRAX_USB_HC_IRQ, etrax_usb_hc_interrupt_top_half, 0, - "ETRAX 100LX built-in USB (HC)", hc)) { - err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ); - etrax_usb_hc_cleanup(); - DBFEXIT; - return -1; - } - - if (request_irq(ETRAX_USB_RX_IRQ, etrax_usb_rx_interrupt, 0, - "ETRAX 100LX built-in USB (Rx)", hc)) { - err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ); - etrax_usb_hc_cleanup(); - DBFEXIT; - return -1; - } - - if (request_irq(ETRAX_USB_TX_IRQ, etrax_usb_tx_interrupt, 0, - "ETRAX 100LX built-in USB (Tx)", hc)) { - err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ); - etrax_usb_hc_cleanup(); - DBFEXIT; - return -1; - } - - /* R_USB_COMMAND: - USB commands in host mode. The fields in this register should all be - written to in one write. Do not read-modify-write one field at a time. A - write to this register will trigger events in the USB controller and an - incomplete command may lead to unpredictable results, and in worst case - even to a deadlock in the controller. - (Note however that the busy field is read-only, so no need to write to it.) */ - - /* Check the busy bit before writing to R_USB_COMMAND. */ - - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - /* Reset the USB interface. */ - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, nop) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, reset); - - /* Designer's Reference, p. 8 - 10 says we should Initate R_USB_FM_PSTART to 0x2A30 (10800), - to guarantee that control traffic gets 10% of the bandwidth, and periodic transfer may - allocate the rest (90%). This doesn't work though. Read on for a lenghty explanation. - - While there is a difference between rev. 2 and rev. 3 of the ETRAX 100LX regarding the NAK - behaviour, it doesn't solve this problem. What happens is that a control transfer will not - be interrupted in its data stage when PSTART happens (the point at which periodic traffic - is started). Thus, if PSTART is set to 10800 and its IN or OUT token is NAKed until just before - PSTART happens, it will continue the IN/OUT transfer as long as it's ACKed. After it's done, - there may be too little time left for an isochronous transfer, causing an epid attention - interrupt due to perror. The work-around for this is to let the control transfers run at the - end of the frame instead of at the beginning, and will be interrupted just fine if it doesn't - fit into the frame. However, since there will *always* be a control transfer at the beginning - of the frame, regardless of what we set PSTART to, that transfer might be a 64-byte transfer - which consumes up to 15% of the frame, leaving only 85% for periodic traffic. The solution to - this would be to 'dummy allocate' 5% of the frame with the usb_claim_bandwidth function to make - sure that the periodic transfers that are inserted will always fit in the frame. - - The idea was suggested that a control transfer could be split up into several 8 byte transfers, - so that it would be interrupted by PSTART, but since this can't be done for an IN transfer this - hasn't been implemented. - - The value 11960 is chosen to be just after the SOF token, with a couple of bit times extra - for possible bit stuffing. */ - - *R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 11960); - -#ifdef CONFIG_ETRAX_USB_HOST_PORT1 - *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no); -#endif - -#ifdef CONFIG_ETRAX_USB_HOST_PORT2 - *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no); -#endif - - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - /* Configure the USB interface as a host controller. */ - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, nop) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config); - - /* Note: Do not reset any ports here. Await the port status interrupts, to have a controlled - sequence of resetting the ports. If we reset both ports now, and there are devices - on both ports, we will get a bus error because both devices will answer the set address - request. */ - - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - /* Start processing of USB traffic. */ - *R_USB_COMMAND = - IO_STATE(R_USB_COMMAND, port_sel, nop) | - IO_STATE(R_USB_COMMAND, port_cmd, reset) | - IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run); - - while (*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)); - - usb_rh = usb_alloc_dev(NULL, hc->bus, 0); - hc->bus->root_hub = usb_rh; - usb_rh->state = USB_STATE_ADDRESS; - usb_rh->speed = USB_SPEED_FULL; - usb_rh->devnum = 1; - hc->bus->devnum_next = 2; - usb_rh->ep0.desc.wMaxPacketSize = __const_cpu_to_le16(64); - usb_get_device_descriptor(usb_rh, USB_DT_DEVICE_SIZE); - usb_new_device(usb_rh); - - DBFEXIT; - - return 0; -} - -static void etrax_usb_hc_cleanup(void) -{ - DBFENTER; - - free_irq(ETRAX_USB_HC_IRQ, NULL); - free_irq(ETRAX_USB_RX_IRQ, NULL); - free_irq(ETRAX_USB_TX_IRQ, NULL); - - usb_deregister_bus(etrax_usb_bus); - - /* FIXME: call kmem_cache_destroy here? */ - - DBFEXIT; -} - -module_init(etrax_usb_hc_init); -module_exit(etrax_usb_hc_cleanup); diff --git a/target/linux/etrax/files/drivers/usb/host/hc_crisv10.h b/target/linux/etrax/files/drivers/usb/host/hc_crisv10.h deleted file mode 100644 index 62f77111d4..0000000000 --- a/target/linux/etrax/files/drivers/usb/host/hc_crisv10.h +++ /dev/null @@ -1,289 +0,0 @@ -#ifndef __LINUX_ETRAX_USB_H -#define __LINUX_ETRAX_USB_H - -#include -#include - -typedef struct USB_IN_Desc { - volatile __u16 sw_len; - volatile __u16 command; - volatile unsigned long next; - volatile unsigned long buf; - volatile __u16 hw_len; - volatile __u16 status; -} USB_IN_Desc_t; - -typedef struct USB_SB_Desc { - volatile __u16 sw_len; - volatile __u16 command; - volatile unsigned long next; - volatile unsigned long buf; - __u32 dummy; -} USB_SB_Desc_t; - -typedef struct USB_EP_Desc { - volatile __u16 hw_len; - volatile __u16 command; - volatile unsigned long sub; - volatile unsigned long next; - __u32 dummy; -} USB_EP_Desc_t; - -struct virt_root_hub { - int devnum; - void *urb; - void *int_addr; - int send; - int interval; - int numports; - struct timer_list rh_int_timer; - volatile __u16 wPortChange_1; - volatile __u16 wPortChange_2; - volatile __u16 prev_wPortStatus_1; - volatile __u16 prev_wPortStatus_2; -}; - -struct etrax_usb_intr_traffic { - int sleeping; - int error; - struct wait_queue *wq; -}; - -typedef struct etrax_usb_hc { - struct usb_bus *bus; - struct virt_root_hub rh; - struct etrax_usb_intr_traffic intr; -} etrax_hc_t; - -typedef enum { - STARTED, - NOT_STARTED, - UNLINK, - TRANSFER_DONE, - WAITING_FOR_DESCR_INTR -} etrax_usb_urb_state_t; - - - -typedef struct etrax_usb_urb_priv { - /* The first_sb field is used for freeing all SB descriptors belonging - to an urb. The corresponding ep descriptor's sub pointer cannot be - used for this since the DMA advances the sub pointer as it processes - the sb list. */ - USB_SB_Desc_t *first_sb; - /* The last_sb field referes to the last SB descriptor that belongs to - this urb. This is important to know so we can free the SB descriptors - that ranges between first_sb and last_sb. */ - USB_SB_Desc_t *last_sb; - - /* The rx_offset field is used in ctrl and bulk traffic to keep track - of the offset in the urb's transfer_buffer where incoming data should be - copied to. */ - __u32 rx_offset; - - /* Counter used in isochronous transfers to keep track of the - number of packets received/transmitted. */ - __u32 isoc_packet_counter; - - /* This field is used to pass information about the urb's current state between - the various interrupt handlers (thus marked volatile). */ - volatile etrax_usb_urb_state_t urb_state; - - /* Connection between the submitted urb and ETRAX epid number */ - __u8 epid; - - /* The rx_data_list field is used for periodic traffic, to hold - received data for later processing in the the complete_urb functions, - where the data us copied to the urb's transfer_buffer. Basically, we - use this intermediate storage because we don't know when it's safe to - reuse the transfer_buffer (FIXME?). */ - struct list_head rx_data_list; -} etrax_urb_priv_t; - -/* This struct is for passing data from the top half to the bottom half. */ -typedef struct usb_interrupt_registers -{ - etrax_hc_t *hc; - __u32 r_usb_epid_attn; - __u8 r_usb_status; - __u16 r_usb_rh_port_status_1; - __u16 r_usb_rh_port_status_2; - __u32 r_usb_irq_mask_read; - __u32 r_usb_fm_number; - struct work_struct usb_bh; -} usb_interrupt_registers_t; - -/* This struct is for passing data from the isoc top half to the isoc bottom half. */ -typedef struct usb_isoc_complete_data -{ - struct urb *urb; - struct work_struct usb_bh; -} usb_isoc_complete_data_t; - -/* This struct holds data we get from the rx descriptors for DMA channel 9 - for periodic traffic (intr and isoc). */ -typedef struct rx_data -{ - void *data; - int length; - struct list_head list; -} rx_data_t; - -typedef struct urb_entry -{ - struct urb *urb; - struct list_head list; -} urb_entry_t; - -/* --------------------------------------------------------------------------- - Virtual Root HUB - ------------------------------------------------------------------------- */ -/* destination of request */ -#define RH_INTERFACE 0x01 -#define RH_ENDPOINT 0x02 -#define RH_OTHER 0x03 - -#define RH_CLASS 0x20 -#define RH_VENDOR 0x40 - -/* Requests: bRequest << 8 | bmRequestType */ -#define RH_GET_STATUS 0x0080 -#define RH_CLEAR_FEATURE 0x0100 -#define RH_SET_FEATURE 0x0300 -#define RH_SET_ADDRESS 0x0500 -#define RH_GET_DESCRIPTOR 0x0680 -#define RH_SET_DESCRIPTOR 0x0700 -#define RH_GET_CONFIGURATION 0x0880 -#define RH_SET_CONFIGURATION 0x0900 -#define RH_GET_STATE 0x0280 -#define RH_GET_INTERFACE 0x0A80 -#define RH_SET_INTERFACE 0x0B00 -#define RH_SYNC_FRAME 0x0C80 -/* Our Vendor Specific Request */ -#define RH_SET_EP 0x2000 - - -/* Hub port features */ -#define RH_PORT_CONNECTION 0x00 -#define RH_PORT_ENABLE 0x01 -#define RH_PORT_SUSPEND 0x02 -#define RH_PORT_OVER_CURRENT 0x03 -#define RH_PORT_RESET 0x04 -#define RH_PORT_POWER 0x08 -#define RH_PORT_LOW_SPEED 0x09 -#define RH_C_PORT_CONNECTION 0x10 -#define RH_C_PORT_ENABLE 0x11 -#define RH_C_PORT_SUSPEND 0x12 -#define RH_C_PORT_OVER_CURRENT 0x13 -#define RH_C_PORT_RESET 0x14 - -/* Hub features */ -#define RH_C_HUB_LOCAL_POWER 0x00 -#define RH_C_HUB_OVER_CURRENT 0x01 - -#define RH_DEVICE_REMOTE_WAKEUP 0x00 -#define RH_ENDPOINT_STALL 0x01 - -/* Our Vendor Specific feature */ -#define RH_REMOVE_EP 0x00 - - -#define RH_ACK 0x01 -#define RH_REQ_ERR -1 -#define RH_NACK 0x00 - -/* Field definitions for */ - -#define USB_IN_command__eol__BITNR 0 /* command macros */ -#define USB_IN_command__eol__WIDTH 1 -#define USB_IN_command__eol__no 0 -#define USB_IN_command__eol__yes 1 - -#define USB_IN_command__intr__BITNR 3 -#define USB_IN_command__intr__WIDTH 1 -#define USB_IN_command__intr__no 0 -#define USB_IN_command__intr__yes 1 - -#define USB_IN_status__eop__BITNR 1 /* status macros. */ -#define USB_IN_status__eop__WIDTH 1 -#define USB_IN_status__eop__no 0 -#define USB_IN_status__eop__yes 1 - -#define USB_IN_status__eot__BITNR 5 -#define USB_IN_status__eot__WIDTH 1 -#define USB_IN_status__eot__no 0 -#define USB_IN_status__eot__yes 1 - -#define USB_IN_status__error__BITNR 6 -#define USB_IN_status__error__WIDTH 1 -#define USB_IN_status__error__no 0 -#define USB_IN_status__error__yes 1 - -#define USB_IN_status__nodata__BITNR 7 -#define USB_IN_status__nodata__WIDTH 1 -#define USB_IN_status__nodata__no 0 -#define USB_IN_status__nodata__yes 1 - -#define USB_IN_status__epid__BITNR 8 -#define USB_IN_status__epid__WIDTH 5 - -#define USB_EP_command__eol__BITNR 0 -#define USB_EP_command__eol__WIDTH 1 -#define USB_EP_command__eol__no 0 -#define USB_EP_command__eol__yes 1 - -#define USB_EP_command__eof__BITNR 1 -#define USB_EP_command__eof__WIDTH 1 -#define USB_EP_command__eof__no 0 -#define USB_EP_command__eof__yes 1 - -#define USB_EP_command__intr__BITNR 3 -#define USB_EP_command__intr__WIDTH 1 -#define USB_EP_command__intr__no 0 -#define USB_EP_command__intr__yes 1 - -#define USB_EP_command__enable__BITNR 4 -#define USB_EP_command__enable__WIDTH 1 -#define USB_EP_command__enable__no 0 -#define USB_EP_command__enable__yes 1 - -#define USB_EP_command__hw_valid__BITNR 5 -#define USB_EP_command__hw_valid__WIDTH 1 -#define USB_EP_command__hw_valid__no 0 -#define USB_EP_command__hw_valid__yes 1 - -#define USB_EP_command__epid__BITNR 8 -#define USB_EP_command__epid__WIDTH 5 - -#define USB_SB_command__eol__BITNR 0 /* command macros. */ -#define USB_SB_command__eol__WIDTH 1 -#define USB_SB_command__eol__no 0 -#define USB_SB_command__eol__yes 1 - -#define USB_SB_command__eot__BITNR 1 -#define USB_SB_command__eot__WIDTH 1 -#define USB_SB_command__eot__no 0 -#define USB_SB_command__eot__yes 1 - -#define USB_SB_command__intr__BITNR 3 -#define USB_SB_command__intr__WIDTH 1 -#define USB_SB_command__intr__no 0 -#define USB_SB_command__intr__yes 1 - -#define USB_SB_command__tt__BITNR 4 -#define USB_SB_command__tt__WIDTH 2 -#define USB_SB_command__tt__zout 0 -#define USB_SB_command__tt__in 1 -#define USB_SB_command__tt__out 2 -#define USB_SB_command__tt__setup 3 - - -#define USB_SB_command__rem__BITNR 8 -#define USB_SB_command__rem__WIDTH 6 - -#define USB_SB_command__full__BITNR 6 -#define USB_SB_command__full__WIDTH 1 -#define USB_SB_command__full__no 0 -#define USB_SB_command__full__yes 1 - -#endif diff --git a/target/linux/etrax/image/Config.in b/target/linux/etrax/image/Config.in deleted file mode 100644 index 4a01de7ec2..0000000000 --- a/target/linux/etrax/image/Config.in +++ /dev/null @@ -1,5 +0,0 @@ -config AXIS_FIMAGE - bool "Build fimage" - depends TARGET_etrax - default y - diff --git a/target/linux/etrax/image/Makefile b/target/linux/etrax/image/Makefile deleted file mode 100644 index 9f716202c3..0000000000 --- a/target/linux/etrax/image/Makefile +++ /dev/null @@ -1,43 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/image.mk - -define Image/BuildKernel - cp $(KDIR)/vmlinuz $(BIN_DIR)/openwrt-$(BOARD)-zImage -endef - -define Image/Prepare - cp $(LINUX_DIR)/arch/cris/boot/zImage $(KDIR)/vmlinuz - $(MAKE) -C e100boot compile - $(MAKE) -C mkfimage compile - $(INSTALL_BIN) ./boot_linux $(BIN_DIR) -endef - -define Image/Build/generic - mkfimage $(KDIR)/vmlinuz $(KDIR)/vmlinuz.tmp - cat $(KDIR)/vmlinuz.tmp $(KDIR)/root.$(1) > $(KDIR)/fimage.$(1).tmp - dd if=$(KDIR)/fimage.$(1).tmp of=$(KDIR)/fimage.$(1) bs=$(2) conv=sync - cp $(KDIR)/fimage.$(1) $(BIN_DIR)/openwrt-$(BOARD)-$(1)-fimage -endef - -define Image/Build/jffs2-64k - $(call prepare_generic_jffs-64k,$(KDIR)/root.jff2-64k) - $(call Image/Build/generic,$(1),4194304) -endef - -define Image/Build/squashfs - $(call prepare_generic_squashfs,$(KDIR)/root.squashfs) - $(call Image/Build/generic,$(1),4194304) -endef - -define Image/Build - $(call Image/Build/$(1),$(1)) -endef - -$(eval $(call BuildImage)) diff --git a/target/linux/etrax/image/boot_linux b/target/linux/etrax/image/boot_linux deleted file mode 100755 index e7d5807f53..0000000000 --- a/target/linux/etrax/image/boot_linux +++ /dev/null @@ -1,512 +0,0 @@ -#!/usr/bin/perl -w - -#***************************************************************************** -#! -#! FILE NAME : boot_linux -#! -#! PARAMETERS : -b the name of the boot image to use -#! -d the interface to use, e.g., eth1 -#! (defaults is eth0) -#! -f save it in flash memory at address 0x10000 -#! -F save it in flash memory at address 0 -#! -h show some help -#! -i name of the image to use (default is fimage) -#! -o the offset in the flash where the flashing -#! starts -#! -O the offset in the image file where the -#! flashing starts from -#! -p print the resulting etrax100boot command -#! instead of executing it -#! -s how much to flash (default is the size of -#! the flash minus the offset specified using -#! -o or -f) -#! -S the size of the flash -#! -#! All sizes and offsets above can be specified as decimal -#! numbers, or as hexadecimal numbers by prefixing them with 0x. -#! It is also possible to use the suffixes k and M to specify -#! kilo (1024) or mega (1048576). -#! -#! DESCRIPTION: Extract the start of the image and any registers that should -#! be set from the kimage or fimage file, and then boot it. -#! -#! FUNCTIONS : convert_size -#! extract_hw_settings -#! get_dword -#! calculate_sdram_init -#! sdram_command -#! print_help -#! -#!---------------------------------------------------------------------------- -#! HISTORY -#! -#! $Log: boot_linux,v $ -#! Revision 1.16 2004/11/01 16:32:27 starvik -#! Corrected help text to avoid confusion -#! -#! Revision 1.15 2003/01/29 11:48:57 pkj -#! Calculate a flash size large enough for the given image if the -#! -S option is not specified. -#! -#! Revision 1.14 2002/11/18 14:40:09 pkj -#! Make use of the --loop option to etrax100boot when initialising -#! SDRAM memories. This requires a lot fewer options to be passed -#! to the boot loader. -#! -#! Revision 1.13 2002/08/15 16:29:02 pkj -#! * The -S option now accepts the size in bytes (just like the -s option). -#! For backwards compatibility it still assumes sizes of 16 and less to -#! be specified in MB. -#! * The suffixes k and M can now be used with all sizes and offsets to -#! specify them in kilo or mega. -#! -#! Revision 1.12 2002/08/15 15:27:34 pkj -#! Use $opts{'x'} instead of $opt_x. -#! -#! Revision 1.11 2002/07/04 17:06:39 pkj -#! * No longer specifies a bootfile by default (not needed any longer). -#! * Implemented option -b to specify a bootfile. -#! * Removed references to option -l (it was never implemented). -#! -#! Revision 1.10 2002/06/04 11:50:23 starvik -#! Check if mrs_data is specified in kernelconfig (necessary for MCM) -#! -#! Revision 1.9 2002/01/29 10:38:26 pkj -#! Change illegal to invalid. -#! -#! Revision 1.8 2001/09/13 12:32:10 pkj -#! * Added option -S to specify the size of the flash (in MB), as -s -#! is used to specify how much to flash nowadays. -#! * Made the default size of the flash depend on the size of the image -#! file. If it is bigger than 0x200100 then the flash is assumed to -#! be 4 MB, otherwise it is assumed to be 2 MB. -#! * Added verification of various options. -#! -#! Revision 1.7 2001/09/13 10:25:11 pkj -#! Minor clean-up. -#! -#! Revision 1.6 2001/06/29 10:05:16 pkj -#! Corrected check for SDRAM. -#! -#! Revision 1.5 2001/06/29 09:11:55 pkj -#! Synchronised boot_elinux and boot_linux. -#! -#!---------------------------------------------------------------------------- -#! (C) Copyright 2001, Axis Communications AB, LUND, SWEDEN -#!**************************************************************************** -# $Id: boot_linux,v 1.16 2004/11/01 16:32:27 starvik Exp $ - -#****************** INCLUDE FILES SECTION ************************************ - -use strict; - -use Getopt::Std; -use File::Basename; - -#****************** VARIABLE DECLARATION SECTION ***************************** - -use vars qw($my_name %opts); -use vars qw($text_start $cmd); -use vars qw($image_name $image_size); -use vars qw($offset $source_offset $flash_size $flashing_size); -use vars qw($sdram_timing_address $sdram_config_address); -use vars qw($sdram_precharge $sdram_nop $sdram_refresh $sdram_mrs); - -#****************** CONSTANT SECTION ***************************************** - -# Register addresses -$sdram_timing_address = "b0000008"; -$sdram_config_address = "b000000c"; - -# SDRAM commands -$sdram_precharge = 3; -$sdram_nop = 0; -$sdram_refresh = 2; -$sdram_mrs = 1; - -#****************** MAIN PROGRAM SECTION ************************************* - -# The name of this program. -$my_name = basename($0); - -# Get options -getopts('b:d:fFhi:o:O:ps:S:', \%opts); - -&print_help if ($opts{'h'}); - -# Name and existance of the image -$image_name = ($opts{'i'} ? $opts{'i'} : 'fimage'); -die "Could not find the image $image_name!\n" unless (-s $image_name); - -if ($opts{'f'} || $opts{'F'}) -{ - $image_size = -s $image_name; - - $offset = ($opts{'f'} ? 0x10000 : 0); - - $offset = &convert_size($opts{'o'}) if (defined($opts{'o'})); - - die("$my_name: Invalid destination offset\n") if ($offset !~ /^\d+$/); - - my $base_name = basename($image_name); - if ($base_name eq 'timage' || $base_name eq 'flash1.img') - { - $source_offset = 0; - } - else - { - $source_offset = $offset; - } - - $source_offset = &convert_size($opts{'O'}) if (defined($opts{'O'})); - - die("$my_name: Invalid source offset\n") if ($source_offset !~ /^\d+$/); - die("$my_name: Source offset > image size\n") if ($source_offset > $image_size); - - if (defined($opts{'S'})) - { - # Backwards compatibility to allow specifying the flash size in MB - # without using an M suffix - $opts{'S'} .= 'M' if ($opts{'S'} =~ /^\d+$/ && $opts{'S'} <= 16); - - $flash_size = &convert_size($opts{'S'}); - } - else - { - # Calculate a flash size large enough for the image without the checksum - # and HWID. - $flash_size = ($image_size - $source_offset + $offset) & 0xFFFF0000; - } - - die("$my_name: Invalid flash size\n") if ($flash_size !~ /^\d+$/); - die("$my_name: Destination offset > flash size\n") if ($offset > $flash_size); - if (defined($opts{'s'})) - { - $flashing_size = &convert_size($opts{'s'}); - } - else - { - $flashing_size = $flash_size - $offset; - } - - die("$my_name: Invalid size to flash\n") if ($flashing_size !~ /^\d+$/); - - if ($flashing_size > $flash_size - $offset) - { - $flashing_size = $flash_size - $offset; - printf("Warning: Flashing size limited to 0x%lx due to the offset (0x%lx) and flash size (0x%lx).\n", $flashing_size, $offset, $flash_size); - } - - if ($flashing_size > $image_size - $source_offset) - { - $flashing_size = $image_size - $source_offset; - printf("Warning: Flashing size limited to 0x%lx due to the offset (0x%lx) and image size (0x%lx).\n", $flashing_size, $source_offset, $image_size); - } -} - -# Create the command line to boot the image -if (system('./etrax100boot --help > /dev/null') == 0) -{ - $cmd = './etrax100boot'; -} -elsif (system('svinto_boot --help > /dev/null') == 0) -{ - $cmd = 'svinto_boot'; -} -else -{ - die("Cannot find e100boot program in your PATH!\n"); -} - -$cmd .= " --device $opts{'d'}" if ($opts{'d'}); - -$cmd .= &extract_hw_settings; - -$cmd .= " --bootfile $opts{'b'}" if ($opts{'b'}); -$cmd .= " --file $image_name $text_start"; - -if ($opts{'f'} || $opts{'F'}) -{ - $cmd .= sprintf(" --flash %lx %lx %lx --jump 0", - hex($text_start) + $source_offset, $offset, $flashing_size); -} -else -{ - $cmd .= " --jump $text_start"; -} - -if ($opts{'p'}) -{ - print "Command:\n$cmd\n"; -} -else -{ - system($cmd); -} - -exit 0; - -#****************** FUNCTION DEFINITION SECTION ****************************** - -#***************************************************************************** -## -## FUNCTION NAME: convert_size -## -##**************************************************************************** - -sub convert_size -{ - my($arg) = @_; - my $size; - - if ($arg =~ /^0x([\da-fA-F]+)([kM])?$/) - { - $size = hex($1); - } - elsif ($arg =~ /^(\d+)([kM])?$/) - { - $size = $1; - } - else - { - return -1; - } - - if (!defined($2)) - { - return $size; - } - elsif ($2 eq 'k') - { - return $size * 1024; - } - elsif ($2 eq 'M') - { - return $size * 1048576; - } -} - -#***************************************************************************** -## -## FUNCTION NAME: extract_hw_settings -## -##**************************************************************************** - -sub extract_hw_settings -{ - my $data; - my $dbg_port; - my $sdram_enabled; - my $return_value = ""; - my $sdram_config; - - # The hw information table has the following format - # - # "HW_PARAM_MAGIC" - # text_start (dword) - # serial debg port (dword) - # sdram enabled (dword) - # register address (dword) - # register value (dword) - # ... - # 0 - - open(FILE, "$image_name") || die("Could not open '$image_name'"); - - while () - { - if (m/HW_PARAM_MAGIC/g) - { - # Seek to first byte after magic - seek(FILE, -length($_) + pos($_), 1); - last; - } - } - - $text_start = &get_dword; - $dbg_port = &get_dword; - $sdram_enabled = int(&get_dword); - - while (1) - { - my $register = &get_dword; - my $value = &get_dword; - - last if ($register eq "00000000"); - - if ($sdram_enabled) - { - if ($register eq $sdram_config_address) - { - $sdram_config = $value; - } - elsif ($register eq $sdram_timing_address) - { - $return_value .= &calculate_sdram_init($value, $sdram_config); - next; - } - } - - $return_value .= " --setreg $register $value"; - } - - close(FILE); - - return $return_value; -} - -#***************************************************************************** -## -## FUNCTION NAME: get_dword -## -##**************************************************************************** - -sub get_dword -{ - my $data; - - read(FILE, $data, 4); - return unpack("H8", pack("V", unpack("N", $data))); -} - -#***************************************************************************** -## -## FUNCTION NAME: calculate_sdram_init -## -##**************************************************************************** - -sub calculate_sdram_init -{ - # Refer to ETRAX 100LX Designers Reference for a description of SDRAM - # initialization - my $sdram_init_val = hex($_[0]); - my $sdram_config_val = hex($_[1]); - my $bus_width = $sdram_config_val & 0x00800000; - my $speed; - my $cas_latency; - my $mrs_data; - my $temp; - my $return_value; - my $value; - - $mrs_data = ($sdram_init_val & 0x00ff0000) >> 16; - $sdram_init_val &= 0x8000ffff; # Make sure mrs data is 0 - $sdram_init_val |= 0x80000000; # Make sure sdram is enabled - $speed = $sdram_init_val & 0x1000; - $cas_latency = $sdram_init_val & 0x3; - if ($speed) # 100 MHz - { - $cas_latency += 2; - } - else # 50 MHz - { - $cas_latency += 1; - } - - # Calculate value of mrs_data - # CAS latency = 2 && bus_width = 32 => 0x40 - # CAS latency = 3 && bus_width = 32 => 0x60 - # CAS latency = 2 && bus_width = 16 => 0x20 - # CAS latency = 3 && bus_width = 16 => 0x30 - if ($mrs_data == 0) - { - if ($bus_width == 0) # 16 bits - { - $mrs_data = $cas_latency == 2 ? 0x20 : 0x30; - } - else # 32 bits - { - $mrs_data = $cas_latency == 2 ? 0x40 : 0x60; - } - } - - $temp = $sdram_init_val | 0x0000c000; # Disable refresh - $return_value .= &sdram_command($temp); - $return_value .= " --pause 20000"; - - $return_value .= &sdram_command($temp, $sdram_precharge); - $return_value .= &sdram_command($temp, $sdram_nop); - - $return_value .= " --setreg +0 7"; - $return_value .= " --label label1"; - $return_value .= &sdram_command($temp, $sdram_refresh); - $return_value .= &sdram_command($temp, $sdram_nop); - $return_value .= " --loop +0 label1"; - - $return_value .= &sdram_command($temp, $sdram_mrs, $mrs_data); - $return_value .= &sdram_command($temp, $sdram_nop); - - $return_value .= &sdram_command($sdram_init_val); - - return $return_value; -} - -#***************************************************************************** -## -## FUNCTION NAME: sdram_command -## -##**************************************************************************** - -sub sdram_command -{ - my($temp, $value, $mrs_data) = @_; - - $value ||= 0; - if ($value == $sdram_mrs) - { - $value = sprintf("%lx", $temp | ($value << 9) | ($mrs_data << 16)); - } - else - { - $value = sprintf("%lx", $temp | ($value << 9)); - } - - return " --setreg $sdram_timing_address $value"; -} - -#***************************************************************************** -## -## FUNCTION NAME: print_help -## -##**************************************************************************** - -sub print_help -{ - print "\nAXIS $my_name, ", '$Revision: 1.16 $ $Date: 2004/11/01 16:32:27 $ ', "\n"; - die < : The boot image to use. - -d : The network interface to use, default is eth0. - -f : Save the image in the flash memory starting at - address 0x10000. - -F : Save the image in the flash memory starting at - address 0. - -h : Print this help text. - -i : The path and name of the image to use, default - is fimage. - -o : The offset in the flash where the flashing starts. - -O : The offset in the image file where the flashing - starts from. - -p : Print the resulting etrax100boot command instead - of executing it. - -s : How much to flash (default is the size of the - flash minus the offset specified using -o or -f). - -S : The size of the flash. - - All sizes and offsets above can be specified as decimal numbers, or as - hexadecimal numbers by prefixing them with 0x. It is also possible to use - the suffixes k and M to specify kilo (1024) or mega (1048576). - -EOT -} - -#****************** END OF FILE boot_linux *********************************** diff --git a/target/linux/etrax/image/e100boot/Makefile b/target/linux/etrax/image/e100boot/Makefile deleted file mode 100644 index ebc9ef3d41..0000000000 --- a/target/linux/etrax/image/e100boot/Makefile +++ /dev/null @@ -1,34 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -# $Id$ - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=e100boot -PKG_VERSION:=0.1 -PKG_RELEASE:=1 - -PKG_SOURCE:=e100boot.tar.bz2 -PKG_SOURCE_URL:=http://www.acmesystems.it/download/owrt -PKG_MD5SUM:= - -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME) - -CRLF_WORKAROUND=1 - -include $(INCLUDE_DIR)/package.mk - -define Build/Compile - make -C $(PKG_BUILD_DIR) STRIP=true -endef - -define Build/InstallDev - $(INSTALL_BIN) $(PKG_BUILD_DIR)/sbl/e100boot $(BIN_DIR)/etrax100boot -endef - -$(eval $(call Build/DefaultTargets)) diff --git a/target/linux/etrax/image/mkfimage/Makefile b/target/linux/etrax/image/mkfimage/Makefile deleted file mode 100644 index f97d098d9b..0000000000 --- a/target/linux/etrax/image/mkfimage/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# -# $Id$ - -include $(TOPDIR)/rules.mk -include $(INCLUDE_DIR)/kernel.mk - -PKG_NAME:=mkfimage -PKG_VERSION:=0.1 -PKG_RELEASE:=1 - -PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/$(PKG_NAME) - -include $(INCLUDE_DIR)/package.mk - -define Build/Compile - mkdir -p $(PKG_BUILD_DIR) - cp -r ./src/* $(PKG_BUILD_DIR) - make -C $(PKG_BUILD_DIR) -endef - -define Build/InstallDev - $(INSTALL_BIN) $(PKG_BUILD_DIR)/mkfimage $(STAGING_DIR_HOST)/bin/mkfimage -endef - -$(eval $(call Build/DefaultTargets)) diff --git a/target/linux/etrax/image/mkfimage/src/Makefile b/target/linux/etrax/image/mkfimage/src/Makefile deleted file mode 100644 index 3e0b79c661..0000000000 --- a/target/linux/etrax/image/mkfimage/src/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -all: mkfimage - gcc mkfimage.c -o mkfimage - diff --git a/target/linux/etrax/image/mkfimage/src/mkfimage.c b/target/linux/etrax/image/mkfimage/src/mkfimage.c deleted file mode 100644 index 6904170cfe..0000000000 --- a/target/linux/etrax/image/mkfimage/src/mkfimage.c +++ /dev/null @@ -1,72 +0,0 @@ -#include -#include -#include -#include -#include -#include - -int main(int argc, char **argv){ - unsigned char *buffer = malloc(64 * 1024); - struct stat s; - unsigned int size_vmlinux = 0, real_size_vmlinux = 0; - const unsigned char *magic_str = "ACME_PART_MAGIC"; - unsigned int loop; - unsigned char *magic; - - if(argc != 3){ - printf("%s in out\n", argv[0]); - return 1; - } - - printf("Generating image\n"); - - FILE *vmlinux = fopen(argv[1], "r"); - FILE *vmlinux_out = fopen(argv[2], "w"); - if((!vmlinux) || (!vmlinux_out)){ - printf("Error opening a file\n"); - return 1; - } - - stat(argv[1], &s); - size_vmlinux = s.st_size; - real_size_vmlinux = (size_vmlinux & 0xffff0000) + 0x10000; - - printf("vmlinux = 0x%.08X / 0x%.08X\n", size_vmlinux, real_size_vmlinux); - - unsigned int t = fread(buffer, 1, 64 * 1024, vmlinux); - for(loop = 0; loop < (64 * 1024) - sizeof(magic_str); loop++){ - if(buffer[loop] == magic_str[0]){ - if((magic = strstr(&buffer[loop], magic_str))){ - printf("Magic at 0x%.08X %p %p\n", magic - buffer, magic, buffer); - printf("Found Magic %X%X%X%X\n", - buffer[loop + strlen(magic_str)], - buffer[loop + strlen(magic_str) + 2], - buffer[loop + strlen(magic_str) + 1], - buffer[loop + strlen(magic_str) + 3]); - - buffer[loop + strlen(magic_str)] = real_size_vmlinux >> 24; - buffer[loop + strlen(magic_str) + 2] = (real_size_vmlinux >> 16) & 0xff; - buffer[loop + strlen(magic_str) + 1] = (real_size_vmlinux >> 8) & 0xff; - buffer[loop + strlen(magic_str) + 3] = (real_size_vmlinux) & 0xff; - - printf("Replaced with %.02X%.02X%.02X%.02X\n", - buffer[loop + strlen(magic_str)], - buffer[loop + strlen(magic_str) + 2], - buffer[loop + strlen(magic_str) + 1], - buffer[loop + strlen(magic_str) + 3]); - - } - } - } - - fwrite(buffer, 1, 64 * 1024, vmlinux_out); - real_size_vmlinux -= 64 * 1024; - do { - real_size_vmlinux -= 64 * 1024; - memset(buffer, 0, 64 * 1024); - fread(buffer, 1, 64 * 1024, vmlinux); - fwrite(buffer, 1, 64 * 1024, vmlinux_out); - } while (real_size_vmlinux); - - return 0; -} diff --git a/target/linux/etrax/patches/100-compile_fixes.patch b/target/linux/etrax/patches/100-compile_fixes.patch deleted file mode 100644 index ea6d08e86f..0000000000 --- a/target/linux/etrax/patches/100-compile_fixes.patch +++ /dev/null @@ -1,302 +0,0 @@ ---- a/arch/cris/Makefile -+++ b/arch/cris/Makefile -@@ -33,7 +33,7 @@ - - LD = $(CROSS_COMPILE)ld -mcrislinux - --OBJCOPYFLAGS := -O binary -R .note -R .comment -S -+OBJCOPYFLAGS := -O binary -R .bss -R .note -R .note.gnu.build-id -R .comment -S - - CPPFLAGS_vmlinux.lds = -DDRAM_VIRTUAL_BASE=0x$(CONFIG_ETRAX_DRAM_VIRTUAL_BASE) - ---- a/arch/cris/arch-v10/boot/Makefile -+++ b/arch/cris/arch-v10/boot/Makefile -@@ -2,9 +2,6 @@ - # arch/cris/arch-v10/boot/Makefile - # - --OBJCOPY = objcopy-cris --OBJCOPYFLAGS = -O binary --remove-section=.bss -- - subdir- := compressed rescue - targets := Image - -@@ -14,7 +11,6 @@ - - $(obj)/compressed/vmlinux: $(obj)/Image FORCE - $(Q)$(MAKE) $(build)=$(obj)/compressed $@ -- $(Q)$(MAKE) $(build)=$(obj)/rescue $(obj)/rescue/rescue.bin - - $(obj)/zImage: $(obj)/compressed/vmlinux - @cp $< $@ ---- a/arch/cris/arch-v10/boot/compressed/Makefile -+++ b/arch/cris/arch-v10/boot/compressed/Makefile -@@ -2,13 +2,9 @@ - # arch/cris/arch-v10/boot/compressed/Makefile - # - --CC = gcc-cris -melf $(LINUXINCLUDE) - ccflags-y += -O2 --LD = ld-cris - ldflags-y += -T $(obj)/decompress.ld - OBJECTS = $(obj)/head.o $(obj)/misc.o --OBJCOPY = objcopy-cris --OBJCOPYFLAGS = -O binary --remove-section=.bss - - quiet_cmd_image = BUILD $@ - cmd_image = cat $(obj)/decompress.bin $(obj)/piggy.gz > $@ -@@ -22,10 +18,10 @@ - $(call if_changed,objcopy) - - $(obj)/head.o: $(obj)/head.S .config -- @$(CC) -D__ASSEMBLY__ -traditional -c $< -o $@ -+ @$(CC) -Iinclude -D__ASSEMBLY__ -traditional -Wa,--em=criself -c $< -o $@ - - $(obj)/misc.o: $(obj)/misc.c .config -- @$(CC) -D__KERNEL__ -c $< -o $@ -+ @$(CC) -Iinclude -D__KERNEL__ -Wa,--em=criself -c $< -o $@ - - $(obj)/vmlinux: $(obj)/piggy.gz $(obj)/decompress.bin FORCE - $(call if_changed,image) ---- a/arch/cris/arch-v10/boot/compressed/decompress.ld -+++ b/arch/cris/arch-v10/boot/compressed/decompress.ld -@@ -1,4 +1,4 @@ --OUTPUT_FORMAT(elf32-us-cris) -+OUTPUT_FORMAT(elf32-cris) - - MEMORY - { ---- a/arch/cris/arch-v10/boot/compressed/head.S -+++ b/arch/cris/arch-v10/boot/compressed/head.S -@@ -10,13 +10,14 @@ - - #define ASSEMBLER_MACROS_ONLY - #include -+#include - - #define RAM_INIT_MAGIC 0x56902387 - #define COMMAND_LINE_MAGIC 0x87109563 - - ;; Exported symbols - -- .globl _input_data -+ .globl input_data - - - .text -@@ -26,7 +27,7 @@ - - ;; We need to initialze DRAM registers before we start using the DRAM - -- cmp.d RAM_INIT_MAGIC, r8 ; Already initialized? -+ cmp.d RAM_INIT_MAGIC, $r8 ; Already initialized? - beq dram_init_finished - nop - -@@ -36,91 +37,91 @@ - - ;; Initiate the PA and PB ports - -- move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, r0 -- move.b r0, [R_PORT_PA_DATA] -+ move.b CONFIG_ETRAX_DEF_R_PORT_PA_DATA, $r0 -+ move.b $r0, [R_PORT_PA_DATA] - -- move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, r0 -- move.b r0, [R_PORT_PA_DIR] -+ move.b CONFIG_ETRAX_DEF_R_PORT_PA_DIR, $r0 -+ move.b $r0, [R_PORT_PA_DIR] - -- move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, r0 -- move.b r0, [R_PORT_PB_DATA] -+ move.b CONFIG_ETRAX_DEF_R_PORT_PB_DATA, $r0 -+ move.b $r0, [R_PORT_PB_DATA] - -- move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, r0 -- move.b r0, [R_PORT_PB_DIR] -+ move.b CONFIG_ETRAX_DEF_R_PORT_PB_DIR, $r0 -+ move.b $r0, [R_PORT_PB_DIR] - - ;; Setup the stack to a suitably high address. - ;; We assume 8 MB is the minimum DRAM in an eLinux - ;; product and put the sp at the top for now. - -- move.d 0x40800000, sp -+ move.d 0x40800000, $sp - - ;; Figure out where the compressed piggyback image is - ;; in the flash (since we wont try to copy it to DRAM - ;; before unpacking). It is at _edata, but in flash. - ;; Use (_edata - basse) as offset to the current PC. - --basse: move.d pc, r5 -- and.d 0x7fffffff, r5 ; strip any non-cache bit -- subq 2, r5 ; compensate for the move.d pc instr -- move.d r5, r0 ; save for later - flash address of 'basse' -- add.d _edata, r5 -- sub.d basse, r5 ; r5 = flash address of '_edata' -+basse: move.d $pc, $r5 -+ and.d 0x7fffffff, $r5 ; strip any non-cache bit -+ subq 2, $r5 ; compensate for the move.d pc instr -+ move.d $r5, $r0 ; save for later - flash address of 'basse' -+ add.d _edata, $r5 -+ sub.d basse, $r5 ; r5 = flash address of '_edata' - - ;; Copy text+data to DRAM - -- move.d basse, r1 ; destination -- move.d _edata, r2 ; end destination --1: move.w [r0+], r3 -- move.w r3, [r1+] -- cmp.d r2, r1 -+ move.d basse, $r1 ; destination -+ move.d _edata, $r2 ; end destination -+1: move.w [$r0+], $r3 -+ move.w $r3, [$r1+] -+ cmp.d $r2, $r1 - bcs 1b - nop - -- move.d r5, [_input_data] ; for the decompressor -+ move.d $r5, [input_data] ; for the decompressor - - - ;; Clear the decompressors BSS (between _edata and _end) - -- moveq 0, r0 -- move.d _edata, r1 -- move.d _end, r2 --1: move.w r0, [r1+] -- cmp.d r2, r1 -+ moveq 0, $r0 -+ move.d _edata, $r1 -+ move.d _end, $r2 -+1: move.w $r0, [$r1+] -+ cmp.d $r2, $r1 - bcs 1b - nop - - ;; Save command line magic and address. -- move.d _cmd_line_magic, $r12 -+ move.d cmd_line_magic, $r12 - move.d $r10, [$r12] -- move.d _cmd_line_addr, $r12 -+ move.d cmd_line_addr, $r12 - move.d $r11, [$r12] - - ;; Do the decompression and save compressed size in _inptr - -- jsr _decompress_kernel -+ jsr decompress_kernel - - ;; Put start address of root partition in r9 so the kernel can use it - ;; when mounting from flash - -- move.d [_input_data], r9 ; flash address of compressed kernel -- add.d [_inptr], r9 ; size of compressed kernel -+ move.d [input_data], $r9 ; flash address of compressed kernel -+ add.d [inptr], $r9 ; size of compressed kernel - - ;; Restore command line magic and address. -- move.d _cmd_line_magic, $r10 -+ move.d cmd_line_magic, $r10 - move.d [$r10], $r10 -- move.d _cmd_line_addr, $r11 -+ move.d cmd_line_addr, $r11 - move.d [$r11], $r11 - - ;; Enter the decompressed kernel -- move.d RAM_INIT_MAGIC, r8 ; Tell kernel that DRAM is initialized -+ move.d RAM_INIT_MAGIC, $r8 ; Tell kernel that DRAM is initialized - jump 0x40004000 ; kernel is linked to this address - - .data - --_input_data: -+input_data: - .dword 0 ; used by the decompressor --_cmd_line_magic: -+cmd_line_magic: - .dword 0 --_cmd_line_addr: -+cmd_line_addr: - .dword 0 - #include "../../lib/hw_settings.S" ---- a/arch/cris/arch-v10/boot/compressed/misc.c -+++ b/arch/cris/arch-v10/boot/compressed/misc.c -@@ -5,7 +5,7 @@ - * adapted for Linux. - * - * malloc by Hannu Savolainen 1993 and Matthias Urlichs 1994 -- * puts by Nick Holloway 1993, better puts by Martin Mares 1995 -+ * putstr by Nick Holloway 1993, better putstr by Martin Mares 1995 - * adaptation for Linux/CRIS Axis Communications AB, 1999 - * - */ -@@ -99,12 +99,12 @@ - static void gzip_mark(void **); - static void gzip_release(void **); - --static void puts(const char *); -+static void putstr(const char *); - - /* the "heap" is put directly after the BSS ends, at end */ - --extern int end; --static long free_mem_ptr = (long)&end; -+extern int _end; -+static long free_mem_ptr = (long)&_end; - - #include "../../../../../lib/inflate.c" - -@@ -139,7 +139,7 @@ - /* decompressor info and error messages to serial console */ - - static void --puts(const char *s) -+putstr(const char *s) - { - #ifndef CONFIG_ETRAX_DEBUG_PORT_NULL - while(*s) { -@@ -209,9 +209,9 @@ - static void - error(char *x) - { -- puts("\n\n"); -- puts(x); -- puts("\n\n -- System halted\n"); -+ putstr("\n\n"); -+ putstr(x); -+ putstr("\n\n -- System halted\n"); - - while(1); /* Halt */ - } -@@ -257,14 +257,7 @@ - - makecrc(); - -- __asm__ volatile ("move vr,%0" : "=rm" (revision)); -- if (revision < 10) -- { -- puts("You need an ETRAX 100LX to run linux 2.6\n"); -- while(1); -- } -- -- puts("Uncompressing Linux...\n"); -+ putstr("Uncompressing Linux...\n"); - gunzip(); -- puts("Done. Now booting the kernel.\n"); -+ putstr("Done. Now booting the kernel.\n"); - } ---- a/arch/cris/arch-v10/mm/init.c -+++ b/arch/cris/arch-v10/mm/init.c -@@ -184,6 +184,9 @@ - - free_area_init_node(0, &contig_page_data, zones_size, PAGE_OFFSET >> PAGE_SHIFT, 0); - } -+void free_initrd_mem(unsigned long start, unsigned long end) -+{ -+} - - /* Initialize remaps of some I/O-ports. It is important that this - * is called before any driver is initialized. diff --git a/target/linux/etrax/patches/101-cris-eth-driver.patch b/target/linux/etrax/patches/101-cris-eth-driver.patch deleted file mode 100644 index f73b379ddc..0000000000 --- a/target/linux/etrax/patches/101-cris-eth-driver.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/drivers/net/cris/eth_v10.c -+++ b/drivers/net/cris/eth_v10.c -@@ -1707,7 +1707,7 @@ - static void - e100_netpoll(struct net_device* netdev) - { -- e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev, NULL); -+ e100rxtx_interrupt(NETWORK_DMA_TX_IRQ_NBR, netdev); - } - #endif - diff --git a/target/linux/etrax/patches/102-missing_arch_include.patch b/target/linux/etrax/patches/102-missing_arch_include.patch deleted file mode 100644 index 8955712b26..0000000000 --- a/target/linux/etrax/patches/102-missing_arch_include.patch +++ /dev/null @@ -1,11 +0,0 @@ ---- a/include/asm-cris/Kbuild -+++ b/include/asm-cris/Kbuild -@@ -1,7 +1,6 @@ - include include/asm-generic/Kbuild.asm - --header-$(CONFIG_ETRAX_ARCH_V10) += arch-v10/ --header-$(CONFIG_ETRAX_ARCH_V32) += arch-v32/ -+header-y += arch-v10/ arch-v32/ - - header-y += ethernet.h - header-y += rtc.h diff --git a/target/linux/etrax/patches/200-samsung_flash.patch b/target/linux/etrax/patches/200-samsung_flash.patch deleted file mode 100644 index ac4ac67818..0000000000 --- a/target/linux/etrax/patches/200-samsung_flash.patch +++ /dev/null @@ -1,13 +0,0 @@ ---- a/drivers/mtd/chips/cfi_cmdset_0002.c -+++ b/drivers/mtd/chips/cfi_cmdset_0002.c -@@ -297,8 +297,8 @@ - return NULL; - } - -- if (extp->MajorVersion != '1' || -- (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { -+ if (extp->MajorVersion < '0' || extp->MajorVersion > '3' || -+ (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { - if (cfi->mfr == MANUFACTURER_SAMSUNG && - (extp->MajorVersion == '3' && extp->MinorVersion == '3')) { - printk(KERN_NOTICE " Newer Samsung flash detected, " diff --git a/target/linux/etrax/patches/201-flashsize.patch b/target/linux/etrax/patches/201-flashsize.patch deleted file mode 100644 index 859bb46fdc..0000000000 --- a/target/linux/etrax/patches/201-flashsize.patch +++ /dev/null @@ -1,88 +0,0 @@ ---- a/arch/cris/arch-v10/lib/hw_settings.S -+++ b/arch/cris/arch-v10/lib/hw_settings.S -@@ -60,3 +60,5 @@ - .dword R_PORT_PB_SET - .dword PB_SET_VALUE - .dword 0 ; No more register values -+ .ascii "ACME_PART_MAGIC" -+ .dword 0xdeadc0de ---- a/arch/cris/arch-v10/drivers/axisflashmap.c -+++ b/arch/cris/arch-v10/drivers/axisflashmap.c -@@ -113,7 +113,7 @@ - - /* If no partition-table was found, we use this default-set. */ - #define MAX_PARTITIONS 7 --#define NUM_DEFAULT_PARTITIONS 3 -+#define NUM_DEFAULT_PARTITIONS 2 - - /* - * Default flash size is 2MB. CONFIG_ETRAX_PTABLE_SECTOR is most likely the -@@ -122,19 +122,14 @@ - */ - static struct mtd_partition axis_default_partitions[NUM_DEFAULT_PARTITIONS] = { - { -- .name = "boot firmware", -- .size = CONFIG_ETRAX_PTABLE_SECTOR, -- .offset = 0 -- }, -- { - .name = "kernel", -- .size = 0x200000 - (6 * CONFIG_ETRAX_PTABLE_SECTOR), -- .offset = CONFIG_ETRAX_PTABLE_SECTOR -+ .size = 0x00, -+ .offset = 0 - }, - { -- .name = "filesystem", -- .size = 5 * CONFIG_ETRAX_PTABLE_SECTOR, -- .offset = 0x200000 - (5 * CONFIG_ETRAX_PTABLE_SECTOR) -+ .name = "rootfs", -+ .size = 0x200000 , -+ .offset = 0x200000 - } - }; - -@@ -281,6 +276,11 @@ - struct partitiontable_entry *ptable; - int use_default_ptable = 1; /* Until proven otherwise. */ - const char pmsg[] = " /dev/flash%d at 0x%08x, size 0x%08x\n"; -+ unsigned int kernel_part_size = 0; -+ unsigned char *flash_mem = (unsigned char*)(FLASH_CACHED_ADDR); -+ unsigned int flash_scan_count = 0; -+ const char *part_magic = "ACME_PART_MAGIC"; -+ unsigned int magic_len = strlen(part_magic); - - if (!(mymtd = flash_probe())) { - /* There's no reason to use this module if no flash chip can -@@ -292,6 +292,31 @@ - mymtd->name, mymtd->size); - axisflash_mtd = mymtd; - } -+ /* scan flash to findout where out partition starts */ -+ -+ printk(KERN_INFO "Scanning flash for end of kernel magic\n"); -+ for(flash_scan_count = 0; flash_scan_count < 100000; flash_scan_count++){ -+ if(strncmp(&flash_mem[flash_scan_count], part_magic, magic_len - 1) == 0) -+ { -+ kernel_part_size = flash_mem[flash_scan_count + magic_len ]; -+ kernel_part_size <<= 8; -+ kernel_part_size += flash_mem[flash_scan_count + magic_len + 2]; -+ kernel_part_size <<= 8; -+ kernel_part_size += flash_mem[flash_scan_count + magic_len + 1]; -+ kernel_part_size <<= 8; -+ kernel_part_size += flash_mem[flash_scan_count + magic_len + 3]; -+ printk(KERN_INFO "Kernel ends at 0x%.08X\n", kernel_part_size); -+ flash_scan_count = 1100000; -+ } -+ } -+ -+ -+ if(kernel_part_size){ -+ kernel_part_size = (kernel_part_size & 0xffff0000); -+ axis_default_partitions[0].size = kernel_part_size; -+ axis_default_partitions[1].size = mymtd->size - axis_default_partitions[0].size; -+ axis_default_partitions[1].offset = axis_default_partitions[0].size; -+ } - - if (mymtd) { - mymtd->owner = THIS_MODULE; diff --git a/target/linux/etrax/patches/300-sysfs.patch b/target/linux/etrax/patches/300-sysfs.patch deleted file mode 100644 index 3b0378421a..0000000000 --- a/target/linux/etrax/patches/300-sysfs.patch +++ /dev/null @@ -1,43 +0,0 @@ ---- a/drivers/serial/crisv10.c -+++ b/drivers/serial/crisv10.c -@@ -27,6 +27,7 @@ - #include - #include - #include -+#include - - #include - #include -@@ -4384,6 +4385,7 @@ - .tiocmset = rs_tiocmset - }; - -+static struct class *rs_class; - static int __init - rs_init(void) - { -@@ -4518,6 +4520,24 @@ - #endif - #endif /* CONFIG_SVINTO_SIM */ - -+ rs_class = class_create(THIS_MODULE, "rs_tty"); -+#ifdef CONFIG_ETRAX_SERIAL_PORT0 -+ class_device_create(rs_class, NULL, -+ MKDEV(TTY_MAJOR, 64), NULL, "ttyS0"); -+#endif -+#ifdef CONFIG_ETRAX_SERIAL_PORT1 -+ class_device_create(rs_class, NULL, -+ MKDEV(TTY_MAJOR, 65), NULL, "ttyS1"); -+#endif -+#ifdef CONFIG_ETRAX_SERIAL_PORT2 -+ class_device_create(rs_class, NULL, -+ MKDEV(TTY_MAJOR, 66), NULL, "ttyS2"); -+#endif -+#ifdef CONFIG_ETRAX_SERIAL_PORT3 -+ class_device_create(rs_class, NULL, -+ MKDEV(TTY_MAJOR, 67), NULL, "ttyS3"); -+#endif -+ - return 0; - } - diff --git a/target/linux/etrax/patches/301-usb_support.patch b/target/linux/etrax/patches/301-usb_support.patch deleted file mode 100644 index 5b443d42fa..0000000000 --- a/target/linux/etrax/patches/301-usb_support.patch +++ /dev/null @@ -1,5301 +0,0 @@ ---- 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_ETRAX_USB_HOST) += host/ - - obj-$(CONFIG_USB_ACM) += class/ - obj-$(CONFIG_USB_PRINTER) += class/ ---- a/drivers/usb/host/Makefile -+++ b/drivers/usb/host/Makefile -@@ -17,3 +17,5 @@ - obj-$(CONFIG_USB_U132_HCD) += u132-hcd.o - obj-$(CONFIG_USB_R8A66597_HCD) += r8a66597-hcd.o - -+#obj-$(CONFIG_USB_CARNEOL) += hc-crisv10.o -+obj-$(CONFIG_ETRAX_USB_HOST) += hc-crisv10.o ---- /dev/null -+++ b/drivers/usb/host/hc-cris-dbg.h -@@ -0,0 +1,143 @@ -+ -+/* macros for debug output */ -+ -+#define hcd_dbg(hcd, fmt, args...) \ -+ dev_info(hcd->self.controller, fmt, ## args) -+#define hcd_err(hcd, fmt, args...) \ -+ dev_err(hcd->self.controller, fmt, ## args) -+#define hcd_info(hcd, fmt, args...) \ -+ dev_info(hcd->self.controller, fmt, ## args) -+#define hcd_warn(hcd, fmt, args...) \ -+ dev_warn(hcd->self.controller, fmt, ## args) -+ -+/* -+#define devdrv_dbg(fmt, args...) \ -+ printk(KERN_INFO "usb_devdrv dbg: ");printk(fmt, ## args) -+*/ -+#define devdrv_dbg(fmt, args...) {} -+ -+#define devdrv_err(fmt, args...) \ -+ printk(KERN_ERR "usb_devdrv error: ");printk(fmt, ## args) -+#define devdrv_info(fmt, args...) \ -+ printk(KERN_INFO "usb_devdrv: ");printk(fmt, ## args) -+ -+#define irq_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_irq dbg: ");printk(fmt, ## args) -+#define irq_err(fmt, args...) \ -+ printk(KERN_ERR "crisv10_irq error: ");printk(fmt, ## args) -+#define irq_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_irq warn: ");printk(fmt, ## args) -+#define irq_info(fmt, args...) \ -+ printk(KERN_INFO "crisv10_hcd: ");printk(fmt, ## args) -+ -+/* -+#define rh_dbg(fmt, args...) \ -+ printk(KERN_DEBUG "crisv10_rh dbg: ");printk(fmt, ## args) -+*/ -+#define rh_dbg(fmt, args...) {} -+ -+#define rh_err(fmt, args...) \ -+ printk(KERN_ERR "crisv10_rh error: ");printk(fmt, ## args) -+#define rh_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_rh warning: ");printk(fmt, ## args) -+#define rh_info(fmt, args...) \ -+ printk(KERN_INFO "crisv10_rh: ");printk(fmt, ## args) -+ -+/* -+#define tc_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_tc dbg: ");printk(fmt, ## args) -+*/ -+#define tc_dbg(fmt, args...) {while(0){}} -+ -+#define tc_err(fmt, args...) \ -+ printk(KERN_ERR "crisv10_tc error: ");printk(fmt, ## args) -+/* -+#define tc_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_tc warning: ");printk(fmt, ## args) -+*/ -+#define tc_warn(fmt, args...) {while(0){}} -+ -+#define tc_info(fmt, args...) \ -+ printk(KERN_INFO "crisv10_tc: ");printk(fmt, ## args) -+ -+ -+/* Debug print-outs for various traffic types */ -+ -+#define intr_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_intr warning: ");printk(fmt, ## args) -+ -+#define intr_dbg(fmt, args...) \ -+ printk(KERN_DEBUG "crisv10_intr dbg: ");printk(fmt, ## args) -+/* -+#define intr_dbg(fmt, args...) {while(0){}} -+*/ -+ -+ -+#define isoc_err(fmt, args...) \ -+ printk(KERN_ERR "crisv10_isoc error: ");printk(fmt, ## args) -+/* -+#define isoc_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_isoc warning: ");printk(fmt, ## args) -+*/ -+#define isoc_warn(fmt, args...) {while(0){}} -+ -+/* -+#define isoc_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_isoc dbg: ");printk(fmt, ## args) -+*/ -+#define isoc_dbg(fmt, args...) {while(0){}} -+ -+/* -+#define timer_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_timer warning: ");printk(fmt, ## args) -+*/ -+#define timer_warn(fmt, args...) {while(0){}} -+ -+/* -+#define timer_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_timer dbg: ");printk(fmt, ## args) -+*/ -+#define timer_dbg(fmt, args...) {while(0){}} -+ -+ -+/* Debug printouts for events related to late finishing of URBs */ -+ -+#define late_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_late dbg: ");printk(fmt, ## args) -+/* -+#define late_dbg(fmt, args...) {while(0){}} -+*/ -+ -+#define late_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_late warning: ");printk(fmt, ## args) -+/* -+#define errno_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_errno dbg: ");printk(fmt, ## args) -+*/ -+#define errno_dbg(fmt, args...) {while(0){}} -+ -+ -+#define dma_dbg(fmt, args...) \ -+ printk(KERN_INFO "crisv10_dma dbg: ");printk(fmt, ## args) -+#define dma_err(fmt, args...) \ -+ printk(KERN_ERR "crisv10_dma error: ");printk(fmt, ## args) -+#define dma_warn(fmt, args...) \ -+ printk(KERN_INFO "crisv10_dma warning: ");printk(fmt, ## args) -+#define dma_info(fmt, args...) \ -+ printk(KERN_INFO "crisv10_dma: ");printk(fmt, ## args) -+ -+ -+ -+#define str_dir(pipe) \ -+ (usb_pipeout(pipe) ? "out" : "in") -+#define str_type(pipe) \ -+ ({ \ -+ char *s = "?"; \ -+ switch (usb_pipetype(pipe)) { \ -+ case PIPE_ISOCHRONOUS: s = "iso"; break; \ -+ case PIPE_INTERRUPT: s = "intr"; break; \ -+ case PIPE_CONTROL: s = "ctrl"; break; \ -+ case PIPE_BULK: s = "bulk"; break; \ -+ }; \ -+ s; \ -+ }) ---- /dev/null -+++ b/drivers/usb/host/hc-crisv10.c -@@ -0,0 +1,4800 @@ -+/* -+ * -+ * ETRAX 100LX USB Host Controller Driver -+ * -+ * Copyright (C) 2005, 2006 Axis Communications AB -+ * -+ * Author: Konrad Eriksson -+ * -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include "../core/hcd.h" -+#include "../core/hub.h" -+#include "hc-crisv10.h" -+#include "hc-cris-dbg.h" -+ -+ -+/***************************************************************************/ -+/***************************************************************************/ -+/* Host Controller settings */ -+/***************************************************************************/ -+/***************************************************************************/ -+ -+#define VERSION "1.00 hinko.4" -+#define COPYRIGHT "(c) 2005, 2006 Axis Communications AB" -+#define DESCRIPTION "ETRAX 100LX USB Host Controller (2.6.25-rc9 port)" -+ -+#define ETRAX_USB_HC_IRQ USB_HC_IRQ_NBR -+#define ETRAX_USB_RX_IRQ USB_DMA_RX_IRQ_NBR -+#define ETRAX_USB_TX_IRQ USB_DMA_TX_IRQ_NBR -+ -+/* Number of physical ports in Etrax 100LX */ -+#define USB_ROOT_HUB_PORTS 2 -+ -+const char hc_name[] = "hc-crisv10"; -+const char product_desc[] = DESCRIPTION; -+ -+/* The number of epids is, among other things, used for pre-allocating -+ ctrl, bulk and isoc EP descriptors (one for each epid). -+ Assumed to be > 1 when initiating the DMA lists. */ -+#define NBR_OF_EPIDS 32 -+ -+/* Support interrupt traffic intervals up to 128 ms. */ -+#define MAX_INTR_INTERVAL 128 -+ -+/* If periodic traffic (intr or isoc) is to be used, then one entry in the EP -+ table must be "invalid". By this we mean that we shouldn't care about epid -+ attentions for this epid, or at least handle them differently from epid -+ attentions for "valid" epids. This define determines which one to use -+ (don't change it). */ -+#define INVALID_EPID 31 -+/* A special epid for the bulk dummys. */ -+#define DUMMY_EPID 30 -+ -+/* Module settings */ -+ -+MODULE_DESCRIPTION(DESCRIPTION); -+MODULE_LICENSE("GPL"); -+MODULE_AUTHOR("Konrad Eriksson "); -+ -+ -+/* Module parameters */ -+ -+/* 0 = No ports enabled -+ 1 = Only port 1 enabled (on board ethernet on devboard) -+ 2 = Only port 2 enabled (external connector on devboard) -+ 3 = Both ports enabled -+*/ -+static unsigned int ports = 3; -+module_param(ports, uint, S_IRUGO); -+MODULE_PARM_DESC(ports, "Bitmask indicating USB ports to use"); -+ -+ -+/***************************************************************************/ -+/***************************************************************************/ -+/* Shared global variables for this module */ -+/***************************************************************************/ -+/***************************************************************************/ -+ -+/* EP descriptor lists for non period transfers. Must be 32-bit aligned. */ -+static volatile struct USB_EP_Desc TxBulkEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -+ -+static volatile struct USB_EP_Desc TxCtrlEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -+ -+/* EP descriptor lists for period transfers. Must be 32-bit aligned. */ -+static volatile struct USB_EP_Desc TxIntrEPList[MAX_INTR_INTERVAL] __attribute__ ((aligned (4))); -+static volatile struct USB_SB_Desc TxIntrSB_zout __attribute__ ((aligned (4))); -+ -+static volatile struct USB_EP_Desc TxIsocEPList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -+static volatile struct USB_SB_Desc TxIsocSB_zout __attribute__ ((aligned (4))); -+ -+//static volatile struct USB_SB_Desc TxIsocSBList[NBR_OF_EPIDS] __attribute__ ((aligned (4))); -+ -+/* After each enabled bulk EP IN we put two disabled EP descriptors with the eol flag set, -+ causing the DMA to stop the DMA channel. The first of these two has the intr flag set, which -+ gives us a dma8_sub0_descr interrupt. When we receive this, we advance the DMA one step in the -+ EP list and then restart the bulk channel, thus forcing a switch between bulk EP descriptors -+ in each frame. */ -+static volatile struct USB_EP_Desc TxBulkDummyEPList[NBR_OF_EPIDS][2] __attribute__ ((aligned (4))); -+ -+/* List of URB pointers, where each points to the active URB for a epid. -+ For Bulk, Ctrl and Intr this means which URB that currently is added to -+ DMA lists (Isoc URBs are all directly added to DMA lists). As soon as -+ URB has completed is the queue examined and the first URB in queue is -+ removed and moved to the activeUrbList while its state change to STARTED and -+ its transfer(s) gets added to DMA list (exception Isoc where URBs enter -+ state STARTED directly and added transfers added to DMA lists). */ -+static struct urb *activeUrbList[NBR_OF_EPIDS]; -+ -+/* Additional software state info for each epid */ -+static struct etrax_epid epid_state[NBR_OF_EPIDS]; -+ -+/* Timer handles for bulk traffic timer used to avoid DMA bug where DMA stops -+ even if there is new data waiting to be processed */ -+static struct timer_list bulk_start_timer = TIMER_INITIALIZER(NULL, 0, 0); -+static struct timer_list bulk_eot_timer = TIMER_INITIALIZER(NULL, 0, 0); -+ -+/* We want the start timer to expire before the eot timer, because the former -+ might start traffic, thus making it unnecessary for the latter to time -+ out. */ -+#define BULK_START_TIMER_INTERVAL (HZ/50) /* 20 ms */ -+#define BULK_EOT_TIMER_INTERVAL (HZ/16) /* 60 ms */ -+ -+/* Delay before a URB completion happen when it's scheduled to be delayed */ -+#define LATER_TIMER_DELAY (HZ/50) /* 20 ms */ -+ -+/* Simplifying macros for checking software state info of a epid */ -+/* ----------------------------------------------------------------------- */ -+#define epid_inuse(epid) epid_state[epid].inuse -+#define epid_out_traffic(epid) epid_state[epid].out_traffic -+#define epid_isoc(epid) (epid_state[epid].type == PIPE_ISOCHRONOUS ? 1 : 0) -+#define epid_intr(epid) (epid_state[epid].type == PIPE_INTERRUPT ? 1 : 0) -+ -+ -+/***************************************************************************/ -+/***************************************************************************/ -+/* DEBUG FUNCTIONS */ -+/***************************************************************************/ -+/***************************************************************************/ -+/* Note that these functions are always available in their "__" variants, -+ for use in error situations. The "__" missing variants are controlled by -+ the USB_DEBUG_DESC/USB_DEBUG_URB macros. */ -+static void __dump_urb(struct urb* purb) -+{ -+ struct crisv10_urb_priv *urb_priv = purb->hcpriv; -+ int urb_num = -1; -+ if(urb_priv) { -+ urb_num = urb_priv->urb_num; -+ } -+ printk("\nURB:0x%x[%d]\n", (unsigned int)purb, urb_num); -+ printk("dev :0x%08lx\n", (unsigned long)purb->dev); -+ printk("pipe :0x%08x\n", purb->pipe); -+ printk("status :%d\n", purb->status); -+ printk("transfer_flags :0x%08x\n", purb->transfer_flags); -+ printk("transfer_buffer :0x%08lx\n", (unsigned long)purb->transfer_buffer); -+ printk("transfer_buffer_length:%d\n", purb->transfer_buffer_length); -+ printk("actual_length :%d\n", purb->actual_length); -+ printk("setup_packet :0x%08lx\n", (unsigned long)purb->setup_packet); -+ printk("start_frame :%d\n", purb->start_frame); -+ printk("number_of_packets :%d\n", purb->number_of_packets); -+ printk("interval :%d\n", purb->interval); -+ printk("error_count :%d\n", purb->error_count); -+ printk("context :0x%08lx\n", (unsigned long)purb->context); -+ printk("complete :0x%08lx\n\n", (unsigned long)purb->complete); -+} -+ -+static void __dump_in_desc(volatile struct USB_IN_Desc *in) -+{ -+ printk("\nUSB_IN_Desc at 0x%08lx\n", (unsigned long)in); -+ printk(" sw_len : 0x%04x (%d)\n", in->sw_len, in->sw_len); -+ printk(" command : 0x%04x\n", in->command); -+ printk(" next : 0x%08lx\n", in->next); -+ printk(" buf : 0x%08lx\n", in->buf); -+ printk(" hw_len : 0x%04x (%d)\n", in->hw_len, in->hw_len); -+ printk(" status : 0x%04x\n\n", in->status); -+} -+ -+static void __dump_sb_desc(volatile struct USB_SB_Desc *sb) -+{ -+ char tt = (sb->command & 0x30) >> 4; -+ char *tt_string; -+ -+ switch (tt) { -+ case 0: -+ tt_string = "zout"; -+ break; -+ case 1: -+ tt_string = "in"; -+ break; -+ case 2: -+ tt_string = "out"; -+ break; -+ case 3: -+ tt_string = "setup"; -+ break; -+ default: -+ tt_string = "unknown (weird)"; -+ } -+ -+ printk(" USB_SB_Desc at 0x%08lx ", (unsigned long)sb); -+ printk(" command:0x%04x (", sb->command); -+ printk("rem:%d ", (sb->command & 0x3f00) >> 8); -+ printk("full:%d ", (sb->command & 0x40) >> 6); -+ printk("tt:%d(%s) ", tt, tt_string); -+ printk("intr:%d ", (sb->command & 0x8) >> 3); -+ printk("eot:%d ", (sb->command & 0x2) >> 1); -+ printk("eol:%d)", sb->command & 0x1); -+ printk(" sw_len:0x%04x(%d)", sb->sw_len, sb->sw_len); -+ printk(" next:0x%08lx", sb->next); -+ printk(" buf:0x%08lx\n", sb->buf); -+} -+ -+ -+static void __dump_ep_desc(volatile struct USB_EP_Desc *ep) -+{ -+ printk("USB_EP_Desc at 0x%08lx ", (unsigned long)ep); -+ printk(" command:0x%04x (", ep->command); -+ printk("ep_id:%d ", (ep->command & 0x1f00) >> 8); -+ printk("enable:%d ", (ep->command & 0x10) >> 4); -+ printk("intr:%d ", (ep->command & 0x8) >> 3); -+ printk("eof:%d ", (ep->command & 0x2) >> 1); -+ printk("eol:%d)", ep->command & 0x1); -+ printk(" hw_len:0x%04x(%d)", ep->hw_len, ep->hw_len); -+ printk(" next:0x%08lx", ep->next); -+ printk(" sub:0x%08lx\n", ep->sub); -+} -+ -+static inline void __dump_ep_list(int pipe_type) -+{ -+ volatile struct USB_EP_Desc *ep; -+ volatile struct USB_EP_Desc *first_ep; -+ volatile struct USB_SB_Desc *sb; -+ -+ switch (pipe_type) -+ { -+ case PIPE_BULK: -+ first_ep = &TxBulkEPList[0]; -+ break; -+ case PIPE_CONTROL: -+ first_ep = &TxCtrlEPList[0]; -+ break; -+ case PIPE_INTERRUPT: -+ first_ep = &TxIntrEPList[0]; -+ break; -+ case PIPE_ISOCHRONOUS: -+ first_ep = &TxIsocEPList[0]; -+ break; -+ default: -+ warn("Cannot dump unknown traffic type"); -+ return; -+ } -+ ep = first_ep; -+ -+ printk("\n\nDumping EP list...\n\n"); -+ -+ do { -+ __dump_ep_desc(ep); -+ /* Cannot phys_to_virt on 0 as it turns into 80000000, which is != 0. */ -+ sb = ep->sub ? phys_to_virt(ep->sub) : 0; -+ while (sb) { -+ __dump_sb_desc(sb); -+ sb = sb->next ? phys_to_virt(sb->next) : 0; -+ } -+ ep = (volatile struct USB_EP_Desc *)(phys_to_virt(ep->next)); -+ -+ } while (ep != first_ep); -+} -+ -+static inline void __dump_ept_data(int epid) -+{ -+ unsigned long flags; -+ __u32 r_usb_ept_data; -+ -+ if (epid < 0 || epid > 31) { -+ printk("Cannot dump ept data for invalid epid %d\n", epid); -+ return; -+ } -+ -+ local_irq_save(flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); -+ nop(); -+ r_usb_ept_data = *R_USB_EPT_DATA; -+ local_irq_restore(flags); -+ -+ printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", r_usb_ept_data, epid); -+ if (r_usb_ept_data == 0) { -+ /* No need for more detailed printing. */ -+ return; -+ } -+ printk(" valid : %d\n", (r_usb_ept_data & 0x80000000) >> 31); -+ printk(" hold : %d\n", (r_usb_ept_data & 0x40000000) >> 30); -+ printk(" error_count_in : %d\n", (r_usb_ept_data & 0x30000000) >> 28); -+ printk(" t_in : %d\n", (r_usb_ept_data & 0x08000000) >> 27); -+ printk(" low_speed : %d\n", (r_usb_ept_data & 0x04000000) >> 26); -+ printk(" port : %d\n", (r_usb_ept_data & 0x03000000) >> 24); -+ printk(" error_code : %d\n", (r_usb_ept_data & 0x00c00000) >> 22); -+ printk(" t_out : %d\n", (r_usb_ept_data & 0x00200000) >> 21); -+ printk(" error_count_out : %d\n", (r_usb_ept_data & 0x00180000) >> 19); -+ printk(" max_len : %d\n", (r_usb_ept_data & 0x0003f800) >> 11); -+ printk(" ep : %d\n", (r_usb_ept_data & 0x00000780) >> 7); -+ printk(" dev : %d\n", (r_usb_ept_data & 0x0000003f)); -+} -+ -+static inline void __dump_ept_data_iso(int epid) -+{ -+ unsigned long flags; -+ __u32 ept_data; -+ -+ if (epid < 0 || epid > 31) { -+ printk("Cannot dump ept data for invalid epid %d\n", epid); -+ return; -+ } -+ -+ local_irq_save(flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); -+ nop(); -+ ept_data = *R_USB_EPT_DATA_ISO; -+ local_irq_restore(flags); -+ -+ printk(" R_USB_EPT_DATA = 0x%x for epid %d :\n", ept_data, epid); -+ if (ept_data == 0) { -+ /* No need for more detailed printing. */ -+ return; -+ } -+ printk(" valid : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, valid, -+ ept_data)); -+ printk(" port : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, port, -+ ept_data)); -+ printk(" error_code : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, -+ ept_data)); -+ printk(" max_len : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, max_len, -+ ept_data)); -+ printk(" ep : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, ep, -+ ept_data)); -+ printk(" dev : %d\n", IO_EXTRACT(R_USB_EPT_DATA_ISO, dev, -+ ept_data)); -+} -+ -+static inline void __dump_ept_data_list(void) -+{ -+ int i; -+ -+ printk("Dumping the whole R_USB_EPT_DATA list\n"); -+ -+ for (i = 0; i < 32; i++) { -+ __dump_ept_data(i); -+ } -+} -+ -+static void debug_epid(int epid) { -+ int i; -+ -+ if(epid_isoc(epid)) { -+ __dump_ept_data_iso(epid); -+ } else { -+ __dump_ept_data(epid); -+ } -+ -+ printk("Bulk:\n"); -+ for(i = 0; i < 32; i++) { -+ if(IO_EXTRACT(USB_EP_command, epid, TxBulkEPList[i].command) == -+ epid) { -+ printk("%d: ", i); __dump_ep_desc(&(TxBulkEPList[i])); -+ } -+ } -+ -+ printk("Ctrl:\n"); -+ for(i = 0; i < 32; i++) { -+ if(IO_EXTRACT(USB_EP_command, epid, TxCtrlEPList[i].command) == -+ epid) { -+ printk("%d: ", i); __dump_ep_desc(&(TxCtrlEPList[i])); -+ } -+ } -+ -+ printk("Intr:\n"); -+ for(i = 0; i < MAX_INTR_INTERVAL; i++) { -+ if(IO_EXTRACT(USB_EP_command, epid, TxIntrEPList[i].command) == -+ epid) { -+ printk("%d: ", i); __dump_ep_desc(&(TxIntrEPList[i])); -+ } -+ } -+ -+ printk("Isoc:\n"); -+ for(i = 0; i < 32; i++) { -+ if(IO_EXTRACT(USB_EP_command, epid, TxIsocEPList[i].command) == -+ epid) { -+ printk("%d: ", i); __dump_ep_desc(&(TxIsocEPList[i])); -+ } -+ } -+ -+ __dump_ept_data_list(); -+ __dump_ep_list(PIPE_INTERRUPT); -+ printk("\n\n"); -+} -+ -+ -+ -+char* hcd_status_to_str(__u8 bUsbStatus) { -+ static char hcd_status_str[128]; -+ hcd_status_str[0] = '\0'; -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, ourun, yes)) { -+ strcat(hcd_status_str, "ourun "); -+ } -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, perror, yes)) { -+ strcat(hcd_status_str, "perror "); -+ } -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, device_mode, yes)) { -+ strcat(hcd_status_str, "device_mode "); -+ } -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, host_mode, yes)) { -+ strcat(hcd_status_str, "host_mode "); -+ } -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, started, yes)) { -+ strcat(hcd_status_str, "started "); -+ } -+ if(bUsbStatus & IO_STATE(R_USB_STATUS, running, yes)) { -+ strcat(hcd_status_str, "running "); -+ } -+ return hcd_status_str; -+} -+ -+ -+char* sblist_to_str(struct USB_SB_Desc* sb_desc) { -+ static char sblist_to_str_buff[128]; -+ char tmp[32], tmp2[32]; -+ sblist_to_str_buff[0] = '\0'; -+ while(sb_desc != NULL) { -+ switch(IO_EXTRACT(USB_SB_command, tt, sb_desc->command)) { -+ case 0: sprintf(tmp, "zout"); break; -+ case 1: sprintf(tmp, "in"); break; -+ case 2: sprintf(tmp, "out"); break; -+ case 3: sprintf(tmp, "setup"); break; -+ } -+ sprintf(tmp2, "(%s %d)", tmp, sb_desc->sw_len); -+ strcat(sblist_to_str_buff, tmp2); -+ if(sb_desc->next != 0) { -+ sb_desc = phys_to_virt(sb_desc->next); -+ } else { -+ sb_desc = NULL; -+ } -+ } -+ return sblist_to_str_buff; -+} -+ -+char* port_status_to_str(__u16 wPortStatus) { -+ static char port_status_str[128]; -+ port_status_str[0] = '\0'; -+ if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, connected, yes)) { -+ strcat(port_status_str, "connected "); -+ } -+ if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)) { -+ strcat(port_status_str, "enabled "); -+ } -+ if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, suspended, yes)) { -+ strcat(port_status_str, "suspended "); -+ } -+ if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, reset, yes)) { -+ strcat(port_status_str, "reset "); -+ } -+ if(wPortStatus & IO_STATE(R_USB_RH_PORT_STATUS_1, speed, full)) { -+ strcat(port_status_str, "full-speed "); -+ } else { -+ strcat(port_status_str, "low-speed "); -+ } -+ return port_status_str; -+} -+ -+ -+char* endpoint_to_str(struct usb_endpoint_descriptor *ed) { -+ static char endpoint_to_str_buff[128]; -+ char tmp[32]; -+ int epnum = ed->bEndpointAddress & 0x0F; -+ int dir = ed->bEndpointAddress & 0x80; -+ int type = ed->bmAttributes & 0x03; -+ endpoint_to_str_buff[0] = '\0'; -+ sprintf(endpoint_to_str_buff, "ep:%d ", epnum); -+ switch(type) { -+ case 0: -+ sprintf(tmp, " ctrl"); -+ break; -+ case 1: -+ sprintf(tmp, " isoc"); -+ break; -+ case 2: -+ sprintf(tmp, " bulk"); -+ break; -+ case 3: -+ sprintf(tmp, " intr"); -+ break; -+ } -+ strcat(endpoint_to_str_buff, tmp); -+ if(dir) { -+ sprintf(tmp, " in"); -+ } else { -+ sprintf(tmp, " out"); -+ } -+ strcat(endpoint_to_str_buff, tmp); -+ -+ return endpoint_to_str_buff; -+} -+ -+/* Debug helper functions for Transfer Controller */ -+char* pipe_to_str(unsigned int pipe) { -+ static char pipe_to_str_buff[128]; -+ char tmp[64]; -+ sprintf(pipe_to_str_buff, "dir:%s", str_dir(pipe)); -+ sprintf(tmp, " type:%s", str_type(pipe)); -+ strcat(pipe_to_str_buff, tmp); -+ -+ sprintf(tmp, " dev:%d", usb_pipedevice(pipe)); -+ strcat(pipe_to_str_buff, tmp); -+ sprintf(tmp, " ep:%d", usb_pipeendpoint(pipe)); -+ strcat(pipe_to_str_buff, tmp); -+ return pipe_to_str_buff; -+} -+ -+ -+#define USB_DEBUG_DESC 1 -+ -+#ifdef USB_DEBUG_DESC -+#define dump_in_desc(x) __dump_in_desc(x) -+#define dump_sb_desc(...) __dump_sb_desc(...) -+#define dump_ep_desc(x) __dump_ep_desc(x) -+#define dump_ept_data(x) __dump_ept_data(x) -+#else -+#define dump_in_desc(...) do {} while (0) -+#define dump_sb_desc(...) do {} while (0) -+#define dump_ep_desc(...) do {} while (0) -+#endif -+ -+ -+/* Uncomment this to enable massive function call trace -+ #define USB_DEBUG_TRACE */ -+//#define USB_DEBUG_TRACE 1 -+ -+#ifdef USB_DEBUG_TRACE -+#define DBFENTER (printk(": Entering: %s\n", __FUNCTION__)) -+#define DBFEXIT (printk(": Exiting: %s\n", __FUNCTION__)) -+#else -+#define DBFENTER do {} while (0) -+#define DBFEXIT do {} while (0) -+#endif -+ -+#define CHECK_ALIGN(x) if (((__u32)(x)) & 0x00000003) \ -+{panic("Alignment check (DWORD) failed at %s:%s:%d\n", __FILE__, __FUNCTION__, __LINE__);} -+ -+/* Most helpful debugging aid */ -+#define ASSERT(expr) ((void) ((expr) ? 0 : (err("assert failed at: %s %d",__FUNCTION__, __LINE__)))) -+ -+ -+/***************************************************************************/ -+/***************************************************************************/ -+/* Forward declarations */ -+/***************************************************************************/ -+/***************************************************************************/ -+void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg); -+void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg); -+void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg); -+void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg); -+ -+void rh_port_status_change(__u16[]); -+int rh_clear_port_feature(__u8, __u16); -+int rh_set_port_feature(__u8, __u16); -+static void rh_disable_port(unsigned int port); -+ -+static void check_finished_bulk_tx_epids(struct usb_hcd *hcd, -+ int timer); -+ -+//static int tc_setup_epid(struct usb_host_endpoint *ep, struct urb *urb, -+// int mem_flags); -+static int tc_setup_epid(struct urb *urb, int mem_flags); -+static void tc_free_epid(struct usb_host_endpoint *ep); -+static int tc_allocate_epid(void); -+static void tc_finish_urb(struct usb_hcd *hcd, struct urb *urb, int status); -+static void tc_finish_urb_later(struct usb_hcd *hcd, struct urb *urb, -+ int status); -+ -+static int urb_priv_create(struct usb_hcd *hcd, struct urb *urb, int epid, -+ int mem_flags); -+static void urb_priv_free(struct usb_hcd *hcd, struct urb *urb); -+ -+static inline struct urb *urb_list_first(int epid); -+static inline void urb_list_add(struct urb *urb, int epid, -+ int mem_flags); -+static inline urb_entry_t *urb_list_entry(struct urb *urb, int epid); -+static inline void urb_list_del(struct urb *urb, int epid); -+static inline void urb_list_move_last(struct urb *urb, int epid); -+static inline struct urb *urb_list_next(struct urb *urb, int epid); -+ -+int create_sb_for_urb(struct urb *urb, int mem_flags); -+int init_intr_urb(struct urb *urb, int mem_flags); -+ -+static inline void etrax_epid_set(__u8 index, __u32 data); -+static inline void etrax_epid_clear_error(__u8 index); -+static inline void etrax_epid_set_toggle(__u8 index, __u8 dirout, -+ __u8 toggle); -+static inline __u8 etrax_epid_get_toggle(__u8 index, __u8 dirout); -+static inline __u32 etrax_epid_get(__u8 index); -+ -+/* We're accessing the same register position in Etrax so -+ when we do full access the internal difference doesn't matter */ -+#define etrax_epid_iso_set(index, data) etrax_epid_set(index, data) -+#define etrax_epid_iso_get(index) etrax_epid_get(index) -+ -+ -+//static void tc_dma_process_isoc_urb(struct urb *urb); -+static void tc_dma_process_queue(int epid); -+static void tc_dma_unlink_intr_urb(struct urb *urb); -+static irqreturn_t tc_dma_tx_interrupt(int irq, void *vhc); -+static irqreturn_t tc_dma_rx_interrupt(int irq, void *vhc); -+ -+static void tc_bulk_start_timer_func(unsigned long dummy); -+static void tc_bulk_eot_timer_func(unsigned long dummy); -+ -+ -+/*************************************************************/ -+/*************************************************************/ -+/* Host Controler Driver block */ -+/*************************************************************/ -+/*************************************************************/ -+ -+/* HCD operations */ -+static irqreturn_t crisv10_hcd_top_irq(int irq, void*); -+static int crisv10_hcd_reset(struct usb_hcd *); -+static int crisv10_hcd_start(struct usb_hcd *); -+static void crisv10_hcd_stop(struct usb_hcd *); -+#ifdef CONFIG_PM -+static int crisv10_hcd_suspend(struct device *, u32, u32); -+static int crisv10_hcd_resume(struct device *, u32); -+#endif /* CONFIG_PM */ -+static int crisv10_hcd_get_frame(struct usb_hcd *); -+ -+//static int tc_urb_enqueue(struct usb_hcd *, struct usb_host_endpoint *ep, struct urb *, gfp_t mem_flags); -+static int tc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); -+//static int tc_urb_dequeue(struct usb_hcd *, struct urb *); -+static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); -+static void tc_endpoint_disable(struct usb_hcd *, struct usb_host_endpoint *ep); -+ -+static int rh_status_data_request(struct usb_hcd *, char *); -+static int rh_control_request(struct usb_hcd *, u16, u16, u16, char*, u16); -+ -+#ifdef CONFIG_PM -+static int crisv10_hcd_hub_suspend(struct usb_hcd *); -+static int crisv10_hcd_hub_resume(struct usb_hcd *); -+#endif /* CONFIG_PM */ -+#ifdef CONFIG_USB_OTG -+static int crisv10_hcd_start_port_reset(struct usb_hcd *, unsigned); -+#endif /* CONFIG_USB_OTG */ -+ -+/* host controller driver interface */ -+static const struct hc_driver crisv10_hc_driver = -+ { -+ .description = hc_name, -+ .product_desc = product_desc, -+ .hcd_priv_size = sizeof(struct crisv10_hcd), -+ -+ /* Attaching IRQ handler manualy in probe() */ -+ /* .irq = crisv10_hcd_irq, */ -+ -+ .flags = HCD_USB11, -+ -+ /* called to init HCD and root hub */ -+ .reset = crisv10_hcd_reset, -+ .start = crisv10_hcd_start, -+ -+ /* cleanly make HCD stop writing memory and doing I/O */ -+ .stop = crisv10_hcd_stop, -+ -+ /* return current frame number */ -+ .get_frame_number = crisv10_hcd_get_frame, -+ -+ -+ /* Manage i/o requests via the Transfer Controller */ -+ .urb_enqueue = tc_urb_enqueue, -+ .urb_dequeue = tc_urb_dequeue, -+ -+ /* hw synch, freeing endpoint resources that urb_dequeue can't */ -+ .endpoint_disable = tc_endpoint_disable, -+ -+ -+ /* Root Hub support */ -+ .hub_status_data = rh_status_data_request, -+ .hub_control = rh_control_request, -+#ifdef CONFIG_PM -+ .hub_suspend = rh_suspend_request, -+ .hub_resume = rh_resume_request, -+#endif /* CONFIG_PM */ -+#ifdef CONFIG_USB_OTG -+ .start_port_reset = crisv10_hcd_start_port_reset, -+#endif /* CONFIG_USB_OTG */ -+ }; -+ -+ -+/* -+ * conversion between pointers to a hcd and the corresponding -+ * crisv10_hcd -+ */ -+ -+static inline struct crisv10_hcd *hcd_to_crisv10_hcd(struct usb_hcd *hcd) -+{ -+ return (struct crisv10_hcd *) hcd->hcd_priv; -+} -+ -+static inline struct usb_hcd *crisv10_hcd_to_hcd(struct crisv10_hcd *hcd) -+{ -+ return container_of((void *) hcd, struct usb_hcd, hcd_priv); -+} -+ -+/* check if specified port is in use */ -+static inline int port_in_use(unsigned int port) -+{ -+ return ports & (1 << port); -+} -+ -+/* number of ports in use */ -+static inline unsigned int num_ports(void) -+{ -+ unsigned int i, num = 0; -+ for (i = 0; i < USB_ROOT_HUB_PORTS; i++) -+ if (port_in_use(i)) -+ num++; -+ return num; -+} -+ -+/* map hub port number to the port number used internally by the HC */ -+static inline unsigned int map_port(unsigned int port) -+{ -+ unsigned int i, num = 0; -+ for (i = 0; i < USB_ROOT_HUB_PORTS; i++) -+ if (port_in_use(i)) -+ if (++num == port) -+ return i; -+ return -1; -+} -+ -+/* size of descriptors in slab cache */ -+#ifndef MAX -+#define MAX(x, y) ((x) > (y) ? (x) : (y)) -+#endif -+ -+ -+/******************************************************************/ -+/* Hardware Interrupt functions */ -+/******************************************************************/ -+ -+/* Fast interrupt handler for HC */ -+static irqreturn_t crisv10_hcd_top_irq(int irq, void *vcd) -+{ -+ struct usb_hcd *hcd = vcd; -+ struct crisv10_irq_reg reg; -+ __u32 irq_mask; -+ unsigned long flags; -+ -+ DBFENTER; -+ -+ ASSERT(hcd != NULL); -+ reg.hcd = hcd; -+ -+ /* Turn of other interrupts while handling these sensitive cases */ -+ local_irq_save(flags); -+ -+ /* Read out which interrupts that are flaged */ -+ irq_mask = *R_USB_IRQ_MASK_READ; -+ reg.r_usb_irq_mask_read = irq_mask; -+ -+ /* Reading R_USB_STATUS clears the ctl_status interrupt. Note that -+ R_USB_STATUS must be read before R_USB_EPID_ATTN since reading the latter -+ clears the ourun and perror fields of R_USB_STATUS. */ -+ reg.r_usb_status = *R_USB_STATUS; -+ -+ /* Reading R_USB_EPID_ATTN clears the iso_eof, bulk_eot and epid_attn -+ interrupts. */ -+ reg.r_usb_epid_attn = *R_USB_EPID_ATTN; -+ -+ /* Reading R_USB_RH_PORT_STATUS_1 and R_USB_RH_PORT_STATUS_2 clears the -+ port_status interrupt. */ -+ reg.r_usb_rh_port_status_1 = *R_USB_RH_PORT_STATUS_1; -+ reg.r_usb_rh_port_status_2 = *R_USB_RH_PORT_STATUS_2; -+ -+ /* Reading R_USB_FM_NUMBER clears the sof interrupt. */ -+ /* Note: the lower 11 bits contain the actual frame number, sent with each -+ sof. */ -+ reg.r_usb_fm_number = *R_USB_FM_NUMBER; -+ -+ /* Interrupts are handled in order of priority. */ -+ if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, port_status)) { -+ crisv10_hcd_port_status_irq(®); -+ } -+ if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, epid_attn)) { -+ crisv10_hcd_epid_attn_irq(®); -+ } -+ if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, ctl_status)) { -+ crisv10_hcd_ctl_status_irq(®); -+ } -+ if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, iso_eof)) { -+ crisv10_hcd_isoc_eof_irq(®); -+ } -+ if (irq_mask & IO_MASK(R_USB_IRQ_MASK_READ, bulk_eot)) { -+ /* Update/restart the bulk start timer since obviously the channel is -+ running. */ -+ mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL); -+ /* Update/restart the bulk eot timer since we just received an bulk eot -+ interrupt. */ -+ mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); -+ -+ /* Check for finished bulk transfers on epids */ -+ check_finished_bulk_tx_epids(hcd, 0); -+ } -+ local_irq_restore(flags); -+ -+ DBFEXIT; -+ return IRQ_HANDLED; -+} -+ -+ -+void crisv10_hcd_epid_attn_irq(struct crisv10_irq_reg *reg) { -+ struct usb_hcd *hcd = reg->hcd; -+ struct crisv10_urb_priv *urb_priv; -+ int epid; -+ DBFENTER; -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ if (test_bit(epid, (void *)®->r_usb_epid_attn)) { -+ struct urb *urb; -+ __u32 ept_data; -+ int error_code; -+ -+ if (epid == DUMMY_EPID || epid == INVALID_EPID) { -+ /* We definitely don't care about these ones. Besides, they are -+ always disabled, so any possible disabling caused by the -+ epid attention interrupt is irrelevant. */ -+ warn("Got epid_attn for INVALID_EPID or DUMMY_EPID (%d).", epid); -+ continue; -+ } -+ -+ if(!epid_inuse(epid)) { -+ irq_err("Epid attention on epid:%d that isn't in use\n", epid); -+ printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status); -+ debug_epid(epid); -+ continue; -+ } -+ -+ /* Note that although there are separate R_USB_EPT_DATA and -+ R_USB_EPT_DATA_ISO registers, they are located at the same address and -+ are of the same size. In other words, this read should be ok for isoc -+ also. */ -+ ept_data = etrax_epid_get(epid); -+ error_code = IO_EXTRACT(R_USB_EPT_DATA, error_code, ept_data); -+ -+ /* Get the active URB for this epid. We blatantly assume -+ that only this URB could have caused the epid attention. */ -+ urb = activeUrbList[epid]; -+ if (urb == NULL) { -+ irq_err("Attention on epid:%d error:%d with no active URB.\n", -+ epid, error_code); -+ printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status); -+ debug_epid(epid); -+ continue; -+ } -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ /* Using IO_STATE_VALUE on R_USB_EPT_DATA should be ok for isoc also. */ -+ if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { -+ -+ /* Isoc traffic doesn't have error_count_in/error_count_out. */ -+ if ((usb_pipetype(urb->pipe) != PIPE_ISOCHRONOUS) && -+ (IO_EXTRACT(R_USB_EPT_DATA, error_count_in, ept_data) == 3 || -+ IO_EXTRACT(R_USB_EPT_DATA, error_count_out, ept_data) == 3)) { -+ /* Check if URB allready is marked for late-finish, we can get -+ several 3rd error for Intr traffic when a device is unplugged */ -+ if(urb_priv->later_data == NULL) { -+ /* 3rd error. */ -+ irq_warn("3rd error for epid:%d (%s %s) URB:0x%x[%d]\n", epid, -+ str_dir(urb->pipe), str_type(urb->pipe), -+ (unsigned int)urb, urb_priv->urb_num); -+ -+ tc_finish_urb_later(hcd, urb, -EPROTO); -+ } -+ -+ } else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) { -+ irq_warn("Perror for epid:%d\n", epid); -+ printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff); -+ printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status); -+ __dump_urb(urb); -+ debug_epid(epid); -+ -+ if (!(ept_data & IO_MASK(R_USB_EPT_DATA, valid))) { -+ /* invalid ep_id */ -+ panic("Perror because of invalid epid." -+ " Deconfigured too early?"); -+ } else { -+ /* past eof1, near eof, zout transfer, setup transfer */ -+ /* Dump the urb and the relevant EP descriptor. */ -+ panic("Something wrong with DMA descriptor contents." -+ " Too much traffic inserted?"); -+ } -+ } else if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) { -+ /* buffer ourun */ -+ printk("FM_NUMBER: %d\n", reg->r_usb_fm_number & 0x7ff); -+ printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status); -+ __dump_urb(urb); -+ debug_epid(epid); -+ -+ panic("Buffer overrun/underrun for epid:%d. DMA too busy?", epid); -+ } else { -+ irq_warn("Attention on epid:%d (%s %s) with no error code\n", epid, -+ str_dir(urb->pipe), str_type(urb->pipe)); -+ printk("R_USB_STATUS: 0x%x\n", reg->r_usb_status); -+ __dump_urb(urb); -+ debug_epid(epid); -+ } -+ -+ } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, -+ stall)) { -+ /* Not really a protocol error, just says that the endpoint gave -+ a stall response. Note that error_code cannot be stall for isoc. */ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ panic("Isoc traffic cannot stall"); -+ } -+ -+ tc_dbg("Stall for epid:%d (%s %s) URB:0x%x\n", epid, -+ str_dir(urb->pipe), str_type(urb->pipe), (unsigned int)urb); -+ tc_finish_urb(hcd, urb, -EPIPE); -+ -+ } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, -+ bus_error)) { -+ /* Two devices responded to a transaction request. Must be resolved -+ by software. FIXME: Reset ports? */ -+ panic("Bus error for epid %d." -+ " Two devices responded to transaction request\n", -+ epid); -+ -+ } else if (error_code == IO_STATE_VALUE(R_USB_EPT_DATA, error_code, -+ buffer_error)) { -+ /* DMA overrun or underrun. */ -+ irq_warn("Buffer overrun/underrun for epid:%d (%s %s)\n", epid, -+ str_dir(urb->pipe), str_type(urb->pipe)); -+ -+ /* It seems that error_code = buffer_error in -+ R_USB_EPT_DATA/R_USB_EPT_DATA_ISO and ourun = yes in R_USB_STATUS -+ are the same error. */ -+ tc_finish_urb(hcd, urb, -EPROTO); -+ } else { -+ irq_warn("Unknown attention on epid:%d (%s %s)\n", epid, -+ str_dir(urb->pipe), str_type(urb->pipe)); -+ dump_ept_data(epid); -+ } -+ } -+ } -+ DBFEXIT; -+} -+ -+void crisv10_hcd_port_status_irq(struct crisv10_irq_reg *reg) -+{ -+ __u16 port_reg[USB_ROOT_HUB_PORTS]; -+ DBFENTER; -+ port_reg[0] = reg->r_usb_rh_port_status_1; -+ port_reg[1] = reg->r_usb_rh_port_status_2; -+ rh_port_status_change(port_reg); -+ DBFEXIT; -+} -+ -+void crisv10_hcd_isoc_eof_irq(struct crisv10_irq_reg *reg) -+{ -+ int epid; -+ struct urb *urb; -+ struct crisv10_urb_priv *urb_priv; -+ -+ DBFENTER; -+ -+ for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { -+ -+ /* Only check epids that are in use, is valid and has SB list */ -+ if (!epid_inuse(epid) || epid == INVALID_EPID || -+ TxIsocEPList[epid].sub == 0 || epid == DUMMY_EPID) { -+ /* Nothing here to see. */ -+ continue; -+ } -+ ASSERT(epid_isoc(epid)); -+ -+ /* Get the active URB for this epid (if any). */ -+ urb = activeUrbList[epid]; -+ if (urb == 0) { -+ isoc_warn("Ignoring NULL urb for epid:%d\n", epid); -+ continue; -+ } -+ if(!epid_out_traffic(epid)) { -+ /* Sanity check. */ -+ ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS); -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ if (urb_priv->urb_state == NOT_STARTED) { -+ /* If ASAP is not set and urb->start_frame is the current frame, -+ start the transfer. */ -+ if (!(urb->transfer_flags & URB_ISO_ASAP) && -+ (urb->start_frame == (*R_USB_FM_NUMBER & 0x7ff))) { -+ /* EP should not be enabled if we're waiting for start_frame */ -+ ASSERT((TxIsocEPList[epid].command & -+ IO_STATE(USB_EP_command, enable, yes)) == 0); -+ -+ isoc_warn("Enabling isoc IN EP descr for epid %d\n", epid); -+ TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); -+ -+ /* This urb is now active. */ -+ urb_priv->urb_state = STARTED; -+ continue; -+ } -+ } -+ } -+ } -+ -+ DBFEXIT; -+} -+ -+void crisv10_hcd_ctl_status_irq(struct crisv10_irq_reg *reg) -+{ -+ struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(reg->hcd); -+ -+ DBFENTER; -+ ASSERT(crisv10_hcd); -+ -+ irq_dbg("ctr_status_irq, controller status: %s\n", -+ hcd_status_to_str(reg->r_usb_status)); -+ -+ /* FIXME: What should we do if we get ourun or perror? Dump the EP and SB -+ list for the corresponding epid? */ -+ if (reg->r_usb_status & IO_MASK(R_USB_STATUS, ourun)) { -+ panic("USB controller got ourun."); -+ } -+ if (reg->r_usb_status & IO_MASK(R_USB_STATUS, perror)) { -+ -+ /* Before, etrax_usb_do_intr_recover was called on this epid if it was -+ an interrupt pipe. I don't see how re-enabling all EP descriptors -+ will help if there was a programming error. */ -+ panic("USB controller got perror."); -+ } -+ -+ /* Keep track of USB Controller, if it's running or not */ -+ if(reg->r_usb_status & IO_STATE(R_USB_STATUS, running, yes)) { -+ crisv10_hcd->running = 1; -+ } else { -+ crisv10_hcd->running = 0; -+ } -+ -+ if (reg->r_usb_status & IO_MASK(R_USB_STATUS, device_mode)) { -+ /* We should never operate in device mode. */ -+ panic("USB controller in device mode."); -+ } -+ -+ /* Set the flag to avoid getting "Unlink after no-IRQ? Controller is probably -+ using the wrong IRQ" from hcd_unlink_urb() in drivers/usb/core/hcd.c */ -+ set_bit(HCD_FLAG_SAW_IRQ, ®->hcd->flags); -+ -+ DBFEXIT; -+} -+ -+ -+/******************************************************************/ -+/* Host Controller interface functions */ -+/******************************************************************/ -+ -+static inline void crisv10_ready_wait(void) { -+ volatile int timeout = 10000; -+ /* Check the busy bit of USB controller in Etrax */ -+ while((*R_USB_COMMAND & IO_MASK(R_USB_COMMAND, busy)) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for USB controller to be idle\n"); -+ } -+} -+ -+/* reset host controller */ -+static int crisv10_hcd_reset(struct usb_hcd *hcd) -+{ -+ DBFENTER; -+ hcd_dbg(hcd, "reset\n"); -+ -+ -+ /* Reset the USB interface. */ -+ /* -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, reset); -+ nop(); -+ */ -+ DBFEXIT; -+ return 0; -+} -+ -+/* start host controller */ -+static int crisv10_hcd_start(struct usb_hcd *hcd) -+{ -+ DBFENTER; -+ hcd_dbg(hcd, "start\n"); -+ -+ crisv10_ready_wait(); -+ -+ /* Start processing of USB traffic. */ -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run); -+ -+ nop(); -+ -+ hcd->state = HC_STATE_RUNNING; -+ -+ DBFEXIT; -+ return 0; -+} -+ -+/* stop host controller */ -+static void crisv10_hcd_stop(struct usb_hcd *hcd) -+{ -+ DBFENTER; -+ hcd_dbg(hcd, "stop\n"); -+ crisv10_hcd_reset(hcd); -+ DBFEXIT; -+} -+ -+/* return the current frame number */ -+static int crisv10_hcd_get_frame(struct usb_hcd *hcd) -+{ -+ DBFENTER; -+ DBFEXIT; -+ return (*R_USB_FM_NUMBER & 0x7ff); -+} -+ -+#ifdef CONFIG_USB_OTG -+ -+static int crisv10_hcd_start_port_reset(struct usb_hcd *hcd, unsigned port) -+{ -+ return 0; /* no-op for now */ -+} -+ -+#endif /* CONFIG_USB_OTG */ -+ -+ -+/******************************************************************/ -+/* Root Hub functions */ -+/******************************************************************/ -+ -+/* root hub status */ -+static const struct usb_hub_status rh_hub_status = -+ { -+ .wHubStatus = 0, -+ .wHubChange = 0, -+ }; -+ -+/* root hub descriptor */ -+static const u8 rh_hub_descr[] = -+ { -+ 0x09, /* bDescLength */ -+ 0x29, /* bDescriptorType */ -+ USB_ROOT_HUB_PORTS, /* bNbrPorts */ -+ 0x00, /* wHubCharacteristics */ -+ 0x00, -+ 0x01, /* bPwrOn2pwrGood */ -+ 0x00, /* bHubContrCurrent */ -+ 0x00, /* DeviceRemovable */ -+ 0xff /* PortPwrCtrlMask */ -+ }; -+ -+/* Actual holder of root hub status*/ -+struct crisv10_rh rh; -+ -+/* Initialize root hub data structures (called from dvdrv_hcd_probe()) */ -+int rh_init(void) { -+ int i; -+ /* Reset port status flags */ -+ for (i = 0; i < USB_ROOT_HUB_PORTS; i++) { -+ rh.wPortChange[i] = 0; -+ rh.wPortStatusPrev[i] = 0; -+ } -+ return 0; -+} -+ -+#define RH_FEAT_MASK ((1<lock); -+ for (i = 1; i <= crisv10_hcd->num_ports; i++) { -+ if (rh.wPortChange[map_port(i)]) { -+ *buf |= (1 << i); -+ rh_dbg("rh_status_data_request, change on port %d: %s Current Status: %s\n", i, -+ port_status_to_str(rh.wPortChange[map_port(i)]), -+ port_status_to_str(rh.wPortStatusPrev[map_port(i)])); -+ } -+ } -+ spin_unlock(&crisv10_hcd->lock); -+ -+// DBFEXIT; -+ -+ return *buf == 0 ? 0 : 1; -+} -+ -+/* Handle a control request for the root hub (called from hcd_driver) */ -+static int rh_control_request(struct usb_hcd *hcd, -+ u16 typeReq, -+ u16 wValue, -+ u16 wIndex, -+ char *buf, -+ u16 wLength) { -+ -+ struct crisv10_hcd *crisv10_hcd = hcd_to_crisv10_hcd(hcd); -+ int retval = 0; -+ int len; -+ DBFENTER; -+ -+ switch (typeReq) { -+ case GetHubDescriptor: -+ rh_dbg("GetHubDescriptor\n"); -+ len = min_t(unsigned int, sizeof rh_hub_descr, wLength); -+ memcpy(buf, rh_hub_descr, len); -+ buf[2] = crisv10_hcd->num_ports; -+ break; -+ case GetHubStatus: -+ rh_dbg("GetHubStatus\n"); -+ len = min_t(unsigned int, sizeof rh_hub_status, wLength); -+ memcpy(buf, &rh_hub_status, len); -+ break; -+ case GetPortStatus: -+ if (!wIndex || wIndex > crisv10_hcd->num_ports) -+ goto error; -+ rh_dbg("GetportStatus, port:%d change:%s status:%s\n", wIndex, -+ port_status_to_str(rh.wPortChange[map_port(wIndex)]), -+ port_status_to_str(rh.wPortStatusPrev[map_port(wIndex)])); -+ *(u16 *) buf = cpu_to_le16(rh.wPortStatusPrev[map_port(wIndex)]); -+ *(u16 *) (buf + 2) = cpu_to_le16(rh.wPortChange[map_port(wIndex)]); -+ break; -+ case SetHubFeature: -+ rh_dbg("SetHubFeature\n"); -+ case ClearHubFeature: -+ rh_dbg("ClearHubFeature\n"); -+ switch (wValue) { -+ case C_HUB_OVER_CURRENT: -+ case C_HUB_LOCAL_POWER: -+ rh_warn("Not implemented hub request:%d \n", typeReq); -+ /* not implemented */ -+ break; -+ default: -+ goto error; -+ } -+ break; -+ case SetPortFeature: -+ if (!wIndex || wIndex > crisv10_hcd->num_ports) -+ goto error; -+ if(rh_set_port_feature(map_port(wIndex), wValue)) -+ goto error; -+ break; -+ case ClearPortFeature: -+ if (!wIndex || wIndex > crisv10_hcd->num_ports) -+ goto error; -+ if(rh_clear_port_feature(map_port(wIndex), wValue)) -+ goto error; -+ break; -+ default: -+ rh_warn("Unknown hub request: %d\n", typeReq); -+ error: -+ retval = -EPIPE; -+ } -+ DBFEXIT; -+ return retval; -+} -+ -+int rh_set_port_feature(__u8 bPort, __u16 wFeature) { -+ __u8 bUsbCommand = 0; -+ switch(wFeature) { -+ case USB_PORT_FEAT_RESET: -+ rh_dbg("SetPortFeature: reset\n"); -+ bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, reset); -+ goto set; -+ break; -+ case USB_PORT_FEAT_SUSPEND: -+ rh_dbg("SetPortFeature: suspend\n"); -+ bUsbCommand |= IO_STATE(R_USB_COMMAND, port_cmd, suspend); -+ goto set; -+ break; -+ case USB_PORT_FEAT_POWER: -+ rh_dbg("SetPortFeature: power\n"); -+ break; -+ case USB_PORT_FEAT_C_CONNECTION: -+ rh_dbg("SetPortFeature: c_connection\n"); -+ break; -+ case USB_PORT_FEAT_C_RESET: -+ rh_dbg("SetPortFeature: c_reset\n"); -+ break; -+ case USB_PORT_FEAT_C_OVER_CURRENT: -+ rh_dbg("SetPortFeature: c_over_current\n"); -+ break; -+ -+ set: -+ /* Select which port via the port_sel field */ -+ bUsbCommand |= IO_FIELD(R_USB_COMMAND, port_sel, bPort+1); -+ -+ /* Make sure the controller isn't busy. */ -+ crisv10_ready_wait(); -+ /* Send out the actual command to the USB controller */ -+ *R_USB_COMMAND = bUsbCommand; -+ -+ /* If port reset then also bring USB controller into running state */ -+ if(wFeature == USB_PORT_FEAT_RESET) { -+ /* Wait a while for controller to first become started after port reset */ -+ udelay(12000); /* 12ms blocking wait */ -+ -+ /* Make sure the controller isn't busy. */ -+ crisv10_ready_wait(); -+ -+ /* If all enabled ports were disabled the host controller goes down into -+ started mode, so we need to bring it back into the running state. -+ (This is safe even if it's already in the running state.) */ -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run); -+ } -+ -+ break; -+ default: -+ rh_dbg("SetPortFeature: unknown feature\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+int rh_clear_port_feature(__u8 bPort, __u16 wFeature) { -+ switch(wFeature) { -+ case USB_PORT_FEAT_ENABLE: -+ rh_dbg("ClearPortFeature: enable\n"); -+ rh_disable_port(bPort); -+ break; -+ case USB_PORT_FEAT_SUSPEND: -+ rh_dbg("ClearPortFeature: suspend\n"); -+ break; -+ case USB_PORT_FEAT_POWER: -+ rh_dbg("ClearPortFeature: power\n"); -+ break; -+ -+ case USB_PORT_FEAT_C_ENABLE: -+ rh_dbg("ClearPortFeature: c_enable\n"); -+ goto clear; -+ case USB_PORT_FEAT_C_SUSPEND: -+ rh_dbg("ClearPortFeature: c_suspend\n"); -+ goto clear; -+ case USB_PORT_FEAT_C_CONNECTION: -+ rh_dbg("ClearPortFeature: c_connection\n"); -+ goto clear; -+ case USB_PORT_FEAT_C_OVER_CURRENT: -+ rh_dbg("ClearPortFeature: c_over_current\n"); -+ goto clear; -+ case USB_PORT_FEAT_C_RESET: -+ rh_dbg("ClearPortFeature: c_reset\n"); -+ goto clear; -+ clear: -+ rh.wPortChange[bPort] &= ~(1 << (wFeature - 16)); -+ break; -+ default: -+ rh_dbg("ClearPortFeature: unknown feature\n"); -+ return -1; -+ } -+ return 0; -+} -+ -+ -+#ifdef CONFIG_PM -+/* Handle a suspend request for the root hub (called from hcd_driver) */ -+static int rh_suspend_request(struct usb_hcd *hcd) -+{ -+ return 0; /* no-op for now */ -+} -+ -+/* Handle a resume request for the root hub (called from hcd_driver) */ -+static int rh_resume_request(struct usb_hcd *hcd) -+{ -+ return 0; /* no-op for now */ -+} -+#endif /* CONFIG_PM */ -+ -+ -+ -+/* Wrapper function for workaround port disable registers in USB controller */ -+static void rh_disable_port(unsigned int port) { -+ volatile int timeout = 10000; -+ volatile char* usb_portx_disable; -+ switch(port) { -+ case 0: -+ usb_portx_disable = R_USB_PORT1_DISABLE; -+ break; -+ case 1: -+ usb_portx_disable = R_USB_PORT2_DISABLE; -+ break; -+ default: -+ /* Invalid port index */ -+ return; -+ } -+ /* Set disable flag in special register */ -+ *usb_portx_disable = IO_STATE(R_USB_PORT1_DISABLE, disable, yes); -+ /* Wait until not enabled anymore */ -+ while((rh.wPortStatusPrev[port] & -+ IO_STATE(R_USB_RH_PORT_STATUS_1, enabled, yes)) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for port %d to become disabled\n", port); -+ } -+ /* clear disable flag in special register */ -+ *usb_portx_disable = IO_STATE(R_USB_PORT1_DISABLE, disable, no); -+ rh_info("Physical port %d disabled\n", port+1); -+} -+ -+ -+/******************************************************************/ -+/* Transfer Controller (TC) functions */ -+/******************************************************************/ -+ -+/* FIXME: Should RX_BUF_SIZE be a config option, or maybe we should adjust it -+ dynamically? -+ To adjust it dynamically we would have to get an interrupt when we reach -+ the end of the rx descriptor list, or when we get close to the end, and -+ then allocate more descriptors. */ -+#define NBR_OF_RX_DESC 512 -+#define RX_DESC_BUF_SIZE 1024 -+#define RX_BUF_SIZE (NBR_OF_RX_DESC * RX_DESC_BUF_SIZE) -+ -+ -+/* Local variables for Transfer Controller */ -+/* --------------------------------------- */ -+ -+/* This is a circular (double-linked) list of the active urbs for each epid. -+ The head is never removed, and new urbs are linked onto the list as -+ urb_entry_t elements. Don't reference urb_list directly; use the wrapper -+ functions instead (which includes spin_locks) */ -+static struct list_head urb_list[NBR_OF_EPIDS]; -+ -+/* Read about the need and usage of this lock in submit_ctrl_urb. */ -+/* Lock for URB lists for each EPID */ -+static spinlock_t urb_list_lock; -+ -+/* Lock for EPID array register (R_USB_EPT_x) in Etrax */ -+static spinlock_t etrax_epid_lock; -+ -+/* Lock for dma8 sub0 handling */ -+static spinlock_t etrax_dma8_sub0_lock; -+ -+/* DMA IN cache bug. Align the DMA IN buffers to 32 bytes, i.e. a cache line. -+ Since RX_DESC_BUF_SIZE is 1024 is a multiple of 32, all rx buffers will be -+ cache aligned. */ -+static volatile unsigned char RxBuf[RX_BUF_SIZE] __attribute__ ((aligned (32))); -+static volatile struct USB_IN_Desc RxDescList[NBR_OF_RX_DESC] __attribute__ ((aligned (4))); -+ -+/* Pointers into RxDescList. */ -+static volatile struct USB_IN_Desc *myNextRxDesc; -+static volatile struct USB_IN_Desc *myLastRxDesc; -+ -+/* A zout transfer makes a memory access at the address of its buf pointer, -+ which means that setting this buf pointer to 0 will cause an access to the -+ flash. In addition to this, setting sw_len to 0 results in a 16/32 bytes -+ (depending on DMA burst size) transfer. -+ Instead, we set it to 1, and point it to this buffer. */ -+static int zout_buffer[4] __attribute__ ((aligned (4))); -+ -+/* Cache for allocating new EP and SB descriptors. */ -+//static kmem_cache_t *usb_desc_cache; -+static struct kmem_cache *usb_desc_cache; -+ -+/* Cache for the data allocated in the isoc descr top half. */ -+//static kmem_cache_t *isoc_compl_cache; -+static struct kmem_cache *isoc_compl_cache; -+ -+/* Cache for the data allocated when delayed finishing of URBs */ -+//static kmem_cache_t *later_data_cache; -+static struct kmem_cache *later_data_cache; -+ -+/* Counter to keep track of how many Isoc EP we have sat up. Used to enable -+ and disable iso_eof interrupt. We only need these interrupts when we have -+ Isoc data endpoints (consumes CPU cycles). -+ FIXME: This could be more fine granular, so this interrupt is only enabled -+ when we have a In Isoc URB not URB_ISO_ASAP flaged queued. */ -+static int isoc_epid_counter; -+ -+/* Protecting wrapper functions for R_USB_EPT_x */ -+/* -------------------------------------------- */ -+static inline void etrax_epid_set(__u8 index, __u32 data) { -+ unsigned long flags; -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index); -+ nop(); -+ *R_USB_EPT_DATA = data; -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+} -+ -+static inline void etrax_epid_clear_error(__u8 index) { -+ unsigned long flags; -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index); -+ nop(); -+ *R_USB_EPT_DATA &= -+ ~(IO_MASK(R_USB_EPT_DATA, error_count_in) | -+ IO_MASK(R_USB_EPT_DATA, error_count_out) | -+ IO_MASK(R_USB_EPT_DATA, error_code)); -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+} -+ -+static inline void etrax_epid_set_toggle(__u8 index, __u8 dirout, -+ __u8 toggle) { -+ unsigned long flags; -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index); -+ nop(); -+ if(dirout) { -+ *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_out); -+ *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_out, toggle); -+ } else { -+ *R_USB_EPT_DATA &= ~IO_MASK(R_USB_EPT_DATA, t_in); -+ *R_USB_EPT_DATA |= IO_FIELD(R_USB_EPT_DATA, t_in, toggle); -+ } -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+} -+ -+static inline __u8 etrax_epid_get_toggle(__u8 index, __u8 dirout) { -+ unsigned long flags; -+ __u8 toggle; -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index); -+ nop(); -+ if (dirout) { -+ toggle = IO_EXTRACT(R_USB_EPT_DATA, t_out, *R_USB_EPT_DATA); -+ } else { -+ toggle = IO_EXTRACT(R_USB_EPT_DATA, t_in, *R_USB_EPT_DATA); -+ } -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+ return toggle; -+} -+ -+ -+static inline __u32 etrax_epid_get(__u8 index) { -+ unsigned long flags; -+ __u32 data; -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, index); -+ nop(); -+ data = *R_USB_EPT_DATA; -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+ return data; -+} -+ -+ -+ -+ -+/* Main functions for Transfer Controller */ -+/* -------------------------------------- */ -+ -+/* Init structs, memories and lists used by Transfer Controller */ -+int tc_init(struct usb_hcd *hcd) { -+ int i; -+ /* Clear software state info for all epids */ -+ memset(epid_state, 0, sizeof(struct etrax_epid) * NBR_OF_EPIDS); -+ -+ /* Set Invalid and Dummy as being in use and disabled */ -+ epid_state[INVALID_EPID].inuse = 1; -+ epid_state[DUMMY_EPID].inuse = 1; -+ epid_state[INVALID_EPID].disabled = 1; -+ epid_state[DUMMY_EPID].disabled = 1; -+ -+ /* Clear counter for how many Isoc epids we have sat up */ -+ isoc_epid_counter = 0; -+ -+ /* Initialize the urb list by initiating a head for each list. -+ Also reset list hodling active URB for each epid */ -+ for (i = 0; i < NBR_OF_EPIDS; i++) { -+ INIT_LIST_HEAD(&urb_list[i]); -+ activeUrbList[i] = NULL; -+ } -+ -+ /* Init lock for URB lists */ -+ spin_lock_init(&urb_list_lock); -+ /* Init lock for Etrax R_USB_EPT register */ -+ spin_lock_init(&etrax_epid_lock); -+ /* Init lock for Etrax dma8 sub0 handling */ -+ spin_lock_init(&etrax_dma8_sub0_lock); -+ -+ /* We use kmem_cache_* to make sure that all DMA desc. are dword aligned */ -+ -+ /* Note that we specify sizeof(struct USB_EP_Desc) as the size, but also -+ allocate SB descriptors from this cache. This is ok since -+ sizeof(struct USB_EP_Desc) == sizeof(struct USB_SB_Desc). */ -+// usb_desc_cache = kmem_cache_create("usb_desc_cache", -+// sizeof(struct USB_EP_Desc), 0, -+// SLAB_HWCACHE_ALIGN, 0, 0); -+ usb_desc_cache = kmem_cache_create( -+ "usb_desc_cache", -+ sizeof(struct USB_EP_Desc), -+ 0, -+ SLAB_HWCACHE_ALIGN, -+ NULL); -+ if(usb_desc_cache == NULL) { -+ return -ENOMEM; -+ } -+ -+ /* Create slab cache for speedy allocation of memory for isoc bottom-half -+ interrupt handling */ -+// isoc_compl_cache = -+// kmem_cache_create("isoc_compl_cache", -+// sizeof(struct crisv10_isoc_complete_data), -+// 0, SLAB_HWCACHE_ALIGN, 0, 0); -+ isoc_compl_cache = kmem_cache_create( -+ "isoc_compl_cache", -+ sizeof(struct crisv10_isoc_complete_data), -+ 0, -+ SLAB_HWCACHE_ALIGN, -+ NULL -+ ); -+ -+ if(isoc_compl_cache == NULL) { -+ return -ENOMEM; -+ } -+ -+ /* Create slab cache for speedy allocation of memory for later URB finish -+ struct */ -+// later_data_cache = -+// kmem_cache_create("later_data_cache", -+// sizeof(struct urb_later_data), -+// 0, SLAB_HWCACHE_ALIGN, 0, 0); -+ -+ later_data_cache = kmem_cache_create( -+ "later_data_cache", -+ sizeof(struct urb_later_data), -+ 0, -+ SLAB_HWCACHE_ALIGN, -+ NULL -+ ); -+ -+ if(later_data_cache == NULL) { -+ return -ENOMEM; -+ } -+ -+ -+ /* Initiate the bulk start timer. */ -+ init_timer(&bulk_start_timer); -+ bulk_start_timer.expires = jiffies + BULK_START_TIMER_INTERVAL; -+ bulk_start_timer.function = tc_bulk_start_timer_func; -+ add_timer(&bulk_start_timer); -+ -+ -+ /* Initiate the bulk eot timer. */ -+ init_timer(&bulk_eot_timer); -+ bulk_eot_timer.expires = jiffies + BULK_EOT_TIMER_INTERVAL; -+ bulk_eot_timer.function = tc_bulk_eot_timer_func; -+ bulk_eot_timer.data = (unsigned long)hcd; -+ add_timer(&bulk_eot_timer); -+ -+ return 0; -+} -+ -+/* Uninitialize all resources used by Transfer Controller */ -+void tc_destroy(void) { -+ -+ /* Destroy all slab cache */ -+ kmem_cache_destroy(usb_desc_cache); -+ kmem_cache_destroy(isoc_compl_cache); -+ kmem_cache_destroy(later_data_cache); -+ -+ /* Remove timers */ -+ del_timer(&bulk_start_timer); -+ del_timer(&bulk_eot_timer); -+} -+ -+static void restart_dma8_sub0(void) { -+ unsigned long flags; -+ spin_lock_irqsave(&etrax_dma8_sub0_lock, flags); -+ /* Verify that the dma is not running */ -+ if ((*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd)) == 0) { -+ struct USB_EP_Desc *ep = (struct USB_EP_Desc *)phys_to_virt(*R_DMA_CH8_SUB0_EP); -+ while (DUMMY_EPID == IO_EXTRACT(USB_EP_command, epid, ep->command)) { -+ ep = (struct USB_EP_Desc *)phys_to_virt(ep->next); -+ } -+ /* Advance the DMA to the next EP descriptor that is not a DUMMY_EPID. -+ * ep->next is already a physical address. virt_to_phys is needed, see -+ * http://mhonarc.axis.se/dev-etrax/msg08630.html -+ */ -+ //*R_DMA_CH8_SUB0_EP = ep->next; -+ *R_DMA_CH8_SUB0_EP = virt_to_phys(ep); -+ /* Restart the DMA */ -+ *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); -+ } -+ spin_unlock_irqrestore(&etrax_dma8_sub0_lock, flags); -+} -+ -+/* queue an URB with the transfer controller (called from hcd_driver) */ -+//static int tc_urb_enqueue(struct usb_hcd *hcd, -+// struct usb_host_endpoint *ep, -+// struct urb *urb, -+// gfp_t mem_flags) { -+static int tc_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) -+{ -+ int epid; -+ int retval; -+// int bustime = 0; -+ int maxpacket; -+ unsigned long flags; -+ struct crisv10_urb_priv *urb_priv; -+ struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd); -+ DBFENTER; -+ -+ if(!(crisv10_hcd->running)) { -+ /* The USB Controller is not running, probably because no device is -+ attached. No idea to enqueue URBs then */ -+ tc_warn("Rejected enqueueing of URB:0x%x because no dev attached\n", -+ (unsigned int)urb); -+ return -ENOENT; -+ } -+ -+ maxpacket = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+ /* Special case check for In Isoc transfers. Specification states that each -+ In Isoc transfer consists of one packet and therefore it should fit into -+ the transfer-buffer of an URB. -+ We do the check here to be sure (an invalid scenario can be produced with -+ parameters to the usbtest suite) */ -+ if(usb_pipeisoc(urb->pipe) && usb_pipein(urb->pipe) && -+ (urb->transfer_buffer_length < maxpacket)) { -+ tc_err("Submit In Isoc URB with buffer length:%d to pipe with maxpacketlen: %d\n", urb->transfer_buffer_length, maxpacket); -+ return -EMSGSIZE; -+ } -+ -+ /* Check if there is enough bandwidth for periodic transfer */ -+ if(usb_pipeint(urb->pipe) || usb_pipeisoc(urb->pipe)) { -+ /* only check (and later claim) if not already claimed */ -+ if (urb->bandwidth == 0) { -+ bustime = usb_check_bandwidth(urb->dev, urb); -+ if (bustime < 0) { -+ tc_err("Not enough periodic bandwidth\n"); -+ return -ENOSPC; -+ } -+ } -+ } -+#endif -+ -+ /* Check if there is a epid for URBs destination, if not this function -+ set up one. */ -+ //epid = tc_setup_epid(ep, urb, mem_flags); -+ epid = tc_setup_epid(urb, mem_flags); -+ if (epid < 0) { -+ tc_err("Failed setup epid:%d for URB:0x%x\n", epid, (unsigned int)urb); -+ DBFEXIT; -+ return -ENOMEM; -+ } -+ -+ if(urb == activeUrbList[epid]) { -+ tc_err("Resubmition of allready active URB:0x%x\n", (unsigned int)urb); -+ return -ENXIO; -+ } -+ -+ if(urb_list_entry(urb, epid)) { -+ tc_err("Resubmition of allready queued URB:0x%x\n", (unsigned int)urb); -+ return -ENXIO; -+ } -+ -+ /* If we actively have flaged endpoint as disabled then refuse submition */ -+ if(epid_state[epid].disabled) { -+ return -ENOENT; -+ } -+ -+ /* Allocate and init HC-private data for URB */ -+ if(urb_priv_create(hcd, urb, epid, mem_flags) != 0) { -+ DBFEXIT; -+ return -ENOMEM; -+ } -+ urb_priv = urb->hcpriv; -+ -+ tc_dbg("Enqueue URB:0x%x[%d] epid:%d (%s) bufflen:%d\n", -+ (unsigned int)urb, urb_priv->urb_num, epid, -+ pipe_to_str(urb->pipe), urb->transfer_buffer_length); -+ -+ /* Create and link SBs required for this URB */ -+ retval = create_sb_for_urb(urb, mem_flags); -+ if(retval != 0) { -+ tc_err("Failed to create SBs for URB:0x%x[%d]\n", (unsigned int)urb, -+ urb_priv->urb_num); -+ urb_priv_free(hcd, urb); -+ DBFEXIT; -+ return retval; -+ } -+ -+ /* Init intr EP pool if this URB is a INTR transfer. This pool is later -+ used when inserting EPs in the TxIntrEPList. We do the alloc here -+ so we can't run out of memory later */ -+ if(usb_pipeint(urb->pipe)) { -+ retval = init_intr_urb(urb, mem_flags); -+ if(retval != 0) { -+ tc_warn("Failed to init Intr URB\n"); -+ urb_priv_free(hcd, urb); -+ DBFEXIT; -+ return retval; -+ } -+ } -+ -+ /* Disable other access when inserting USB */ -+ -+ /* BUG on sleeping inside int disabled if using local_irq_save/local_irq_restore -+ * her - because urb_list_add() and tc_dma_process_queue() save irqs again !??! -+ */ -+// local_irq_save(flags); -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+ /* Claim bandwidth, if needed */ -+ if(bustime) { -+ usb_claim_bandwidth(urb->dev, urb, bustime, 0); -+ } -+ -+ /* Add URB to EP queue */ -+ urb_list_add(urb, epid, mem_flags); -+ -+ if(usb_pipeisoc(urb->pipe)) { -+ /* Special processing of Isoc URBs. */ -+ tc_dma_process_isoc_urb(urb); -+ } else { -+ /* Process EP queue for rest of the URB types (Bulk, Ctrl, Intr) */ -+ tc_dma_process_queue(epid); -+ } -+#endif -+ /* Add URB to EP queue */ -+ urb_list_add(urb, epid, mem_flags); -+ -+ /*hinko link/unlink urb -> ep */ -+ spin_lock_irqsave(&crisv10_hcd->lock, flags); -+ //spin_lock(&crisv10_hcd->lock); -+ retval = usb_hcd_link_urb_to_ep(hcd, urb); -+ if (retval) { -+ spin_unlock_irqrestore(&crisv10_hcd->lock, flags); -+ tc_warn("Failed to link urb to ep\n"); -+ urb_priv_free(hcd, urb); -+ DBFEXIT; -+ return retval; -+ } -+ spin_unlock_irqrestore(&crisv10_hcd->lock, flags); -+ //spin_unlock(&crisv10_hcd->lock); -+ -+ /* Process EP queue for rest of the URB types (Bulk, Ctrl, Intr) */ -+ tc_dma_process_queue(epid); -+ -+// local_irq_restore(flags); -+ -+ DBFEXIT; -+ return 0; -+} -+ -+/* remove an URB from the transfer controller queues (called from hcd_driver)*/ -+//static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb) -+static int tc_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -+{ -+ struct crisv10_urb_priv *urb_priv; -+ unsigned long flags; -+ int epid; -+ -+ DBFENTER; -+ /* Disable interrupts here since a descriptor interrupt for the isoc epid -+ will modify the sb list. This could possibly be done more granular, but -+ urb_dequeue should not be used frequently anyway. -+ */ -+ local_irq_save(flags); -+ -+ urb_priv = urb->hcpriv; -+ -+ if (!urb_priv) { -+ /* This happens if a device driver calls unlink on an urb that -+ was never submitted (lazy driver) or if the urb was completed -+ while dequeue was being called. */ -+ tc_warn("Dequeing of not enqueued URB:0x%x\n", (unsigned int)urb); -+ local_irq_restore(flags); -+ return 0; -+ } -+ epid = urb_priv->epid; -+ -+ tc_warn("Dequeing %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n", -+ (urb == activeUrbList[epid]) ? "active" : "queued", -+ (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), epid, urb->status, -+ (urb_priv->later_data) ? "later-sched" : ""); -+ -+ /* For Bulk, Ctrl and Intr are only one URB active at a time. So any URB -+ that isn't active can be dequeued by just removing it from the queue */ -+ if(usb_pipebulk(urb->pipe) || usb_pipecontrol(urb->pipe) || -+ usb_pipeint(urb->pipe)) { -+ -+ /* Check if URB haven't gone further than the queue */ -+ if(urb != activeUrbList[epid]) { -+ ASSERT(urb_priv->later_data == NULL); -+ tc_warn("Dequeing URB:0x%x[%d] (%s %s epid:%d) from queue" -+ " (not active)\n", (unsigned int)urb, urb_priv->urb_num, -+ str_dir(urb->pipe), str_type(urb->pipe), epid); -+ -+ /* Finish the URB with error status from USB core */ -+ tc_finish_urb(hcd, urb, urb->status); -+ local_irq_restore(flags); -+ return 0; -+ } -+ } -+ -+ /* Set URB status to Unlink for handling when interrupt comes. */ -+ urb_priv->urb_state = UNLINK; -+ -+ /* Differentiate dequeing of Bulk and Ctrl from Isoc and Intr */ -+ switch(usb_pipetype(urb->pipe)) { -+ case PIPE_BULK: -+ /* Check if EP still is enabled */ -+ if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ /* The EP was enabled, disable it. */ -+ TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ } -+ /* Kicking dummy list out of the party. */ -+ TxBulkEPList[epid].next = virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]); -+ break; -+ case PIPE_CONTROL: -+ /* Check if EP still is enabled */ -+ if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ /* The EP was enabled, disable it. */ -+ TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ } -+ break; -+ case PIPE_ISOCHRONOUS: -+ /* Disabling, busy-wait and unlinking of Isoc SBs will be done in -+ finish_isoc_urb(). Because there might the case when URB is dequeued -+ but there are other valid URBs waiting */ -+ -+ /* Check if In Isoc EP still is enabled */ -+ if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ /* The EP was enabled, disable it. */ -+ TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ } -+ break; -+ case PIPE_INTERRUPT: -+ /* Special care is taken for interrupt URBs. EPs are unlinked in -+ tc_finish_urb */ -+ break; -+ default: -+ break; -+ } -+ -+ /* Asynchronous unlink, finish the URB later from scheduled or other -+ event (data finished, error) */ -+ tc_finish_urb_later(hcd, urb, urb->status); -+ -+ local_irq_restore(flags); -+ DBFEXIT; -+ return 0; -+} -+ -+ -+static void tc_sync_finish_epid(struct usb_hcd *hcd, int epid) { -+ volatile int timeout = 10000; -+ struct urb* urb; -+ struct crisv10_urb_priv* urb_priv; -+ unsigned long flags; -+ -+ volatile struct USB_EP_Desc *first_ep; /* First EP in the list. */ -+ volatile struct USB_EP_Desc *curr_ep; /* Current EP, the iterator. */ -+ volatile struct USB_EP_Desc *next_ep; /* The EP after current. */ -+ -+ int type = epid_state[epid].type; -+ -+ /* Setting this flag will cause enqueue() to return -ENOENT for new -+ submitions on this endpoint and finish_urb() wont process queue further */ -+ epid_state[epid].disabled = 1; -+ -+ switch(type) { -+ case PIPE_BULK: -+ /* Check if EP still is enabled */ -+ if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ /* The EP was enabled, disable it. */ -+ TxBulkEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ tc_warn("sync_finish: Disabling EP for epid:%d\n", epid); -+ -+ /* Do busy-wait until DMA not using this EP descriptor anymore */ -+ while((*R_DMA_CH8_SUB0_EP == -+ virt_to_phys(&TxBulkEPList[epid])) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for DMA-TX-Bulk to leave EP for" -+ " epid:%d\n", epid); -+ } -+ } -+ break; -+ -+ case PIPE_CONTROL: -+ /* Check if EP still is enabled */ -+ if (TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ /* The EP was enabled, disable it. */ -+ TxCtrlEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ tc_warn("sync_finish: Disabling EP for epid:%d\n", epid); -+ -+ /* Do busy-wait until DMA not using this EP descriptor anymore */ -+ while((*R_DMA_CH8_SUB1_EP == -+ virt_to_phys(&TxCtrlEPList[epid])) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for DMA-TX-Ctrl to leave EP for" -+ " epid:%d\n", epid); -+ } -+ } -+ break; -+ -+ case PIPE_INTERRUPT: -+ local_irq_save(flags); -+ /* Disable all Intr EPs belonging to epid */ -+ first_ep = &TxIntrEPList[0]; -+ curr_ep = first_ep; -+ do { -+ next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next); -+ if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) { -+ /* Disable EP */ -+ next_ep->command &= ~IO_MASK(USB_EP_command, enable); -+ } -+ curr_ep = phys_to_virt(curr_ep->next); -+ } while (curr_ep != first_ep); -+ -+ local_irq_restore(flags); -+ break; -+ -+ case PIPE_ISOCHRONOUS: -+ /* Check if EP still is enabled */ -+ if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ tc_warn("sync_finish: Disabling Isoc EP for epid:%d\n", epid); -+ /* The EP was enabled, disable it. */ -+ TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ -+ while((*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for DMA-TX-Isoc to leave EP for" -+ " epid:%d\n", epid); -+ } -+ } -+ break; -+ } -+ -+ local_irq_save(flags); -+ -+ /* Finish if there is active URB for this endpoint */ -+ if(activeUrbList[epid] != NULL) { -+ urb = activeUrbList[epid]; -+ urb_priv = urb->hcpriv; -+ ASSERT(urb_priv); -+ tc_warn("Sync finish %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n", -+ (urb == activeUrbList[epid]) ? "active" : "queued", -+ (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), epid, urb->status, -+ (urb_priv->later_data) ? "later-sched" : ""); -+ -+ tc_finish_urb(hcd, activeUrbList[epid], -ENOENT); -+ ASSERT(activeUrbList[epid] == NULL); -+ } -+ -+ /* Finish any queued URBs for this endpoint. There won't be any resubmitions -+ because epid_disabled causes enqueue() to fail for this endpoint */ -+ while((urb = urb_list_first(epid)) != NULL) { -+ urb_priv = urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ tc_warn("Sync finish %s URB:0x%x[%d] (%s %s epid:%d) status:%d %s\n", -+ (urb == activeUrbList[epid]) ? "active" : "queued", -+ (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), epid, urb->status, -+ (urb_priv->later_data) ? "later-sched" : ""); -+ -+ tc_finish_urb(hcd, urb, -ENOENT); -+ } -+ epid_state[epid].disabled = 0; -+ local_irq_restore(flags); -+} -+ -+/* free resources associated with an endpoint (called from hcd_driver) */ -+static void tc_endpoint_disable(struct usb_hcd *hcd, -+ struct usb_host_endpoint *ep) { -+ DBFENTER; -+ /* Only free epid if it has been allocated. We get two endpoint_disable -+ requests for ctrl endpoints so ignore the second one */ -+ if(ep->hcpriv != NULL) { -+ struct crisv10_ep_priv *ep_priv = ep->hcpriv; -+ int epid = ep_priv->epid; -+ tc_warn("endpoint_disable ep:0x%x ep-priv:0x%x (%s) (epid:%d freed)\n", -+ (unsigned int)ep, (unsigned int)ep->hcpriv, -+ endpoint_to_str(&(ep->desc)), epid); -+ -+ tc_sync_finish_epid(hcd, epid); -+ -+ ASSERT(activeUrbList[epid] == NULL); -+ ASSERT(list_empty(&urb_list[epid])); -+ -+ tc_free_epid(ep); -+ } else { -+ tc_dbg("endpoint_disable ep:0x%x ep-priv:0x%x (%s)\n", (unsigned int)ep, -+ (unsigned int)ep->hcpriv, endpoint_to_str(&(ep->desc))); -+ } -+ DBFEXIT; -+} -+ -+//static void tc_finish_urb_later_proc(void *data) { -+static void tc_finish_urb_later_proc(struct work_struct *work) { -+ unsigned long flags; -+ //struct urb_later_data* uld = (struct urb_later_data*)data; -+ struct urb_later_data* uld = container_of(work, struct urb_later_data, ws.work); -+ local_irq_save(flags); -+ if(uld->urb == NULL) { -+ late_dbg("Later finish of URB = NULL (allready finished)\n"); -+ } else { -+ struct crisv10_urb_priv* urb_priv = uld->urb->hcpriv; -+ ASSERT(urb_priv); -+ if(urb_priv->urb_num == uld->urb_num) { -+ late_dbg("Later finish of URB:0x%x[%d]\n", (unsigned int)(uld->urb), -+ urb_priv->urb_num); -+ if(uld->status != uld->urb->status) { -+ errno_dbg("Later-finish URB with status:%d, later-status:%d\n", -+ uld->urb->status, uld->status); -+ } -+ if(uld != urb_priv->later_data) { -+ panic("Scheduled uld not same as URBs uld\n"); -+ } -+ tc_finish_urb(uld->hcd, uld->urb, uld->status); -+ } else { -+ late_warn("Ignoring later finish of URB:0x%x[%d]" -+ ", urb_num doesn't match current URB:0x%x[%d]", -+ (unsigned int)(uld->urb), uld->urb_num, -+ (unsigned int)(uld->urb), urb_priv->urb_num); -+ } -+ } -+ local_irq_restore(flags); -+ kmem_cache_free(later_data_cache, uld); -+} -+ -+static void tc_finish_urb_later(struct usb_hcd *hcd, struct urb *urb, -+ int status) { -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ struct urb_later_data* uld; -+ -+ ASSERT(urb_priv); -+ -+ if(urb_priv->later_data != NULL) { -+ /* Later-finish allready scheduled for this URB, just update status to -+ return when finishing later */ -+ errno_dbg("Later-finish schedule change URB status:%d with new" -+ " status:%d\n", urb_priv->later_data->status, status); -+ -+ urb_priv->later_data->status = status; -+ return; -+ } -+ -+ uld = kmem_cache_alloc(later_data_cache, GFP_ATOMIC); -+ ASSERT(uld); -+ -+ uld->hcd = hcd; -+ uld->urb = urb; -+ uld->urb_num = urb_priv->urb_num; -+ uld->status = status; -+ -+ //INIT_WORK(&uld->ws, tc_finish_urb_later_proc, uld); -+ INIT_DELAYED_WORK(&uld->ws, tc_finish_urb_later_proc); -+ urb_priv->later_data = uld; -+ -+ /* Schedule the finishing of the URB to happen later */ -+ schedule_delayed_work(&uld->ws, LATER_TIMER_DELAY); -+} -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+static void tc_finish_isoc_urb(struct usb_hcd *hcd, struct urb *urb, -+ int status); -+#endif -+ -+static void tc_finish_urb(struct usb_hcd *hcd, struct urb *urb, int status) { -+ struct crisv10_hcd* crisv10_hcd = hcd_to_crisv10_hcd(hcd); -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ int epid; -+ char toggle; -+ int urb_num; -+ -+ DBFENTER; -+ ASSERT(urb_priv != NULL); -+ epid = urb_priv->epid; -+ urb_num = urb_priv->urb_num; -+ -+ if(urb != activeUrbList[epid]) { -+ if(urb_list_entry(urb, epid)) { -+ /* Remove this URB from the list. Only happens when URB are finished -+ before having been processed (dequeing) */ -+ urb_list_del(urb, epid); -+ } else { -+ tc_warn("Finishing of URB:0x%x[%d] neither active or in queue for" -+ " epid:%d\n", (unsigned int)urb, urb_num, epid); -+ } -+ } -+ -+ /* Cancel any pending later-finish of this URB */ -+ if(urb_priv->later_data) { -+ urb_priv->later_data->urb = NULL; -+ } -+ -+ /* For an IN pipe, we always set the actual length, regardless of whether -+ there was an error or not (which means the device driver can use the data -+ if it wants to). */ -+ if(usb_pipein(urb->pipe)) { -+ urb->actual_length = urb_priv->rx_offset; -+ } else { -+ /* Set actual_length for OUT urbs also; the USB mass storage driver seems -+ to want that. */ -+ if (status == 0 && urb->status == -EINPROGRESS) { -+ urb->actual_length = urb->transfer_buffer_length; -+ } else { -+ /* We wouldn't know of any partial writes if there was an error. */ -+ urb->actual_length = 0; -+ } -+ } -+ -+ -+ /* URB status mangling */ -+ if(urb->status == -EINPROGRESS) { -+ /* The USB core hasn't changed the status, let's set our finish status */ -+ urb->status = status; -+ -+ if ((status == 0) && (urb->transfer_flags & URB_SHORT_NOT_OK) && -+ usb_pipein(urb->pipe) && -+ (urb->actual_length != urb->transfer_buffer_length)) { -+ /* URB_SHORT_NOT_OK means that short reads (shorter than the endpoint's -+ max length) is to be treated as an error. */ -+ errno_dbg("Finishing URB:0x%x[%d] with SHORT_NOT_OK flag and short" -+ " data:%d\n", (unsigned int)urb, urb_num, -+ urb->actual_length); -+ urb->status = -EREMOTEIO; -+ } -+ -+ if(urb_priv->urb_state == UNLINK) { -+ /* URB has been requested to be unlinked asynchronously */ -+ urb->status = -ECONNRESET; -+ errno_dbg("Fixing unlink status of URB:0x%x[%d] to:%d\n", -+ (unsigned int)urb, urb_num, urb->status); -+ } -+ } else { -+ /* The USB Core wants to signal some error via the URB, pass it through */ -+ } -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+ /* use completely different finish function for Isoc URBs */ -+ if(usb_pipeisoc(urb->pipe)) { -+ tc_finish_isoc_urb(hcd, urb, status); -+ return; -+ } -+#endif -+ -+ /* Do special unlinking of EPs for Intr traffic */ -+ if(usb_pipeint(urb->pipe)) { -+ tc_dma_unlink_intr_urb(urb); -+ } -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+ /* Release allocated bandwidth for periodic transfers */ -+ if(usb_pipeint(urb->pipe) || usb_pipeisoc(urb->pipe)) -+ usb_release_bandwidth(urb->dev, urb, 0); -+#endif -+ -+ /* This URB is active on EP */ -+ if(urb == activeUrbList[epid]) { -+ /* We need to fiddle with the toggle bits because the hardware doesn't do -+ it for us. */ -+ toggle = etrax_epid_get_toggle(epid, usb_pipeout(urb->pipe)); -+ usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe), toggle); -+ -+ /* Checks for Ctrl and Bulk EPs */ -+ switch(usb_pipetype(urb->pipe)) { -+ case PIPE_BULK: -+ /* Check so Bulk EP realy is disabled before finishing active URB */ -+ ASSERT((TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) == -+ IO_STATE(USB_EP_command, enable, no)); -+ /* Disable sub-pointer for EP to avoid next tx_interrupt() to -+ process Bulk EP. */ -+ TxBulkEPList[epid].sub = 0; -+ /* No need to wait for the DMA before changing the next pointer. -+ The modulo NBR_OF_EPIDS isn't actually necessary, since we will never use -+ the last one (INVALID_EPID) for actual traffic. */ -+ TxBulkEPList[epid].next = -+ virt_to_phys(&TxBulkEPList[(epid + 1) % NBR_OF_EPIDS]); -+ break; -+ case PIPE_CONTROL: -+ /* Check so Ctrl EP realy is disabled before finishing active URB */ -+ ASSERT((TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) == -+ IO_STATE(USB_EP_command, enable, no)); -+ /* Disable sub-pointer for EP to avoid next tx_interrupt() to -+ process Ctrl EP. */ -+ TxCtrlEPList[epid].sub = 0; -+ break; -+ } -+ } -+ -+ /* Free HC-private URB data*/ -+ urb_priv_free(hcd, urb); -+ -+ if(urb->status) { -+ errno_dbg("finish_urb (URB:0x%x[%d] %s %s) (data:%d) status:%d\n", -+ (unsigned int)urb, urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), urb->actual_length, urb->status); -+ } else { -+ tc_dbg("finish_urb (URB:0x%x[%d] %s %s) (data:%d) status:%d\n", -+ (unsigned int)urb, urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), urb->actual_length, urb->status); -+ } -+ -+ /* If we just finished an active URB, clear active pointer. */ -+ if (urb == activeUrbList[epid]) { -+ /* Make URB not active on EP anymore */ -+ activeUrbList[epid] = NULL; -+ -+ if(urb->status == 0) { -+ /* URB finished sucessfully, process queue to see if there are any more -+ URBs waiting before we call completion function.*/ -+ if(crisv10_hcd->running) { -+ /* Only process queue if USB controller is running */ -+ tc_dma_process_queue(epid); -+ } else { -+ tc_warn("No processing of queue for epid:%d, USB Controller not" -+ " running\n", epid); -+ } -+ } -+ } -+ -+ /* Hand the URB from HCD to its USB device driver, using its completion -+ functions */ -+// usb_hcd_giveback_urb (hcd, urb); -+ /** -+ * usb_hcd_unlink_urb_from_ep - remove an URB from its endpoint queue -+ * @hcd: host controller to which @urb was submitted -+ * @urb: URB being unlinked -+ * -+ * Host controller drivers should call this routine before calling -+ * usb_hcd_giveback_urb(). The HCD's private spinlock must be held and -+ * interrupts must be disabled. The actions carried out here are required -+ * for URB completion. -+ */ -+ -+ /*hinko link/unlink urb -> ep */ -+ //spin_lock(&crisv10_hcd->lock); -+ unsigned long flags; -+ spin_lock_irqsave(&crisv10_hcd->lock, flags); -+ usb_hcd_unlink_urb_from_ep(hcd, urb); -+ usb_hcd_giveback_urb(hcd, urb, status); -+ //spin_unlock(&crisv10_hcd->lock); -+ spin_unlock_irqrestore(&crisv10_hcd->lock, flags); -+ -+ /* Check the queue once more if the URB returned with error, because we -+ didn't do it before the completion function because the specification -+ states that the queue should not restart until all it's unlinked -+ URBs have been fully retired, with the completion functions run */ -+ if(crisv10_hcd->running) { -+ /* Only process queue if USB controller is running */ -+ tc_dma_process_queue(epid); -+ } else { -+ tc_warn("No processing of queue for epid:%d, USB Controller not running\n", -+ epid); -+ } -+ -+ DBFEXIT; -+} -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+static void tc_finish_isoc_urb(struct usb_hcd *hcd, struct urb *urb, -+ int status) { -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ int epid, i; -+ volatile int timeout = 10000; -+ -+ ASSERT(urb_priv); -+ epid = urb_priv->epid; -+ -+ ASSERT(usb_pipeisoc(urb->pipe)); -+ -+ /* Set that all isoc packets have status and length set before -+ completing the urb. */ -+ for (i = urb_priv->isoc_packet_counter; i < urb->number_of_packets; i++){ -+ urb->iso_frame_desc[i].actual_length = 0; -+ urb->iso_frame_desc[i].status = -EPROTO; -+ } -+ -+ /* Check if the URB is currently active (done or error) */ -+ if(urb == activeUrbList[epid]) { -+ /* Check if there are another In Isoc URB queued for this epid */ -+ if (!list_empty(&urb_list[epid])&& !epid_state[epid].disabled) { -+ /* Move it from queue to active and mark it started so Isoc transfers -+ won't be interrupted. -+ All Isoc URBs data transfers are already added to DMA lists so we -+ don't have to insert anything in DMA lists here. */ -+ activeUrbList[epid] = urb_list_first(epid); -+ ((struct crisv10_urb_priv *)(activeUrbList[epid]->hcpriv))->urb_state = -+ STARTED; -+ urb_list_del(activeUrbList[epid], epid); -+ -+ if(urb->status) { -+ errno_dbg("finish_isoc_urb (URB:0x%x[%d] %s %s) (%d of %d packets)" -+ " status:%d, new waiting URB:0x%x[%d]\n", -+ (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), urb_priv->isoc_packet_counter, -+ urb->number_of_packets, urb->status, -+ (unsigned int)activeUrbList[epid], -+ ((struct crisv10_urb_priv *)(activeUrbList[epid]->hcpriv))->urb_num); -+ } -+ -+ } else { /* No other URB queued for this epid */ -+ if(urb->status) { -+ errno_dbg("finish_isoc_urb (URB:0x%x[%d] %s %s) (%d of %d packets)" -+ " status:%d, no new URB waiting\n", -+ (unsigned int)urb, urb_priv->urb_num, str_dir(urb->pipe), -+ str_type(urb->pipe), urb_priv->isoc_packet_counter, -+ urb->number_of_packets, urb->status); -+ } -+ -+ /* Check if EP is still enabled, then shut it down. */ -+ if (TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ isoc_dbg("Isoc EP enabled for epid:%d, disabling it\n", epid); -+ -+ /* Should only occur for In Isoc EPs where SB isn't consumed. */ -+ ASSERT(usb_pipein(urb->pipe)); -+ -+ /* Disable it and wait for it to stop */ -+ TxIsocEPList[epid].command &= ~IO_MASK(USB_EP_command, enable); -+ -+ /* Ah, the luxury of busy-wait. */ -+ while((*R_DMA_CH8_SUB3_EP == virt_to_phys(&TxIsocEPList[epid])) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for DMA-TX-Isoc to leave EP for epid:%d\n", epid); -+ } -+ } -+ -+ /* Unlink SB to say that epid is finished. */ -+ TxIsocEPList[epid].sub = 0; -+ TxIsocEPList[epid].hw_len = 0; -+ -+ /* No URB active for EP anymore */ -+ activeUrbList[epid] = NULL; -+ } -+ } else { /* Finishing of not active URB (queued up with SBs thought) */ -+ isoc_warn("finish_isoc_urb (URB:0x%x %s) (%d of %d packets) status:%d," -+ " SB queued but not active\n", -+ (unsigned int)urb, str_dir(urb->pipe), -+ urb_priv->isoc_packet_counter, urb->number_of_packets, -+ urb->status); -+ if(usb_pipeout(urb->pipe)) { -+ /* Finishing of not yet active Out Isoc URB needs unlinking of SBs. */ -+ struct USB_SB_Desc *iter_sb, *prev_sb, *next_sb; -+ -+ iter_sb = TxIsocEPList[epid].sub ? -+ phys_to_virt(TxIsocEPList[epid].sub) : 0; -+ prev_sb = 0; -+ -+ /* SB that is linked before this URBs first SB */ -+ while (iter_sb && (iter_sb != urb_priv->first_sb)) { -+ prev_sb = iter_sb; -+ iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; -+ } -+ -+ if (iter_sb == 0) { -+ /* Unlink of the URB currently being transmitted. */ -+ prev_sb = 0; -+ iter_sb = TxIsocEPList[epid].sub ? phys_to_virt(TxIsocEPList[epid].sub) : 0; -+ } -+ -+ while (iter_sb && (iter_sb != urb_priv->last_sb)) { -+ iter_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; -+ } -+ -+ if (iter_sb) { -+ next_sb = iter_sb->next ? phys_to_virt(iter_sb->next) : 0; -+ } else { -+ /* This should only happen if the DMA has completed -+ processing the SB list for this EP while interrupts -+ are disabled. */ -+ isoc_dbg("Isoc urb not found, already sent?\n"); -+ next_sb = 0; -+ } -+ if (prev_sb) { -+ prev_sb->next = next_sb ? virt_to_phys(next_sb) : 0; -+ } else { -+ TxIsocEPList[epid].sub = next_sb ? virt_to_phys(next_sb) : 0; -+ } -+ } -+ } -+ -+ /* Free HC-private URB data*/ -+ urb_priv_free(hcd, urb); -+ -+ usb_release_bandwidth(urb->dev, urb, 0); -+ -+ /* Hand the URB from HCD to its USB device driver, using its completion -+ functions */ -+ usb_hcd_giveback_urb (hcd, urb); -+} -+#endif -+ -+static __u32 urb_num = 0; -+ -+/* allocate and initialize URB private data */ -+static int urb_priv_create(struct usb_hcd *hcd, struct urb *urb, int epid, -+ int mem_flags) { -+ struct crisv10_urb_priv *urb_priv; -+ -+ urb_priv = kmalloc(sizeof *urb_priv, mem_flags); -+ if (!urb_priv) -+ return -ENOMEM; -+ memset(urb_priv, 0, sizeof *urb_priv); -+ -+ urb_priv->epid = epid; -+ urb_priv->urb_state = NOT_STARTED; -+ -+ urb->hcpriv = urb_priv; -+ /* Assign URB a sequence number, and increment counter */ -+ urb_priv->urb_num = urb_num; -+ urb_num++; -+ return 0; -+} -+ -+/* free URB private data */ -+static void urb_priv_free(struct usb_hcd *hcd, struct urb *urb) { -+ int i; -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ ASSERT(urb_priv != 0); -+ -+ /* Check it has any SBs linked that needs to be freed*/ -+ if(urb_priv->first_sb != NULL) { -+ struct USB_SB_Desc *next_sb, *first_sb, *last_sb; -+ int i = 0; -+ first_sb = urb_priv->first_sb; -+ last_sb = urb_priv->last_sb; -+ ASSERT(last_sb); -+ while(first_sb != last_sb) { -+ next_sb = (struct USB_SB_Desc *)phys_to_virt(first_sb->next); -+ kmem_cache_free(usb_desc_cache, first_sb); -+ first_sb = next_sb; -+ i++; -+ } -+ kmem_cache_free(usb_desc_cache, last_sb); -+ i++; -+ } -+ -+ /* Check if it has any EPs in its Intr pool that also needs to be freed */ -+ if(urb_priv->intr_ep_pool_length > 0) { -+ for(i = 0; i < urb_priv->intr_ep_pool_length; i++) { -+ kfree(urb_priv->intr_ep_pool[i]); -+ } -+ /* -+ tc_dbg("Freed %d EPs from URB:0x%x EP pool\n", -+ urb_priv->intr_ep_pool_length, (unsigned int)urb); -+ */ -+ } -+ -+ kfree(urb_priv); -+ urb->hcpriv = NULL; -+} -+ -+static int ep_priv_create(struct usb_host_endpoint *ep, int mem_flags) { -+ struct crisv10_ep_priv *ep_priv; -+ -+ ep_priv = kmalloc(sizeof *ep_priv, mem_flags); -+ if (!ep_priv) -+ return -ENOMEM; -+ memset(ep_priv, 0, sizeof *ep_priv); -+ -+ ep->hcpriv = ep_priv; -+ return 0; -+} -+ -+static void ep_priv_free(struct usb_host_endpoint *ep) { -+ struct crisv10_ep_priv *ep_priv = ep->hcpriv; -+ ASSERT(ep_priv); -+ kfree(ep_priv); -+ ep->hcpriv = NULL; -+} -+ -+/* EPID handling functions, managing EP-list in Etrax through wrappers */ -+/* ------------------------------------------------------------------- */ -+ -+/* Sets up a new EPID for an endpoint or returns existing if found */ -+//static int tc_setup_epid(struct usb_host_endpoint *ep, struct urb *urb, -+// int mem_flags) { -+static int tc_setup_epid(struct urb *urb, int mem_flags) -+{ -+ int epid; -+ char devnum, endpoint, out_traffic, slow; -+ int maxlen; -+ __u32 epid_data; -+ struct usb_host_endpoint *ep = urb->ep; -+ struct crisv10_ep_priv *ep_priv = ep->hcpriv; -+ -+ DBFENTER; -+ -+ /* Check if a valid epid already is setup for this endpoint */ -+ if(ep_priv != NULL) { -+ return ep_priv->epid; -+ } -+ -+ /* We must find and initiate a new epid for this urb. */ -+ epid = tc_allocate_epid(); -+ -+ if (epid == -1) { -+ /* Failed to allocate a new epid. */ -+ DBFEXIT; -+ return epid; -+ } -+ -+ /* We now have a new epid to use. Claim it. */ -+ epid_state[epid].inuse = 1; -+ -+ /* Init private data for new endpoint */ -+ if(ep_priv_create(ep, mem_flags) != 0) { -+ return -ENOMEM; -+ } -+ ep_priv = ep->hcpriv; -+ ep_priv->epid = epid; -+ -+ devnum = usb_pipedevice(urb->pipe); -+ endpoint = usb_pipeendpoint(urb->pipe); -+ slow = (urb->dev->speed == USB_SPEED_LOW); -+ maxlen = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); -+ -+ if (usb_pipetype(urb->pipe) == PIPE_CONTROL) { -+ /* We want both IN and OUT control traffic to be put on the same -+ EP/SB list. */ -+ out_traffic = 1; -+ } else { -+ out_traffic = usb_pipeout(urb->pipe); -+ } -+ -+ if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { -+ epid_data = IO_STATE(R_USB_EPT_DATA_ISO, valid, yes) | -+ /* FIXME: Change any to the actual port? */ -+ IO_STATE(R_USB_EPT_DATA_ISO, port, any) | -+ IO_FIELD(R_USB_EPT_DATA_ISO, max_len, maxlen) | -+ IO_FIELD(R_USB_EPT_DATA_ISO, ep, endpoint) | -+ IO_FIELD(R_USB_EPT_DATA_ISO, dev, devnum); -+ etrax_epid_iso_set(epid, epid_data); -+ } else { -+ epid_data = IO_STATE(R_USB_EPT_DATA, valid, yes) | -+ IO_FIELD(R_USB_EPT_DATA, low_speed, slow) | -+ /* FIXME: Change any to the actual port? */ -+ IO_STATE(R_USB_EPT_DATA, port, any) | -+ IO_FIELD(R_USB_EPT_DATA, max_len, maxlen) | -+ IO_FIELD(R_USB_EPT_DATA, ep, endpoint) | -+ IO_FIELD(R_USB_EPT_DATA, dev, devnum); -+ etrax_epid_set(epid, epid_data); -+ } -+ -+ epid_state[epid].out_traffic = out_traffic; -+ epid_state[epid].type = usb_pipetype(urb->pipe); -+ -+ tc_warn("Setting up ep:0x%x epid:%d (addr:%d endp:%d max_len:%d %s %s %s)\n", -+ (unsigned int)ep, epid, devnum, endpoint, maxlen, -+ str_type(urb->pipe), out_traffic ? "out" : "in", -+ slow ? "low" : "full"); -+ -+ /* Enable Isoc eof interrupt if we set up the first Isoc epid */ -+ if(usb_pipeisoc(urb->pipe)) { -+ isoc_epid_counter++; -+ if(isoc_epid_counter == 1) { -+ isoc_warn("Enabled Isoc eof interrupt\n"); -+ *R_USB_IRQ_MASK_SET |= IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set); -+ } -+ } -+ -+ DBFEXIT; -+ return epid; -+} -+ -+static void tc_free_epid(struct usb_host_endpoint *ep) { -+ unsigned long flags; -+ struct crisv10_ep_priv *ep_priv = ep->hcpriv; -+ int epid; -+ volatile int timeout = 10000; -+ -+ DBFENTER; -+ -+ if (ep_priv == NULL) { -+ tc_warn("Trying to free unused epid on ep:0x%x\n", (unsigned int)ep); -+ DBFEXIT; -+ return; -+ } -+ -+ epid = ep_priv->epid; -+ -+ /* Disable Isoc eof interrupt if we free the last Isoc epid */ -+ if(epid_isoc(epid)) { -+ ASSERT(isoc_epid_counter > 0); -+ isoc_epid_counter--; -+ if(isoc_epid_counter == 0) { -+ *R_USB_IRQ_MASK_SET &= ~IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set); -+ isoc_warn("Disabled Isoc eof interrupt\n"); -+ } -+ } -+ -+ /* Take lock manualy instead of in epid_x_x wrappers, -+ because we need to be polling here */ -+ spin_lock_irqsave(&etrax_epid_lock, flags); -+ -+ *R_USB_EPT_INDEX = IO_FIELD(R_USB_EPT_INDEX, value, epid); -+ nop(); -+ while((*R_USB_EPT_DATA & IO_MASK(R_USB_EPT_DATA, hold)) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for epid:%d to drop hold\n", epid); -+ } -+ /* This will, among other things, set the valid field to 0. */ -+ *R_USB_EPT_DATA = 0; -+ spin_unlock_irqrestore(&etrax_epid_lock, flags); -+ -+ /* Free resource in software state info list */ -+ epid_state[epid].inuse = 0; -+ -+ /* Free private endpoint data */ -+ ep_priv_free(ep); -+ -+ DBFEXIT; -+} -+ -+static int tc_allocate_epid(void) { -+ int i; -+ DBFENTER; -+ for (i = 0; i < NBR_OF_EPIDS; i++) { -+ if (!epid_inuse(i)) { -+ DBFEXIT; -+ return i; -+ } -+ } -+ -+ tc_warn("Found no free epids\n"); -+ DBFEXIT; -+ return -1; -+} -+ -+ -+/* Wrappers around the list functions (include/linux/list.h). */ -+/* ---------------------------------------------------------- */ -+static inline int __urb_list_empty(int epid) { -+ int retval; -+ retval = list_empty(&urb_list[epid]); -+ return retval; -+} -+ -+/* Returns first urb for this epid, or NULL if list is empty. */ -+static inline struct urb *urb_list_first(int epid) { -+ unsigned long flags; -+ struct urb *first_urb = 0; -+ spin_lock_irqsave(&urb_list_lock, flags); -+ if (!__urb_list_empty(epid)) { -+ /* Get the first urb (i.e. head->next). */ -+ urb_entry_t *urb_entry = list_entry((&urb_list[epid])->next, urb_entry_t, list); -+ first_urb = urb_entry->urb; -+ } -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+ return first_urb; -+} -+ -+/* Adds an urb_entry last in the list for this epid. */ -+static inline void urb_list_add(struct urb *urb, int epid, int mem_flags) { -+ unsigned long flags; -+ urb_entry_t *urb_entry = (urb_entry_t *)kmalloc(sizeof(urb_entry_t), mem_flags); -+ ASSERT(urb_entry); -+ -+ urb_entry->urb = urb; -+ spin_lock_irqsave(&urb_list_lock, flags); -+ list_add_tail(&urb_entry->list, &urb_list[epid]); -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+} -+ -+/* Search through the list for an element that contains this urb. (The list -+ is expected to be short and the one we are about to delete will often be -+ the first in the list.) -+ Should be protected by spin_locks in calling function */ -+static inline urb_entry_t *__urb_list_entry(struct urb *urb, int epid) { -+ struct list_head *entry; -+ struct list_head *tmp; -+ urb_entry_t *urb_entry; -+ -+ list_for_each_safe(entry, tmp, &urb_list[epid]) { -+ urb_entry = list_entry(entry, urb_entry_t, list); -+ ASSERT(urb_entry); -+ ASSERT(urb_entry->urb); -+ -+ if (urb_entry->urb == urb) { -+ return urb_entry; -+ } -+ } -+ return 0; -+} -+ -+/* Same function as above but for global use. Protects list by spinlock */ -+static inline urb_entry_t *urb_list_entry(struct urb *urb, int epid) { -+ unsigned long flags; -+ urb_entry_t *urb_entry; -+ spin_lock_irqsave(&urb_list_lock, flags); -+ urb_entry = __urb_list_entry(urb, epid); -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+ return (urb_entry); -+} -+ -+/* Delete an urb from the list. */ -+static inline void urb_list_del(struct urb *urb, int epid) { -+ unsigned long flags; -+ urb_entry_t *urb_entry; -+ -+ /* Delete entry and free. */ -+ spin_lock_irqsave(&urb_list_lock, flags); -+ urb_entry = __urb_list_entry(urb, epid); -+ ASSERT(urb_entry); -+ -+ list_del(&urb_entry->list); -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+ kfree(urb_entry); -+} -+ -+/* Move an urb to the end of the list. */ -+static inline void urb_list_move_last(struct urb *urb, int epid) { -+ unsigned long flags; -+ urb_entry_t *urb_entry; -+ -+ spin_lock_irqsave(&urb_list_lock, flags); -+ urb_entry = __urb_list_entry(urb, epid); -+ ASSERT(urb_entry); -+ -+ list_del(&urb_entry->list); -+ list_add_tail(&urb_entry->list, &urb_list[epid]); -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+} -+ -+/* Get the next urb in the list. */ -+static inline struct urb *urb_list_next(struct urb *urb, int epid) { -+ unsigned long flags; -+ urb_entry_t *urb_entry; -+ -+ spin_lock_irqsave(&urb_list_lock, flags); -+ urb_entry = __urb_list_entry(urb, epid); -+ ASSERT(urb_entry); -+ -+ if (urb_entry->list.next != &urb_list[epid]) { -+ struct list_head *elem = urb_entry->list.next; -+ urb_entry = list_entry(elem, urb_entry_t, list); -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+ return urb_entry->urb; -+ } else { -+ spin_unlock_irqrestore(&urb_list_lock, flags); -+ return NULL; -+ } -+} -+ -+struct USB_EP_Desc* create_ep(int epid, struct USB_SB_Desc* sb_desc, -+ int mem_flags) { -+ struct USB_EP_Desc *ep_desc; -+ ep_desc = (struct USB_EP_Desc *) kmem_cache_alloc(usb_desc_cache, mem_flags); -+ if(ep_desc == NULL) -+ return NULL; -+ memset(ep_desc, 0, sizeof(struct USB_EP_Desc)); -+ -+ ep_desc->hw_len = 0; -+ ep_desc->command = (IO_FIELD(USB_EP_command, epid, epid) | -+ IO_STATE(USB_EP_command, enable, yes)); -+ if(sb_desc == NULL) { -+ ep_desc->sub = 0; -+ } else { -+ ep_desc->sub = virt_to_phys(sb_desc); -+ } -+ return ep_desc; -+} -+ -+#define TT_ZOUT 0 -+#define TT_IN 1 -+#define TT_OUT 2 -+#define TT_SETUP 3 -+ -+#define CMD_EOL IO_STATE(USB_SB_command, eol, yes) -+#define CMD_INTR IO_STATE(USB_SB_command, intr, yes) -+#define CMD_FULL IO_STATE(USB_SB_command, full, yes) -+ -+/* Allocation and setup of a generic SB. Used to create SETUP, OUT and ZOUT -+ SBs. Also used by create_sb_in() to avoid same allocation procedure at two -+ places */ -+struct USB_SB_Desc* create_sb(struct USB_SB_Desc* sb_prev, int tt, void* data, -+ int datalen, int mem_flags) { -+ struct USB_SB_Desc *sb_desc; -+ sb_desc = (struct USB_SB_Desc*)kmem_cache_alloc(usb_desc_cache, mem_flags); -+ if(sb_desc == NULL) -+ return NULL; -+ memset(sb_desc, 0, sizeof(struct USB_SB_Desc)); -+ -+ sb_desc->command = IO_FIELD(USB_SB_command, tt, tt) | -+ IO_STATE(USB_SB_command, eot, yes); -+ -+ sb_desc->sw_len = datalen; -+ if(data != NULL) { -+ sb_desc->buf = virt_to_phys(data); -+ } else { -+ sb_desc->buf = 0; -+ } -+ if(sb_prev != NULL) { -+ sb_prev->next = virt_to_phys(sb_desc); -+ } -+ return sb_desc; -+} -+ -+/* Creates a copy of an existing SB by allocation space for it and copy -+ settings */ -+struct USB_SB_Desc* create_sb_copy(struct USB_SB_Desc* sb_orig, int mem_flags) { -+ struct USB_SB_Desc *sb_desc; -+ sb_desc = (struct USB_SB_Desc*)kmem_cache_alloc(usb_desc_cache, mem_flags); -+ if(sb_desc == NULL) -+ return NULL; -+ -+ memcpy(sb_desc, sb_orig, sizeof(struct USB_SB_Desc)); -+ return sb_desc; -+} -+ -+/* A specific create_sb function for creation of in SBs. This is due to -+ that datalen in In SBs shows how many packets we are expecting. It also -+ sets up the rem field to show if how many bytes we expect in last packet -+ if it's not a full one */ -+struct USB_SB_Desc* create_sb_in(struct USB_SB_Desc* sb_prev, int datalen, -+ int maxlen, int mem_flags) { -+ struct USB_SB_Desc *sb_desc; -+ sb_desc = create_sb(sb_prev, TT_IN, NULL, -+ datalen ? (datalen - 1) / maxlen + 1 : 0, mem_flags); -+ if(sb_desc == NULL) -+ return NULL; -+ sb_desc->command |= IO_FIELD(USB_SB_command, rem, datalen % maxlen); -+ return sb_desc; -+} -+ -+void set_sb_cmds(struct USB_SB_Desc *sb_desc, __u16 flags) { -+ sb_desc->command |= flags; -+} -+ -+int create_sb_for_urb(struct urb *urb, int mem_flags) { -+ int is_out = !usb_pipein(urb->pipe); -+ int type = usb_pipetype(urb->pipe); -+ int maxlen = usb_maxpacket(urb->dev, urb->pipe, is_out); -+ int buf_len = urb->transfer_buffer_length; -+ void *buf = buf_len > 0 ? urb->transfer_buffer : NULL; -+ struct USB_SB_Desc *sb_desc = NULL; -+ -+ struct crisv10_urb_priv *urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv != NULL); -+ -+ switch(type) { -+ case PIPE_CONTROL: -+ /* Setup stage */ -+ sb_desc = create_sb(NULL, TT_SETUP, urb->setup_packet, 8, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ set_sb_cmds(sb_desc, CMD_FULL); -+ -+ /* Attach first SB to URB */ -+ urb_priv->first_sb = sb_desc; -+ -+ if (is_out) { /* Out Control URB */ -+ /* If this Control OUT transfer has an optional data stage we add -+ an OUT token before the mandatory IN (status) token */ -+ if ((buf_len > 0) && buf) { -+ sb_desc = create_sb(sb_desc, TT_OUT, buf, buf_len, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ set_sb_cmds(sb_desc, CMD_FULL); -+ } -+ -+ /* Status stage */ -+ /* The data length has to be exactly 1. This is due to a requirement -+ of the USB specification that a host must be prepared to receive -+ data in the status phase */ -+ sb_desc = create_sb(sb_desc, TT_IN, NULL, 1, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ } else { /* In control URB */ -+ /* Data stage */ -+ sb_desc = create_sb_in(sb_desc, buf_len, maxlen, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ -+ /* Status stage */ -+ /* Read comment at zout_buffer declaration for an explanation to this. */ -+ sb_desc = create_sb(sb_desc, TT_ZOUT, &zout_buffer[0], 1, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ /* Set descriptor interrupt flag for in URBs so we can finish URB after -+ zout-packet has been sent */ -+ set_sb_cmds(sb_desc, CMD_INTR | CMD_FULL); -+ } -+ /* Set end-of-list flag in last SB */ -+ set_sb_cmds(sb_desc, CMD_EOL); -+ /* Attach last SB to URB */ -+ urb_priv->last_sb = sb_desc; -+ break; -+ -+ case PIPE_BULK: -+ if (is_out) { /* Out Bulk URB */ -+ sb_desc = create_sb(NULL, TT_OUT, buf, buf_len, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ /* The full field is set to yes, even if we don't actually check that -+ this is a full-length transfer (i.e., that transfer_buffer_length % -+ maxlen = 0). -+ Setting full prevents the USB controller from sending an empty packet -+ in that case. However, if URB_ZERO_PACKET was set we want that. */ -+ if (!(urb->transfer_flags & URB_ZERO_PACKET)) { -+ set_sb_cmds(sb_desc, CMD_FULL); -+ } -+ } else { /* In Bulk URB */ -+ sb_desc = create_sb_in(NULL, buf_len, maxlen, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ } -+ /* Set end-of-list flag for last SB */ -+ set_sb_cmds(sb_desc, CMD_EOL); -+ -+ /* Attach SB to URB */ -+ urb_priv->first_sb = sb_desc; -+ urb_priv->last_sb = sb_desc; -+ break; -+ -+ case PIPE_INTERRUPT: -+ if(is_out) { /* Out Intr URB */ -+ sb_desc = create_sb(NULL, TT_OUT, buf, buf_len, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ -+ /* The full field is set to yes, even if we don't actually check that -+ this is a full-length transfer (i.e., that transfer_buffer_length % -+ maxlen = 0). -+ Setting full prevents the USB controller from sending an empty packet -+ in that case. However, if URB_ZERO_PACKET was set we want that. */ -+ if (!(urb->transfer_flags & URB_ZERO_PACKET)) { -+ set_sb_cmds(sb_desc, CMD_FULL); -+ } -+ /* Only generate TX interrupt if it's a Out URB*/ -+ set_sb_cmds(sb_desc, CMD_INTR); -+ -+ } else { /* In Intr URB */ -+ sb_desc = create_sb_in(NULL, buf_len, maxlen, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ } -+ /* Set end-of-list flag for last SB */ -+ set_sb_cmds(sb_desc, CMD_EOL); -+ -+ /* Attach SB to URB */ -+ urb_priv->first_sb = sb_desc; -+ urb_priv->last_sb = sb_desc; -+ -+ break; -+ case PIPE_ISOCHRONOUS: -+ if(is_out) { /* Out Isoc URB */ -+ int i; -+ if(urb->number_of_packets == 0) { -+ tc_err("Can't create SBs for Isoc URB with zero packets\n"); -+ return -EPIPE; -+ } -+ /* Create one SB descriptor for each packet and link them together. */ -+ for(i = 0; i < urb->number_of_packets; i++) { -+ if (urb->iso_frame_desc[i].length > 0) { -+ -+ sb_desc = create_sb(sb_desc, TT_OUT, urb->transfer_buffer + -+ urb->iso_frame_desc[i].offset, -+ urb->iso_frame_desc[i].length, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ -+ /* Check if it's a full length packet */ -+ if (urb->iso_frame_desc[i].length == -+ usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe))) { -+ set_sb_cmds(sb_desc, CMD_FULL); -+ } -+ -+ } else { /* zero length packet */ -+ sb_desc = create_sb(sb_desc, TT_ZOUT, &zout_buffer[0], 1, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ set_sb_cmds(sb_desc, CMD_FULL); -+ } -+ /* Attach first SB descriptor to URB */ -+ if (i == 0) { -+ urb_priv->first_sb = sb_desc; -+ } -+ } -+ /* Set interrupt and end-of-list flags in last SB */ -+ set_sb_cmds(sb_desc, CMD_INTR | CMD_EOL); -+ /* Attach last SB descriptor to URB */ -+ urb_priv->last_sb = sb_desc; -+ tc_dbg("Created %d out SBs for Isoc URB:0x%x\n", -+ urb->number_of_packets, (unsigned int)urb); -+ } else { /* In Isoc URB */ -+ /* Actual number of packets is not relevant for periodic in traffic as -+ long as it is more than zero. Set to 1 always. */ -+ sb_desc = create_sb(sb_desc, TT_IN, NULL, 1, mem_flags); -+ if(sb_desc == NULL) -+ return -ENOMEM; -+ /* Set end-of-list flags for SB */ -+ set_sb_cmds(sb_desc, CMD_EOL); -+ -+ /* Attach SB to URB */ -+ urb_priv->first_sb = sb_desc; -+ urb_priv->last_sb = sb_desc; -+ } -+ break; -+ default: -+ tc_err("Unknown pipe-type\n"); -+ return -EPIPE; -+ break; -+ } -+ return 0; -+} -+ -+int init_intr_urb(struct urb *urb, int mem_flags) { -+ struct crisv10_urb_priv *urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ struct USB_EP_Desc* ep_desc; -+ int interval; -+ int i; -+ int ep_count; -+ -+ ASSERT(urb_priv != NULL); -+ ASSERT(usb_pipeint(urb->pipe)); -+ /* We can't support interval longer than amount of eof descriptors in -+ TxIntrEPList */ -+ if(urb->interval > MAX_INTR_INTERVAL) { -+ tc_err("Interrupt interval %dms too big (max: %dms)\n", urb->interval, -+ MAX_INTR_INTERVAL); -+ return -EINVAL; -+ } -+ -+ /* We assume that the SB descriptors already have been setup */ -+ ASSERT(urb_priv->first_sb != NULL); -+ -+ /* Round of the interval to 2^n, it is obvious that this code favours -+ smaller numbers, but that is actually a good thing */ -+ /* FIXME: The "rounding error" for larger intervals will be quite -+ large. For in traffic this shouldn't be a problem since it will only -+ mean that we "poll" more often. */ -+ interval = urb->interval; -+ for (i = 0; interval; i++) { -+ interval = interval >> 1; -+ } -+ urb_priv->interval = 1 << (i - 1); -+ -+ /* We can only have max interval for Out Interrupt due to that we can only -+ handle one linked in EP for a certain epid in the Intr descr array at the -+ time. The USB Controller in the Etrax 100LX continues to process Intr EPs -+ so we have no way of knowing which one that caused the actual transfer if -+ we have several linked in. */ -+ if(usb_pipeout(urb->pipe)) { -+ urb_priv->interval = MAX_INTR_INTERVAL; -+ } -+ -+ /* Calculate amount of EPs needed */ -+ ep_count = MAX_INTR_INTERVAL / urb_priv->interval; -+ -+ for(i = 0; i < ep_count; i++) { -+ ep_desc = create_ep(urb_priv->epid, urb_priv->first_sb, mem_flags); -+ if(ep_desc == NULL) { -+ /* Free any descriptors that we may have allocated before failure */ -+ while(i > 0) { -+ i--; -+ kfree(urb_priv->intr_ep_pool[i]); -+ } -+ return -ENOMEM; -+ } -+ urb_priv->intr_ep_pool[i] = ep_desc; -+ } -+ urb_priv->intr_ep_pool_length = ep_count; -+ return 0; -+} -+ -+/* DMA RX/TX functions */ -+/* ----------------------- */ -+ -+static void tc_dma_init_rx_list(void) { -+ int i; -+ -+ /* Setup descriptor list except last one */ -+ for (i = 0; i < (NBR_OF_RX_DESC - 1); i++) { -+ RxDescList[i].sw_len = RX_DESC_BUF_SIZE; -+ RxDescList[i].command = 0; -+ RxDescList[i].next = virt_to_phys(&RxDescList[i + 1]); -+ RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE)); -+ RxDescList[i].hw_len = 0; -+ RxDescList[i].status = 0; -+ -+ /* DMA IN cache bug. (struct etrax_dma_descr has the same layout as -+ USB_IN_Desc for the relevant fields.) */ -+ prepare_rx_descriptor((struct etrax_dma_descr*)&RxDescList[i]); -+ -+ } -+ /* Special handling of last descriptor */ -+ RxDescList[i].sw_len = RX_DESC_BUF_SIZE; -+ RxDescList[i].command = IO_STATE(USB_IN_command, eol, yes); -+ RxDescList[i].next = virt_to_phys(&RxDescList[0]); -+ RxDescList[i].buf = virt_to_phys(RxBuf + (i * RX_DESC_BUF_SIZE)); -+ RxDescList[i].hw_len = 0; -+ RxDescList[i].status = 0; -+ -+ /* Setup list pointers that show progress in list */ -+ myNextRxDesc = &RxDescList[0]; -+ myLastRxDesc = &RxDescList[NBR_OF_RX_DESC - 1]; -+ -+ flush_etrax_cache(); -+ /* Point DMA to first descriptor in list and start it */ -+ *R_DMA_CH9_FIRST = virt_to_phys(myNextRxDesc); -+ *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, start); -+} -+ -+ -+static void tc_dma_init_tx_bulk_list(void) { -+ int i; -+ volatile struct USB_EP_Desc *epDescr; -+ -+ for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { -+ epDescr = &(TxBulkEPList[i]); -+ CHECK_ALIGN(epDescr); -+ epDescr->hw_len = 0; -+ epDescr->command = IO_FIELD(USB_EP_command, epid, i); -+ epDescr->sub = 0; -+ epDescr->next = virt_to_phys(&TxBulkEPList[i + 1]); -+ -+ /* Initiate two EPs, disabled and with the eol flag set. No need for any -+ preserved epid. */ -+ -+ /* The first one has the intr flag set so we get an interrupt when the DMA -+ channel is about to become disabled. */ -+ CHECK_ALIGN(&TxBulkDummyEPList[i][0]); -+ TxBulkDummyEPList[i][0].hw_len = 0; -+ TxBulkDummyEPList[i][0].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) | -+ IO_STATE(USB_EP_command, eol, yes) | -+ IO_STATE(USB_EP_command, intr, yes)); -+ TxBulkDummyEPList[i][0].sub = 0; -+ TxBulkDummyEPList[i][0].next = virt_to_phys(&TxBulkDummyEPList[i][1]); -+ -+ /* The second one. */ -+ CHECK_ALIGN(&TxBulkDummyEPList[i][1]); -+ TxBulkDummyEPList[i][1].hw_len = 0; -+ TxBulkDummyEPList[i][1].command = (IO_FIELD(USB_EP_command, epid, DUMMY_EPID) | -+ IO_STATE(USB_EP_command, eol, yes)); -+ TxBulkDummyEPList[i][1].sub = 0; -+ /* The last dummy's next pointer is the same as the current EP's next pointer. */ -+ TxBulkDummyEPList[i][1].next = virt_to_phys(&TxBulkEPList[i + 1]); -+ } -+ -+ /* Special handling of last descr in list, make list circular */ -+ epDescr = &TxBulkEPList[i]; -+ CHECK_ALIGN(epDescr); -+ epDescr->hw_len = 0; -+ epDescr->command = IO_STATE(USB_EP_command, eol, yes) | -+ IO_FIELD(USB_EP_command, epid, i); -+ epDescr->sub = 0; -+ epDescr->next = virt_to_phys(&TxBulkEPList[0]); -+ -+ /* Init DMA sub-channel pointers to last item in each list */ -+ *R_DMA_CH8_SUB0_EP = virt_to_phys(&TxBulkEPList[i]); -+ /* No point in starting the bulk channel yet. -+ *R_DMA_CH8_SUB0_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */ -+} -+ -+static void tc_dma_init_tx_ctrl_list(void) { -+ int i; -+ volatile struct USB_EP_Desc *epDescr; -+ -+ for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { -+ epDescr = &(TxCtrlEPList[i]); -+ CHECK_ALIGN(epDescr); -+ epDescr->hw_len = 0; -+ epDescr->command = IO_FIELD(USB_EP_command, epid, i); -+ epDescr->sub = 0; -+ epDescr->next = virt_to_phys(&TxCtrlEPList[i + 1]); -+ } -+ /* Special handling of last descr in list, make list circular */ -+ epDescr = &TxCtrlEPList[i]; -+ CHECK_ALIGN(epDescr); -+ epDescr->hw_len = 0; -+ epDescr->command = IO_STATE(USB_EP_command, eol, yes) | -+ IO_FIELD(USB_EP_command, epid, i); -+ epDescr->sub = 0; -+ epDescr->next = virt_to_phys(&TxCtrlEPList[0]); -+ -+ /* Init DMA sub-channel pointers to last item in each list */ -+ *R_DMA_CH8_SUB1_EP = virt_to_phys(&TxCtrlEPList[i]); -+ /* No point in starting the ctrl channel yet. -+ *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB0_CMD, cmd, start); */ -+} -+ -+ -+static void tc_dma_init_tx_intr_list(void) { -+ int i; -+ -+ TxIntrSB_zout.sw_len = 1; -+ TxIntrSB_zout.next = 0; -+ TxIntrSB_zout.buf = virt_to_phys(&zout_buffer[0]); -+ TxIntrSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) | -+ IO_STATE(USB_SB_command, tt, zout) | -+ IO_STATE(USB_SB_command, full, yes) | -+ IO_STATE(USB_SB_command, eot, yes) | -+ IO_STATE(USB_SB_command, eol, yes)); -+ -+ for (i = 0; i < (MAX_INTR_INTERVAL - 1); i++) { -+ CHECK_ALIGN(&TxIntrEPList[i]); -+ TxIntrEPList[i].hw_len = 0; -+ TxIntrEPList[i].command = -+ (IO_STATE(USB_EP_command, eof, yes) | -+ IO_STATE(USB_EP_command, enable, yes) | -+ IO_FIELD(USB_EP_command, epid, INVALID_EPID)); -+ TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout); -+ TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[i + 1]); -+ } -+ -+ /* Special handling of last descr in list, make list circular */ -+ CHECK_ALIGN(&TxIntrEPList[i]); -+ TxIntrEPList[i].hw_len = 0; -+ TxIntrEPList[i].command = -+ (IO_STATE(USB_EP_command, eof, yes) | -+ IO_STATE(USB_EP_command, eol, yes) | -+ IO_STATE(USB_EP_command, enable, yes) | -+ IO_FIELD(USB_EP_command, epid, INVALID_EPID)); -+ TxIntrEPList[i].sub = virt_to_phys(&TxIntrSB_zout); -+ TxIntrEPList[i].next = virt_to_phys(&TxIntrEPList[0]); -+ -+ intr_dbg("Initiated Intr EP descriptor list\n"); -+ -+ -+ /* Connect DMA 8 sub-channel 2 to first in list */ -+ *R_DMA_CH8_SUB2_EP = virt_to_phys(&TxIntrEPList[0]); -+} -+ -+static void tc_dma_init_tx_isoc_list(void) { -+ int i; -+ -+ DBFENTER; -+ -+ /* Read comment at zout_buffer declaration for an explanation to this. */ -+ TxIsocSB_zout.sw_len = 1; -+ TxIsocSB_zout.next = 0; -+ TxIsocSB_zout.buf = virt_to_phys(&zout_buffer[0]); -+ TxIsocSB_zout.command = (IO_FIELD(USB_SB_command, rem, 0) | -+ IO_STATE(USB_SB_command, tt, zout) | -+ IO_STATE(USB_SB_command, full, yes) | -+ IO_STATE(USB_SB_command, eot, yes) | -+ IO_STATE(USB_SB_command, eol, yes)); -+ -+ /* The last isochronous EP descriptor is a dummy. */ -+ for (i = 0; i < (NBR_OF_EPIDS - 1); i++) { -+ CHECK_ALIGN(&TxIsocEPList[i]); -+ TxIsocEPList[i].hw_len = 0; -+ TxIsocEPList[i].command = IO_FIELD(USB_EP_command, epid, i); -+ TxIsocEPList[i].sub = 0; -+ TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[i + 1]); -+ } -+ -+ CHECK_ALIGN(&TxIsocEPList[i]); -+ TxIsocEPList[i].hw_len = 0; -+ -+ /* Must enable the last EP descr to get eof interrupt. */ -+ TxIsocEPList[i].command = (IO_STATE(USB_EP_command, enable, yes) | -+ IO_STATE(USB_EP_command, eof, yes) | -+ IO_STATE(USB_EP_command, eol, yes) | -+ IO_FIELD(USB_EP_command, epid, INVALID_EPID)); -+ TxIsocEPList[i].sub = virt_to_phys(&TxIsocSB_zout); -+ TxIsocEPList[i].next = virt_to_phys(&TxIsocEPList[0]); -+ -+ *R_DMA_CH8_SUB3_EP = virt_to_phys(&TxIsocEPList[0]); -+ *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start); -+} -+ -+static int tc_dma_init(struct usb_hcd *hcd) { -+ tc_dma_init_rx_list(); -+ tc_dma_init_tx_bulk_list(); -+ tc_dma_init_tx_ctrl_list(); -+ tc_dma_init_tx_intr_list(); -+ tc_dma_init_tx_isoc_list(); -+ -+ if (cris_request_dma(USB_TX_DMA_NBR, -+ "ETRAX 100LX built-in USB (Tx)", -+ DMA_VERBOSE_ON_ERROR, -+ dma_usb)) { -+ err("Could not allocate DMA ch 8 for USB"); -+ return -EBUSY; -+ } -+ -+ if (cris_request_dma(USB_RX_DMA_NBR, -+ "ETRAX 100LX built-in USB (Rx)", -+ DMA_VERBOSE_ON_ERROR, -+ dma_usb)) { -+ err("Could not allocate DMA ch 9 for USB"); -+ return -EBUSY; -+ } -+ -+ *R_IRQ_MASK2_SET = -+ /* Note that these interrupts are not used. */ -+ IO_STATE(R_IRQ_MASK2_SET, dma8_sub0_descr, set) | -+ /* Sub channel 1 (ctrl) descr. interrupts are used. */ -+ IO_STATE(R_IRQ_MASK2_SET, dma8_sub1_descr, set) | -+ IO_STATE(R_IRQ_MASK2_SET, dma8_sub2_descr, set) | -+ /* Sub channel 3 (isoc) descr. interrupts are used. */ -+ IO_STATE(R_IRQ_MASK2_SET, dma8_sub3_descr, set); -+ -+ /* Note that the dma9_descr interrupt is not used. */ -+ *R_IRQ_MASK2_SET = -+ IO_STATE(R_IRQ_MASK2_SET, dma9_eop, set) | -+ IO_STATE(R_IRQ_MASK2_SET, dma9_descr, set); -+ -+ if (request_irq(ETRAX_USB_RX_IRQ, tc_dma_rx_interrupt, 0, -+ "ETRAX 100LX built-in USB (Rx)", hcd)) { -+ err("Could not allocate IRQ %d for USB", ETRAX_USB_RX_IRQ); -+ return -EBUSY; -+ } -+ -+ if (request_irq(ETRAX_USB_TX_IRQ, tc_dma_tx_interrupt, 0, -+ "ETRAX 100LX built-in USB (Tx)", hcd)) { -+ err("Could not allocate IRQ %d for USB", ETRAX_USB_TX_IRQ); -+ return -EBUSY; -+ } -+ -+ return 0; -+} -+ -+static void tc_dma_destroy(void) { -+ free_irq(ETRAX_USB_RX_IRQ, NULL); -+ free_irq(ETRAX_USB_TX_IRQ, NULL); -+ -+ cris_free_dma(USB_TX_DMA_NBR, "ETRAX 100LX built-in USB (Tx)"); -+ cris_free_dma(USB_RX_DMA_NBR, "ETRAX 100LX built-in USB (Rx)"); -+ -+} -+ -+static void tc_dma_link_intr_urb(struct urb *urb); -+ -+/* Handle processing of Bulk, Ctrl and Intr queues */ -+static void tc_dma_process_queue(int epid) { -+ struct urb *urb; -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ unsigned long flags; -+ char toggle; -+ -+ if(epid_state[epid].disabled) { -+ /* Don't process any URBs on a disabled endpoint */ -+ return; -+ } -+ -+ /* Do not disturb us while fiddling with EPs and epids */ -+ local_irq_save(flags); -+ -+ /* For bulk, Ctrl and Intr can we only have one URB active at a time for -+ a specific EP. */ -+ if(activeUrbList[epid] != NULL) { -+ /* An URB is already active on EP, skip checking queue */ -+ local_irq_restore(flags); -+ return; -+ } -+ -+ urb = urb_list_first(epid); -+ if(urb == NULL) { -+ /* No URB waiting in EP queue. Nothing do to */ -+ local_irq_restore(flags); -+ return; -+ } -+ -+ urb_priv = urb->hcpriv; -+ ASSERT(urb_priv != NULL); -+ ASSERT(urb_priv->urb_state == NOT_STARTED); -+ ASSERT(!usb_pipeisoc(urb->pipe)); -+ -+ /* Remove this URB from the queue and move it to active */ -+ activeUrbList[epid] = urb; -+ urb_list_del(urb, epid); -+ -+ urb_priv->urb_state = STARTED; -+ -+ /* Reset error counters (regardless of which direction this traffic is). */ -+ etrax_epid_clear_error(epid); -+ -+ /* Special handling of Intr EP lists */ -+ if(usb_pipeint(urb->pipe)) { -+ tc_dma_link_intr_urb(urb); -+ local_irq_restore(flags); -+ return; -+ } -+ -+ /* Software must preset the toggle bits for Bulk and Ctrl */ -+ if(usb_pipecontrol(urb->pipe)) { -+ /* Toggle bits are initialized only during setup transaction in a -+ CTRL transfer */ -+ etrax_epid_set_toggle(epid, 0, 0); -+ etrax_epid_set_toggle(epid, 1, 0); -+ } else { -+ toggle = usb_gettoggle(urb->dev, usb_pipeendpoint(urb->pipe), -+ usb_pipeout(urb->pipe)); -+ etrax_epid_set_toggle(epid, usb_pipeout(urb->pipe), toggle); -+ } -+ -+ tc_dbg("Added SBs from (URB:0x%x %s %s) to epid %d: %s\n", -+ (unsigned int)urb, str_dir(urb->pipe), str_type(urb->pipe), epid, -+ sblist_to_str(urb_priv->first_sb)); -+ -+ /* We start the DMA sub channel without checking if it's running or not, -+ because: -+ 1) If it's already running, issuing the start command is a nop. -+ 2) We avoid a test-and-set race condition. */ -+ switch(usb_pipetype(urb->pipe)) { -+ case PIPE_BULK: -+ /* Assert that the EP descriptor is disabled. */ -+ ASSERT(!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable))); -+ -+ /* Set up and enable the EP descriptor. */ -+ TxBulkEPList[epid].sub = virt_to_phys(urb_priv->first_sb); -+ TxBulkEPList[epid].hw_len = 0; -+ TxBulkEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); -+ -+ /* Check if the dummy list is already with us (if several urbs were queued). */ -+ if (usb_pipein(urb->pipe) && (TxBulkEPList[epid].next != virt_to_phys(&TxBulkDummyEPList[epid][0]))) { -+ tc_dbg("Inviting dummy list to the party for urb 0x%lx, epid %d", -+ (unsigned long)urb, epid); -+ -+ /* We don't need to check if the DMA is at this EP or not before changing the -+ next pointer, since we will do it in one 32-bit write (EP descriptors are -+ 32-bit aligned). */ -+ TxBulkEPList[epid].next = virt_to_phys(&TxBulkDummyEPList[epid][0]); -+ } -+ -+ restart_dma8_sub0(); -+ -+ /* Update/restart the bulk start timer since we just started the channel.*/ -+ mod_timer(&bulk_start_timer, jiffies + BULK_START_TIMER_INTERVAL); -+ /* Update/restart the bulk eot timer since we just inserted traffic. */ -+ mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); -+ break; -+ case PIPE_CONTROL: -+ /* Assert that the EP descriptor is disabled. */ -+ ASSERT(!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable))); -+ -+ /* Set up and enable the EP descriptor. */ -+ TxCtrlEPList[epid].sub = virt_to_phys(urb_priv->first_sb); -+ TxCtrlEPList[epid].hw_len = 0; -+ TxCtrlEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); -+ -+ *R_DMA_CH8_SUB1_CMD = IO_STATE(R_DMA_CH8_SUB1_CMD, cmd, start); -+ break; -+ } -+ local_irq_restore(flags); -+} -+ -+static void tc_dma_link_intr_urb(struct urb *urb) { -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ volatile struct USB_EP_Desc *tmp_ep; -+ struct USB_EP_Desc *ep_desc; -+ int i = 0, epid; -+ int pool_idx = 0; -+ -+ ASSERT(urb_priv != NULL); -+ epid = urb_priv->epid; -+ ASSERT(urb_priv->interval > 0); -+ ASSERT(urb_priv->intr_ep_pool_length > 0); -+ -+ tmp_ep = &TxIntrEPList[0]; -+ -+ /* Only insert one EP descriptor in list for Out Intr URBs. -+ We can only handle Out Intr with interval of 128ms because -+ it's not possible to insert several Out Intr EPs because they -+ are not consumed by the DMA. */ -+ if(usb_pipeout(urb->pipe)) { -+ ep_desc = urb_priv->intr_ep_pool[0]; -+ ASSERT(ep_desc); -+ ep_desc->next = tmp_ep->next; -+ tmp_ep->next = virt_to_phys(ep_desc); -+ i++; -+ } else { -+ /* Loop through Intr EP descriptor list and insert EP for URB at -+ specified interval */ -+ do { -+ /* Each EP descriptor with eof flag sat signals a new frame */ -+ if (tmp_ep->command & IO_MASK(USB_EP_command, eof)) { -+ /* Insert a EP from URBs EP pool at correct interval */ -+ if ((i % urb_priv->interval) == 0) { -+ ep_desc = urb_priv->intr_ep_pool[pool_idx]; -+ ASSERT(ep_desc); -+ ep_desc->next = tmp_ep->next; -+ tmp_ep->next = virt_to_phys(ep_desc); -+ pool_idx++; -+ ASSERT(pool_idx <= urb_priv->intr_ep_pool_length); -+ } -+ i++; -+ } -+ tmp_ep = (struct USB_EP_Desc *)phys_to_virt(tmp_ep->next); -+ } while(tmp_ep != &TxIntrEPList[0]); -+ } -+ -+ intr_dbg("Added SBs to intr epid %d: %s interval:%d (%d EP)\n", epid, -+ sblist_to_str(urb_priv->first_sb), urb_priv->interval, pool_idx); -+ -+ /* We start the DMA sub channel without checking if it's running or not, -+ because: -+ 1) If it's already running, issuing the start command is a nop. -+ 2) We avoid a test-and-set race condition. */ -+ *R_DMA_CH8_SUB2_CMD = IO_STATE(R_DMA_CH8_SUB2_CMD, cmd, start); -+} -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+static void tc_dma_process_isoc_urb(struct urb *urb) { -+ unsigned long flags; -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ int epid; -+ -+ /* Do not disturb us while fiddling with EPs and epids */ -+ local_irq_save(flags); -+ -+ ASSERT(urb_priv); -+ ASSERT(urb_priv->first_sb); -+ epid = urb_priv->epid; -+ -+ if(activeUrbList[epid] == NULL) { -+ /* EP is idle, so make this URB active */ -+ activeUrbList[epid] = urb; -+ urb_list_del(urb, epid); -+ ASSERT(TxIsocEPList[epid].sub == 0); -+ ASSERT(!(TxIsocEPList[epid].command & -+ IO_STATE(USB_EP_command, enable, yes))); -+ -+ /* Differentiate between In and Out Isoc. Because In SBs are not consumed*/ -+ if(usb_pipein(urb->pipe)) { -+ /* Each EP for In Isoc will have only one SB descriptor, setup when -+ submitting the first active urb. We do it here by copying from URBs -+ pre-allocated SB. */ -+ memcpy((void *)&(TxIsocSBList[epid]), urb_priv->first_sb, -+ sizeof(TxIsocSBList[epid])); -+ TxIsocEPList[epid].hw_len = 0; -+ TxIsocEPList[epid].sub = virt_to_phys(&(TxIsocSBList[epid])); -+ } else { -+ /* For Out Isoc we attach the pre-allocated list of SBs for the URB */ -+ TxIsocEPList[epid].hw_len = 0; -+ TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb); -+ -+ isoc_dbg("Attached first URB:0x%x[%d] to epid:%d first_sb:0x%x" -+ " last_sb::0x%x\n", -+ (unsigned int)urb, urb_priv->urb_num, epid, -+ (unsigned int)(urb_priv->first_sb), -+ (unsigned int)(urb_priv->last_sb)); -+ } -+ -+ if (urb->transfer_flags & URB_ISO_ASAP) { -+ /* The isoc transfer should be started as soon as possible. The -+ start_frame field is a return value if URB_ISO_ASAP was set. Comparing -+ R_USB_FM_NUMBER with a USB Chief trace shows that the first isoc IN -+ token is sent 2 frames later. I'm not sure how this affects usage of -+ the start_frame field by the device driver, or how it affects things -+ when USB_ISO_ASAP is not set, so therefore there's no compensation for -+ the 2 frame "lag" here. */ -+ urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff); -+ TxIsocEPList[epid].command |= IO_STATE(USB_EP_command, enable, yes); -+ urb_priv->urb_state = STARTED; -+ isoc_dbg("URB_ISO_ASAP set, urb->start_frame set to %d\n", -+ urb->start_frame); -+ } else { -+ /* Not started yet. */ -+ urb_priv->urb_state = NOT_STARTED; -+ isoc_warn("urb_priv->urb_state set to NOT_STARTED for URB:0x%x\n", -+ (unsigned int)urb); -+ } -+ -+ } else { -+ /* An URB is already active on the EP. Leave URB in queue and let -+ finish_isoc_urb process it after current active URB */ -+ ASSERT(TxIsocEPList[epid].sub != 0); -+ -+ if(usb_pipein(urb->pipe)) { -+ /* Because there already is a active In URB on this epid we do nothing -+ and the finish_isoc_urb() function will handle switching to next URB*/ -+ -+ } else { /* For Out Isoc, insert new URBs traffic last in SB-list. */ -+ struct USB_SB_Desc *temp_sb_desc; -+ -+ /* Set state STARTED to all Out Isoc URBs added to SB list because we -+ don't know how many of them that are finished before descr interrupt*/ -+ urb_priv->urb_state = STARTED; -+ -+ /* Find end of current SB list by looking for SB with eol flag sat */ -+ temp_sb_desc = phys_to_virt(TxIsocEPList[epid].sub); -+ while ((temp_sb_desc->command & IO_MASK(USB_SB_command, eol)) != -+ IO_STATE(USB_SB_command, eol, yes)) { -+ ASSERT(temp_sb_desc->next); -+ temp_sb_desc = phys_to_virt(temp_sb_desc->next); -+ } -+ -+ isoc_dbg("Appended URB:0x%x[%d] (first:0x%x last:0x%x) to epid:%d" -+ " sub:0x%x eol:0x%x\n", -+ (unsigned int)urb, urb_priv->urb_num, -+ (unsigned int)(urb_priv->first_sb), -+ (unsigned int)(urb_priv->last_sb), epid, -+ (unsigned int)phys_to_virt(TxIsocEPList[epid].sub), -+ (unsigned int)temp_sb_desc); -+ -+ /* Next pointer must be set before eol is removed. */ -+ temp_sb_desc->next = virt_to_phys(urb_priv->first_sb); -+ /* Clear the previous end of list flag since there is a new in the -+ added SB descriptor list. */ -+ temp_sb_desc->command &= ~IO_MASK(USB_SB_command, eol); -+ -+ if (!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) { -+ __u32 epid_data; -+ /* 8.8.5 in Designer's Reference says we should check for and correct -+ any errors in the EP here. That should not be necessary if -+ epid_attn is handled correctly, so we assume all is ok. */ -+ epid_data = etrax_epid_iso_get(epid); -+ if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) != -+ IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { -+ isoc_err("Disabled Isoc EP with error:%d on epid:%d when appending" -+ " URB:0x%x[%d]\n", -+ IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data), epid, -+ (unsigned int)urb, urb_priv->urb_num); -+ } -+ -+ /* The SB list was exhausted. */ -+ if (virt_to_phys(urb_priv->last_sb) != TxIsocEPList[epid].sub) { -+ /* The new sublist did not get processed before the EP was -+ disabled. Setup the EP again. */ -+ -+ if(virt_to_phys(temp_sb_desc) == TxIsocEPList[epid].sub) { -+ isoc_dbg("EP for epid:%d stoped at SB:0x%x before newly inserted" -+ ", restarting from this URBs SB:0x%x\n", -+ epid, (unsigned int)temp_sb_desc, -+ (unsigned int)(urb_priv->first_sb)); -+ TxIsocEPList[epid].hw_len = 0; -+ TxIsocEPList[epid].sub = virt_to_phys(urb_priv->first_sb); -+ urb->start_frame = (*R_USB_FM_NUMBER & 0x7ff); -+ /* Enable the EP again so data gets processed this time */ -+ TxIsocEPList[epid].command |= -+ IO_STATE(USB_EP_command, enable, yes); -+ -+ } else { -+ /* The EP has been disabled but not at end this URB (god knows -+ where). This should generate an epid_attn so we should not be -+ here */ -+ isoc_warn("EP was disabled on sb:0x%x before SB list for" -+ " URB:0x%x[%d] got processed\n", -+ (unsigned int)phys_to_virt(TxIsocEPList[epid].sub), -+ (unsigned int)urb, urb_priv->urb_num); -+ } -+ } else { -+ /* This might happend if we are slow on this function and isn't -+ an error. */ -+ isoc_dbg("EP was disabled and finished with SBs from appended" -+ " URB:0x%x[%d]\n", (unsigned int)urb, urb_priv->urb_num); -+ } -+ } -+ } -+ } -+ -+ /* Start the DMA sub channel */ -+ *R_DMA_CH8_SUB3_CMD = IO_STATE(R_DMA_CH8_SUB3_CMD, cmd, start); -+ -+ local_irq_restore(flags); -+} -+#endif -+ -+static void tc_dma_unlink_intr_urb(struct urb *urb) { -+ struct crisv10_urb_priv *urb_priv = urb->hcpriv; -+ volatile struct USB_EP_Desc *first_ep; /* First EP in the list. */ -+ volatile struct USB_EP_Desc *curr_ep; /* Current EP, the iterator. */ -+ volatile struct USB_EP_Desc *next_ep; /* The EP after current. */ -+ volatile struct USB_EP_Desc *unlink_ep; /* The one we should remove from -+ the list. */ -+ int count = 0; -+ volatile int timeout = 10000; -+ int epid; -+ -+ /* Read 8.8.4 in Designer's Reference, "Removing an EP Descriptor from the -+ List". */ -+ ASSERT(urb_priv); -+ ASSERT(urb_priv->intr_ep_pool_length > 0); -+ epid = urb_priv->epid; -+ -+ /* First disable all Intr EPs belonging to epid for this URB */ -+ first_ep = &TxIntrEPList[0]; -+ curr_ep = first_ep; -+ do { -+ next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next); -+ if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) { -+ /* Disable EP */ -+ next_ep->command &= ~IO_MASK(USB_EP_command, enable); -+ } -+ curr_ep = phys_to_virt(curr_ep->next); -+ } while (curr_ep != first_ep); -+ -+ -+ /* Now unlink all EPs belonging to this epid from Descr list */ -+ first_ep = &TxIntrEPList[0]; -+ curr_ep = first_ep; -+ do { -+ next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next); -+ if (IO_EXTRACT(USB_EP_command, epid, next_ep->command) == epid) { -+ /* This is the one we should unlink. */ -+ unlink_ep = next_ep; -+ -+ /* Actually unlink the EP from the DMA list. */ -+ curr_ep->next = unlink_ep->next; -+ -+ /* Wait until the DMA is no longer at this descriptor. */ -+ while((*R_DMA_CH8_SUB2_EP == virt_to_phys(unlink_ep)) && -+ (timeout-- > 0)); -+ if(timeout == 0) { -+ warn("Timeout while waiting for DMA-TX-Intr to leave unlink EP\n"); -+ } -+ -+ count++; -+ } -+ curr_ep = phys_to_virt(curr_ep->next); -+ } while (curr_ep != first_ep); -+ -+ if(count != urb_priv->intr_ep_pool_length) { -+ intr_warn("Unlinked %d of %d Intr EPs for URB:0x%x[%d]\n", count, -+ urb_priv->intr_ep_pool_length, (unsigned int)urb, -+ urb_priv->urb_num); -+ } else { -+ intr_dbg("Unlinked %d of %d interrupt EPs for URB:0x%x\n", count, -+ urb_priv->intr_ep_pool_length, (unsigned int)urb); -+ } -+} -+ -+static void check_finished_bulk_tx_epids(struct usb_hcd *hcd, -+ int timer) { -+ unsigned long flags; -+ int epid; -+ struct urb *urb; -+ struct crisv10_urb_priv * urb_priv; -+ __u32 epid_data; -+ -+ /* Protect TxEPList */ -+ local_irq_save(flags); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ /* A finished EP descriptor is disabled and has a valid sub pointer */ -+ if (!(TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) && -+ (TxBulkEPList[epid].sub != 0)) { -+ -+ /* Get the active URB for this epid */ -+ urb = activeUrbList[epid]; -+ /* Sanity checks */ -+ ASSERT(urb); -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ /* Only handle finished out Bulk EPs here, -+ and let RX interrupt take care of the rest */ -+ if(!epid_out_traffic(epid)) { -+ continue; -+ } -+ -+ if(timer) { -+ tc_warn("Found finished %s Bulk epid:%d URB:0x%x[%d] from timeout\n", -+ epid_out_traffic(epid) ? "Out" : "In", epid, (unsigned int)urb, -+ urb_priv->urb_num); -+ } else { -+ tc_dbg("Found finished %s Bulk epid:%d URB:0x%x[%d] from interrupt\n", -+ epid_out_traffic(epid) ? "Out" : "In", epid, (unsigned int)urb, -+ urb_priv->urb_num); -+ } -+ -+ if(urb_priv->urb_state == UNLINK) { -+ /* This Bulk URB is requested to be unlinked, that means that the EP -+ has been disabled and we might not have sent all data */ -+ tc_finish_urb(hcd, urb, urb->status); -+ continue; -+ } -+ -+ ASSERT(urb_priv->urb_state == STARTED); -+ if (phys_to_virt(TxBulkEPList[epid].sub) != urb_priv->last_sb) { -+ tc_err("Endpoint got disabled before reaching last sb\n"); -+ } -+ -+ epid_data = etrax_epid_get(epid); -+ if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) == -+ IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { -+ /* This means that the endpoint has no error, is disabled -+ and had inserted traffic, i.e. transfer successfully completed. */ -+ tc_finish_urb(hcd, urb, 0); -+ } else { -+ /* Shouldn't happen. We expect errors to be caught by epid -+ attention. */ -+ tc_err("Found disabled bulk EP desc (epid:%d error:%d)\n", -+ epid, IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data)); -+ } -+ } else { -+ tc_dbg("Ignoring In Bulk epid:%d, let RX interrupt handle it\n", epid); -+ } -+ } -+ -+ local_irq_restore(flags); -+} -+ -+static void check_finished_ctrl_tx_epids(struct usb_hcd *hcd) { -+ unsigned long flags; -+ int epid; -+ struct urb *urb; -+ struct crisv10_urb_priv * urb_priv; -+ __u32 epid_data; -+ -+ /* Protect TxEPList */ -+ local_irq_save(flags); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ if(epid == DUMMY_EPID) -+ continue; -+ -+ /* A finished EP descriptor is disabled and has a valid sub pointer */ -+ if (!(TxCtrlEPList[epid].command & IO_MASK(USB_EP_command, enable)) && -+ (TxCtrlEPList[epid].sub != 0)) { -+ -+ /* Get the active URB for this epid */ -+ urb = activeUrbList[epid]; -+ -+ if(urb == NULL) { -+ tc_warn("Found finished Ctrl epid:%d with no active URB\n", epid); -+ continue; -+ } -+ -+ /* Sanity checks */ -+ ASSERT(usb_pipein(urb->pipe)); -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ if (phys_to_virt(TxCtrlEPList[epid].sub) != urb_priv->last_sb) { -+ tc_err("Endpoint got disabled before reaching last sb\n"); -+ } -+ -+ epid_data = etrax_epid_get(epid); -+ if (IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data) == -+ IO_STATE_VALUE(R_USB_EPT_DATA, error_code, no_error)) { -+ /* This means that the endpoint has no error, is disabled -+ and had inserted traffic, i.e. transfer successfully completed. */ -+ -+ /* Check if RX-interrupt for In Ctrl has been processed before -+ finishing the URB */ -+ if(urb_priv->ctrl_rx_done) { -+ tc_dbg("Finishing In Ctrl URB:0x%x[%d] in tx_interrupt\n", -+ (unsigned int)urb, urb_priv->urb_num); -+ tc_finish_urb(hcd, urb, 0); -+ } else { -+ /* If we get zout descriptor interrupt before RX was done for a -+ In Ctrl transfer, then we flag that and it will be finished -+ in the RX-Interrupt */ -+ urb_priv->ctrl_zout_done = 1; -+ tc_dbg("Got zout descr interrupt before RX interrupt\n"); -+ } -+ } else { -+ /* Shouldn't happen. We expect errors to be caught by epid -+ attention. */ -+ tc_err("Found disabled Ctrl EP desc (epid:%d URB:0x%x[%d]) error_code:%d\n", epid, (unsigned int)urb, urb_priv->urb_num, IO_EXTRACT(R_USB_EPT_DATA, error_code, epid_data)); -+ __dump_ep_desc(&(TxCtrlEPList[epid])); -+ __dump_ept_data(epid); -+ } -+ } -+ } -+ local_irq_restore(flags); -+} -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+/* This function goes through all epids that are setup for Out Isoc transfers -+ and marks (isoc_out_done) all queued URBs that the DMA has finished -+ transfer for. -+ No URB completetion is done here to make interrupt routine return quickly. -+ URBs are completed later with help of complete_isoc_bottom_half() that -+ becomes schedules when this functions is finished. */ -+static void check_finished_isoc_tx_epids(void) { -+ unsigned long flags; -+ int epid; -+ struct urb *urb; -+ struct crisv10_urb_priv * urb_priv; -+ struct USB_SB_Desc* sb_desc; -+ int epid_done; -+ -+ /* Protect TxIsocEPList */ -+ local_irq_save(flags); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ if (TxIsocEPList[epid].sub == 0 || epid == INVALID_EPID || -+ !epid_out_traffic(epid)) { -+ /* Nothing here to see. */ -+ continue; -+ } -+ ASSERT(epid_inuse(epid)); -+ ASSERT(epid_isoc(epid)); -+ -+ sb_desc = phys_to_virt(TxIsocEPList[epid].sub); -+ /* Find the last descriptor of the currently active URB for this ep. -+ This is the first descriptor in the sub list marked for a descriptor -+ interrupt. */ -+ while (sb_desc && !IO_EXTRACT(USB_SB_command, intr, sb_desc->command)) { -+ sb_desc = sb_desc->next ? phys_to_virt(sb_desc->next) : 0; -+ } -+ ASSERT(sb_desc); -+ -+ isoc_dbg("Descr IRQ checking epid:%d sub:0x%x intr:0x%x\n", -+ epid, (unsigned int)phys_to_virt(TxIsocEPList[epid].sub), -+ (unsigned int)sb_desc); -+ -+ urb = activeUrbList[epid]; -+ if(urb == NULL) { -+ isoc_err("Isoc Descr irq on epid:%d with no active URB\n", epid); -+ continue; -+ } -+ -+ epid_done = 0; -+ while(urb && !epid_done) { -+ /* Sanity check. */ -+ ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS); -+ ASSERT(usb_pipeout(urb->pipe)); -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ ASSERT(urb_priv->urb_state == STARTED || -+ urb_priv->urb_state == UNLINK); -+ -+ if (sb_desc != urb_priv->last_sb) { -+ /* This urb has been sent. */ -+ urb_priv->isoc_out_done = 1; -+ -+ } else { /* Found URB that has last_sb as the interrupt reason */ -+ -+ /* Check if EP has been disabled, meaning that all transfers are done*/ -+ if(!(TxIsocEPList[epid].command & IO_MASK(USB_EP_command, enable))) { -+ ASSERT((sb_desc->command & IO_MASK(USB_SB_command, eol)) == -+ IO_STATE(USB_SB_command, eol, yes)); -+ ASSERT(sb_desc->next == 0); -+ urb_priv->isoc_out_done = 1; -+ } else { -+ isoc_dbg("Skipping URB:0x%x[%d] because EP not disabled yet\n", -+ (unsigned int)urb, urb_priv->urb_num); -+ } -+ /* Stop looking any further in queue */ -+ epid_done = 1; -+ } -+ -+ if (!epid_done) { -+ if(urb == activeUrbList[epid]) { -+ urb = urb_list_first(epid); -+ } else { -+ urb = urb_list_next(urb, epid); -+ } -+ } -+ } /* END: while(urb && !epid_done) */ -+ } -+ -+ local_irq_restore(flags); -+} -+ -+ -+/* This is where the Out Isoc URBs are realy completed. This function is -+ scheduled from tc_dma_tx_interrupt() when one or more Out Isoc transfers -+ are done. This functions completes all URBs earlier marked with -+ isoc_out_done by fast interrupt routine check_finished_isoc_tx_epids() */ -+ -+static void complete_isoc_bottom_half(void *data) { -+ struct crisv10_isoc_complete_data *comp_data; -+ struct usb_iso_packet_descriptor *packet; -+ struct crisv10_urb_priv * urb_priv; -+ unsigned long flags; -+ struct urb* urb; -+ int epid_done; -+ int epid; -+ int i; -+ -+ comp_data = (struct crisv10_isoc_complete_data*)data; -+ -+ local_irq_save(flags); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS - 1; epid++) { -+ if(!epid_inuse(epid) || !epid_isoc(epid) || !epid_out_traffic(epid) || epid == DUMMY_EPID) { -+ /* Only check valid Out Isoc epids */ -+ continue; -+ } -+ -+ isoc_dbg("Isoc bottom-half checking epid:%d, sub:0x%x\n", epid, -+ (unsigned int)phys_to_virt(TxIsocEPList[epid].sub)); -+ -+ /* The descriptor interrupt handler has marked all transmitted Out Isoc -+ URBs with isoc_out_done. Now we traverse all epids and for all that -+ have out Isoc traffic we traverse its URB list and complete the -+ transmitted URBs. */ -+ epid_done = 0; -+ while (!epid_done) { -+ -+ /* Get the active urb (if any) */ -+ urb = activeUrbList[epid]; -+ if (urb == 0) { -+ isoc_dbg("No active URB on epid:%d anymore\n", epid); -+ epid_done = 1; -+ continue; -+ } -+ -+ /* Sanity check. */ -+ ASSERT(usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS); -+ ASSERT(usb_pipeout(urb->pipe)); -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ if (!(urb_priv->isoc_out_done)) { -+ /* We have reached URB that isn't flaged done yet, stop traversing. */ -+ isoc_dbg("Stoped traversing Out Isoc URBs on epid:%d" -+ " before not yet flaged URB:0x%x[%d]\n", -+ epid, (unsigned int)urb, urb_priv->urb_num); -+ epid_done = 1; -+ continue; -+ } -+ -+ /* This urb has been sent. */ -+ isoc_dbg("Found URB:0x%x[%d] that is flaged isoc_out_done\n", -+ (unsigned int)urb, urb_priv->urb_num); -+ -+ /* Set ok on transfered packets for this URB and finish it */ -+ for (i = 0; i < urb->number_of_packets; i++) { -+ packet = &urb->iso_frame_desc[i]; -+ packet->status = 0; -+ packet->actual_length = packet->length; -+ } -+ urb_priv->isoc_packet_counter = urb->number_of_packets; -+ tc_finish_urb(comp_data->hcd, urb, 0); -+ -+ } /* END: while(!epid_done) */ -+ } /* END: for(epid...) */ -+ -+ local_irq_restore(flags); -+ kmem_cache_free(isoc_compl_cache, comp_data); -+} -+#endif -+ -+static void check_finished_intr_tx_epids(struct usb_hcd *hcd) { -+ unsigned long flags; -+ int epid; -+ struct urb *urb; -+ struct crisv10_urb_priv * urb_priv; -+ volatile struct USB_EP_Desc *curr_ep; /* Current EP, the iterator. */ -+ volatile struct USB_EP_Desc *next_ep; /* The EP after current. */ -+ -+ /* Protect TxintrEPList */ -+ local_irq_save(flags); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ if(!epid_inuse(epid) || !epid_intr(epid) || !epid_out_traffic(epid)) { -+ /* Nothing to see on this epid. Only check valid Out Intr epids */ -+ continue; -+ } -+ -+ urb = activeUrbList[epid]; -+ if(urb == 0) { -+ intr_warn("Found Out Intr epid:%d with no active URB\n", epid); -+ continue; -+ } -+ -+ /* Sanity check. */ -+ ASSERT(usb_pipetype(urb->pipe) == PIPE_INTERRUPT); -+ ASSERT(usb_pipeout(urb->pipe)); -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ -+ /* Go through EPs between first and second sof-EP. It's here Out Intr EPs -+ are inserted.*/ -+ curr_ep = &TxIntrEPList[0]; -+ do { -+ next_ep = (struct USB_EP_Desc *)phys_to_virt(curr_ep->next); -+ if(next_ep == urb_priv->intr_ep_pool[0]) { -+ /* We found the Out Intr EP for this epid */ -+ -+ /* Disable it so it doesn't get processed again */ -+ next_ep->command &= ~IO_MASK(USB_EP_command, enable); -+ -+ /* Finish the active Out Intr URB with status OK */ -+ tc_finish_urb(hcd, urb, 0); -+ } -+ curr_ep = phys_to_virt(curr_ep->next); -+ } while (curr_ep != &TxIntrEPList[1]); -+ -+ } -+ local_irq_restore(flags); -+} -+ -+/* Interrupt handler for DMA8/IRQ24 with subchannels (called from hardware intr) */ -+static irqreturn_t tc_dma_tx_interrupt(int irq, void *vhc) { -+ struct usb_hcd *hcd = (struct usb_hcd*)vhc; -+ ASSERT(hcd); -+ -+ if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub0_descr)) { -+ /* Clear this interrupt */ -+ *R_DMA_CH8_SUB0_CLR_INTR = IO_STATE(R_DMA_CH8_SUB0_CLR_INTR, clr_descr, do); -+ restart_dma8_sub0(); -+ } -+ -+ if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub1_descr)) { -+ /* Clear this interrupt */ -+ *R_DMA_CH8_SUB1_CLR_INTR = IO_STATE(R_DMA_CH8_SUB1_CLR_INTR, clr_descr, do); -+ check_finished_ctrl_tx_epids(hcd); -+ } -+ -+ if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub2_descr)) { -+ /* Clear this interrupt */ -+ *R_DMA_CH8_SUB2_CLR_INTR = IO_STATE(R_DMA_CH8_SUB2_CLR_INTR, clr_descr, do); -+ check_finished_intr_tx_epids(hcd); -+ } -+ -+ /* hinko ignore usb_pipeisoc */ -+#if 0 -+ if (*R_IRQ_READ2 & IO_MASK(R_IRQ_READ2, dma8_sub3_descr)) { -+ struct crisv10_isoc_complete_data* comp_data; -+ -+ /* Flag done Out Isoc for later completion */ -+ check_finished_isoc_tx_epids(); -+ -+ /* Clear this interrupt */ -+ *R_DMA_CH8_SUB3_CLR_INTR = IO_STATE(R_DMA_CH8_SUB3_CLR_INTR, clr_descr, do); -+ /* Schedule bottom half of Out Isoc completion function. This function -+ finishes the URBs marked with isoc_out_done */ -+ comp_data = (struct crisv10_isoc_complete_data*) -+ kmem_cache_alloc(isoc_compl_cache, GFP_ATOMIC); -+ ASSERT(comp_data != NULL); -+ comp_data ->hcd = hcd; -+ -+ //INIT_WORK(&comp_data->usb_bh, complete_isoc_bottom_half, comp_data); -+ INIT_WORK(&comp_data->usb_bh, complete_isoc_bottom_half); -+ schedule_work(&comp_data->usb_bh); -+ } -+#endif -+ -+ return IRQ_HANDLED; -+} -+ -+/* Interrupt handler for DMA9/IRQ25 (called from hardware intr) */ -+static irqreturn_t tc_dma_rx_interrupt(int irq, void *vhc) { -+ unsigned long flags; -+ struct urb *urb; -+ struct usb_hcd *hcd = (struct usb_hcd*)vhc; -+ struct crisv10_urb_priv *urb_priv; -+ int epid = 0; -+ int real_error; -+ -+ ASSERT(hcd); -+ -+ /* Clear this interrupt. */ -+ *R_DMA_CH9_CLR_INTR = IO_STATE(R_DMA_CH9_CLR_INTR, clr_eop, do); -+ -+ /* Custom clear interrupt for this interrupt */ -+ /* The reason we cli here is that we call the driver's callback functions. */ -+ local_irq_save(flags); -+ -+ /* Note that this while loop assumes that all packets span only -+ one rx descriptor. */ -+ while(myNextRxDesc->status & IO_MASK(USB_IN_status, eop)) { -+ epid = IO_EXTRACT(USB_IN_status, epid, myNextRxDesc->status); -+ /* Get the active URB for this epid */ -+ urb = activeUrbList[epid]; -+ -+ ASSERT(epid_inuse(epid)); -+ if (!urb) { -+ dma_err("No urb for epid %d in rx interrupt\n", epid); -+ goto skip_out; -+ } -+ -+ /* Check if any errors on epid */ -+ real_error = 0; -+ if (myNextRxDesc->status & IO_MASK(USB_IN_status, error)) { -+ __u32 r_usb_ept_data; -+ -+ if (usb_pipeisoc(urb->pipe)) { -+ r_usb_ept_data = etrax_epid_iso_get(epid); -+ if((r_usb_ept_data & IO_MASK(R_USB_EPT_DATA_ISO, valid)) && -+ (IO_EXTRACT(R_USB_EPT_DATA_ISO, error_code, r_usb_ept_data) == 0) && -+ (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata))) { -+ /* Not an error, just a failure to receive an expected iso -+ in packet in this frame. This is not documented -+ in the designers reference. Continue processing. -+ */ -+ } else real_error = 1; -+ } else real_error = 1; -+ } -+ -+ if(real_error) { -+ dma_err("Error in RX descr on epid:%d for URB 0x%x", -+ epid, (unsigned int)urb); -+ dump_ept_data(epid); -+ dump_in_desc(myNextRxDesc); -+ goto skip_out; -+ } -+ -+ urb_priv = (struct crisv10_urb_priv *)urb->hcpriv; -+ ASSERT(urb_priv); -+ ASSERT(urb_priv->urb_state == STARTED || -+ urb_priv->urb_state == UNLINK); -+ -+ if ((usb_pipetype(urb->pipe) == PIPE_BULK) || -+ (usb_pipetype(urb->pipe) == PIPE_CONTROL) || -+ (usb_pipetype(urb->pipe) == PIPE_INTERRUPT)) { -+ -+ /* We get nodata for empty data transactions, and the rx descriptor's -+ hw_len field is not valid in that case. No data to copy in other -+ words. */ -+ if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) { -+ /* No data to copy */ -+ } else { -+ /* -+ dma_dbg("Processing RX for URB:0x%x epid:%d (data:%d ofs:%d)\n", -+ (unsigned int)urb, epid, myNextRxDesc->hw_len, -+ urb_priv->rx_offset); -+ */ -+ /* Only copy data if URB isn't flaged to be unlinked*/ -+ if(urb_priv->urb_state != UNLINK) { -+ /* Make sure the data fits in the buffer. */ -+ if(urb_priv->rx_offset + myNextRxDesc->hw_len -+ <= urb->transfer_buffer_length) { -+ -+ /* Copy the data to URBs buffer */ -+ memcpy(urb->transfer_buffer + urb_priv->rx_offset, -+ phys_to_virt(myNextRxDesc->buf), myNextRxDesc->hw_len); -+ urb_priv->rx_offset += myNextRxDesc->hw_len; -+ } else { -+ /* Signal overflow when returning URB */ -+ urb->status = -EOVERFLOW; -+ tc_finish_urb_later(hcd, urb, urb->status); -+ } -+ } -+ } -+ -+ /* Check if it was the last packet in the transfer */ -+ if (myNextRxDesc->status & IO_MASK(USB_IN_status, eot)) { -+ /* Special handling for In Ctrl URBs. */ -+ if(usb_pipecontrol(urb->pipe) && usb_pipein(urb->pipe) && -+ !(urb_priv->ctrl_zout_done)) { -+ /* Flag that RX part of Ctrl transfer is done. Because zout descr -+ interrupt hasn't happend yet will the URB be finished in the -+ TX-Interrupt. */ -+ urb_priv->ctrl_rx_done = 1; -+ tc_dbg("Not finishing In Ctrl URB:0x%x from rx_interrupt, waiting" -+ " for zout\n", (unsigned int)urb); -+ } else { -+ tc_finish_urb(hcd, urb, 0); -+ } -+ } -+ } else { /* ISOC RX */ -+ /* -+ isoc_dbg("Processing RX for epid:%d (URB:0x%x) ISOC pipe\n", -+ epid, (unsigned int)urb); -+ */ -+ -+ struct usb_iso_packet_descriptor *packet; -+ -+ if (urb_priv->urb_state == UNLINK) { -+ isoc_warn("Ignoring Isoc Rx data for urb being unlinked.\n"); -+ goto skip_out; -+ } else if (urb_priv->urb_state == NOT_STARTED) { -+ isoc_err("What? Got Rx data for Isoc urb that isn't started?\n"); -+ goto skip_out; -+ } -+ -+ packet = &urb->iso_frame_desc[urb_priv->isoc_packet_counter]; -+ ASSERT(packet); -+ packet->status = 0; -+ -+ if (myNextRxDesc->status & IO_MASK(USB_IN_status, nodata)) { -+ /* We get nodata for empty data transactions, and the rx descriptor's -+ hw_len field is not valid in that case. We copy 0 bytes however to -+ stay in synch. */ -+ packet->actual_length = 0; -+ } else { -+ packet->actual_length = myNextRxDesc->hw_len; -+ /* Make sure the data fits in the buffer. */ -+ ASSERT(packet->actual_length <= packet->length); -+ memcpy(urb->transfer_buffer + packet->offset, -+ phys_to_virt(myNextRxDesc->buf), packet->actual_length); -+ if(packet->actual_length > 0) -+ isoc_dbg("Copied %d bytes, packet %d for URB:0x%x[%d]\n", -+ packet->actual_length, urb_priv->isoc_packet_counter, -+ (unsigned int)urb, urb_priv->urb_num); -+ } -+ -+ /* Increment the packet counter. */ -+ urb_priv->isoc_packet_counter++; -+ -+ /* Note that we don't care about the eot field in the rx descriptor's -+ status. It will always be set for isoc traffic. */ -+ if (urb->number_of_packets == urb_priv->isoc_packet_counter) { -+ /* Complete the urb with status OK. */ -+ tc_finish_urb(hcd, urb, 0); -+ } -+ } -+ -+ skip_out: -+ myNextRxDesc->status = 0; -+ myNextRxDesc->command |= IO_MASK(USB_IN_command, eol); -+ myLastRxDesc->command &= ~IO_MASK(USB_IN_command, eol); -+ myLastRxDesc = myNextRxDesc; -+ myNextRxDesc = phys_to_virt(myNextRxDesc->next); -+ flush_etrax_cache(); -+ *R_DMA_CH9_CMD = IO_STATE(R_DMA_CH9_CMD, cmd, restart); -+ } -+ -+ local_irq_restore(flags); -+ -+ return IRQ_HANDLED; -+} -+ -+static void tc_bulk_start_timer_func(unsigned long dummy) { -+ /* We might enable an EP descriptor behind the current DMA position when -+ it's about to decide that there are no more bulk traffic and it should -+ stop the bulk channel. -+ Therefore we periodically check if the bulk channel is stopped and there -+ is an enabled bulk EP descriptor, in which case we start the bulk -+ channel. */ -+ -+ if (!(*R_DMA_CH8_SUB0_CMD & IO_MASK(R_DMA_CH8_SUB0_CMD, cmd))) { -+ int epid; -+ -+ timer_dbg("bulk_start_timer: Bulk DMA channel not running.\n"); -+ -+ for (epid = 0; epid < NBR_OF_EPIDS; epid++) { -+ if (TxBulkEPList[epid].command & IO_MASK(USB_EP_command, enable)) { -+ timer_warn("Found enabled EP for epid %d, starting bulk channel.\n", -+ epid); -+ restart_dma8_sub0(); -+ -+ /* Restart the bulk eot timer since we just started the bulk channel.*/ -+ mod_timer(&bulk_eot_timer, jiffies + BULK_EOT_TIMER_INTERVAL); -+ -+ /* No need to search any further. */ -+ break; -+ } -+ } -+ } else { -+ timer_dbg("bulk_start_timer: Bulk DMA channel running.\n"); -+ } -+} -+ -+static void tc_bulk_eot_timer_func(unsigned long dummy) { -+ struct usb_hcd *hcd = (struct usb_hcd*)dummy; -+ ASSERT(hcd); -+ /* Because of a race condition in the top half, we might miss a bulk eot. -+ This timer "simulates" a bulk eot if we don't get one for a while, -+ hopefully correcting the situation. */ -+ timer_dbg("bulk_eot_timer timed out.\n"); -+ check_finished_bulk_tx_epids(hcd, 1); -+} -+ -+ -+/*************************************************************/ -+/*************************************************************/ -+/* Device driver block */ -+/*************************************************************/ -+/*************************************************************/ -+ -+/* Forward declarations for device driver functions */ -+static int devdrv_hcd_probe(struct device *); -+static int devdrv_hcd_remove(struct device *); -+#ifdef CONFIG_PM -+static int devdrv_hcd_suspend(struct device *, u32, u32); -+static int devdrv_hcd_resume(struct device *, u32); -+#endif /* CONFIG_PM */ -+ -+/* the device */ -+static struct platform_device *devdrv_hc_platform_device; -+ -+/* device driver interface */ -+static struct device_driver devdrv_hc_device_driver = { -+ .name = (char *) hc_name, -+ .bus = &platform_bus_type, -+ -+ .probe = devdrv_hcd_probe, -+ .remove = devdrv_hcd_remove, -+ -+#ifdef CONFIG_PM -+ .suspend = devdrv_hcd_suspend, -+ .resume = devdrv_hcd_resume, -+#endif /* CONFIG_PM */ -+}; -+ -+/* initialize the host controller and driver */ -+static int __init_or_module devdrv_hcd_probe(struct device *dev) -+{ -+ struct usb_hcd *hcd; -+ struct crisv10_hcd *crisv10_hcd; -+ int retval; -+ -+ /* Check DMA burst length */ -+ if(IO_EXTRACT(R_BUS_CONFIG, dma_burst, *R_BUS_CONFIG) != -+ IO_STATE(R_BUS_CONFIG, dma_burst, burst32)) { -+ devdrv_err("Invalid DMA burst length in Etrax 100LX," -+ " needs to be 32\n"); -+ return -EPERM; -+ } -+ -+ hcd = usb_create_hcd(&crisv10_hc_driver, dev, dev->bus_id); -+ if (!hcd) -+ return -ENOMEM; -+ -+ crisv10_hcd = hcd_to_crisv10_hcd(hcd); -+ spin_lock_init(&crisv10_hcd->lock); -+ crisv10_hcd->num_ports = num_ports(); -+ crisv10_hcd->running = 0; -+ -+ dev_set_drvdata(dev, crisv10_hcd); -+ -+ devdrv_dbg("ETRAX USB IRQs HC:%d RX:%d TX:%d\n", ETRAX_USB_HC_IRQ, -+ ETRAX_USB_RX_IRQ, ETRAX_USB_TX_IRQ); -+ -+ /* Print out chip version read from registers */ -+ int rev_maj = *R_USB_REVISION & IO_MASK(R_USB_REVISION, major); -+ int rev_min = *R_USB_REVISION & IO_MASK(R_USB_REVISION, minor); -+ if(rev_min == 0) { -+ devdrv_info("Etrax 100LX USB Revision %d v1,2\n", rev_maj); -+ } else { -+ devdrv_info("Etrax 100LX USB Revision %d v%d\n", rev_maj, rev_min); -+ } -+ -+ devdrv_info("Bulk timer interval, start:%d eot:%d\n", -+ BULK_START_TIMER_INTERVAL, -+ BULK_EOT_TIMER_INTERVAL); -+ -+ -+ /* Init root hub data structures */ -+ if(rh_init()) { -+ devdrv_err("Failed init data for Root Hub\n"); -+ retval = -ENOMEM; -+ } -+ -+ if(port_in_use(0)) { -+ if (cris_request_io_interface(if_usb_1, "ETRAX100LX USB-HCD")) { -+ printk(KERN_CRIT "usb-host: request IO interface usb1 failed"); -+ retval = -EBUSY; -+ goto out; -+ } -+ devdrv_info("Claimed interface for USB physical port 1\n"); -+ } -+ if(port_in_use(1)) { -+ if (cris_request_io_interface(if_usb_2, "ETRAX100LX USB-HCD")) { -+ /* Free first interface if second failed to be claimed */ -+ if(port_in_use(0)) { -+ cris_free_io_interface(if_usb_1); -+ } -+ printk(KERN_CRIT "usb-host: request IO interface usb2 failed"); -+ retval = -EBUSY; -+ goto out; -+ } -+ devdrv_info("Claimed interface for USB physical port 2\n"); -+ } -+ -+ /* Init transfer controller structs and locks */ -+ if((retval = tc_init(hcd)) != 0) { -+ goto out; -+ } -+ -+ /* Attach interrupt functions for DMA and init DMA controller */ -+ if((retval = tc_dma_init(hcd)) != 0) { -+ goto out; -+ } -+ -+ /* Attach the top IRQ handler for USB controller interrupts */ -+ if (request_irq(ETRAX_USB_HC_IRQ, crisv10_hcd_top_irq, 0, -+ "ETRAX 100LX built-in USB (HC)", hcd)) { -+ err("Could not allocate IRQ %d for USB", ETRAX_USB_HC_IRQ); -+ retval = -EBUSY; -+ goto out; -+ } -+ -+ /* iso_eof is only enabled when isoc traffic is running. */ -+ *R_USB_IRQ_MASK_SET = -+ /* IO_STATE(R_USB_IRQ_MASK_SET, iso_eof, set) | */ -+ IO_STATE(R_USB_IRQ_MASK_SET, bulk_eot, set) | -+ IO_STATE(R_USB_IRQ_MASK_SET, epid_attn, set) | -+ IO_STATE(R_USB_IRQ_MASK_SET, port_status, set) | -+ IO_STATE(R_USB_IRQ_MASK_SET, ctl_status, set); -+ -+ -+ crisv10_ready_wait(); -+ /* Reset the USB interface. */ -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, reset); -+ -+ /* Designer's Reference, p. 8 - 10 says we should Initate R_USB_FM_PSTART to -+ 0x2A30 (10800), to guarantee that control traffic gets 10% of the -+ bandwidth, and periodic transfer may allocate the rest (90%). -+ This doesn't work though. -+ The value 11960 is chosen to be just after the SOF token, with a couple -+ of bit times extra for possible bit stuffing. */ -+ *R_USB_FM_PSTART = IO_FIELD(R_USB_FM_PSTART, value, 11960); -+ -+ crisv10_ready_wait(); -+ /* Configure the USB interface as a host controller. */ -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, host_config); -+ -+ -+ /* Check so controller not busy before enabling ports */ -+ crisv10_ready_wait(); -+ -+ /* Enable selected USB ports */ -+ if(port_in_use(0)) { -+ *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, no); -+ } else { -+ *R_USB_PORT1_DISABLE = IO_STATE(R_USB_PORT1_DISABLE, disable, yes); -+ } -+ if(port_in_use(1)) { -+ *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, no); -+ } else { -+ *R_USB_PORT2_DISABLE = IO_STATE(R_USB_PORT2_DISABLE, disable, yes); -+ } -+ -+ crisv10_ready_wait(); -+ /* Start processing of USB traffic. */ -+ *R_USB_COMMAND = -+ IO_STATE(R_USB_COMMAND, port_sel, nop) | -+ IO_STATE(R_USB_COMMAND, port_cmd, reset) | -+ IO_STATE(R_USB_COMMAND, ctrl_cmd, host_run); -+ -+ /* Do not continue probing initialization before USB interface is done */ -+ crisv10_ready_wait(); -+ -+ /* Register our Host Controller to USB Core -+ * Finish the remaining parts of generic HCD initialization: allocate the -+ * buffers of consistent memory, register the bus -+ * and call the driver's reset() and start() routines. */ -+ retval = usb_add_hcd(hcd, ETRAX_USB_HC_IRQ, IRQF_DISABLED); -+ if (retval != 0) { -+ devdrv_err("Failed registering HCD driver\n"); -+ goto out; -+ } -+ -+ return 0; -+ -+ out: -+ devdrv_hcd_remove(dev); -+ return retval; -+} -+ -+ -+/* cleanup after the host controller and driver */ -+static int __init_or_module devdrv_hcd_remove(struct device *dev) -+{ -+ struct crisv10_hcd *crisv10_hcd = dev_get_drvdata(dev); -+ struct usb_hcd *hcd; -+ -+ if (!crisv10_hcd) -+ return 0; -+ hcd = crisv10_hcd_to_hcd(crisv10_hcd); -+ -+ -+ /* Stop USB Controller in Etrax 100LX */ -+ crisv10_hcd_reset(hcd); -+ -+ usb_remove_hcd(hcd); -+ devdrv_dbg("Removed HCD from USB Core\n"); -+ -+ /* Free USB Controller IRQ */ -+ free_irq(ETRAX_USB_HC_IRQ, NULL); -+ -+ /* Free resources */ -+ tc_dma_destroy(); -+ tc_destroy(); -+ -+ -+ if(port_in_use(0)) { -+ cris_free_io_interface(if_usb_1); -+ } -+ if(port_in_use(1)) { -+ cris_free_io_interface(if_usb_2); -+ } -+ -+ devdrv_dbg("Freed all claimed resources\n"); -+ -+ return 0; -+} -+ -+ -+#ifdef CONFIG_PM -+ -+static int devdrv_hcd_suspend(struct usb_hcd *hcd, u32 state, u32 level) -+{ -+ return 0; /* no-op for now */ -+} -+ -+static int devdrv_hcd_resume(struct usb_hcd *hcd, u32 level) -+{ -+ return 0; /* no-op for now */ -+} -+ -+#endif /* CONFIG_PM */ -+ -+ -+ -+/*************************************************************/ -+/*************************************************************/ -+/* Module block */ -+/*************************************************************/ -+/*************************************************************/ -+ -+/* register driver */ -+static int __init module_hcd_init(void) -+{ -+ -+ if (usb_disabled()) -+ return -ENODEV; -+ -+ /* Here we select enabled ports by following defines created from -+ menuconfig */ -+#ifndef CONFIG_ETRAX_USB_HOST_PORT1 -+ ports &= ~(1<<0); -+#endif -+#ifndef CONFIG_ETRAX_USB_HOST_PORT2 -+ ports &= ~(1<<1); -+#endif -+ -+ printk(KERN_INFO "%s version "VERSION" "COPYRIGHT"\n", product_desc); -+ -+ devdrv_hc_platform_device = -+ platform_device_register_simple((char *) hc_name, 0, NULL, 0); -+ -+ if (IS_ERR(devdrv_hc_platform_device)) -+ return PTR_ERR(devdrv_hc_platform_device); -+ return driver_register(&devdrv_hc_device_driver); -+ /* -+ * Note that we do not set the DMA mask for the device, -+ * i.e. we pretend that we will use PIO, since no specific -+ * allocation routines are needed for DMA buffers. This will -+ * cause the HCD buffer allocation routines to fall back to -+ * kmalloc(). -+ */ -+} -+ -+/* unregister driver */ -+static void __exit module_hcd_exit(void) -+{ -+ driver_unregister(&devdrv_hc_device_driver); -+} -+ -+ -+/* Module hooks */ -+module_init(module_hcd_init); -+module_exit(module_hcd_exit); ---- /dev/null -+++ b/drivers/usb/host/hc-crisv10.h -@@ -0,0 +1,331 @@ -+#ifndef __LINUX_ETRAX_USB_H -+#define __LINUX_ETRAX_USB_H -+ -+#include -+#include -+ -+struct USB_IN_Desc { -+ volatile __u16 sw_len; -+ volatile __u16 command; -+ volatile unsigned long next; -+ volatile unsigned long buf; -+ volatile __u16 hw_len; -+ volatile __u16 status; -+}; -+ -+struct USB_SB_Desc { -+ volatile __u16 sw_len; -+ volatile __u16 command; -+ volatile unsigned long next; -+ volatile unsigned long buf; -+}; -+ -+struct USB_EP_Desc { -+ volatile __u16 hw_len; -+ volatile __u16 command; -+ volatile unsigned long sub; -+ volatile unsigned long next; -+}; -+ -+ -+/* Root Hub port status struct */ -+struct crisv10_rh { -+ volatile __u16 wPortChange[2]; -+ volatile __u16 wPortStatusPrev[2]; -+}; -+ -+/* HCD description */ -+struct crisv10_hcd { -+ spinlock_t lock; -+ __u8 num_ports; -+ __u8 running; -+}; -+ -+ -+/* Endpoint HC private data description */ -+struct crisv10_ep_priv { -+ int epid; -+}; -+ -+/* Additional software state info for a USB Controller epid */ -+struct etrax_epid { -+ __u8 inuse; /* !0 = setup in Etrax and used for a endpoint */ -+ __u8 disabled; /* !0 = Temporarly disabled to avoid resubmission */ -+ __u8 type; /* Setup as: PIPE_BULK, PIPE_CONTROL ... */ -+ __u8 out_traffic; /* !0 = This epid is for out traffic */ -+}; -+ -+/* Struct to hold information of scheduled later URB completion */ -+struct urb_later_data { -+// struct work_struct ws; -+ struct delayed_work ws; -+ struct usb_hcd *hcd; -+ struct urb *urb; -+ int urb_num; -+ int status; -+}; -+ -+ -+typedef enum { -+ STARTED, -+ NOT_STARTED, -+ UNLINK, -+} crisv10_urb_state_t; -+ -+ -+struct crisv10_urb_priv { -+ /* Sequence number for this URB. Every new submited URB gets this from -+ a incrementing counter. Used when a URB is scheduled for later finish to -+ be sure that the intended URB hasn't already been completed (device -+ drivers has a tendency to reuse URBs once they are completed, causing us -+ to not be able to single old ones out only based on the URB pointer.) */ -+ __u32 urb_num; -+ -+ /* The first_sb field is used for freeing all SB descriptors belonging -+ to an urb. The corresponding ep descriptor's sub pointer cannot be -+ used for this since the DMA advances the sub pointer as it processes -+ the sb list. */ -+ struct USB_SB_Desc *first_sb; -+ -+ /* The last_sb field referes to the last SB descriptor that belongs to -+ this urb. This is important to know so we can free the SB descriptors -+ that ranges between first_sb and last_sb. */ -+ struct USB_SB_Desc *last_sb; -+ -+ /* The rx_offset field is used in ctrl and bulk traffic to keep track -+ of the offset in the urb's transfer_buffer where incoming data should be -+ copied to. */ -+ __u32 rx_offset; -+ -+ /* Counter used in isochronous transfers to keep track of the -+ number of packets received/transmitted. */ -+ __u32 isoc_packet_counter; -+ -+ /* Flag that marks if this Isoc Out URB has finished it's transfer. Used -+ because several URBs can be finished before list is processed */ -+ __u8 isoc_out_done; -+ -+ /* This field is used to pass information about the urb's current state -+ between the various interrupt handlers (thus marked volatile). */ -+ volatile crisv10_urb_state_t urb_state; -+ -+ /* In Ctrl transfers consist of (at least) 3 packets: SETUP, IN and ZOUT. -+ When DMA8 sub-channel 2 has processed the SB list for this sequence we -+ get a interrupt. We also get a interrupt for In transfers and which -+ one of these interrupts that comes first depends of data size and device. -+ To be sure that we have got both interrupts before we complete the URB -+ we have these to flags that shows which part that has completed. -+ We can then check when we get one of the interrupts that if the other has -+ occured it's safe for us to complete the URB, otherwise we set appropriate -+ flag and do the completion when we get the other interrupt. */ -+ volatile unsigned char ctrl_zout_done; -+ volatile unsigned char ctrl_rx_done; -+ -+ /* Connection between the submitted urb and ETRAX epid number */ -+ __u8 epid; -+ -+ /* The rx_data_list field is used for periodic traffic, to hold -+ received data for later processing in the the complete_urb functions, -+ where the data us copied to the urb's transfer_buffer. Basically, we -+ use this intermediate storage because we don't know when it's safe to -+ reuse the transfer_buffer (FIXME?). */ -+ struct list_head rx_data_list; -+ -+ -+ /* The interval time rounded up to closest 2^N */ -+ int interval; -+ -+ /* Pool of EP descriptors needed if it's a INTR transfer. -+ Amount of EPs in pool correspons to how many INTR that should -+ be inserted in TxIntrEPList (max 128, defined by MAX_INTR_INTERVAL) */ -+ struct USB_EP_Desc* intr_ep_pool[128]; -+ -+ /* The mount of EPs allocated for this INTR URB */ -+ int intr_ep_pool_length; -+ -+ /* Pointer to info struct if URB is scheduled to be finished later */ -+ struct urb_later_data* later_data; -+}; -+ -+ -+/* This struct is for passing data from the top half to the bottom half irq -+ handlers */ -+struct crisv10_irq_reg { -+ struct usb_hcd* hcd; -+ __u32 r_usb_epid_attn; -+ __u8 r_usb_status; -+ __u16 r_usb_rh_port_status_1; -+ __u16 r_usb_rh_port_status_2; -+ __u32 r_usb_irq_mask_read; -+ __u32 r_usb_fm_number; -+ struct work_struct usb_bh; -+}; -+ -+ -+/* This struct is for passing data from the isoc top half to the isoc bottom -+ half. */ -+struct crisv10_isoc_complete_data { -+ struct usb_hcd *hcd; -+ struct urb *urb; -+ struct work_struct usb_bh; -+}; -+ -+/* Entry item for URB lists for each endpint */ -+typedef struct urb_entry -+{ -+ struct urb *urb; -+ struct list_head list; -+} urb_entry_t; -+ -+/* --------------------------------------------------------------------------- -+ Virtual Root HUB -+ ------------------------------------------------------------------------- */ -+/* destination of request */ -+#define RH_INTERFACE 0x01 -+#define RH_ENDPOINT 0x02 -+#define RH_OTHER 0x03 -+ -+#define RH_CLASS 0x20 -+#define RH_VENDOR 0x40 -+ -+/* Requests: bRequest << 8 | bmRequestType */ -+#define RH_GET_STATUS 0x0080 -+#define RH_CLEAR_FEATURE 0x0100 -+#define RH_SET_FEATURE 0x0300 -+#define RH_SET_ADDRESS 0x0500 -+#define RH_GET_DESCRIPTOR 0x0680 -+#define RH_SET_DESCRIPTOR 0x0700 -+#define RH_GET_CONFIGURATION 0x0880 -+#define RH_SET_CONFIGURATION 0x0900 -+#define RH_GET_STATE 0x0280 -+#define RH_GET_INTERFACE 0x0A80 -+#define RH_SET_INTERFACE 0x0B00 -+#define RH_SYNC_FRAME 0x0C80 -+/* Our Vendor Specific Request */ -+#define RH_SET_EP 0x2000 -+ -+ -+/* Hub port features */ -+#define RH_PORT_CONNECTION 0x00 -+#define RH_PORT_ENABLE 0x01 -+#define RH_PORT_SUSPEND 0x02 -+#define RH_PORT_OVER_CURRENT 0x03 -+#define RH_PORT_RESET 0x04 -+#define RH_PORT_POWER 0x08 -+#define RH_PORT_LOW_SPEED 0x09 -+#define RH_C_PORT_CONNECTION 0x10 -+#define RH_C_PORT_ENABLE 0x11 -+#define RH_C_PORT_SUSPEND 0x12 -+#define RH_C_PORT_OVER_CURRENT 0x13 -+#define RH_C_PORT_RESET 0x14 -+ -+/* Hub features */ -+#define RH_C_HUB_LOCAL_POWER 0x00 -+#define RH_C_HUB_OVER_CURRENT 0x01 -+ -+#define RH_DEVICE_REMOTE_WAKEUP 0x00 -+#define RH_ENDPOINT_STALL 0x01 -+ -+/* Our Vendor Specific feature */ -+#define RH_REMOVE_EP 0x00 -+ -+ -+#define RH_ACK 0x01 -+#define RH_REQ_ERR -1 -+#define RH_NACK 0x00 -+ -+/* Field definitions for */ -+ -+#define USB_IN_command__eol__BITNR 0 /* command macros */ -+#define USB_IN_command__eol__WIDTH 1 -+#define USB_IN_command__eol__no 0 -+#define USB_IN_command__eol__yes 1 -+ -+#define USB_IN_command__intr__BITNR 3 -+#define USB_IN_command__intr__WIDTH 1 -+#define USB_IN_command__intr__no 0 -+#define USB_IN_command__intr__yes 1 -+ -+#define USB_IN_status__eop__BITNR 1 /* status macros. */ -+#define USB_IN_status__eop__WIDTH 1 -+#define USB_IN_status__eop__no 0 -+#define USB_IN_status__eop__yes 1 -+ -+#define USB_IN_status__eot__BITNR 5 -+#define USB_IN_status__eot__WIDTH 1 -+#define USB_IN_status__eot__no 0 -+#define USB_IN_status__eot__yes 1 -+ -+#define USB_IN_status__error__BITNR 6 -+#define USB_IN_status__error__WIDTH 1 -+#define USB_IN_status__error__no 0 -+#define USB_IN_status__error__yes 1 -+ -+#define USB_IN_status__nodata__BITNR 7 -+#define USB_IN_status__nodata__WIDTH 1 -+#define USB_IN_status__nodata__no 0 -+#define USB_IN_status__nodata__yes 1 -+ -+#define USB_IN_status__epid__BITNR 8 -+#define USB_IN_status__epid__WIDTH 5 -+ -+#define USB_EP_command__eol__BITNR 0 -+#define USB_EP_command__eol__WIDTH 1 -+#define USB_EP_command__eol__no 0 -+#define USB_EP_command__eol__yes 1 -+ -+#define USB_EP_command__eof__BITNR 1 -+#define USB_EP_command__eof__WIDTH 1 -+#define USB_EP_command__eof__no 0 -+#define USB_EP_command__eof__yes 1 -+ -+#define USB_EP_command__intr__BITNR 3 -+#define USB_EP_command__intr__WIDTH 1 -+#define USB_EP_command__intr__no 0 -+#define USB_EP_command__intr__yes 1 -+ -+#define USB_EP_command__enable__BITNR 4 -+#define USB_EP_command__enable__WIDTH 1 -+#define USB_EP_command__enable__no 0 -+#define USB_EP_command__enable__yes 1 -+ -+#define USB_EP_command__hw_valid__BITNR 5 -+#define USB_EP_command__hw_valid__WIDTH 1 -+#define USB_EP_command__hw_valid__no 0 -+#define USB_EP_command__hw_valid__yes 1 -+ -+#define USB_EP_command__epid__BITNR 8 -+#define USB_EP_command__epid__WIDTH 5 -+ -+#define USB_SB_command__eol__BITNR 0 /* command macros. */ -+#define USB_SB_command__eol__WIDTH 1 -+#define USB_SB_command__eol__no 0 -+#define USB_SB_command__eol__yes 1 -+ -+#define USB_SB_command__eot__BITNR 1 -+#define USB_SB_command__eot__WIDTH 1 -+#define USB_SB_command__eot__no 0 -+#define USB_SB_command__eot__yes 1 -+ -+#define USB_SB_command__intr__BITNR 3 -+#define USB_SB_command__intr__WIDTH 1 -+#define USB_SB_command__intr__no 0 -+#define USB_SB_command__intr__yes 1 -+ -+#define USB_SB_command__tt__BITNR 4 -+#define USB_SB_command__tt__WIDTH 2 -+#define USB_SB_command__tt__zout 0 -+#define USB_SB_command__tt__in 1 -+#define USB_SB_command__tt__out 2 -+#define USB_SB_command__tt__setup 3 -+ -+ -+#define USB_SB_command__rem__BITNR 8 -+#define USB_SB_command__rem__WIDTH 6 -+ -+#define USB_SB_command__full__BITNR 6 -+#define USB_SB_command__full__WIDTH 1 -+#define USB_SB_command__full__no 0 -+#define USB_SB_command__full__yes 1 -+ -+#endif diff --git a/target/linux/etrax/profiles/100-generic.mk b/target/linux/etrax/profiles/100-generic.mk deleted file mode 100644 index 9d0fc72f88..0000000000 --- a/target/linux/etrax/profiles/100-generic.mk +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/default - NAME:=Normal (default) -endef - -define Profile/default/Description - Normal Foxboard setup (no vhdl) -endef -$(eval $(call Profile,default)) - diff --git a/target/linux/etrax/profiles/101-vhdl-nofb.mk b/target/linux/etrax/profiles/101-vhdl-nofb.mk deleted file mode 100644 index 620db4209a..0000000000 --- a/target/linux/etrax/profiles/101-vhdl-nofb.mk +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (C) 2006 OpenWrt.org -# -# This is free software, licensed under the GNU General Public License v2. -# See /LICENSE for more information. -# - -define Profile/vhdl_no_fb - NAME:=FOXVHDL no fb -# PACKAGES:=kmod-madwifi -endef - -define Profile/vhdl_no_fb/Description - Setup the Foxboard for FOXVHDL support with no framebuffer -endef -$(eval $(call Profile,vhdl_no_fb)) - diff --git a/target/linux/etrax/Makefile b/target/linux/ifxmips/Makefile similarity index 51% rename from target/linux/etrax/Makefile rename to target/linux/ifxmips/Makefile index dcc0c37a71..de982abf17 100644 --- a/target/linux/etrax/Makefile +++ b/target/linux/ifxmips/Makefile @@ -1,23 +1,22 @@ # -# Copyright (C) 2006 OpenWrt.org +# Copyright (C) 2007 OpenWrt.org # # This is free software, licensed under the GNU General Public License v2. # See /LICENSE for more information. # include $(TOPDIR)/rules.mk -ARCH:=cris -BOARD:=etrax -BOARDNAME:=Foxboard (ETRAX 100LX) -FEATURES:=squashfs jffs2 broken -LINUX_VERSION:=2.6.25.17 +ARCH:=mips +BOARD:=ifxmips +BOARDNAME:=Infineon Mips +FEATURES:=squashfs jffs2 +LINUX_VERSION:=2.6.26.5 include $(INCLUDE_DIR)/target.mk - -KERNELNAME:="zImage" +DEFAULT_PACKAGES+=uboot-ifxmips define Target/Description - Build firmware images for the FOXBOARD made by acmesystems.it + Build firmware images for Infineon Mips Controllers endef $(eval $(call BuildTarget)) diff --git a/target/linux/ifxmips/base-files/etc/hotplug.d/button/00-reset b/target/linux/ifxmips/base-files/etc/hotplug.d/button/00-reset new file mode 100644 index 0000000000..ef70cd49a5 --- /dev/null +++ b/target/linux/ifxmips/base-files/etc/hotplug.d/button/00-reset @@ -0,0 +1,3 @@ +[ "$ACTION" = "released" -a "$BUTTON" = reset ] && { + reboot +} diff --git a/target/linux/ifxmips/base-files/etc/inittab b/target/linux/ifxmips/base-files/etc/inittab new file mode 100644 index 0000000000..7989a7f60e --- /dev/null +++ b/target/linux/ifxmips/base-files/etc/inittab @@ -0,0 +1,4 @@ +::sysinit:/etc/init.d/rcS S boot +::shutdown:/etc/init.d/rcS K stop +ttyS0::askfirst:/bin/ash --login +ttyS1::askfirst:/bin/ash --login diff --git a/target/linux/ifxmips/config-2.6.26 b/target/linux/ifxmips/config-2.6.26 new file mode 100644 index 0000000000..9b506672ec --- /dev/null +++ b/target/linux/ifxmips/config-2.6.26 @@ -0,0 +1,236 @@ +CONFIG_32BIT=y +# CONFIG_64BIT is not set +# CONFIG_8139TOO is not set +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set +CONFIG_ARCH_POPULATES_NODE_MAP=y +# CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_ARCH_SUPPORTS_OPROFILE=y +CONFIG_ARCH_SUSPEND_POSSIBLE=y +# CONFIG_ATM is not set +CONFIG_BASE_SMALL=0 +# CONFIG_BCM47XX is not set +CONFIG_BITREVERSE=y +# CONFIG_BT is not set +CONFIG_CEVT_R4K=y +CONFIG_CLASSIC_RCU=y +CONFIG_CMDLINE="console=ttyS0,9600 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_CRYPTO_GF128MUL=m +CONFIG_CSRC_R4K=y +CONFIG_DEVPORT=y +# CONFIG_DM9000 is not set +CONFIG_DMA_NEED_PCI_MAP_STATE=y +CONFIG_DMA_NONCOHERENT=y +# CONFIG_E1000E_ENABLED is not set +CONFIG_EARLY_PRINTK=y +CONFIG_FS_POSIX_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_GPIO_DEVICE=y +CONFIG_HAS_DMA=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +# CONFIG_HAVE_DMA_ATTRS is not set +CONFIG_HAVE_IDE=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +CONFIG_HAVE_OPROFILE=y +CONFIG_HAVE_STD_PC_SERIAL_PORT=y +# CONFIG_HIGH_RES_TIMERS is not set +# CONFIG_HOSTAP is not set +CONFIG_HW_HAS_PCI=y +CONFIG_HW_RANDOM=y +# CONFIG_I2C is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IDE is not set +CONFIG_IFXMIPS=y +CONFIG_IFXMIPS_EEPROM=y +CONFIG_IFXMIPS_GPIO_RST_BTN=y +# CONFIG_IFXMIPS_MEI is not set +CONFIG_IFXMIPS_MII0=y +# CONFIG_IFXMIPS_PROM_ASC0 is not set +CONFIG_IFXMIPS_PROM_ASC1=y +CONFIG_IFXMIPS_SSC=y +CONFIG_IFXMIPS_WDT=y +CONFIG_INITRAMFS_SOURCE="" +CONFIG_IPV6_NDISC_NODETYPE=y +CONFIG_IRQ_CPU=y +# CONFIG_IWLWIFI_LEDS is not set +CONFIG_KALLSYMS=y +# CONFIG_LEDS_ALIX is not set +CONFIG_LEDS_GPIO=y +CONFIG_LEDS_IFXMIPS=y +# 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_VR41XX is not set +CONFIG_MIPS=y +# CONFIG_MIPS_ATLAS is not set +# 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_SEAD is not set +# CONFIG_MIPS_SIM is not set +CONFIG_MTD=y +# CONFIG_MTD_ABSENT 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=y +CONFIG_MTD_CFI_AMDSTD=y +# CONFIG_MTD_CFI_BE_BYTE_SWAP is not set +CONFIG_MTD_CFI_GEOMETRY=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_LE_BYTE_SWAP is not set +CONFIG_MTD_CFI_NOSWAP=y +# CONFIG_MTD_CFI_STAA is not set +CONFIG_MTD_CFI_UTIL=y +CONFIG_MTD_CHAR=y +# CONFIG_MTD_CMDLINE_PARTS is not set +CONFIG_MTD_COMPLEX_MAPPINGS=y +# CONFIG_MTD_CONCAT is not set +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_GEN_PROBE=y +CONFIG_MTD_IFXMIPS=y +# CONFIG_MTD_JEDECPROBE is not set +# CONFIG_MTD_MAP_BANK_WIDTH_1 is not set +# 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 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_ONENAND is not set +# CONFIG_MTD_OTP is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_PCI is not set +# CONFIG_MTD_PHRAM is not set +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_PHYSMAP_BANKWIDTH=0 +CONFIG_MTD_PHYSMAP_LEN=0x0 +CONFIG_MTD_PHYSMAP_START=0x0 +# CONFIG_MTD_PLATRAM is not set +# CONFIG_MTD_PMC551 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_REDBOOT_PARTS is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_SLRAM is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_NET_VENDOR_3COM is not set +# CONFIG_NO_IOPORT is not set +# CONFIG_OCF_OCF 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_PCI=y +# CONFIG_PCIPCWATCHDOG is not set +CONFIG_PCI_DOMAINS=y +CONFIG_PCSPKR_PLATFORM=y +# CONFIG_PMC_MSP is not set +# CONFIG_PMC_YOSEMITE is not set +# CONFIG_PNX8550_JBS is not set +# CONFIG_PNX8550_STB810 is not set +# CONFIG_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_IFXMIPS=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_SOFT_WATCHDOG is not set +# 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_TC35815 is not set +# CONFIG_THERMAL is not set +# CONFIG_THERMAL_HWMON is not set +# CONFIG_TICK_ONESHOT is not set +# CONFIG_TOSHIBA_JMR3927 is not set +# CONFIG_TOSHIBA_RBTX4927 is not set +# CONFIG_TOSHIBA_RBTX4938 is not set +CONFIG_TRAD_SIGNALS=y +CONFIG_USB=m +# CONFIG_USB_DWC_HCD is not set +# CONFIG_USB_EHCI_HCD is not set +# CONFIG_USB_ISIGHTFW is not set +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_V4L1=m +CONFIG_VIDEO_V4L2=m +CONFIG_VIDEO_V4L2_COMMON=m +CONFIG_ZONE_DMA_FLAG=0 diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/Kconfig b/target/linux/ifxmips/files/arch/mips/ifxmips/Kconfig new file mode 100644 index 0000000000..621020f83f --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/Kconfig @@ -0,0 +1,40 @@ +# copyright 2007 john crispin + +menu "IFXMips built-in" + +config MTD_IFXMIPS + bool "IFXMips flash map" + default y + +config IFXMIPS_SSC + bool "IFXMips ssc" + default y + +config IFXMIPS_EEPROM + bool "IFXMips eeprom" + default y + +config IFXMIPS_MEI + bool "IFXMips mei" + default y + +config IFXMIPS_GPIO_RST_BTN + bool "Reset Button" + default y + +choice + prompt "prom_printf ASC" + help + Choose which serial port is used, until the console driver is loaded + +config IFXMIPS_PROM_ASC0 + bool "ASC0" + +config IFXMIPS_PROM_ASC1 + bool "ASC1" + +endchoice + + +endmenu + diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile new file mode 100644 index 0000000000..eb9a77ede4 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/Makefile @@ -0,0 +1 @@ +obj-y := reset.o prom.o setup.o interrupt.o dma-core.o pmu.o board.o clock.o timer.o gpio.o diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/board.c b/target/linux/ifxmips/files/arch/mips/ifxmips/board.c new file mode 100644 index 0000000000..86a2595fad --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/board.c @@ -0,0 +1,381 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_BOARD_NAME_LEN 32 +#define MAX_IFXMIPS_DEVS 9 + +#define SYSTEM_DANUBE "Danube" +#define SYSTEM_DANUBE_CHIPID1 0x10129083 +#define SYSTEM_DANUBE_CHIPID2 0x3012B083 + +#define SYSTEM_TWINPASS "Twinpass" +#define SYSTEM_TWINPASS_CHIPID 0x3012D083 + +enum { + EASY50712, + EASY4010, + ARV4519, +}; + +extern int ifxmips_pci_external_clock; + +static unsigned int chiprev; +static int cmdline_mac = 0; +char board_name[MAX_BOARD_NAME_LEN + 1] = { 0 }; + +struct ifxmips_board { + int type; + char name[32]; + unsigned int system_type; + struct platform_device **devs; + struct resource reset_resource; + struct resource gpiodev_resource; + struct gpio_led *ifxmips_leds; + struct gpio_led *gpio_leds; + int pci_external_clock; + int num_devs; +}; + +spinlock_t ebu_lock = SPIN_LOCK_UNLOCKED; +EXPORT_SYMBOL_GPL(ebu_lock); + +static unsigned char ifxmips_mii_mac[6]; +static int ifxmips_brn = 0; + +static struct gpio_led_platform_data ifxmips_led_data; + +static struct platform_device +ifxmips_led = +{ + .id = 0, + .name = "ifxmips_led", + .dev = { + .platform_data = (void *) &ifxmips_led_data, + } +}; + +static struct platform_device +ifxmips_gpio = +{ + .id = 0, + .name = "ifxmips_gpio", + .num_resources = 1, +}; + +static struct platform_device +ifxmips_mii = +{ + .id = 0, + .name = "ifxmips_mii0", + .dev = { + .platform_data = ifxmips_mii_mac, + } +}; + +static struct platform_device +ifxmips_wdt = +{ + .id = 0, + .name = "ifxmips_wdt", +}; + +static struct resource +ifxmips_mtd_resource = { + .start = IFXMIPS_FLASH_START, + .end = IFXMIPS_FLASH_START + IFXMIPS_FLASH_MAX - 1, + .flags = IORESOURCE_MEM, +}; + +static struct platform_device +ifxmips_mtd = +{ + .id = 0, + .name = "ifxmips_mtd", + .num_resources = 1, + .resource = &ifxmips_mtd_resource, +}; + +static struct platform_device +ifxmips_gpio_dev = { + .name = "GPIODEV", + .id = -1, + .num_resources = 1, +}; + +#ifdef CONFIG_LEDS_GPIO +static struct gpio_led arv4519_gpio_leds[] = { + { .name = "ifx:green:power", .gpio = 3, .active_low = 1, }, + { .name = "ifx:red:power", .gpio = 7, .active_low = 1, }, + { .name = "ifx:green:adsl", .gpio = 4, .active_low = 1, }, + { .name = "ifx:green:internet", .gpio = 5, .active_low = 1, }, + { .name = "ifx:red:internet", .gpio = 8, .active_low = 1, }, + { .name = "ifx:green:wlan", .gpio = 6, .active_low = 1, }, + { .name = "ifx:green:usb", .gpio = 19, .active_low = 1, }, +}; + +static struct gpio_led_platform_data ifxmips_gpio_led_data; + +static struct platform_device ifxmips_gpio_leds = { + .name = "leds-gpio", + .id = -1, + .dev = { + .platform_data = (void *) &ifxmips_gpio_led_data, + } +}; +#endif + +struct platform_device *easy50712_devs[] = { + &ifxmips_led, &ifxmips_gpio, &ifxmips_mii, + &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev +}; + +struct platform_device *easy4010_devs[] = { + &ifxmips_led, &ifxmips_gpio, &ifxmips_mii, + &ifxmips_mtd, &ifxmips_wdt, &ifxmips_gpio_dev +}; + +struct platform_device *arv5419_devs[] = { + &ifxmips_gpio, &ifxmips_mii, &ifxmips_mtd, &ifxmips_wdt, +#ifdef CONFIG_LEDS_GPIO + &ifxmips_gpio_leds, +#endif +}; + +static struct gpio_led easy50712_leds[] = { + { .name = "ifx:green:test0", .gpio = 0,}, + { .name = "ifx:green:test1", .gpio = 1,}, + { .name = "ifx:green:test2", .gpio = 2,}, + { .name = "ifx:green:test3", .gpio = 3,}, +}; + +static struct gpio_led easy4010_leds[] = { + { .name = "ifx:green:test0", .gpio = 0,}, + { .name = "ifx:green:test1", .gpio = 1,}, + { .name = "ifx:green:test2", .gpio = 2,}, + { .name = "ifx:green:test3", .gpio = 3,}, +}; + +static struct ifxmips_board boards[] = +{ + { + .type = EASY50712, + .name = "EASY50712", + .system_type = SYSTEM_DANUBE_CHIPID1, + .devs = easy50712_devs, + .reset_resource = {.name = "reset", .start = 1, .end = 15,}, + .gpiodev_resource = {.name = "gpio", .start = (1 << 0) | (1 << 1), + .end = (1 << 0) | (1 << 1)}, + .ifxmips_leds = easy50712_leds, + }, { + .type = EASY4010, + .name = "EASY4010", + .system_type = SYSTEM_TWINPASS_CHIPID, + .devs = easy4010_devs, + .reset_resource = {.name = "reset", .start = 1, .end = 15}, + .gpiodev_resource = {.name = "gpio", .start = (1 << 0) | (1 << 1), + .end = (1 << 0) | (1 << 1)}, + .ifxmips_leds = easy4010_leds, + }, { + .type = ARV4519, + .name = "ARV4519", + .system_type = SYSTEM_DANUBE_CHIPID2, + .devs = arv5419_devs, + .reset_resource = {.name = "reset", .start = 1, .end = 14}, + .pci_external_clock = 1, + .gpio_leds = arv4519_gpio_leds, + }, +}; + +const char* +get_system_type(void) +{ + chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID); + switch(chiprev) + { + case SYSTEM_DANUBE_CHIPID1: + case SYSTEM_DANUBE_CHIPID2: + return SYSTEM_DANUBE; + + case SYSTEM_TWINPASS_CHIPID: + return SYSTEM_TWINPASS; + } + + return BOARD_SYSTEM_TYPE; +} + +static int __init +ifxmips_set_board_type(char *str) +{ + str = strchr(str, '='); + if(!str) + goto out; + str++; + if(strlen(str) > MAX_BOARD_NAME_LEN) + goto out; + strncpy(board_name, str, MAX_BOARD_NAME_LEN); + printk("bootloader told us, that this is a %s board\n", board_name); +out: + return 1; +} +__setup("ifxmips_board", ifxmips_set_board_type); + +static int __init +ifxmips_set_mii0_mac(char *str) +{ +#define IS_HEX(x) \ + (((x >='0' && x <= '9') || (x >='a' && x <= 'f') || (x >='A' && x <= 'F'))?(1):(0)) + int i; + str = strchr(str, '='); + if(!str) + goto out; + str++; + if(strlen(str) != 17) + goto out; + for(i = 0; i < 6; i++) + { + if(!IS_HEX(str[3 * i]) || !IS_HEX(str[(3 * i) + 1])) + goto out; + if((i != 5) && (str[(3 * i) + 2] != ':')) + goto out; + ifxmips_mii_mac[i] = simple_strtoul(&str[3 * i], NULL, 16); + } + if(is_valid_ether_addr(ifxmips_mii_mac)) + cmdline_mac = 1; +out: + return 1; +} +__setup("mii0_mac", ifxmips_set_mii0_mac); + +int +ifxmips_find_brn_block(void){ + unsigned char temp[8]; + memcpy_fromio(temp, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000), 8); + if(memcmp(temp, "BRN-BOOT", 8) == 0) + { + if(!cmdline_mac) + memcpy_fromio(ifxmips_mii_mac, (void*)KSEG1ADDR(IFXMIPS_FLASH_START + 0x800000 - 0x10000 + 0x16), 6); + cmdline_mac = 1; + return 1; + } else { + return 0; + } +} + +int +ifxmips_has_brn_block(void) +{ + return ifxmips_brn; +} +EXPORT_SYMBOL(ifxmips_has_brn_block); + +struct ifxmips_board* +ifxmips_find_board(void) +{ + int i; + if(!*board_name) + return 0; + for(i = 0; i < ARRAY_SIZE(boards); i++) + if((boards[i].system_type == chiprev) && (!strcmp(boards[i].name, board_name))) + return &boards[i]; + return 0; +} + +int __init +ifxmips_init_devices(void) +{ + struct ifxmips_board *board = ifxmips_find_board(); + + chiprev = ifxmips_r32(IFXMIPS_MPS_CHIPID); + ifxmips_brn = ifxmips_find_brn_block(); + + if(!cmdline_mac) + random_ether_addr(ifxmips_mii_mac); + + if(!board) + { + switch(chiprev) + { + case SYSTEM_DANUBE_CHIPID1: + case SYSTEM_DANUBE_CHIPID2: + board = &boards[0]; + break; + case SYSTEM_TWINPASS_CHIPID: + board = &boards[1]; + break; + } + } + + switch(board->type) + { + case EASY50712: + board->num_devs = ARRAY_SIZE(easy50712_devs); + ifxmips_led_data.num_leds = ARRAY_SIZE(easy50712_leds); + break; + case EASY4010: + board->num_devs = ARRAY_SIZE(easy4010_devs); + ifxmips_led_data.num_leds = ARRAY_SIZE(easy4010_leds); + break; + case ARV4519: + gpio_set_value(3, 0); + gpio_set_value(4, 0); + gpio_set_value(5, 0); + gpio_set_value(6, 0); + gpio_set_value(7, 1); + gpio_set_value(8, 1); + gpio_set_value(19, 0); + board->num_devs = ARRAY_SIZE(arv5419_devs); +#ifdef CONFIG_LEDS_GPIO + ifxmips_gpio_led_data.num_leds = ARRAY_SIZE(arv4519_gpio_leds); +#endif + break; + } +#ifdef CONFIG_LEDS_GPIO + ifxmips_gpio_led_data.leds = board->gpio_leds; +#endif + ifxmips_led_data.leds = board->ifxmips_leds; + + printk("%s:%s[%d]adding %d devs\n", __FILE__, __func__, __LINE__, board->num_devs); + + ifxmips_gpio.resource = &board->reset_resource; + ifxmips_gpio_dev.resource = &board->gpiodev_resource; + if(board->pci_external_clock) + ifxmips_pci_external_clock = 1; + printk("using board definition %s\n", board->name); + return platform_add_devices(board->devs, board->num_devs); +} + +arch_initcall(ifxmips_init_devices); diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/clock.c b/target/linux/ifxmips/files/arch/mips/ifxmips/clock.c new file mode 100644 index 0000000000..fc3658b71f --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/clock.c @@ -0,0 +1,243 @@ +/* + * 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. + * + * Copyright (C) 2007 Xu Liang, infineon + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define BASIC_INPUT_CLOCK_FREQUENCY_1 35328000 +#define BASIC_INPUT_CLOCK_FREQUENCY_2 36000000 + +#define BASIS_INPUT_CRYSTAL_USB 12000000 + +#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb)) + + +#define CGU_PLL0_PHASE_DIVIDER_ENABLE (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 31)) +#define CGU_PLL0_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 30)) +#define CGU_PLL0_CFG_DSMSEL (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 28)) +#define CGU_PLL0_CFG_FRAC_EN (ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & (1 << 27)) +#define CGU_PLL1_SRC (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 31)) +#define CGU_PLL1_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 30)) +#define CGU_PLL1_CFG_DSMSEL (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 28)) +#define CGU_PLL1_CFG_FRAC_EN (ifxmips_r32(IFXMIPS_CGU_PLL1_CFG) & (1 << 27)) +#define CGU_PLL2_PHASE_DIVIDER_ENABLE (ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & (1 << 20)) +#define CGU_PLL2_BYPASS (ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & (1 << 19)) +#define CGU_SYS_FPI_SEL (1 << 6) +#define CGU_SYS_DDR_SEL 0x3 +#define CGU_PLL0_SRC (1 << 29) + +#define CGU_PLL0_CFG_PLLK GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 26, 17) +#define CGU_PLL0_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 12, 6) +#define CGU_PLL0_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL0_CFG, 5, 2) +#define CGU_PLL1_CFG_PLLK GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 26, 17) +#define CGU_PLL1_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 12, 6) +#define CGU_PLL1_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL1_CFG, 5, 2) +#define CGU_PLL2_SRC GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 18, 17) +#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 16, 13) +#define CGU_PLL2_CFG_PLLN GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 12, 6) +#define CGU_PLL2_CFG_PLLM GET_BITS(*IFXMIPS_CGU_PLL2_CFG, 5, 2) +#define CGU_IF_CLK_PCI_CLK GET_BITS(*IFXMIPS_CGU_IF_CLK, 23, 20) + +static unsigned int cgu_get_pll0_fdiv(void); +unsigned int ifxmips_clocks[] = {CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M }; + +#define DDR_HZ ifxmips_clocks[ifxmips_r32(IFXMIPS_CGU_SYS) & 0x3] + + +static inline unsigned int +get_input_clock(int pll) +{ + switch(pll) + { + case 0: + if(ifxmips_r32(IFXMIPS_CGU_PLL0_CFG) & CGU_PLL0_SRC) + return BASIS_INPUT_CRYSTAL_USB; + else if(CGU_PLL0_PHASE_DIVIDER_ENABLE) + return BASIC_INPUT_CLOCK_FREQUENCY_1; + else + return BASIC_INPUT_CLOCK_FREQUENCY_2; + case 1: + if(CGU_PLL1_SRC) + return BASIS_INPUT_CRYSTAL_USB; + else if(CGU_PLL0_PHASE_DIVIDER_ENABLE) + return BASIC_INPUT_CLOCK_FREQUENCY_1; + else + return BASIC_INPUT_CLOCK_FREQUENCY_2; + case 2: + switch(CGU_PLL2_SRC) + { + case 0: + return cgu_get_pll0_fdiv(); + case 1: + return CGU_PLL2_PHASE_DIVIDER_ENABLE ? BASIC_INPUT_CLOCK_FREQUENCY_1 : BASIC_INPUT_CLOCK_FREQUENCY_2; + case 2: + return BASIS_INPUT_CRYSTAL_USB; + } + default: + return 0; + } +} + +static inline unsigned int +cal_dsm(int pll, unsigned int num, unsigned int den) +{ + u64 res, clock = get_input_clock(pll); + + res = num * clock; + do_div(res, den); + return res; +} + +static inline unsigned int +mash_dsm(int pll, unsigned int M, unsigned int N, unsigned int K) +{ + unsigned int num = ((N + 1) << 10) + K; + unsigned int den = (M + 1) << 10; + + return cal_dsm(pll, num, den); +} + +static inline unsigned int +ssff_dsm_1(int pll, unsigned int M, unsigned int N, unsigned int K) +{ + unsigned int num = ((N + 1) << 11) + K + 512; + unsigned int den = (M + 1) << 11; + + return cal_dsm(pll, num, den); +} + +static inline unsigned int +ssff_dsm_2(int pll, unsigned int M, unsigned int N, unsigned int K) +{ + unsigned int num = K >= 512 ? + ((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584; + unsigned int den = (M + 1) << 12; + + return cal_dsm(pll, num, den); +} + +static inline unsigned int +dsm(int pll, unsigned int M, unsigned int N, unsigned int K, + unsigned int dsmsel, unsigned int phase_div_en) +{ + if(!dsmsel) + return mash_dsm(pll, M, N, K); + else if(!phase_div_en) + return mash_dsm(pll, M, N, K); + else + return ssff_dsm_2(pll, M, N, K); +} + +static inline unsigned int +cgu_get_pll0_fosc(void) +{ + if(CGU_PLL0_BYPASS) + return get_input_clock(0); + else + return !CGU_PLL0_CFG_FRAC_EN + ? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0, CGU_PLL0_CFG_DSMSEL, + CGU_PLL0_PHASE_DIVIDER_ENABLE) + : dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, CGU_PLL0_CFG_PLLK, + CGU_PLL0_CFG_DSMSEL, CGU_PLL0_PHASE_DIVIDER_ENABLE); +} + +static unsigned int +cgu_get_pll0_fdiv(void) +{ + register unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1; + return (cgu_get_pll0_fosc() + (div >> 1)) / div; +} + +unsigned int +cgu_get_io_region_clock(void) +{ + register unsigned int ret = cgu_get_pll0_fosc(); + switch(ifxmips_r32(IFXMIPS_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) + { + default: + case 0: + return (ret + 1) / 2; + case 1: + return (ret * 2 + 2) / 5; + case 2: + return (ret + 1) / 3; + case 3: + return (ret + 2) / 4; + } +} + +unsigned int +cgu_get_fpi_bus_clock(int fpi) +{ + register unsigned int ret = cgu_get_io_region_clock(); + if((fpi == 2) && (ifxmips_r32(IFXMIPS_CGU_SYS) & CGU_SYS_FPI_SEL)) + ret >>= 1; + return ret; +} + +void cgu_setup_pci_clk(int external_clock) +{ + //set clock to 33Mhz + ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~0xf00000, IFXMIPS_CGU_IFCCR); + ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | 0x800000, IFXMIPS_CGU_IFCCR); + if(external_clock) + { + ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) & ~ (1 << 16), IFXMIPS_CGU_IFCCR); + ifxmips_w32((1 << 30), IFXMIPS_CGU_PCICR); + } else { + ifxmips_w32(ifxmips_r32(IFXMIPS_CGU_IFCCR) | (1 << 16), IFXMIPS_CGU_IFCCR); + ifxmips_w32((1 << 31) | (1 << 30), IFXMIPS_CGU_PCICR); + } +} + +unsigned int +ifxmips_get_cpu_hz(void) +{ + unsigned int ddr_clock = DDR_HZ; + switch(ifxmips_r32(IFXMIPS_CGU_SYS) & 0xc) + { + case 0: + return CLOCK_333M; + case 4: + return ddr_clock; + } + return ddr_clock << 1; +} +EXPORT_SYMBOL(ifxmips_get_cpu_hz); + +unsigned int +ifxmips_get_fpi_hz(void) +{ + unsigned int ddr_clock = DDR_HZ; + if(ifxmips_r32(IFXMIPS_CGU_SYS) & 0x40) + return ddr_clock >> 1; + return ddr_clock; +} +EXPORT_SYMBOL(ifxmips_get_fpi_hz); diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/dma-core.c b/target/linux/ifxmips/files/arch/mips/ifxmips/dma-core.c new file mode 100644 index 0000000000..a57b803e53 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/dma-core.c @@ -0,0 +1,758 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/*25 descriptors for each dma channel,4096/8/20=25.xx*/ +#define IFXMIPS_DMA_DESCRIPTOR_OFFSET 25 + +#define MAX_DMA_DEVICE_NUM 6 /*max ports connecting to dma */ +#define MAX_DMA_CHANNEL_NUM 20 /*max dma channels */ +#define DMA_INT_BUDGET 100 /*budget for interrupt handling */ +#define DMA_POLL_COUNTER 4 /*fix me, set the correct counter value here! */ + +extern void ifxmips_mask_and_ack_irq (unsigned int irq_nr); +extern void ifxmips_enable_irq (unsigned int irq_nr); +extern void ifxmips_disable_irq (unsigned int irq_nr); + +u64 *g_desc_list; +_dma_device_info dma_devs[MAX_DMA_DEVICE_NUM]; +_dma_channel_info dma_chan[MAX_DMA_CHANNEL_NUM]; + +char global_device_name[MAX_DMA_DEVICE_NUM][20] = + { {"PPE"}, {"DEU"}, {"SPI"}, {"SDIO"}, {"MCTRL0"}, {"MCTRL1"} }; + +_dma_chan_map default_dma_map[MAX_DMA_CHANNEL_NUM] = { + {"PPE", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH0_INT, 0}, + {"PPE", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH1_INT, 0}, + {"PPE", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH2_INT, 1}, + {"PPE", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH3_INT, 1}, + {"PPE", IFXMIPS_DMA_RX, 2, IFXMIPS_DMA_CH4_INT, 2}, + {"PPE", IFXMIPS_DMA_TX, 2, IFXMIPS_DMA_CH5_INT, 2}, + {"PPE", IFXMIPS_DMA_RX, 3, IFXMIPS_DMA_CH6_INT, 3}, + {"PPE", IFXMIPS_DMA_TX, 3, IFXMIPS_DMA_CH7_INT, 3}, + {"DEU", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH8_INT, 0}, + {"DEU", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH9_INT, 0}, + {"DEU", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH10_INT, 1}, + {"DEU", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH11_INT, 1}, + {"SPI", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH12_INT, 0}, + {"SPI", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH13_INT, 0}, + {"SDIO", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH14_INT, 0}, + {"SDIO", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH15_INT, 0}, + {"MCTRL0", IFXMIPS_DMA_RX, 0, IFXMIPS_DMA_CH16_INT, 0}, + {"MCTRL0", IFXMIPS_DMA_TX, 0, IFXMIPS_DMA_CH17_INT, 0}, + {"MCTRL1", IFXMIPS_DMA_RX, 1, IFXMIPS_DMA_CH18_INT, 1}, + {"MCTRL1", IFXMIPS_DMA_TX, 1, IFXMIPS_DMA_CH19_INT, 1} +}; + +_dma_chan_map *chan_map = default_dma_map; +volatile u32 g_ifxmips_dma_int_status = 0; +volatile int g_ifxmips_dma_in_process = 0;/*0=not in process,1=in process*/ + +void do_dma_tasklet (unsigned long); +DECLARE_TASKLET (dma_tasklet, do_dma_tasklet, 0); + +u8* +common_buffer_alloc (int len, int *byte_offset, void **opt) +{ + u8 *buffer = (u8 *) kmalloc (len * sizeof (u8), GFP_KERNEL); + + *byte_offset = 0; + + return buffer; +} + +void +common_buffer_free (u8 *dataptr, void *opt) +{ + if (dataptr) + kfree(dataptr); +} + +void +enable_ch_irq (_dma_channel_info *pCh) +{ + int chan_no = (int)(pCh - dma_chan); + int flag; + + local_irq_save(flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(0x4a, IFXMIPS_DMA_CIE); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN); + local_irq_restore(flag); + ifxmips_enable_irq(pCh->irq); +} + +void +disable_ch_irq (_dma_channel_info *pCh) +{ + int flag; + int chan_no = (int) (pCh - dma_chan); + + local_irq_save(flag); + g_ifxmips_dma_int_status &= ~(1 << chan_no); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(0, IFXMIPS_DMA_CIE); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); + local_irq_restore(flag); + ifxmips_mask_and_ack_irq(pCh->irq); +} + +void +open_chan (_dma_channel_info *pCh) +{ + int flag; + int chan_no = (int)(pCh - dma_chan); + + local_irq_save(flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 1, IFXMIPS_DMA_CCTRL); + if(pCh->dir == IFXMIPS_DMA_RX) + enable_ch_irq(pCh); + local_irq_restore(flag); +} + +void +close_chan(_dma_channel_info *pCh) +{ + int flag; + int chan_no = (int) (pCh - dma_chan); + + local_irq_save(flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL); + disable_ch_irq(pCh); + local_irq_restore(flag); +} + +void +reset_chan (_dma_channel_info *pCh) +{ + int chan_no = (int) (pCh - dma_chan); + + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL); +} + +void +rx_chan_intr_handler (int chan_no) +{ + _dma_device_info *pDev = (_dma_device_info *)dma_chan[chan_no].dma_dev; + _dma_channel_info *pCh = &dma_chan[chan_no]; + struct rx_desc *rx_desc_p; + int tmp; + int flag; + + /*handle command complete interrupt */ + rx_desc_p = (struct rx_desc*)pCh->desc_base + pCh->curr_desc; + if (rx_desc_p->status.field.OWN == CPU_OWN + && rx_desc_p->status.field.C + && rx_desc_p->status.field.data_length < 1536){ + /*Every thing is correct, then we inform the upper layer */ + pDev->current_rx_chan = pCh->rel_chan_no; + if(pDev->intr_handler) + pDev->intr_handler(pDev, RCV_INT); + pCh->weight--; + } else { + local_irq_save(flag); + tmp = ifxmips_r32(IFXMIPS_DMA_CS); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS); + ifxmips_w32(tmp, IFXMIPS_DMA_CS); + g_ifxmips_dma_int_status &= ~(1 << chan_no); + local_irq_restore(flag); + ifxmips_enable_irq(dma_chan[chan_no].irq); + } +} + +inline void +tx_chan_intr_handler (int chan_no) +{ + _dma_device_info *pDev = (_dma_device_info*)dma_chan[chan_no].dma_dev; + _dma_channel_info *pCh = &dma_chan[chan_no]; + int tmp; + int flag; + + local_irq_save(flag); + tmp = ifxmips_r32(IFXMIPS_DMA_CS); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CIS) | 0x7e, IFXMIPS_DMA_CIS); + ifxmips_w32(tmp, IFXMIPS_DMA_CS); + g_ifxmips_dma_int_status &= ~(1 << chan_no); + local_irq_restore(flag); + pDev->current_tx_chan = pCh->rel_chan_no; + if (pDev->intr_handler) + pDev->intr_handler(pDev, TRANSMIT_CPT_INT); +} + +void +do_dma_tasklet (unsigned long unused) +{ + int i; + int chan_no = 0; + int budget = DMA_INT_BUDGET; + int weight = 0; + int flag; + + while (g_ifxmips_dma_int_status) + { + if (budget-- < 0) + { + tasklet_schedule(&dma_tasklet); + return; + } + chan_no = -1; + weight = 0; + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + { + if ((g_ifxmips_dma_int_status & (1 << i)) && dma_chan[i].weight > 0) + { + if (dma_chan[i].weight > weight) + { + chan_no = i; + weight = dma_chan[chan_no].weight; + } + } + } + + if (chan_no >= 0) + { + if (chan_map[chan_no].dir == IFXMIPS_DMA_RX) + rx_chan_intr_handler(chan_no); + else + tx_chan_intr_handler(chan_no); + } else { + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + { + dma_chan[i].weight = dma_chan[i].default_weight; + } + } + } + + local_irq_save(flag); + g_ifxmips_dma_in_process = 0; + if (g_ifxmips_dma_int_status) + { + g_ifxmips_dma_in_process = 1; + tasklet_schedule(&dma_tasklet); + } + local_irq_restore(flag); +} + +irqreturn_t +dma_interrupt (int irq, void *dev_id) +{ + _dma_channel_info *pCh; + int chan_no = 0; + int tmp; + + pCh = (_dma_channel_info*)dev_id; + chan_no = (int)(pCh - dma_chan); + if (chan_no < 0 || chan_no > 19) + BUG(); + + tmp = ifxmips_r32(IFXMIPS_DMA_IRNEN); + ifxmips_w32(0, IFXMIPS_DMA_IRNEN); + g_ifxmips_dma_int_status |= 1 << chan_no; + ifxmips_w32(tmp, IFXMIPS_DMA_IRNEN); + ifxmips_mask_and_ack_irq(irq); + + if (!g_ifxmips_dma_in_process) + { + g_ifxmips_dma_in_process = 1; + tasklet_schedule(&dma_tasklet); + } + + return IRQ_HANDLED; +} + +_dma_device_info* +dma_device_reserve (char *dev_name) +{ + int i; + + for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) + { + if (strcmp(dev_name, dma_devs[i].device_name) == 0) + { + if (dma_devs[i].reserved) + return NULL; + dma_devs[i].reserved = 1; + break; + } + } + + return &dma_devs[i]; +} + +void +dma_device_release (_dma_device_info *dev) +{ + dev->reserved = 0; +} + +void +dma_device_register(_dma_device_info *dev) +{ + int i, j; + int chan_no = 0; + u8 *buffer; + int byte_offset; + int flag; + _dma_device_info *pDev; + _dma_channel_info *pCh; + struct rx_desc *rx_desc_p; + struct tx_desc *tx_desc_p; + + for (i = 0; i < dev->max_tx_chan_num; i++) + { + pCh = dev->tx_chan[i]; + if (pCh->control == IFXMIPS_DMA_CH_ON) + { + chan_no = (int)(pCh - dma_chan); + for (j = 0; j < pCh->desc_len; j++) + { + tx_desc_p = (struct tx_desc*)pCh->desc_base + j; + memset(tx_desc_p, 0, sizeof(struct tx_desc)); + } + local_irq_save(flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + /*check if the descriptor length is changed */ + if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len) + ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN); + + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL); + while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2){}; + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN); + ifxmips_w32(0x30100, IFXMIPS_DMA_CCTRL); /*reset and enable channel,enable channel later */ + local_irq_restore(flag); + } + } + + for (i = 0; i < dev->max_rx_chan_num; i++) + { + pCh = dev->rx_chan[i]; + if (pCh->control == IFXMIPS_DMA_CH_ON) + { + chan_no = (int)(pCh - dma_chan); + + for (j = 0; j < pCh->desc_len; j++) + { + rx_desc_p = (struct rx_desc*)pCh->desc_base + j; + pDev = (_dma_device_info*)(pCh->dma_dev); + buffer = pDev->buffer_alloc(pCh->packet_size, &byte_offset, (void*)&(pCh->opt[j])); + if (!buffer) + break; + + dma_cache_inv((unsigned long) buffer, pCh->packet_size); + + rx_desc_p->Data_Pointer = (u32)CPHYSADDR((u32)buffer); + rx_desc_p->status.word = 0; + rx_desc_p->status.field.byte_offset = byte_offset; + rx_desc_p->status.field.OWN = DMA_OWN; + rx_desc_p->status.field.data_length = pCh->packet_size; + } + + local_irq_save(flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + /*check if the descriptor length is changed */ + if (ifxmips_r32(IFXMIPS_DMA_CDLEN) != pCh->desc_len) + ifxmips_w32(pCh->desc_len, IFXMIPS_DMA_CDLEN); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) | 2, IFXMIPS_DMA_CCTRL); + while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 2){}; + ifxmips_w32(0x0a, IFXMIPS_DMA_CIE); /*fix me, should enable all the interrupts here? */ + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) | (1 << chan_no), IFXMIPS_DMA_IRNEN); + ifxmips_w32(0x30000, IFXMIPS_DMA_CCTRL); + local_irq_restore(flag); + ifxmips_enable_irq(dma_chan[chan_no].irq); + } + } +} + +void +dma_device_unregister (_dma_device_info *dev) +{ + int i, j; + int chan_no; + _dma_channel_info *pCh; + struct rx_desc *rx_desc_p; + struct tx_desc *tx_desc_p; + int flag; + + for (i = 0; i < dev->max_tx_chan_num; i++) + { + pCh = dev->tx_chan[i]; + if (pCh->control == IFXMIPS_DMA_CH_ON) + { + chan_no = (int)(dev->tx_chan[i] - dma_chan); + local_irq_save (flag); + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + pCh->curr_desc = 0; + pCh->prev_desc = 0; + pCh->control = IFXMIPS_DMA_CH_OFF; + ifxmips_w32(0, IFXMIPS_DMA_CIE); /*fix me, should disable all the interrupts here? */ + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /*disable interrupts */ + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL); + while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1) {}; + local_irq_restore (flag); + + for (j = 0; j < pCh->desc_len; j++) + { + tx_desc_p = (struct tx_desc*)pCh->desc_base + j; + if ((tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C) + || (tx_desc_p->status.field.OWN == DMA_OWN && tx_desc_p->status.field.data_length > 0)) + { + dev->buffer_free ((u8 *) __va (tx_desc_p->Data_Pointer), (void*)pCh->opt[j]); + } + tx_desc_p->status.field.OWN = CPU_OWN; + memset (tx_desc_p, 0, sizeof (struct tx_desc)); + } + //TODO should free buffer that is not transferred by dma + } + } + + for (i = 0; i < dev->max_rx_chan_num; i++) + { + pCh = dev->rx_chan[i]; + chan_no = (int)(dev->rx_chan[i] - dma_chan); + ifxmips_disable_irq(pCh->irq); + + local_irq_save(flag); + g_ifxmips_dma_int_status &= ~(1 << chan_no); + pCh->curr_desc = 0; + pCh->prev_desc = 0; + pCh->control = IFXMIPS_DMA_CH_OFF; + + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + ifxmips_w32(0, IFXMIPS_DMA_CIE); /*fix me, should disable all the interrupts here? */ + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_IRNEN) & ~(1 << chan_no), IFXMIPS_DMA_IRNEN); /*disable interrupts */ + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~1, IFXMIPS_DMA_CCTRL); + while (ifxmips_r32(IFXMIPS_DMA_CCTRL) & 1) {}; + + local_irq_restore (flag); + for (j = 0; j < pCh->desc_len; j++) + { + rx_desc_p = (struct rx_desc *) pCh->desc_base + j; + if ((rx_desc_p->status.field.OWN == CPU_OWN + && rx_desc_p->status.field.C) + || (rx_desc_p->status.field.OWN == DMA_OWN + && rx_desc_p->status.field.data_length > 0)) { + dev->buffer_free ((u8 *) + __va (rx_desc_p-> + Data_Pointer), + (void *) pCh->opt[j]); + } + } + } +} + +int +dma_device_read (struct dma_device_info *dma_dev, u8 ** dataptr, void **opt) +{ + u8 *buf; + int len; + int byte_offset = 0; + void *p = NULL; + _dma_channel_info *pCh = dma_dev->rx_chan[dma_dev->current_rx_chan]; + struct rx_desc *rx_desc_p; + + /*get the rx data first */ + rx_desc_p = (struct rx_desc *) pCh->desc_base + pCh->curr_desc; + if (!(rx_desc_p->status.field.OWN == CPU_OWN && rx_desc_p->status.field.C)) + { + return 0; + } + + buf = (u8 *) __va (rx_desc_p->Data_Pointer); + *(u32*)dataptr = (u32)buf; + len = rx_desc_p->status.field.data_length; + + if (opt) + { + *(int*)opt = (int)pCh->opt[pCh->curr_desc]; + } + + /*replace with a new allocated buffer */ + buf = dma_dev->buffer_alloc(pCh->packet_size, &byte_offset, &p); + + if (buf) + { + dma_cache_inv ((unsigned long) buf, + pCh->packet_size); + pCh->opt[pCh->curr_desc] = p; + wmb (); + + rx_desc_p->Data_Pointer = (u32) CPHYSADDR ((u32) buf); + rx_desc_p->status.word = (DMA_OWN << 31) | ((byte_offset) << 23) | pCh->packet_size; + wmb (); + } else { + *(u32 *) dataptr = 0; + if (opt) + *(int *) opt = 0; + len = 0; + } + + /*increase the curr_desc pointer */ + pCh->curr_desc++; + if (pCh->curr_desc == pCh->desc_len) + pCh->curr_desc = 0; + + return len; +} + +int +dma_device_write (struct dma_device_info *dma_dev, u8 * dataptr, int len, void *opt) +{ + int flag; + u32 tmp, byte_offset; + _dma_channel_info *pCh; + int chan_no; + struct tx_desc *tx_desc_p; + local_irq_save (flag); + + pCh = dma_dev->tx_chan[dma_dev->current_tx_chan]; + chan_no = (int)(pCh - (_dma_channel_info *) dma_chan); + + tx_desc_p = (struct tx_desc*)pCh->desc_base + pCh->prev_desc; + while (tx_desc_p->status.field.OWN == CPU_OWN && tx_desc_p->status.field.C) + { + dma_dev->buffer_free((u8 *) __va (tx_desc_p->Data_Pointer), pCh->opt[pCh->prev_desc]); + memset(tx_desc_p, 0, sizeof (struct tx_desc)); + pCh->prev_desc = (pCh->prev_desc + 1) % (pCh->desc_len); + tx_desc_p = (struct tx_desc*)pCh->desc_base + pCh->prev_desc; + } + tx_desc_p = (struct tx_desc*)pCh->desc_base + pCh->curr_desc; + /*Check whether this descriptor is available */ + if (tx_desc_p->status.field.OWN == DMA_OWN || tx_desc_p->status.field.C) + { + /*if not , the tell the upper layer device */ + dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT); + local_irq_restore(flag); + printk (KERN_INFO "%s %d: failed to write!\n", __func__, __LINE__); + + return 0; + } + pCh->opt[pCh->curr_desc] = opt; + /*byte offset----to adjust the starting address of the data buffer, should be multiple of the burst length. */ + byte_offset = ((u32) CPHYSADDR ((u32) dataptr)) % ((dma_dev->tx_burst_len) * 4); + dma_cache_wback ((unsigned long) dataptr, len); + wmb (); + tx_desc_p->Data_Pointer = (u32) CPHYSADDR ((u32) dataptr) - byte_offset; + wmb (); + tx_desc_p->status.word = (DMA_OWN << 31) | DMA_DESC_SOP_SET | DMA_DESC_EOP_SET | ((byte_offset) << 23) | len; + wmb (); + + pCh->curr_desc++; + if (pCh->curr_desc == pCh->desc_len) + pCh->curr_desc = 0; + + /*Check whether this descriptor is available */ + tx_desc_p = (struct tx_desc *) pCh->desc_base + pCh->curr_desc; + if (tx_desc_p->status.field.OWN == DMA_OWN) + { + /*if not , the tell the upper layer device */ + dma_dev->intr_handler (dma_dev, TX_BUF_FULL_INT); + } + + ifxmips_w32(chan_no, IFXMIPS_DMA_CS); + tmp = ifxmips_r32(IFXMIPS_DMA_CCTRL); + + if (!(tmp & 1)) + pCh->open (pCh); + + local_irq_restore (flag); + + return len; +} + +int +map_dma_chan(_dma_chan_map *map) +{ + int i, j; + int result; + + for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) + { + strcpy(dma_devs[i].device_name, global_device_name[i]); + } + + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + { + dma_chan[i].irq = map[i].irq; + result = request_irq(dma_chan[i].irq, dma_interrupt, IRQF_DISABLED, "dma-core", (void*)&dma_chan[i]); + if (result) + { + printk("error, cannot get dma_irq!\n"); + free_irq(dma_chan[i].irq, (void *) &dma_interrupt); + + return -EFAULT; + } + } + + for (i = 0; i < MAX_DMA_DEVICE_NUM; i++) + { + dma_devs[i].num_tx_chan = 0; /*set default tx channel number to be one */ + dma_devs[i].num_rx_chan = 0; /*set default rx channel number to be one */ + dma_devs[i].max_rx_chan_num = 0; + dma_devs[i].max_tx_chan_num = 0; + dma_devs[i].buffer_alloc = &common_buffer_alloc; + dma_devs[i].buffer_free = &common_buffer_free; + dma_devs[i].intr_handler = NULL; + dma_devs[i].tx_burst_len = 4; + dma_devs[i].rx_burst_len = 4; + if (i == 0) + { + ifxmips_w32(0, IFXMIPS_DMA_PS); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_PCTRL) | ((0xf << 8) | (1 << 6)), IFXMIPS_DMA_PCTRL); /*enable dma drop */ + } + + if (i == 1) + { + ifxmips_w32(1, IFXMIPS_DMA_PS); + ifxmips_w32(0x14, IFXMIPS_DMA_PCTRL); /*deu port setting */ + } + + for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) + { + dma_chan[j].byte_offset = 0; + dma_chan[j].open = &open_chan; + dma_chan[j].close = &close_chan; + dma_chan[j].reset = &reset_chan; + dma_chan[j].enable_irq = &enable_ch_irq; + dma_chan[j].disable_irq = &disable_ch_irq; + dma_chan[j].rel_chan_no = map[j].rel_chan_no; + dma_chan[j].control = IFXMIPS_DMA_CH_OFF; + dma_chan[j].default_weight = IFXMIPS_DMA_CH_DEFAULT_WEIGHT; + dma_chan[j].weight = dma_chan[j].default_weight; + dma_chan[j].curr_desc = 0; + dma_chan[j].prev_desc = 0; + } + + for (j = 0; j < MAX_DMA_CHANNEL_NUM; j++) + { + if (strcmp(dma_devs[i].device_name, map[j].dev_name) == 0) + { + if (map[j].dir == IFXMIPS_DMA_RX) + { + dma_chan[j].dir = IFXMIPS_DMA_RX; + dma_devs[i].max_rx_chan_num++; + dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1] = &dma_chan[j]; + dma_devs[i].rx_chan[dma_devs[i].max_rx_chan_num - 1]->pri = map[j].pri; + dma_chan[j].dma_dev = (void*)&dma_devs[i]; + } else if(map[j].dir == IFXMIPS_DMA_TX) + { /*TX direction */ + dma_chan[j].dir = IFXMIPS_DMA_TX; + dma_devs[i].max_tx_chan_num++; + dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1] = &dma_chan[j]; + dma_devs[i].tx_chan[dma_devs[i].max_tx_chan_num - 1]->pri = map[j].pri; + dma_chan[j].dma_dev = (void*)&dma_devs[i]; + } else { + printk ("WRONG DMA MAP!\n"); + } + } + } + } + + return 0; +} + +void +dma_chip_init(void) +{ + int i; + + // enable DMA from PMU + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA); + + // reset DMA + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CTRL) | 1, IFXMIPS_DMA_CTRL); + + // diable all interrupts + ifxmips_w32(0, IFXMIPS_DMA_IRNEN); + + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + { + ifxmips_w32(i, IFXMIPS_DMA_CS); + ifxmips_w32(0x2, IFXMIPS_DMA_CCTRL); + ifxmips_w32(0x80000040, IFXMIPS_DMA_CPOLL); + ifxmips_w32(ifxmips_r32(IFXMIPS_DMA_CCTRL) & ~0x1, IFXMIPS_DMA_CCTRL); + + } +} + +int +ifxmips_dma_init (void) +{ + int i; + + dma_chip_init(); + if (map_dma_chan(default_dma_map)) + BUG(); + + g_desc_list = (u64*)KSEG1ADDR(__get_free_page(GFP_DMA)); + + if (g_desc_list == NULL) + { + printk("no memory for desriptor\n"); + return -ENOMEM; + } + + memset(g_desc_list, 0, PAGE_SIZE); + + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + { + dma_chan[i].desc_base = (u32)g_desc_list + i * IFXMIPS_DMA_DESCRIPTOR_OFFSET * 8; + dma_chan[i].curr_desc = 0; + dma_chan[i].desc_len = IFXMIPS_DMA_DESCRIPTOR_OFFSET; + + ifxmips_w32(i, IFXMIPS_DMA_CS); + ifxmips_w32((u32)CPHYSADDR(dma_chan[i].desc_base), IFXMIPS_DMA_CDBA); + ifxmips_w32(dma_chan[i].desc_len, IFXMIPS_DMA_CDLEN); + } + + return 0; +} + +arch_initcall(ifxmips_dma_init); + +void +dma_cleanup(void) +{ + int i; + + free_page(KSEG0ADDR((unsigned long) g_desc_list)); + for (i = 0; i < MAX_DMA_CHANNEL_NUM; i++) + free_irq(dma_chan[i].irq, (void*)&dma_interrupt); +} + +EXPORT_SYMBOL (dma_device_reserve); +EXPORT_SYMBOL (dma_device_release); +EXPORT_SYMBOL (dma_device_register); +EXPORT_SYMBOL (dma_device_unregister); +EXPORT_SYMBOL (dma_device_read); +EXPORT_SYMBOL (dma_device_write); + +MODULE_LICENSE ("GPL"); diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/gpio.c b/target/linux/ifxmips/files/arch/mips/ifxmips/gpio.c new file mode 100644 index 0000000000..eef5146698 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/gpio.c @@ -0,0 +1,385 @@ +/* + * 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. + * + * Copyright (C) 2004 btxu Generate from INCA-IP project + * Copyright (C) 2005 Jin-Sze.Sow Comments edited + * Copyright (C) 2006 Huang Xiaogang Modification & verification on Danube chip + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_PORTS 2 +#define PINS_PER_PORT 16 + +#ifdef CONFIG_IFXMIPS_GPIO_RST_BTN + +unsigned int rst_port = 1; +unsigned int rst_pin = 15; +static struct timer_list rst_button_timer; + +extern struct sock *uevent_sock; +extern u64 uevent_next_seqnum(void); +static unsigned long seen; +static int pressed = 0; + +struct event_t { + struct work_struct wq; + int set; + unsigned long jiffies; +}; +#endif + +#define IFXMIPS_GPIO_SANITY {if (port > MAX_PORTS || pin > PINS_PER_PORT) return -EINVAL; } +int +ifxmips_port_reserve_pin(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + printk("%s : call to obseleted function\n", __func__); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_reserve_pin); + +int +ifxmips_port_free_pin(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + printk("%s : call to obseleted function\n", __func__); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_free_pin); + +int +ifxmips_port_set_open_drain(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_OD + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_open_drain); + +int +ifxmips_port_clear_open_drain(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OD + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_OD + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_open_drain); + +int +ifxmips_port_set_pudsel(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_pudsel); + +int +ifxmips_port_clear_pudsel (unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_PUDSEL + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_pudsel); + +int +ifxmips_port_set_puden(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_puden); + +int +ifxmips_port_clear_puden(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_PUDEN + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_puden); + +int +ifxmips_port_set_stoff(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_STOFF + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_stoff); + +int +ifxmips_port_clear_stoff(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_STOFF + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_STOFF + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_stoff); + +int +ifxmips_port_set_dir_out(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_DIR + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_dir_out); + +int +ifxmips_port_set_dir_in(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_DIR + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_DIR + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_dir_in); + +int +ifxmips_port_set_output(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_OUT + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_output); + +int +ifxmips_port_clear_output(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_OUT + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_OUT + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_output); + +int +ifxmips_port_get_input(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + if (ifxmips_r32(IFXMIPS_GPIO_P0_IN + (port * 0xC)) & (1 << pin)) + return 0; + else + return 1; +} +EXPORT_SYMBOL(ifxmips_port_get_input); + +int +ifxmips_port_set_altsel0(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_altsel0); + +int +ifxmips_port_clear_altsel0(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_ALTSEL0 + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_altsel0); + +int +ifxmips_port_set_altsel1(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) | (1 << pin), + IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_set_altsel1); + +int +ifxmips_port_clear_altsel1(unsigned int port, unsigned int pin) +{ + IFXMIPS_GPIO_SANITY; + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)) & ~(1 << pin), + IFXMIPS_GPIO_P0_ALTSEL1 + (port * 0xC)); + return 0; +} +EXPORT_SYMBOL(ifxmips_port_clear_altsel1); + +#ifdef CONFIG_IFXMIPS_GPIO_RST_BTN +static inline void +add_msg(struct sk_buff *skb, char *msg) +{ + char *scratch; + scratch = skb_put(skb, strlen(msg) + 1); + sprintf(scratch, msg); +} + +static void +hotplug_button(struct work_struct *wq) +{ + struct sk_buff *skb; + struct event_t *event; + size_t len; + char *scratch, *s; + char buf[128]; + + event = container_of(wq, struct event_t, wq); + if(!uevent_sock) + goto done; + + s = event->set ? "pressed" : "released"; + len = strlen(s) + 2; + skb = alloc_skb(len + 2048, GFP_KERNEL); + if(!skb) + goto done; + + scratch = skb_put(skb, len); + sprintf(scratch, "%s@",s); + add_msg(skb, "HOME=/"); + add_msg(skb, "PATH=/sbin:/bin:/usr/sbin:/usr/bin"); + add_msg(skb, "SUBSYSTEM=button"); + add_msg(skb, "BUTTON=reset"); + add_msg(skb, (event->set ? "ACTION=pressed" : "ACTION=released")); + sprintf(buf, "SEEN=%ld", (event->jiffies - seen)/HZ); + add_msg(skb, buf); + snprintf(buf, 128, "SEQNUM=%llu", uevent_next_seqnum()); + add_msg(skb, buf); + + NETLINK_CB(skb).dst_group = 1; + netlink_broadcast(uevent_sock, skb, 0, 1, GFP_KERNEL); +done: + kfree(event); +} + +static void +reset_button_poll(unsigned long unused) +{ + struct event_t *event; + + rst_button_timer.expires = jiffies + (HZ / 4); + add_timer(&rst_button_timer); + + if (pressed != ifxmips_port_get_input(rst_port, rst_pin)) + { + if(pressed) + pressed = 0; + else + pressed = 1; + event = (struct event_t *) kzalloc(sizeof(struct event_t), GFP_ATOMIC); + if (!event) + { + printk("Could not alloc hotplug event\n"); + return; + } + event->set = pressed; + event->jiffies = jiffies; + INIT_WORK(&event->wq, (void *)(void *)hotplug_button); + schedule_work(&event->wq); + seen = jiffies; + } +} +#endif + +static int +ifxmips_gpio_probe(struct platform_device *dev) +{ + int retval = 0; + +#ifdef CONFIG_IFXMIPS_GPIO_RST_BTN + rst_port = dev->resource[0].start; + rst_pin = dev->resource[0].end; + ifxmips_port_set_open_drain(rst_port, rst_pin); + ifxmips_port_clear_altsel0(rst_port, rst_pin); + ifxmips_port_clear_altsel1(rst_port, rst_pin); + ifxmips_port_set_dir_in(rst_port, rst_pin); + seen = jiffies; + init_timer(&rst_button_timer); + rst_button_timer.function = reset_button_poll; + rst_button_timer.expires = jiffies + HZ; + add_timer(&rst_button_timer); +#endif + return retval; +} + +static int +ifxmips_gpio_remove(struct platform_device *pdev) +{ +#ifdef CONFIG_IFXMIPS_GPIO_RST_BTN + del_timer_sync(&rst_button_timer); +#endif + return 0; +} + +static struct +platform_driver ifxmips_gpio_driver = { + .probe = ifxmips_gpio_probe, + .remove = ifxmips_gpio_remove, + .driver = { + .name = "ifxmips_gpio", + .owner = THIS_MODULE, + }, +}; + +int __init +ifxmips_gpio_init(void) +{ + int ret = platform_driver_register(&ifxmips_gpio_driver); + if (ret) + printk(KERN_INFO "ifxmips_gpio : Error registering platfom driver!"); + return ret; +} + +void __exit +ifxmips_gpio_exit(void) +{ + platform_driver_unregister(&ifxmips_gpio_driver); +} + +module_init(ifxmips_gpio_init); +module_exit(ifxmips_gpio_exit); diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/interrupt.c b/target/linux/ifxmips/files/arch/mips/ifxmips/interrupt.c new file mode 100644 index 0000000000..b47074d79c --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/interrupt.c @@ -0,0 +1,203 @@ +/* + * 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. + * + * Copyright (C) 2005 Wu Qi Ming infineon + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +void +ifxmips_disable_irq(unsigned int irq_nr) +{ + int i; + u32 *ifxmips_ier = IFXMIPS_ICU_IM0_IER; + + irq_nr -= INT_NUM_IRQ0; + for(i = 0; i <= 4; i++) + { + if(irq_nr < INT_NUM_IM_OFFSET){ + ifxmips_w32(ifxmips_r32(ifxmips_ier) & ~(1 << irq_nr ), ifxmips_ier); + return; + } + ifxmips_ier += IFXMIPS_ICU_OFFSET; + irq_nr -= INT_NUM_IM_OFFSET; + } +} +EXPORT_SYMBOL(ifxmips_disable_irq); + +void +ifxmips_mask_and_ack_irq(unsigned int irq_nr) +{ + int i; + u32 *ifxmips_ier = IFXMIPS_ICU_IM0_IER; + u32 *ifxmips_isr = IFXMIPS_ICU_IM0_ISR; + + irq_nr -= INT_NUM_IRQ0; + for(i = 0; i <= 4; i++) + { + if(irq_nr < INT_NUM_IM_OFFSET) + { + ifxmips_w32(ifxmips_r32(ifxmips_ier) & ~(1 << irq_nr ), ifxmips_ier); + ifxmips_w32((1 << irq_nr ), ifxmips_isr); + return; + } + ifxmips_ier += IFXMIPS_ICU_OFFSET; + ifxmips_isr += IFXMIPS_ICU_OFFSET; + irq_nr -= INT_NUM_IM_OFFSET; + } +} +EXPORT_SYMBOL(ifxmips_mask_and_ack_irq); + +void +ifxmips_enable_irq(unsigned int irq_nr) +{ + int i; + u32 *ifxmips_ier = IFXMIPS_ICU_IM0_IER; + + irq_nr -= INT_NUM_IRQ0; + for(i = 0; i <= 4; i++) + { + if(irq_nr < INT_NUM_IM_OFFSET) + { + ifxmips_w32(ifxmips_r32(ifxmips_ier) | (1 << irq_nr ), ifxmips_ier); + return; + } + ifxmips_ier += IFXMIPS_ICU_OFFSET; + irq_nr -= INT_NUM_IM_OFFSET; + } +} +EXPORT_SYMBOL(ifxmips_enable_irq); + +static unsigned int +ifxmips_startup_irq(unsigned int irq) +{ + ifxmips_enable_irq(irq); + return 0; +} + +static void +ifxmips_end_irq(unsigned int irq) +{ + if(!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) + ifxmips_enable_irq (irq); +} + +static struct hw_interrupt_type +ifxmips_irq_type = { + "IFXMIPS", + .startup = ifxmips_startup_irq, + .enable = ifxmips_enable_irq, + .disable = ifxmips_disable_irq, + .unmask = ifxmips_enable_irq, + .ack = ifxmips_end_irq, + .mask = ifxmips_disable_irq, + .mask_ack = ifxmips_mask_and_ack_irq, + .end = ifxmips_end_irq, +}; + +static inline int +ls1bit32(unsigned long x) +{ + __asm__ ( + ".set push \n" + ".set mips32 \n" + "clz %0, %1 \n" + ".set pop \n" + : "=r" (x) + : "r" (x)); + return 31 - x; +} + +void +ifxmips_hw_irqdispatch(int module) +{ + u32 irq; + + irq = ifxmips_r32(IFXMIPS_ICU_IM0_IOSR + (module * IFXMIPS_ICU_OFFSET)); + if(irq == 0) + return; + + /* we need to do this due to a silicon bug */ + irq = ls1bit32(irq); + do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module)); + + if((irq == 22) && (module == 0)){ + ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_ISTAT) | 0x10, IFXMIPS_EBU_PCC_ISTAT); + } +} + +asmlinkage void +plat_irq_dispatch(void) +{ + unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM; + unsigned int i; + + if(pending & CAUSEF_IP7) + { + do_IRQ(MIPS_CPU_TIMER_IRQ); + goto out; + } else { + for(i = 0; i < 5; i++) + { + if(pending & (CAUSEF_IP2 << i)) + { + ifxmips_hw_irqdispatch(i); + goto out; + } + } + } + printk("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status()); + +out: + return; +} + +static struct irqaction +cascade = { + .handler = no_action, + .flags = IRQF_DISABLED, + .name = "cascade", +}; + +void __init +arch_init_irq(void) +{ + int i; + + for(i = 0; i < 5; i++) + ifxmips_w32(0, IFXMIPS_ICU_IM0_IER + (i * IFXMIPS_ICU_OFFSET)); + + mips_cpu_irq_init(); + + for(i = 2; i <= 6; i++) + setup_irq(i, &cascade); + + for(i = INT_NUM_IRQ0; i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++) + set_irq_chip_and_handler(i, &ifxmips_irq_type, handle_level_irq); + + set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5); +} diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/pmu.c b/target/linux/ifxmips/files/arch/mips/ifxmips/pmu.c new file mode 100644 index 0000000000..2831182ab8 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/pmu.c @@ -0,0 +1,42 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include + +void +ifxmips_pmu_enable(unsigned int module) +{ + int err = 1000000; + + ifxmips_w32(ifxmips_r32(IFXMIPS_PMU_PWDCR) & ~module, IFXMIPS_PMU_PWDCR); + while (--err && (ifxmips_r32(IFXMIPS_PMU_PWDSR) & module)) {} + + if (!err) + panic("activating PMU module failed!"); +} +EXPORT_SYMBOL(ifxmips_pmu_enable); + +void +ifxmips_pmu_disable(unsigned int module) +{ + ifxmips_w32(ifxmips_r32(IFXMIPS_PMU_PWDCR) | module, IFXMIPS_PMU_PWDCR); +} +EXPORT_SYMBOL(ifxmips_pmu_disable); diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/prom.c b/target/linux/ifxmips/files/arch/mips/ifxmips/prom.c new file mode 100644 index 0000000000..880febc62b --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/prom.c @@ -0,0 +1,145 @@ +/* + * 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. + * + * Copyright (C) 2005 Wu Qi Ming infineon + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include + +static char buf[1024]; +unsigned int *prom_cp1_base = NULL; +unsigned int prom_cp1_size = 0; + +#ifdef IFXMIPS_PROM_ASC0 +#define IFXMIPS_ASC_DIFF 0 +#else +#define IFXMIPS_ASC_DIFF IFXMIPS_ASC_BASE_DIFF +#endif + +static inline u32 +asc_r32(unsigned long r) +{ + return ifxmips_r32((u32*)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_DIFF + r)); +} + +static inline void +asc_w32(u32 v, unsigned long r) +{ + ifxmips_w32(v, (u32*)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_DIFF + r)); +} + +void +prom_free_prom_memory(void) +{ +} + +void +prom_putchar(char c) +{ + unsigned long flags; + + local_irq_save(flags); + while((asc_r32(IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK) >> ASCFSTAT_TXFFLOFF); + + if(c == '\n') + asc_w32('\r', IFXMIPS_ASC_TBUF); + asc_w32(c, IFXMIPS_ASC_TBUF); + local_irq_restore(flags); +} + +void +prom_printf(const char * fmt, ...) +{ + va_list args; + int l; + char *p, *buf_end; + + va_start(args, fmt); + l = vsprintf(buf, fmt, args); + va_end(args); + buf_end = buf + l; + + for(p = buf; p < buf_end; p++) + prom_putchar(*p); +} + +unsigned int *prom_get_cp1_base(void) +{ + return prom_cp1_base; +} +EXPORT_SYMBOL(prom_get_cp1_base); + +unsigned int prom_get_cp1_size(void) +{ + return prom_cp1_size; +} +EXPORT_SYMBOL(prom_get_cp1_size); + +void __init +prom_init(void) +{ + int argc = fw_arg0; + char **argv = (char **) fw_arg1; + char **envp = (char **) fw_arg2; + + int memsize = 16; + int i; + + mips_machtype = MACH_INFINEON_IFXMIPS; + + argv = (char**)KSEG1ADDR((unsigned long)argv); + arcs_cmdline[0] = '\0'; + for(i = 1; i < argc; i++) + { + char *a = (char*)KSEG1ADDR(argv[i]); + if(!a) + continue; + if(strlen(arcs_cmdline) + strlen(a + 1) >= sizeof(arcs_cmdline)) + break; + strcat(arcs_cmdline, a); + strcat(arcs_cmdline, " "); + } + + envp = (char**)KSEG1ADDR((unsigned long)envp); + while(*envp) + { + char *e = (char*)KSEG1ADDR(*envp); + + if(!strncmp(e, "memsize=", 8)) + { + e += 8; + memsize = simple_strtoul(e, NULL, 10); + } + envp++; + } + + prom_cp1_size = 2; + memsize -= prom_cp1_size; + prom_cp1_base = (unsigned int*)(0xA0000000 + (memsize * 1024 * 1024)); + + prom_printf("Using %dMB Ram and reserving %dMB for cp1\n", memsize, prom_cp1_size); + memsize *= 1024 * 1024; + + if(!*arcs_cmdline) + strcpy(&(arcs_cmdline[0]), + "console=ttyS0,115200 rootfstype=squashfs,jffs2 init=/etc/preinit"); + + add_memory_region(0x00000000, memsize, BOOT_MEM_RAM); +} diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/reset.c b/target/linux/ifxmips/files/arch/mips/ifxmips/reset.c new file mode 100644 index 0000000000..d94d8ac810 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/reset.c @@ -0,0 +1,58 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include +#include + +static void +ifxmips_machine_restart(char *command) +{ + printk(KERN_NOTICE "System restart\n"); + local_irq_disable(); + + ifxmips_w32(ifxmips_r32(IFXMIPS_RCU_RST) | IFXMIPS_RCU_RST_ALL, IFXMIPS_RCU_RST); + for(;;); +} + +static void +ifxmips_machine_halt(void) +{ + printk(KERN_NOTICE "System halted.\n"); + local_irq_disable(); + for(;;); +} + +static void +ifxmips_machine_power_off(void) +{ + printk (KERN_NOTICE "Please turn off the power now.\n"); + local_irq_disable(); + for(;;); +} + +void +ifxmips_reboot_setup(void) +{ + _machine_restart = ifxmips_machine_restart; + _machine_halt = ifxmips_machine_halt; + pm_power_off = ifxmips_machine_power_off; +} diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/setup.c b/target/linux/ifxmips/files/arch/mips/ifxmips/setup.c new file mode 100644 index 0000000000..a29a54d288 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/setup.c @@ -0,0 +1,90 @@ +/* + * 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. + * + * Copyright (C) 2004 peng.liu@infineon.com + * Copyright (C) 2007 John Crispin + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int r4k_offset; +static unsigned int r4k_cur; + +extern void ifxmips_reboot_setup(void); + +unsigned int +ifxmips_get_cpu_ver(void) +{ + return (ifxmips_r32(IFXMIPS_MPS_CHIPID) & 0xF0000000) >> 28; +} +EXPORT_SYMBOL(ifxmips_get_cpu_ver); + +static __inline__ u32 +ifxmips_get_counter_resolution(void) +{ + u32 res; + __asm__ __volatile__( + ".set push\n" + ".set mips32r2\n" + ".set noreorder\n" + "rdhwr %0, $3\n" + "ehb\n" + ".set pop\n" + : "=&r" (res) + : /* no input */ + : "memory"); + instruction_hazard(); + return res; +} + +void __init +plat_time_init(void) +{ + mips_hpt_frequency = ifxmips_get_cpu_hz() / ifxmips_get_counter_resolution(); + r4k_cur = (read_c0_count() + r4k_offset); + write_c0_compare(r4k_cur); + + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_GPT | IFXMIPS_PMU_PWDCR_FPI); + ifxmips_w32(0x100, IFXMIPS_GPTU_GPT_CLC); // set clock divider to 1 +} + +void __init +plat_mem_setup(void) +{ + u32 status; + prom_printf("This %s has a cpu rev of 0x%X\n", get_system_type(), ifxmips_get_cpu_ver()); + + status = read_c0_status(); + status &= (~(1<<25)); + write_c0_status(status); + + ifxmips_reboot_setup(); + + ioport_resource.start = IOPORT_RESOURCE_START; + ioport_resource.end = IOPORT_RESOURCE_END; + iomem_resource.start = IOMEM_RESOURCE_START; + iomem_resource.end = IOMEM_RESOURCE_END; +} diff --git a/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c new file mode 100644 index 0000000000..738f420030 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/ifxmips/timer.c @@ -0,0 +1,844 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6 + +#ifdef TIMER1A +#define FIRST_TIMER TIMER1A +#else +#define FIRST_TIMER 2 +#endif + +/* + * GPTC divider is set or not. + */ +#define GPTU_CLC_RMC_IS_SET 0 + +/* + * Timer Interrupt (IRQ) + */ +#define TIMER_INTERRUPT INT_NUM_IM3_IRL0 + 22 // Must be adjusted when ICU driver is available + +/* + * Bits Operation + */ +#define GET_BITS(x, msb, lsb) (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb)) +#define SET_BITS(x, msb, lsb, value) (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb))) + +/* + * GPTU Register Mapping + */ +#define IFXMIPS_GPTU (KSEG1 + 0x1E100A00) +#define IFXMIPS_GPTU_CLC ((volatile u32*)(IFXMIPS_GPTU + 0x0000)) +#define IFXMIPS_GPTU_ID ((volatile u32*)(IFXMIPS_GPTU + 0x0008)) +#define IFXMIPS_GPTU_CON(n, X) ((volatile u32*)(IFXMIPS_GPTU + 0x0010 + ((X) * 4) + ((n) - 1) * 0x0020)) // X must be either A or B +#define IFXMIPS_GPTU_RUN(n, X) ((volatile u32*)(IFXMIPS_GPTU + 0x0018 + ((X) * 4) + ((n) - 1) * 0x0020)) // X must be either A or B +#define IFXMIPS_GPTU_RELOAD(n, X) ((volatile u32*)(IFXMIPS_GPTU + 0x0020 + ((X) * 4) + ((n) - 1) * 0x0020)) // X must be either A or B +#define IFXMIPS_GPTU_COUNT(n, X) ((volatile u32*)(IFXMIPS_GPTU + 0x0028 + ((X) * 4) + ((n) - 1) * 0x0020)) // X must be either A or B +#define IFXMIPS_GPTU_IRNEN ((volatile u32*)(IFXMIPS_GPTU + 0x00F4)) +#define IFXMIPS_GPTU_IRNICR ((volatile u32*)(IFXMIPS_GPTU + 0x00F8)) +#define IFXMIPS_GPTU_IRNCR ((volatile u32*)(IFXMIPS_GPTU + 0x00FC)) + +/* + * Clock Control Register + */ +#define GPTU_CLC_SMC GET_BITS(*IFXMIPS_GPTU_CLC, 23, 16) +#define GPTU_CLC_RMC GET_BITS(*IFXMIPS_GPTU_CLC, 15, 8) +#define GPTU_CLC_FSOE (*IFXMIPS_GPTU_CLC & (1 << 5)) +#define GPTU_CLC_EDIS (*IFXMIPS_GPTU_CLC & (1 << 3)) +#define GPTU_CLC_SPEN (*IFXMIPS_GPTU_CLC & (1 << 2)) +#define GPTU_CLC_DISS (*IFXMIPS_GPTU_CLC & (1 << 1)) +#define GPTU_CLC_DISR (*IFXMIPS_GPTU_CLC & (1 << 0)) + +#define GPTU_CLC_SMC_SET(value) SET_BITS(0, 23, 16, (value)) +#define GPTU_CLC_RMC_SET(value) SET_BITS(0, 15, 8, (value)) +#define GPTU_CLC_FSOE_SET(value) ((value) ? (1 << 5) : 0) +#define GPTU_CLC_SBWE_SET(value) ((value) ? (1 << 4) : 0) +#define GPTU_CLC_EDIS_SET(value) ((value) ? (1 << 3) : 0) +#define GPTU_CLC_SPEN_SET(value) ((value) ? (1 << 2) : 0) +#define GPTU_CLC_DISR_SET(value) ((value) ? (1 << 0) : 0) + +/* + * ID Register + */ +#define GPTU_ID_ID GET_BITS(*IFXMIPS_GPTU_ID, 15, 8) +#define GPTU_ID_CFG GET_BITS(*IFXMIPS_GPTU_ID, 7, 5) +#define GPTU_ID_REV GET_BITS(*IFXMIPS_GPTU_ID, 4, 0) + +/* + * Control Register of Timer/Counter nX + * n is the index of block (1 based index) + * X is either A or B + */ +#define GPTU_CON_SRC_EG(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 10)) +#define GPTU_CON_SRC_EXT(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 9)) +#define GPTU_CON_SYNC(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 8)) +#define GPTU_CON_EDGE(n, X) GET_BITS(*IFXMIPS_GPTU_CON(n, X), 7, 6) +#define GPTU_CON_INV(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 5)) +#define GPTU_CON_EXT(n, X) (*IFXMIPS_GPTU_CON(n, A) & (1 << 4)) // Timer/Counter B does not have this bit +#define GPTU_CON_STP(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 3)) +#define GPTU_CON_CNT(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 2)) +#define GPTU_CON_DIR(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 1)) +#define GPTU_CON_EN(n, X) (*IFXMIPS_GPTU_CON(n, X) & (1 << 0)) + +#define GPTU_CON_SRC_EG_SET(value) ((value) ? 0 : (1 << 10)) +#define GPTU_CON_SRC_EXT_SET(value) ((value) ? (1 << 9) : 0) +#define GPTU_CON_SYNC_SET(value) ((value) ? (1 << 8) : 0) +#define GPTU_CON_EDGE_SET(value) SET_BITS(0, 7, 6, (value)) +#define GPTU_CON_INV_SET(value) ((value) ? (1 << 5) : 0) +#define GPTU_CON_EXT_SET(value) ((value) ? (1 << 4) : 0) +#define GPTU_CON_STP_SET(value) ((value) ? (1 << 3) : 0) +#define GPTU_CON_CNT_SET(value) ((value) ? (1 << 2) : 0) +#define GPTU_CON_DIR_SET(value) ((value) ? (1 << 1) : 0) + +#define GPTU_RUN_RL_SET(value) ((value) ? (1 << 2) : 0) +#define GPTU_RUN_CEN_SET(value) ((value) ? (1 << 1) : 0) +#define GPTU_RUN_SEN_SET(value) ((value) ? (1 << 0) : 0) + +#define GPTU_IRNEN_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0) +#define GPTU_IRNCR_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0) + +#define TIMER_FLAG_MASK_SIZE(x) (x & 0x0001) +#define TIMER_FLAG_MASK_TYPE(x) (x & 0x0002) +#define TIMER_FLAG_MASK_STOP(x) (x & 0x0004) +#define TIMER_FLAG_MASK_DIR(x) (x & 0x0008) +#define TIMER_FLAG_NONE_EDGE 0x0000 +#define TIMER_FLAG_MASK_EDGE(x) (x & 0x0030) +#define TIMER_FLAG_REAL 0x0000 +#define TIMER_FLAG_INVERT 0x0040 +#define TIMER_FLAG_MASK_INVERT(x) (x & 0x0040) +#define TIMER_FLAG_MASK_TRIGGER(x) (x & 0x0070) +#define TIMER_FLAG_MASK_SYNC(x) (x & 0x0080) +#define TIMER_FLAG_CALLBACK_IN_HB 0x0200 +#define TIMER_FLAG_MASK_HANDLE(x) (x & 0x0300) +#define TIMER_FLAG_MASK_SRC(x) (x & 0x1000) + +struct timer_dev_timer { + unsigned int f_irq_on; + unsigned int irq; + unsigned int flag; + unsigned long arg1; + unsigned long arg2; +}; + +struct timer_dev { + struct mutex gptu_mutex; + unsigned int number_of_timers; + unsigned int occupation; + unsigned int f_gptu_on; + struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2]; +}; + +static int gptu_ioctl(struct inode *, struct file *, unsigned int, unsigned long); +static int gptu_open(struct inode *, struct file *); +static int gptu_release(struct inode *, struct file *); + +static struct file_operations gptu_fops = { + .owner = THIS_MODULE, + .ioctl = gptu_ioctl, + .open = gptu_open, + .release = gptu_release +}; + +static struct miscdevice gptu_miscdev = { + .minor = MISC_DYNAMIC_MINOR, + .name = "gptu", + .fops = &gptu_fops, +}; + +static struct timer_dev timer_dev; + + +static irqreturn_t +timer_irq_handler(int irq, void *p) +{ + unsigned int timer; + unsigned int flag; + struct timer_dev_timer *dev_timer = (struct timer_dev_timer*) p; + + timer = irq - TIMER_INTERRUPT; + if(timer < timer_dev.number_of_timers && dev_timer == &timer_dev.timer[timer]) + { + /* Clear interrupt. */ + ifxmips_w32(1 << timer, IFXMIPS_GPTU_IRNCR); + + /* Call user hanler or signal. */ + flag = dev_timer->flag; + if (!(timer & 0x01) || TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT) + { /* 16-bit timer or timer A of 32-bit timer */ + switch(TIMER_FLAG_MASK_HANDLE (flag)) + { + case TIMER_FLAG_CALLBACK_IN_IRQ: + case TIMER_FLAG_CALLBACK_IN_HB: + if (dev_timer->arg1) + (*(timer_callback) dev_timer->arg1) (dev_timer->arg2); + break; + case TIMER_FLAG_SIGNAL: + send_sig ((int) dev_timer->arg2, (struct task_struct *) dev_timer->arg1, 0); + break; + } + } + } + return IRQ_HANDLED; +} + +static inline void +ifxmips_enable_gptu(void) +{ + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_GPT); + + /* Set divider as 1, disable write protection for SPEN, enable module. */ + *IFXMIPS_GPTU_CLC = + GPTU_CLC_SMC_SET(0x00) | GPTU_CLC_RMC_SET(0x01) | GPTU_CLC_FSOE_SET(0) | + GPTU_CLC_SBWE_SET(1) | GPTU_CLC_EDIS_SET(0) | GPTU_CLC_SPEN_SET(0) | GPTU_CLC_DISR_SET(0); +} + +static inline void +ifxmips_disable_gptu(void) +{ + ifxmips_w32(0x00, IFXMIPS_GPTU_IRNEN); + ifxmips_w32(0xfff, IFXMIPS_GPTU_IRNCR); + + /* Set divider as 0, enable write protection for SPEN, disable module. */ + *IFXMIPS_GPTU_CLC = + GPTU_CLC_SMC_SET (0x00) | GPTU_CLC_RMC_SET (0x00) | GPTU_CLC_FSOE_SET (0) | + GPTU_CLC_SBWE_SET (0) | GPTU_CLC_EDIS_SET (0) | GPTU_CLC_SPEN_SET (0) | GPTU_CLC_DISR_SET (1); + + ifxmips_pmu_disable(IFXMIPS_PMU_PWDCR_GPT); +} + +int +ifxmips_request_timer(unsigned int timer, unsigned int flag, unsigned long value, + unsigned long arg1, unsigned long arg2) +{ + int ret = 0; + unsigned int con_reg, irnen_reg; + int n, X; + + if(timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + printk(KERN_INFO "request_timer(%d, 0x%08X, %lu)...", (u32)timer, (u32)flag, value); + + if(TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) + value &= 0xFFFF; + else + timer &= ~0x01; + + mutex_lock(&timer_dev.gptu_mutex); + + /* + * Allocate timer. + */ + if (timer < FIRST_TIMER) { + unsigned int mask; + unsigned int shift; + unsigned int offset = TIMER2A;/* This takes care of TIMER1B which is the only choice for Voice TAPI system */ + + /* + * Pick up a free timer. + */ + if (TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT) { + mask = 1 << offset; + shift = 1; + } + else { + mask = 3 << offset; + shift = 2; + } + for (timer = offset; + timer < offset + timer_dev.number_of_timers; + timer += shift, mask <<= shift) + if (!(timer_dev.occupation & mask)) { + timer_dev.occupation |= mask; + break; + } + if (timer >= offset + timer_dev.number_of_timers) { + printk("failed![%d]\n", __LINE__); + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + else + ret = timer; + } + else { + register unsigned int mask; + + /* + * Check if the requested timer is free. + */ + mask = (TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer; + if ((timer_dev.occupation & mask)) { + printk("failed![%d] mask %#x, timer_dev.occupation %#x\n", __LINE__, mask, timer_dev.occupation); + mutex_unlock(&timer_dev.gptu_mutex); + return -EBUSY; + } + else { + timer_dev.occupation |= mask; + ret = 0; + } + } + + /* + * Prepare control register value. + */ + switch (TIMER_FLAG_MASK_EDGE (flag)) { + default: + case TIMER_FLAG_NONE_EDGE: + con_reg = GPTU_CON_EDGE_SET (0x00); + break; + case TIMER_FLAG_RISE_EDGE: + con_reg = GPTU_CON_EDGE_SET (0x01); + break; + case TIMER_FLAG_FALL_EDGE: + con_reg = GPTU_CON_EDGE_SET (0x02); + break; + case TIMER_FLAG_ANY_EDGE: + con_reg = GPTU_CON_EDGE_SET (0x03); + break; + } + if (TIMER_FLAG_MASK_TYPE (flag) == TIMER_FLAG_TIMER) + con_reg |= + TIMER_FLAG_MASK_SRC (flag) == + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET (1) : + GPTU_CON_SRC_EXT_SET (0); + else + con_reg |= + TIMER_FLAG_MASK_SRC (flag) == + TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET (1) : + GPTU_CON_SRC_EG_SET (0); + con_reg |= + TIMER_FLAG_MASK_SYNC (flag) == + TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET (0) : + GPTU_CON_SYNC_SET (1); + con_reg |= + TIMER_FLAG_MASK_INVERT (flag) == + TIMER_FLAG_REAL ? GPTU_CON_INV_SET (0) : GPTU_CON_INV_SET (1); + con_reg |= + TIMER_FLAG_MASK_SIZE (flag) == + TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET (0) : + GPTU_CON_EXT_SET (1); + con_reg |= + TIMER_FLAG_MASK_STOP (flag) == + TIMER_FLAG_ONCE ? GPTU_CON_STP_SET (1) : GPTU_CON_STP_SET (0); + con_reg |= + TIMER_FLAG_MASK_TYPE (flag) == + TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET (0) : + GPTU_CON_CNT_SET (1); + con_reg |= + TIMER_FLAG_MASK_DIR (flag) == + TIMER_FLAG_UP ? GPTU_CON_DIR_SET (1) : GPTU_CON_DIR_SET (0); + + /* + * Fill up running data. + */ + timer_dev.timer[timer - FIRST_TIMER].flag = flag; + timer_dev.timer[timer - FIRST_TIMER].arg1 = arg1; + timer_dev.timer[timer - FIRST_TIMER].arg2 = arg2; + if (TIMER_FLAG_MASK_SIZE (flag) != TIMER_FLAG_16BIT) + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flag; + + /* + * Enable GPTU module. + */ + if (!timer_dev.f_gptu_on) { + ifxmips_enable_gptu (); + timer_dev.f_gptu_on = 1; + } + + /* + * Enable IRQ. + */ + if (TIMER_FLAG_MASK_HANDLE (flag) != TIMER_FLAG_NO_HANDLE) { + if (TIMER_FLAG_MASK_HANDLE (flag) == TIMER_FLAG_SIGNAL) + timer_dev.timer[timer - FIRST_TIMER].arg1 = + (unsigned long) find_task_by_pid ((int) arg1); + + irnen_reg = 1 << (timer - FIRST_TIMER); + + if (TIMER_FLAG_MASK_HANDLE (flag) == TIMER_FLAG_SIGNAL + || (TIMER_FLAG_MASK_HANDLE (flag) == + TIMER_FLAG_CALLBACK_IN_IRQ + && timer_dev.timer[timer - FIRST_TIMER].arg1)) { + enable_irq (timer_dev.timer[timer - FIRST_TIMER].irq); + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 1; + } + } + else + irnen_reg = 0; + + /* + * Write config register, reload value and enable interrupt. + */ + n = timer >> 1; + X = timer & 0x01; + *IFXMIPS_GPTU_CON (n, X) = con_reg; + *IFXMIPS_GPTU_RELOAD (n, X) = value; +// printk("reload value = %d\n", (u32)value); + *IFXMIPS_GPTU_IRNEN |= irnen_reg; + + mutex_unlock(&timer_dev.gptu_mutex); + printk("successful!\n"); + return ret; +} + +int +ifxmips_free_timer(unsigned int timer) +{ + unsigned int flag; + unsigned int mask; + int n, X; + + if(!timer_dev.f_gptu_on) + return -EINVAL; + + if(timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + mutex_lock(&timer_dev.gptu_mutex); + + flag = timer_dev.timer[timer - FIRST_TIMER].flag; + if(TIMER_FLAG_MASK_SIZE (flag) != TIMER_FLAG_16BIT) + timer &= ~0x01; + + mask = (TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer; + if(((timer_dev.occupation & mask) ^ mask)) + { + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + + n = timer >> 1; + X = timer & 0x01; + + if(GPTU_CON_EN (n, X)) + *IFXMIPS_GPTU_RUN (n, X) = GPTU_RUN_CEN_SET (1); + + *IFXMIPS_GPTU_IRNEN &= ~GPTU_IRNEN_TC_SET (n, X, 1); + *IFXMIPS_GPTU_IRNCR |= GPTU_IRNCR_TC_SET (n, X, 1); + + if(timer_dev.timer[timer - FIRST_TIMER].f_irq_on) { + disable_irq (timer_dev.timer[timer - FIRST_TIMER].irq); + timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 0; + } + + timer_dev.occupation &= ~mask; + if(!timer_dev.occupation && timer_dev.f_gptu_on) + { + ifxmips_disable_gptu(); + timer_dev.f_gptu_on = 0; + } + + mutex_unlock(&timer_dev.gptu_mutex); + + return 0; +} + +int +ifxmips_start_timer(unsigned int timer, int is_resume) +{ + unsigned int flag; + unsigned int mask; + int n, X; + + if(!timer_dev.f_gptu_on) + return -EINVAL; + + if(timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + mutex_lock(&timer_dev.gptu_mutex); + + flag = timer_dev.timer[timer - FIRST_TIMER].flag; + if(TIMER_FLAG_MASK_SIZE (flag) != TIMER_FLAG_16BIT) + timer &= ~0x01; + + mask = (TIMER_FLAG_MASK_SIZE (flag) == + TIMER_FLAG_16BIT ? 1 : 3) << timer; + if(((timer_dev.occupation & mask) ^ mask)) + { + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + + n = timer >> 1; + X = timer & 0x01; + + *IFXMIPS_GPTU_RUN (n, X) = GPTU_RUN_RL_SET (!is_resume) | GPTU_RUN_SEN_SET (1); + + mutex_unlock(&timer_dev.gptu_mutex); + + return 0; +} + +int +ifxmips_stop_timer(unsigned int timer) +{ + unsigned int flag; + unsigned int mask; + int n, X; + + if (!timer_dev.f_gptu_on) + return -EINVAL; + + if (timer < FIRST_TIMER + || timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + mutex_lock(&timer_dev.gptu_mutex); + + flag = timer_dev.timer[timer - FIRST_TIMER].flag; + if(TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT) + timer &= ~0x01; + + mask = (TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer; + if(((timer_dev.occupation & mask) ^ mask)) + { + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + + n = timer >> 1; + X = timer & 0x01; + + *IFXMIPS_GPTU_RUN (n, X) = GPTU_RUN_CEN_SET (1); + + mutex_unlock(&timer_dev.gptu_mutex); + + return 0; +} + +int +ifxmips_reset_counter_flags(u32 timer, u32 flags) +{ + unsigned int oflag; + unsigned int mask, con_reg; + int n, X; + + if(!timer_dev.f_gptu_on) + return -EINVAL; + + if(timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + mutex_lock(&timer_dev.gptu_mutex); + + oflag = timer_dev.timer[timer - FIRST_TIMER].flag; + if(TIMER_FLAG_MASK_SIZE (oflag) != TIMER_FLAG_16BIT) + timer &= ~0x01; + + mask = (TIMER_FLAG_MASK_SIZE (oflag) == TIMER_FLAG_16BIT ? 1 : 3) << timer; + if(((timer_dev.occupation & mask) ^ mask)) + { + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + + switch(TIMER_FLAG_MASK_EDGE (flags)) + { + default: + case TIMER_FLAG_NONE_EDGE: + con_reg = GPTU_CON_EDGE_SET(0x00); + break; + case TIMER_FLAG_RISE_EDGE: + con_reg = GPTU_CON_EDGE_SET(0x01); + break; + case TIMER_FLAG_FALL_EDGE: + con_reg = GPTU_CON_EDGE_SET(0x02); + break; + case TIMER_FLAG_ANY_EDGE: + con_reg = GPTU_CON_EDGE_SET(0x03); + break; + } + if(TIMER_FLAG_MASK_TYPE (flags) == TIMER_FLAG_TIMER) + con_reg |= TIMER_FLAG_MASK_SRC (flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET (1) : GPTU_CON_SRC_EXT_SET (0); + else + con_reg |= TIMER_FLAG_MASK_SRC (flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET (1) : GPTU_CON_SRC_EG_SET (0); + con_reg |= TIMER_FLAG_MASK_SYNC (flags) == TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET (0) : GPTU_CON_SYNC_SET (1); + con_reg |= TIMER_FLAG_MASK_INVERT (flags) == TIMER_FLAG_REAL ? GPTU_CON_INV_SET (0) : GPTU_CON_INV_SET (1); + con_reg |= TIMER_FLAG_MASK_SIZE (flags) == TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET (0) : GPTU_CON_EXT_SET (1); + con_reg |= TIMER_FLAG_MASK_STOP (flags) == TIMER_FLAG_ONCE ? GPTU_CON_STP_SET (1) : GPTU_CON_STP_SET (0); + con_reg |= TIMER_FLAG_MASK_TYPE (flags) == TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET (0) : GPTU_CON_CNT_SET (1); + con_reg |= TIMER_FLAG_MASK_DIR (flags) == TIMER_FLAG_UP ? GPTU_CON_DIR_SET (1) : GPTU_CON_DIR_SET (0); + + timer_dev.timer[timer - FIRST_TIMER].flag = flags; + if(TIMER_FLAG_MASK_SIZE(flags) != TIMER_FLAG_16BIT) + timer_dev.timer[timer - FIRST_TIMER + 1].flag = flags; + + n = timer >> 1; + X = timer & 0x01; + + *IFXMIPS_GPTU_CON(n, X) = con_reg; + smp_wmb(); + printk(KERN_INFO "[%s]: counter%d oflags %#x, nflags %#x, GPTU_CON %#x\n", __func__, timer, oflag, flags, *IFXMIPS_GPTU_CON (n, X)); + mutex_unlock(&timer_dev.gptu_mutex); + return 0; +} +EXPORT_SYMBOL(ifxmips_reset_counter_flags); + +inline int +ifxmips_get_count_value(unsigned int timer, unsigned long *value) +{ + + unsigned int flag; + unsigned int mask; + int n, X; + + if(!timer_dev.f_gptu_on) + return -EINVAL; + + if(timer < FIRST_TIMER + || timer >= FIRST_TIMER + timer_dev.number_of_timers) + return -EINVAL; + + mutex_lock(&timer_dev.gptu_mutex); + + flag = timer_dev.timer[timer - FIRST_TIMER].flag; + if(TIMER_FLAG_MASK_SIZE (flag) != TIMER_FLAG_16BIT) + timer &= ~0x01; + + mask = (TIMER_FLAG_MASK_SIZE (flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer; + if (((timer_dev.occupation & mask) ^ mask)) + { + mutex_unlock(&timer_dev.gptu_mutex); + return -EINVAL; + } + + n = timer >> 1; + X = timer & 0x01; + + *value = *IFXMIPS_GPTU_COUNT (n, X); + + mutex_unlock(&timer_dev.gptu_mutex); + + return 0; +} + +u32 +ifxmips_cal_divider(unsigned long freq) +{ + u64 module_freq, fpi = cgu_get_fpi_bus_clock(2); + u32 clock_divider = 1; + module_freq = fpi * 1000; + do_div(module_freq, clock_divider * freq); + return module_freq; +} + +int +ifxmips_set_timer (unsigned int timer, unsigned int freq, int is_cyclic, + int is_ext_src, unsigned int handle_flag, unsigned long arg1, + unsigned long arg2) +{ + unsigned long divider; + unsigned int flag; + + divider = ifxmips_cal_divider(freq); + if (divider == 0) + return -EINVAL; + flag = ((divider & ~0xFFFF) ? TIMER_FLAG_32BIT : TIMER_FLAG_16BIT) + | (is_cyclic ? TIMER_FLAG_CYCLIC : TIMER_FLAG_ONCE) + | (is_ext_src ? TIMER_FLAG_EXT_SRC : TIMER_FLAG_INT_SRC) + | TIMER_FLAG_TIMER | TIMER_FLAG_DOWN + | TIMER_FLAG_MASK_HANDLE (handle_flag); + + printk(KERN_INFO "set_timer(%d, %d), divider = %lu\n", timer, freq, divider); + return ifxmips_request_timer (timer, flag, divider, arg1, arg2); +} + +int +ifxmips_set_counter(unsigned int timer, unsigned int flag, u32 reload, unsigned long arg1, unsigned long arg2) +{ + printk(KERN_INFO "set_counter(%d, %#x, %d)\n", timer, flag, reload); + return ifxmips_request_timer(timer, flag, reload, arg1, arg2); +} + +static int +gptu_ioctl (struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret; + struct gptu_ioctl_param param; + + if (!access_ok (VERIFY_READ, arg, sizeof (struct gptu_ioctl_param))) + return -EFAULT; + copy_from_user (¶m, (void *) arg, sizeof (param)); + + if ((((cmd == GPTU_REQUEST_TIMER || cmd == GPTU_SET_TIMER + || GPTU_SET_COUNTER) && param.timer < 2) + || cmd == GPTU_GET_COUNT_VALUE || cmd == GPTU_CALCULATE_DIVIDER) + && !access_ok (VERIFY_WRITE, arg, + sizeof (struct gptu_ioctl_param))) + return -EFAULT; + + switch (cmd) { + case GPTU_REQUEST_TIMER: + ret = ifxmips_request_timer (param.timer, param.flag, param.value, + (unsigned long) param.pid, + (unsigned long) param.sig); + if (ret > 0) { + copy_to_user (&((struct gptu_ioctl_param *) arg)-> + timer, &ret, sizeof (&ret)); + ret = 0; + } + break; + case GPTU_FREE_TIMER: + ret = ifxmips_free_timer (param.timer); + break; + case GPTU_START_TIMER: + ret = ifxmips_start_timer (param.timer, param.flag); + break; + case GPTU_STOP_TIMER: + ret = ifxmips_stop_timer (param.timer); + break; + case GPTU_GET_COUNT_VALUE: + ret = ifxmips_get_count_value (param.timer, ¶m.value); + if (!ret) + copy_to_user (&((struct gptu_ioctl_param *) arg)-> + value, ¶m.value, + sizeof (param.value)); + break; + case GPTU_CALCULATE_DIVIDER: + param.value = ifxmips_cal_divider (param.value); + if (param.value == 0) + ret = -EINVAL; + else { + copy_to_user (&((struct gptu_ioctl_param *) arg)-> + value, ¶m.value, + sizeof (param.value)); + ret = 0; + } + break; + case GPTU_SET_TIMER: + ret = ifxmips_set_timer (param.timer, param.value, + TIMER_FLAG_MASK_STOP (param.flag) != + TIMER_FLAG_ONCE ? 1 : 0, + TIMER_FLAG_MASK_SRC (param.flag) == + TIMER_FLAG_EXT_SRC ? 1 : 0, + TIMER_FLAG_MASK_HANDLE (param.flag) == + TIMER_FLAG_SIGNAL ? TIMER_FLAG_SIGNAL : + TIMER_FLAG_NO_HANDLE, + (unsigned long) param.pid, + (unsigned long) param.sig); + if (ret > 0) { + copy_to_user (&((struct gptu_ioctl_param *) arg)-> + timer, &ret, sizeof (&ret)); + ret = 0; + } + break; + case GPTU_SET_COUNTER: + ifxmips_set_counter (param.timer, param.flag, param.value, 0, 0); + if (ret > 0) { + copy_to_user (&((struct gptu_ioctl_param *) arg)-> + timer, &ret, sizeof (&ret)); + ret = 0; + } + break; + default: + ret = -ENOTTY; + } + + return ret; +} + +static int +gptu_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int +gptu_release(struct inode *inode, struct file *file) +{ + return 0; +} +int __init +ifxmips_gptu_init(void) +{ + int ret; + unsigned int i; + + ifxmips_w32(0, IFXMIPS_GPTU_IRNEN); + ifxmips_w32(0xfff, IFXMIPS_GPTU_IRNCR); + + memset(&timer_dev, 0, sizeof (timer_dev)); + mutex_init(&timer_dev.gptu_mutex); + + ifxmips_enable_gptu(); + timer_dev.number_of_timers = GPTU_ID_CFG * 2; + ifxmips_disable_gptu (); + if(timer_dev.number_of_timers > MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2) + timer_dev.number_of_timers = MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2; + printk (KERN_INFO "gptu: totally %d 16-bit timers/counters\n", timer_dev.number_of_timers); + + ret = misc_register(&gptu_miscdev); + if(ret) + { + printk(KERN_ERR "gptu: can't misc_register, get error %d\n", -ret); + return ret; + } else { + printk(KERN_INFO "gptu: misc_register on minor %d\n", gptu_miscdev.minor); + } + + for(i = 0; i < timer_dev.number_of_timers; i++) + { + ret = request_irq (TIMER_INTERRUPT + i, timer_irq_handler, IRQF_TIMER, gptu_miscdev.name, &timer_dev.timer[i]); + if(ret) + { + for (; i >= 0; i--) + free_irq (TIMER_INTERRUPT + i, &timer_dev.timer[i]); + misc_deregister(&gptu_miscdev); + printk(KERN_ERR "gptu: failed in requesting irq (%d), get error %d\n", i, -ret); + return ret; + } else { + timer_dev.timer[i].irq = TIMER_INTERRUPT + i; + disable_irq(timer_dev.timer[i].irq); + printk(KERN_INFO "gptu: succeeded to request irq %d\n", timer_dev.timer[i].irq); + } + } + + return 0; +} + +void __exit +ifxmips_gptu_exit(void) +{ + unsigned int i; + + for(i = 0; i < timer_dev.number_of_timers; i++) + { + if(timer_dev.timer[i].f_irq_on) + disable_irq (timer_dev.timer[i].irq); + free_irq(timer_dev.timer[i].irq, &timer_dev.timer[i]); + } + ifxmips_disable_gptu(); + misc_deregister(&gptu_miscdev); +} + +EXPORT_SYMBOL(ifxmips_request_timer); +EXPORT_SYMBOL(ifxmips_free_timer); +EXPORT_SYMBOL(ifxmips_start_timer); +EXPORT_SYMBOL(ifxmips_stop_timer); +EXPORT_SYMBOL(ifxmips_get_count_value); +EXPORT_SYMBOL(ifxmips_cal_divider); +EXPORT_SYMBOL(ifxmips_set_timer); +EXPORT_SYMBOL(ifxmips_set_counter); + +module_init(ifxmips_gptu_init); +module_exit(ifxmips_gptu_exit); diff --git a/target/linux/ifxmips/files/arch/mips/pci/ops-ifxmips.c b/target/linux/ifxmips/files/arch/mips/pci/ops-ifxmips.c new file mode 100644 index 0000000000..e04c246eae --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/pci/ops-ifxmips.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IFXMIPS_PCI_CFG_BUSNUM_SHF 16 +#define IFXMIPS_PCI_CFG_DEVNUM_SHF 11 +#define IFXMIPS_PCI_CFG_FUNNUM_SHF 8 + +#define PCI_ACCESS_READ 0 +#define PCI_ACCESS_WRITE 1 + +extern u32 ifxmips_pci_mapped_cfg; + +static int +ifxmips_pci_config_access(unsigned char access_type, + struct pci_bus *bus, unsigned int devfn, unsigned int where, u32 *data) +{ + unsigned long cfg_base; + unsigned long flags; + + u32 temp; + + /* IFXMips support slot from 0 to 15 */ + /* dev_fn 0&0x68 (AD29) is ifxmips itself */ + if ((bus->number != 0) || ((devfn & 0xf8) > 0x78) + || ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68)) + return 1; + + spin_lock_irqsave(&ebu_lock, flags); + + cfg_base = ifxmips_pci_mapped_cfg; + cfg_base |= (bus->number << IFXMIPS_PCI_CFG_BUSNUM_SHF) | (devfn << + IFXMIPS_PCI_CFG_FUNNUM_SHF) | (where & ~0x3); + + /* Perform access */ + if (access_type == PCI_ACCESS_WRITE) + { +#ifdef CONFIG_SWAP_IO_SPACE + ifxmips_w32(swab32(*data), ((u32*)cfg_base)); +#else + ifxmips_w32(*data, ((u32*)cfg_base)); +#endif + } else { + *data = ifxmips_r32(((u32*)(cfg_base))); +#ifdef CONFIG_SWAP_IO_SPACE + *data = swab32(*data); +#endif + } + wmb(); + + /* clean possible Master abort */ + cfg_base = (ifxmips_pci_mapped_cfg | (0x0 << IFXMIPS_PCI_CFG_FUNNUM_SHF)) + 4; + temp = ifxmips_r32(((u32*)(cfg_base))); +#ifdef CONFIG_SWAP_IO_SPACE + temp = swab32 (temp); +#endif + cfg_base = (ifxmips_pci_mapped_cfg | (0x68 << IFXMIPS_PCI_CFG_FUNNUM_SHF)) + 4; + ifxmips_w32(temp, ((u32*)cfg_base)); + + spin_unlock_irqrestore(&ebu_lock, flags); + + if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ)) + return 1; + + return 0; +} + +int +ifxmips_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * val) +{ + u32 data = 0; + + if (ifxmips_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (size == 1) + *val = (data >> ((where & 3) << 3)) & 0xff; + else if (size == 2) + *val = (data >> ((where & 3) << 3)) & 0xffff; + else + *val = data; + + return PCIBIOS_SUCCESSFUL; +} + +int +ifxmips_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 val) +{ + u32 data = 0; + + if (size == 4) + { + data = val; + } else { + if (ifxmips_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + if (size == 1) + data = (data & ~(0xff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + else if (size == 2) + data = (data & ~(0xffff << ((where & 3) << 3))) | + (val << ((where & 3) << 3)); + } + + if (ifxmips_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} diff --git a/target/linux/ifxmips/files/arch/mips/pci/pci-ifxmips.c b/target/linux/ifxmips/files/arch/mips/pci/pci-ifxmips.c new file mode 100644 index 0000000000..97efa37dd1 --- /dev/null +++ b/target/linux/ifxmips/files/arch/mips/pci/pci-ifxmips.c @@ -0,0 +1,193 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IFXMIPS_PCI_MEM_BASE 0x18000000 +#define IFXMIPS_PCI_MEM_SIZE 0x02000000 +#define IFXMIPS_PCI_IO_BASE 0x1AE00000 +#define IFXMIPS_PCI_IO_SIZE 0x00200000 + +extern int ifxmips_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 *val); +extern int ifxmips_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val); + +struct pci_ops ifxmips_pci_ops = +{ + .read = ifxmips_pci_read_config_dword, + .write = ifxmips_pci_write_config_dword +}; + +static struct resource pci_io_resource = +{ + .name = "io pci IO space", + .start = IFXMIPS_PCI_IO_BASE, + .end = IFXMIPS_PCI_IO_BASE + IFXMIPS_PCI_IO_SIZE - 1, + .flags = IORESOURCE_IO +}; + +static struct resource pci_mem_resource = +{ + .name = "ext pci memory space", + .start = IFXMIPS_PCI_MEM_BASE, + .end = IFXMIPS_PCI_MEM_BASE + IFXMIPS_PCI_MEM_SIZE - 1, + .flags = IORESOURCE_MEM +}; + +static struct pci_controller ifxmips_pci_controller = +{ + .pci_ops = &ifxmips_pci_ops, + .mem_resource = &pci_mem_resource, + .mem_offset = 0x00000000UL, + .io_resource = &pci_io_resource, + .io_offset = 0x00000000UL, +}; + +u32 ifxmips_pci_mapped_cfg; +int ifxmips_pci_external_clock = 0; + +static int __init +ifxmips_pci_set_external_clk(char *str) +{ + printk("cgu: setting up external pci clock\n"); + ifxmips_pci_external_clock = 1; + return 1; +} +__setup("pci_external_clk", ifxmips_pci_set_external_clk); + +int +pcibios_plat_dev_init(struct pci_dev *dev) +{ + u8 pin; + + pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin); + switch(pin) + { + case 0: + break; + case 1: + //falling edge level triggered:0x4, low level:0xc, rising edge:0x2 + ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_CON) | 0xc, IFXMIPS_EBU_PCC_CON); + ifxmips_w32(ifxmips_r32(IFXMIPS_EBU_PCC_IEN) | 0x10, IFXMIPS_EBU_PCC_IEN); + break; + case 2: + case 3: + case 4: + printk ("WARNING: interrupt pin %d not supported yet!\n", pin); + default: + printk ("WARNING: invalid interrupt pin %d\n", pin); + return 1; + } + return 0; +} + +static void __init +ifxmips_pci_startup(void) +{ + u32 temp_buffer; + + cgu_setup_pci_clk(ifxmips_pci_external_clock); + + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OD) | (1 << 5), IFXMIPS_GPIO_P1_OD); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | (1 << 5), IFXMIPS_GPIO_P1_DIR); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL1); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) & ~(1 << 5), IFXMIPS_GPIO_P1_ALTSEL0); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) & ~0x2000, IFXMIPS_GPIO_P1_DIR); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_DIR) | 0x4000, IFXMIPS_GPIO_P1_DIR); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL1) & ~0x6000, IFXMIPS_GPIO_P1_ALTSEL1); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_ALTSEL0) | 0x6000, IFXMIPS_GPIO_P1_ALTSEL0); + /* enable auto-switching between PCI and EBU */ + ifxmips_w32(0xa, PCI_CR_CLK_CTRL); + /* busy, i.e. configuration is not done, PCI access has to be retried */ + ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD); + wmb (); + /* BUS Master/IO/MEM access */ + ifxmips_w32(ifxmips_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD); + + /* enable external 2 PCI masters */ + temp_buffer = ifxmips_r32(PCI_CR_PC_ARB); + temp_buffer &= (~(0xf << 16)); + /* enable internal arbiter */ + temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT); + /* enable internal PCI master reqest */ + temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS)); + + /* enable EBU reqest */ + temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS)); + + /* enable all external masters request */ + temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS)); + ifxmips_w32(temp_buffer, PCI_CR_PC_ARB); + wmb (); + + ifxmips_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0); + ifxmips_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1); + ifxmips_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2); + ifxmips_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3); + ifxmips_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4); + ifxmips_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5); + ifxmips_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6); + ifxmips_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7); + ifxmips_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg); + ifxmips_w32(0x0e000008, PCI_CR_BAR11MASK); + ifxmips_w32(0, PCI_CR_PCI_ADDR_MAP11); + ifxmips_w32(0, PCI_CS_BASE_ADDR1); +#ifdef CONFIG_SWAP_IO_SPACE + /* both TX and RX endian swap are enabled */ + ifxmips_w32(ifxmips_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI); + wmb (); +#endif + /*TODO: disable BAR2 & BAR3 - why was this in the origianl infineon code */ + ifxmips_w32(ifxmips_r32(PCI_CR_BAR12MASK) | 0x80000000, PCI_CR_BAR12MASK); + ifxmips_w32(ifxmips_r32(PCI_CR_BAR13MASK) | 0x80000000, PCI_CR_BAR13MASK); + /*use 8 dw burst length */ + ifxmips_w32(0x303, PCI_CR_FCI_BURST_LENGTH); + ifxmips_w32(ifxmips_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD); + wmb(); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) & ~(1 << 5), IFXMIPS_GPIO_P1_OUT); + wmb(); + mdelay(1); + ifxmips_w32(ifxmips_r32(IFXMIPS_GPIO_P1_OUT) | (1 << 5), IFXMIPS_GPIO_P1_OUT); +} + +int __init +pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin){ + switch(slot) + { + case 13: + /* IDSEL = AD29 --> USB Host Controller */ + return (INT_NUM_IM1_IRL0 + 17); + case 14: + /* IDSEL = AD30 --> mini PCI connector */ + return (INT_NUM_IM0_IRL0 + 22); + default: + printk("Warning: no IRQ found for PCI device in slot %d, pin %d\n", slot, pin); + return 0; + } +} + +int +pcibios_init(void) +{ + extern int pci_probe_only; + + pci_probe_only = 0; + printk("PCI: Probing PCI hardware on host bus 0.\n"); + ifxmips_pci_startup (); + // IFXMIPS_PCI_REG32(PCI_CR_CLK_CTRL_REG) &= (~8); + ifxmips_pci_mapped_cfg = (u32)ioremap_nocache(0x17000000, 0x800 * 16); + printk("IFXMips PCI mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_mapped_cfg); + ifxmips_pci_controller.io_map_base = (unsigned long)ioremap(IFXMIPS_PCI_IO_BASE, IFXMIPS_PCI_IO_SIZE - 1); + printk("IFXMips PCI I/O mapped to 0x%08lX\n", (unsigned long)ifxmips_pci_controller.io_map_base); + register_pci_controller(&ifxmips_pci_controller); + return 0; +} + +arch_initcall(pcibios_init); diff --git a/target/linux/ifxmips/files/drivers/char/ifxmips_eeprom.c b/target/linux/ifxmips/files/drivers/char/ifxmips_eeprom.c new file mode 100644 index 0000000000..ea1303cd66 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/char/ifxmips_eeprom.c @@ -0,0 +1,541 @@ +/* + * 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. + * + * This driver was originally based on the INCA-IP driver, but due to + * fundamental conceptual drawbacks there has been changed a lot. + * + * Based on INCA-IP driver Copyright (c) 2003 Gary Jennejohn + * Based on the VxWorks drivers Copyright (c) 2002, Infineon Technologies. + * + * Copyright (C) 2006 infineon + * Copyright (C) 2007 John Crispin + * + */ + +#define IFAP_EEPROM_DRV_VERSION "0.0.1" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* allow the user to set the major device number */ +static int ifxmips_eeprom_maj = 0; + +extern int ifx_ssc_init (void); +extern int ifx_ssc_open (struct inode *inode, struct file *filp); +extern int ifx_ssc_close (struct inode *inode, struct file *filp); +extern void ifx_ssc_cleanup_module (void); +extern int ifx_ssc_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long data); +extern ssize_t ifx_ssc_kwrite (int port, const char *kbuf, size_t len); +extern ssize_t ifx_ssc_kread (int port, char *kbuf, size_t len); + +extern int ifx_ssc_cs_low (unsigned int pin); +extern int ifx_ssc_cs_high (unsigned int pin); +extern int ifx_ssc_txrx (char *tx_buf, unsigned int tx_len, char *rx_buf, unsigned int rx_len); +extern int ifx_ssc_tx (char *tx_buf, unsigned int tx_len); +extern int ifx_ssc_rx (char *rx_buf, unsigned int rx_len); + +#define EEPROM_CS IFX_SSC_WHBGPOSTAT_OUT0_POS + +/* commands for EEPROM, x25160, x25140 */ +#define EEPROM_WREN ((unsigned char)0x06) +#define EEPROM_WRDI ((unsigned char)0x04) +#define EEPROM_RDSR ((unsigned char)0x05) +#define EEPROM_WRSR ((unsigned char)0x01) +#define EEPROM_READ ((unsigned char)0x03) +#define EEPROM_WRITE ((unsigned char)0x02) +#define EEPROM_PAGE_SIZE 4 +#define EEPROM_SIZE 512 + +static int +eeprom_rdsr (void) +{ + int ret = 0; + unsigned char cmd = EEPROM_RDSR; + unsigned long flag; + char status; + + local_irq_save(flag); + + if ((ret = ifx_ssc_cs_low(EEPROM_CS)) == 0) + if ((ret = ifx_ssc_txrx(&cmd, 1, &status, 1)) >= 0) + ret = status & 1; + + ifx_ssc_cs_high(EEPROM_CS); + local_irq_restore(flag); + + return ret; +} + +void +eeprom_wip_over (void) +{ + while (eeprom_rdsr()) + printk("waiting for eeprom\n"); +} + +static int +eeprom_wren (void) +{ + unsigned char cmd = EEPROM_WREN; + int ret = 0; + unsigned long flag; + + local_irq_save(flag); + if ((ret = ifx_ssc_cs_low(EEPROM_CS)) == 0) + if ((ret = ifx_ssc_tx(&cmd, 1)) >= 0) + ret = 0; + + ifx_ssc_cs_high(EEPROM_CS); + local_irq_restore(flag); + + if (!ret) + eeprom_wip_over(); + + return ret; +} + +static int +eeprom_wrsr (void) +{ + int ret = 0; + unsigned char cmd[2]; + unsigned long flag; + + cmd[0] = EEPROM_WRSR; + cmd[1] = 0; + + if ((ret = eeprom_wren())) + { + printk ("eeprom_wren fails\n"); + goto out1; + } + + local_irq_save(flag); + + if ((ret = ifx_ssc_cs_low(EEPROM_CS))) + goto out; + + if ((ret = ifx_ssc_tx(cmd, 2)) < 0) { + ifx_ssc_cs_high(EEPROM_CS); + goto out; + } + + if ((ret = ifx_ssc_cs_low(EEPROM_CS))) + goto out; + + local_irq_restore(flag); + eeprom_wip_over(); + + return ret; + +out: + local_irq_restore (flag); + eeprom_wip_over (); + +out1: + return ret; +} + +static int +eeprom_read (unsigned int addr, unsigned char *buf, unsigned int len) +{ + int ret = 0; + unsigned char write_buf[2]; + unsigned int eff = 0; + unsigned long flag; + + while (1) + { + eeprom_wip_over(); + eff = EEPROM_PAGE_SIZE - (addr % EEPROM_PAGE_SIZE); + eff = (eff < len) ? eff : len; + local_irq_save(flag); + + if ((ret = ifx_ssc_cs_low(EEPROM_CS)) < 0) + goto out; + + write_buf[0] = EEPROM_READ | ((unsigned char) ((addr & 0x100) >> 5)); + write_buf[1] = (addr & 0xff); + + if ((ret = ifx_ssc_txrx (write_buf, 2, buf, eff)) != eff) + { + printk("ssc_txrx fails %d\n", ret); + ifx_ssc_cs_high (EEPROM_CS); + goto out; + } + + buf += ret; + len -= ret; + addr += ret; + + if ((ret = ifx_ssc_cs_high(EEPROM_CS))) + goto out; + + local_irq_restore(flag); + + if (len <= 0) + goto out2; + } + +out: + local_irq_restore (flag); +out2: + return ret; +} + +static int +eeprom_write (unsigned int addr, unsigned char *buf, unsigned int len) +{ + int ret = 0; + unsigned int eff = 0; + unsigned char write_buf[2]; + int i; + unsigned char rx_buf[EEPROM_PAGE_SIZE]; + + while (1) + { + eeprom_wip_over(); + + if ((ret = eeprom_wren())) + { + printk("eeprom_wren fails\n"); + goto out; + } + + write_buf[0] = EEPROM_WRITE | ((unsigned char) ((addr & 0x100) >> 5)); + write_buf[1] = (addr & 0xff); + + eff = EEPROM_PAGE_SIZE - (addr % EEPROM_PAGE_SIZE); + eff = (eff < len) ? eff : len; + + printk("EEPROM Write:\n"); + for (i = 0; i < eff; i++) { + printk("%2x ", buf[i]); + if ((i % 16) == 15) + printk("\n"); + } + printk("\n"); + + if ((ret = ifx_ssc_cs_low(EEPROM_CS))) + goto out; + + if ((ret = ifx_ssc_tx (write_buf, 2)) < 0) + { + printk("ssc_tx fails %d\n", ret); + ifx_ssc_cs_high(EEPROM_CS); + goto out; + } + + if ((ret = ifx_ssc_tx (buf, eff)) != eff) + { + printk("ssc_tx fails %d\n", ret); + ifx_ssc_cs_high(EEPROM_CS); + goto out; + } + + buf += ret; + len -= ret; + addr += ret; + + if ((ret = ifx_ssc_cs_high (EEPROM_CS))) + goto out; + + printk ("<=="); + eeprom_read((addr - eff), rx_buf, eff); + for (i = 0; i < eff; i++) + { + printk ("[%x]", rx_buf[i]); + } + printk ("\n"); + + if (len <= 0) + break; + } + +out: + return ret; +} + +int +ifxmips_eeprom_open (struct inode *inode, struct file *filp) +{ + filp->f_pos = 0; + return 0; +} + +int +ifxmips_eeprom_close (struct inode *inode, struct file *filp) +{ + return 0; +} + +int +ifxmips_eeprom_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + return 0; +} + +ssize_t +ifxmips_eeprom_read (char *buf, size_t len, unsigned int addr) +{ + int ret = 0; + unsigned int data; + + printk("addr:=%d\n", addr); + printk("len:=%d\n", len); + + if ((addr + len) > EEPROM_SIZE) + { + printk("invalid len\n"); + addr = 0; + len = EEPROM_SIZE / 2; + } + + if ((ret = ifx_ssc_open((struct inode *) 0, NULL))) + { + printk("ifxmips_eeprom_open fails\n"); + goto out; + } + + data = (unsigned int)IFX_SSC_MODE_RXTX; + + if ((ret = ifx_ssc_ioctl((struct inode *) 0, NULL, IFX_SSC_RXTX_MODE_SET, (unsigned long) &data))) + { + printk("set RXTX mode fails\n"); + goto out; + } + + if ((ret = eeprom_wrsr())) + { + printk("EEPROM reset fails\n"); + goto out; + } + + if ((ret = eeprom_read(addr, buf, len))) + { + printk("eeprom read fails\n"); + goto out; + } + +out: + if (ifx_ssc_close((struct inode *) 0, NULL)) + printk("ifxmips_eeprom_close fails\n"); + + return len; +} +EXPORT_SYMBOL(ifxmips_eeprom_read); + +static ssize_t +ifxmips_eeprom_fops_read (struct file *filp, char *ubuf, size_t len, loff_t * off) +{ + int ret = 0; + unsigned char ssc_rx_buf[EEPROM_SIZE]; + long flag; + + if (*off >= EEPROM_SIZE) + return 0; + + if (*off + len > EEPROM_SIZE) + len = EEPROM_SIZE - *off; + + if (len == 0) + return 0; + + local_irq_save(flag); + + if ((ret = ifxmips_eeprom_read(ssc_rx_buf, len, *off)) < 0) + { + printk("read fails, err=%x\n", ret); + local_irq_restore(flag); + return ret; + } + + if (copy_to_user((void*)ubuf, ssc_rx_buf, ret) != 0) + { + local_irq_restore(flag); + ret = -EFAULT; + } + + local_irq_restore(flag); + *off += len; + + return len; +} + +ssize_t +ifxmips_eeprom_write (char *buf, size_t len, unsigned int addr) +{ + int ret = 0; + unsigned int data; + + if ((ret = ifx_ssc_open ((struct inode *) 0, NULL))) + { + printk ("ifxmips_eeprom_open fails\n"); + goto out; + } + + data = (unsigned int) IFX_SSC_MODE_RXTX; + + if ((ret = ifx_ssc_ioctl ((struct inode *) 0, NULL, IFX_SSC_RXTX_MODE_SET, (unsigned long) &data))) + { + printk ("set RXTX mode fails\n"); + goto out; + } + + if ((ret = eeprom_wrsr ())) { + printk ("EEPROM reset fails\n"); + goto out; + } + + if ((ret = eeprom_write (addr, buf, len))) { + printk ("eeprom write fails\n"); + goto out; + } + +out: + if (ifx_ssc_close ((struct inode *) 0, NULL)) + printk ("ifxmips_eeprom_close fails\n"); + + return ret; +} +EXPORT_SYMBOL(ifxmips_eeprom_write); + +static ssize_t +ifxmips_eeprom_fops_write (struct file *filp, const char *ubuf, size_t len, loff_t * off) +{ + int ret = 0; + unsigned char ssc_tx_buf[EEPROM_SIZE]; + + if (*off >= EEPROM_SIZE) + return 0; + + if (len + *off > EEPROM_SIZE) + len = EEPROM_SIZE - *off; + + if ((ret = copy_from_user (ssc_tx_buf, ubuf, len))) + return EFAULT; + + ret = ifxmips_eeprom_write (ssc_tx_buf, len, *off); + + if (ret > 0) + *off = ret; + + return ret; +} + +loff_t +ifxmips_eeprom_llseek (struct file * filp, loff_t off, int whence) +{ + loff_t newpos; + switch (whence) { + case SEEK_SET: + newpos = off; + break; + + case SEEK_CUR: + newpos = filp->f_pos + off; + break; + + default: + return -EINVAL; + } + + if (newpos < 0) + return -EINVAL; + + filp->f_pos = newpos; + + return newpos; +} + +static struct file_operations ifxmips_eeprom_fops = { + owner:THIS_MODULE, + llseek:ifxmips_eeprom_llseek, + read:ifxmips_eeprom_fops_read, + write:ifxmips_eeprom_fops_write, + ioctl:ifxmips_eeprom_ioctl, + open:ifxmips_eeprom_open, + release:ifxmips_eeprom_close, +}; + +int __init +ifxmips_eeprom_init (void) +{ + int ret = 0; + + ifxmips_eeprom_maj = register_chrdev(0, "eeprom", &ifxmips_eeprom_fops); + + if (ifxmips_eeprom_maj < 0) + { + printk("failed to register eeprom device\n"); + ret = -EINVAL; + + goto out; + } + + printk("ifxmips_eeprom : /dev/eeprom mayor %d\n", ifxmips_eeprom_maj); + +out: + return ret; +} + +void __exit +ifxmips_eeprom_cleanup_module (void) +{ + /*if (unregister_chrdev (ifxmips_eeprom_maj, "eeprom")) { + printk ("Unable to unregister major %d for the EEPROM\n", + maj); + }*/ +} + +module_exit (ifxmips_eeprom_cleanup_module); +module_init (ifxmips_eeprom_init); + +MODULE_LICENSE ("GPL"); +MODULE_AUTHOR ("Peng Liu"); +MODULE_DESCRIPTION ("IFAP EEPROM driver"); +MODULE_SUPPORTED_DEVICE ("ifxmips_eeprom"); + + diff --git a/target/linux/ifxmips/files/drivers/char/ifxmips_mei_core.c b/target/linux/ifxmips/files/drivers/char/ifxmips_mei_core.c new file mode 100644 index 0000000000..e8787c5710 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/char/ifxmips_mei_core.c @@ -0,0 +1,3658 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_core.c +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment + 1.00.01 TC Chen Fixed cell rate calculation issue + Fixed pvovider_id of adsl mib swapping issue + 1.00.02 TC Chen Added L3 Low Poewr Mode support. + 1.00.03 TC Chen Fixed Clear Eoc transmit issue. + 1.00.04 31/08/2006 TC Chen Add ADSL Link/Data Led + Add Dual Latency Path + Add AUTOBOOT_ENABLE_SET ioctl for autoboot + mode enable/disable + Fix fast path cell rate calculation + 1.00.05 25/09/2006 TC Chen Fix ATM QoS fail on interface 0(fast path). + 1.00.06 02/10/2006 TC Chen Change ifxmips_ppe_set_cell_rate to + ifx_atm_set_cell_rate + Add ATM Led callback function + 1.00.07 13/11/2006 TC Chen Invert ADSL Link LED Signal + 1.00.08 08/12/2006 TC Chen Fix loop diagnostic warning message issue + 1.00.09 20/12/2006 TC Chen Workaround for USB OC interrupt which is trigegred once DSL reset +******************************************************************************/ + +/* + * =========================================================================== + * INCLUDE FILES + * =========================================================================== + */ + +#include + +char IFXMIPS_MEI_VERSION[] = "1.00.09"; + +#define IFXMIPS_MEI_CMV_EXTRA //WINHOST debug +#define IFX_ADSL_L3_MODE_SUPPORT //L3 Low Power Mode Support +#define IFX_ADSL_DUAL_LATENCY_SUPPORT +#undef IFXMIPS_CLEAR_EOC //clear eoc support + +// for ARC memory access +#define WHILE_DELAY 20000 +#if defined(IFXMIPS_PORT_RTEMS) +#undef IFXMIPS_DMA_DEBUG_MUTEX +#else +#define IFXMIPS_DMA_DEBUG_MUTEX +#endif + +#define IMAGE_SWAP +#define BOOT_SWAP +#define HEADER_SWAP + +//TODO +#undef DFE_LOOPBACK // testing code //undefined by Henry , start to real link test. + //165203:henryhsu + +#ifdef DFE_LOOPBACK +//#define DFE_MEM_TEST +//#define DFE_PING_TEST +#define DFE_ATM_LOOPBACK +#endif + +#undef DATA_LED_ON_MODE +#define DATA_LED_SUPPORT // support adsl data led +//#define DATA_LED_ADSL_FW_HANDLE // adsl data led handle by firmware +#define CONFIG_IFXMIPS_MEI_LED // adsl led support + +// Block size per BAR +#define SDRAM_SEGMENT_SIZE (64*1024) +// Number of Bar registers +#define MAX_BAR_REGISTERS (17) + +#define XDATA_REGISTER (15) + +#define IFXMIPS_MEI_DEVNAME "mei" + +#ifdef DFE_LOOPBACK +#ifndef UINT32 +#define UINT32 unsigned long +#endif +#ifdef DFE_PING_TEST +#include "dsp_xmem_arb_rand_em.h" +#endif +#ifdef DFE_MEM_TEST +#include "aai_mem_test.h" +#endif +#ifdef DFE_ATM_LOOPBACK +#include "aai_lpbk_dyn_rate.h" +#endif +#endif + +/************************************************************************ + * Function declaration + ************************************************************************/ +static MEI_ERROR meiDMAWrite (u32 destaddr, u32 * databuff, u32 databuffsize); +static MEI_ERROR meiDMARead (u32 srcaddr, u32 * databuff, u32 databuffsize); +static void meiControlModeSwitch (int mode); +static void meiPollForDbgDone (void); +static MEI_ERROR _meiDebugLongWordRead (u32 DEC_mode, u32 address, + u32 * data); +static MEI_ERROR _meiDebugLongWordWrite (u32 DEC_mode, u32 address, u32 data); +MEI_ERROR meiDebugWrite (u32 destaddr, u32 * databuff, u32 databuffsize); +static MEI_ERROR meiDebugRead (u32 srcaddr, u32 * databuff, u32 databuffsize); +static MEI_ERROR meiMailboxWrite (u16 * msgsrcbuffer, u16 msgsize); +static MEI_ERROR meiDownloadBootCode (void); +static MEI_ERROR meiHaltArc (void); +static MEI_ERROR meiRunArc (void); +static MEI_ERROR meiRunAdslModem (void); +static int meiGetPage (u32 Page, u32 data, u32 MaxSize, u32 * Buffer, + u32 * Dest); +void makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, + u16 * data, u16 * CMVMSG); +MEI_ERROR meiCMV (u16 * request, int reply, u16 * response); +static void meiMailboxInterruptsDisable (void); +static void meiMailboxInterruptsEnable (void); +static int update_bar_register (int nTotalBar); +static int free_image_buffer (int type); +static int alloc_processor_memory (unsigned long size, + smmu_mem_info_t * adsl_mem_info); +ssize_t mei_write (MEI_file_t * filp, char *buf, size_t size, loff_t * loff); +int mei_ioctl (MEI_inode_t * ino, MEI_file_t * fil, unsigned int command, + unsigned long lon); + +#ifdef CONFIG_PROC_FS +static int proc_read (struct file *file, char *buf, size_t nbytes, + loff_t * ppos); +static ssize_t proc_write (struct file *file, const char *buffer, + size_t count, loff_t * ppos); +#endif + +#ifdef CONFIG_IFXMIPS_MEI_MIB +int mei_mib_ioctl (MEI_inode_t * ino, MEI_file_t * fil, unsigned int command, + unsigned long lon); +int mei_mib_adsl_link_up (void); +int mei_mib_adsl_link_down (void); +int ifxmips_mei_mib_init (void); +int ifxmips_mei_mib_cleanup (void); +#endif +#if defined(CONFIG_IFXMIPS_MEI_LED) && defined(DATA_LED_SUPPORT) +static int ifxmips_mei_led_init (void); +static int ifxmips_mei_led_cleanup (void); +static int adsl_led_flash_task (void); +#endif +// for clearEoC +#ifdef IFXMIPS_CLEAR_EOC +extern void ifx_push_eoc (struct sk_buff *pkt); +#endif + +/************************************************************************ + * variable declaration + ************************************************************************/ +static smmu_mem_info_t adsl_mem_info[MAX_BAR_REGISTERS]; +static unsigned long image_size = 0; +static struct timeval time_disconnect, time_showtime; +static u16 unavailable_seconds = 0; +#ifdef IFXMIPS_CLEAR_EOC +static wait_queue_head_t wait_queue_hdlc_poll; ///clear eoc +#endif + +static int showtime_lock_flag = 0; +static int quiet_mode_flag = 0; + +int showtime = 0; +static int major = IFXMIPS_MEI_MAJOR; +MEI_mutex_t mei_sema; + +// Mei to ARC CMV count, reply count, ARC Indicator count +static int indicator_count = 0; +static int cmv_count = 0; +static int reply_count = 0; +static u16 Recent_indicator[MSG_LENGTH]; +static int reset_arc_flag = 0; + +// Used in interrupt handler as flags +static int arcmsgav = 0; +static int cmv_reply = 0; +static int cmv_waiting = 0; +static int modem_ready = 0; +// to wait for arc cmv reply, sleep on wait_queue_arcmsgav; +static wait_queue_head_t wait_queue_arcmsgav; + +// CMV mailbox messages +// ARC to MEI message +static u16 CMV_RxMsg[MSG_LENGTH] __attribute__ ((aligned (4))); +// MEI to ARC message +static u16 CMV_TxMsg[MSG_LENGTH] __attribute__ ((aligned (4))); + +static u32 *mei_arc_swap_buff = NULL; // holding swap pages +static ARC_IMG_HDR *img_hdr; +static int arc_halt_flag = 0; +static int nBar = 0; // total bars to be used. + +static u32 loop_diagnostics_mode = 0; +wait_queue_head_t wait_queue_loop_diagnostic; +int loop_diagnostics_completed = 0; +u32 adsl_mode, adsl_mode_extend; // adsl mode : adsl/ 2/ 2+ +static int autoboot_enable_flag = 0; + +#ifdef IFX_ADSL_DUAL_LATENCY_SUPPORT +static u8 bDualLatency = 0; +#endif + +#ifdef IFXMIPS_CLEAR_EOC +static u16 ceoc_read_idx = 0; +#endif + +#ifdef IFX_ADSL_L3_MODE_SUPPORT +static wait_queue_head_t wait_queue_l3; // l3 power mode +static int l3_shutdown = 0; +int get_l3_power_status (void); +#endif + +#if defined(CONFIG_IFXMIPS_MEI_LED) && defined(DATA_LED_SUPPORT) +int led_status_on = 0, led_need_to_flash = 0; +static int stop_led_module = 0; //wakeup and clean led module +static wait_queue_head_t wait_queue_led_polling; // adsl led +#endif + +static struct file_operations mei_operations = { + write : mei_write, + ioctl : mei_ioctl, +}; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *meidir; +static struct file_operations proc_operations = { + read:proc_read, + write:proc_write, +}; +static reg_entry_t regs[PROC_ITEMS]; //total items to be monitored by /proc/mei +#define NUM_OF_REG_ENTRY (sizeof(regs)/sizeof(reg_entry_t)) +#endif //#ifdef CONFIG_PROC_FS + +#ifdef DFE_LOOPBACK +unsigned char got_int = 0; +#endif + +///////////////// mei access Rd/Wr methods /////////////// +/** + * Write a value to register + * This function writes a value to ifxmips register + * + * \param ul_address The address to write + * \param ul_data The value to write + * \ingroup Internal + */ +static void +meiLongwordWrite (u32* ul_address, u32 ul_data) +{ + ifxmips_w32(ul_data, ul_address); + wmb(); + return; +} // end of "meiLongwordWrite(..." + +/** + * Read the ifxmips register + * This function read the value from ifxmips register + * + * \param ul_address The address to write + * \param pul_data Pointer to the data + * \ingroup Internal + */ +static void +meiLongwordRead (u32* ul_address, u32 * pul_data) +{ + //*pul_data = *((volatile u32 *)ul_address); + *pul_data = ifxmips_r32(ul_address); + wmb(); + return; +} // end of "meiLongwordRead(..." + +/** + * Write several DWORD datas to ARC memory via ARC DMA interface + * This function writes several DWORD datas to ARC memory via DMA interface. + * + * \param destaddr The address to write + * \param databuff Pointer to the data buffer + * \param databuffsize Number of DWORDs to write + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiDMAWrite (u32 destaddr, u32 * databuff, u32 databuffsize) +{ + u32 *p = databuff; + u32 temp; + MEI_intstat_t flags; + + if (destaddr & 3) + return MEI_FAILURE; + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_LOCKINT (flags); +#endif + + //printk("destaddr=%X,size=%d\n",destaddr,databuffsize); + // Set the write transfer address + meiLongwordWrite (MEI_XFR_ADDR, destaddr); + + // Write the data pushed across DMA + while (databuffsize--) { + temp = *p; + if (databuff == (u32 *) CMV_TxMsg) + MEI_HALF_WORD_SWAP (temp); + meiLongwordWrite (MEI_DATA_XFR, temp); + p++; + } // end of "while(..." + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_UNLOCKINT (flags); +#endif + + return MEI_SUCCESS; + +} // end of "meiDMAWrite(..." + +/** + * Read several DWORD datas from ARC memory via ARC DMA interface + * This function reads several DWORD datas from ARC memory via DMA interface. + * + * \param srcaddr The address to read + * \param databuff Pointer to the data buffer + * \param databuffsize Number of DWORDs to read + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiDMARead (u32 srcaddr, u32 * databuff, u32 databuffsize) +{ + u32 *p = databuff; + u32 temp; +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_intstat_t flags; +#endif + //printk("destaddr=%X,size=%X\n",srcaddr,databuffsize); + if (srcaddr & 3) + return MEI_FAILURE; + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_LOCKINT (flags); +#endif + + // Set the read transfer address + meiLongwordWrite (MEI_XFR_ADDR, srcaddr); + + // Read the data popped across DMA + while (databuffsize--) { + meiLongwordRead (MEI_DATA_XFR, &temp); + if (databuff == (u32 *) CMV_RxMsg) // swap half word + MEI_HALF_WORD_SWAP (temp); + *p = temp; + p++; + } // end of "while(..." + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_UNLOCKINT (flags); +#endif + + return MEI_SUCCESS; + +} // end of "meiDMARead(..." + +/** + * Switch the ARC control mode + * This function switchs the ARC control mode to JTAG mode or MEI mode + * + * \param mode The mode want to switch: JTAG_MASTER_MODE or MEI_MASTER_MODE. + * \ingroup Internal + */ +static void +meiControlModeSwitch (int mode) +{ + u32 temp = 0x0; + meiLongwordRead ( MEI_DBG_MASTER, &temp); + switch (mode) { + case JTAG_MASTER_MODE: + temp &= ~(HOST_MSTR); + break; + case MEI_MASTER_MODE: + temp |= (HOST_MSTR); + break; + default: + printk ("meiControlModeSwitch: unkonwn mode [%d]\n", + mode); + return; + } + meiLongwordWrite (MEI_DBG_MASTER, temp); +} + +/** + * Poll for transaction complete signal + * This function polls and waits for transaction complete signal. + * + * \ingroup Internal + */ +static void +meiPollForDbgDone (void) +{ + u32 query = 0; + int i = 0; + while (i < WHILE_DELAY) { + meiLongwordRead (ARC_TO_MEI_INT, &query); + query &= (ARC_TO_MEI_DBG_DONE); + if (query) + break; + i++; + if (i == WHILE_DELAY) { + printk ("\n\n PollforDbg fail"); + } + } + meiLongwordWrite ( ARC_TO_MEI_INT, ARC_TO_MEI_DBG_DONE); // to clear this interrupt +} // end of "meiPollForDbgDone(..." + +/** + * ARC Debug Memory Access for a single DWORD reading. + * This function used for direct, address-based access to ARC memory. + * + * \param DEC_mode ARC memory space to used + * \param address Address to read + * \param data Pointer to data + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +_meiDebugLongWordRead (u32 DEC_mode, u32 address, u32 * data) +{ + meiLongwordWrite ( MEI_DEBUG_DEC, DEC_mode); + meiLongwordWrite ( MEI_DEBUG_RAD, address); + meiPollForDbgDone (); + meiLongwordRead (MEI_DEBUG_DATA, data); + return MEI_SUCCESS; +} + +/** + * ARC Debug Memory Access for a single DWORD writing. + * This function used for direct, address-based access to ARC memory. + * + * \param DEC_mode ARC memory space to used + * \param address The address to write + * \param data The data to write + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +_meiDebugLongWordWrite (u32 DEC_mode, u32 address, u32 data) +{ + meiLongwordWrite (MEI_DEBUG_DEC, DEC_mode); + meiLongwordWrite (MEI_DEBUG_WAD, address); + meiLongwordWrite (MEI_DEBUG_DATA, data); + meiPollForDbgDone (); + return MEI_SUCCESS; +} + +/** + * ARC Debug Memory Access for writing. + * This function used for direct, address-based access to ARC memory. + * + * \param destaddr The address to ead + * \param databuffer Pointer to data + * \param databuffsize The number of DWORDs to read + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ + +MEI_ERROR +meiDebugWrite (u32 destaddr, u32 * databuff, u32 databuffsize) +{ + u32 i; + u32 temp = 0x0; + u32 address = 0x0; + u32 *buffer = 0x0; +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_intstat_t flags; +#endif + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_LOCKINT (flags); +#endif + + // Open the debug port before DMP memory write + meiControlModeSwitch (MEI_MASTER_MODE); + + meiLongwordWrite (MEI_DEBUG_DEC, MEI_DEBUG_DEC_DMP1_MASK); + + // For the requested length, write the address and write the data + address = destaddr; + buffer = databuff; + for (i = 0; i < databuffsize; i++) { + temp = *buffer; + _meiDebugLongWordWrite (MEI_DEBUG_DEC_DMP1_MASK, address, + temp); + address += 4; + buffer++; + } // end of "for(..." + + // Close the debug port after DMP memory write + meiControlModeSwitch (JTAG_MASTER_MODE); + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_UNLOCKINT (flags); +#endif + + // Return + return MEI_SUCCESS; + +} // end of "meiDebugWrite(..." + +/** + * ARC Debug Memory Access for reading. + * This function used for direct, address-based access to ARC memory. + * + * \param srcaddr The address to read + * \param databuffer Pointer to data + * \param databuffsize The number of DWORDs to read + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiDebugRead (u32 srcaddr, u32 * databuff, u32 databuffsize) +{ + u32 i; + u32 temp = 0x0; + u32 address = 0x0; + u32 *buffer = 0x0; +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_intstat_t flags; +#endif + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_LOCKINT (flags); +#endif + + // Open the debug port before DMP memory read + meiControlModeSwitch (MEI_MASTER_MODE); + + meiLongwordWrite (MEI_DEBUG_DEC, MEI_DEBUG_DEC_DMP1_MASK); + + // For the requested length, write the address and read the data + address = srcaddr; + buffer = databuff; + for (i = 0; i < databuffsize; i++) { + _meiDebugLongWordRead (MEI_DEBUG_DEC_DMP1_MASK, address, + &temp); + *buffer = temp; + address += 4; + buffer++; + } // end of "for(..." + + // Close the debug port after DMP memory read + meiControlModeSwitch (JTAG_MASTER_MODE); + +#ifdef IFXMIPS_DMA_DEBUG_MUTEX + MEI_UNLOCKINT (flags); +#endif + + // Return + return MEI_SUCCESS; + +} // end of "meiDebugRead(..." + +/** + * Send a message to ARC MailBox. + * This function sends a message to ARC Mailbox via ARC DMA interface. + * + * \param msgsrcbuffer Pointer to message. + * \param msgsize The number of words to write. + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiMailboxWrite (u16 * msgsrcbuffer, u16 msgsize) +{ + int i; + u32 arc_mailbox_status = 0x0; + u32 temp = 0; + MEI_ERROR meiMailboxError = MEI_SUCCESS; + + // Write to mailbox + meiMailboxError = + meiDMAWrite (MEI_TO_ARC_MAILBOX, (u32 *) msgsrcbuffer, + msgsize / 2); + meiMailboxError = + meiDMAWrite (MEI_TO_ARC_MAILBOXR, (u32 *) (&temp), 1); + + // Notify arc that mailbox write completed + cmv_waiting = 1; + meiLongwordWrite (MEI_TO_ARC_INT, MEI_TO_ARC_MSGAV); + + i = 0; + while (i < WHILE_DELAY) { // wait for ARC to clear the bit + meiLongwordRead ( MEI_TO_ARC_INT, &arc_mailbox_status); + if ((arc_mailbox_status & MEI_TO_ARC_MSGAV) != + MEI_TO_ARC_MSGAV) + break; + i++; + if (i == WHILE_DELAY) { + printk + ("\n\n MEI_TO_ARC_MSGAV not cleared by ARC"); + meiMailboxError = MEI_FAILURE; + } + } + + // Return + return meiMailboxError; + +} // end of "meiMailboxWrite(..." + +/** + * Read a message from ARC MailBox. + * This function reads a message from ARC Mailbox via ARC DMA interface. + * + * \param msgsrcbuffer Pointer to message. + * \param msgsize The number of words to read + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiMailboxRead (u16 * msgdestbuffer, u16 msgsize) +{ + MEI_ERROR meiMailboxError = MEI_SUCCESS; + // Read from mailbox + meiMailboxError = + meiDMARead (ARC_TO_MEI_MAILBOX, (u32 *) msgdestbuffer, + msgsize / 2); + + // Notify arc that mailbox read completed + meiLongwordWrite (ARC_TO_MEI_INT, ARC_TO_MEI_MSGAV); + + // Return + return meiMailboxError; + +} // end of "meiMailboxRead(..." + +/** + * Download boot pages to ARC. + * This function downloads boot pages to ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiDownloadBootPages (void) +{ + int boot_loop; + int page_size; + u32 dest_addr; + + /* + ** DMA the boot code page(s) + */ +#ifndef HEADER_SWAP + for (boot_loop = 1; boot_loop < le32_to_cpu (img_hdr->count); + boot_loop++) +#else + for (boot_loop = 1; boot_loop < (img_hdr->count); boot_loop++) +#endif + { +#ifndef HEADER_SWAP + if (le32_to_cpu (img_hdr->page[boot_loop].p_size) & BOOT_FLAG) +#else + if ((img_hdr->page[boot_loop].p_size) & BOOT_FLAG) +#endif + { + page_size = + meiGetPage (boot_loop, GET_PROG, MAXSWAPSIZE, + mei_arc_swap_buff, &dest_addr); + if (page_size > 0) { + meiDMAWrite (dest_addr, mei_arc_swap_buff, + page_size); + } + } +#ifndef HEADER_SWAP + if (le32_to_cpu (img_hdr->page[boot_loop].d_size) & BOOT_FLAG) +#else + if ((img_hdr->page[boot_loop].d_size) & BOOT_FLAG) +#endif + { + page_size = + meiGetPage (boot_loop, GET_DATA, MAXSWAPSIZE, + mei_arc_swap_buff, &dest_addr); + if (page_size > 0) { + meiDMAWrite (dest_addr, mei_arc_swap_buff, + page_size); + } + } + } + return MEI_SUCCESS; +} + +/** + * Initial efuse rar. + **/ +static void +mei_fuse_rar_init (void) +{ + u32 data = 0; + meiDMAWrite (IRAM0_BASE, &data, 1); + meiDMAWrite (IRAM0_BASE + 4, &data, 1); + meiDMAWrite (IRAM1_BASE, &data, 1); + meiDMAWrite (IRAM1_BASE + 4, &data, 1); + meiDMAWrite (BRAM_BASE, &data, 1); + meiDMAWrite (BRAM_BASE + 4, &data, 1); + meiDMAWrite (ADSL_DILV_BASE, &data, 1); + meiDMAWrite (ADSL_DILV_BASE + 4, &data, 1); +} + +/** + * efuse rar program + **/ +static void +mei_fuse_prg (void) +{ + u32 reg_data, fuse_value; + int i = 0; + meiLongwordRead ( IFXMIPS_RCU_RST, ®_data); + while ((reg_data & 0x10000000) == 0) { + meiLongwordRead ( IFXMIPS_RCU_RST, ®_data); + //add a watchdog + i++; + /* 0x4000 translate to about 16 ms@111M, so should be enough */ + if (i == 0x4000) + return; + } + // STEP a: Prepare memory for external accesses + // Write fuse_en bit24 + meiLongwordRead (IFXMIPS_RCU_RST, ®_data); + meiLongwordWrite (IFXMIPS_RCU_RST, reg_data | (1 << 24)); + + mei_fuse_rar_init (); + for (i = 0; i < 4; i++) { + meiLongwordRead((u32*)(IFXMIPS_FUSE_BASE_ADDR + (i * 4)), &fuse_value); + switch (fuse_value & 0xF0000) { + case 0x80000: + reg_data = + ((fuse_value & RX_DILV_ADDR_BIT_MASK) | + (RX_DILV_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (ADSL_DILV_BASE, ®_data, 1); + break; + case 0x90000: + reg_data = + ((fuse_value & RX_DILV_ADDR_BIT_MASK) | + (RX_DILV_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (ADSL_DILV_BASE + 4, ®_data, 1); + break; + case 0xA0000: + reg_data = + ((fuse_value & IRAM0_ADDR_BIT_MASK) | + (IRAM0_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (IRAM0_BASE, ®_data, 1); + break; + case 0xB0000: + reg_data = + ((fuse_value & IRAM0_ADDR_BIT_MASK) | + (IRAM0_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (IRAM0_BASE + 4, ®_data, 1); + break; + case 0xC0000: + reg_data = + ((fuse_value & IRAM1_ADDR_BIT_MASK) | + (IRAM1_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (IRAM1_BASE, ®_data, 1); + break; + case 0xD0000: + reg_data = + ((fuse_value & IRAM1_ADDR_BIT_MASK) | + (IRAM1_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (IRAM1_BASE + 4, ®_data, 1); + break; + case 0xE0000: + reg_data = + ((fuse_value & BRAM_ADDR_BIT_MASK) | + (BRAM_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (BRAM_BASE, ®_data, 1); + break; + case 0xF0000: + reg_data = + ((fuse_value & BRAM_ADDR_BIT_MASK) | + (BRAM_ADDR_BIT_MASK + 0x1)); + meiDMAWrite (BRAM_BASE + 4, ®_data, 1); + break; + default: // PPE efuse + break; + } + } + meiLongwordRead (IFXMIPS_RCU_RST, ®_data); + meiLongwordWrite (IFXMIPS_RCU_RST, reg_data & 0xF7FFFFFF); +} + +/** + * Download boot code to ARC. + * This function downloads boot code to ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiDownloadBootCode (void) +{ + u32 arc_debug_data = ACL_CLK_MODE_ENABLE; //0x10 + + meiMailboxInterruptsDisable (); + + // Switch arc control from JTAG mode to MEI mode + meiControlModeSwitch (MEI_MASTER_MODE); + //enable ac_clk signal + _meiDebugLongWordRead (MEI_DEBUG_DEC_DMP1_MASK, CRI_CCR0, + &arc_debug_data); + arc_debug_data |= ACL_CLK_MODE_ENABLE; + _meiDebugLongWordWrite (MEI_DEBUG_DEC_DMP1_MASK, CRI_CCR0, + arc_debug_data); + //Switch arc control from MEI mode to JTAG mode + meiControlModeSwitch (JTAG_MASTER_MODE); + + mei_fuse_prg (); //program fuse rar + + meiDownloadBootPages (); + + return MEI_SUCCESS; + +} // end of "meiDownloadBootCode(..." + +//#endif + +/** + * Halt the ARC. + * This function halts the ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiHaltArc (void) +{ + u32 arc_debug_data = 0x0; + + // Switch arc control from JTAG mode to MEI mode + meiControlModeSwitch (MEI_MASTER_MODE); + _meiDebugLongWordRead (MEI_DEBUG_DEC_AUX_MASK, ARC_DEBUG, + &arc_debug_data); + arc_debug_data |= (BIT1); + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, ARC_DEBUG, + arc_debug_data); + // Switch arc control from MEI mode to JTAG mode + meiControlModeSwitch (JTAG_MASTER_MODE); + arc_halt_flag = 1; + + MEI_WAIT (10); + // Return + return MEI_SUCCESS; + +} // end of "meiHalt(..." + +/** + * Run the ARC. + * This function runs the ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiRunArc (void) +{ + u32 arc_debug_data = 0x0; + + // Switch arc control from JTAG mode to MEI mode- write '1' to bit0 + meiControlModeSwitch (MEI_MASTER_MODE); + _meiDebugLongWordRead (MEI_DEBUG_DEC_AUX_MASK, AUX_STATUS, + &arc_debug_data); + + // Write debug data reg with content ANDd with 0xFDFFFFFF (halt bit cleared) + arc_debug_data &= ~(BIT25); + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, AUX_STATUS, + arc_debug_data); + + // Switch arc control from MEI mode to JTAG mode- write '0' to bit0 + meiControlModeSwitch (JTAG_MASTER_MODE); + // Enable mask for arc codeswap interrupts + meiMailboxInterruptsEnable (); + arc_halt_flag = 0; + + // Return + return MEI_SUCCESS; + +} // end of "meiActivate(..." + +/** + * Reset the ARC. + * This function resets the ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiResetARC (void) +{ + + u32 arc_debug_data = 0; + showtime = 0; + + meiHaltArc (); + + meiLongwordRead (IFXMIPS_RCU_RST, &arc_debug_data); + meiLongwordWrite (IFXMIPS_RCU_RST, + arc_debug_data | IFXMIPS_RCU_RST_REQ_DFE | + IFXMIPS_RCU_RST_REQ_AFE); + meiLongwordWrite (IFXMIPS_RCU_RST, arc_debug_data); + // reset ARC + meiLongwordWrite(MEI_RST_CONTROL, MEI_SOFT_RESET); + meiLongwordWrite(MEI_RST_CONTROL, 0); + + meiMailboxInterruptsDisable (); + MEI_MUTEX_INIT (mei_sema, 1); + reset_arc_flag = 1; + modem_ready = 0; + return MEI_SUCCESS; +} + +/** + * Reset the ARC, download boot codes, and run the ARC. + * This function resets the ARC, downloads boot codes to ARC, and runs the ARC. + * + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +static MEI_ERROR +meiRunAdslModem (void) +{ + int nSize = 0, idx = 0; + + img_hdr = (ARC_IMG_HDR *) adsl_mem_info[0].address; +#if defined(HEADER_SWAP) + if ((img_hdr->count) * sizeof (ARC_SWP_PAGE_HDR) > SDRAM_SEGMENT_SIZE) +#else //define(HEADER_SWAP) + if (le32_to_cpu (img_hdr->count) * sizeof (ARC_SWP_PAGE_HDR) > + SDRAM_SEGMENT_SIZE) +#endif //define(HEADER_SWAP) + { + printk + ("segment_size is smaller than firmware header size\n"); + return -1; + } + // check image size + for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) { + nSize += adsl_mem_info[idx].nCopy; + } + if (nSize != image_size) { + printk + ("Firmware download is not completed. \nPlease download firmware again!\n"); + return -1; + } + // TODO: check crc + /// + if (reset_arc_flag == 0) { + u32 arc_debug_data; + + meiResetARC (); + meiControlModeSwitch (MEI_MASTER_MODE); + //enable ac_clk signal + _meiDebugLongWordRead (MEI_DEBUG_DEC_DMP1_MASK, CRI_CCR0, + &arc_debug_data); + arc_debug_data |= ACL_CLK_MODE_ENABLE; + _meiDebugLongWordWrite (MEI_DEBUG_DEC_DMP1_MASK, CRI_CCR0, + arc_debug_data); + meiControlModeSwitch (JTAG_MASTER_MODE); + meiHaltArc (); + update_bar_register (nBar); + } + reset_arc_flag = 0; + if (arc_halt_flag == 0) { + meiHaltArc (); + } + printk ("Starting to meiDownloadBootCode\n"); + + meiDownloadBootCode(); + + // 1.00.09 20/12/2006 TC Chen + // disable USB OC interrupt, reset DSL chip will triger OC interrupt + disable_irq(IFXMIPS_USB_OC_INT); + + meiRunArc (); + + MEI_WAIT (100); //wait 100ms + + //1.00.09 20/12/2006 TC Chen + // restore USB OC interrupt + MEI_MASK_AND_ACK_IRQ(IFXMIPS_USB_OC_INT); + enable_irq(IFXMIPS_USB_OC_INT); + + if (modem_ready != 1) { + printk ("Running ADSL modem firmware fail!\n"); + return MEI_FAILURE; + } + + + return MEI_SUCCESS; +} + +/** + * Get the page's data pointer + * This function caculats the data address from the firmware header. + * + * \param Page The page number. + * \param data Data page or program page. + * \param MaxSize The maximum size to read. + * \param Buffer Pointer to data. + * \param Dest Pointer to the destination address. + * \return The number of bytes to read. + * \ingroup Internal + */ +static int +meiGetPage (u32 Page, u32 data, u32 MaxSize, u32 * Buffer, u32 * Dest) +{ + u32 size; + u32 i; + u32 *p; + u32 idx, offset, nBar = 0; + + if (Page > img_hdr->count) + return -2; + /* + ** Get program or data size, depending on "data" flag + */ +#ifndef HEADER_SWAP + size = (data == + GET_DATA) ? le32_to_cpu (img_hdr->page[Page]. + d_size) : le32_to_cpu (img_hdr-> + page[Page]. + p_size); +#else + size = (data == + GET_DATA) ? (img_hdr->page[Page].d_size) : (img_hdr-> + page[Page]. + p_size); +#endif + size &= BOOT_FLAG_MASK; // Clear boot bit! + if (size > MaxSize) + return -1; + + if (size == 0) + return 0; + /* + ** Get program or data offset, depending on "data" flag + */ +#ifndef HEADER_SWAP + i = data ? le32_to_cpu (img_hdr->page[Page]. + d_offset) : le32_to_cpu (img_hdr->page[Page]. + p_offset); +#else + i = data ? (img_hdr->page[Page].d_offset) : (img_hdr->page[Page]. + p_offset); +#endif + + /* + ** Copy data/program to buffer + */ + + idx = i / SDRAM_SEGMENT_SIZE; + offset = i % SDRAM_SEGMENT_SIZE; + p = (u32 *) ((u8 *) adsl_mem_info[idx].address + offset); + + for (i = 0; i < size; i++) { + if (offset + i * 4 - (nBar * SDRAM_SEGMENT_SIZE) >= + SDRAM_SEGMENT_SIZE) { + idx++; + nBar++; + p = (u32 *) ((u8 *) + KSEG1ADDR ((u32) adsl_mem_info[idx]. + address)); + } + Buffer[i] = *p++; +#ifdef BOOT_SWAP +#ifndef IMAGE_SWAP + Buffer[i] = le32_to_cpu (Buffer[i]); +#endif +#endif + } + + /* + ** Pass back data/program destination address + */ +#ifndef HEADER_SWAP + *Dest = data ? le32_to_cpu (img_hdr->page[Page]. + d_dest) : le32_to_cpu (img_hdr-> + page[Page].p_dest); +#else + *Dest = data ? (img_hdr->page[Page].d_dest) : (img_hdr->page[Page]. + p_dest); +#endif + + return size; +} + +////////////////makeCMV(Opcode, Group, Address, Index, Size, Data), CMV in u16 TxMessage[MSG_LENGTH]/////////////////////////// + +/** + * Compose a message. + * This function compose a message from opcode, group, address, index, size, and data + * + * \param opcode The message opcode + * \param group The message group number + * \param address The message address. + * \param index The message index. + * \param size The number of words to read/write. + * \param data The pointer to data. + * \param CMVMSG The pointer to message buffer. + * \ingroup Internal + */ +void +makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, + u16 * CMVMSG) +{ + memset (CMVMSG, 0, MSG_LENGTH * 2); + CMVMSG[0] = (opcode << 4) + (size & 0xf); + CMVMSG[1] = (((index == 0) ? 0 : 1) << 7) + (group & 0x7f); + CMVMSG[2] = address; + CMVMSG[3] = index; + if (opcode == H2D_CMV_WRITE) + memcpy (CMVMSG + 4, data, size * 2); + return; +} + +/** + * Send a message to ARC and read the response + * This function sends a message to arc, waits the response, and reads the responses. + * + * \param request Pointer to the request + * \param reply Wait reply or not. + * \param response Pointer to the response + * \return MEI_SUCCESS or MEI_FAILURE + * \ingroup Internal + */ +MEI_ERROR +meiCMV (u16 * request, int reply, u16 * response) // write cmv to arc, if reply needed, wait for reply +{ + MEI_ERROR meierror; +#if defined(IFXMIPS_PORT_RTEMS) + int delay_counter = 0; +#endif + + cmv_reply = reply; + memcpy (CMV_TxMsg, request, MSG_LENGTH * 2); + arcmsgav = 0; + + meierror = meiMailboxWrite (CMV_TxMsg, MSG_LENGTH); + + if (meierror != MEI_SUCCESS) { + cmv_waiting = 0; + arcmsgav = 0; + printk ("\n\n MailboxWrite Fail."); + return meierror; + } + else { + cmv_count++; + } + + if (cmv_reply == NO_REPLY) + return MEI_SUCCESS; + +#if !defined(IFXMIPS_PORT_RTEMS) + if (arcmsgav == 0) + MEI_WAIT_EVENT_TIMEOUT (wait_queue_arcmsgav, CMV_TIMEOUT); +#else + while (arcmsgav == 0 && delay_counter < CMV_TIMEOUT / 5) { + MEI_WAIT (5); + delay_counter++; + } +#endif + + cmv_waiting = 0; + if (arcmsgav == 0) { //CMV_timeout + arcmsgav = 0; + printk ("\nmeiCMV: MEI_MAILBOX_TIMEOUT\n"); + return MEI_MAILBOX_TIMEOUT; + } + else { + arcmsgav = 0; + reply_count++; + memcpy (response, CMV_RxMsg, MSG_LENGTH * 2); + return MEI_SUCCESS; + } + return MEI_SUCCESS; +} + +///////////////////// Interrupt handler ///////////////////////// +/** + * Disable ARC to MEI interrupt + * + * \ingroup Internal + */ +static void +meiMailboxInterruptsDisable (void) +{ + meiLongwordWrite (ARC_TO_MEI_INT_MASK, 0x0); +} // end of "meiMailboxInterruptsDisable(..." + +/** + * Eable ARC to MEI interrupt + * + * \ingroup Internal + */ +static void +meiMailboxInterruptsEnable (void) +{ + meiLongwordWrite (ARC_TO_MEI_INT_MASK, MSGAV_EN); +} // end of "meiMailboxInterruptsEnable(..." + +/** + * MEI interrupt handler + * + * \param int1 + * \param void0 + * \param regs Pointer to the structure of ifxmips mips registers + * \ingroup Internal + */ +irqreturn_t +mei_interrupt_arcmsgav (int int1, void *void0) +{ + u32 scratch; + +#if defined(DFE_LOOPBACK) && defined(DFE_PING_TEST) + dfe_loopback_irq_handler (); + goto out; +#endif //DFE_LOOPBACK + + meiDebugRead (ARC_MEI_MAILBOXR, &scratch, 1); + if (scratch & OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK) { + printk("\n\n Receive Code Swap Request interrupt!!!"); + goto out; + } + else if (scratch & OMB_CLEAREOC_INTERRUPT_CODE) // clear eoc message interrupt + { + meiLongwordWrite (ARC_TO_MEI_INT, ARC_TO_MEI_MSGAV); +#if defined (IFXMIPS_CLEAR_EOC) + MEI_WAKEUP_EVENT (wait_queue_hdlc_poll); +#endif + MEI_MASK_AND_ACK_IRQ (IFXMIPS_MEI_INT); + goto out; + } + else { // normal message + meiMailboxRead (CMV_RxMsg, MSG_LENGTH); +#if 0 + { + int msg_idx = 0; + printk ("got interrupt\n"); + for (msg_idx = 0; msg_idx < MSG_LENGTH; msg_idx++) { + printk ("%04X ", CMV_RxMsg[msg_idx]); + if (msg_idx % 8 == 7) + printk ("\n"); + } + printk ("\n"); + } +#endif + if (cmv_waiting == 1) { + arcmsgav = 1; + cmv_waiting = 0; +#if !defined(IFXMIPS_PORT_RTEMS) + MEI_WAKEUP_EVENT (wait_queue_arcmsgav); +#endif + } + else { + indicator_count++; + memcpy ((char *) Recent_indicator, (char *) CMV_RxMsg, + MSG_LENGTH * 2); + if (((CMV_RxMsg[0] & 0xff0) >> 4) == D2H_AUTONOMOUS_MODEM_READY_MSG) // arc ready + { //check ARC ready message + printk ("Got MODEM_READY_MSG\n"); + modem_ready = 1; + MEI_MUTEX_UNLOCK (mei_sema); // allow cmv access + } + } + } + + MEI_MASK_AND_ACK_IRQ (IFXMIPS_MEI_INT); +out: + return IRQ_HANDLED;; +} + +////////////////////////hdlc //////////////// + +/** + * Get the hdlc status + * + * \return HDLC status + * \ingroup Internal + */ +static unsigned int +ifx_me_hdlc_status (void) +{ + u16 CMVMSG[MSG_LENGTH]; + int ret; + + if (showtime != 1) + return -ENETRESET; + + makeCMV (H2D_CMV_READ, STAT, 14, 0, 1, NULL, CMVMSG); //Get HDLC status + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + return CMVMSG[4] & 0x0F; +} + +/** + * Check if the me is reslved. + * + * \param status the me status + * \return ME_HDLC_UNRESOLVED or ME_HDLC_RESOLVED + * \ingroup Internal + */ +int +ifx_me_is_resloved (int status) +{ + u16 CMVMSG[MSG_LENGTH]; + int ret; + if (adsl_mode <= 8 && adsl_mode_extend == 0) // adsl mode + { + makeCMV (H2D_CMV_READ, CNTL, 2, 0, 1, NULL, CMVMSG); //Get ME-HDLC Control + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return ME_HDLC_UNRESOLVED; + } + if (CMVMSG[4] & (1 << 0)) { + return ME_HDLC_UNRESOLVED; + } + } + else { + if (status == ME_HDLC_MSG_QUEUED + || status == ME_HDLC_MSG_SENT) + return ME_HDLC_UNRESOLVED; + if (status == ME_HDLC_IDLE) { + makeCMV (H2D_CMV_READ, CNTL, 2, 0, 1, NULL, CMVMSG); //Get ME-HDLC Control + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return IFX_POP_EOC_FAIL; + } + if (CMVMSG[4] & (1 << 0)) { + return ME_HDLC_UNRESOLVED; + } + } + } + return ME_HDLC_RESOLVED; +} + +int +_ifx_me_hdlc_send (unsigned char *hdlc_pkt, int pkt_len, int max_length) +{ + int ret; + u16 CMVMSG[MSG_LENGTH]; + u16 data = 0; + u16 len = 0; + int rx_length = 0; + int write_size = 0; + + if (pkt_len > max_length) { + makeCMV (H2D_CMV_READ, INFO, 85, 2, 1, NULL, CMVMSG); //Get ME-HDLC Control + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + rx_length = CMVMSG[4]; + if (rx_length + max_length < pkt_len) { + printk ("Exceed maximum eoc rx(%d)+tx(%d) message length\n", rx_length, max_length); + return -EMSGSIZE; + } + data = 1; + makeCMV (H2D_CMV_WRITE, INFO, 85, 6, 1, &data, CMVMSG); //disable RX Eoc + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + } + while (len < pkt_len) { + write_size = pkt_len - len; + if (write_size > 24) + write_size = 24; + //printk("len=%d,write_size=%d,pkt_len=%d\n",len,write_size,pkt_len); + memset (CMVMSG, 0, sizeof (CMVMSG)); + makeCMV (H2D_CMV_WRITE, INFO, 81, len / 2, (write_size + 1) / 2, (u16 *) (hdlc_pkt + len), CMVMSG); //Write clear eoc message to ARC + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + len += write_size; + } + makeCMV (H2D_CMV_WRITE, INFO, 83, 2, 1, &len, CMVMSG); //Update tx message length + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + + data = (1 << 0); + makeCMV (H2D_CMV_WRITE, CNTL, 2, 0, 1, &data, CMVMSG); //Start to send + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + return 0; +} + +/** + * Send hdlc packets + * + * \param hdlc_pkt Pointer to hdlc packet + * \param hdlc_pkt_len The number of bytes to send + * \return success or failure. + * \ingroup Internal + */ +int +ifx_me_hdlc_send (unsigned char *hdlc_pkt, int hdlc_pkt_len) +{ + int hdlc_status = 0; + u16 CMVMSG[MSG_LENGTH]; + int max_hdlc_tx_length = 0, ret = 0, retry = 0; + int power_mode = 0; + int send_busy_counter = 0; + int send_retry = 0; + + HDLC_SEND: + // retry 1000 times (10 seconds) + while (retry < 1000) { + /* In L2 power mode, do not read the OHC related parameters, + instead give the indication to the calling IOCTL, + that the readout fails (just return -EBUSY). */ + power_mode = get_l3_power_status(); + if (power_mode == L2_POWER_MODE) { + return -EBUSY; + } + + hdlc_status = ifx_me_hdlc_status (); + if (ifx_me_is_resloved (hdlc_status) == ME_HDLC_RESOLVED) // arc ready to send HDLC message + { + makeCMV (H2D_CMV_READ, INFO, 83, 0, 1, NULL, CMVMSG); //Get Maximum Allowed HDLC Tx Message Length + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + printk + ("ifx_me_hdlc_send failed. Return -EIO"); + return -EIO; + } + max_hdlc_tx_length = CMVMSG[4]; + ret = _ifx_me_hdlc_send (hdlc_pkt, hdlc_pkt_len, + max_hdlc_tx_length); + return ret; + } + else { + if (hdlc_status == ME_HDLC_MSG_SENT) + send_busy_counter++; + } + retry++; + MEI_WAIT (1); + } + // wait 10 seconds and FW still report busy -> reset FW HDLC status + if (send_busy_counter > 950 && send_retry == 0) { + u16 data = 0; + send_retry = 1; + retry = 0; + printk ("Reset FW HDLC status!!\n"); + send_busy_counter = 0; + data = (1 << 1); + makeCMV (H2D_CMV_WRITE, CNTL, 2, 0, 1, NULL, CMVMSG); //Force reset to idle + ret = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + goto HDLC_SEND; + } + printk ("ifx_me_hdlc_send failed. Return -EBUSY"); + return -EBUSY; +} + +/** + * Read the hdlc packets + * + * \param hdlc_pkt Pointer to hdlc packet + * \param hdlc_pkt_len The maximum number of bytes to read + * \return The number of bytes which reads. + * \ingroup Internal + */ +int +ifx_mei_hdlc_read (char *hdlc_pkt, int max_hdlc_pkt_len) +{ + u16 CMVMSG[MSG_LENGTH]; + int msg_read_len, ret = 0, pkt_len = 0, retry = 0; + + while (retry < 10) { + ret = ifx_me_hdlc_status (); + if (ret == ME_HDLC_RESP_RCVD) { + int current_size = 0; + makeCMV (H2D_CMV_READ, INFO, 83, 3, 1, NULL, CMVMSG); //Get EoC packet length + ret = mei_ioctl ((MEI_inode_t *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + + pkt_len = CMVMSG[4]; + if (pkt_len > max_hdlc_pkt_len) { + ret = -ENOMEM; + goto error; + } + while (current_size < pkt_len) { + if (pkt_len - current_size > + (MSG_LENGTH * 2 - 8)) + msg_read_len = (MSG_LENGTH * 2 - 8); + else + msg_read_len = + pkt_len - (current_size); + makeCMV (H2D_CMV_READ, INFO, 82, 0 + (current_size / 2), (msg_read_len + 1) / 2, NULL, CMVMSG); //Get hdlc packet + ret = mei_ioctl ((MEI_inode_t *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + goto error; + } + memcpy (hdlc_pkt + current_size, &CMVMSG[4], + msg_read_len); + current_size += msg_read_len; + } + ret = current_size; + break; + } + else { + ret = -ENODATA; + } + + retry++; + + MEI_WAIT (10); + } + error: + return ret; +} + +#if defined(IFXMIPS_CLEAR_EOC) +int +ifx_me_ceoc_send (struct sk_buff *eoc_pkt) +{ + int ret, pkt_len = 0; + unsigned char *pkt_data_ptr; + int offset = 0; + int swap_idx = 0; + + if (adsl_mode <= 8 && adsl_mode_extend == 0) // adsl mode + { + pkt_len = eoc_pkt->len; + + pkt_data_ptr = kmalloc (pkt_len + 3, GFP_KERNEL); + + offset = 2; + pkt_data_ptr[0] = 0x4c; + pkt_data_ptr[1] = 0x81; + pkt_len += 2; + } else { + pkt_len = eoc_pkt->len + 4; + pkt_data_ptr = kmalloc (pkt_len + 1 + 2, GFP_KERNEL); + memset (pkt_data_ptr, 0, pkt_len + 1 + 2); + //fill clear eoc header + pkt_data_ptr[0] = 0x1; + pkt_data_ptr[1] = 0x8; + pkt_data_ptr[2] = 0x4c; + pkt_data_ptr[3] = 0x81; + offset = 4; + } + for (swap_idx = 0; swap_idx < (eoc_pkt->len / 2) * 2; swap_idx += 2) + { + //printk("%02X %02X ",eoc_pkt->data[swap_idx],eoc_pkt->data[swap_idx+1]); + pkt_data_ptr[swap_idx + offset] = eoc_pkt->data[swap_idx + 1]; + pkt_data_ptr[swap_idx + 1 + offset] = eoc_pkt->data[swap_idx]; + } + if (eoc_pkt->len % 2) + { + //printk("%02X ",eoc_pkt->data[eoc_pkt->len-1]); + pkt_data_ptr[eoc_pkt->len - 1 + offset] = + eoc_pkt->data[eoc_pkt->len - 1]; + pkt_data_ptr[eoc_pkt->len + offset] = + eoc_pkt->data[eoc_pkt->len - 1]; + } + ret = ifx_me_hdlc_send (pkt_data_ptr, pkt_len); + + if (pkt_data_ptr != eoc_pkt->data) + { + kfree (pkt_data_ptr); + } + dev_kfree_skb (eoc_pkt); + return ret; +} + +int +get_me_ceoc_data (int pkt_len, int rx_buffer_addr, int rx_buffer_len, + u8 * data_ptr1) +{ + int ret; + MEI_ERROR dma_ret; + u16 CMVMSG[MSG_LENGTH]; + int read_size, aread_size; + int offset = 0; + u8 *data = NULL, *data_ptr = NULL; + int i, j; + int over_read = 0; + + i = j = 0; + + read_size = (pkt_len / 4) + 4; + offset = ceoc_read_idx % 4; + over_read = read_size * 4 - pkt_len - offset; + + ceoc_read_idx = (ceoc_read_idx & 0xFFFFFFFC); + + data = kmalloc (read_size * 4, GFP_KERNEL); + if (data == NULL) + goto error; + data_ptr = kmalloc (read_size * 4, GFP_KERNEL); + if (data_ptr == NULL) + goto error; + if (ceoc_read_idx + read_size * 4 >= rx_buffer_len) { + aread_size = (rx_buffer_len - ceoc_read_idx) / 4; + } + else { + aread_size = read_size; + } + + //printk("aread_size = %d,ceoc_read_idx=%d,read_size=%d,offset=%d\n",aread_size,ceoc_read_idx,read_size,offset); + dma_ret = + meiDebugRead (rx_buffer_addr + ceoc_read_idx, (u32 *) (data), + aread_size); + ceoc_read_idx += aread_size * 4; + if (aread_size != read_size) { + dma_ret = + meiDebugRead (rx_buffer_addr, + (u32 *) (data) + aread_size, + read_size - aread_size); + ceoc_read_idx = (read_size - aread_size) * 4; + } + if (ceoc_read_idx < over_read) + ceoc_read_idx = rx_buffer_len + ceoc_read_idx - over_read; + else + ceoc_read_idx -= over_read; + + if (offset == 0 || offset == 2) { + for (i = 0; i < read_size; i++) { + // 3412 --> 1234 + + for (j = 0; j < 4; j++) { + if (i * 4 + j - offset >= 0) + data_ptr[i * 4 + j - offset] = + data[i * 4 + (3 - j)]; + } + } + + } + else if (offset == 1) { + for (i = 0; i < pkt_len; i = i + 4) { + + data_ptr[i + 1] = data[i + 1]; + data_ptr[i] = data[i + 2]; + data_ptr[i + 3] = data[i + 7]; + data_ptr[i + 2] = data[i]; + } + } + else if (offset == 3) { + for (i = 0; i < pkt_len; i = i + 4) { + data_ptr[i + 1] = data[i + 7]; + data_ptr[i + 0] = data[i]; + data_ptr[i + 3] = data[i + 5]; + data_ptr[i + 2] = data[i + 6]; + } + } + if (pkt_len % 2 == 1) + data_ptr[pkt_len - 1] = data_ptr[pkt_len]; + + kfree (data); + memcpy (data_ptr1, data_ptr, pkt_len); + kfree (data_ptr); + + makeCMV (H2D_CMV_WRITE, INFO, 85, 3, 1, &ceoc_read_idx, CMVMSG); + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + goto error; + } + + return dma_ret; + error: + kfree (data); + kfree (data_ptr); + return -1; +} + +int +ifx_me_ceoc_receive (int ceoc_write_idx, int rx_buffer_len, + struct sk_buff **eoc_pkt) +{ + u16 CMVMSG[MSG_LENGTH]; + int pkt_len, ret; + u16 lsw_addr, msw_addr; + u32 rx_buffer_addr = 0; + MEI_ERROR dma_ret; + + //printk("rx_buffer_len=%d,ceoc_read_idx=%d,ceoc_write_idx=%d\n",rx_buffer_len,ceoc_read_idx,ceoc_write_idx); + if (ceoc_write_idx > ceoc_read_idx) { + pkt_len = ceoc_write_idx - ceoc_read_idx; + } + else { + pkt_len = rx_buffer_len - ceoc_read_idx + ceoc_write_idx; + } + *eoc_pkt = dev_alloc_skb (pkt_len); + if (*eoc_pkt == NULL) { + printk ("Out of memory!\n"); + ret = -ENOMEM; + goto error; + } + + makeCMV (H2D_CMV_READ, INFO, 85, 0, 1, NULL, CMVMSG); //Get HDLC packet + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + goto error; + } + lsw_addr = CMVMSG[4]; + + makeCMV (H2D_CMV_READ, INFO, 85, 1, 1, NULL, CMVMSG); //Get HDLC packet + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + goto error; + } + msw_addr = CMVMSG[4]; + rx_buffer_addr = msw_addr << 16 | lsw_addr; + dma_ret = + get_me_ceoc_data (pkt_len, rx_buffer_addr, rx_buffer_len, + (u16 *) skb_put (*eoc_pkt, pkt_len)); + if (dma_ret != MEI_SUCCESS) { + ret = -EIO; + goto error; + } + + return 0; + error: + if (*eoc_pkt != NULL) + dev_kfree_skb (*eoc_pkt); + return ret; +} + +int +ifx_mei_ceoc_rx (void) +{ + u16 CMVMSG[MSG_LENGTH]; + int rx_buffer_len, ret, pkt_len = 0; + struct sk_buff *eoc_pkt; + u16 ceoc_write_idx = 0; + + makeCMV (H2D_CMV_READ, INFO, 85, 2, 1, NULL, CMVMSG); //Get EoC packet length + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + printk ("ioctl fail!!\n"); + } + rx_buffer_len = CMVMSG[4]; + + makeCMV (H2D_CMV_READ, INFO, 85, 4, 1, NULL, CMVMSG); //Get write index + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + if (ret != 0) { + return -EIO; + } + + ceoc_write_idx = CMVMSG[4]; + ret = ifx_me_ceoc_receive (ceoc_write_idx, rx_buffer_len, &eoc_pkt); +#if defined (CONFIG_ATM_IFXMIPS) + if (ret == 0) { + skb_pull (eoc_pkt, 2); // skip 4c 81 header + ifx_push_ceoc (eoc_pkt); //pass data to higher layer + } + + return ret; +#endif +} + +static int +adsl_clear_eoc_poll (void *unused) +{ + struct task_struct *tsk = current; + + daemonize("mei_eoc_poll"); + strcpy(tsk->comm, "mei_ceoc_poll"); + sigfillset(&tsk->blocked); + + while (1) + { + MEI_WAIT_EVENT (wait_queue_hdlc_poll); + if (showtime) + ifx_mei_ceoc_rx(); + } + return 0; +} +#endif //#if defined(IFXMIPS_CLEAR_EOC) + +#ifdef IFXMIPS_CLEAR_EOC +static int +ifxmips_mei_ceoc_init (void) +{ + kernel_thread (adsl_clear_eoc_poll, NULL, + CLONE_FS | CLONE_FILES | CLONE_SIGNAL); + return 0; +} +#endif + +////////////////////// Driver Structure /////////////////////// + +/** + * Free the memory for ARC firmware + * + * \param type Free all memory or free the unused memory after showtime + * \ingroup Internal + */ +static int +free_image_buffer (int type) +{ + int idx = 0; + for (idx = 0; idx < MAX_BAR_REGISTERS; idx++) { + printk ("meminfo[%d].type=%d,size=%ld,addr=%X\n", idx, + adsl_mem_info[idx].type, adsl_mem_info[idx].size, + (unsigned int)adsl_mem_info[idx].address); + if (type == FREE_ALL || adsl_mem_info[idx].type == type) { + if (adsl_mem_info[idx].size > 0) { + kfree (adsl_mem_info[idx].org_address); + adsl_mem_info[idx].address = 0; + adsl_mem_info[idx].size = 0; + adsl_mem_info[idx].type = 0; + adsl_mem_info[idx].nCopy = 0; + } + } + } + return 0; +} + +/** + * Allocate memory for ARC firmware + * + * \param size The number of bytes to allocate. + * \param adsl_mem_info Pointer to firmware information. + * \ingroup Internal + */ +static int +alloc_processor_memory (unsigned long size, smmu_mem_info_t * adsl_mem_info) +{ + char *mem_ptr = NULL; + char *org_mem_ptr = NULL; + int idx = 0; + long total_size = 0; + long img_size = size; + int err = 0; + + // Alloc Swap Pages + while (img_size > 0 && idx < MAX_BAR_REGISTERS) { + // skip bar15 for XDATA usage. +#ifndef DFE_LOOPBACK + if (idx == XDATA_REGISTER) + idx++; +#endif + if (idx == MAX_BAR_REGISTERS - 1) + { + //allocate 1MB memory for bar16 + org_mem_ptr = kmalloc (1024 * 1024, GFP_ATOMIC); + mem_ptr = (char*)((unsigned long) (org_mem_ptr + 1023) & 0xFFFFFC00); + adsl_mem_info[idx].size = 1024 * 1024; + } else { + org_mem_ptr = kmalloc (SDRAM_SEGMENT_SIZE, GFP_ATOMIC); + mem_ptr = (char*)((unsigned long) (org_mem_ptr + 1023) & 0xFFFFFC00); + adsl_mem_info[idx].size = SDRAM_SEGMENT_SIZE; + } + if (org_mem_ptr == NULL) + { + printk ("kmalloc memory fail!\n"); + err = -ENOMEM; + goto allocate_error; + } + adsl_mem_info[idx].address = mem_ptr; + adsl_mem_info[idx].org_address = org_mem_ptr; + + img_size -= SDRAM_SEGMENT_SIZE; + total_size += SDRAM_SEGMENT_SIZE; + printk("alloc memory idx=%d,img_size=%ld,addr=%X\n", + idx, img_size, (unsigned int)adsl_mem_info[idx].address); + idx++; + } + if (img_size > 0) + { + printk ("Image size is too large!\n"); + err = -EFBIG; + goto allocate_error; + } + err = idx; + return err; + + allocate_error: + free_image_buffer (FREE_ALL); + return err; +} + +/** + * Program the BAR registers + * + * \param nTotalBar The number of bar to program. + * \ingroup Internal + */ +static int +update_bar_register (int nTotalBar) +{ + int idx = 0; + + for (idx = 0; idx < nTotalBar; idx++) { + //skip XDATA register + if (idx == XDATA_REGISTER) + idx++; + meiLongwordWrite ( MEI_XMEM_BAR_BASE + idx * 4, + (((uint32_t) adsl_mem_info[idx]. + address) & 0x0FFFFFFF)); + printk ("BAR%d=%08X, addr=%08X\n", idx, + (((uint32_t) adsl_mem_info[idx]. + address) & 0x0FFFFFFF), + (((uint32_t) adsl_mem_info[idx].address))); + } + for (idx = nTotalBar; idx < MAX_BAR_REGISTERS; idx++) { + if (idx == XDATA_REGISTER) + idx++; + meiLongwordWrite ( MEI_XMEM_BAR_BASE + idx * 4, + (((uint32_t) adsl_mem_info[nTotalBar - 1]. + address) & 0x0FFFFFFF)); + } + + meiLongwordWrite (MEI_XMEM_BAR_BASE + XDATA_REGISTER * 4, + (((uint32_t) adsl_mem_info[XDATA_REGISTER]. + address) & 0x0FFFFFFF)); + // update MEI_XDATA_BASE_SH + printk ("update bar15 register with %08lX\n", + ((unsigned long) adsl_mem_info[XDATA_REGISTER]. + address) & 0x0FFFFFFF); + meiLongwordWrite (MEI_XDATA_BASE_SH, + ((unsigned long) adsl_mem_info[XDATA_REGISTER]. + address) & 0x0FFFFFFF); + return MEI_SUCCESS; +} + +/** + * Copy the firmware to BARs memory. + * + * \param filp Pointer to the file structure. + * \param buf Pointer to the data. + * \param size The number of bytes to copy. + * \param loff The file offset. + * \return The current file position. + * \ingroup Internal + */ +ssize_t +mei_write (MEI_file_t * filp, char *buf, size_t size, loff_t * loff) +{ + ARC_IMG_HDR img_hdr_tmp, *img_hdr; + + size_t nRead = 0, nCopy = 0; + char *mem_ptr; + ssize_t retval = -ENOMEM; + int idx = 0; + + if (*loff == 0) { + if (size < sizeof (img_hdr)) { + printk ("Firmware size is too small!\n"); + return retval; + } + copy_from_user ((char *) &img_hdr_tmp, buf, + sizeof (img_hdr_tmp)); + image_size = le32_to_cpu (img_hdr_tmp.size) + 8; // header of image_size and crc are not included. + if (image_size > 1024 * 1024) { + printk ("Firmware size is too large!\n"); + return retval; + } + // check if arc is halt + if (arc_halt_flag != 1) { + meiResetARC (); + meiHaltArc (); + } + + // reset part of PPE + *(unsigned long *) (IFXMIPS_PPE32_SRST) = 0xC30; + *(unsigned long *) (IFXMIPS_PPE32_SRST) = 0xFFF; + + free_image_buffer (FREE_ALL); //free all + + retval = alloc_processor_memory (image_size, adsl_mem_info); + if (retval < 0) { + printk ("Error: No memory space left.\n"); + goto error; + } + + for (idx = 0; idx < retval; idx++) { + //skip XDATA register + if (idx == XDATA_REGISTER) + idx++; + if (idx * SDRAM_SEGMENT_SIZE < + le32_to_cpu (img_hdr_tmp.page[0].p_offset)) { + adsl_mem_info[idx].type = FREE_RELOAD; + } + else { + adsl_mem_info[idx].type = FREE_SHOWTIME; + } + + } + nBar = retval; + + img_hdr = (ARC_IMG_HDR *) adsl_mem_info[0].address; + +#if !defined(__LINUX__) + adsl_mem_info[XDATA_REGISTER].org_address = + kmalloc (SDRAM_SEGMENT_SIZE + 1023, GFP_ATOMIC); +#else + adsl_mem_info[XDATA_REGISTER].org_address = + kmalloc (SDRAM_SEGMENT_SIZE, GFP_ATOMIC); +#endif + adsl_mem_info[XDATA_REGISTER].address = + (char + *) ((unsigned long) (adsl_mem_info[XDATA_REGISTER]. + org_address + + 1023) & 0xFFFFFC00); + adsl_mem_info[XDATA_REGISTER].size = SDRAM_SEGMENT_SIZE; + if (adsl_mem_info[XDATA_REGISTER].address == NULL) { + printk ("kmalloc memory fail!\n"); + retval = -ENOMEM; + goto error; + } + adsl_mem_info[XDATA_REGISTER].type = FREE_RELOAD; + update_bar_register (nBar); + + } + else if (image_size == 0) { + printk ("Error: Firmware size=0! \n"); + goto error; + } + else { + if (arc_halt_flag == 0) { + printk + ("Please download the firmware from the beginning of the firmware!\n"); + goto error; + } + } + + nRead = 0; + while (nRead < size) { + long offset = ((long) (*loff) + nRead) % SDRAM_SEGMENT_SIZE; + idx = (((long) (*loff)) + nRead) / SDRAM_SEGMENT_SIZE; + mem_ptr = (char *) + KSEG1ADDR ((unsigned long) (adsl_mem_info[idx]. + address) + offset); + if ((size - nRead + offset) > SDRAM_SEGMENT_SIZE) + nCopy = SDRAM_SEGMENT_SIZE - offset; + else + nCopy = size - nRead; + copy_from_user (mem_ptr, buf + nRead, nCopy); +#ifdef IMAGE_SWAP + for (offset = 0; offset < (nCopy / 4); offset++) { + ((unsigned long *) mem_ptr)[offset] = + le32_to_cpu (((unsigned long *) + mem_ptr)[offset]); + } +#endif //IMAGE_SWAP + nRead += nCopy; + adsl_mem_info[idx].nCopy += nCopy; + } + +#if ( defined(HEADER_SWAP) && !defined(IMAGE_SWAP)) || (defined(IMAGE_SWAP) && !defined(HEADER_SWAP)) + if (*loff == 0) { + + for (idx = 0; + idx < + (sizeof (ARC_IMG_HDR) + + (le32_to_cpu (img_hdr_tmp.count) - + 1) * sizeof (ARC_SWP_PAGE_HDR)) / 4; idx++) { + ((unsigned long *) img_hdr)[idx] = + le32_to_cpu (((unsigned long *) + img_hdr)[idx]); + } + } +#endif //( defined(HEADER_SWAP) && !defined(IMAGE_SWAP)) || (defined(IMAGE_SWAP) && !defined(HEADER_SWAP)) + printk ("size=%X,loff=%08X\n", size, (unsigned int) *loff); + + *loff += size; + return size; + error: + free_image_buffer (FREE_ALL); + + return retval; +} + +/******************************************************** + * L3 Power Mode * + ********************************************************/ +/** + * Send a CMV message. + * This function sends a CMV message to ARC + * + * \param opcode The message opcode + * \param group The message group number + * \param address The message address. + * \param index The message index. + * \param size The number of words to read/write. + * \param data The pointer to data. + * \param CMVMSG The pointer to message buffer. + * \return 0: success + * \ingroup Internal + */ +int +send_cmv (u8 opcode, u8 group, u16 address, u16 index, int size, u16 * data, u16 * CMVMSG) +{ + int ret; + + makeCMV(opcode, group, address, index, size, data, CMVMSG); + ret = mei_ioctl((struct inode *) 0, NULL, IFXMIPS_MEI_CMV_WINHOST, (unsigned long)CMVMSG); + return ret; +} + +#ifdef IFX_ADSL_L3_MODE_SUPPORT + +/** + * Check the L3 request from CO + * This function Check if CPE received the L3 request from CO + * \return 1: got L3 request. + * \ingroup Internal + */ +int +check_co_l3_shutdown_request (void) +{ + u16 CMVMSG[MSG_LENGTH]; + if (modem_ready == 1) { + if (send_cmv (H2D_CMV_READ, STAT, 4, 0, 1, NULL, CMVMSG) != 0) { + return -EBUSY; + } + if (CMVMSG[4] & BIT14) { + return 1; + } + } + return 0; +} + +/** + * Check the L3 status + * This function get the CPE Power Management Mode status + * \return 0: L0 Mode + * 2: L2 Mode + * 3: L3 Mode + * \ingroup Internal + */ +int +get_l3_power_status (void) +{ + u16 CMVMSG[MSG_LENGTH]; + if (modem_ready == 0) { + return L3_POWER_MODE; + } + else { + if (send_cmv (H2D_CMV_READ, STAT, 18, 0, 1, NULL, CMVMSG) != + 0) { + return -EBUSY; + } + return ((int) CMVMSG[4]); + + } + return 0; +} + +/** + * Send a L3 request to CO + * This function send a L3 request to CO and check the CO response. + * \return 0: Success. Others: Fail. + * \ingroup Internal + */ +int +send_l3_shutdown_cmd (void) +{ + u16 cmd = 0x1; + int nRetry = 0; + u16 CMVMSG[MSG_LENGTH]; + + if (modem_ready == 0) { + return -EBUSY; + } + // send l3 request to CO + if (send_cmv (H2D_CMV_WRITE, CNTL, 3, 0, 1, &cmd, CMVMSG) != 0) { + return -EBUSY; + } + retry: + MEI_WAIT (10); + + // check CO response + if (send_cmv (H2D_CMV_READ, STAT, 20, 0, 1, NULL, CMVMSG) != 0) { + return -EBUSY; + } + if (CMVMSG[4] == 0) { + nRetry++; + if (nRetry < 10) { + goto retry; + } + else { + return -EBUSY; + } + + } + else if (CMVMSG[4] == 1) // reject + { + return -EPERM; + } + else if (CMVMSG[4] == 2) // ok + { + return 0; + } + else if (CMVMSG[4] == 3) // failure + { + return -EAGAIN; + } + return 0; +} + +/** + * Enable L3 Power Mode + * This function send a L3 request to CO and check the CO response. Then reboot the CPE to enter L3 Mode. + * \return 0: Success. Others: Fail. + * \ingroup Internal + */ +int +set_l3_shutdown (void) +{ + int ret = 0; + if (l3_shutdown == 0) { + // send l3 request to CO + ret = send_l3_shutdown_cmd (); + if (ret == 0) //got CO ACK + { + //reboot adsl and block autoboot daemon + ret = mei_ioctl ((struct inode *) 0, NULL, IFXMIPS_MEI_REBOOT, (unsigned long)NULL); + l3_shutdown = 1; + } + } + return ret; +} + +/** + * Disable L3 Power Mode + * This function disable L3 Mode and wake up the autoboot daemon. + * \return 0: Success. + * \ingroup Internal + */ +//l3 power mode disable +int +set_l3_power_on (void) +{ + if (l3_shutdown == 1) { + l3_shutdown = 0; + // wakeup autoboot daemon + MEI_WAKEUP_EVENT (wait_queue_l3); + + } + return 0; +} + +/******************************************************** + * End of L3 Power Mode * + ********************************************************/ +#endif //IFX_ADSL_L3_MODE_SUPPORT + +#ifdef CONFIG_IFXMIPS_MEI_LED +/* + * LED Initialization function + */ +int +meiADSLLedInit (void) +{ + u16 data = 0x0600; + u16 CMVMSG[MSG_LENGTH]; + + data = 0x0400; +#if defined(DATA_LED_SUPPORT) && defined (DATA_LED_ADSL_FW_HANDLE) + data |= 0x200; +#endif + // Setup ADSL Link/Data LED + if (send_cmv (H2D_CMV_WRITE, INFO, 91, 0, 1, &data, CMVMSG) != 0) { + return -EBUSY; + } + + if (send_cmv (H2D_CMV_WRITE, INFO, 91, 2, 1, &data, CMVMSG) != 0) { + return -EBUSY; + } + + // Let FW to handle ADSL Link LED + data = 0x0a03; //invert the LED signal as per input from Stefan on 13/11/2006 + if (send_cmv (H2D_CMV_WRITE, INFO, 91, 4, 1, &data, CMVMSG) != 0) { + return -EBUSY; + } + +#ifdef DATA_LED_SUPPORT +#ifdef DATA_LED_ADSL_FW_HANDLE + + // Turn ADSL Data LED on + data = 0x0900; + if (send_cmv (H2D_CMV_WRITE, INFO, 91, 5, 1, &data, CMVMSG) != 0) { + return -EBUSY; + } +#else + ifxmips_led_set(0x1); +#endif +#endif + return 0; +} +#endif + +#ifdef IFX_ADSL_DUAL_LATENCY_SUPPORT +/* + * Dual Latency Path Initialization function + */ +int +meiDualLatencyInit (void) +{ + u16 nDual = 0; + u16 CMVMSG[MSG_LENGTH]; + + // setup up stream path + if (bDualLatency & DUAL_LATENCY_US_ENABLE) { + nDual = 2; + } + else { + nDual = 1; + } + + if (send_cmv (H2D_CMV_WRITE, CNFG, 10, 0, 1, &nDual, CMVMSG) != 0) { + return -EBUSY; + } + + if (send_cmv (H2D_CMV_WRITE, CNFG, 11, 0, 1, &nDual, CMVMSG) != 0) { + return -EBUSY; + } + + // setup down stream path + if (bDualLatency & DUAL_LATENCY_DS_ENABLE) { + nDual = 2; + } + else { + nDual = 1; + } + + if (send_cmv (H2D_CMV_WRITE, CNFG, 21, 0, 1, &nDual, CMVMSG) != 0) { + return -EBUSY; + } + if (send_cmv (H2D_CMV_WRITE, CNFG, 22, 0, 1, &nDual, CMVMSG) != 0) { + return -EBUSY; + } + return 0; +} + +int +mei_is_dual_latency_enabled (void) +{ + return bDualLatency; +} +#endif + +int +meiAdslStartupInit (void) +{ +#ifdef CONFIG_IFXMIPS_MEI_LED + meiADSLLedInit (); +#endif +#ifdef IFX_ADSL_DUAL_LATENCY_SUPPORT + meiDualLatencyInit (); +#endif + return 0; +} + +/** + * MEI IO controls for user space accessing + * + * \param ino Pointer to the stucture of inode. + * \param fil Pointer to the stucture of file. + * \param command The ioctl command. + * \param lon The address of data. + * \return Success or failure. + * \ingroup Internal + */ +int +mei_ioctl (MEI_inode_t * ino, MEI_file_t * fil, unsigned int command, + unsigned long lon) +{ + int i; + + int meierr = MEI_SUCCESS; + meireg regrdwr; + meidebug debugrdwr; + u32 arc_debug_data, reg_data; +#ifdef IFXMIPS_CLEAR_EOC + u16 data; + struct sk_buff *eoc_skb; +#endif //IFXMIPS_CLEAR_EOC + u16 RxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + u16 TxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + + int from_kernel = 0; //joelin + if (ino == (MEI_inode_t *) 0) + from_kernel = 1; //joelin + if (command < IFXMIPS_MEI_START) { +#ifdef CONFIG_IFXMIPS_MEI_MIB + return mei_mib_ioctl (ino, fil, command, lon); +#endif //CONFIG_IFXMIPS_MEI_MIB + + if (command == IFXMIPS_MIB_LO_ATUR + || command == IFXMIPS_MIB_LO_ATUC) + return MEI_SUCCESS; + printk + ("No such ioctl command (0x%X)! MEI ADSL MIB is not supported!\n", + command); + return -ENOIOCTLCMD; + } + else { + switch (command) { + case IFXMIPS_MEI_START: + + showtime = 0; + loop_diagnostics_completed = 0; + if (time_disconnect.tv_sec == 0) + do_gettimeofday (&time_disconnect); + + if (MEI_MUTEX_LOCK (mei_sema)) //disable CMV access until ARC ready + { + printk ("-ERESTARTSYS\n"); + return -ERESTARTSYS; + } + + meiMailboxInterruptsDisable (); //disable all MEI interrupts + if (mei_arc_swap_buff == NULL) { + mei_arc_swap_buff = + (u32 *) kmalloc (MAXSWAPSIZE * 4, + GFP_KERNEL); + if (mei_arc_swap_buff == NULL) { + printk + ("\n\n malloc fail for codeswap buff"); + meierr = MEI_FAILURE; + } + } + if (meiRunAdslModem () != MEI_SUCCESS) { + printk + ("meiRunAdslModem() error..."); + meierr = MEI_FAILURE; + } +#ifdef IFX_ADSL_L3_MODE_SUPPORT + /* L3 Power Mode Start */ + if (l3_shutdown == 1) { + // block autoboot daemon until l3 power mode disable + MEI_WAIT_EVENT (wait_queue_l3); + } + /* L3 Power Mode End */ +#endif //IFX_ADSL_L3_MODE_SUPPORT + if (autoboot_enable_flag) + meiAdslStartupInit (); + break; + + case IFXMIPS_MEI_SHOWTIME: + if (MEI_MUTEX_LOCK (mei_sema)) + return -ERESTARTSYS; + + do_gettimeofday (&time_showtime); + unavailable_seconds += + time_showtime.tv_sec - time_disconnect.tv_sec; + time_disconnect.tv_sec = 0; + makeCMV (H2D_CMV_READ, RATE, 0, 0, 4, NULL, TxMessage); //maximum allowed tx message length, in bytes + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { + printk + ("\n\nCMV fail, Group RAGE Address 0 Index 0"); + } + else { + u32 rate_fast; + u32 rate_intl; + rate_intl = RxMessage[4] | RxMessage[5] << 16; + rate_fast = RxMessage[6] | RxMessage[7] << 16; + // 609251:tc.chen Fix ATM QoS issue start + if (rate_intl && rate_fast) // apply cell rate to each path + { +#ifdef CONFIG_ATM_IFXMIPS + ifx_atm_set_cell_rate (1, + rate_intl / + (53 * 8)); + ifx_atm_set_cell_rate (0, + rate_fast / + (53 * 8)); +#endif + } + else if (rate_fast) // apply fast path cell rate to atm interface 0 + { +#ifdef CONFIG_ATM_IFXMIPS + ifx_atm_set_cell_rate (0, + rate_fast / + (53 * 8)); +#endif + } + else if (rate_intl) // apply interleave path cell rate to atm interface 0 + { +#ifdef CONFIG_ATM_IFXMIPS + ifx_atm_set_cell_rate (0, + rate_intl / + (53 * 8)); +#endif + } + else { + printk ("Got rate fail.\n"); + } + // 609251:tc.chen end + } + +#ifdef IFXMIPS_CLEAR_EOC + data = 1; + makeCMV (H2D_CMV_WRITE, OPTN, 24, 0, 1, &data, + TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { + printk ("Enable clear eoc fail!\n"); + } +#endif + // read adsl mode + makeCMV (H2D_CMV_READ, STAT, 1, 0, 1, NULL, + TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { +#ifdef IFXMIPS_MEI_DEBUG_ON + printk ("\n\nCMV fail, Group STAT Address 1 Index 0"); +#endif + } + adsl_mode = RxMessage[4]; + makeCMV (H2D_CMV_READ, STAT, 17, 0, 1, NULL, + TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { +#ifdef IFXMIPS_MEI_DEBUG_ON + printk ("\n\nCMV fail, Group STAT Address 1 Index 0"); +#endif + } + adsl_mode_extend = RxMessage[4]; +#ifdef CONFIG_IFXMIPS_MEI_MIB + mei_mib_adsl_link_up (); +#endif + +//joelin 04/16/2005-start + makeCMV (H2D_CMV_WRITE, PLAM, 10, 0, 1, + &unavailable_seconds, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { + printk + ("\n\nCMV fail, Group 7 Address 10 Index 0"); + } + +//joelin 04/16/2005-end + showtime = 1; + free_image_buffer (FREE_SHOWTIME); + MEI_MUTEX_UNLOCK (mei_sema); + break; + + case IFXMIPS_MEI_HALT: + if (arc_halt_flag == 0) { + meiResetARC (); + meiHaltArc (); + } + break; + case IFXMIPS_MEI_RUN: + if (arc_halt_flag == 1) { + meiRunArc (); + } + break; + case IFXMIPS_MEI_CMV_WINHOST: + if (MEI_MUTEX_LOCK (mei_sema)) + return -ERESTARTSYS; + + if (!from_kernel) + copy_from_user ((char *) TxMessage, (char *) lon, MSG_LENGTH * 2); //joelin + else + memcpy (TxMessage, (char *) lon, + MSG_LENGTH * 2); + + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != + MEI_SUCCESS) { + printk + ("\n\nWINHOST CMV fail :TxMessage:%X %X %X %X, RxMessage:%X %X %X %X %X\n", + TxMessage[0], TxMessage[1], + TxMessage[2], TxMessage[3], + RxMessage[0], RxMessage[1], + RxMessage[2], RxMessage[3], + RxMessage[4]); + meierr = MEI_FAILURE; + } + else { + if (!from_kernel) //joelin + copy_to_user ((char *) lon, + (char *) RxMessage, + MSG_LENGTH * 2); + else + memcpy ((char *) lon, + (char *) RxMessage, + MSG_LENGTH * 2); + } + + MEI_MUTEX_UNLOCK (mei_sema); + break; +#ifdef IFXMIPS_MEI_CMV_EXTRA + case IFXMIPS_MEI_CMV_READ: + copy_from_user ((char *) (®rdwr), (char *) lon, + sizeof (meireg)); + meiLongwordRead ((u32*)regrdwr.iAddress, &(regrdwr.iData)); + + copy_to_user((char *) lon, (char *) (®rdwr), sizeof (meireg)); + break; + + case IFXMIPS_MEI_CMV_WRITE: + copy_from_user ((char *) (®rdwr), (char *) lon, sizeof (meireg)); + meiLongwordWrite ((u32*)regrdwr.iAddress, regrdwr.iData); + break; + + case IFXMIPS_MEI_REMOTE: + copy_from_user ((char *) (&i), (char *) lon, + sizeof (int)); + if (i == 0) { + meiMailboxInterruptsEnable (); + + MEI_MUTEX_UNLOCK (mei_sema); + } + else if (i == 1) { + meiMailboxInterruptsDisable (); + if (MEI_MUTEX_LOCK (mei_sema)) + return -ERESTARTSYS; + } + else { + printk + ("\n\n IFXMIPS_MEI_REMOTE argument error"); + meierr = MEI_FAILURE; + } + break; + + case IFXMIPS_MEI_READDEBUG: + case IFXMIPS_MEI_WRITEDEBUG: +#if 0 //tc.chen:It is no necessary to acquire lock to read debug memory!! + if (MEI_MUTEX_LOCK (mei_sema)) + return -ERESTARTSYS; +#endif + if (!from_kernel) + copy_from_user ((char *) (&debugrdwr), + (char *) lon, + sizeof (debugrdwr)); + else + memcpy ((char *) (&debugrdwr), (char *) lon, + sizeof (debugrdwr)); + + if (command == IFXMIPS_MEI_READDEBUG) + meiDebugRead (debugrdwr.iAddress, + debugrdwr.buffer, + debugrdwr.iCount); + else + meiDebugWrite (debugrdwr.iAddress, + debugrdwr.buffer, + debugrdwr.iCount); + + if (!from_kernel) + copy_to_user ((char *) lon, (char *) (&debugrdwr), sizeof (debugrdwr)); //dying gasp +#if 0 //tc.chen:It is no necessary to acquire lock to read debug memory!! + MEI_MUTEX_UNLOCK (mei_sema); +#endif + break; + case IFXMIPS_MEI_RESET: + case IFXMIPS_MEI_REBOOT: + +#ifdef CONFIG_IFXMIPS_MEI_MIB + mei_mib_adsl_link_down (); +#endif + +#ifdef IFX_ADSL_L3_MODE_SUPPORT + /* L3 Power Mode start */ + if (check_co_l3_shutdown_request () == 1) //co request + { + // cpe received co L3 request + l3_shutdown = 1; + } + /* L3 Power Mode end */ +#endif //IFX_ADSL_L3_MODE_SUPPORT + + meiResetARC (); + meiControlModeSwitch (MEI_MASTER_MODE); + //enable ac_clk signal + _meiDebugLongWordRead (MEI_DEBUG_DEC_DMP1_MASK, + CRI_CCR0, &arc_debug_data); + arc_debug_data |= ACL_CLK_MODE_ENABLE; + _meiDebugLongWordWrite (MEI_DEBUG_DEC_DMP1_MASK, + CRI_CCR0, arc_debug_data); + meiControlModeSwitch (JTAG_MASTER_MODE); + meiHaltArc (); + update_bar_register (nBar); + break; + case IFXMIPS_MEI_DOWNLOAD: + // DMA the boot code page(s) + printk ("Start download pages"); + meiDownloadBootPages (); + break; +#endif //IFXMIPS_MEI_CMV_EXTRA + //for clearEoC +#ifdef IFXMIPS_CLEAR_EOC + case IFXMIPS_MEI_EOC_SEND: + if (!showtime) { + return -EIO; + } + if (!from_kernel) { + copy_from_user ((char *) (&debugrdwr), + (char *) lon, + sizeof (debugrdwr)); + eoc_skb = + dev_alloc_skb (debugrdwr.iCount * 4); + if (eoc_skb == NULL) { + printk + ("\n\nskb alloc fail"); + break; + } + + eoc_skb->len = debugrdwr.iCount * 4; + memcpy (skb_put + (eoc_skb, debugrdwr.iCount * 4), + (char *) debugrdwr.buffer, + debugrdwr.iCount * 4); + } + else { + eoc_skb = (struct sk_buff *) lon; + } + ifx_me_ceoc_send (eoc_skb); //pass data to higher layer + break; +#endif // IFXMIPS_CLEAR_EOC + case IFXMIPS_MEI_JTAG_ENABLE: + printk ("ARC JTAG Enable.\n"); + *(IFXMIPS_GPIO_P0_DIR) = (*IFXMIPS_GPIO_P0_DIR) & (~0x800); // set gpio11 to input + *(IFXMIPS_GPIO_P0_ALTSEL0) = ((*IFXMIPS_GPIO_P0_ALTSEL0) & (~0x800)); + *(IFXMIPS_GPIO_P0_ALTSEL1) = ((*IFXMIPS_GPIO_P0_ALTSEL1) & (~0x800)); + *IFXMIPS_GPIO_P0_OD = (*IFXMIPS_GPIO_P0_OD) | 0x800; + + //enable ARC JTAG + meiLongwordRead(IFXMIPS_RCU_RST, ®_data); + meiLongwordWrite(IFXMIPS_RCU_RST, reg_data | IFXMIPS_RCU_RST_REQ_ARC_JTAG); + break; + + case GET_ADSL_LOOP_DIAGNOSTICS_MODE: + copy_to_user ((char *) lon, (char *) &loop_diagnostics_mode, sizeof(int)); + break; + case LOOP_DIAGNOSTIC_MODE_COMPLETE: + loop_diagnostics_completed = 1; +#ifdef CONFIG_IFXMIPS_MEI_MIB + // read adsl mode + makeCMV (H2D_CMV_READ, STAT, 1, 0, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { +#ifdef IFXMIPS_MEI_DEBUG_ON + printk ("\n\nCMV fail, Group STAT Address 1 Index 0"); +#endif + } + adsl_mode = RxMessage[4]; + + makeCMV (H2D_CMV_READ, STAT, 17, 0, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { +#ifdef IFXMIPS_MEI_DEBUG_ON + printk ("\n\nCMV fail, Group STAT Address 1 Index 0"); +#endif + } + adsl_mode_extend = RxMessage[4]; +#endif + MEI_WAKEUP_EVENT (wait_queue_loop_diagnostic); + break; + case SET_ADSL_LOOP_DIAGNOSTICS_MODE: + if (lon != loop_diagnostics_mode) { + loop_diagnostics_completed = 0; + loop_diagnostics_mode = lon; +#if 0 //08/12/2006 tc.chen : autoboot daemon should reset dsl + mei_ioctl ((MEI_inode_t *) 0, NULL, + IFXMIPS_MEI_REBOOT, + (unsigned long) NULL); +#endif + } + break; + case IS_ADSL_LOOP_DIAGNOSTICS_MODE_COMPLETE: + copy_to_user ((char *) lon, + (char *) &loop_diagnostics_completed, + sizeof (int)); + break; +#ifdef IFX_ADSL_L3_MODE_SUPPORT + /* L3 Power Mode Start */ + case GET_POWER_MANAGEMENT_MODE: + i = get_l3_power_status (); + copy_to_user ((char *) lon, (char *) &i, + sizeof (int)); + break; + case SET_L3_POWER_MODE: + i = 1; + copy_from_user ((char *) &i, (char *) lon, + sizeof (int)); + if (i == 0) { + return set_l3_shutdown (); + } + else { + return set_l3_power_on (); + } + break; + /* L3 Power Mode End */ +#endif //IFX_ADSL_L3_MODE_SUPPORT +#ifdef IFX_ADSL_DUAL_LATENCY_SUPPORT + case GET_ADSL_DUAL_LATENCY: + i = mei_is_dual_latency_enabled (); + if (i < 0) + return i; + copy_to_user ((char *) lon, (char *) &i, + sizeof (int)); + break; + case SET_ADSL_DUAL_LATENCY: + i = 0; + copy_from_user ((char *) &i, (char *) lon, + sizeof (int)); + if (i > DUAL_LATENCY_US_DS_ENABLE) { + return -EINVAL; + } + if (i != bDualLatency) { + bDualLatency = i; + i = 1; // DualLatency update,need to reboot arc + } + else { + i = 0; // DualLatency is the same + } + if (modem_ready && i) // modem is already start, reboot arc to apply Dual Latency changed + { + mei_ioctl ((MEI_inode_t *) 0, NULL, + IFXMIPS_MEI_REBOOT, + (unsigned long) NULL); + } + break; + +#endif + case QUIET_MODE_GET: + copy_to_user ((char *) lon, (char *) &quiet_mode_flag, + sizeof (int)); + break; + case QUIET_MODE_SET: + copy_from_user ((char *) &i, (char *) lon, + sizeof (int)); + if (i > 1 || i < 0) + return -EINVAL; + if (i == 1) { + u16 CMVMSG[MSG_LENGTH]; + u16 data = 0; + makeCMV (H2D_CMV_WRITE, INFO, 94, 0, 1, &data, CMVMSG); // set tx power to 0 + meierr = mei_ioctl ((struct inode *) 0, NULL, + IFXMIPS_MEI_CMV_WINHOST, + (unsigned long) CMVMSG); + } + quiet_mode_flag = i; + break; + case SHOWTIME_LOCK_GET: + copy_to_user ((char *) lon, + (char *) &showtime_lock_flag, + sizeof (int)); + break; + case SHOWTIME_LOCK_SET: + copy_from_user ((char *) &i, (char *) lon, + sizeof (int)); + if (i > 1 || i < 0) + return -EINVAL; + showtime_lock_flag = i; + break; + case AUTOBOOT_ENABLE_SET: + copy_from_user ((char *) &i, (char *) lon, + sizeof (int)); + if (i > 1 || i < 0) + return -EINVAL; + autoboot_enable_flag = i; + break; + default: + printk + ("The ioctl command(0x%X is not supported!\n", + command); + meierr = -ENOIOCTLCMD; + } + } + return meierr; +} //mei_ioctl + +//////////////////// procfs debug /////////////////////////// + +#ifdef CONFIG_PROC_FS +static int +proc_read (struct file *file, char *buf, size_t nbytes, loff_t * ppos) +{ + int i_ino = (file->f_dentry->d_inode)->i_ino; + char outputbuf[64]; + int count = 0; + int i; + u32 version = 0; + reg_entry_t *current_reg = NULL; + u16 RxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + u16 TxMessage[MSG_LENGTH] __attribute__ ((aligned (4))); + + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + if (regs[i].low_ino == i_ino) { + current_reg = ®s[i]; + break; + } + } + if (current_reg == NULL) + return -EINVAL; + + if (current_reg->flag == (int *) 8) { + ///proc/mei/version + //format: + //Firmware version: major.minor.sub_version.int_version.rel_state.spl_appl + ///Firmware Date Time Code: date/month min:hour + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; // indicates end of file + if (MEI_MUTEX_LOCK (mei_sema)) + return -ERESTARTSYS; + + if (indicator_count < 1) { + MEI_MUTEX_UNLOCK (mei_sema); + return -EAGAIN; + } + //major:bits 0-7 + //minor:bits 8-15 + makeCMV (H2D_CMV_READ, INFO, 54, 0, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { + MEI_MUTEX_UNLOCK (mei_sema); + return -EIO; + } + version = RxMessage[4]; + count = sprintf (outputbuf, "%d.%d.", (version) & 0xff, + (version >> 8) & 0xff); + + //sub_version:bits 4-7 + //int_version:bits 0-3 + //spl_appl:bits 8-13 + //rel_state:bits 14-15 + makeCMV (H2D_CMV_READ, INFO, 54, 1, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { + MEI_MUTEX_UNLOCK (mei_sema); + return -EFAULT; + } + version = RxMessage[4]; + count += sprintf (outputbuf + count, "%d.%d.%d.%d", + (version >> 4) & 0xf, + version & 0xf, + (version >> 14) & 0x3, + (version >> 8) & 0x3f); + //Date:bits 0-7 + //Month:bits 8-15 + makeCMV (H2D_CMV_READ, INFO, 55, 0, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { + MEI_MUTEX_UNLOCK (mei_sema); + return -EIO; + } + version = RxMessage[4]; + + //Hour:bits 0-7 + //Minute:bits 8-15 + makeCMV (H2D_CMV_READ, INFO, 55, 1, 1, NULL, TxMessage); + if (meiCMV (TxMessage, YES_REPLY, RxMessage) != MEI_SUCCESS) { + MEI_MUTEX_UNLOCK (mei_sema); + return -EFAULT; + } + version += (RxMessage[4] << 16); + count += sprintf (outputbuf + count, " %d/%d %d:%d\n", + version & 0xff, (version >> 8) & 0xff, + (version >> 25) & 0xff, + (version >> 16) & 0xff); + MEI_MUTEX_UNLOCK (mei_sema); + + *ppos += count; + } + else if (current_reg->flag != (int *) Recent_indicator) { + if (*ppos > 0) /* Assume reading completed in previous read */ + return 0; // indicates end of file + count = sprintf (outputbuf, "0x%08X\n\n", + *(current_reg->flag)); + *ppos += count; + if (count > nbytes) /* Assume output can be read at one time */ + return -EINVAL; + } + else { + if ((int) (*ppos) / ((int) 7) == 16) + return 0; // indicate end of the message + count = sprintf (outputbuf, "0x%04X\n\n", + *(((u16 *) (current_reg->flag)) + + (int) (*ppos) / ((int) 7))); + *ppos += count; + } + if (copy_to_user (buf, outputbuf, count)) + return -EFAULT; + return count; +} + +static ssize_t +proc_write (struct file *file, const char *buffer, size_t count, + loff_t * ppos) +{ + int i_ino = (file->f_dentry->d_inode)->i_ino; + reg_entry_t *current_reg = NULL; + int i; + unsigned long newRegValue; + char *endp; + + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + if (regs[i].low_ino == i_ino) { + current_reg = ®s[i]; + break; + } + } + if ((current_reg == NULL) + || (current_reg->flag == (int *) Recent_indicator)) + return -EINVAL; + + newRegValue = simple_strtoul (buffer, &endp, 0); + *(current_reg->flag) = (int) newRegValue; + return (count + endp - buffer); +} +#endif //CONFIG_PROC_FS + +//TODO, for loopback test +#ifdef DFE_LOOPBACK +#define mte_reg_base (0x4800*4+0x20000) + +/* Iridia Registers Address Constants */ +#define MTE_Reg(r) (int)(mte_reg_base + (r*4)) + +#define IT_AMODE MTE_Reg(0x0004) + +#define OMBOX_BASE 0xDF80 +#define OMBOX1 (OMBOX_BASE+0x4) +#define IMBOX_BASE 0xDFC0 + +#define TIMER_DELAY (1024) +#define BC0_BYTES (32) +#define BC1_BYTES (30) +#define NUM_MB (12) +#define TIMEOUT_VALUE 2000 + +static void +BFMWait (u32 cycle) +{ + u32 i; + for (i = 0; i < cycle; i++); +} + +static void +WriteRegLong (u32 addr, u32 data) +{ + //*((volatile u32 *)(addr)) = data; + IFXMIPS_WRITE_REGISTER_L (data, addr); +} + +static u32 +ReadRegLong (u32 addr) +{ + // u32 rd_val; + //rd_val = *((volatile u32 *)(addr)); + // return rd_val; + return IFXMIPS_READ_REGISTER_L (addr); +} + +/* This routine writes the mailbox with the data in an input array */ +static void +WriteMbox (u32 * mboxarray, u32 size) +{ + meiDebugWrite (IMBOX_BASE, mboxarray, size); + printk ("write to %X\n", IMBOX_BASE); + meiLongwordWrite ( MEI_TO_ARC_INT, MEI_TO_ARC_MSGAV); +} + +/* This routine reads the output mailbox and places the results into an array */ +static void +ReadMbox (u32 * mboxarray, u32 size) +{ + meiDebugRead (OMBOX_BASE, mboxarray, size); + printk ("read from %X\n", OMBOX_BASE); +} + +static void +MEIWriteARCValue (u32 address, u32 value) +{ + u32 i, check = 0; + + /* Write address register */ + IFXMIPS_WRITE_REGISTER_L (address, MEI_DEBUG_WAD); + + /* Write data register */ + IFXMIPS_WRITE_REGISTER_L (value, MEI_DEBUG_DATA); + + /* wait until complete - timeout at 40 */ + for (i = 0; i < 40; i++) { + check = IFXMIPS_READ_REGISTER_L (ARC_TO_MEI_INT); + + if ((check & ARC_TO_MEI_DBG_DONE)) + break; + } + /* clear the flag */ + IFXMIPS_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ARC_TO_MEI_INT); +} + +void +arc_code_page_download (uint32_t arc_code_length, uint32_t * start_address) +{ + int count; + printk ("try to download pages,size=%d\n", arc_code_length); + meiControlModeSwitch (MEI_MASTER_MODE); + if (arc_halt_flag == 0) { + meiHaltArc (); + } + meiLongwordWrite ( MEI_XFR_ADDR, 0); + for (count = 0; count < arc_code_length; count++) { + meiLongwordWrite ( MEI_DATA_XFR, + *(start_address + count)); + } + meiControlModeSwitch (JTAG_MASTER_MODE); +} +static int +load_jump_table (unsigned long addr) +{ + int i; + uint32_t addr_le, addr_be; + uint32_t jump_table[32]; + for (i = 0; i < 16; i++) { + addr_le = i * 8 + addr; + addr_be = ((addr_le >> 16) & 0xffff); + addr_be |= ((addr_le & 0xffff) << 16); + jump_table[i * 2 + 0] = 0x0f802020; + jump_table[i * 2 + 1] = addr_be; + //printk("jt %X %08X %08X\n",i,jump_table[i*2+0],jump_table[i*2+1]); + } + arc_code_page_download (32, &jump_table[0]); + return 0; +} + +void +dfe_loopback_irq_handler (void) +{ + uint32_t rd_mbox[10]; + + memset (&rd_mbox[0], 0, 10 * 4); + ReadMbox (&rd_mbox[0], 6); + if (rd_mbox[0] == 0x0) { + printk ("Get ARC_ACK\n"); + got_int = 1; + } + else if (rd_mbox[0] == 0x5) { + printk ("Get ARC_BUSY\n"); + got_int = 2; + } + else if (rd_mbox[0] == 0x3) { + printk ("Get ARC_EDONE\n"); + if (rd_mbox[1] == 0x0) { + got_int = 3; + printk ("Get E_MEMTEST\n"); + if (rd_mbox[2] != 0x1) { + got_int = 4; + printk ("Get Result %X\n", + rd_mbox[2]); + } + } + } + meiLongwordWrite ( ARC_TO_MEI_INT, ARC_TO_MEI_DBG_DONE); + MEI_MASK_AND_ACK_IRQ (IFXMIPS_MEI_INT); + disable_irq (IFXMIPS_MEI_INT); + //got_int = 1; + return; +} + +static void +wait_mem_test_result (void) +{ + uint32_t mbox[5]; + mbox[0] = 0; + printk ("Waiting Starting\n"); + while (mbox[0] == 0) { + ReadMbox (&mbox[0], 5); + } + printk ("Try to get mem test result.\n"); + ReadMbox (&mbox[0], 5); + if (mbox[0] == 0xA) { + printk ("Success.\n"); + } + else if (mbox[0] == 0xA) { + printk + ("Fail,address %X,except data %X,receive data %X\n", + mbox[1], mbox[2], mbox[3]); + } + else { + printk ("Fail\n"); + } +} + +static int +arc_ping_testing (void) +{ +#define MEI_PING 0x00000001 + uint32_t wr_mbox[10], rd_mbox[10]; + int i; + for (i = 0; i < 10; i++) { + wr_mbox[i] = 0; + rd_mbox[i] = 0; + } + + printk ("send ping msg\n"); + wr_mbox[0] = MEI_PING; + WriteMbox (&wr_mbox[0], 10); + + while (got_int == 0) { + MEI_WAIT (100); + } + + printk ("send start event\n"); + got_int = 0; + + wr_mbox[0] = 0x4; + wr_mbox[1] = 0; + wr_mbox[2] = 0; + wr_mbox[3] = (uint32_t) 0xf5acc307e; + wr_mbox[4] = 5; + wr_mbox[5] = 2; + wr_mbox[6] = 0x1c000; + wr_mbox[7] = 64; + wr_mbox[8] = 0; + wr_mbox[9] = 0; + WriteMbox (&wr_mbox[0], 10); + enable_irq (IFXMIPS_MEI_INT); + //printk("meiMailboxWrite ret=%d\n",i); + meiLongwordWrite ( MEI_TO_ARC_INT, MEI_TO_ARC_MSGAV); + printk ("sleeping\n"); + while (1) { + if (got_int > 0) { + + if (got_int > 3) + printk ("got_int >>>> 3\n"); + else + printk ("got int = %d\n", got_int); + got_int = 0; + //schedule(); + enable_irq (IFXMIPS_MEI_INT); + } + //mbox_read(&rd_mbox[0],6); + MEI_WAIT (100); + } +} + +static MEI_ERROR +DFE_Loopback_Test (void) +{ + int i = 0; + u32 arc_debug_data = 0, temp; + + meiResetARC (); + // start the clock + arc_debug_data = ACL_CLK_MODE_ENABLE; + meiDebugWrite (CRI_CCR0, &arc_debug_data, 1); + +#if defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK) + // WriteARCreg(AUX_XMEM_LTEST,0); + meiControlModeSwitch (MEI_MASTER_MODE); +#define AUX_XMEM_LTEST 0x128 + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, AUX_XMEM_LTEST, 0); + meiControlModeSwitch (JTAG_MASTER_MODE); + + // WriteARCreg(AUX_XDMA_GAP,0); + meiControlModeSwitch (MEI_MASTER_MODE); +#define AUX_XDMA_GAP 0x114 + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, AUX_XDMA_GAP, 0); + meiControlModeSwitch (JTAG_MASTER_MODE); + + meiControlModeSwitch (MEI_MASTER_MODE); + temp = 0; + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, + (u32) MEI_XDATA_BASE_SH, temp); + meiControlModeSwitch (JTAG_MASTER_MODE); + + i = alloc_processor_memory (SDRAM_SEGMENT_SIZE * 16, adsl_mem_info); + if (i >= 0) { + int idx; + + for (idx = 0; idx < i; idx++) { + adsl_mem_info[idx].type = FREE_RELOAD; + IFXMIPS_WRITE_REGISTER_L ((((uint32_t) + adsl_mem_info[idx]. + address) & 0x0fffffff), + MEI_XMEM_BAR_BASE + idx * 4); + printk ("bar%d(%X)=%X\n", idx, + MEI_XMEM_BAR_BASE + idx * 4, + (((uint32_t) adsl_mem_info[idx]. + address) & 0x0fffffff)); + memset ((u8 *) adsl_mem_info[idx].address, 0, + SDRAM_SEGMENT_SIZE); + } + + meiLongwordWrite ( MEI_XDATA_BASE_SH, ((unsigned long) + adsl_mem_info + [XDATA_REGISTER]. + address) & + 0x0FFFFFFF); + + } + else { + printk ("cannot load image: no memory\n\n"); + return MEI_FAILURE; + } + //WriteARCreg(AUX_IC_CTRL,2); + meiControlModeSwitch (MEI_MASTER_MODE); +#define AUX_IC_CTRL 0x11 + _meiDebugLongWordWrite (MEI_DEBUG_DEC_AUX_MASK, AUX_IC_CTRL, 2); + meiControlModeSwitch (JTAG_MASTER_MODE); + + meiHaltArc (); + +#ifdef DFE_PING_TEST + + printk ("ping test image size=%d\n", sizeof (code_array)); + memcpy ((u8 *) (adsl_mem_info[0].address + 0x1004), &code_array[0], + sizeof (code_array)); + load_jump_table (0x80000 + 0x1004); + +#endif //DFE_PING_TEST + + printk ("ARC ping test code download complete\n"); +#endif //defined( DFE_PING_TEST )|| defined( DFE_ATM_LOOPBACK) +#ifdef DFE_MEM_TEST + meiLongwordWrite (ARC_TO_MEI_INT_MASK, MSGAV_EN); + + arc_code_page_download (1537, &mem_test_code_array[0]); + printk ("ARC mem test code download complete\n"); +#endif //DFE_MEM_TEST +#ifdef DFE_ATM_LOOPBACK + arc_debug_data = 0xf; + arc_code_page_download (1077, &code_array[0]); + // Start Iridia IT_AMODE (in dmp access) why is it required? + meiDebugWrite (0x32010, &arc_debug_data, 1); +#endif //DFE_ATM_LOOPBACK + meiMailboxInterruptsEnable (); + meiRunArc (); + +#ifdef DFE_PING_TEST + arc_ping_testing (); +#endif //DFE_PING_TEST +#ifdef DFE_MEM_TEST + wait_mem_test_result (); +#endif //DFE_MEM_TEST + + free_image_buffer (FREE_ALL); + return MEI_SUCCESS; +} + +#endif //DFE_LOOPBACK +//end of TODO, for loopback test + +#if defined(CONFIG_IFXMIPS_MEI_LED) && defined(DATA_LED_SUPPORT) + +/* + * Led Thread Main function + */ +static int +led_poll (void *unused) +{ + struct task_struct *tsk = current; + + daemonize("mei_led_poll"); + strcpy (tsk->comm, "atm_led"); + sigfillset (&tsk->blocked); + + stop_led_module = 0; //begin polling ... + + while (!stop_led_module) { + if (led_status_on || led_need_to_flash) { + adsl_led_flash_task (); + } + if (led_status_on) //sleep 200 ms to check if need to turn led off + { + interruptible_sleep_on_timeout + (&wait_queue_led_polling, 25); + } + else { + interruptible_sleep_on (&wait_queue_led_polling); + } + } + return 0; +} + +/* + * API for atm driver to notify led thread a data coming/sending + */ +#if defined (CONFIG_ATM_IFXMIPS) +static int +adsl_led_flash (void) +{ + if (!modem_ready) + return 0; + + if (led_status_on == 0 && led_need_to_flash == 0) + { + wake_up_interruptible (&wait_queue_led_polling); //wake up and clean led module + } + led_need_to_flash = 1; //asking to flash led + + return 0; +} +#endif +/* + * Main task for led controlling. + */ +static int +adsl_led_flash_task (void) +{ +#ifdef DATA_LED_ADSL_FW_HANDLE + u16 one = 1; + u16 zero = 0; + u16 data = 0x0600; + u16 CMVMSG[MSG_LENGTH]; +#endif + +// printk("Task Running...\n"); //joelin test + + if (!showtime) { + led_need_to_flash = 0; + led_status_on = 0; + return 0; + } + + if (led_status_on == 0 && led_need_to_flash == 1) { + +#ifdef DATA_LED_ADSL_FW_HANDLE + data = 0x0901; //flash + send_cmv (H2D_CMV_WRITE, INFO, 91, 5, 1, &data, CMVMSG); //use GPIO9 for TR68 data led .flash. +#else + ifxmips_led_blink_set(0x0); // data + ifxmips_led_blink_set(0x1); // link +#endif + led_status_on = 1; + + } + else if (led_status_on == 1 && led_need_to_flash == 0) { +#ifdef DATA_LED_ADSL_FW_HANDLE +#ifdef DATA_LED_ON_MODE + data = 0x0903; //use GPIO9 for TR68 data led .turn on. +#else + data = 0x0900; //off +#endif + printk ("off %04X\n", data); + send_cmv (H2D_CMV_WRITE, INFO, 91, 5, 1, &data, CMVMSG); //use GPIO9 for TR68 data led .off. +#else +#endif + led_status_on = 0; + } + led_need_to_flash = 0; + return 0; +} + +/* + * Led initialization function + * This function create a thread to polling atm traffic and do led blanking + */ +static int +ifxmips_mei_led_init (void) +{ + init_waitqueue_head (&wait_queue_led_polling); // adsl led for led function + kernel_thread (led_poll, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD); + return 0; +} + +/* + * Led destory function + */ +static int +ifxmips_mei_led_cleanup (void) +{ + stop_led_module = 1; //wake up and clean led module + wake_up_interruptible (&wait_queue_led_polling); //wake up and clean led module + return 0; +} +#endif //#ifdef CONFIG_IFXMIPS_MEI_LED + +//////////////////////////////////////////////////////////////////////////// +int __init +ifxmips_mei_init_module (void) +{ + struct proc_dir_entry *entry; + int i; + u32 temp; +#ifdef CONFIG_DEVFS_FS + char buf[10]; +#endif + reg_entry_t regs_temp[PROC_ITEMS] = // Items being debugged + { + /* { flag, name, description } */ + {&arcmsgav, "arcmsgav", "arc to mei message ", 0}, + {&cmv_reply, "cmv_reply", "cmv needs reply", 0}, + {&cmv_waiting, "cmv_waiting", + "waiting for cmv reply from arc", 0}, + {&indicator_count, "indicator_count", + "ARC to MEI indicator count", 0}, + {&cmv_count, "cmv_count", "MEI to ARC CMVs", 0}, + {&reply_count, "reply_count", "ARC to MEI Reply", 0}, + {(int *) Recent_indicator, "Recent_indicator", + "most recent indicator", 0}, + {(int *) 8, "version", "version of firmware", 0}, + }; + do_gettimeofday (&time_disconnect); + + printk ("Danube MEI version:%s\n", IFXMIPS_MEI_VERSION); + + memcpy ((char *) regs, (char *) regs_temp, sizeof (regs_temp)); + MEI_MUTEX_INIT (mei_sema, 1); // semaphore initialization, mutex + MEI_INIT_WAKELIST ("arcq", wait_queue_arcmsgav); // for ARCMSGAV + MEI_INIT_WAKELIST ("arcldq", wait_queue_loop_diagnostic); // for loop diagnostic function +#ifdef IFX_ADSL_L3_MODE_SUPPORT + MEI_INIT_WAKELIST ("arcl3q", wait_queue_l3); // for l3 power mode +#endif //IFX_ADSL_L3_MODE_SUPPORT + + + memset (&adsl_mem_info[0], 0, sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS); +#if defined(CONFIG_IFXMIPS_MEI_LED) && defined(DATA_LED_SUPPORT) + printk("not enabling mei leds due to bug that makes the board hang\n"); +// ifxmips_mei_led_init (); +#endif + +#ifdef CONFIG_IFXMIPS_MEI_MIB + ifxmips_mei_mib_init (); +#endif + +#ifdef IFXMIPS_CLEAR_EOC + MEI_INIT_WAKELIST ("arceoc", wait_queue_hdlc_poll); + ifxmips_mei_ceoc_init (); +#endif + // power up mei + temp = ifxmips_r32(IFXMIPS_PMU_PWDCR); + temp &= 0xffff7dbe; + ifxmips_w32(temp, IFXMIPS_PMU_PWDCR); + +#if defined (CONFIG_ATM_IFXMIPS) + IFX_ATM_LED_Callback_Register (adsl_led_flash); +#endif + if (register_chrdev (major, IFXMIPS_MEI_DEVNAME, &mei_operations) != 0) { + printk("\n\n unable to register major for ifxmips_mei!!!"); + return -ENODEV; + } else { + printk("registered ifxmips_mei on #%d\n", major); + } + + disable_irq(IFXMIPS_MEI_INT); + + if (request_irq(IFXMIPS_MEI_INT, mei_interrupt_arcmsgav, 0, "ifxmips_mei_arcmsgav", NULL) != 0) { + printk("\n\n unable to register irq(%d) for ifxmips_mei!!!", + IFXMIPS_MEI_INT); + return -1; + } + +// enable_irq(IFXMIPS_MEI_INT); + // procfs + meidir = proc_mkdir(MEI_DIRNAME, &proc_root); + if (meidir == NULL) + { + printk(": can't create /proc/" MEI_DIRNAME "\n\n"); + return -ENOMEM; + } + + for (i = 0; i < NUM_OF_REG_ENTRY; i++) { + entry = create_proc_entry (regs[i].name, + S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH, meidir); + if (entry) + { + regs[i].low_ino = entry->low_ino; + entry->proc_fops = &proc_operations; + } else { + printk (": can't create /proc/" MEI_DIRNAME "/%s\n\n", regs[i].name); + return -ENOMEM; + } + } + + ///////////////////////////////// register net device //////////////////////////// +#ifdef DFE_LOOPBACK + DFE_Loopback_Test (); +#endif //DFE_LOOPBACK + return 0; +} + +void __exit +ifxmips_mei_cleanup_module (void) +{ + int i; + +#if defined(CONFIG_IFXMIPS_MEI_LED) && defined(DATA_LED_SUPPORT) + ifxmips_mei_led_cleanup (); +#endif + showtime = 0; //joelin,clear task + +#ifdef CONFIG_PROC_FS + for (i = 0; i < NUM_OF_REG_ENTRY; i++) + remove_proc_entry (regs[i].name, meidir); + + remove_proc_entry (MEI_DIRNAME, &proc_root); +#endif //CONFIG_PROC_FS + +#if defined (CONFIG_ATM_IFXMIPS) + IFX_ATM_LED_Callback_Unregister (adsl_led_flash); +#endif + disable_irq (IFXMIPS_MEI_INT); + free_irq(IFXMIPS_MEI_INT, NULL); + +#ifdef CONFIG_DEVFS_FS + devfs_unregister (mei_devfs_handle); +#else + unregister_chrdev (major, "ifxmips_mei"); +#endif +#ifdef CONFIG_IFXMIPS_MEI_MIB + ifxmips_mei_mib_cleanup (); +#endif + + free_image_buffer (FREE_ALL); + return; +} + +EXPORT_SYMBOL (meiDebugRead); +EXPORT_SYMBOL (meiDebugWrite); +EXPORT_SYMBOL (ifx_me_hdlc_send); +EXPORT_SYMBOL (ifx_mei_hdlc_read); +MODULE_LICENSE ("GPL"); + +module_init (ifxmips_mei_init_module); +module_exit (ifxmips_mei_cleanup_module); diff --git a/target/linux/ifxmips/files/drivers/char/ifxmips_ssc.c b/target/linux/ifxmips/files/drivers/char/ifxmips_ssc.c new file mode 100644 index 0000000000..35b32e8529 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/char/ifxmips_ssc.c @@ -0,0 +1,1417 @@ +/* + * 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. + * + * Copyright (C) 2006 infineon + * Copyright (C) 2007 John Crispin + * + */ + +// ### TO DO: general issues: +// - power management +// - interrupt handling (direct/indirect) +// - pin/mux-handling (just overall concept due to project dependency) +// - multiple instances capability +// - slave functionality + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* allow the user to set the major device number */ +static int maj = 0; + +/* + * This is the per-channel data structure containing pointers, flags + * and variables for the port. This driver supports a maximum of PORT_CNT. + * isp is allocated in ifx_ssc_init() based on the chip version. + */ +static struct ifx_ssc_port *isp; + +/* other forward declarations */ +static unsigned int ifx_ssc_get_kernel_clk (struct ifx_ssc_port *info); +static void tx_int (struct ifx_ssc_port *); + +extern unsigned int ifxmips_get_fpi_hz (void); +extern void ifxmips_mask_and_ack_irq (unsigned int irq_nr); + +static inline unsigned int +ifx_ssc_get_kernel_clk (struct ifx_ssc_port *info) +{ + unsigned int rmc; + + rmc = (ifxmips_r32(IFXMIPS_SSC_CLC) & IFX_CLC_RUN_DIVIDER_MASK) >> IFX_CLC_RUN_DIVIDER_OFFSET; + if (rmc == 0) + { + printk ("ifx_ssc_get_kernel_clk rmc==0 \n"); + return 0; + } + return ifxmips_get_fpi_hz () / rmc; +} + +inline static void +rx_int (struct ifx_ssc_port *info) +{ + int fifo_fill_lev, bytes_in_buf, i; + unsigned long tmp_val; + unsigned long *tmp_ptr; + unsigned int rx_valid_cnt; + /* number of words waiting in the RX FIFO */ + fifo_fill_lev = (ifxmips_r32(IFXMIPS_SSC_FSTAT) & IFX_SSC_FSTAT_RECEIVED_WORDS_MASK) >> IFX_SSC_FSTAT_RECEIVED_WORDS_OFFSET; + bytes_in_buf = info->rxbuf_end - info->rxbuf_ptr; + // transfer with 32 bits per entry + while ((bytes_in_buf >= 4) && (fifo_fill_lev > 0)) { + tmp_ptr = (unsigned long *) info->rxbuf_ptr; + *tmp_ptr = ifxmips_r32(IFXMIPS_SSC_RB); + info->rxbuf_ptr += 4; + info->stats.rxBytes += 4; + fifo_fill_lev--; + bytes_in_buf -= 4; + } + + // now do the rest as mentioned in STATE.RXBV + while ((bytes_in_buf > 0) && (fifo_fill_lev > 0)) { + rx_valid_cnt = (ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_RX_BYTE_VALID_MASK) >> IFX_SSC_STATE_RX_BYTE_VALID_OFFSET; + if (rx_valid_cnt == 0) + break; + + if (rx_valid_cnt > bytes_in_buf) + rx_valid_cnt = bytes_in_buf; + + tmp_val = ifxmips_r32(IFXMIPS_SSC_RB); + + for (i = 0; i < rx_valid_cnt; i++) + { + *info->rxbuf_ptr = (tmp_val >> (8 * (rx_valid_cnt - i - 1))) & 0xff; + bytes_in_buf--; + info->rxbuf_ptr++; + } + info->stats.rxBytes += rx_valid_cnt; + } + + // check if transfer is complete + if (info->rxbuf_ptr >= info->rxbuf_end) + { + disable_irq(IFXMIPS_SSC_RIR); + wake_up_interruptible (&info->rwait); + } else if ((info->opts.modeRxTx == IFX_SSC_MODE_RX) && (ifxmips_r32(IFXMIPS_SSC_RXCNT) == 0)) + { + if (info->rxbuf_end - info->rxbuf_ptr < IFX_SSC_RXREQ_BLOCK_SIZE) + ifxmips_w32((info->rxbuf_end - info->rxbuf_ptr) << IFX_SSC_RXREQ_RXCOUNT_OFFSET, IFXMIPS_SSC_RXREQ); + else + ifxmips_w32(IFX_SSC_RXREQ_BLOCK_SIZE << IFX_SSC_RXREQ_RXCOUNT_OFFSET, IFXMIPS_SSC_RXREQ); + } +} + +inline static void +tx_int (struct ifx_ssc_port *info) +{ + + int fifo_space, fill, i; + fifo_space = ((ifxmips_r32(IFXMIPS_SSC_ID) & IFX_SSC_PERID_TXFS_MASK) >> IFX_SSC_PERID_TXFS_OFFSET) + - ((ifxmips_r32(IFXMIPS_SSC_FSTAT) & IFX_SSC_FSTAT_TRANSMIT_WORDS_MASK) >> IFX_SSC_FSTAT_TRANSMIT_WORDS_OFFSET); + + if (fifo_space == 0) + return; + + fill = info->txbuf_end - info->txbuf_ptr; + + if (fill > fifo_space * 4) + fill = fifo_space * 4; + + for (i = 0; i < fill / 4; i++) + { + // at first 32 bit access + ifxmips_w32(*(UINT32 *) info->txbuf_ptr, IFXMIPS_SSC_TB); + info->txbuf_ptr += 4; + } + + fifo_space -= fill / 4; + info->stats.txBytes += fill & ~0x3; + fill &= 0x3; + if ((fifo_space > 0) & (fill > 1)) + { + // trailing 16 bit access + WRITE_PERIPHERAL_REGISTER_16 (*(UINT16 *) info->txbuf_ptr, info->mapbase + IFX_SSC_TB); + info->txbuf_ptr += 2; + info->stats.txBytes += 2; + fifo_space--; + fill -= 2; + } + + if ((fifo_space > 0) & (fill > 0)) + { + // trailing 8 bit access + WRITE_PERIPHERAL_REGISTER_8 (*(UINT8 *) info->txbuf_ptr, info->mapbase + IFX_SSC_TB); + info->txbuf_ptr++; + info->stats.txBytes++; + } + + // check if transmission complete + if (info->txbuf_ptr >= info->txbuf_end) + { + disable_irq(IFXMIPS_SSC_TIR); + kfree (info->txbuf); + info->txbuf = NULL; + } + +} + +irqreturn_t +ifx_ssc_rx_int (int irq, void *dev_id) +{ + struct ifx_ssc_port *info = (struct ifx_ssc_port *) dev_id; + rx_int (info); + + return IRQ_HANDLED; +} + +irqreturn_t +ifx_ssc_tx_int (int irq, void *dev_id) +{ + struct ifx_ssc_port *info = (struct ifx_ssc_port *) dev_id; + tx_int (info); + + return IRQ_HANDLED; +} + +irqreturn_t +ifx_ssc_err_int (int irq, void *dev_id) +{ + struct ifx_ssc_port *info = (struct ifx_ssc_port *) dev_id; + unsigned int state; + unsigned int write_back = 0; + unsigned long flags; + + local_irq_save (flags); + state = ifxmips_r32(IFXMIPS_SSC_STATE); + + if ((state & IFX_SSC_STATE_RX_UFL) != 0) { + info->stats.rxUnErr++; + write_back |= IFX_SSC_WHBSTATE_CLR_RX_UFL_ERROR; + } + + if ((state & IFX_SSC_STATE_RX_OFL) != 0) { + info->stats.rxOvErr++; + write_back |= IFX_SSC_WHBSTATE_CLR_RX_OFL_ERROR; + } + + if ((state & IFX_SSC_STATE_TX_OFL) != 0) { + info->stats.txOvErr++; + write_back |= IFX_SSC_WHBSTATE_CLR_TX_OFL_ERROR; + } + + if ((state & IFX_SSC_STATE_TX_UFL) != 0) { + info->stats.txUnErr++; + write_back |= IFX_SSC_WHBSTATE_CLR_TX_UFL_ERROR; + } + + if ((state & IFX_SSC_STATE_MODE_ERR) != 0) { + info->stats.modeErr++; + write_back |= IFX_SSC_WHBSTATE_CLR_MODE_ERROR; + } + + if (write_back) + ifxmips_w32(write_back, IFXMIPS_SSC_WHBSTATE); + + local_irq_restore (flags); + + return IRQ_HANDLED; +} + +static void +ifx_ssc_abort (struct ifx_ssc_port *info) +{ + unsigned long flags; + bool enabled; + + local_irq_save (flags); + + disable_irq(IFXMIPS_SSC_RIR); + disable_irq(IFXMIPS_SSC_TIR); + disable_irq(IFXMIPS_SSC_EIR); + + local_irq_restore (flags); + + // disable SSC (also aborts a receive request!) + // ### TO DO: Perhaps it's better to abort after the receiption of a + // complete word. The disable cuts the transmission immediatly and + // releases the chip selects. This could result in unpredictable + // behavior of connected external devices! + enabled = (ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_IS_ENABLED) != 0; + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE, IFXMIPS_SSC_WHBSTATE); + + // flush fifos + ifxmips_w32(IFX_SSC_XFCON_FIFO_FLUSH, IFXMIPS_SSC_TXFCON); + ifxmips_w32(IFX_SSC_XFCON_FIFO_FLUSH, IFXMIPS_SSC_RXFCON); + + // free txbuf + if (info->txbuf != NULL) + { + kfree (info->txbuf); + info->txbuf = NULL; + } + + // wakeup read process + if (info->rxbuf != NULL) + wake_up_interruptible (&info->rwait); + + // clear pending int's + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_RIR); + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_TIR); + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_EIR); + + // clear error flags + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ALL_ERROR, IFXMIPS_SSC_WHBSTATE); + + if (enabled) + ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE, IFXMIPS_SSC_WHBSTATE); + +} + +/* + * This routine is called whenever a port is opened. It enforces + * exclusive opening of a port and enables interrupts, etc. + */ +int +ifx_ssc_open (struct inode *inode, struct file *filp) +{ + struct ifx_ssc_port *info; + int line; + int from_kernel = 0; + + if ((inode == (struct inode *) 0) || (inode == (struct inode *) 1)) { + from_kernel = 1; + line = (int) inode; + } else { + line = MINOR (filp->f_dentry->d_inode->i_rdev); + } + + /* don't open more minor devices than we can support */ + if (line < 0 || line >= PORT_CNT) + return -ENXIO; + + info = &isp[line]; + + /* exclusive open */ + if (info->port_is_open != 0) + return -EBUSY; + info->port_is_open++; + + disable_irq(IFXMIPS_SSC_RIR); + disable_irq(IFXMIPS_SSC_TIR); + disable_irq(IFXMIPS_SSC_EIR); + + /* Flush and enable TX/RX FIFO */ + ifxmips_w32((IFX_SSC_DEF_TXFIFO_FL << IFX_SSC_XFCON_ITL_OFFSET) | IFX_SSC_XFCON_FIFO_FLUSH | IFX_SSC_XFCON_FIFO_ENABLE, IFXMIPS_SSC_TXFCON); + ifxmips_w32((IFX_SSC_DEF_RXFIFO_FL << IFX_SSC_XFCON_ITL_OFFSET) | IFX_SSC_XFCON_FIFO_FLUSH | IFX_SSC_XFCON_FIFO_ENABLE, IFXMIPS_SSC_RXFCON); + + /* logically flush the software FIFOs */ + info->rxbuf_ptr = 0; + info->txbuf_ptr = 0; + + /* clear all error bits */ + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ALL_ERROR, IFXMIPS_SSC_WHBSTATE); + + // clear pending interrupts + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_RIR); + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_TIR); + ifxmips_mask_and_ack_irq(IFXMIPS_SSC_EIR); + + ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE, IFXMIPS_SSC_WHBSTATE); + + return 0; +} +EXPORT_SYMBOL(ifx_ssc_open); + +int +ifx_ssc_close (struct inode *inode, struct file *filp) +{ + struct ifx_ssc_port *info; + int idx; + + if ((inode == (struct inode *) 0) || (inode == (struct inode *) 1)) + idx = (int) inode; + else + idx = MINOR (filp->f_dentry->d_inode->i_rdev); + + if (idx < 0 || idx >= PORT_CNT) + return -ENXIO; + + info = &isp[idx]; + if (!info) + return -ENXIO; + + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE, IFXMIPS_SSC_WHBSTATE); + + ifx_ssc_abort(info); + + info->port_is_open--; + + return 0; +} +EXPORT_SYMBOL(ifx_ssc_close); + +static ssize_t +ifx_ssc_read_helper_poll (struct ifx_ssc_port *info, char *buf, size_t len, int from_kernel) +{ + ssize_t ret_val; + unsigned long flags; + + if (info->opts.modeRxTx == IFX_SSC_MODE_TX) + return -EFAULT; + local_irq_save (flags); + info->rxbuf_ptr = info->rxbuf; + info->rxbuf_end = info->rxbuf + len; + local_irq_restore (flags); + /* Vinetic driver always works in IFX_SSC_MODE_RXTX */ + /* TXRX in poll mode */ + while (info->rxbuf_ptr < info->rxbuf_end) + { + if (info->txbuf_ptr < info->txbuf_end) + tx_int (info); + + rx_int (info); + }; + + ret_val = info->rxbuf_ptr - info->rxbuf; + + return ret_val; +} + +static ssize_t +ifx_ssc_read_helper (struct ifx_ssc_port *info, char *buf, size_t len, int from_kernel) +{ + ssize_t ret_val; + unsigned long flags; + DECLARE_WAITQUEUE (wait, current); + + if (info->opts.modeRxTx == IFX_SSC_MODE_TX) + return -EFAULT; + + local_irq_save (flags); + info->rxbuf_ptr = info->rxbuf; + info->rxbuf_end = info->rxbuf + len; + + if (info->opts.modeRxTx == IFX_SSC_MODE_RXTX) + { + if ((info->txbuf == NULL) || (info->txbuf != info->txbuf_ptr) || (info->txbuf_end != len + info->txbuf)) + { + local_irq_restore (flags); + printk ("IFX SSC - %s: write must be called before calling " "read in combined RX/TX!\n", __func__); + return -EFAULT; + } + + local_irq_restore(flags); + tx_int (info); + + if (info->txbuf_ptr < info->txbuf_end) + enable_irq(IFXMIPS_SSC_TIR); + + enable_irq(IFXMIPS_SSC_RIR); + } else { + local_irq_restore(flags); + if (ifxmips_r32(IFXMIPS_SSC_RXCNT) & IFX_SSC_RXCNT_TODO_MASK) + return -EBUSY; + enable_irq(IFXMIPS_SSC_RIR); + if (len < IFX_SSC_RXREQ_BLOCK_SIZE) + ifxmips_w32(len << IFX_SSC_RXREQ_RXCOUNT_OFFSET, IFXMIPS_SSC_RXREQ); + else + ifxmips_w32(IFX_SSC_RXREQ_BLOCK_SIZE << IFX_SSC_RXREQ_RXCOUNT_OFFSET, IFXMIPS_SSC_RXREQ); + } + + __add_wait_queue (&info->rwait, &wait); + set_current_state (TASK_INTERRUPTIBLE); + + do { + local_irq_save (flags); + if (info->rxbuf_ptr >= info->rxbuf_end) + break; + + local_irq_restore (flags); + + if (signal_pending (current)) + { + ret_val = -ERESTARTSYS; + goto out; + } + schedule(); + } while (1); + + ret_val = info->rxbuf_ptr - info->rxbuf; + local_irq_restore (flags); + +out: + current->state = TASK_RUNNING; + __remove_wait_queue (&info->rwait, &wait); + + return (ret_val); +} + +static ssize_t +ifx_ssc_write_helper (struct ifx_ssc_port *info, const char *buf, + size_t len, int from_kernel) +{ + if (info->opts.modeRxTx == IFX_SSC_MODE_RX) + return -EFAULT; + + info->txbuf_ptr = info->txbuf; + info->txbuf_end = len + info->txbuf; + if (info->opts.modeRxTx == IFX_SSC_MODE_TX) + { + tx_int (info); + if (info->txbuf_ptr < info->txbuf_end) + { + enable_irq(IFXMIPS_SSC_TIR); + } + } + + return len; +} + +ssize_t +ifx_ssc_kread (int port, char *kbuf, size_t len) +{ + struct ifx_ssc_port *info; + ssize_t ret_val; + + if (port < 0 || port >= PORT_CNT) + return -ENXIO; + + if (len == 0) + return 0; + + info = &isp[port]; + + if (info->rxbuf != NULL) + { + printk ("SSC device busy\n"); + return -EBUSY; + } + + info->rxbuf = kbuf; + if (info->rxbuf == NULL) + { + printk ("SSC device error\n"); + return -EINVAL; + } + + ret_val = ifx_ssc_read_helper_poll (info, kbuf, len, 1); + info->rxbuf = NULL; + + disable_irq(IFXMIPS_SSC_RIR); + + return ret_val; +} +EXPORT_SYMBOL(ifx_ssc_kread); + +ssize_t +ifx_ssc_kwrite (int port, const char *kbuf, size_t len) +{ + struct ifx_ssc_port *info; + ssize_t ret_val; + + if (port < 0 || port >= PORT_CNT) + return -ENXIO; + + if (len == 0) + return 0; + + info = &isp[port]; + + // check if transmission in progress + if (info->txbuf != NULL) + return -EBUSY; + + info->txbuf = (char *) kbuf; + + ret_val = ifx_ssc_write_helper (info, info->txbuf, len, 1); + + if (ret_val < 0) + info->txbuf = NULL; + + return ret_val; +} +EXPORT_SYMBOL(ifx_ssc_kwrite); + +static ssize_t +ifx_ssc_read (struct file *filp, char *ubuf, size_t len, loff_t * off) +{ + ssize_t ret_val; + int idx; + struct ifx_ssc_port *info; + + idx = MINOR (filp->f_dentry->d_inode->i_rdev); + info = &isp[idx]; + + if (info->rxbuf != NULL) + return -EBUSY; + + info->rxbuf = kmalloc (len + 3, GFP_KERNEL); + if (info->rxbuf == NULL) + return -ENOMEM; + + ret_val = ifx_ssc_read_helper (info, info->rxbuf, len, 0); + if (copy_to_user ((void *) ubuf, info->rxbuf, ret_val) != 0) + ret_val = -EFAULT; + + disable_irq(IFXMIPS_SSC_RIR); + + kfree (info->rxbuf); + info->rxbuf = NULL; + + return (ret_val); +} + +static ssize_t +ifx_ssc_write (struct file *filp, const char *ubuf, size_t len, loff_t * off) +{ + int idx; + struct ifx_ssc_port *info; + int ret_val; + + if (len == 0) + return (0); + + idx = MINOR (filp->f_dentry->d_inode->i_rdev); + info = &isp[idx]; + + if (info->txbuf != NULL) + return -EBUSY; + + info->txbuf = kmalloc (len + 3, GFP_KERNEL); + if (info->txbuf == NULL) + return -ENOMEM; + + ret_val = copy_from_user (info->txbuf, ubuf, len); + if (ret_val == 0) + ret_val = ifx_ssc_write_helper (info, info->txbuf, len, 0); + else + ret_val = -EFAULT; + + if (ret_val < 0) + { + kfree (info->txbuf); + info->txbuf = NULL; + } + + return (ret_val); +} + +static struct ifx_ssc_frm_status * +ifx_ssc_frm_status_get (struct ifx_ssc_port *info) +{ + unsigned long tmp; + + tmp = ifxmips_r32(IFXMIPS_SSC_SFSTAT); + info->frm_status.DataBusy = (tmp & IFX_SSC_SFSTAT_IN_DATA) > 0; + info->frm_status.PauseBusy = (tmp & IFX_SSC_SFSTAT_IN_PAUSE) > 0; + info->frm_status.DataCount = (tmp & IFX_SSC_SFSTAT_DATA_COUNT_MASK) >> IFX_SSC_SFSTAT_DATA_COUNT_OFFSET; + info->frm_status.PauseCount = (tmp & IFX_SSC_SFSTAT_PAUSE_COUNT_MASK) >> IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET; + tmp = ifxmips_r32(IFXMIPS_SSC_SFCON); + info->frm_status.EnIntAfterData = (tmp & IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE) > 0; + info->frm_status.EnIntAfterPause = (tmp & IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE) > 0; + + return &info->frm_status; +} + + +static struct ifx_ssc_frm_opts * +ifx_ssc_frm_control_get (struct ifx_ssc_port *info) +{ + unsigned long tmp; + + tmp = ifxmips_r32(IFXMIPS_SSC_SFCON); + info->frm_opts.FrameEnable = (tmp & IFX_SSC_SFCON_SF_ENABLE) > 0; + info->frm_opts.DataLength = (tmp & IFX_SSC_SFCON_DATA_LENGTH_MASK) >> IFX_SSC_SFCON_DATA_LENGTH_OFFSET; + info->frm_opts.PauseLength = (tmp & IFX_SSC_SFCON_PAUSE_LENGTH_MASK) >> IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET; + info->frm_opts.IdleData = (tmp & IFX_SSC_SFCON_PAUSE_DATA_MASK) >> IFX_SSC_SFCON_PAUSE_DATA_OFFSET; + info->frm_opts.IdleClock = (tmp & IFX_SSC_SFCON_PAUSE_CLOCK_MASK) >> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET; + info->frm_opts.StopAfterPause = (tmp & IFX_SSC_SFCON_STOP_AFTER_PAUSE) > 0; + + return &info->frm_opts; +} + +static int +ifx_ssc_frm_control_set (struct ifx_ssc_port *info) +{ + unsigned long tmp; + + if ((info->frm_opts.DataLength > IFX_SSC_SFCON_DATA_LENGTH_MAX) + || (info->frm_opts.DataLength < 1) + || (info->frm_opts.PauseLength > IFX_SSC_SFCON_PAUSE_LENGTH_MAX) + || (info->frm_opts.PauseLength < 1) + || (info->frm_opts.IdleData & ~(IFX_SSC_SFCON_PAUSE_DATA_MASK >> IFX_SSC_SFCON_PAUSE_DATA_OFFSET)) + || (info->frm_opts.IdleClock & ~(IFX_SSC_SFCON_PAUSE_CLOCK_MASK >> IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET))) + return -EINVAL; + + // read interrupt bits (they're not changed here) + tmp = ifxmips_r32(IFXMIPS_SSC_SFCON) & + (IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE | IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE); + + // set all values with respect to it's bit position (for data and pause + // length set N-1) + tmp = (info->frm_opts.DataLength - 1) << IFX_SSC_SFCON_DATA_LENGTH_OFFSET; + tmp |= (info->frm_opts.PauseLength - 1) << IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET; + tmp |= info->frm_opts.IdleData << IFX_SSC_SFCON_PAUSE_DATA_OFFSET; + tmp |= info->frm_opts.IdleClock << IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET; + tmp |= info->frm_opts.FrameEnable * IFX_SSC_SFCON_SF_ENABLE; + tmp |= info->frm_opts.StopAfterPause * IFX_SSC_SFCON_STOP_AFTER_PAUSE; + + ifxmips_w32(tmp, IFXMIPS_SSC_SFCON); + + return 0; +} + +static int +ifx_ssc_rxtx_mode_set (struct ifx_ssc_port *info, unsigned int val) +{ + unsigned long tmp; + + if (!(info) || (val & ~(IFX_SSC_MODE_MASK))) + return -EINVAL; + + if ((ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_BUSY) + || (ifxmips_r32(IFXMIPS_SSC_RXCNT) & IFX_SSC_RXCNT_TODO_MASK)) + return -EBUSY; + + tmp = (ifxmips_r32(IFXMIPS_SSC_CON) & ~(IFX_SSC_CON_RX_OFF | IFX_SSC_CON_TX_OFF)) | (val); + ifxmips_w32(tmp, IFXMIPS_SSC_SFCON); + info->opts.modeRxTx = val; + + return 0; +} + +static int +ifx_ssc_sethwopts (struct ifx_ssc_port *info) +{ + unsigned long flags, bits; + struct ifx_ssc_hwopts *opts = &info->opts; + + if ((opts->dataWidth < IFX_SSC_MIN_DATA_WIDTH) + || (opts->dataWidth > IFX_SSC_MAX_DATA_WIDTH)) + return -EINVAL; + + bits = (opts->dataWidth - 1) << IFX_SSC_CON_DATA_WIDTH_OFFSET; + bits |= IFX_SSC_CON_ENABLE_BYTE_VALID; + + if (opts->rxOvErrDetect) + bits |= IFX_SSC_CON_RX_OFL_CHECK; + if (opts->rxUndErrDetect) + bits |= IFX_SSC_CON_RX_UFL_CHECK; + if (opts->txOvErrDetect) + bits |= IFX_SSC_CON_TX_OFL_CHECK; + if (opts->txUndErrDetect) + bits |= IFX_SSC_CON_TX_UFL_CHECK; + if (opts->loopBack) + bits |= IFX_SSC_CON_LOOPBACK_MODE; + if (opts->echoMode) + bits |= IFX_SSC_CON_ECHO_MODE_ON; + if (opts->headingControl) + bits |= IFX_SSC_CON_MSB_FIRST; + if (opts->clockPhase) + bits |= IFX_SSC_CON_LATCH_THEN_SHIFT; + if (opts->clockPolarity) + bits |= IFX_SSC_CON_CLOCK_FALL; + + switch (opts->modeRxTx) + { + case IFX_SSC_MODE_TX: + bits |= IFX_SSC_CON_RX_OFF; + break; + case IFX_SSC_MODE_RX: + bits |= IFX_SSC_CON_TX_OFF; + break; + } + + local_irq_save (flags); + + ifxmips_w32(bits, IFXMIPS_SSC_CON); + ifxmips_w32((info->opts.gpoCs << IFX_SSC_GPOCON_ISCSB0_POS) | + (info->opts.gpoInv << IFX_SSC_GPOCON_INVOUT0_POS), IFXMIPS_SSC_GPOCON); + + ifxmips_w32(info->opts.gpoCs << IFX_SSC_WHBGPOSTAT_SETOUT0_POS, IFXMIPS_SSC_WHBGPOSTAT); + + //master mode + if (opts->masterSelect) + ifxmips_w32(IFX_SSC_WHBSTATE_SET_MASTER_SELECT, IFXMIPS_SSC_WHBSTATE); + else + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_MASTER_SELECT, IFXMIPS_SSC_WHBSTATE); + + // init serial framing + ifxmips_w32(0, IFXMIPS_SSC_SFCON); + /* set up the port pins */ + //check for general requirements to switch (external) pad/pin characteristics + /* TODO: P0.9 SPI_CS4, P0.10 SPI_CS5, P 0.11 SPI_CS6, because of ASC0 */ + /* p0.15 SPI_CS1(EEPROM), P0.13 SPI_CS3, */ + /* Set p0.15 to alternative 01, others to 00 (In/OUT) */ + *(IFXMIPS_GPIO_P0_DIR) = (*IFXMIPS_GPIO_P0_DIR) | (0xA000); + *(IFXMIPS_GPIO_P0_ALTSEL0) = (((*IFXMIPS_GPIO_P0_ALTSEL0) | (0x8000)) & (~(0x2000))); + *(IFXMIPS_GPIO_P0_ALTSEL1) = (((*IFXMIPS_GPIO_P0_ALTSEL1) & (~0x8000)) & (~(0x2000))); + *(IFXMIPS_GPIO_P0_OD) = (*IFXMIPS_GPIO_P0_OD) | 0xA000; + + /* p1.6 SPI_CS2(SFLASH), p1.0 SPI_DIN, p1.1 SPI_DOUT, p1.2 SPI_CLK */ + *(IFXMIPS_GPIO_P1_DIR) = ((*IFXMIPS_GPIO_P1_DIR) | (0x46)) & (~1); + *(IFXMIPS_GPIO_P1_ALTSEL0) = ((*IFXMIPS_GPIO_P1_ALTSEL0) | (0x47)); + *(IFXMIPS_GPIO_P1_ALTSEL1) = (*IFXMIPS_GPIO_P1_ALTSEL1) & (~0x47); + *(IFXMIPS_GPIO_P1_OD) = (*IFXMIPS_GPIO_P1_OD) | 0x0046; + + /*CS3 */ + /*TODO: CS4 CS5 CS6 */ + *IFXMIPS_GPIO_P0_OUT = ((*IFXMIPS_GPIO_P0_OUT) | 0x2000); + + local_irq_restore (flags); + + return 0; +} + +static int +ifx_ssc_set_baud (struct ifx_ssc_port *info, unsigned int baud) +{ + unsigned int ifx_ssc_clock; + unsigned int br; + unsigned long flags; + bool enabled; + int retval = 0; + + ifx_ssc_clock = ifx_ssc_get_kernel_clk(info); + if (ifx_ssc_clock == 0) + { + retval = -EINVAL; + goto out; + } + + local_irq_save (flags); + + enabled = (ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_IS_ENABLED); + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE, IFXMIPS_SSC_WHBSTATE); + + br = (((ifx_ssc_clock >> 1) + baud / 2) / baud) - 1; + wmb(); + + if (br > 0xffff || ((br == 0) && + ((ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_IS_MASTER) == 0))) { + local_irq_restore (flags); + printk ("%s: invalid baudrate %u\n", __func__, baud); + return -EINVAL; + } + + ifxmips_w32(br, IFXMIPS_SSC_BR); + + if (enabled) + ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE, IFXMIPS_SSC_WHBSTATE); + + local_irq_restore(flags); + +out: + return retval; +} + +static int +ifx_ssc_hwinit (struct ifx_ssc_port *info) +{ + unsigned long flags; + bool enabled; + + enabled = (ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_IS_ENABLED); + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE, IFXMIPS_SSC_WHBSTATE); + + if (ifx_ssc_sethwopts (info) < 0) + { + printk ("%s: setting the hardware options failed\n", __func__); + return -EINVAL; + } + + if (ifx_ssc_set_baud (info, info->baud) < 0) + { + printk ("%s: setting the baud rate failed\n", __func__); + return -EINVAL; + } + + local_irq_save (flags); + + /* TX FIFO */ + ifxmips_w32((IFX_SSC_DEF_TXFIFO_FL << IFX_SSC_XFCON_ITL_OFFSET) | IFX_SSC_XFCON_FIFO_ENABLE, IFXMIPS_SSC_TXFCON); + /* RX FIFO */ + ifxmips_w32((IFX_SSC_DEF_RXFIFO_FL << IFX_SSC_XFCON_ITL_OFFSET) | IFX_SSC_XFCON_FIFO_ENABLE, IFXMIPS_SSC_RXFCON); + + local_irq_restore (flags); + + if (enabled) + ifxmips_w32(IFX_SSC_WHBSTATE_SET_ENABLE, IFXMIPS_SSC_WHBSTATE); + + return 0; +} + +int +ifx_ssc_ioctl (struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data) +{ + struct ifx_ssc_port *info; + int line, ret_val = 0; + unsigned long flags; + unsigned long tmp; + int from_kernel = 0; + + if ((inode == (struct inode *) 0) || (inode == (struct inode *) 1)) + { + from_kernel = 1; + line = (int) inode; + } else { + line = MINOR (filp->f_dentry->d_inode->i_rdev); + } + + if (line < 0 || line >= PORT_CNT) + return -ENXIO; + + info = &isp[line]; + + switch (cmd) + { + case IFX_SSC_STATS_READ: + /* data must be a pointer to a struct ifx_ssc_statistics */ + if (from_kernel) + memcpy ((void *) data, (void *) &info->stats, + sizeof (struct ifx_ssc_statistics)); + else if (copy_to_user ((void *) data, + (void *) &info->stats, + sizeof (struct ifx_ssc_statistics))) + ret_val = -EFAULT; + break; + case IFX_SSC_STATS_RESET: + /* just resets the statistics counters */ + memset ((void *) &info->stats, 0, + sizeof (struct ifx_ssc_statistics)); + break; + case IFX_SSC_BAUD_SET: + /* if the buffers are not empty then the port is */ + /* busy and we shouldn't change things on-the-fly! */ + if (!info->txbuf || !info->rxbuf || + (ifxmips_r32(IFXMIPS_SSC_STATE) & IFX_SSC_STATE_BUSY)) { + ret_val = -EBUSY; + break; + } + /* misuse flags */ + if (from_kernel) + flags = *((unsigned long *) data); + else if (copy_from_user ((void *) &flags, + (void *) data, sizeof (flags))) { + ret_val = -EFAULT; + break; + } + if (flags == 0) { + ret_val = -EINVAL; + break; + } + if (ifx_ssc_set_baud (info, flags) < 0) { + ret_val = -EINVAL; + break; + } + info->baud = flags; + break; + case IFX_SSC_BAUD_GET: + if (from_kernel) + *((unsigned int *) data) = info->baud; + else if (copy_to_user ((void *) data, + (void *) &info->baud, + sizeof (unsigned long))) + ret_val = -EFAULT; + break; + case IFX_SSC_RXTX_MODE_SET: + if (from_kernel) + tmp = *((unsigned long *) data); + else if (copy_from_user ((void *) &tmp, + (void *) data, sizeof (tmp))) { + ret_val = -EFAULT; + break; + } + ret_val = ifx_ssc_rxtx_mode_set (info, tmp); + break; + case IFX_SSC_RXTX_MODE_GET: + tmp = ifxmips_r32(IFXMIPS_SSC_CON) & + (~(IFX_SSC_CON_RX_OFF | IFX_SSC_CON_TX_OFF)); + if (from_kernel) + *((unsigned int *) data) = tmp; + else if (copy_to_user ((void *) data, + (void *) &tmp, sizeof (tmp))) + ret_val = -EFAULT; + break; + + case IFX_SSC_ABORT: + ifx_ssc_abort (info); + break; + + case IFX_SSC_GPO_OUT_SET: + if (from_kernel) + tmp = *((unsigned long *) data); + else if (copy_from_user ((void *) &tmp, + (void *) data, sizeof (tmp))) { + ret_val = -EFAULT; + break; + } + if (tmp > IFX_SSC_MAX_GPO_OUT) + ret_val = -EINVAL; + else + ifxmips_w32(1 << (tmp + IFX_SSC_WHBGPOSTAT_SETOUT0_POS), + IFXMIPS_SSC_WHBGPOSTAT); + break; + case IFX_SSC_GPO_OUT_CLR: + if (from_kernel) + tmp = *((unsigned long *) data); + else if (copy_from_user ((void *) &tmp, (void *) data, sizeof (tmp))) { + ret_val = -EFAULT; + break; + } + if (tmp > IFX_SSC_MAX_GPO_OUT) + ret_val = -EINVAL; + else { + ifxmips_w32(1 << (tmp + IFX_SSC_WHBGPOSTAT_CLROUT0_POS), + IFXMIPS_SSC_WHBGPOSTAT); + } + break; + case IFX_SSC_GPO_OUT_GET: + tmp = ifxmips_r32(IFXMIPS_SSC_GPOSTAT); + if (from_kernel) + *((unsigned int *) data) = tmp; + else if (copy_to_user ((void *) data, + (void *) &tmp, sizeof (tmp))) + ret_val = -EFAULT; + break; + case IFX_SSC_FRM_STATUS_GET: + ifx_ssc_frm_status_get (info); + if (from_kernel) + memcpy ((void *) data, (void *) &info->frm_status, + sizeof (struct ifx_ssc_frm_status)); + else if (copy_to_user ((void *) data, + (void *) &info->frm_status, + sizeof (struct ifx_ssc_frm_status))) + ret_val = -EFAULT; + break; + case IFX_SSC_FRM_CONTROL_GET: + ifx_ssc_frm_control_get (info); + if (from_kernel) + memcpy ((void *) data, (void *) &info->frm_opts, + sizeof (struct ifx_ssc_frm_opts)); + else if (copy_to_user ((void *) data, + (void *) &info->frm_opts, + sizeof (struct ifx_ssc_frm_opts))) + ret_val = -EFAULT; + break; + case IFX_SSC_FRM_CONTROL_SET: + if (from_kernel) + memcpy ((void *) &info->frm_opts, (void *) data, + sizeof (struct ifx_ssc_frm_opts)); + else if (copy_to_user ((void *) &info->frm_opts, + (void *) data, + sizeof (struct ifx_ssc_frm_opts))) { + ret_val = -EFAULT; + break; + } + ret_val = ifx_ssc_frm_control_set (info); + break; + case IFX_SSC_HWOPTS_SET: + /* data must be a pointer to a struct ifx_ssc_hwopts */ + /* if the buffers are not empty then the port is */ + /* busy and we shouldn't change things on-the-fly! */ + if (!info->txbuf || !info->rxbuf || + (ifxmips_r32(IFXMIPS_SSC_STATE) + & IFX_SSC_STATE_BUSY)) { + ret_val = -EBUSY; + break; + } + if (from_kernel) + memcpy ((void *) &info->opts, (void *) data, + sizeof (struct ifx_ssc_hwopts)); + else if (copy_from_user ((void *) &info->opts, + (void *) data, sizeof(struct ifx_ssc_hwopts))) { + ret_val = -EFAULT; + break; + } + if (ifx_ssc_hwinit (info) < 0) { + ret_val = -EIO; + } + break; + case IFX_SSC_HWOPTS_GET: + /* data must be a pointer to a struct ifx_ssc_hwopts */ + if (from_kernel) + memcpy ((void *) data, (void *) &info->opts, + sizeof (struct ifx_ssc_hwopts)); + else if (copy_to_user ((void *) data, + (void *) &info->opts, + sizeof (struct ifx_ssc_hwopts))) + ret_val = -EFAULT; + break; + default: + ret_val = -ENOIOCTLCMD; + } + + return ret_val; +} +EXPORT_SYMBOL(ifx_ssc_ioctl); + +static struct file_operations ifx_ssc_fops = { + .owner = THIS_MODULE, + .read = ifx_ssc_read, + .write = ifx_ssc_write, + .ioctl = ifx_ssc_ioctl, + .open = ifx_ssc_open, + .release = ifx_ssc_close, +}; + +int __init +ifx_ssc_init (void) +{ + struct ifx_ssc_port *info; + int i, nbytes; + unsigned long flags; + int ret_val; + + ret_val = -ENOMEM; + nbytes = PORT_CNT * sizeof(struct ifx_ssc_port); + isp = (struct ifx_ssc_port*)kmalloc(nbytes, GFP_KERNEL); + + if (isp == NULL) + { + printk("%s: no memory for isp\n", __func__); + return (ret_val); + } + memset(isp, 0, nbytes); + + ret_val = -ENXIO; + if ((i = register_chrdev (maj, "ssc", &ifx_ssc_fops)) < 0) + { + printk ("Unable to register major %d for the Infineon SSC\n", maj); + if (maj == 0) + { + goto errout; + } else { + maj = 0; + if ((i = register_chrdev (maj, "ssc", &ifx_ssc_fops)) < 0) + { + printk ("Unable to register major %d for the Infineon SSC\n", maj); + goto errout; + } + } + } + + if (maj == 0) + maj = i; + + /* set default values in ifx_ssc_port */ + for (i = 0; i < PORT_CNT; i++) { + info = &isp[i]; + info->port_nr = i; + /* default values for the HwOpts */ + info->opts.AbortErrDetect = IFX_SSC_DEF_ABRT_ERR_DETECT; + info->opts.rxOvErrDetect = IFX_SSC_DEF_RO_ERR_DETECT; + info->opts.rxUndErrDetect = IFX_SSC_DEF_RU_ERR_DETECT; + info->opts.txOvErrDetect = IFX_SSC_DEF_TO_ERR_DETECT; + info->opts.txUndErrDetect = IFX_SSC_DEF_TU_ERR_DETECT; + info->opts.loopBack = IFX_SSC_DEF_LOOP_BACK; + info->opts.echoMode = IFX_SSC_DEF_ECHO_MODE; + info->opts.idleValue = IFX_SSC_DEF_IDLE_DATA; + info->opts.clockPolarity = IFX_SSC_DEF_CLOCK_POLARITY; + info->opts.clockPhase = IFX_SSC_DEF_CLOCK_PHASE; + info->opts.headingControl = IFX_SSC_DEF_HEADING_CONTROL; + info->opts.dataWidth = IFX_SSC_DEF_DATA_WIDTH; + info->opts.modeRxTx = IFX_SSC_DEF_MODE_RXTX; + info->opts.gpoCs = IFX_SSC_DEF_GPO_CS; + info->opts.gpoInv = IFX_SSC_DEF_GPO_INV; + info->opts.masterSelect = IFX_SSC_DEF_MASTERSLAVE; + info->baud = IFX_SSC_DEF_BAUDRATE; + info->rxbuf = NULL; + info->txbuf = NULL; + /* values specific to SSC1 */ + if (i == 0) { + info->mapbase = IFXMIPS_SSC_BASE_ADDR; + } + + ifxmips_w32(IFX_SSC_DEF_RMC << IFX_CLC_RUN_DIVIDER_OFFSET, IFXMIPS_SSC_CLC); + + init_waitqueue_head (&info->rwait); + + local_irq_save (flags); + + // init serial framing register + ifxmips_w32(IFX_SSC_DEF_SFCON, IFXMIPS_SSC_SFCON); + + ret_val = request_irq(IFXMIPS_SSC_TIR, ifx_ssc_tx_int, IRQF_DISABLED, "ifx_ssc_tx", info); + if (ret_val) + { + printk("%s: unable to get irq %d\n", __func__, IFXMIPS_SSC_TIR); + local_irq_restore(flags); + goto errout; + } + + ret_val = request_irq(IFXMIPS_SSC_RIR, ifx_ssc_rx_int, IRQF_DISABLED, "ifx_ssc_rx", info); + if (ret_val) + { + printk ("%s: unable to get irq %d\n", __func__, IFXMIPS_SSC_RIR); + local_irq_restore (flags); + goto irqerr; + } + + ret_val = request_irq(IFXMIPS_SSC_EIR, ifx_ssc_err_int, IRQF_DISABLED, "ifx_ssc_err", info); + if (ret_val) + { + printk ("%s: unable to get irq %d\n", __func__, IFXMIPS_SSC_EIR); + local_irq_restore (flags); + goto irqerr; + } + ifxmips_w32(IFX_SSC_DEF_IRNEN, IFXMIPS_SSC_IRN); + + //enable_irq(IFXMIPS_SSC_TIR); + //enable_irq(IFXMIPS_SSC_RIR); + //enable_irq(IFXMIPS_SSC_EIR); + + local_irq_restore (flags); + } + + for (i = 0; i < PORT_CNT; i++) { + info = &isp[i]; + if (ifx_ssc_hwinit (info) < 0) + { + printk ("%s: hardware init failed for port %d\n", __func__, i); + goto irqerr; + } + } + + + return 0; + +irqerr: + free_irq(IFXMIPS_SSC_TIR, &isp[0]); + free_irq(IFXMIPS_SSC_RIR, &isp[0]); + free_irq(IFXMIPS_SSC_EIR, &isp[0]); +errout: + kfree (isp); + return (ret_val); +} + +void +ifx_ssc_cleanup_module (void) +{ + int i; + + for (i = 0; i < PORT_CNT; i++) { + ifxmips_w32(IFX_SSC_WHBSTATE_CLR_ENABLE, IFXMIPS_SSC_WHBSTATE); + free_irq(IFXMIPS_SSC_TIR, &isp[i]); + free_irq(IFXMIPS_SSC_RIR, &isp[i]); + free_irq(IFXMIPS_SSC_EIR, &isp[i]); + } + kfree (isp); +} + +module_init(ifx_ssc_init); +module_exit(ifx_ssc_cleanup_module); + + +inline int +ifx_ssc_cs_low (u32 pin) +{ + int ret = 0; + if ((ret = ifx_ssc_ioctl ((struct inode *) 0, NULL, IFX_SSC_GPO_OUT_CLR, (unsigned long) &pin))) + printk ("clear CS %d fails\n", pin); + wmb (); + + return ret; +} +EXPORT_SYMBOL(ifx_ssc_cs_low); + +inline int +ifx_ssc_cs_high (u32 pin) +{ + int ret = 0; + if ((ret = ifx_ssc_ioctl((struct inode *) 0, NULL, IFX_SSC_GPO_OUT_SET, (unsigned long) &pin))) + printk ("set CS %d fails\n", pin); + wmb (); + + return ret; +} +EXPORT_SYMBOL(ifx_ssc_cs_high); + +static int +ssc_session (char *tx_buf, u32 tx_len, char *rx_buf, u32 rx_len) +{ + int ret = 0; + + char *ssc_tx_buf = NULL; + char *ssc_rx_buf = NULL; + int eff_size = 0; + u8 mode = 0; + + if (tx_buf == NULL && tx_len == 0 && rx_buf == NULL && rx_len == 0) { + printk ("invalid parameters\n"); + ret = -EINVAL; + goto ssc_session_exit; + } + else if (tx_buf == NULL || tx_len == 0) { + if (rx_buf != NULL && rx_len != 0) { + mode = IFX_SSC_MODE_RX; + } + else { + printk ("invalid parameters\n"); + ret = -EINVAL; + goto ssc_session_exit; + } + } + else if (rx_buf == NULL || rx_len == 0) { + if (tx_buf != NULL && tx_len != 0) { + mode = IFX_SSC_MODE_TX; + } + else { + printk ("invalid parameters\n"); + ret = -EINVAL; + goto ssc_session_exit; + } + } + else { + mode = IFX_SSC_MODE_RXTX; + } + + if (mode == IFX_SSC_MODE_RXTX) { + eff_size = tx_len + rx_len; + } + else if (mode == IFX_SSC_MODE_RX) { + eff_size = rx_len; + } + else { + eff_size = tx_len; + } + + //4 bytes alignment, required by driver + /* change by TaiCheng */ + //if (in_irq()){ + if (1) { + ssc_tx_buf = + (char *) kmalloc (sizeof (char) * + ((eff_size + 3) & (~3)), + GFP_ATOMIC); + ssc_rx_buf = + (char *) kmalloc (sizeof (char) * + ((eff_size + 3) & (~3)), + GFP_ATOMIC); + } + else { + ssc_tx_buf = + (char *) kmalloc (sizeof (char) * + ((eff_size + 3) & (~3)), + GFP_KERNEL); + ssc_rx_buf = + (char *) kmalloc (sizeof (char) * + ((eff_size + 3) & (~3)), + GFP_KERNEL); + } + if (ssc_tx_buf == NULL || ssc_rx_buf == NULL) { + printk ("no memory for size of %d\n", eff_size); + ret = -ENOMEM; + goto ssc_session_exit; + } + memset ((void *) ssc_tx_buf, 0, eff_size); + memset ((void *) ssc_rx_buf, 0, eff_size); + + if (tx_len > 0) { + memcpy (ssc_tx_buf, tx_buf, tx_len); + } + + ret = ifx_ssc_kwrite (0, ssc_tx_buf, eff_size); + + if (ret > 0) { + ssc_tx_buf = NULL; //should be freed by ifx_ssc_kwrite + } + + if (ret != eff_size) { + printk ("ifx_ssc_write return %d\n", ret); + goto ssc_session_exit; + } + ret = ifx_ssc_kread (0, ssc_rx_buf, eff_size); + if (ret != eff_size) { + printk ("ifx_ssc_read return %d\n", ret); + goto ssc_session_exit; + } + + memcpy (rx_buf, ssc_rx_buf + tx_len, rx_len); + + if (mode == IFX_SSC_MODE_TX) { + ret = tx_len; + } + else { + ret = rx_len; + } + ssc_session_exit: + + if (ssc_tx_buf != NULL) + kfree (ssc_tx_buf); + if (ssc_rx_buf != NULL) + kfree (ssc_rx_buf); + + if (ret < 0) { + printk ("ssc session fails\n"); + } + return ret; +} + +int +ifx_ssc_txrx (char *tx_buf, u32 tx_len, char *rx_buf, u32 rx_len) +{ + return ssc_session(tx_buf, tx_len, rx_buf, rx_len); +} +EXPORT_SYMBOL(ifx_ssc_txrx); + +int +ifx_ssc_tx (char *tx_buf, u32 tx_len) +{ + return ssc_session(tx_buf, tx_len, NULL, 0); +} +EXPORT_SYMBOL(ifx_ssc_tx); + +int +ifx_ssc_rx (char *rx_buf, u32 rx_len) +{ + return ssc_session(NULL, 0, rx_buf, rx_len); +} +EXPORT_SYMBOL(ifx_ssc_rx); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("ifxmips ssc driver"); + diff --git a/target/linux/ifxmips/files/drivers/leds/leds-ifxmips.c b/target/linux/ifxmips/files/drivers/leds/leds-ifxmips.c new file mode 100644 index 0000000000..090516c5ad --- /dev/null +++ b/target/linux/ifxmips/files/drivers/leds/leds-ifxmips.c @@ -0,0 +1,192 @@ +/* + * 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. + * + * Copyright (C) 2006 infineon + * Copyright (C) 2007 John Crispin + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRVNAME "ifxmips_led" + +#define IFXMIPS_LED_CLK_EDGE IFXMIPS_LED_FALLING +//#define IFXMIPS_LED_CLK_EDGE IFXMIPS_LED_RISING + +#define IFXMIPS_LED_SPEED IFXMIPS_LED_8HZ + +#define IFXMIPS_LED_GPIO_PORT 0 + +#define IFXMIPS_MAX_LED 24 + +struct ifxmips_led { + struct led_classdev cdev; + u8 bit; +}; + +void +ifxmips_led_set (unsigned int led) +{ + led &= 0xffffff; + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CPU0) | led, IFXMIPS_LED_CPU0); +} +EXPORT_SYMBOL(ifxmips_led_set); + +void +ifxmips_led_clear (unsigned int led) +{ + led = ~(led & 0xffffff); + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CPU0) & led, IFXMIPS_LED_CPU0); +} +EXPORT_SYMBOL(ifxmips_led_clear); + +void +ifxmips_led_blink_set (unsigned int led) +{ + led &= 0xffffff; + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | led, IFXMIPS_LED_CON0); +} +EXPORT_SYMBOL(ifxmips_led_blink_set); + +void +ifxmips_led_blink_clear (unsigned int led) +{ + led = ~(led & 0xffffff); + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) & led, IFXMIPS_LED_CON0); +} +EXPORT_SYMBOL(ifxmips_led_blink_clear); + +void +ifxmips_ledapi_set(struct led_classdev *led_cdev, enum led_brightness value) +{ + struct ifxmips_led *led_dev = container_of(led_cdev, struct ifxmips_led, cdev); + + if(value) + ifxmips_led_set(1 << led_dev->bit); + else + ifxmips_led_clear(1 << led_dev->bit); +} + +void +ifxmips_led_setup_gpio (void) +{ + int i = 0; + + /* we need to setup pins SH,D,ST (4,5,6) */ + for (i = 4; i < 7; i++) + { + ifxmips_port_set_altsel0(IFXMIPS_LED_GPIO_PORT, i); + ifxmips_port_clear_altsel1(IFXMIPS_LED_GPIO_PORT, i); + ifxmips_port_set_dir_out(IFXMIPS_LED_GPIO_PORT, i); + ifxmips_port_set_open_drain(IFXMIPS_LED_GPIO_PORT, i); + } +} + +static int +ifxmips_led_probe(struct platform_device *dev) +{ + int i = 0; + + ifxmips_led_setup_gpio(); + + ifxmips_w32(0, IFXMIPS_LED_AR); + ifxmips_w32(0, IFXMIPS_LED_CPU0); + ifxmips_w32(0, IFXMIPS_LED_CPU1); + ifxmips_w32(LED_CON0_SWU, IFXMIPS_LED_CON0); + ifxmips_w32(0, IFXMIPS_LED_CON1); + + /* setup the clock edge that the shift register is triggered on */ + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) & ~IFXMIPS_LED_EDGE_MASK, IFXMIPS_LED_CON0); + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | IFXMIPS_LED_CLK_EDGE, IFXMIPS_LED_CON0); + + /* per default leds 15-0 are set */ + ifxmips_w32(IFXMIPS_LED_GROUP1 | IFXMIPS_LED_GROUP0, IFXMIPS_LED_CON1); + + /* leds are update periodically by the FPID */ + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) & ~IFXMIPS_LED_UPD_MASK, IFXMIPS_LED_CON1); + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) | IFXMIPS_LED_UPD_SRC_FPI, IFXMIPS_LED_CON1); + + /* set led update speed */ + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) & ~IFXMIPS_LED_MASK, IFXMIPS_LED_CON1); + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON1) | IFXMIPS_LED_SPEED, IFXMIPS_LED_CON1); + + /* adsl 0 and 1 leds are updated by the arc */ + ifxmips_w32(ifxmips_r32(IFXMIPS_LED_CON0) | IFXMIPS_LED_ADSL_SRC, IFXMIPS_LED_CON0); + + /* per default, the leds are turned on */ + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_LED); + + for(i = 0; i < IFXMIPS_MAX_LED; i++) + { + struct ifxmips_led *tmp = kzalloc(sizeof(struct ifxmips_led), GFP_KERNEL); + tmp->cdev.brightness_set = ifxmips_ledapi_set; + tmp->cdev.name = kmalloc(sizeof("ifxmips:led:00"), GFP_KERNEL); + sprintf((char*)tmp->cdev.name, "ifxmips:led:%02d", i); + tmp->cdev.default_trigger = NULL; + tmp->bit = i; + led_classdev_register(&dev->dev, &tmp->cdev); + } + + return 0; +} + +static int +ifxmips_led_remove(struct platform_device *pdev) +{ + return 0; +} + +static struct +platform_driver ifxmips_led_driver = { + .probe = ifxmips_led_probe, + .remove = ifxmips_led_remove, + .driver = { + .name = DRVNAME, + .owner = THIS_MODULE, + }, +}; + +int __init +ifxmips_led_init (void) +{ + int ret = platform_driver_register(&ifxmips_led_driver); + if (ret) + printk(KERN_INFO "ifxmips_led: Error registering platfom driver!"); + + return ret; +} + +void __exit +ifxmips_led_exit (void) +{ + platform_driver_unregister(&ifxmips_led_driver); +} + +module_init(ifxmips_led_init); +module_exit(ifxmips_led_exit); diff --git a/target/linux/ifxmips/files/drivers/mtd/maps/ifxmips.c b/target/linux/ifxmips/files/drivers/mtd/maps/ifxmips.c new file mode 100644 index 0000000000..b3692e72a0 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/mtd/maps/ifxmips.c @@ -0,0 +1,238 @@ +/* + * 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 + * + * Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct map_info +ifxmips_map = { + .name = "ifxmips_mtd", + .bankwidth = 2, + .size = 0x400000, +}; + +static map_word +ifxmips_read16(struct map_info * map, unsigned long adr) +{ + unsigned long flags; + map_word temp; + spin_lock_irqsave(&ebu_lock, flags); + adr ^= 2; + temp.x[0] = *((__u16*)(map->virt + adr)); + spin_unlock_irqrestore(&ebu_lock, flags); + return temp; +} + +static void +ifxmips_write16(struct map_info *map, map_word d, unsigned long adr) +{ + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + adr ^= 2; + *((__u16*)(map->virt + adr)) = d.x[0]; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +void +ifxmips_copy_from(struct map_info *map, void *to, unsigned long from, ssize_t len) +{ + unsigned char *p; + unsigned char *to_8; + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + from = (unsigned long)(from + map->virt); + p = (unsigned char*) from; + to_8 = (unsigned char*) to; + while(len--) + *to_8++ = *p++; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +void +ifxmips_copy_to(struct map_info *map, unsigned long to, const void *from, ssize_t len) +{ + unsigned char *p = (unsigned char*)from; + unsigned char *to_8; + unsigned long flags; + spin_lock_irqsave(&ebu_lock, flags); + to += (unsigned long) map->virt; + to_8 = (unsigned char*)to; + while(len--) + *p++ = *to_8++; + spin_unlock_irqrestore(&ebu_lock, flags); +} + +static struct mtd_partition +ifxmips_partitions[] = { + { + name:"uboot", + offset:0x00000000, + size:0x00020000, + }, + { + name:"uboot_env", + offset:0x00020000, + size:0x00010000, + }, + { + name:"kernel", + offset:0x00030000, + size:0x0, + }, + { + name:"rootfs", + offset:0x0, + size:0x0, + }, + { + name:"board_config", + offset:0x0, + size:0x0, + }, +}; + +int +find_uImage_size(unsigned long start_offset){ + unsigned long temp; + ifxmips_copy_from(&ifxmips_map, &temp, start_offset + 12, 4); + printk(KERN_INFO "ifxmips_mtd: kernel size is %ld \n", temp + 0x40); + return temp + 0x40; +} + +int +find_brn_block(unsigned long start_offset){ + unsigned char temp[9]; + ifxmips_copy_from(&ifxmips_map, &temp, start_offset, 8); + temp[8] = '\0'; + printk(KERN_INFO "data in brn block %s\n", temp); + if(memcmp(temp, "BRN-BOOT", 8) == 0) + return 1; + else + return 0; +} + +int +detect_squashfs_partition(unsigned long start_offset){ + unsigned long temp; + ifxmips_copy_from(&ifxmips_map, &temp, start_offset, 4); + return (temp == SQUASHFS_MAGIC); +} + +static int +ifxmips_mtd_probe(struct platform_device *dev) +{ + struct mtd_info *ifxmips_mtd = NULL; + struct mtd_partition *parts = NULL; + unsigned long uimage_size; + + ifxmips_w32(0x1d7ff, IFXMIPS_EBU_BUSCON0); + + ifxmips_map.read = ifxmips_read16; + ifxmips_map.write = ifxmips_write16; + ifxmips_map.copy_from = ifxmips_copy_from; + ifxmips_map.copy_to = ifxmips_copy_to; + ifxmips_map.phys = dev->resource->start; + ifxmips_map.size = dev->resource->end - ifxmips_map.phys + 1; + ifxmips_map.virt = ioremap_nocache(ifxmips_map.phys, ifxmips_map.size); + + if(!ifxmips_map.virt) + { + printk(KERN_WARNING "ifxmips_mtd: failed to ioremap!\n"); + return -EIO; + } + + ifxmips_mtd = (struct mtd_info *) do_map_probe("cfi_probe", &ifxmips_map); + if(!ifxmips_mtd) + { + iounmap(ifxmips_map.virt); + printk(KERN_WARNING "ifxmips_mtd: probing failed\n"); + return -ENXIO; + } + + ifxmips_mtd->owner = THIS_MODULE; + uimage_size = find_uImage_size(ifxmips_partitions[2].offset); + + if(detect_squashfs_partition(ifxmips_partitions[2].offset + uimage_size)) + { + printk(KERN_INFO "ifxmips_mtd: found a squashfs following the uImage\n"); + } else { + uimage_size &= ~0xffff; + uimage_size += 0x10000; + } + + parts = &ifxmips_partitions[0]; + ifxmips_partitions[2].size = uimage_size; + ifxmips_partitions[3].offset = ifxmips_partitions[2].offset + ifxmips_partitions[2].size; + ifxmips_partitions[3].size = ((ifxmips_mtd->size >> 20) * 1024 * 1024) - ifxmips_partitions[3].offset; + if(ifxmips_has_brn_block()) + { + ifxmips_partitions[3].size -= ifxmips_mtd->erasesize; + ifxmips_partitions[4].offset = ifxmips_mtd->size - ifxmips_mtd->erasesize; + ifxmips_partitions[4].size = ifxmips_mtd->erasesize; + add_mtd_partitions(ifxmips_mtd, parts, 5); + } else { + add_mtd_partitions(ifxmips_mtd, parts, 4); + } + + printk(KERN_INFO "ifxmips_mtd: added ifxmips flash with %dMB\n", ifxmips_mtd->size >> 20); + return 0; +} + +static struct +platform_driver ifxmips_mtd_driver = { + .probe = ifxmips_mtd_probe, + .driver = { + .name = "ifxmips_mtd", + .owner = THIS_MODULE, + }, +}; + +int __init +init_ifxmips_mtd(void) +{ + int ret = platform_driver_register(&ifxmips_mtd_driver); + if(ret) + printk(KERN_INFO "ifxmips_mtd: error registering platfom driver!"); + return ret; +} + +static void __exit +cleanup_ifxmips_mtd(void) +{ + platform_driver_unregister(&ifxmips_mtd_driver); +} + +module_init(init_ifxmips_mtd); +module_exit(cleanup_ifxmips_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("MTD map driver for IFXMIPS boards"); diff --git a/target/linux/ifxmips/files/drivers/net/ifxmips_mii0.c b/target/linux/ifxmips/files/drivers/net/ifxmips_mii0.c new file mode 100644 index 0000000000..fe7f25ec2a --- /dev/null +++ b/target/linux/ifxmips/files/drivers/net/ifxmips_mii0.c @@ -0,0 +1,416 @@ +/* + * 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. + * + * Copyright (C) 2005 Wu Qi Ming + * Copyright (C) 2008 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct ifxmips_mii_priv { + struct net_device_stats stats; + struct dma_device_info *dma_device; + struct sk_buff *skb; +}; + +static struct net_device *ifxmips_mii0_dev; +static unsigned char mac_addr[MAX_ADDR_LEN]; + +void +ifxmips_write_mdio(u32 phy_addr, u32 phy_reg, u16 phy_data) +{ + u32 val = MDIO_ACC_REQUEST | + ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) | + ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET) | + phy_data; + + while(ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST); + ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC); +} +EXPORT_SYMBOL(ifxmips_write_mdio); + +unsigned short +ifxmips_read_mdio(u32 phy_addr, u32 phy_reg) +{ + u32 val = MDIO_ACC_REQUEST | MDIO_ACC_READ | + ((phy_addr & MDIO_ACC_ADDR_MASK) << MDIO_ACC_ADDR_OFFSET) | + ((phy_reg & MDIO_ACC_REG_MASK) << MDIO_ACC_REG_OFFSET); + + while(ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST); + ifxmips_w32(val, IFXMIPS_PPE32_MDIO_ACC); + while(ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_REQUEST){}; + val = ifxmips_r32(IFXMIPS_PPE32_MDIO_ACC) & MDIO_ACC_VAL_MASK; + return val; +} +EXPORT_SYMBOL(ifxmips_read_mdio); + +int +ifxmips_ifxmips_mii_open(struct net_device *dev) +{ + struct ifxmips_mii_priv* priv = (struct ifxmips_mii_priv*)dev->priv; + struct dma_device_info* dma_dev = priv->dma_device; + int i; + + for(i = 0; i < dma_dev->max_rx_chan_num; i++) + { + if((dma_dev->rx_chan[i])->control == IFXMIPS_DMA_CH_ON) + (dma_dev->rx_chan[i])->open(dma_dev->rx_chan[i]); + } + netif_start_queue(dev); + return 0; +} + +int +ifxmips_mii_release(struct net_device *dev){ + struct ifxmips_mii_priv* priv = (struct ifxmips_mii_priv*)dev->priv; + struct dma_device_info* dma_dev = priv->dma_device; + int i; + + for(i = 0; i < dma_dev->max_rx_chan_num; i++) + dma_dev->rx_chan[i]->close(dma_dev->rx_chan[i]); + netif_stop_queue(dev); + return 0; +} + +int +ifxmips_mii_hw_receive(struct net_device* dev,struct dma_device_info* dma_dev) +{ + struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv*)dev->priv; + unsigned char* buf = NULL; + struct sk_buff *skb = NULL; + int len = 0; + + len = dma_device_read(dma_dev, &buf, (void**)&skb); + + if(len >= ETHERNET_PACKET_DMA_BUFFER_SIZE) + { + printk(KERN_INFO "ifxmips_mii0: packet too large %d\n",len); + goto ifxmips_mii_hw_receive_err_exit; + } + + /* remove CRC */ + len -= 4; + if(skb == NULL) + { + printk(KERN_INFO "ifxmips_mii0: cannot restore pointer\n"); + goto ifxmips_mii_hw_receive_err_exit; + } + + if(len > (skb->end - skb->tail)) + { + printk(KERN_INFO "ifxmips_mii0: BUG, len:%d end:%p tail:%p\n", + (len+4), skb->end, skb->tail); + goto ifxmips_mii_hw_receive_err_exit; + } + + skb_put(skb, len); + skb->dev = dev; + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + + priv->stats.rx_packets++; + priv->stats.rx_bytes += len; + return 0; + +ifxmips_mii_hw_receive_err_exit: + if(len == 0) + { + if(skb) + dev_kfree_skb_any(skb); + priv->stats.rx_errors++; + priv->stats.rx_dropped++; + return -EIO; + } else { + return len; + } +} + +int +ifxmips_mii_hw_tx(char *buf, int len, struct net_device *dev) +{ + int ret = 0; + struct ifxmips_mii_priv *priv = dev->priv; + struct dma_device_info* dma_dev = priv->dma_device; + ret = dma_device_write(dma_dev, buf, len, priv->skb); + return ret; +} + +int +ifxmips_mii_tx(struct sk_buff *skb, struct net_device *dev) +{ + int len; + char *data; + struct ifxmips_mii_priv *priv = dev->priv; + struct dma_device_info* dma_dev = priv->dma_device; + + len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len; + data = skb->data; + priv->skb = skb; + dev->trans_start = jiffies; + // TODO we got more than 1 dma channel, so we should do something intelligent + // here to select one + dma_dev->current_tx_chan = 0; + + wmb(); + + if(ifxmips_mii_hw_tx(data, len, dev) != len) + { + dev_kfree_skb_any(skb); + priv->stats.tx_errors++; + priv->stats.tx_dropped++; + } else { + priv->stats.tx_packets++; + priv->stats.tx_bytes+=len; + } + + return 0; +} + +void +ifxmips_mii_tx_timeout(struct net_device *dev) +{ + int i; + struct ifxmips_mii_priv* priv = (struct ifxmips_mii_priv*)dev->priv; + + priv->stats.tx_errors++; + for(i = 0; i < priv->dma_device->max_tx_chan_num; i++) + priv->dma_device->tx_chan[i]->disable_irq(priv->dma_device->tx_chan[i]); + netif_wake_queue(dev); + return; +} + +int +dma_intr_handler(struct dma_device_info* dma_dev, int status) +{ + int i; + + switch(status) + { + case RCV_INT: + ifxmips_mii_hw_receive(ifxmips_mii0_dev, dma_dev); + break; + + case TX_BUF_FULL_INT: + printk(KERN_INFO "ifxmips_mii0: tx buffer full\n"); + netif_stop_queue(ifxmips_mii0_dev); + for (i = 0; i < dma_dev->max_tx_chan_num; i++) + { + if ((dma_dev->tx_chan[i])->control==IFXMIPS_DMA_CH_ON) + dma_dev->tx_chan[i]->enable_irq(dma_dev->tx_chan[i]); + } + break; + + case TRANSMIT_CPT_INT: + for(i = 0; i < dma_dev->max_tx_chan_num; i++) + dma_dev->tx_chan[i]->disable_irq(dma_dev->tx_chan[i]); + + netif_wake_queue(ifxmips_mii0_dev); + break; + } + + return 0; +} + +unsigned char* +ifxmips_etop_dma_buffer_alloc(int len, int *byte_offset, void **opt) +{ + unsigned char *buffer = NULL; + struct sk_buff *skb = NULL; + + skb = dev_alloc_skb(ETHERNET_PACKET_DMA_BUFFER_SIZE); + if(skb == NULL) + return NULL; + + buffer = (unsigned char*)(skb->data); + skb_reserve(skb, 2); + *(int*)opt = (int)skb; + *byte_offset = 2; + + return buffer; +} + +void +ifxmips_etop_dma_buffer_free(unsigned char *dataptr, void *opt) +{ + struct sk_buff *skb = NULL; + + if(opt == NULL) + { + kfree(dataptr); + } else { + skb = (struct sk_buff*)opt; + dev_kfree_skb_any(skb); + } +} + +static struct net_device_stats* +ifxmips_get_stats(struct net_device *dev) +{ + return (struct net_device_stats *)dev->priv; +} + +static int +ifxmips_mii_dev_init(struct net_device *dev) +{ + int i; + struct ifxmips_mii_priv *priv; + + ether_setup(dev); + printk(KERN_INFO "ifxmips_mii0: %s is up\n", dev->name); + dev->open = ifxmips_ifxmips_mii_open; + dev->stop = ifxmips_mii_release; + dev->hard_start_xmit = ifxmips_mii_tx; + dev->get_stats = ifxmips_get_stats; + dev->tx_timeout = ifxmips_mii_tx_timeout; + dev->watchdog_timeo = 10 * HZ; + memset(dev->priv, 0, sizeof(struct ifxmips_mii_priv)); + priv = dev->priv; + priv->dma_device = dma_device_reserve("PPE"); + if(!priv->dma_device){ + BUG(); + return -ENODEV; + } + priv->dma_device->buffer_alloc = &ifxmips_etop_dma_buffer_alloc; + priv->dma_device->buffer_free = &ifxmips_etop_dma_buffer_free; + priv->dma_device->intr_handler = &dma_intr_handler; + priv->dma_device->max_rx_chan_num = 4; + + for(i = 0; i < priv->dma_device->max_rx_chan_num; i++) + { + priv->dma_device->rx_chan[i]->packet_size = ETHERNET_PACKET_DMA_BUFFER_SIZE; + priv->dma_device->rx_chan[i]->control = IFXMIPS_DMA_CH_ON; + } + + for(i = 0; i < priv->dma_device->max_tx_chan_num; i++) + if(i == 0) + priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_ON; + else + priv->dma_device->tx_chan[i]->control = IFXMIPS_DMA_CH_OFF; + + dma_device_register(priv->dma_device); + + printk(KERN_INFO "ifxmips_mii0: using mac="); + for(i = 0; i < 6; i++) + { + dev->dev_addr[i] = mac_addr[i]; + printk("%02X%c", dev->dev_addr[i], (i == 5)?('\n'):(':')); + } + return 0; +} + +static void +ifxmips_mii_chip_init(int mode) +{ + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_DMA); + ifxmips_pmu_enable(IFXMIPS_PMU_PWDCR_PPE); + + if(mode == REV_MII_MODE) + ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_REVERSE, IFXMIPS_PPE32_CFG); + else if(mode == MII_MODE) + ifxmips_w32_mask(PPE32_MII_MASK, PPE32_MII_NORMAL, IFXMIPS_PPE32_CFG); + ifxmips_w32(PPE32_PLEN_UNDER | PPE32_PLEN_OVER, IFXMIPS_PPE32_IG_PLEN_CTRL); + ifxmips_w32(PPE32_CGEN, IFXMIPS_PPE32_ENET_MAC_CFG); + wmb(); +} + +static int +ifxmips_mii_probe(struct platform_device *dev) +{ + int result = 0; + unsigned char *mac = (unsigned char*)dev->dev.platform_data; + ifxmips_mii0_dev = alloc_etherdev(sizeof(struct ifxmips_mii_priv)); + ifxmips_mii0_dev->init = ifxmips_mii_dev_init; + memcpy(mac_addr, mac, 6); + strcpy(ifxmips_mii0_dev->name, "eth%d"); + ifxmips_mii_chip_init(REV_MII_MODE); + result = register_netdev(ifxmips_mii0_dev); + if (result) + { + printk(KERN_INFO "ifxmips_mii0: error %i registering device \"%s\"\n", result, ifxmips_mii0_dev->name); + goto out; + } + + printk(KERN_INFO "ifxmips_mii0: driver loaded!\n"); + +out: + return result; +} + +static int +ifxmips_mii_remove(struct platform_device *dev) +{ + struct ifxmips_mii_priv *priv = (struct ifxmips_mii_priv*)ifxmips_mii0_dev->priv; + + printk(KERN_INFO "ifxmips_mii0: ifxmips_mii0 cleanup\n"); + + dma_device_unregister(priv->dma_device); + dma_device_release(priv->dma_device); + kfree(priv->dma_device); + kfree(ifxmips_mii0_dev->priv); + unregister_netdev(ifxmips_mii0_dev); + return 0; +} + +static struct +platform_driver ifxmips_mii_driver = { + .probe = ifxmips_mii_probe, + .remove = ifxmips_mii_remove, + .driver = { + .name = "ifxmips_mii0", + .owner = THIS_MODULE, + }, +}; + +int __init +ifxmips_mii_init(void) +{ + int ret = platform_driver_register(&ifxmips_mii_driver); + if (ret) + printk(KERN_INFO "ifxmips_mii0: Error registering platfom driver!"); + return ret; +} + +static void __exit +ifxmips_mii_cleanup(void) +{ + platform_driver_unregister(&ifxmips_mii_driver); +} + +module_init(ifxmips_mii_init); +module_exit(ifxmips_mii_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("ethernet map driver for IFXMIPS boards"); diff --git a/target/linux/ifxmips/files/drivers/serial/ifxmips_asc.c b/target/linux/ifxmips/files/drivers/serial/ifxmips_asc.c new file mode 100644 index 0000000000..2dc8917fe1 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/serial/ifxmips_asc.c @@ -0,0 +1,599 @@ +/* + * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o. + * + * 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 + * + * Copyright (C) 2004 Infineon IFAP DC COM CPE + * Copyright (C) 2007 Felix Fietkau + * Copyright (C) 2007 John Crispin + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PORT_IFXMIPSASC 111 + +#include + +#define UART_DUMMY_UER_RX 1 + +static void ifxmipsasc_tx_chars(struct uart_port *port); +extern void prom_printf(const char * fmt, ...); +static struct uart_port ifxmipsasc_port[2]; +static struct uart_driver ifxmipsasc_reg; +extern unsigned int ifxmips_get_fpi_hz(void); + +static void +ifxmipsasc_stop_tx(struct uart_port *port) +{ + return; +} + +static void +ifxmipsasc_start_tx(struct uart_port *port) +{ + unsigned long flags; + local_irq_save(flags); + ifxmipsasc_tx_chars(port); + local_irq_restore(flags); + return; +} + +static void +ifxmipsasc_stop_rx(struct uart_port *port) +{ + ifxmips_w32(ASCWHBSTATE_CLRREN, port->membase + IFXMIPS_ASC_WHBSTATE); +} + +static void +ifxmipsasc_enable_ms(struct uart_port *port) +{ +} + +static void +ifxmipsasc_rx_chars(struct uart_port *port) +{ + struct tty_struct *tty = port->info->tty; + unsigned int ch = 0, rsr = 0, fifocnt; + + fifocnt = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_RXFFLMASK; + while(fifocnt--) + { + u8 flag = TTY_NORMAL; + ch = ifxmips_r32(port->membase + IFXMIPS_ASC_RBUF); + rsr = (ifxmips_r32(port->membase + IFXMIPS_ASC_STATE) & ASCSTATE_ANY) | UART_DUMMY_UER_RX; + tty_flip_buffer_push(tty); + port->icount.rx++; + + /* + * Note that the error handling code is + * out of the main execution path + */ + if(rsr & ASCSTATE_ANY) + { + if(rsr & ASCSTATE_PE) + { + port->icount.parity++; + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE, port->membase + IFXMIPS_ASC_WHBSTATE); + } else if(rsr & ASCSTATE_FE) + { + port->icount.frame++; + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRFE, port->membase + IFXMIPS_ASC_WHBSTATE); + } + if(rsr & ASCSTATE_ROE) + { + port->icount.overrun++; + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE); + } + + rsr &= port->read_status_mask; + + if(rsr & ASCSTATE_PE) + flag = TTY_PARITY; + else if(rsr & ASCSTATE_FE) + flag = TTY_FRAME; + } + + if((rsr & port->ignore_status_mask) == 0) + tty_insert_flip_char(tty, ch, flag); + + if(rsr & ASCSTATE_ROE) + /* + * Overrun is special, since it's reported + * immediately, and doesn't affect the current + * character + */ + tty_insert_flip_char(tty, 0, TTY_OVERRUN); + } + if(ch != 0) + tty_flip_buffer_push(tty); + return; +} + + +static void +ifxmipsasc_tx_chars(struct uart_port *port) +{ + struct circ_buf *xmit = &port->info->xmit; + if(uart_tx_stopped(port)) + { + ifxmipsasc_stop_tx(port); + return; + } + + while(((ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK) + >> ASCFSTAT_TXFFLOFF) != TXFIFO_FULL) + { + if(port->x_char) + { + ifxmips_w32(port->x_char, port->membase + IFXMIPS_ASC_TBUF); + port->icount.tx++; + port->x_char = 0; + continue; + } + + if(uart_circ_empty(xmit)) + break; + + ifxmips_w32(port->info->xmit.buf[port->info->xmit.tail], port->membase + IFXMIPS_ASC_TBUF); + xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); + port->icount.tx++; + } + + if(uart_circ_chars_pending(xmit) < WAKEUP_CHARS) + uart_write_wakeup(port); +} + +static irqreturn_t +ifxmipsasc_tx_int(int irq, void *_port) +{ + struct uart_port *port = (struct uart_port*) _port; + ifxmips_w32(ASC_IRNCR_TIR, port->membase + IFXMIPS_ASC_IRNCR); + ifxmipsasc_start_tx(port); + ifxmips_mask_and_ack_irq(irq); + return IRQ_HANDLED; +} + +static irqreturn_t +ifxmipsasc_er_int(int irq, void *_port) +{ + struct uart_port *port = (struct uart_port*) _port; + /* clear any pending interrupts */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_WHBSTATE) | ASCWHBSTATE_CLRPE | + ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE, port->membase + IFXMIPS_ASC_WHBSTATE); + return IRQ_HANDLED; +} + +static irqreturn_t +ifxmipsasc_rx_int(int irq, void *_port) +{ + struct uart_port *port = (struct uart_port*)_port; + ifxmips_w32(ASC_IRNCR_RIR, port->membase + IFXMIPS_ASC_IRNCR); + ifxmipsasc_rx_chars((struct uart_port*)port); + ifxmips_mask_and_ack_irq(irq); + return IRQ_HANDLED; +} + +static unsigned int +ifxmipsasc_tx_empty(struct uart_port *port) +{ + int status; + status = ifxmips_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK; + return status ? 0 : TIOCSER_TEMT; +} + +static unsigned int +ifxmipsasc_get_mctrl(struct uart_port *port) +{ + return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR; +} + +static void +ifxmipsasc_set_mctrl(struct uart_port *port, u_int mctrl) +{ +} + +static void +ifxmipsasc_break_ctl(struct uart_port *port, int break_state) +{ +} + +static int +ifxmipsasc_startup(struct uart_port *port) +{ + unsigned long flags; + int retval; + + port->uartclk = ifxmips_get_fpi_hz(); + + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~IFXMIPS_ASC_CLC_DISS, port->membase + IFXMIPS_ASC_CLC); + ifxmips_w32(((ifxmips_r32(port->membase + IFXMIPS_ASC_CLC) & ~ASCCLC_RMCMASK)) | (1 << ASCCLC_RMCOFFSET), port->membase + IFXMIPS_ASC_CLC); + ifxmips_w32(0, port->membase + IFXMIPS_ASC_PISEL); + ifxmips_w32(((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) | ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON); + ifxmips_w32(((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK) | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON); + wmb (); + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN, port->membase + IFXMIPS_ASC_CON); + + local_irq_save(flags); + + retval = request_irq(port->irq, ifxmipsasc_tx_int, IRQF_DISABLED, "asc_tx", port); + if(retval) + { + printk("failed to request ifxmipsasc_tx_int\n"); + return retval; + } + + retval = request_irq(port->irq + 2, ifxmipsasc_rx_int, IRQF_DISABLED, "asc_rx", port); + if(retval) + { + printk("failed to request ifxmipsasc_rx_int\n"); + goto err1; + } + + retval = request_irq(port->irq + 3, ifxmipsasc_er_int, IRQF_DISABLED, "asc_er", port); + if(retval) + { + printk("failed to request ifxmipsasc_er_int\n"); + goto err2; + } + + ifxmips_w32(ASC_IRNREN_RX_BUF | ASC_IRNREN_TX_BUF | ASC_IRNREN_ERR | ASC_IRNREN_TX, port->membase + IFXMIPS_ASC_IRNREN); + + local_irq_restore(flags); + return 0; + +err2: + free_irq(port->irq + 2, port); +err1: + free_irq(port->irq, port); + local_irq_restore(flags); + return retval; +} + +static void +ifxmipsasc_shutdown(struct uart_port *port) +{ + free_irq(port->irq, port); + free_irq(port->irq + 2, port); + free_irq(port->irq + 3, port); + + ifxmips_w32(0, port->membase + IFXMIPS_ASC_CON); + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) | ASCRXFCON_RXFFLU, port->membase + IFXMIPS_ASC_RXFCON); + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_RXFCON) & ~ASCRXFCON_RXFEN, port->membase + IFXMIPS_ASC_RXFCON); + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) | ASCTXFCON_TXFFLU, port->membase + IFXMIPS_ASC_TXFCON); + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_TXFCON) & ~ASCTXFCON_TXFEN, port->membase + IFXMIPS_ASC_TXFCON); +} + +static void ifxmipsasc_set_termios(struct uart_port *port, struct ktermios *new, struct ktermios *old) +{ + unsigned int cflag; + unsigned int iflag; + unsigned int quot; + unsigned int baud; + unsigned int con = 0; + unsigned long flags; + + cflag = new->c_cflag; + iflag = new->c_iflag; + + switch(cflag & CSIZE) + { + case CS7: + con = ASCCON_M_7ASYNC; + break; + + case CS5: + case CS6: + default: + con = ASCCON_M_8ASYNC; + break; + } + + if(cflag & CSTOPB) + con |= ASCCON_STP; + + if(cflag & PARENB) + { + if(!(cflag & PARODD)) + con &= ~ASCCON_ODD; + else + con |= ASCCON_ODD; + } + + port->read_status_mask = ASCSTATE_ROE; + if(iflag & INPCK) + port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE; + + port->ignore_status_mask = 0; + if(iflag & IGNPAR) + port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE; + + if(iflag & IGNBRK) + { + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if(iflag & IGNPAR) + port->ignore_status_mask |= ASCSTATE_ROE; + } + + if((cflag & CREAD) == 0) + port->ignore_status_mask |= UART_DUMMY_UER_RX; + + /* set error signals - framing, parity and overrun, enable receiver */ + con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN; + + local_irq_save(flags); + + /* set up CON */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | con, port->membase + IFXMIPS_ASC_CON); + + /* Set baud rate - take a divider of 2 into account */ + baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16); + quot = uart_get_divisor(port, baud); + quot = quot / 2 - 1; + + /* disable the baudrate generator */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_R, port->membase + IFXMIPS_ASC_CON); + + /* make sure the fractional divider is off */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_FDE, port->membase + IFXMIPS_ASC_CON); + + /* set up to use divisor of 2 */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) & ~ASCCON_BRS, port->membase + IFXMIPS_ASC_CON); + + /* now we can write the new baudrate into the register */ + ifxmips_w32(quot, port->membase + IFXMIPS_ASC_BG); + + /* turn the baudrate generator back on */ + ifxmips_w32(ifxmips_r32(port->membase + IFXMIPS_ASC_CON) | ASCCON_R, port->membase + IFXMIPS_ASC_CON); + + /* enable rx */ + ifxmips_w32(ASCWHBSTATE_SETREN, port->membase + IFXMIPS_ASC_WHBSTATE); + + local_irq_restore(flags); +} + +static const char* +ifxmipsasc_type(struct uart_port *port) +{ + if(port->type == PORT_IFXMIPSASC) + { + if(port->membase == (void*)IFXMIPS_ASC_BASE_ADDR) + return "asc0"; + else + return "asc1"; + } else { + return NULL; + } +} + +static void +ifxmipsasc_release_port(struct uart_port *port) +{ +} + +static int +ifxmipsasc_request_port(struct uart_port *port) +{ + return 0; +} + +static void +ifxmipsasc_config_port(struct uart_port *port, int flags) +{ + if(flags & UART_CONFIG_TYPE) + { + port->type = PORT_IFXMIPSASC; + ifxmipsasc_request_port(port); + } +} + +static int +ifxmipsasc_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + int ret = 0; + if(ser->type != PORT_UNKNOWN && ser->type != PORT_IFXMIPSASC) + ret = -EINVAL; + if(ser->irq < 0 || ser->irq >= NR_IRQS) + ret = -EINVAL; + if(ser->baud_base < 9600) + ret = -EINVAL; + return ret; +} + +static struct uart_ops ifxmipsasc_pops = +{ + .tx_empty = ifxmipsasc_tx_empty, + .set_mctrl = ifxmipsasc_set_mctrl, + .get_mctrl = ifxmipsasc_get_mctrl, + .stop_tx = ifxmipsasc_stop_tx, + .start_tx = ifxmipsasc_start_tx, + .stop_rx = ifxmipsasc_stop_rx, + .enable_ms = ifxmipsasc_enable_ms, + .break_ctl = ifxmipsasc_break_ctl, + .startup = ifxmipsasc_startup, + .shutdown = ifxmipsasc_shutdown, + .set_termios = ifxmipsasc_set_termios, + .type = ifxmipsasc_type, + .release_port = ifxmipsasc_release_port, + .request_port = ifxmipsasc_request_port, + .config_port = ifxmipsasc_config_port, + .verify_port = ifxmipsasc_verify_port, +}; + +static struct uart_port ifxmipsasc_port[2] = +{ + { + membase: (void *)IFXMIPS_ASC_BASE_ADDR, + mapbase: IFXMIPS_ASC_BASE_ADDR, + iotype: SERIAL_IO_MEM, + irq: IFXMIPSASC_TIR(0), + uartclk: 0, + fifosize: 16, + type: PORT_IFXMIPSASC, + ops: &ifxmipsasc_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 0 + }, { + membase: (void *)(IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF), + mapbase: IFXMIPS_ASC_BASE_ADDR + IFXMIPS_ASC_BASE_DIFF, + iotype: SERIAL_IO_MEM, + irq: IFXMIPSASC_TIR(1), + uartclk: 0, + fifosize: 16, + type: PORT_IFXMIPSASC, + ops: &ifxmipsasc_pops, + flags: ASYNC_BOOT_AUTOCONF, + line: 1 + } +}; + +static void +ifxmipsasc_console_write(struct console *co, const char *s, u_int count) +{ + int port = co->index; + int i, fifocnt; + unsigned long flags; + local_irq_save(flags); + for(i = 0; i < count; i++) + { + do { + fifocnt = (ifxmips_r32((u32*)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK) + >> ASCFSTAT_TXFFLOFF; + } while(fifocnt == TXFIFO_FULL); + + if(s[i] == '\0') + break; + + if(s[i] == '\n') + { + ifxmips_w32('\r', (u32*)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF)); + do { + fifocnt = (ifxmips_r32((u32*)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_FSTAT)) & ASCFSTAT_TXFFLMASK) + >> ASCFSTAT_TXFFLOFF; + } while(fifocnt == TXFIFO_FULL); + } + ifxmips_w32(s[i], (u32*)(IFXMIPS_ASC_BASE_ADDR + (port * IFXMIPS_ASC_BASE_DIFF) + IFXMIPS_ASC_TBUF)); + } + + local_irq_restore(flags); +} + +static int __init +ifxmipsasc_console_setup(struct console *co, char *options) +{ + int port = co->index; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + ifxmipsasc_port[port].uartclk = ifxmips_get_fpi_hz(); + ifxmipsasc_port[port].type = PORT_IFXMIPSASC; + if(options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + return uart_set_options(&ifxmipsasc_port[port], co, baud, parity, bits, flow); +} + +static struct console ifxmipsasc_console[2] = +{ + { + name: "ttyS", + write: ifxmipsasc_console_write, + device: uart_console_device, + setup: ifxmipsasc_console_setup, + flags: CON_PRINTBUFFER, + index: 0, + data: &ifxmipsasc_reg, + }, { + name: "ttyS", + write: ifxmipsasc_console_write, + device: uart_console_device, + setup: ifxmipsasc_console_setup, + flags: CON_PRINTBUFFER, + index: 1, + data: &ifxmipsasc_reg, + } +}; + +static int __init +ifxmipsasc_console_init(void) +{ + register_console(&ifxmipsasc_console[0]); + register_console(&ifxmipsasc_console[1]); + return 0; +} +console_initcall(ifxmipsasc_console_init); + +static struct uart_driver ifxmipsasc_reg = +{ + .owner = THIS_MODULE, + .driver_name = "serial", + .dev_name = "ttyS", + .major = TTY_MAJOR, + .minor = 64, + .nr = 2, + .cons = &ifxmipsasc_console[1], +}; + +int __init +ifxmipsasc_init(void) +{ + int ret; + uart_register_driver(&ifxmipsasc_reg); + ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[0]); + ret = uart_add_one_port(&ifxmipsasc_reg, &ifxmipsasc_port[1]); + return 0; +} + +void __exit +ifxmipsasc_exit(void) +{ + uart_unregister_driver(&ifxmipsasc_reg); +} + +module_init(ifxmipsasc_init); +module_exit(ifxmipsasc_exit); + +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("MIPS IFXMips serial port driver"); +MODULE_LICENSE("GPL"); diff --git a/target/linux/ifxmips/files/drivers/watchdog/ifxmips_wdt.c b/target/linux/ifxmips/files/drivers/watchdog/ifxmips_wdt.c new file mode 100644 index 0000000000..58e2161489 --- /dev/null +++ b/target/linux/ifxmips/files/drivers/watchdog/ifxmips_wdt.c @@ -0,0 +1,204 @@ +/* + * 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 + * + * Copyright (C) 2008 John Crispin + * Based on EP93xx wdt driver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IFXMIPS_WDT_PW1 0x00BE0000 +#define IFXMIPS_WDT_PW2 0x00DC0000 + +#ifndef CONFIG_WATCHDOG_NOWAYOUT +static int wdt_ok_to_close = 0; +#endif + +int wdt_timeout = 30; + +int +ifxmips_wdt_enable(unsigned int timeout) +{ + u32 fpi; + fpi = cgu_get_io_region_clock(); + ifxmips_w32(IFXMIPS_WDT_PW1, IFXMIPS_BIU_WDT_CR); + ifxmips_w32(IFXMIPS_WDT_PW2 | + (0x3 << 26) | // PWL + (0x3 << 24) | // CLKDIV + (0x1 << 31) | // enable + ((timeout * (fpi / 0x40000)) + 0x1000), // reload + IFXMIPS_BIU_WDT_CR); + return 0; +} + +void +ifxmips_wdt_disable(void) +{ +#ifndef CONFIG_WATCHDOG_NOWAYOUT + wdt_ok_to_close = 0; +#endif + ifxmips_w32(IFXMIPS_WDT_PW1, IFXMIPS_BIU_WDT_CR); + ifxmips_w32(IFXMIPS_WDT_PW2, IFXMIPS_BIU_WDT_CR); +} + +static ssize_t +ifxmips_wdt_write(struct file *file, const char __user *data, size_t len, + loff_t *ppos) +{ + size_t i; + + if(!len) + return 0; + +#ifndef CONFIG_WATCHDOG_NOWAYOUT + for(i = 0; i != len; i++) + { + char c; + if(get_user(c, data + i)) + return -EFAULT; + if(c == 'V') + wdt_ok_to_close = 1; + } +#endif + ifxmips_wdt_enable(wdt_timeout); + return len; +} + +static struct watchdog_info ident = { + .options = WDIOF_MAGICCLOSE, + .identity = "ifxmips Watchdog", +}; + +static int +ifxmips_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, + unsigned long arg) +{ + int ret = -ENOTTY; + + switch(cmd) + { + case WDIOC_GETSUPPORT: + ret = copy_to_user((struct watchdog_info __user *)arg, &ident, + sizeof(ident)) ? -EFAULT : 0; + break; + + case WDIOC_GETTIMEOUT: + ret = put_user(wdt_timeout, (int __user *)arg); + break; + + case WDIOC_SETTIMEOUT: + ret = get_user(wdt_timeout, (int __user*)arg); + break; + + case WDIOC_KEEPALIVE: + ifxmips_wdt_enable(wdt_timeout); + ret = 0; + break; + } + return ret; +} + +static int +ifxmips_wdt_open(struct inode *inode, struct file *file) +{ + ifxmips_wdt_enable(wdt_timeout); + return nonseekable_open(inode, file); +} + +static int ifxmips_wdt_release(struct inode *inode, struct file *file) +{ +#ifndef CONFIG_WATCHDOG_NOWAYOUT + if(wdt_ok_to_close) + ifxmips_wdt_disable(); + else +#endif + printk("ifxmips_wdt: watchdog closed without warning, rebooting system\n"); + return 0; +} + +static const struct file_operations ifxmips_wdt_fops = { + .owner = THIS_MODULE, + .write = ifxmips_wdt_write, + .ioctl = ifxmips_wdt_ioctl, + .open = ifxmips_wdt_open, + .release = ifxmips_wdt_release, +}; + +static struct miscdevice ifxmips_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &ifxmips_wdt_fops, +}; + +static int +ifxmips_wdt_probe(struct platform_device *dev) +{ + int err; + err = misc_register(&ifxmips_wdt_miscdev); + if(err) + printk("ifxmips_wdt: error creating device\n"); + else + printk("ifxmips_wdt: loaded\n"); + return err; +} + +static int +ifxmips_wdt_remove(struct platform_device *dev) +{ + ifxmips_wdt_disable(); + misc_deregister(&ifxmips_wdt_miscdev); + return 0; +} + + +static struct platform_driver ifxmips_wdt_driver = { + .probe = ifxmips_wdt_probe, + .remove = ifxmips_wdt_remove, + .driver = { + .name = "ifxmips_wdt", + .owner = THIS_MODULE, + }, +}; + +static int __init +init_ifxmips_wdt(void) +{ + int ret = platform_driver_register(&ifxmips_wdt_driver); + if(ret) + printk(KERN_INFO "ifxmips_wdt: error registering platfom driver!"); + return ret; +} + +static void __exit +exit_ifxmips_wdt(void) +{ + platform_driver_unregister(&ifxmips_wdt_driver); +} + +module_init(init_ifxmips_wdt); +module_exit(exit_ifxmips_wdt); + +MODULE_AUTHOR("John Crispin "); +MODULE_DESCRIPTION("ifxmips Watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_peripheral_definitions.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_peripheral_definitions.h new file mode 100644 index 0000000000..5bd788fff6 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_peripheral_definitions.h @@ -0,0 +1,119 @@ +//************************************************************************* +//* Summary of definitions which are used in each peripheral * +//************************************************************************* + +#ifndef peripheral_definitions_h +#define peripheral_definitions_h + +////#include "cpu.h" +// +///* These files have to be included by each peripheral */ +//#include +//#include +//#include +//#include +//#include +//#include "SRAM_address_map.h" +// +///* common header files for all CPU's */ +//#include "iiu.h" +//#include "bcu.h" +//#include "FPI_address_map.h" +//#include "direct_interrupts.h" + +///////////////////////////////////////////////////////////////////////// + +//extern int _clz(); +//extern void _nop(); +//extern void _sleep(); +//extern void sys_enable_int(); + +typedef unsigned char UINT8; +typedef signed char INT8; +typedef unsigned short UINT16; +typedef signed short INT16; +typedef unsigned int UINT32; +typedef signed int INT32; +typedef unsigned long long UINT64; +typedef signed long long INT64; + +#define REG8( addr ) (*(volatile UINT8 *) (addr)) +#define REG16( addr ) (*(volatile UINT16 *)(addr)) +#define REG32( addr ) (*(volatile UINT32 *)(addr)) +#define REG64( addr ) (*(volatile UINT64 *)(addr)) + +/* define routine to set FPI access in Supervisor Mode */ +#define IFX_SUPERVISOR_ON() REG32(FB0_CFG) = 0x01 +/* Supervisor mode ends, following functions will be done in User mode */ +#define IFX_SUPERVISOR_OFF() REG32(FB0_CFG) = 0x00 +/* Supervisor mode ends, following functions will be done in User mode */ +#define IFX_SUPERVISOR_MODE() REG32(FB0_CFG) +/* Supervisor mode ends, following functions will be done in User mode */ +#define IFX_SUPERVISOR_SET(svm) REG32(FB0_CFG) = svm +/* enable all Interrupts in IIU */ +//#define IFX_ENABLE_IRQ(irq_mask, im_base) REG32(im_base | IIU_MASK) = irq_mask +///* get all high priority interrupt bits in IIU */ +//#define IFX_GET_IRQ_MASKED(im_base) REG32(im_base | IIU_IRMASKED) +///* signal ends of interrupt to IIU */ +//#define IFX_CLEAR_DIRECT_IRQ(irq_bit, im_base) REG32(im_base | IIU_IR) = irq_bit +///* force IIU interrupt register */ +//#define IFX_FORCE_IIU_REGISTER(data, im_base) REG32(im_base | IIU_IRDEBUG) = data +///* get all bits of interrupt register */ +//#define IFX_GET_IRQ_UNMASKED(im_base) REG32(im_base | IIU_IR) +/* insert a NOP instruction */ +#define NOP _nop() +/* CPU goes to power down mode until interrupt occurs */ +#define IFX_CPU_SLEEP _sleep() +/* enable all interrupts to CPU */ +#define IFX_CPU_ENABLE_ALL_INTERRUPT sys_enable_int() +/* get all low priority interrupt bits in peripheral */ +#define IFX_GET_LOW_PRIO_IRQ(int_reg) REG32(int_reg) +/* clear low priority interrupt bit in peripheral */ +#define IFX_CLEAR_LOW_PRIO_IRQ(irq_bit, int_reg) REG32(int_reg) = irq_bit +/* write FPI bus */ +#define WRITE_FPI_BYTE(data, addr) REG8(addr) = data +#define WRITE_FPI_16BIT(data, addr) REG16(addr) = data +#define WRITE_FPI_32BIT(data, addr) REG32(addr) = data +/* read FPI bus */ +#define READ_FPI_BYTE(addr) REG8(addr) +#define READ_FPI_16BIT(addr) REG16(addr) +#define READ_FPI_32BIT(addr) REG32(addr) +/* write peripheral register */ +#define WRITE_PERIPHERAL_REGISTER(data, addr) REG32(addr) = data + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +#define WRITE_PERIPHERAL_REGISTER_16(data, addr) REG16(addr) = data +#define WRITE_PERIPHERAL_REGISTER_8(data, addr) REG8(addr) = data +#else //not CONFIG_CPU_LITTLE_ENDIAN +#define WRITE_PERIPHERAL_REGISTER_16(data, addr) REG16(addr+2) = data +#define WRITE_PERIPHERAL_REGISTER_8(data, addr) REG8(addr+3) = data +#endif //CONFIG_CPU_LITTLE_ENDIAN + +/* read peripheral register */ +#define READ_PERIPHERAL_REGISTER(addr) REG32(addr) + +/* read/modify(or)/write peripheral register */ +#define RMW_OR_PERIPHERAL_REGISTER(data, addr) REG32(addr) = REG32(addr) | data +/* read/modify(and)/write peripheral register */ +#define RMW_AND_PERIPHERAL_REGISTER(data, addr) REG32(addr) = REG32(addr) & (UINT32)data + +/* CPU-independent mnemonic constants */ +/* CLC register bits */ +#define IFX_CLC_ENABLE 0x00000000 +#define IFX_CLC_DISABLE 0x00000001 +#define IFX_CLC_DISABLE_STATUS 0x00000002 +#define IFX_CLC_SUSPEND_ENABLE 0x00000004 +#define IFX_CLC_CLOCK_OFF_DISABLE 0x00000008 +#define IFX_CLC_OVERWRITE_SPEN_FSOE 0x00000010 +#define IFX_CLC_FAST_CLOCK_SWITCH_OFF 0x00000020 +#define IFX_CLC_RUN_DIVIDER_MASK 0x0000FF00 +#define IFX_CLC_RUN_DIVIDER_OFFSET 8 +#define IFX_CLC_SLEEP_DIVIDER_MASK 0x00FF0000 +#define IFX_CLC_SLEEP_DIVIDER_OFFSET 16 +#define IFX_CLC_SPECIFIC_DIVIDER_MASK 0x00FF0000 +#define IFX_CLC_SPECIFIC_DIVIDER_OFFSET 24 + +/* number of cycles to wait for interrupt service routine to be called */ +#define WAIT_CYCLES 50 + +#endif /* PERIPHERAL_DEFINITIONS_H not yet defined */ diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc.h new file mode 100644 index 0000000000..c6dd5d47a9 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc.h @@ -0,0 +1,258 @@ +/* + * ifx_ssc.h defines some data sructures used in ifx_ssc.c + * + * Copyright (C) 2004 Michael Schoenenborn (IFX COM TI BT) + * + * + */ + +#ifndef __IFX_SSC_H +#define __IFX_SSC_H +#ifdef __KERNEL__ +#include +#endif //__KERNEL__ + +#define PORT_CNT 1 // assume default value + +/* symbolic constants to be used in SSC routines */ + +// ### TO DO: bad performance +#define IFX_SSC_TXFIFO_ITL 1 +#define IFX_SSC_RXFIFO_ITL 1 + +struct ifx_ssc_statistics { + unsigned int abortErr; /* abort error */ + unsigned int modeErr; /* master/slave mode error */ + unsigned int txOvErr; /* TX Overflow error */ + unsigned int txUnErr; /* TX Underrun error */ + unsigned int rxOvErr; /* RX Overflow error */ + unsigned int rxUnErr; /* RX Underrun error */ + unsigned int rxBytes; + unsigned int txBytes; +}; + +struct ifx_ssc_hwopts { + unsigned int AbortErrDetect:1; /* Abort Error detection (in slave mode) */ + unsigned int rxOvErrDetect:1; /* Receive Overflow Error detection */ + unsigned int rxUndErrDetect:1; /* Receive Underflow Error detection */ + unsigned int txOvErrDetect:1; /* Transmit Overflow Error detection */ + unsigned int txUndErrDetect:1; /* Transmit Underflow Error detection */ + unsigned int echoMode:1; /* Echo mode */ + unsigned int loopBack:1; /* Loopback mode */ + unsigned int idleValue:1; /* Idle value */ + unsigned int clockPolarity:1; /* Idle clock is high or low */ + unsigned int clockPhase:1; /* Tx on trailing or leading edge */ + unsigned int headingControl:1; /* LSB first or MSB first */ + unsigned int dataWidth:6; /* from 2 up to 32 bits */ + unsigned int masterSelect:1; /* Master or Slave mode */ + unsigned int modeRxTx:2; /* rx/tx mode */ + unsigned int gpoCs:8; /* choose outputs to use for chip select */ + unsigned int gpoInv:8; /* invert GPO outputs */ +}; + +struct ifx_ssc_frm_opts { + bool FrameEnable; // SFCON.SFEN + unsigned int DataLength; // SFCON.DLEN + unsigned int PauseLength; // SFCON.PLEN + unsigned int IdleData; // SFCON.IDAT + unsigned int IdleClock; // SFCON.ICLK + bool StopAfterPause; // SFCON.STOP +}; + +struct ifx_ssc_frm_status { + bool DataBusy; // SFSTAT.DBSY + bool PauseBusy; // SFSTAT.PBSY + unsigned int DataCount; // SFSTAT.DCNT + unsigned int PauseCount; // SFSTAT.PCNT + bool EnIntAfterData; // SFCON.IBEN + bool EnIntAfterPause; // SFCON.IAEN +}; + +typedef struct { + char *buf; + size_t len; +} ifx_ssc_buf_item_t; + +// data structures for batch execution +typedef union { + struct { + bool save_options; + } init; + ifx_ssc_buf_item_t read; + ifx_ssc_buf_item_t write; + ifx_ssc_buf_item_t rd_wr; + unsigned int set_baudrate; + struct ifx_ssc_frm_opts set_frm; + unsigned int set_gpo; + struct ifx_ssc_hwopts set_hwopts; +} ifx_ssc_batch_cmd_param; + +struct ifx_ssc_batch_list { + unsigned int cmd; + ifx_ssc_batch_cmd_param cmd_param; + struct ifx_ssc_batch_list *next; +}; + +#ifdef __KERNEL__ +#define IFX_SSC_IS_MASTER(p) ((p)->opts.masterSelect == SSC_MASTER_MODE) + +struct ifx_ssc_port { + unsigned long mapbase; + struct ifx_ssc_hwopts opts; + struct ifx_ssc_statistics stats; + struct ifx_ssc_frm_status frm_status; + struct ifx_ssc_frm_opts frm_opts; + /* wait queue for ifx_ssc_read() */ + wait_queue_head_t rwait, pwait; + int port_nr; + char port_is_open; /* exclusive open - boolean */ +// int no_of_bits; /* number of _valid_ bits */ +// int elem_size; /* shift for element (no of bytes)*/ + /* buffer and pointers to the read/write position */ + char *rxbuf; /* buffer for RX */ + char *rxbuf_end; /* buffer end pointer for RX */ + volatile char *rxbuf_ptr; /* buffer write pointer for RX */ + char *txbuf; /* buffer for TX */ + char *txbuf_end; /* buffer end pointer for TX */ + volatile char *txbuf_ptr; /* buffer read pointer for TX */ + unsigned int baud; + /* each channel has its own interrupts */ + /* (transmit/receive/error/frame) */ + unsigned int txirq, rxirq, errirq, frmirq; +}; +/* default values for SSC configuration */ +// values of CON +#define IFX_SSC_DEF_IDLE_DATA 1 /* enable */ +#define IFX_SSC_DEF_BYTE_VALID_CTL 1 /* enable */ +#define IFX_SSC_DEF_DATA_WIDTH 32 /* bits */ +#define IFX_SSC_DEF_ABRT_ERR_DETECT 0 /* disable */ +#define IFX_SSC_DEF_RO_ERR_DETECT 1 /* enable */ +#define IFX_SSC_DEF_RU_ERR_DETECT 0 /* disable */ +#define IFX_SSC_DEF_TO_ERR_DETECT 0 /* disable */ +#define IFX_SSC_DEF_TU_ERR_DETECT 0 /* disable */ +#define IFX_SSC_DEF_LOOP_BACK 0 /* disable */ +#define IFX_SSC_DEF_ECHO_MODE 0 /* disable */ +#define IFX_SSC_DEF_CLOCK_POLARITY 0 /* low */ +#define IFX_SSC_DEF_CLOCK_PHASE 1 /* 0: shift on leading edge, latch on trailling edge, 1, otherwise */ +#define IFX_SSC_DEF_HEADING_CONTROL IFX_SSC_MSB_FIRST +#define IFX_SSC_DEF_MODE_RXTX IFX_SSC_MODE_RXTX +// other values +#define IFX_SSC_DEF_MASTERSLAVE IFX_SSC_MASTER_MODE /* master */ +#ifdef CONFIG_USE_EMULATOR +#define IFX_SSC_DEF_BAUDRATE 10000 +#else +#define IFX_SSC_DEF_BAUDRATE 2000000 +#endif +#define IFX_SSC_DEF_RMC 0x10 + +#define IFX_SSC_DEF_TXFIFO_FL 8 +#define IFX_SSC_DEF_RXFIFO_FL 1 + +#if 1 //TODO +#define IFX_SSC_DEF_GPO_CS 0x3 /* no chip select */ +#define IFX_SSC_DEF_GPO_INV 0 /* no chip select */ +#else +#error "what is ur Chip Select???" +#endif +#define IFX_SSC_DEF_SFCON 0 /* no serial framing */ +#if 0 +#define IFX_SSC_DEF_IRNEN IFX_SSC_T_BIT | /* enable all int's */\ + IFX_SSC_R_BIT | IFX_SSC_E_BIT | IFX_SSC_F_BIT +#endif +#define IFX_SSC_DEF_IRNEN IFX_SSC_T_BIT | /* enable all int's */\ + IFX_SSC_R_BIT | IFX_SSC_E_BIT +#endif /* __KERNEL__ */ + +// batch execution commands +#define IFX_SSC_BATCH_CMD_INIT 1 +#define IFX_SSC_BATCH_CMD_READ 2 +#define IFX_SSC_BATCH_CMD_WRITE 3 +#define IFX_SSC_BATCH_CMD_RD_WR 4 +#define IFX_SSC_BATCH_CMD_SET_BAUDRATE 5 +#define IFX_SSC_BATCH_CMD_SET_HWOPTS 6 +#define IFX_SSC_BATCH_CMD_SET_FRM 7 +#define IFX_SSC_BATCH_CMD_SET_GPO 8 +#define IFX_SSC_BATCH_CMD_FIFO_FLUSH 9 +//#define IFX_SSC_BATCH_CMD_ +//#define IFX_SSC_BATCH_CMD_ +#define IFX_SSC_BATCH_CMD_END_EXEC 0 + +/* Macros to configure SSC hardware */ +/* headingControl: */ +#define IFX_SSC_LSB_FIRST 0 +#define IFX_SSC_MSB_FIRST 1 +/* dataWidth: */ +#define IFX_SSC_MIN_DATA_WIDTH 2 +#define IFX_SSC_MAX_DATA_WIDTH 32 +/* master/slave mode select */ +#define IFX_SSC_MASTER_MODE 1 +#define IFX_SSC_SLAVE_MODE 0 +/* rx/tx mode */ +// ### TO DO: !!! ATTENTION! Hardware dependency => move to ifx_ssc_defines.h +#define IFX_SSC_MODE_RXTX 0 +#define IFX_SSC_MODE_RX 1 +#define IFX_SSC_MODE_TX 2 +#define IFX_SSC_MODE_OFF 3 +#define IFX_SSC_MODE_MASK IFX_SSC_MODE_RX | IFX_SSC_MODE_TX + +/* GPO values */ +#define IFX_SSC_MAX_GPO_OUT 7 + +#define IFX_SSC_RXREQ_BLOCK_SIZE 32768 + +/***********************/ +/* defines for ioctl's */ +/***********************/ +#define IFX_SSC_IOCTL_MAGIC 'S' +/* read out the statistics */ +#define IFX_SSC_STATS_READ _IOR(IFX_SSC_IOCTL_MAGIC, 1, struct ifx_ssc_statistics) +/* clear the statistics */ +#define IFX_SSC_STATS_RESET _IO(IFX_SSC_IOCTL_MAGIC, 2) +/* set the baudrate */ +#define IFX_SSC_BAUD_SET _IOW(IFX_SSC_IOCTL_MAGIC, 3, unsigned int) +/* get the current baudrate */ +#define IFX_SSC_BAUD_GET _IOR(IFX_SSC_IOCTL_MAGIC, 4, unsigned int) +/* set hardware options */ +#define IFX_SSC_HWOPTS_SET _IOW(IFX_SSC_IOCTL_MAGIC, 5, struct ifx_ssc_hwopts) +/* get the current hardware options */ +#define IFX_SSC_HWOPTS_GET _IOR(IFX_SSC_IOCTL_MAGIC, 6, struct ifx_ssc_hwopts) +/* set transmission mode */ +#define IFX_SSC_RXTX_MODE_SET _IOW(IFX_SSC_IOCTL_MAGIC, 7, unsigned int) +/* get the current transmission mode */ +#define IFX_SSC_RXTX_MODE_GET _IOR(IFX_SSC_IOCTL_MAGIC, 8, unsigned int) +/* abort transmission */ +#define IFX_SSC_ABORT _IO(IFX_SSC_IOCTL_MAGIC, 9) +#define IFX_SSC_FIFO_FLUSH _IO(IFX_SSC_IOCTL_MAGIC, 9) + +/* set general purpose outputs */ +#define IFX_SSC_GPO_OUT_SET _IOW(IFX_SSC_IOCTL_MAGIC, 32, unsigned int) +/* clear general purpose outputs */ +#define IFX_SSC_GPO_OUT_CLR _IOW(IFX_SSC_IOCTL_MAGIC, 33, unsigned int) +/* get general purpose outputs */ +#define IFX_SSC_GPO_OUT_GET _IOR(IFX_SSC_IOCTL_MAGIC, 34, unsigned int) + +/*** serial framing ***/ +/* get status of serial framing */ +#define IFX_SSC_FRM_STATUS_GET _IOR(IFX_SSC_IOCTL_MAGIC, 48, struct ifx_ssc_frm_status) +/* get counter reload values and control bits */ +#define IFX_SSC_FRM_CONTROL_GET _IOR(IFX_SSC_IOCTL_MAGIC, 49, struct ifx_ssc_frm_opts) +/* set counter reload values and control bits */ +#define IFX_SSC_FRM_CONTROL_SET _IOW(IFX_SSC_IOCTL_MAGIC, 50, struct ifx_ssc_frm_opts) + +/*** batch execution ***/ +/* do batch execution */ +#define IFX_SSC_BATCH_EXEC _IOW(IFX_SSC_IOCTL_MAGIC, 64, struct ifx_ssc_batch_list) + +#ifdef __KERNEL__ +// routines from ifx_ssc.c +// ### TO DO +/* kernel interface for read and write */ +ssize_t ifx_ssc_kread (int, char *, size_t); +ssize_t ifx_ssc_kwrite (int, const char *, size_t); + +#ifdef CONFIG_IFX_VP_KERNEL_TEST +void ifx_ssc_tc (void); +#endif // CONFIG_IFX_VP_KERNEL_TEST + +#endif //__KERNEL__ +#endif // __IFX_SSC_H diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc_defines.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc_defines.h new file mode 100644 index 0000000000..805d48ad84 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifx_ssc_defines.h @@ -0,0 +1,547 @@ +#ifndef IFX_SSC_DEFINES_H +#define IFX_SSC_DEFINES_H + +#include "ifx_peripheral_definitions.h" + +/* maximum SSC FIFO size */ +#define IFX_SSC_MAX_FIFO_SIZE 32 + +/* register map of SSC */ + +/* address of the Clock Control Register of the SSC */ +#define IFX_SSC_CLC 0x00000000 +/* IFX_SSC_CLC register is significant in bits 23 downto 8 and in bits 5, 3, 2, 0 + bit 1 is hardware modified*/ +#define IFX_SSC_CLC_readmask 0x00FFFFEF +#define IFX_SSC_CLC_writemask 0x00FFFF3D +#define IFX_SSC_CLC_hwmask 0x00000002 +#define IFX_SSC_CLC_dontcare (IFX_SSC_CLC_readmask & IFX_SSC_CLC_writemask & ~IFX_SSC_CLC_hwmask) + +/* address of Port Input Select Register of the SSC */ +#define IFX_SSC_PISEL 0x00000004 +/* IFX_SSC_PISEL register is significant in lowest three bits only */ +#define IFX_SSC_PISEL_readmask 0x00000007 +#define IFX_SSC_PISEL_writemask 0x00000007 +#define IFX_SSC_PISEL_hwmask 0x00000000 +#define IFX_SSC_PISEL_dontcare (IFX_SSC_PISEL_readmask & IFX_SSC_PISEL_writemask & ~IFX_SSC_PISEL_hwmask) + +/* address of Identification Register of the SSC */ +#define IFX_SSC_ID 0x00000008 +/* IFX_SSC_ID register is significant in no bit */ +#define IFX_SSC_ID_readmask 0x0000FF3F +#define IFX_SSC_ID_writemask 0x00000000 +#define IFX_SSC_ID_hwmask 0x00000000 +#define IFX_SSC_ID_dontcare (IFX_SSC_ID_readmask & IFX_SSC_ID_writemask & ~IFX_SSC_ID_hwmask) + +/* address of the Control Register of the SSC */ +#define IFX_SSC_CON 0x00000010 +/* IFX_SSC_CON register is significant in bits 23:22, 20:16 and 12:0 */ +#define IFX_SSC_CON_readmask 0x01DF1FFF +#define IFX_SSC_CON_writemask 0x01DF1FFF +#define IFX_SSC_CON_hwmask 0x00000000 +#define IFX_SSC_CON_dontcare (IFX_SSC_CON_readmask & IFX_SSC_CON_writemask & ~IFX_SSC_CON_hwmask) + +/* address of the Status Register of the SSC */ +#define IFX_SSC_STATE 0x00000014 +/* IFX_SSC_STATE register is readable in bits 30:28, 26:24, 20:16, 12:7 and 2:0 + all bits except 1:0 are hardware modified */ +#define IFX_SSC_STATE_readmask 0x771F3F87 +#define IFX_SSC_STATE_writemask 0x00000000 +#define IFX_SSC_STATE_hwmask 0x771F3F84 +#define IFX_SSC_STATE_dontcare (IFX_SSC_STATE_readmask & IFX_SSC_STATE_writemask & ~IFX_SSC_STATE_hwmask) + +/* address of the Write Hardware Modified Control Register Bits of the SSC */ +#define IFX_SSC_WHBSTATE 0x00000018 +/* IFX_SSC_WHBSTATE register is write only */ +#define IFX_SSC_WHBSTATE_readmask 0x00000000 +#define IFX_SSC_WHBSTATE_writemask 0x0000FFFF +#define IFX_SSC_WHBSTATE_hwmask 0x00000000 +#define IFX_SSC_WHBSTATE_dontcare (IFX_SSC_WHBSTATE_readmask & IFX_SSC_WHBSTATE_writemask & ~IFX_SSC_WHBSTATE_hwmask) + +/* address of the Baudrate Timer Reload Register of the SSC */ +#define IFX_SSC_BR 0x00000040 +/* IFX_SSC_BR register is significant in bit 15 downto 0*/ +#define IFX_SSC_BR_readmask 0x0000FFFF +#define IFX_SSC_BR_writemask 0x0000FFFF +#define IFX_SSC_BR_hwmask 0x00000000 +#define IFX_SSC_BR_dontcare (IFX_SSC_BR_readmask & IFX_SSC_BR_writemask & ~IFX_SSC_BR_hwmask) + +/* address of the Baudrate Timer Status Register of the SSC */ +#define IFX_SSC_BRSTAT 0x00000044 +/* IFX_SSC_BRSTAT register is significant in bit 15 downto 0*/ +#define IFX_SSC_BRSTAT_readmask 0x0000FFFF +#define IFX_SSC_BRSTAT_writemask 0x00000000 +#define IFX_SSC_BRSTAT_hwmask 0x0000FFFF +#define IFX_SSC_BRSTAT_dontcare (IFX_SSC_BRSTAT_readmask & IFX_SSC_BRSTAT_writemask & ~IFX_SSC_BRSTAT_hwmask) + +/* address of the Transmitter Buffer Register of the SSC */ +#define IFX_SSC_TB 0x00000020 +/* IFX_SSC_TB register is significant in bit 31 downto 0*/ +#define IFX_SSC_TB_readmask 0xFFFFFFFF +#define IFX_SSC_TB_writemask 0xFFFFFFFF +#define IFX_SSC_TB_hwmask 0x00000000 +#define IFX_SSC_TB_dontcare (IFX_SSC_TB_readmask & IFX_SSC_TB_writemask & ~IFX_SSC_TB_hwmask) + +/* address of the Reciver Buffer Register of the SSC */ +#define IFX_SSC_RB 0x00000024 +/* IFX_SSC_RB register is significant in no bits*/ +#define IFX_SSC_RB_readmask 0xFFFFFFFF +#define IFX_SSC_RB_writemask 0x00000000 +#define IFX_SSC_RB_hwmask 0xFFFFFFFF +#define IFX_SSC_RB_dontcare (IFX_SSC_RB_readmask & IFX_SSC_RB_writemask & ~IFX_SSC_RB_hwmask) + +/* address of the Receive FIFO Control Register of the SSC */ +#define IFX_SSC_RXFCON 0x00000030 +/* IFX_SSC_RXFCON register is significant in bit 13 downto 8 and bit 1 downto 0 */ +#define IFX_SSC_RXFCON_readmask 0x00003F03 +#define IFX_SSC_RXFCON_writemask 0x00003F03 +#define IFX_SSC_RXFCON_hwmask 0x00000000 +#define IFX_SSC_RXFCON_dontcare (IFX_SSC_RXFCON_readmask & IFX_SSC_RXFCON_writemask & ~IFX_SSC_RXFCON_hwmask) + +/* address of the Transmit FIFO Control Register of the SSC */ +#define IFX_SSC_TXFCON 0x00000034 +/* IFX_SSC_TXFCON register is significant in bit 13 downto 8 and bit 1 downto 0 */ +#define IFX_SSC_TXFCON_readmask 0x00003F03 +#define IFX_SSC_TXFCON_writemask 0x00003F03 +#define IFX_SSC_TXFCON_hwmask 0x00000000 +#define IFX_SSC_TXFCON_dontcare (IFX_SSC_TXFCON_readmask & IFX_SSC_TXFCON_writemask & ~IFX_SSC_TXFCON_hwmask) + +/* address of the FIFO Status Register of the SSC */ +#define IFX_SSC_FSTAT 0x00000038 +/* IFX_SSC_FSTAT register is significant in no bit*/ +#define IFX_SSC_FSTAT_readmask 0x00003F3F +#define IFX_SSC_FSTAT_writemask 0x00000000 +#define IFX_SSC_FSTAT_hwmask 0x00003F3F +#define IFX_SSC_FSTAT_dontcare (IFX_SSC_FSTAT_readmask & IFX_SSC_FSTAT_writemask & ~IFX_SSC_FSTAT_hwmask) + +/* address of the Data Frame Control register of the SSC */ +#define IFX_SSC_SFCON 0x00000060 +#define IFX_SSC_SFCON_readmask 0xFFDFFFFD +#define IFX_SSC_SFCON_writemask 0xFFDFFFFD +#define IFX_SSC_SFCON_hwmask 0x00000000 +#define IFX_SSC_SFCON_dontcare (IFX_SSC_SFCON_readmask & IFX_SSC_SFCON_writemask & ~IFX_SSC_SFCON_hwmask) + +/* address of the Data Frame Status register of the SSC */ +#define IFX_SSC_SFSTAT 0x00000064 +#define IFX_SSC_SFSTAT_readmask 0xFFC0FFF3 +#define IFX_SSC_SFSTAT_writemask 0x00000000 +#define IFX_SSC_SFSTAT_hwmask 0xFFC0FFF3 +#define IFX_SSC_SFSTAT_dontcare (IFX_SSC_SFSTAT_readmask & IFX_SSC_SFSTAT_writemask & ~IFX_SSC_SFSTAT_hwmask) + +/* address of the General Purpose Output Control register of the SSC */ +#define IFX_SSC_GPOCON 0x00000070 +#define IFX_SSC_GPOCON_readmask 0x0000FFFF +#define IFX_SSC_GPOCON_writemask 0x0000FFFF +#define IFX_SSC_GPOCON_hwmask 0x00000000 +#define IFX_SSC_GPOCON_dontcare (IFX_SSC_GPOCON_readmask & IFX_SSC_GPOCON_writemask & ~IFX_SSC_GPOCON_hwmask) + +/* address of the General Purpose Output Status register of the SSC */ +#define IFX_SSC_GPOSTAT 0x00000074 +#define IFX_SSC_GPOSTAT_readmask 0x000000FF +#define IFX_SSC_GPOSTAT_writemask 0x00000000 +#define IFX_SSC_GPOSTAT_hwmask 0x00000000 +#define IFX_SSC_GPOSTAT_dontcare (IFX_SSC_GPOSTAT_readmask & IFX_SSC_GPOSTAT_writemask & ~IFX_SSC_GPOSTAT_hwmask) + +/* address of the Force GPO Status register of the SSC */ +#define IFX_SSC_WHBGPOSTAT 0x00000078 +#define IFX_SSC_WHBGPOSTAT_readmask 0x00000000 +#define IFX_SSC_WHBGPOSTAT_writemask 0x0000FFFF +#define IFX_SSC_WHBGPOSTAT_hwmask 0x00000000 +#define IFX_SSC_WHBGPOSTAT_dontcare (IFX_SSC_WHBGPOSTAT_readmask & IFX_SSC_WHBGPOSTAT_writemask & ~IFX_SSC_WHBGPOSTAT_hwmask) + +/* address of the Receive Request Register of the SSC */ +#define IFX_SSC_RXREQ 0x00000080 +#define IFX_SSC_RXREQ_readmask 0x0000FFFF +#define IFX_SSC_RXREQ_writemask 0x0000FFFF +#define IFX_SSC_RXREQ_hwmask 0x00000000 +#define IFX_SSC_RXREQ_dontcare (IFX_SSC_RXREQ_readmask & IFX_SSC_RXREQ_writemask & ~IFX_SSC_RXREQ_hwmask) + +/* address of the Receive Count Register of the SSC */ +#define IFX_SSC_RXCNT 0x00000084 +#define IFX_SSC_RXCNT_readmask 0x0000FFFF +#define IFX_SSC_RXCNT_writemask 0x00000000 +#define IFX_SSC_RXCNT_hwmask 0x0000FFFF +#define IFX_SSC_RXCNT_dontcare (IFX_SSC_RXCNT_readmask & IFX_SSC_RXCNT_writemask & ~IFX_SSC_RXCNT_hwmask) + +/* address of the DMA Configuration Register of the SSC */ +#define IFX_SSC_DMACON 0x000000EC +#define IFX_SSC_DMACON_readmask 0x0000FFFF +#define IFX_SSC_DMACON_writemask 0x00000000 +#define IFX_SSC_DMACON_hwmask 0x0000FFFF +#define IFX_SSC_DMACON_dontcare (IFX_SSC_DMACON_readmask & IFX_SSC_DMACON_writemask & ~IFX_SSC_DMACON_hwmask) + +//------------------------------------------------------ +// interrupt register for enabling interrupts, mask register of irq_reg +#define IFX_SSC_IRN_EN 0xF4 +// read/write +#define IFX_SSC_IRN_EN_readmask 0x0000000F +#define IFX_SSC_IRN_EN_writemask 0x0000000F +#define IFX_SSC_IRN_EN_hwmask 0x00000000 +#define IFX_SSC_IRN_EN_dontcare (IFX_SSC_IRN_EN_readmask & IFX_SSC_IRN_EN_writemask & ~IFX_SSC_IRN_EN_hwmask) + +// interrupt register for accessing interrupts +#define IFX_SSC_IRN_CR 0xF8 +// read/write +#define IFX_SSC_IRN_CR_readmask 0x0000000F +#define IFX_SSC_IRN_CR_writemask 0x0000000F +#define IFX_SSC_IRN_CR_hwmask 0x0000000F +#define IFX_SSC_IRN_CR_dontcare (IFX_SSC_IRN_CR_readmask & IFX_SSC_IRN_CR_writemask & ~IFX_SSC_IRN_CR_hwmask) + +// interrupt register for stimulating interrupts +#define IFX_SSC_IRN_ICR 0xFC +// read/write +#define IFX_SSC_IRN_ICR_readmask 0x0000000F +#define IFX_SSC_IRN_ICR_writemask 0x0000000F +#define IFX_SSC_IRN_ICR_hwmask 0x00000000 +#define IFX_SSC_IRN_ICR_dontcare (IFX_SSC_IRN_ICR_readmask & IFX_SSC_IRN_ICR_writemask & ~IFX_SSC_IRN_ICR_hwmask) + +//--------------------------------------------------------------------- +// Number of IRQs and bitposition of IRQ +#define IFX_SSC_NUM_IRQ 4 +#define IFX_SSC_T_BIT 0x00000001 +#define IFX_SSC_R_BIT 0x00000002 +#define IFX_SSC_E_BIT 0x00000004 +#define IFX_SSC_F_BIT 0x00000008 + +/* bit masks for SSC registers */ + +/* ID register */ +#define IFX_SSC_PERID_REV_MASK 0x0000001F +#define IFX_SSC_PERID_CFG_MASK 0x00000020 +#define IFX_SSC_PERID_ID_MASK 0x0000FF00 +#define IFX_SSC_PERID_REV_OFFSET 0 +#define IFX_SSC_PERID_CFG_OFFSET 5 +#define IFX_SSC_PERID_ID_OFFSET 8 +#define IFX_SSC_PERID_ID 0x45 +#define IFX_SSC_PERID_DMA_ON 0x00000020 +#define IFX_SSC_PERID_RXFS_MASK 0x003F0000 +#define IFX_SSC_PERID_RXFS_OFFSET 16 +#define IFX_SSC_PERID_TXFS_MASK 0x3F000000 +#define IFX_SSC_PERID_TXFS_OFFSET 24 + +/* PISEL register */ +#define IFX_SSC_PISEL_MASTER_IN_A 0x0000 +#define IFX_SSC_PISEL_MASTER_IN_B 0x0001 +#define IFX_SSC_PISEL_SLAVE_IN_A 0x0000 +#define IFX_SSC_PISEL_SLAVE_IN_B 0x0002 +#define IFX_SSC_PISEL_CLOCK_IN_A 0x0000 +#define IFX_SSC_PISEL_CLOCK_IN_B 0x0004 + +/* IFX_SSC_CON register */ +#define IFX_SSC_CON_ECHO_MODE_ON 0x01000000 +#define IFX_SSC_CON_ECHO_MODE_OFF 0x00000000 +#define IFX_SSC_CON_IDLE_HIGH 0x00800000 +#define IFX_SSC_CON_IDLE_LOW 0x00000000 +#define IFX_SSC_CON_ENABLE_BYTE_VALID 0x00400000 +#define IFX_SSC_CON_DISABLE_BYTE_VALID 0x00000000 +#define IFX_SSC_CON_DATA_WIDTH_OFFSET 16 +#define IFX_SSC_CON_DATA_WIDTH_MASK 0x001F0000 +#define IFX_SSC_ENCODE_DATA_WIDTH(width) (((width - 1) << IFX_SSC_CON_DATA_WIDTH_OFFSET) & IFX_SSC_CON_DATA_WIDTH_MASK) + +#define IFX_SSC_CON_RESET_ON_BAUDERR 0x00002000 +#define IFX_SSC_CON_GO_ON_ON_BAUDERR 0x00000000 + +#define IFX_SSC_CON_RX_UFL_CHECK 0x00001000 +#define IFX_SSC_CON_RX_UFL_IGNORE 0x00000000 +#define IFX_SSC_CON_TX_UFL_CHECK 0x00000800 +#define IFX_SSC_CON_TX_UFL_IGNORE 0x00000000 +#define IFX_SSC_CON_ABORT_ERR_CHECK 0x00000400 +#define IFX_SSC_CON_ABORT_ERR_IGNORE 0x00000000 +#define IFX_SSC_CON_RX_OFL_CHECK 0x00000200 +#define IFX_SSC_CON_RX_OFL_IGNORE 0x00000000 +#define IFX_SSC_CON_TX_OFL_CHECK 0x00000100 +#define IFX_SSC_CON_TX_OFL_IGNORE 0x00000000 +#define IFX_SSC_CON_ALL_ERR_CHECK 0x00001F00 +#define IFX_SSC_CON_ALL_ERR_IGNORE 0x00000000 + +#define IFX_SSC_CON_LOOPBACK_MODE 0x00000080 +#define IFX_SSC_CON_NO_LOOPBACK 0x00000000 +#define IFX_SSC_CON_HALF_DUPLEX 0x00000080 +#define IFX_SSC_CON_FULL_DUPLEX 0x00000000 +#define IFX_SSC_CON_CLOCK_FALL 0x00000040 +#define IFX_SSC_CON_CLOCK_RISE 0x00000000 +#define IFX_SSC_CON_SHIFT_THEN_LATCH 0x00000000 +#define IFX_SSC_CON_LATCH_THEN_SHIFT 0x00000020 +#define IFX_SSC_CON_MSB_FIRST 0x00000010 +#define IFX_SSC_CON_LSB_FIRST 0x00000000 +#define IFX_SSC_CON_ENABLE_CSB 0x00000008 +#define IFX_SSC_CON_DISABLE_CSB 0x00000000 +#define IFX_SSC_CON_INVERT_CSB 0x00000004 +#define IFX_SSC_CON_TRUE_CSB 0x00000000 +#define IFX_SSC_CON_RX_OFF 0x00000002 +#define IFX_SSC_CON_RX_ON 0x00000000 +#define IFX_SSC_CON_TX_OFF 0x00000001 +#define IFX_SSC_CON_TX_ON 0x00000000 + +/* IFX_SSC_STATE register */ +#define IFX_SSC_STATE_RX_BYTE_VALID_OFFSET 28 +#define IFX_SSC_STATE_RX_BYTE_VALID_MASK 0x70000000 +#define IFX_SSC_DECODE_RX_BYTE_VALID(con_state) ((con_state & IFX_SSC_STATE_RX_BYTE_VALID_MASK) >> IFX_SSC_STATE_RX_BYTE_VALID_OFFSET) +#define IFX_SSC_STATE_TX_BYTE_VALID_OFFSET 24 +#define IFX_SSC_STATE_TX_BYTE_VALID_MASK 0x07000000 +#define IFX_SSC_DECODE_TX_BYTE_VALID(con_state) ((con_state & IFX_SSC_STATE_TX_BYTE_VALID_MASK) >> IFX_SSC_STATE_TX_BYTE_VALID_OFFSET) +#define IFX_SSC_STATE_BIT_COUNT_OFFSET 16 +#define IFX_SSC_STATE_BIT_COUNT_MASK 0x001F0000 +#define IFX_SSC_DECODE_DATA_WIDTH(con_state) (((con_state & IFX_SSC_STATE_BIT_COUNT_MASK) >> IFX_SSC_STATE_BIT_COUNT_OFFSET) + 1) +#define IFX_SSC_STATE_BUSY 0x00002000 +#define IFX_SSC_STATE_RX_UFL 0x00001000 +#define IFX_SSC_STATE_TX_UFL 0x00000800 +#define IFX_SSC_STATE_ABORT_ERR 0x00000400 +#define IFX_SSC_STATE_RX_OFL 0x00000200 +#define IFX_SSC_STATE_TX_OFL 0x00000100 +#define IFX_SSC_STATE_MODE_ERR 0x00000080 +#define IFX_SSC_STATE_SLAVE_IS_SELECTED 0x00000004 +#define IFX_SSC_STATE_IS_MASTER 0x00000002 +#define IFX_SSC_STATE_IS_ENABLED 0x00000001 + +/* WHBSTATE register */ +#define IFX_SSC_WHBSTATE_DISABLE_SSC 0x0001 +#define IFX_SSC_WHBSTATE_CONFIGURATION_MODE 0x0001 +#define IFX_SSC_WHBSTATE_CLR_ENABLE 0x0001 + +#define IFX_SSC_WHBSTATE_ENABLE_SSC 0x0002 +#define IFX_SSC_WHBSTATE_RUN_MODE 0x0002 +#define IFX_SSC_WHBSTATE_SET_ENABLE 0x0002 + +#define IFX_SSC_WHBSTATE_SLAVE_MODE 0x0004 +#define IFX_SSC_WHBSTATE_CLR_MASTER_SELECT 0x0004 + +#define IFX_SSC_WHBSTATE_MASTER_MODE 0x0008 +#define IFX_SSC_WHBSTATE_SET_MASTER_SELECT 0x0008 + +#define IFX_SSC_WHBSTATE_CLR_RX_UFL_ERROR 0x0010 +#define IFX_SSC_WHBSTATE_SET_RX_UFL_ERROR 0x0020 + +#define IFX_SSC_WHBSTATE_CLR_MODE_ERROR 0x0040 +#define IFX_SSC_WHBSTATE_SET_MODE_ERROR 0x0080 + +#define IFX_SSC_WHBSTATE_CLR_TX_OFL_ERROR 0x0100 +#define IFX_SSC_WHBSTATE_CLR_RX_OFL_ERROR 0x0200 +#define IFX_SSC_WHBSTATE_CLR_ABORT_ERROR 0x0400 +#define IFX_SSC_WHBSTATE_CLR_TX_UFL_ERROR 0x0800 +#define IFX_SSC_WHBSTATE_SET_TX_OFL_ERROR 0x1000 +#define IFX_SSC_WHBSTATE_SET_RX_OFL_ERROR 0x2000 +#define IFX_SSC_WHBSTATE_SET_ABORT_ERROR 0x4000 +#define IFX_SSC_WHBSTATE_SET_TX_UFL_ERROR 0x8000 +#define IFX_SSC_WHBSTATE_CLR_ALL_ERROR 0x0F50 +#define IFX_SSC_WHBSTATE_SET_ALL_ERROR 0xF0A0 + +/* BR register */ +#define IFX_SSC_BR_BAUDRATE_OFFSET 0 +#define IFX_SSC_BR_BAUDRATE_MASK 0xFFFF + +/* BR_STAT register */ +#define IFX_SSC_BRSTAT_BAUDTIMER_OFFSET 0 +#define IFX_SSC_BRSTAT_BAUDTIMER_MASK 0xFFFF + +/* TB register */ +#define IFX_SSC_TB_DATA_OFFSET 0 +#define IFX_SSC_TB_DATA_MASK 0xFFFFFFFF + +/* RB register */ +#define IFX_SSC_RB_DATA_OFFSET 0 +#define IFX_SSC_RB_DATA_MASK 0xFFFFFFFF + +/* RXFCON and TXFCON registers */ +#define IFX_SSC_XFCON_FIFO_DISABLE 0x0000 +#define IFX_SSC_XFCON_FIFO_ENABLE 0x0001 +#define IFX_SSC_XFCON_FIFO_FLUSH 0x0002 +#define IFX_SSC_XFCON_ITL_MASK 0x00003F00 +#define IFX_SSC_XFCON_ITL_OFFSET 8 + +/* FSTAT register */ +#define IFX_SSC_FSTAT_RECEIVED_WORDS_OFFSET 0 +#define IFX_SSC_FSTAT_RECEIVED_WORDS_MASK 0x003F +#define IFX_SSC_FSTAT_TRANSMIT_WORDS_OFFSET 8 +#define IFX_SSC_FSTAT_TRANSMIT_WORDS_MASK 0x3F00 + +/* GPOCON register */ +#define IFX_SSC_GPOCON_INVOUT0_POS 0 +#define IFX_SSC_GPOCON_INV_OUT0 0x00000001 +#define IFX_SSC_GPOCON_TRUE_OUT0 0x00000000 +#define IFX_SSC_GPOCON_INVOUT1_POS 1 +#define IFX_SSC_GPOCON_INV_OUT1 0x00000002 +#define IFX_SSC_GPOCON_TRUE_OUT1 0x00000000 +#define IFX_SSC_GPOCON_INVOUT2_POS 2 +#define IFX_SSC_GPOCON_INV_OUT2 0x00000003 +#define IFX_SSC_GPOCON_TRUE_OUT2 0x00000000 +#define IFX_SSC_GPOCON_INVOUT3_POS 3 +#define IFX_SSC_GPOCON_INV_OUT3 0x00000008 +#define IFX_SSC_GPOCON_TRUE_OUT3 0x00000000 +#define IFX_SSC_GPOCON_INVOUT4_POS 4 +#define IFX_SSC_GPOCON_INV_OUT4 0x00000010 +#define IFX_SSC_GPOCON_TRUE_OUT4 0x00000000 +#define IFX_SSC_GPOCON_INVOUT5_POS 5 +#define IFX_SSC_GPOCON_INV_OUT5 0x00000020 +#define IFX_SSC_GPOCON_TRUE_OUT5 0x00000000 +#define IFX_SSC_GPOCON_INVOUT6_POS 6 +#define IFX_SSC_GPOCON_INV_OUT6 0x00000040 +#define IFX_SSC_GPOCON_TRUE_OUT6 0x00000000 +#define IFX_SSC_GPOCON_INVOUT7_POS 7 +#define IFX_SSC_GPOCON_INV_OUT7 0x00000080 +#define IFX_SSC_GPOCON_TRUE_OUT7 0x00000000 +#define IFX_SSC_GPOCON_INV_OUT_ALL 0x000000FF +#define IFX_SSC_GPOCON_TRUE_OUT_ALL 0x00000000 + +#define IFX_SSC_GPOCON_ISCSB0_POS 8 +#define IFX_SSC_GPOCON_IS_CSB0 0x00000100 +#define IFX_SSC_GPOCON_IS_GPO0 0x00000000 +#define IFX_SSC_GPOCON_ISCSB1_POS 9 +#define IFX_SSC_GPOCON_IS_CSB1 0x00000200 +#define IFX_SSC_GPOCON_IS_GPO1 0x00000000 +#define IFX_SSC_GPOCON_ISCSB2_POS 10 +#define IFX_SSC_GPOCON_IS_CSB2 0x00000400 +#define IFX_SSC_GPOCON_IS_GPO2 0x00000000 +#define IFX_SSC_GPOCON_ISCSB3_POS 11 +#define IFX_SSC_GPOCON_IS_CSB3 0x00000800 +#define IFX_SSC_GPOCON_IS_GPO3 0x00000000 +#define IFX_SSC_GPOCON_ISCSB4_POS 12 +#define IFX_SSC_GPOCON_IS_CSB4 0x00001000 +#define IFX_SSC_GPOCON_IS_GPO4 0x00000000 +#define IFX_SSC_GPOCON_ISCSB5_POS 13 +#define IFX_SSC_GPOCON_IS_CSB5 0x00002000 +#define IFX_SSC_GPOCON_IS_GPO5 0x00000000 +#define IFX_SSC_GPOCON_ISCSB6_POS 14 +#define IFX_SSC_GPOCON_IS_CSB6 0x00004000 +#define IFX_SSC_GPOCON_IS_GPO6 0x00000000 +#define IFX_SSC_GPOCON_ISCSB7_POS 15 +#define IFX_SSC_GPOCON_IS_CSB7 0x00008000 +#define IFX_SSC_GPOCON_IS_GPO7 0x00000000 +#define IFX_SSC_GPOCON_IS_CSB_ALL 0x0000FF00 +#define IFX_SSC_GPOCON_IS_GPO_ALL 0x00000000 + +/* GPOSTAT register */ +#define IFX_SSC_GPOSTAT_OUT0 0x00000001 +#define IFX_SSC_GPOSTAT_OUT1 0x00000002 +#define IFX_SSC_GPOSTAT_OUT2 0x00000004 +#define IFX_SSC_GPOSTAT_OUT3 0x00000008 +#define IFX_SSC_GPOSTAT_OUT4 0x00000010 +#define IFX_SSC_GPOSTAT_OUT5 0x00000020 +#define IFX_SSC_GPOSTAT_OUT6 0x00000040 +#define IFX_SSC_GPOSTAT_OUT7 0x00000080 +#define IFX_SSC_GPOSTAT_OUT_ALL 0x000000FF + +/* WHBGPOSTAT register */ +#define IFX_SSC_WHBGPOSTAT_CLROUT0_POS 0 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT0 0x00000001 +#define IFX_SSC_WHBGPOSTAT_CLROUT1_POS 1 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT1 0x00000002 +#define IFX_SSC_WHBGPOSTAT_CLROUT2_POS 2 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT2 0x00000004 +#define IFX_SSC_WHBGPOSTAT_CLROUT3_POS 3 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT3 0x00000008 +#define IFX_SSC_WHBGPOSTAT_CLROUT4_POS 4 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT4 0x00000010 +#define IFX_SSC_WHBGPOSTAT_CLROUT5_POS 5 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT5 0x00000020 +#define IFX_SSC_WHBGPOSTAT_CLROUT6_POS 6 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT6 0x00000040 +#define IFX_SSC_WHBGPOSTAT_CLROUT7_POS 7 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT7 0x00000080 +#define IFX_SSC_WHBGPOSTAT_CLR_OUT_ALL 0x000000FF + +#define IFX_SSC_WHBGPOSTAT_OUT0_POS 0 +#define IFX_SSC_WHBGPOSTAT_OUT1_POS 1 +#define IFX_SSC_WHBGPOSTAT_OUT2_POS 2 +#define IFX_SSC_WHBGPOSTAT_OUT3_POS 3 +#define IFX_SSC_WHBGPOSTAT_OUT4_POS 4 +#define IFX_SSC_WHBGPOSTAT_OUT5_POS 5 +#define IFX_SSC_WHBGPOSTAT_OUT6_POS 6 +#define IFX_SSC_WHBGPOSTAT_OUT7_POS 7 + +#define IFX_SSC_WHBGPOSTAT_SETOUT0_POS 8 +#define IFX_SSC_WHBGPOSTAT_SET_OUT0 0x00000100 +#define IFX_SSC_WHBGPOSTAT_SETOUT1_POS 9 +#define IFX_SSC_WHBGPOSTAT_SET_OUT1 0x00000200 +#define IFX_SSC_WHBGPOSTAT_SETOUT2_POS 10 +#define IFX_SSC_WHBGPOSTAT_SET_OUT2 0x00000400 +#define IFX_SSC_WHBGPOSTAT_SETOUT3_POS 11 +#define IFX_SSC_WHBGPOSTAT_SET_OUT3 0x00000800 +#define IFX_SSC_WHBGPOSTAT_SETOUT4_POS 12 +#define IFX_SSC_WHBGPOSTAT_SET_OUT4 0x00001000 +#define IFX_SSC_WHBGPOSTAT_SETOUT5_POS 13 +#define IFX_SSC_WHBGPOSTAT_SET_OUT5 0x00002000 +#define IFX_SSC_WHBGPOSTAT_SETOUT6_POS 14 +#define IFX_SSC_WHBGPOSTAT_SET_OUT6 0x00004000 +#define IFX_SSC_WHBGPOSTAT_SETOUT7_POS 15 +#define IFX_SSC_WHBGPOSTAT_SET_OUT7 0x00008000 +#define IFX_SSC_WHBGPOSTAT_SET_OUT_ALL 0x0000FF00 + +/* SFCON register */ +#define IFX_SSC_SFCON_SF_ENABLE 0x00000001 +#define IFX_SSC_SFCON_SF_DISABLE 0x00000000 +#define IFX_SSC_SFCON_FIR_ENABLE_BEFORE_PAUSE 0x00000004 +#define IFX_SSC_SFCON_FIR_DISABLE_BEFORE_PAUSE 0x00000000 +#define IFX_SSC_SFCON_FIR_ENABLE_AFTER_PAUSE 0x00000008 +#define IFX_SSC_SFCON_FIR_DISABLE_AFTER_PAUSE 0x00000000 +#define IFX_SSC_SFCON_DATA_LENGTH_MASK 0x0000FFF0 +#define IFX_SSC_SFCON_DATA_LENGTH_OFFSET 4 +#define IFX_SSC_SFCON_PAUSE_DATA_MASK 0x00030000 +#define IFX_SSC_SFCON_PAUSE_DATA_OFFSET 16 +#define IFX_SSC_SFCON_PAUSE_DATA_0 0x00000000 +#define IFX_SSC_SFCON_PAUSE_DATA_1 0x00010000 +#define IFX_SSC_SFCON_PAUSE_DATA_IDLE 0x00020000 +#define IFX_SSC_SFCON_PAUSE_CLOCK_MASK 0x000C0000 +#define IFX_SSC_SFCON_PAUSE_CLOCK_OFFSET 18 +#define IFX_SSC_SFCON_PAUSE_CLOCK_0 0x00000000 +#define IFX_SSC_SFCON_PAUSE_CLOCK_1 0x00040000 +#define IFX_SSC_SFCON_PAUSE_CLOCK_IDLE 0x00080000 +#define IFX_SSC_SFCON_PAUSE_CLOCK_RUN 0x000C0000 +#define IFX_SSC_SFCON_STOP_AFTER_PAUSE 0x00100000 +#define IFX_SSC_SFCON_CONTINUE_AFTER_PAUSE 0x00000000 +#define IFX_SSC_SFCON_PAUSE_LENGTH_MASK 0xFFC00000 +#define IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET 22 +#define IFX_SSC_SFCON_DATA_LENGTH_MAX 4096 +#define IFX_SSC_SFCON_PAUSE_LENGTH_MAX 1024 + +#define IFX_SSC_SFCON_EXTRACT_DATA_LENGTH(sfcon) ((sfcon & IFX_SSC_SFCON_DATA_LENGTH_MASK) >> IFX_SSC_SFCON_DATA_LENGTH_OFFSET) +#define IFX_SSC_SFCON_EXTRACT_PAUSE_LENGTH(sfcon) ((sfcon & IFX_SSC_SFCON_PAUSE_LENGTH_MASK) >> IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET) +#define IFX_SSC_SFCON_SET_DATA_LENGTH(value) ((value << IFX_SSC_SFCON_DATA_LENGTH_OFFSET) & IFX_SSC_SFCON_DATA_LENGTH_MASK) +#define IFX_SSC_SFCON_SET_PAUSE_LENGTH(value) ((value << IFX_SSC_SFCON_PAUSE_LENGTH_OFFSET) & IFX_SSC_SFCON_PAUSE_LENGTH_MASK) + +/* SFSTAT register */ +#define IFX_SSC_SFSTAT_IN_DATA 0x00000001 +#define IFX_SSC_SFSTAT_IN_PAUSE 0x00000002 +#define IFX_SSC_SFSTAT_DATA_COUNT_MASK 0x0000FFF0 +#define IFX_SSC_SFSTAT_DATA_COUNT_OFFSET 4 +#define IFX_SSC_SFSTAT_PAUSE_COUNT_MASK 0xFFF00000 +#define IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET 20 + +#define IFX_SSC_SFSTAT_EXTRACT_DATA_COUNT(sfstat) ((sfstat & IFX_SSC_SFSTAT_DATA_COUNT_MASK) >> IFX_SSC_SFSTAT_DATA_COUNT_OFFSET) +#define IFX_SSC_SFSTAT_EXTRACT_PAUSE_COUNT(sfstat) ((sfstat & IFX_SSC_SFSTAT_PAUSE_COUNT_MASK) >> IFX_SSC_SFSTAT_PAUSE_COUNT_OFFSET) + +/* RXREQ register */ +#define IFX_SSC_RXREQ_RXCOUNT_MASK 0x0000FFFF +#define IFX_SSC_RXREQ_RXCOUNT_OFFSET 0 + +/* RXCNT register */ +#define IFX_SSC_RXCNT_TODO_MASK 0x0000FFFF +#define IFX_SSC_RXCNT_TODO_OFFSET 0 + +/* DMACON register */ +#define IFX_SSC_DMACON_RXON 0x00000001 +#define IFX_SSC_DMACON_RXOFF 0x00000000 +#define IFX_SSC_DMACON_TXON 0x00000002 +#define IFX_SSC_DMACON_TXOFF 0x00000000 +#define IFX_SSC_DMACON_DMAON 0x00000003 +#define IFX_SSC_DMACON_DMAOFF 0x00000000 +#define IFX_SSC_DMACON_CLASS_MASK 0x0000000C +#define IFX_SSC_DMACON_CLASS_OFFSET 2 + +/* register access macros */ +#define ifx_ssc_fstat_received_words(status) (status & 0x003F) +#define ifx_ssc_fstat_words_to_transmit(status) ((status & 0x3F00) >> 8) + +#define ifx_ssc_change_status(data, addr) WRITE_PERIPHERAL_REGISTER(data, (PHYS_OFFSET + addr + IFX_SSC_WHBSTATE)) +#define ifx_ssc_set_config(data, addr) WRITE_PERIPHERAL_REGISTER(data, (PHYS_OFFSET + addr + IFX_SSC_CON)) +#define ifx_ssc_get_config(addr) READ_PERIPHERAL_REGISTER((PHYS_OFFSET + addr + IFX_SSC_CON)) +#define ifx_ssc_get_status(addr) READ_PERIPHERAL_REGISTER((PHYS_OFFSET + addr + IFX_SSC_STATE)) +#define ifx_ssc_receive(addr) READ_PERIPHERAL_REGISTER((PHYS_OFFSET + addr + IFX_SSC_RB)) +#define ifx_ssc_transmit(data, addr) WRITE_PERIPHERAL_REGISTER(data, (PHYS_OFFSET + addr + IFX_SSC_TB)) +#define ifx_ssc_fifo_status(addr) READ_PERIPHERAL_REGISTER((PHYS_OFFSET + addr + IFX_SSC_FSTAT)) +#define ifx_ssc_set_baudrate(data, addr) WRITE_PERIPHERAL_REGISTER(data, (PHYS_OFFSET + addr + IFX_SSC_BR)) + +#define ifx_ssc_extract_rx_fifo_size(id) ((id & IFX_SSC_PERID_RXFS_MASK) >> IFX_SSC_PERID_RXFS_OFFSET) +#define ifx_ssc_extract_tx_fifo_size(id) ((id & IFX_SSC_PERID_TXFS_MASK) >> IFX_SSC_PERID_TXFS_OFFSET) + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips.h new file mode 100644 index 0000000000..2180f44394 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips.h @@ -0,0 +1,515 @@ +/* + * 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. + * + * Copyright (C) 2005 infineon + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_H__ +#define _IFXMIPS_H__ + +#define ifxmips_r32(reg) __raw_readl(reg) +#define ifxmips_w32(val,reg) __raw_writel(val,reg) +#define ifxmips_w32_mask(clear,set,reg) ifxmips_w32((ifxmips_r32(reg) & ~clear) | set, reg) + +/*------------ GENERAL */ + +#define BOARD_SYSTEM_TYPE "IFXMIPS" + +#define IOPORT_RESOURCE_START 0x10000000 +#define IOPORT_RESOURCE_END 0xffffffff +#define IOMEM_RESOURCE_START 0x10000000 +#define IOMEM_RESOURCE_END 0xffffffff + +#define IFXMIPS_FLASH_START 0x10000000 +#define IFXMIPS_FLASH_MAX 0x2000000 + + +/*------------ ASC1 */ + +#define IFXMIPS_ASC_BASE_ADDR (KSEG1 + 0x1E100400) +#define IFXMIPS_ASC_BASE_DIFF (0x1E100C00 - 0x1E100400) + +#define IFXMIPS_ASC_FSTAT 0x0048 +#define IFXMIPS_ASC_TBUF 0x0020 +#define IFXMIPS_ASC_WHBSTATE 0x0018 +#define IFXMIPS_ASC_RBUF 0x0024 +#define IFXMIPS_ASC_STATE 0x0014 +#define IFXMIPS_ASC_IRNCR 0x00F8 +#define IFXMIPS_ASC_CLC 0x0000 +#define IFXMIPS_ASC_PISEL 0x0004 +#define IFXMIPS_ASC_TXFCON 0x0044 +#define IFXMIPS_ASC_RXFCON 0x0040 +#define IFXMIPS_ASC_CON 0x0010 +#define IFXMIPS_ASC_BG 0x0050 +#define IFXMIPS_ASC_IRNREN 0x00F4 + +#define IFXMIPS_ASC_CLC_DISS 0x2 +#define ASC_IRNREN_RX_BUF 0x8 +#define ASC_IRNREN_TX_BUF 0x4 +#define ASC_IRNREN_ERR 0x2 +#define ASC_IRNREN_TX 0x1 +#define ASC_IRNCR_TIR 0x4 +#define ASC_IRNCR_RIR 0x2 +#define ASC_IRNCR_EIR 0x4 +#define ASCOPT_CSIZE 0x3 +#define ASCOPT_CS7 0x1 +#define ASCOPT_CS8 0x2 +#define ASCOPT_PARENB 0x4 +#define ASCOPT_STOPB 0x8 +#define ASCOPT_PARODD 0x0 +#define ASCOPT_CREAD 0x20 +#define TXFIFO_FL 1 +#define RXFIFO_FL 1 +#define TXFIFO_FULL 16 +#define ASCCLC_RMCMASK 0x0000FF00 +#define ASCCLC_RMCOFFSET 8 +#define ASCCON_M_8ASYNC 0x0 +#define ASCCON_M_7ASYNC 0x2 +#define ASCCON_ODD 0x00000020 +#define ASCCON_STP 0x00000080 +#define ASCCON_BRS 0x00000100 +#define ASCCON_FDE 0x00000200 +#define ASCCON_R 0x00008000 +#define ASCCON_FEN 0x00020000 +#define ASCCON_ROEN 0x00080000 +#define ASCCON_TOEN 0x00100000 +#define ASCSTATE_PE 0x00010000 +#define ASCSTATE_FE 0x00020000 +#define ASCSTATE_ROE 0x00080000 +#define ASCSTATE_ANY (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE) +#define ASCWHBSTATE_CLRREN 0x00000001 +#define ASCWHBSTATE_SETREN 0x00000002 +#define ASCWHBSTATE_CLRPE 0x00000004 +#define ASCWHBSTATE_CLRFE 0x00000008 +#define ASCWHBSTATE_CLRROE 0x00000020 +#define ASCTXFCON_TXFEN 0x0001 +#define ASCTXFCON_TXFFLU 0x0002 +#define ASCTXFCON_TXFITLMASK 0x3F00 +#define ASCTXFCON_TXFITLOFF 8 +#define ASCRXFCON_RXFEN 0x0001 +#define ASCRXFCON_RXFFLU 0x0002 +#define ASCRXFCON_RXFITLMASK 0x3F00 +#define ASCRXFCON_RXFITLOFF 8 +#define ASCFSTAT_RXFFLMASK 0x003F +#define ASCFSTAT_TXFFLMASK 0x3F00 +#define ASCFSTAT_TXFFLOFF 8 + + + +/*------------ RCU */ +#define IFXMIPS_RCU_BASE_ADDR 0xBF203000 + +/* reset request */ +#define IFXMIPS_RCU_RST ((u32*)(IFXMIPS_RCU_BASE_ADDR + 0x0010)) +#define IFXMIPS_RCU_RST_CPU1 (1 << 3) +#define IFXMIPS_RCU_RST_ALL 0x40000000 + +#define IFXMIPS_RCU_RST_REQ_DFE (1 << 7) +#define IFXMIPS_RCU_RST_REQ_AFE (1 << 11) +#define IFXMIPS_RCU_RST_REQ_ARC_JTAG (1 << 20) + + +/*------------ GPTU */ + +#define IFXMIPS_GPTU_BASE_ADDR 0xB8000300 + +/* clock control register */ +#define IFXMIPS_GPTU_GPT_CLC ((u32*)(IFXMIPS_GPTU_BASE_ADDR + 0x0000)) + +/* captur reload register */ +#define IFXMIPS_GPTU_GPT_CAPREL ((u32*)(IFXMIPS_GPTU_BASE_ADDR + 0x0030)) + +/* timer 6 control register */ +#define IFXMIPS_GPTU_GPT_T6CON ((u32*)(IFXMIPS_GPTU_BASE_ADDR + 0x0020)) + + +/*------------ EBU */ + +#define IFXMIPS_EBU_BASE_ADDR 0xBE105300 + +/* bus configuration register */ +#define IFXMIPS_EBU_BUSCON0 ((u32*)(IFXMIPS_EBU_BASE_ADDR + 0x0060)) +#define IFXMIPS_EBU_PCC_CON ((u32*)(IFXMIPS_EBU_BASE_ADDR + 0x0090)) +#define IFXMIPS_EBU_PCC_IEN ((u32*)(IFXMIPS_EBU_BASE_ADDR + 0x00A4)) +#define IFXMIPS_EBU_PCC_ISTAT ((u32*)(IFXMIPS_EBU_BASE_ADDR + 0x00A0)) + + +/*------------ CGU */ +#define IFXMIPS_CGU_BASE_ADDR (KSEG1 + 0x1F103000) +#define IFXMIPS_CGU_PLL0_CFG ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0004)) +#define IFXMIPS_CGU_PLL1_CFG ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0008)) +#define IFXMIPS_CGU_PLL2_CFG ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x000C)) +#define IFXMIPS_CGU_SYS ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0010)) +#define IFXMIPS_CGU_UPDATE ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0014)) +#define IFXMIPS_CGU_IF_CLK ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0018)) +#define IFXMIPS_CGU_OSC_CON ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x001C)) +#define IFXMIPS_CGU_SMD ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0020)) +#define IFXMIPS_CGU_CT1SR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0028)) +#define IFXMIPS_CGU_CT2SR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x002C)) +#define IFXMIPS_CGU_PCMCR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0030)) +#define IFXMIPS_CGU_PCI_CR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0034)) +#define IFXMIPS_CGU_PD_PC ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0038)) +#define IFXMIPS_CGU_FMR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x003C)) + +/* clock mux */ +#define IFXMIPS_CGU_SYS ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0010)) +#define IFXMIPS_CGU_IFCCR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0018)) +#define IFXMIPS_CGU_PCICR ((u32*)(IFXMIPS_CGU_BASE_ADDR + 0x0034)) + +#define CLOCK_60M 60000000 +#define CLOCK_83M 83333333 +#define CLOCK_111M 111111111 +#define CLOCK_133M 133333333 +#define CLOCK_167M 166666667 +#define CLOCK_333M 333333333 + + +/*------------ CGU */ + +#define IFXMIPS_PMU_BASE_ADDR (KSEG1 + 0x1F102000) + +#define IFXMIPS_PMU_PWDCR ((u32*)(IFXMIPS_PMU_BASE_ADDR + 0x001C)) +#define IFXMIPS_PMU_PWDSR ((u32*)(IFXMIPS_PMU_BASE_ADDR + 0x0020)) + + +/*------------ ICU */ + +#define IFXMIPS_ICU_BASE_ADDR 0xBF880200 + + +#define IFXMIPS_ICU_IM0_ISR ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0000)) +#define IFXMIPS_ICU_IM0_IER ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0008)) +#define IFXMIPS_ICU_IM0_IOSR ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0010)) +#define IFXMIPS_ICU_IM0_IRSR ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0018)) +#define IFXMIPS_ICU_IM0_IMR ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0020)) + +#define IFXMIPS_ICU_IM1_ISR ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0028)) +#define IFXMIPS_ICU_IM2_IER ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x0058)) +#define IFXMIPS_ICU_IM5_IER ((u32*)(IFXMIPS_ICU_BASE_ADDR + 0x00D0)) + +#define IFXMIPS_ICU_OFFSET (IFXMIPS_ICU_IM1_ISR - IFXMIPS_ICU_IM0_ISR) + + +/*------------ ETOP */ + +#define IFXMIPS_PPE32_BASE_ADDR 0xBE180000 + +#define ETHERNET_PACKET_DMA_BUFFER_SIZE 0x600 + +#define IFXMIPS_PPE32_MEM_MAP ((u32*)(IFXMIPS_PPE32_BASE_ADDR + 0x10000)) +#define IFXMIPS_PPE32_SRST ((u32*)(IFXMIPS_PPE32_BASE_ADDR + 0x10080)) + +#define MII_MODE 1 +#define REV_MII_MODE 2 + +/* mdio access */ +#define IFXMIPS_PPE32_MDIO_CFG ((u32*)(IFXMIPS_PPE32_BASE_ADDR + 0x11800)) +#define IFXMIPS_PPE32_MDIO_ACC ((u32*)(IFXMIPS_PPE32_BASE_ADDR + 0x11804)) + +#define MDIO_ACC_REQUEST 0x80000000 +#define MDIO_ACC_READ 0x40000000 +#define MDIO_ACC_ADDR_MASK 0x1f +#define MDIO_ACC_ADDR_OFFSET 0x15 +#define MDIO_ACC_REG_MASK 0xff +#define MDIO_ACC_REG_OFFSET 0x10 +#define MDIO_ACC_VAL_MASK 0xffff + +/* configuration */ +#define IFXMIPS_PPE32_CFG ((u32*)(IFXMIPS_PPE32_MEM_MAP + 0x1808)) + +#define PPE32_MII_MASK 0xfffffffc +#define PPE32_MII_NORMAL 0x8 +#define PPE32_MII_REVERSE 0xe + +/* packet length */ +#define IFXMIPS_PPE32_IG_PLEN_CTRL ((u32*)(IFXMIPS_PPE32_MEM_MAP + 0x1820)) + +#define PPE32_PLEN_OVER 0x5ee +#define PPE32_PLEN_UNDER 0x400000 + +/* enet */ +#define IFXMIPS_PPE32_ENET_MAC_CFG ((u32*)(IFXMIPS_PPE32_MEM_MAP + 0x1840)) + +#define PPE32_CGEN 0x800 + + +/*------------ DMA */ +#define IFXMIPS_DMA_BASE_ADDR 0xBE104100 + +#define IFXMIPS_DMA_CS ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x18)) +#define IFXMIPS_DMA_CIE ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x2C)) +#define IFXMIPS_DMA_IRNEN ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0xf4)) +#define IFXMIPS_DMA_CCTRL ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x1C)) +#define IFXMIPS_DMA_CIS ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x28)) +#define IFXMIPS_DMA_CDLEN ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x24)) +#define IFXMIPS_DMA_PS ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x40)) +#define IFXMIPS_DMA_PCTRL ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x44)) +#define IFXMIPS_DMA_CTRL ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x10)) +#define IFXMIPS_DMA_CPOLL ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x14)) +#define IFXMIPS_DMA_CDBA ((u32*)(IFXMIPS_DMA_BASE_ADDR + 0x20)) + + +/*------------ PCI */ +#define PCI_CR_PR_BASE_ADDR (KSEG1 + 0x1E105400) + +#define PCI_CR_FCI_ADDR_MAP0 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00C0)) +#define PCI_CR_FCI_ADDR_MAP1 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00C4)) +#define PCI_CR_FCI_ADDR_MAP2 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00C8)) +#define PCI_CR_FCI_ADDR_MAP3 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00CC)) +#define PCI_CR_FCI_ADDR_MAP4 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00D0)) +#define PCI_CR_FCI_ADDR_MAP5 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00D4)) +#define PCI_CR_FCI_ADDR_MAP6 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00D8)) +#define PCI_CR_FCI_ADDR_MAP7 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00DC)) +#define PCI_CR_CLK_CTRL ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0000)) +#define PCI_CR_PCI_MOD ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0030)) +#define PCI_CR_PC_ARB ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0080)) +#define PCI_CR_FCI_ADDR_MAP11hg ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00E4)) +#define PCI_CR_BAR11MASK ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0044)) +#define PCI_CR_BAR12MASK ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0048)) +#define PCI_CR_BAR13MASK ((u32*)(PCI_CR_PR_BASE_ADDR + 0x004C)) +#define PCI_CS_BASE_ADDR1 ((u32*)(PCI_CS_PR_BASE_ADDR + 0x0010)) +#define PCI_CR_PCI_ADDR_MAP11 ((u32*)(PCI_CR_PR_BASE_ADDR + 0x0064)) +#define PCI_CR_FCI_BURST_LENGTH ((u32*)(PCI_CR_PR_BASE_ADDR + 0x00E8)) +#define PCI_CR_PCI_EOI ((u32*)(PCI_CR_PR_BASE_ADDR + 0x002C)) + +#define PCI_CS_PR_BASE_ADDR (KSEG1 + 0x17000000) + +#define PCI_CS_STS_CMD ((u32*)(PCI_CS_PR_BASE_ADDR + 0x0004)) + +#define PCI_MASTER0_REQ_MASK_2BITS 8 +#define PCI_MASTER1_REQ_MASK_2BITS 10 +#define PCI_MASTER2_REQ_MASK_2BITS 12 +#define INTERNAL_ARB_ENABLE_BIT 0 + + +/*------------ WDT */ + +#define IFXMIPS_WDT_BASE_ADDR (KSEG1 + 0x1F880000) + +#define IFXMIPS_BIU_WDT_CR ((u32*)(IFXMIPS_WDT_BASE_ADDR + 0x03F0)) +#define IFXMIPS_BIU_WDT_SR ((u32*)(IFXMIPS_WDT_BASE_ADDR + 0x03F8)) + + +/*------------ LED */ + +#define IFXMIPS_LED_BASE_ADDR (KSEG1 + 0x1E100BB0) +#define IFXMIPS_LED_CON0 ((u32*)(IFXMIPS_LED_BASE_ADDR + 0x0000)) +#define IFXMIPS_LED_CON1 ((u32*)(IFXMIPS_LED_BASE_ADDR + 0x0004)) +#define IFXMIPS_LED_CPU0 ((u32*)(IFXMIPS_LED_BASE_ADDR + 0x0008)) +#define IFXMIPS_LED_CPU1 ((u32*)(IFXMIPS_LED_BASE_ADDR + 0x000C)) +#define IFXMIPS_LED_AR ((u32*)(IFXMIPS_LED_BASE_ADDR + 0x0010)) + +#define LED_CON0_SWU (1 << 31) +#define LED_CON0_AD1 (1 << 25) +#define LED_CON0_AD0 (1 << 24) + +#define IFXMIPS_LED_2HZ (0) +#define IFXMIPS_LED_4HZ (1 << 23) +#define IFXMIPS_LED_8HZ (2 << 23) +#define IFXMIPS_LED_10HZ (3 << 23) +#define IFXMIPS_LED_MASK (0xf << 23) + +#define IFXMIPS_LED_UPD_SRC_FPI (1 << 31) +#define IFXMIPS_LED_UPD_MASK (3 << 30) +#define IFXMIPS_LED_ADSL_SRC (3 << 24) + +#define IFXMIPS_LED_GROUP0 (1 << 0) +#define IFXMIPS_LED_GROUP1 (1 << 1) +#define IFXMIPS_LED_GROUP2 (1 << 2) + +#define IFXMIPS_LED_RISING 0 +#define IFXMIPS_LED_FALLING (1 << 26) +#define IFXMIPS_LED_EDGE_MASK (1 << 26) + + +/*------------ GPIO */ + +#define IFXMIPS_GPIO_BASE_ADDR (0xBE100B00) + +#define IFXMIPS_GPIO_P0_OUT ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0010)) +#define IFXMIPS_GPIO_P1_OUT ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0040)) +#define IFXMIPS_GPIO_P0_IN ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0014)) +#define IFXMIPS_GPIO_P1_IN ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0044)) +#define IFXMIPS_GPIO_P0_DIR ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0018)) +#define IFXMIPS_GPIO_P1_DIR ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0048)) +#define IFXMIPS_GPIO_P0_ALTSEL0 ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x001C)) +#define IFXMIPS_GPIO_P1_ALTSEL0 ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x004C)) +#define IFXMIPS_GPIO_P0_ALTSEL1 ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0020)) +#define IFXMIPS_GPIO_P1_ALTSEL1 ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0050)) +#define IFXMIPS_GPIO_P0_OD ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0024)) +#define IFXMIPS_GPIO_P1_OD ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0054)) +#define IFXMIPS_GPIO_P0_STOFF ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0028)) +#define IFXMIPS_GPIO_P1_STOFF ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0058)) +#define IFXMIPS_GPIO_P0_PUDSEL ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x002C)) +#define IFXMIPS_GPIO_P1_PUDSEL ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x005C)) +#define IFXMIPS_GPIO_P0_PUDEN ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0030)) +#define IFXMIPS_GPIO_P1_PUDEN ((u32*)(IFXMIPS_GPIO_BASE_ADDR + 0x0060)) + + +/*------------ SSC */ + +#define IFXMIPS_SSC_BASE_ADDR (KSEG1 + 0x1e100800) + + +#define IFXMIPS_SSC_CLC ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0000)) +#define IFXMIPS_SSC_IRN ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x00F4)) +#define IFXMIPS_SSC_SFCON ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0060)) +#define IFXMIPS_SSC_WHBGPOSTAT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0078)) +#define IFXMIPS_SSC_STATE ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0014)) +#define IFXMIPS_SSC_WHBSTATE ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0018)) +#define IFXMIPS_SSC_FSTAT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0038)) +#define IFXMIPS_SSC_ID ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0008)) +#define IFXMIPS_SSC_TB ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0020)) +#define IFXMIPS_SSC_RXFCON ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0030)) +#define IFXMIPS_SSC_TXFCON ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0034)) +#define IFXMIPS_SSC_CON ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0010)) +#define IFXMIPS_SSC_GPOSTAT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0074)) +#define IFXMIPS_SSC_RB ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0024)) +#define IFXMIPS_SSC_RXCNT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0084)) +#define IFXMIPS_SSC_GPOCON ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0070)) +#define IFXMIPS_SSC_BR ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0040)) +#define IFXMIPS_SSC_RXREQ ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0080)) +#define IFXMIPS_SSC_SFSTAT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0064)) +#define IFXMIPS_SSC_RXCNT ((u32*)(IFXMIPS_SSC_BASE_ADDR + 0x0084)) + + +/*------------ MEI */ + +#define IFXMIPS_MEI_BASE_ADDR (0xBE116000) + +#define MEI_DATA_XFR ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0000)) +#define MEI_VERSION ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0004)) +#define MEI_ARC_GP_STAT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0008)) +#define MEI_DATA_XFR_STAT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x000C)) +#define MEI_XFR_ADDR ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0010)) +#define MEI_MAX_WAIT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0014)) +#define MEI_TO_ARC_INT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0018)) +#define ARC_TO_MEI_INT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x001C)) +#define ARC_TO_MEI_INT_MASK ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0020)) +#define MEI_DEBUG_WAD ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0024)) +#define MEI_DEBUG_RAD ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0028)) +#define MEI_DEBUG_DATA ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x002C)) +#define MEI_DEBUG_DEC ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0030)) +#define MEI_CONFIG ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0034)) +#define MEI_RST_CONTROL ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0038)) +#define MEI_DBG_MASTER ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x003C)) +#define MEI_CLK_CONTROL ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0040)) +#define MEI_BIST_CONTROL ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0044)) +#define MEI_BIST_STAT ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0048)) +#define MEI_XDATA_BASE_SH ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x004c)) +#define MEI_XDATA_BASE ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0050)) +#define MEI_XMEM_BAR_BASE ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0054)) +#define MEI_XMEM_BAR0 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0054)) +#define MEI_XMEM_BAR1 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0058)) +#define MEI_XMEM_BAR2 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x005C)) +#define MEI_XMEM_BAR3 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0060)) +#define MEI_XMEM_BAR4 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0064)) +#define MEI_XMEM_BAR5 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0068)) +#define MEI_XMEM_BAR6 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x006C)) +#define MEI_XMEM_BAR7 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0070)) +#define MEI_XMEM_BAR8 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0074)) +#define MEI_XMEM_BAR9 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0078)) +#define MEI_XMEM_BAR10 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x007C)) +#define MEI_XMEM_BAR11 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0080)) +#define MEI_XMEM_BAR12 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0084)) +#define MEI_XMEM_BAR13 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0088)) +#define MEI_XMEM_BAR14 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x008C)) +#define MEI_XMEM_BAR15 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0090)) +#define MEI_XMEM_BAR16 ((u32*)(IFXMIPS_MEI_BASE_ADDR + 0x0094)) + + +/*------------ DEU */ + +#define IFXMIPS_DEU_BASE (KSEG1 + 0x1E103100) +#define IFXMIPS_DEU_CLK ((u32 *)(IFXMIPS_DEU_BASE + 0x0000)) +#define IFXMIPS_DEU_ID ((u32 *)(IFXMIPS_DEU_BASE + 0x0008)) + +#define IFXMIPS_DES_CON ((u32 *)(IFXMIPS_DEU_BASE + 0x0010)) +#define IFXMIPS_DES_IHR ((u32 *)(IFXMIPS_DEU_BASE + 0x0014)) +#define IFXMIPS_DES_ILR ((u32 *)(IFXMIPS_DEU_BASE + 0x0018)) +#define IFXMIPS_DES_K1HR ((u32 *)(IFXMIPS_DEU_BASE + 0x001C)) +#define IFXMIPS_DES_K1LR ((u32 *)(IFXMIPS_DEU_BASE + 0x0020)) +#define IFXMIPS_DES_K3HR ((u32 *)(IFXMIPS_DEU_BASE + 0x0024)) +#define IFXMIPS_DES_K3LR ((u32 *)(IFXMIPS_DEU_BASE + 0x0028)) +#define IFXMIPS_DES_IVHR ((u32 *)(IFXMIPS_DEU_BASE + 0x002C)) +#define IFXMIPS_DES_IVLR ((u32 *)(IFXMIPS_DEU_BASE + 0x0030)) +#define IFXMIPS_DES_OHR ((u32 *)(IFXMIPS_DEU_BASE + 0x0040)) +#define IFXMIPS_DES_OLR ((u32 *)(IFXMIPS_DEU_BASE + 0x0050)) +#define IFXMIPS_AES_CON ((u32 *)(IFXMIPS_DEU_BASE + 0x0050)) +#define IFXMIPS_AES_ID3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0054)) +#define IFXMIPS_AES_ID2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0058)) +#define IFXMIPS_AES_ID1R ((u32 *)(IFXMIPS_DEU_BASE + 0x005C)) +#define IFXMIPS_AES_ID0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0060)) +#define IFXMIPS_AES_K7R ((u32 *)(IFXMIPS_DEU_BASE + 0x0064)) +#define IFXMIPS_AES_K6R ((u32 *)(IFXMIPS_DEU_BASE + 0x0068)) +#define IFXMIPS_AES_K5R ((u32 *)(IFXMIPS_DEU_BASE + 0x006C)) +#define IFXMIPS_AES_K4R ((u32 *)(IFXMIPS_DEU_BASE + 0x0070)) +#define IFXMIPS_AES_K3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0074)) +#define IFXMIPS_AES_K2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0078)) +#define IFXMIPS_AES_K1R ((u32 *)(IFXMIPS_DEU_BASE + 0x007C)) +#define IFXMIPS_AES_K0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0080)) +#define IFXMIPS_AES_IV3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0084)) +#define IFXMIPS_AES_IV2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0088)) +#define IFXMIPS_AES_IV1R ((u32 *)(IFXMIPS_DEU_BASE + 0x008C)) +#define IFXMIPS_AES_IV0R ((u32 *)(IFXMIPS_DEU_BASE + 0x0090)) +#define IFXMIPS_AES_0D3R ((u32 *)(IFXMIPS_DEU_BASE + 0x0094)) +#define IFXMIPS_AES_0D2R ((u32 *)(IFXMIPS_DEU_BASE + 0x0098)) +#define IFXMIPS_AES_OD1R ((u32 *)(IFXMIPS_DEU_BASE + 0x009C)) +#define IFXMIPS_AES_OD0R ((u32 *)(IFXMIPS_DEU_BASE + 0x00A0)) + +/*------------ FUSE */ + +#define IFXMIPS_FUSE_BASE_ADDR (KSEG1 + 0x1F107354) + + +/*------------ MPS */ + +#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000) +#define IFXMIPS_MPS_SRAM ((u32*)(KSEG1 + 0x1F200000)) + +#define IFXMIPS_MPS_CHIPID ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0344)) +#define IFXMIPS_MPS_VC0ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0000)) +#define IFXMIPS_MPS_VC1ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0004)) +#define IFXMIPS_MPS_VC2ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0008)) +#define IFXMIPS_MPS_VC3ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x000C)) +#define IFXMIPS_MPS_RVC0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0010)) +#define IFXMIPS_MPS_RVC1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0014)) +#define IFXMIPS_MPS_RVC2SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0018)) +#define IFXMIPS_MPS_RVC3SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x001C)) +#define IFXMIPS_MPS_SVC0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0020)) +#define IFXMIPS_MPS_SVC1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0024)) +#define IFXMIPS_MPS_SVC2SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0028)) +#define IFXMIPS_MPS_SVC3SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x002C)) +#define IFXMIPS_MPS_CVC0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0030)) +#define IFXMIPS_MPS_CVC1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0034)) +#define IFXMIPS_MPS_CVC2SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0038)) +#define IFXMIPS_MPS_CVC3SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x003C)) +#define IFXMIPS_MPS_RAD0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0040)) +#define IFXMIPS_MPS_RAD1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0044)) +#define IFXMIPS_MPS_SAD0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0048)) +#define IFXMIPS_MPS_SAD1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x004C)) +#define IFXMIPS_MPS_CAD0SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0050)) +#define IFXMIPS_MPS_CAD1SR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0054)) +#define IFXMIPS_MPS_AD0ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x0058)) +#define IFXMIPS_MPS_AD1ENR ((u32*)(IFXMIPS_MPS_BASE_ADDR + 0x005C)) + +#define IFXMIPS_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1)) +#define IFXMIPS_MPS_CHIPID_VERSION_SET(value) (((( 1 << 4) - 1) & (value)) << 28) +#define IFXMIPS_MPS_CHIPID_PARTNUM_GET(value) (((value) >> 12) & ((1 << 16) - 1)) +#define IFXMIPS_MPS_CHIPID_PARTNUM_SET(value) (((( 1 << 16) - 1) & (value)) << 12) +#define IFXMIPS_MPS_CHIPID_MANID_GET(value) (((value) >> 1) & ((1 << 10) - 1)) +#define IFXMIPS_MPS_CHIPID_MANID_SET(value) (((( 1 << 10) - 1) & (value)) << 1) + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_cgu.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_cgu.h new file mode 100644 index 0000000000..899bbbca3e --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_cgu.h @@ -0,0 +1,29 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_CGU_H__ +#define _IFXMIPS_CGU_H__ + +unsigned int cgu_get_mips_clock(int cpu); +unsigned int cgu_get_io_region_clock(void); +unsigned int cgu_get_fpi_bus_clock(int fpi); +void cgu_setup_pci_clk(int internal_clock); +unsigned int ifxmips_get_ddr_hz(void); +unsigned int ifxmips_get_fpi_hz(void); +unsigned int ifxmips_get_cpu_hz(void); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_dma.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_dma.h new file mode 100644 index 0000000000..02c7aec539 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_dma.h @@ -0,0 +1,202 @@ +/* + * 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. + * + * Copyright (C) 2005 infineon + * Copyright (C) 2007 John Crispin + * + */ +#ifndef _IFXMIPS_DMA_H__ +#define _IFXMIPS_DMA_H__ + +#define RCV_INT 1 +#define TX_BUF_FULL_INT 2 +#define TRANSMIT_CPT_INT 4 +#define IFXMIPS_DMA_CH_ON 1 +#define IFXMIPS_DMA_CH_OFF 0 +#define IFXMIPS_DMA_CH_DEFAULT_WEIGHT 100 + +enum attr_t{ + TX = 0, + RX = 1, + RESERVED = 2, + DEFAULT = 3, +}; + +#define DMA_OWN 1 +#define CPU_OWN 0 +#define DMA_MAJOR 250 + +#define DMA_DESC_OWN_CPU 0x0 +#define DMA_DESC_OWN_DMA 0x80000000 +#define DMA_DESC_CPT_SET 0x40000000 +#define DMA_DESC_SOP_SET 0x20000000 +#define DMA_DESC_EOP_SET 0x10000000 + +#define MISCFG_MASK 0x40 +#define RDERR_MASK 0x20 +#define CHOFF_MASK 0x10 +#define DESCPT_MASK 0x8 +#define DUR_MASK 0x4 +#define EOP_MASK 0x2 + +#define DMA_DROP_MASK (1<<31) + +#define IFXMIPS_DMA_RX -1 +#define IFXMIPS_DMA_TX 1 + +typedef struct dma_chan_map { + char dev_name[15]; + enum attr_t dir; + int pri; + int irq; + int rel_chan_no; +} _dma_chan_map; + +#ifdef CONFIG_CPU_LITTLE_ENDIAN +typedef struct rx_desc{ + u32 data_length:16; + volatile u32 reserved:7; + volatile u32 byte_offset:2; + volatile u32 Burst_length_offset:3; + volatile u32 EoP:1; + volatile u32 Res:1; + volatile u32 C:1; + volatile u32 OWN:1; + volatile u32 Data_Pointer; + /*fix me:should be 28 bits here, 32 bits just for host simulatiuon purpose*/ +}_rx_desc; + +typedef struct tx_desc{ + volatile u32 data_length:16; + volatile u32 reserved1:7; + volatile u32 byte_offset:5; + volatile u32 EoP:1; + volatile u32 SoP:1; + volatile u32 C:1; + volatile u32 OWN:1; + volatile u32 Data_Pointer;//fix me:should be 28 bits here +}_tx_desc; +#else //BIG +typedef struct rx_desc{ + union + { + struct + { + volatile u32 OWN:1; + volatile u32 C:1; + volatile u32 SoP:1; + volatile u32 EoP:1; + volatile u32 Burst_length_offset:3; + volatile u32 byte_offset:2; + volatile u32 reserve:7; + volatile u32 data_length:16; + }field; + volatile u32 word; + }status; + volatile u32 Data_Pointer; +}_rx_desc; + +typedef struct tx_desc{ + union + { + struct + { + volatile u32 OWN:1; + volatile u32 C:1; + volatile u32 SoP:1; + volatile u32 EoP:1; + volatile u32 byte_offset:5; + volatile u32 reserved:7; + volatile u32 data_length:16; + }field; + volatile u32 word; + }status; + volatile u32 Data_Pointer; +}_tx_desc; +#endif //ENDIAN + +typedef struct dma_channel_info{ + /*relative channel number*/ + int rel_chan_no; + /*class for this channel for QoS*/ + int pri; + /*specify byte_offset*/ + int byte_offset; + /*direction*/ + int dir; + /*irq number*/ + int irq; + /*descriptor parameter*/ + int desc_base; + int desc_len; + int curr_desc; + int prev_desc;/*only used if it is a tx channel*/ + /*weight setting for WFQ algorithm*/ + int weight; + int default_weight; + int packet_size; + int burst_len; + /*on or off of this channel*/ + int control; + /**optional information for the upper layer devices*/ +#if defined(CONFIG_IFXMIPS_ETHERNET_D2) || defined(CONFIG_IFXMIPS_PPA) + void* opt[64]; +#else + void* opt[25]; +#endif + /*Pointer to the peripheral device who is using this channel*/ + void* dma_dev; + /*channel operations*/ + void (*open)(struct dma_channel_info* pCh); + void (*close)(struct dma_channel_info* pCh); + void (*reset)(struct dma_channel_info* pCh); + void (*enable_irq)(struct dma_channel_info* pCh); + void (*disable_irq)(struct dma_channel_info* pCh); +}_dma_channel_info; + +typedef struct dma_device_info{ + /*device name of this peripheral*/ + char device_name[15]; + int reserved; + int tx_burst_len; + int rx_burst_len; + int default_weight; + int current_tx_chan; + int current_rx_chan; + int num_tx_chan; + int num_rx_chan; + int max_rx_chan_num; + int max_tx_chan_num; + _dma_channel_info* tx_chan[20]; + _dma_channel_info* rx_chan[20]; + /*functions, optional*/ + u8* (*buffer_alloc)(int len,int* offset, void** opt); + void (*buffer_free)(u8* dataptr, void* opt); + int (*intr_handler)(struct dma_device_info* info, int status); + void * priv; /* used by peripheral driver only */ +}_dma_device_info; + +_dma_device_info* dma_device_reserve(char* dev_name); + +void dma_device_release(_dma_device_info* dev); + +void dma_device_register(_dma_device_info* info); + +void dma_device_unregister(_dma_device_info* info); + +int dma_device_read(struct dma_device_info* info, u8** dataptr, void** opt); + +int dma_device_write(struct dma_device_info* info, u8* dataptr, int len, void* opt); +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_ebu.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_ebu.h new file mode 100644 index 0000000000..f9278ed15f --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_ebu.h @@ -0,0 +1,23 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_EBU_H__ +#define _IFXMIPS_EBU_H__ + +extern spinlock_t ebu_lock; + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gpio.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gpio.h new file mode 100644 index 0000000000..237db01ec4 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gpio.h @@ -0,0 +1,40 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License 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. + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_GPIO_H__ +#define _IFXMIPS_GPIO_H__ + +extern int ifxmips_port_reserve_pin (unsigned int port, unsigned int pin); +extern int ifxmips_port_free_pin (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_open_drain (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_open_drain (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_pudsel (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_pudsel (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_puden (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_puden (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_stoff (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_stoff (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_dir_out (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_dir_in (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_output (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_output (unsigned int port, unsigned int pin); +extern int ifxmips_port_get_input (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_altsel0 (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_altsel0 (unsigned int port, unsigned int pin); +extern int ifxmips_port_set_altsel1 (unsigned int port, unsigned int pin); +extern int ifxmips_port_clear_altsel1 (unsigned int port, unsigned int pin); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gptu.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gptu.h new file mode 100644 index 0000000000..6ad4cc58ca --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_gptu.h @@ -0,0 +1,161 @@ +#ifndef __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ +#define __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ + + +/****************************************************************************** + Copyright (c) 2002, Infineon Technologies. All rights reserved. + + No Warranty + Because the program is licensed free of charge, there is no warranty for + the program, to the extent permitted by applicable law. Except when + otherwise stated in writing the copyright holders and/or other parties + provide the program "as is" without warranty of any kind, either + expressed or implied, including, but not limited to, the implied + warranties of merchantability and fitness for a particular purpose. The + entire risk as to the quality and performance of the program is with + you. should the program prove defective, you assume the cost of all + necessary servicing, repair or correction. + + In no event unless required by applicable law or agreed to in writing + will any copyright holder, or any other party who may modify and/or + redistribute the program as permitted above, be liable to you for + damages, including any general, special, incidental or consequential + damages arising out of the use or inability to use the program + (including but not limited to loss of data or data being rendered + inaccurate or losses sustained by you or third parties or a failure of + the program to operate with any other programs), even if such holder or + other party has been advised of the possibility of such damages. +******************************************************************************/ + + +/* + * #################################### + * Definition + * #################################### + */ + +/* + * Available Timer/Counter Index + */ +#define TIMER(n, X) (n * 2 + (X ? 1 : 0)) +#define TIMER_ANY 0x00 +#define TIMER1A TIMER(1, 0) +#define TIMER1B TIMER(1, 1) +#define TIMER2A TIMER(2, 0) +#define TIMER2B TIMER(2, 1) +#define TIMER3A TIMER(3, 0) +#define TIMER3B TIMER(3, 1) + +/* + * Flag of Timer/Counter + * These flags specify the way in which timer is configured. + */ +/* Bit size of timer/counter. */ +#define TIMER_FLAG_16BIT 0x0000 +#define TIMER_FLAG_32BIT 0x0001 +/* Switch between timer and counter. */ +#define TIMER_FLAG_TIMER 0x0000 +#define TIMER_FLAG_COUNTER 0x0002 +/* Stop or continue when overflowing/underflowing. */ +#define TIMER_FLAG_ONCE 0x0000 +#define TIMER_FLAG_CYCLIC 0x0004 +/* Count up or counter down. */ +#define TIMER_FLAG_UP 0x0000 +#define TIMER_FLAG_DOWN 0x0008 +/* Count on specific level or edge. */ +#define TIMER_FLAG_HIGH_LEVEL_SENSITIVE 0x0000 +#define TIMER_FLAG_LOW_LEVEL_SENSITIVE 0x0040 +#define TIMER_FLAG_RISE_EDGE 0x0010 +#define TIMER_FLAG_FALL_EDGE 0x0020 +#define TIMER_FLAG_ANY_EDGE 0x0030 +/* Signal is syncronous to module clock or not. */ +#define TIMER_FLAG_UNSYNC 0x0000 +#define TIMER_FLAG_SYNC 0x0080 +/* Different interrupt handle type. */ +#define TIMER_FLAG_NO_HANDLE 0x0000 +#if defined(__KERNEL__) + #define TIMER_FLAG_CALLBACK_IN_IRQ 0x0100 +#endif // defined(__KERNEL__) +#define TIMER_FLAG_SIGNAL 0x0300 +/* Internal clock source or external clock source */ +#define TIMER_FLAG_INT_SRC 0x0000 +#define TIMER_FLAG_EXT_SRC 0x1000 + + +/* + * ioctl Command + */ +#define GPTU_REQUEST_TIMER 0x01 /* General method to setup timer/counter. */ +#define GPTU_FREE_TIMER 0x02 /* Free timer/counter. */ +#define GPTU_START_TIMER 0x03 /* Start or resume timer/counter. */ +#define GPTU_STOP_TIMER 0x04 /* Suspend timer/counter. */ +#define GPTU_GET_COUNT_VALUE 0x05 /* Get current count value. */ +#define GPTU_CALCULATE_DIVIDER 0x06 /* Calculate timer divider from given freq.*/ +#define GPTU_SET_TIMER 0x07 /* Simplified method to setup timer. */ +#define GPTU_SET_COUNTER 0x08 /* Simplified method to setup counter. */ + +/* + * Data Type Used to Call ioctl + */ +struct gptu_ioctl_param { + unsigned int timer; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and * + * GPTU_SET_COUNTER, this field is ID of expected * + * timer/counter. If it's zero, a timer/counter would * + * be dynamically allocated and ID would be stored in * + * this field. * + * In command GPTU_GET_COUNT_VALUE, this field is * + * ignored. * + * In other command, this field is ID of timer/counter * + * allocated. */ + unsigned int flag; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and * + * GPTU_SET_COUNTER, this field contains flags to * + * specify how to configure timer/counter. * + * In command GPTU_START_TIMER, zero indicate start * + * and non-zero indicate resume timer/counter. * + * In other command, this field is ignored. */ + unsigned long value; /* In command GPTU_REQUEST_TIMER, this field contains * + * init/reload value. * + * In command GPTU_SET_TIMER, this field contains * + * frequency (0.001Hz) of timer. * + * In command GPTU_GET_COUNT_VALUE, current count * + * value would be stored in this field. * + * In command GPTU_CALCULATE_DIVIDER, this field * + * contains frequency wanted, and after calculation, * + * divider would be stored in this field to overwrite * + * the frequency. * + * In other command, this field is ignored. */ + int pid; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, * + * if signal is required, this field contains process * + * ID to which signal would be sent. * + * In other command, this field is ignored. */ + int sig; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, * + * if signal is required, this field contains signal * + * number which would be sent. * + * In other command, this field is ignored. */ +}; + +/* + * #################################### + * Data Type + * #################################### + */ +typedef void (*timer_callback)(unsigned long arg); + + +#if defined(__KERNEL__) + extern int ifxmips_request_timer(unsigned int, unsigned int, unsigned long, unsigned long, unsigned long); + extern int ifxmips_free_timer(unsigned int); + extern int ifxmips_start_timer(unsigned int, int); + extern int ifxmips_stop_timer(unsigned int); + extern int ifxmips_reset_counter_flags(u32 timer, u32 flags); + extern int ifxmips_get_count_value(unsigned int, unsigned long *); + + extern u32 cal_divider(unsigned long); + + extern int set_timer(unsigned int, unsigned int, int, int, unsigned int, unsigned long, unsigned long); +extern int set_counter (unsigned int timer, unsigned int flag, u32 reload, unsigned long arg1, unsigned long arg2); +// extern int set_counter(unsigned int, int, int, int, unsigned int, unsigned int, unsigned long, unsigned long); +#endif // defined(__KERNEL__) + + +#endif // __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_irq.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_irq.h new file mode 100644 index 0000000000..694a646e86 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_irq.h @@ -0,0 +1,72 @@ +/* + * 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. + * + * Copyright (C) 2005 infineon + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_IRQ__ +#define _IFXMIPS_IRQ__ + +#define INT_NUM_IRQ0 8 +#define INT_NUM_IM0_IRL0 (INT_NUM_IRQ0 + 0) +#define INT_NUM_IM1_IRL0 (INT_NUM_IRQ0 + 32) +#define INT_NUM_IM2_IRL0 (INT_NUM_IRQ0 + 64) +#define INT_NUM_IM3_IRL0 (INT_NUM_IRQ0 + 96) +#define INT_NUM_IM4_IRL0 (INT_NUM_IRQ0 + 128) +#define INT_NUM_IM_OFFSET (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0) + +#define IFXMIPSASC_TIR(x) (INT_NUM_IM3_IRL0 + (x * 7)) +#define IFXMIPSASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 7) + 2) +#define IFXMIPSASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 7) + 3) + +#define IFXMIPS_SSC_TIR (INT_NUM_IM0_IRL0 + 15) +#define IFXMIPS_SSC_RIR (INT_NUM_IM0_IRL0 + 14) +#define IFXMIPS_SSC_EIR (INT_NUM_IM0_IRL0 + 16) + +#define IFXMIPS_MEI_INT (INT_NUM_IM1_IRL0 + 23) + +#define IFXMIPS_TIMER6_INT (INT_NUM_IM1_IRL0 + 23) +#define IFXMIPS_USB_OC_INT (INT_NUM_IM4_IRL0 + 23) + +#define MIPS_CPU_TIMER_IRQ 7 + +#define IFXMIPS_DMA_CH0_INT (INT_NUM_IM2_IRL0) +#define IFXMIPS_DMA_CH1_INT (INT_NUM_IM2_IRL0 + 1) +#define IFXMIPS_DMA_CH2_INT (INT_NUM_IM2_IRL0 + 2) +#define IFXMIPS_DMA_CH3_INT (INT_NUM_IM2_IRL0 + 3) +#define IFXMIPS_DMA_CH4_INT (INT_NUM_IM2_IRL0 + 4) +#define IFXMIPS_DMA_CH5_INT (INT_NUM_IM2_IRL0 + 5) +#define IFXMIPS_DMA_CH6_INT (INT_NUM_IM2_IRL0 + 6) +#define IFXMIPS_DMA_CH7_INT (INT_NUM_IM2_IRL0 + 7) +#define IFXMIPS_DMA_CH8_INT (INT_NUM_IM2_IRL0 + 8) +#define IFXMIPS_DMA_CH9_INT (INT_NUM_IM2_IRL0 + 9) +#define IFXMIPS_DMA_CH10_INT (INT_NUM_IM2_IRL0 + 10) +#define IFXMIPS_DMA_CH11_INT (INT_NUM_IM2_IRL0 + 11) +#define IFXMIPS_DMA_CH12_INT (INT_NUM_IM2_IRL0 + 25) +#define IFXMIPS_DMA_CH13_INT (INT_NUM_IM2_IRL0 + 26) +#define IFXMIPS_DMA_CH14_INT (INT_NUM_IM2_IRL0 + 27) +#define IFXMIPS_DMA_CH15_INT (INT_NUM_IM2_IRL0 + 28) +#define IFXMIPS_DMA_CH16_INT (INT_NUM_IM2_IRL0 + 29) +#define IFXMIPS_DMA_CH17_INT (INT_NUM_IM2_IRL0 + 30) +#define IFXMIPS_DMA_CH18_INT (INT_NUM_IM2_IRL0 + 16) +#define IFXMIPS_DMA_CH19_INT (INT_NUM_IM2_IRL0 + 21) + +#define IFXMIPS_USB_INT (INT_NUM_IM4_IRL0 + 22) +#define IFXMIPS_USB_OC_INT (INT_NUM_IM4_IRL0 + 23) + + +extern void ifxmips_mask_and_ack_irq(unsigned int irq_nr); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_led.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_led.h new file mode 100644 index 0000000000..5e0d7f3e1d --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_led.h @@ -0,0 +1,26 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_LED_H__ +#define _IFXMIPS_LED_H__ + +extern void ifxmips_led_set(unsigned int led); +extern void ifxmips_led_clear(unsigned int led); +extern void ifxmips_led_blink_set(unsigned int led); +extern void ifxmips_led_blink_clear(unsigned int led); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei.h new file mode 100644 index 0000000000..d8a4b8867f --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei.h @@ -0,0 +1,270 @@ +/****************************************************************************** +** +** FILE NAME : danube_mei.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#ifndef _IFXMIPS_MEI_H +#define _IFXMIPS_MEI_H +///////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "ifxmips_mei_app.h" + +#define IFXMIPS_MEI_DEBUG +#define IFXMIPS_MEI_CMV_EXTRA +#define IFXMIPS_MEI_MAJOR 106 + +/* +** Define where in ME Processor's memory map the Stratify chip lives +*/ + +#define MAXSWAPSIZE 8 * 1024 //8k *(32bits) + +// Mailboxes +#define MSG_LENGTH 16 // x16 bits +#define YES_REPLY 1 +#define NO_REPLY 0 + +#define CMV_TIMEOUT 100 //jiffies +#define MIB_INTERVAL 10000 //msec + +/*** Bit definitions ***/ + +#define FALSE 0 +#define TRUE 1 +#define BIT0 1<<0 +#define BIT1 1<<1 +#define BIT2 1<<2 +#define BIT3 1<<3 +#define BIT4 1<<4 +#define BIT5 1<<5 +#define BIT6 1<<6 +#define BIT7 1<<7 +#define BIT8 1<<8 +#define BIT9 1<<9 +#define BIT10 1<<10 +#define BIT11 1<<11 +#define BIT12 1<<12 +#define BIT13 1<<13 +#define BIT14 1<<14 +#define BIT15 1<<15 +#define BIT16 1<<16 +#define BIT17 1<<17 +#define BIT18 1<<18 +#define BIT19 1<<19 +#define BIT20 1<<20 +#define BIT21 1<<21 +#define BIT22 1<<22 +#define BIT23 1<<23 +#define BIT24 1<<24 +#define BIT25 1<<25 +#define BIT26 1<<26 +#define BIT27 1<<27 +#define BIT28 1<<28 +#define BIT29 1<<29 +#define BIT30 1<<30 +#define BIT31 1<<31 + +// ARC register addresss +#define ARC_STATUS 0x0 +#define ARC_LP_START 0x2 +#define ARC_LP_END 0x3 +#define ARC_DEBUG 0x5 +#define ARC_INT_MASK 0x10A + +#define IRAM0_BASE (0x00000) +#define IRAM1_BASE (0x04000) +#define BRAM_BASE (0x0A000) + +#define ADSL_BASE (0x20000) +#define CRI_BASE (ADSL_BASE + 0x11F00) +#define CRI_CCR0 (CRI_BASE + 0x00) +#define CRI_RST (CRI_BASE + 0x04*4) +#define ADSL_DILV_BASE (ADSL_BASE+0x20000) + +// +#define IRAM0_ADDR_BIT_MASK 0xFFF +#define IRAM1_ADDR_BIT_MASK 0xFFF +#define BRAM_ADDR_BIT_MASK 0xFFF +#define RX_DILV_ADDR_BIT_MASK 0x1FFF + +// CRI_CCR0 Register definitions +#define CLK_2M_MODE_ENABLE BIT6 +#define ACL_CLK_MODE_ENABLE BIT4 +#define FDF_CLK_MODE_ENABLE BIT2 +#define STM_CLK_MODE_ENABLE BIT0 + +// CRI_RST Register definitions +#define FDF_SRST BIT3 +#define MTE_SRST BIT2 +#define FCI_SRST BIT1 +#define AAI_SRST BIT0 + +// MEI_TO_ARC_INTERRUPT Register definitions +#define MEI_TO_ARC_INT1 BIT3 +#define MEI_TO_ARC_INT0 BIT2 +#define MEI_TO_ARC_CS_DONE BIT1 //need to check +#define MEI_TO_ARC_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT Register definitions +#define ARC_TO_MEI_INT1 BIT8 +#define ARC_TO_MEI_INT0 BIT7 +#define ARC_TO_MEI_CS_REQ BIT6 +#define ARC_TO_MEI_DBG_DONE BIT5 +#define ARC_TO_MEI_MSGACK BIT4 +#define ARC_TO_MEI_NO_ACCESS BIT3 +#define ARC_TO_MEI_CHECK_AAITX BIT2 +#define ARC_TO_MEI_CHECK_AAIRX BIT1 +#define ARC_TO_MEI_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT_MASK Register definitions +#define GP_INT1_EN BIT8 +#define GP_INT0_EN BIT7 +#define CS_REQ_EN BIT6 +#define DBG_DONE_EN BIT5 +#define MSGACK_EN BIT4 +#define NO_ACC_EN BIT3 +#define AAITX_EN BIT2 +#define AAIRX_EN BIT1 +#define MSGAV_EN BIT0 + +#define MEI_SOFT_RESET BIT0 + +#define HOST_MSTR BIT0 + +#define JTAG_MASTER_MODE 0x0 +#define MEI_MASTER_MODE HOST_MSTR + +// MEI_DEBUG_DECODE Register definitions +#define MEI_DEBUG_DEC_MASK (0x3) +#define MEI_DEBUG_DEC_AUX_MASK (0x0) +#define MEI_DEBUG_DEC_DMP1_MASK (0x1) +#define MEI_DEBUG_DEC_DMP2_MASK (0x2) +#define MEI_DEBUG_DEC_CORE_MASK (0x3) + +#define AUX_STATUS (0x0) +// ARC_TO_MEI_MAILBOX[11] is a special location used to indicate +// page swap requests. +#define MEI_TO_ARC_MAILBOX (0xDFD0) +#define MEI_TO_ARC_MAILBOXR (MEI_TO_ARC_MAILBOX + 0x2C) + +#define ARC_TO_MEI_MAILBOX (0xDFA0) +#define ARC_MEI_MAILBOXR (ARC_TO_MEI_MAILBOX + 0x2C) + +// Codeswap request messages are indicated by setting BIT31 +#define OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK (0x80000000) + +// Clear Eoc messages received are indicated by setting BIT17 +#define OMB_CLEAREOC_INTERRUPT_CODE (0x00020000) + +/* +** Swap page header +*/ +// Page must be loaded at boot time if size field has BIT31 set +#define BOOT_FLAG (BIT31) +#define BOOT_FLAG_MASK ~BOOT_FLAG + +#define FREE_RELOAD 1 +#define FREE_SHOWTIME 2 +#define FREE_ALL 3 + +#define IFX_POP_EOC_DONE 0 +#define IFX_POP_EOC_FAIL -1 + +#define CLREOC_BUFF_SIZE 12 //number of clreoc commands being buffered + +// marcos +#define IFXMIPS_WRITE_REGISTER_L(data,addr) do{ *((volatile u32*)(addr)) = (u32)(data);} while (0) +#define IFXMIPS_READ_REGISTER_L(addr) (*((volatile u32*)(addr))) +#define SET_BIT(reg, mask) reg |= (mask) +#define CLEAR_BIT(reg, mask) reg &= (~mask) +#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask) +#define SET_BITS(reg, mask) SET_BIT(reg, mask) +#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);} + +#define ALIGN_SIZE ( 1L<<10 ) //1K size align +#define MEM_ALIGN(addr) (((addr) + ALIGN_SIZE - 1) & ~ (ALIGN_SIZE -1) ) + +// swap marco +#define MEI_HALF_WORD_SWAP(data) {data = ((data & 0xffff)<<16) + ((data & 0xffff0000)>>16);} +#define MEI_BYTE_SWAP(data) {data = ((data & 0xff)<<24) + ((data & 0xff00)<<8)+ ((data & 0xff0000)>>8)+ ((data & 0xff000000)>>24);} + +// Swap page header describes size in 32-bit words, load location, and image offset +// for program and/or data segments +typedef struct _arc_swp_page_hdr { + u32 p_offset; //Offset bytes of progseg from beginning of image + u32 p_dest; //Destination addr of progseg on processor + u32 p_size; //Size in 32-bitwords of program segment + u32 d_offset; //Offset bytes of dataseg from beginning of image + u32 d_dest; //Destination addr of dataseg on processor + u32 d_size; //Size in 32-bitwords of data segment +} ARC_SWP_PAGE_HDR; + +#ifdef CONFIG_PROC_FS +typedef struct reg_entry { + int *flag; + char name[30]; // big enough to hold names + char description[100]; // big enough to hold description + unsigned short low_ino; +} reg_entry_t; +#endif + +/* +** Swap image header +*/ +#define GET_PROG 0 // Flag used for program mem segment +#define GET_DATA 1 // Flag used for data mem segment + +// Image header contains size of image, checksum for image, and count of +// page headers. Following that are 'count' page headers followed by +// the code and/or data segments to be loaded +typedef struct _arc_img_hdr { + u32 size; // Size of binary image in bytes + u32 checksum; // Checksum for image + u32 count; // Count of swp pages in image + ARC_SWP_PAGE_HDR page[1]; // Should be "count" pages - '1' to make compiler happy +} ARC_IMG_HDR; + +typedef struct smmu_mem_info { + int type; + unsigned long nCopy; + unsigned long size; + unsigned char *address; + unsigned char *org_address; +} smmu_mem_info_t; + +/* +** Native size for the Stratiphy interface is 32-bits. All reads and writes +** MUST be aligned on 32-bit boundaries. Trickery must be invoked to read word and/or +** byte data. Read routines are provided. Write routines are probably a bad idea, as the +** Arc has unrestrained, unseen access to the same memory, so a read-modify-write cycle +** could very well have unintended results. +*/ +MEI_ERROR meiCMV (u16 *, int, u16 *); // first arg is CMV to ARC, second to indicate whether need reply + +MEI_ERROR meiDebugWrite (u32 destaddr, u32 * databuff, u32 databuffsize); +extern int ifx_mei_hdlc_send (char *hdlc_pkt, int hdlc_pkt_len); +extern int ifx_mei_hdlc_read (char *hdlc_pkt, int max_hdlc_pkt_len); +#if defined(__KERNEL__) || defined (IFXMIPS_PORT_RTEMS) +extern void makeCMV (u8 opcode, u8 group, u16 address, u16 index, int size, + u16 * data, u16 * CMVMSG); +int ifx_mei_hdlc_send (char *, int); +int ifx_mei_hdlc_read (char *, int); +#endif + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app.h new file mode 100644 index 0000000000..cba742e58a --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app.h @@ -0,0 +1,116 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_app.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#ifndef _IFXMIPS_MEI_APP_H +#define _IFXMIPS_MEI_APP_H + // ioctl control +#define IFXMIPS_MEI_START 300 +#define IFXMIPS_MEI_REPLY 301 +#define IFXMIPS_MEI_NOREPLY 302 + +#define IFXMIPS_MEI_RESET 303 +#define IFXMIPS_MEI_REBOOT 304 +#define IFXMIPS_MEI_HALT 305 +#define IFXMIPS_MEI_CMV_WINHOST 306 +#define IFXMIPS_MEI_CMV_READ 307 +#define IFXMIPS_MEI_CMV_WRITE 308 +#define IFXMIPS_MEI_MIB_DAEMON 309 +#define IFXMIPS_MEI_SHOWTIME 310 +#define IFXMIPS_MEI_REMOTE 311 +#define IFXMIPS_MEI_READDEBUG 312 +#define IFXMIPS_MEI_WRITEDEBUG 313 +#define IFXMIPS_MEI_LOP 314 + +#define IFXMIPS_MEI_PCM_SETUP 315 +#define IFXMIPS_MEI_PCM_START_TIMER 316 +#define IFXMIPS_MEI_PCM_STOP_TIMER 317 +#define IFXMIPS_MEI_PCM_CHECK 318 +#define IFXMIPS_MEI_GET_EOC_LEN 319 +#define IFXMIPS_MEI_GET_EOC_DATA 320 +#define IFXMIPS_MEI_PCM_GETDATA 321 +#define IFXMIPS_MEI_PCM_GPIO 322 +#define IFXMIPS_MEI_EOC_SEND 323 +#define IFXMIPS_MEI_DOWNLOAD 326 +#define IFXMIPS_MEI_JTAG_ENABLE 327 +#define IFXMIPS_MEI_RUN 328 +#define IFXMIPS_MEI_DEBUG_MODE 329 + +/* Loop diagnostics mode of the ADSL line related constants */ +#define SET_ADSL_LOOP_DIAGNOSTICS_MODE 330 +#define GET_ADSL_LOOP_DIAGNOSTICS_MODE 331 +#define LOOP_DIAGNOSTIC_MODE_COMPLETE 332 +#define IS_ADSL_LOOP_DIAGNOSTICS_MODE_COMPLETE 333 + +/* L3 Power Mode */ +/* Get current Power Moaagement Mode Status*/ +#define GET_POWER_MANAGEMENT_MODE 334 +/* Set L3 Power Mode /disable L3 power mode */ +#define SET_L3_POWER_MODE 335 + +/* get current dual latency configuration */ +#define GET_ADSL_DUAL_LATENCY 336 +/* enable/disable dual latency path */ +#define SET_ADSL_DUAL_LATENCY 337 + +/* Enable/Disable autoboot mode. */ +/* When the autoboot mode is disabled, the driver will excute some cmv + commands for led control and dual latency when DSL startup.*/ +#define AUTOBOOT_ENABLE_SET 338 + +/* Enable/Disable Quiet Mode*/ +/* Quiet mode is used for firmware debug. if the quiet mode enable, the autoboot daemon will not reset arc when the arc need to reboot */ +#define QUIET_MODE_GET 339 +#define QUIET_MODE_SET 340 + +/* Enable/Disable showtime lock*/ +/* showtime lock is used for firmware debug. if the showtime lock enable, the autoboot daemon will not reset arc when the arc reach showtime and need to reboot */ +#define SHOWTIME_LOCK_GET 341 +#define SHOWTIME_LOCK_SET 342 + +#define L0_POWER_MODE 0 +#define L2_POWER_MODE 2 +#define L3_POWER_MODE 3 + +#define DUAL_LATENCY_US_DS_DISABLE 0 +#define DUAL_LATENCY_US_ENABLE (1<<0) +#define DUAL_LATENCY_DS_ENABLE (1<<1) +#define DUAL_LATENCY_US_DS_ENABLE (DUAL_LATENCY_US_ENABLE|DUAL_LATENCY_DS_ENABLE) + +#define ME_HDLC_IDLE 0 +#define ME_HDLC_INVALID_MSG 1 +#define ME_HDLC_MSG_QUEUED 2 +#define ME_HDLC_MSG_SENT 3 +#define ME_HDLC_RESP_RCVD 4 +#define ME_HDLC_RESP_TIMEOUT 5 +#define ME_HDLC_RX_BUF_OVERFLOW 6 +#define ME_HDLC_UNRESOLVED 1 +#define ME_HDLC_RESOLVED 2 + +/*** Enums ***/ +typedef enum mei_error { + MEI_SUCCESS = 0, + MEI_FAILURE = -1, + MEI_MAILBOX_FULL = -2, + MEI_MAILBOX_EMPTY = -3, + MEI_MAILBOX_TIMEOUT = -4, +} MEI_ERROR; + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app_ioctl.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app_ioctl.h new file mode 100644 index 0000000000..08c3dd3fc1 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_app_ioctl.h @@ -0,0 +1,1191 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_app_ioctl.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#ifndef __IFXMIPS_MEI_APP_IOCTL_H +#define __IFXMIPS_MEI_APP_IOCTL_H + +#ifdef __KERNEL__ +#include "ifxmips_mei_ioctl.h" +#endif + +/* Interface Name */ +//#define INTERFACE_NAME + +/* adslLineTable constants */ +#define GET_ADSL_LINE_CODE 1 + +/* adslAtucPhysTable constants */ +#define GET_ADSL_ATUC_PHY 4 + +/* adslAturPhysTable constants */ +#define GET_ADSL_ATUR_PHY 10 + +/* adslAtucChanTable constants */ +#define GET_ADSL_ATUC_CHAN_INFO 15 + +/* adslAturChanTable constants */ +#define GET_ADSL_ATUR_CHAN_INFO 18 + +/* adslAtucPerfDataTable constants */ +#define GET_ADSL_ATUC_PERF_DATA 21 + +/* adslAturPerfDataTable constants */ +#define GET_ADSL_ATUR_PERF_DATA 40 + +/* adslAtucIntervalTable constants */ +#define GET_ADSL_ATUC_INTVL_INFO 60 + +/* adslAturIntervalTable constants */ +#define GET_ADSL_ATUR_INTVL_INFO 65 + +/* adslAtucChanPerfDataTable constants */ +#define GET_ADSL_ATUC_CHAN_PERF_DATA 70 + +/* adslAturChanPerfDataTable constants */ +#define GET_ADSL_ATUR_CHAN_PERF_DATA 90 + +/* adslAtucChanIntervalTable constants */ +#define GET_ADSL_ATUC_CHAN_INTVL_INFO 110 + +/* adslAturChanIntervalTable constants */ +#define GET_ADSL_ATUR_CHAN_INTVL_INFO 115 + +/* adslLineAlarmConfProfileTable constants */ +#define GET_ADSL_ALRM_CONF_PROF 120 +#define SET_ADSL_ALRM_CONF_PROF 121 + +/* adslAturTrap constants */ +#define ADSL_ATUR_TRAPS 135 + +////////////////// RFC-3440 ////////////// + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +/* adslLineExtTable */ +#define GET_ADSL_ATUC_LINE_EXT 201 +#define SET_ADSL_ATUC_LINE_EXT 203 + +/* adslAtucPerfDateExtTable */ +#define GET_ADSL_ATUC_PERF_DATA_EXT 205 + +/* adslAtucIntervalExtTable */ +#define GET_ADSL_ATUC_INTVL_EXT_INFO 221 + +/* adslAturPerfDataExtTable */ +#define GET_ADSL_ATUR_PERF_DATA_EXT 225 + +/* adslAturIntervalExtTable */ +#define GET_ADSL_ATUR_INTVL_EXT_INFO 233 + +/* adslAlarmConfProfileExtTable */ +#define GET_ADSL_ALRM_CONF_PROF_EXT 235 +#define SET_ADSL_ALRM_CONF_PROF_EXT 236 + +/* adslAturExtTrap */ +#define ADSL_ATUR_EXT_TRAPS 240 + +#endif + +/* The following constants are added to support the WEB related ADSL Statistics */ + +/* adslLineStatus constants */ +#define GET_ADSL_LINE_STATUS 245 + +/* adslLineRate constants */ +#define GET_ADSL_LINE_RATE 250 + +/* adslLineInformation constants */ +#define GET_ADSL_LINE_INFO 255 + +/* adslNearEndPerformanceStats constants */ +#define GET_ADSL_NEAREND_STATS 270 + +/* adslFarEndPerformanceStats constants */ +#define GET_ADSL_FAREND_STATS 290 + +/* Sub-carrier related parameters */ +#define GET_ADSL_LINE_INIT_STATS 150 +#define GET_ADSL_POWER_SPECTRAL_DENSITY 151 + +#define IFXMIPS_MIB_LO_ATUC 295 +#define IFXMIPS_MIB_LO_ATUR 296 + +#define GET_ADSL_ATUC_SUBCARRIER_STATS 297 +#define GET_ADSL_ATUR_SUBCARRIER_STATS 298 + + + +/////////////////////////////////////////////////////////// +// makeCMV(Opcode, Group, Address, Index, Size, Data) + +/* adslLineCode Flags */ +#define LINE_CODE_FLAG 0x1 /* BIT 0th position */ + +/* adslAtucPhysTable Flags */ +#define ATUC_PHY_SER_NUM_FLAG 0x1 /* BIT 0th position */ +#define ATUC_PHY_SER_NUM_FLAG_MAKECMV1 makeCMV(H2D_CMV_READ, INFO, 57, 0, 12, data,TxMessage) +#define ATUC_PHY_SER_NUM_FLAG_MAKECMV2 makeCMV(H2D_CMV_READ, INFO, 57, 12, 4, data,TxMessage) + +#define ATUC_PHY_VENDOR_ID_FLAG 0x2 /* BIT 1 */ +#define ATUC_PHY_VENDOR_ID_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 64, 0, 4, data,TxMessage) + +#define ATUC_PHY_VER_NUM_FLAG 0x4 /* BIT 2 */ +#define ATUC_PHY_VER_NUM_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 58, 0, 8, data,TxMessage) + +#define ATUC_CURR_STAT_FLAG 0x8 /* BIT 3 */ + +#define ATUC_CURR_OUT_PWR_FLAG 0x10 /* BIT 4 */ +#define ATUC_CURR_OUT_PWR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 5, 1, data,TxMessage) + +#define ATUC_CURR_ATTR_FLAG 0x20 /* BIT 5 */ +#define ATUC_CURR_ATTR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 0, 2, data,TxMessage) + + +/* adslAturPhysTable Flags */ +#define ATUR_PHY_SER_NUM_FLAG 0x1 /* BIT 0th position */ +#define ATUR_PHY_SER_NUM_FLAG_MAKECMV1 makeCMV(H2D_CMV_READ, INFO, 62, 0, 12, data,TxMessage) +#define ATUR_PHY_SER_NUM_FLAG_MAKECMV2 makeCMV(H2D_CMV_READ, INFO, 62, 12, 4, data,TxMessage) + +#define ATUR_PHY_VENDOR_ID_FLAG 0x2 /* BIT 1 */ +#define ATUR_PHY_VENDOR_ID_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 65, 0, 4, data,TxMessage) + +#define ATUR_PHY_VER_NUM_FLAG 0x4 /* BIT 2 */ +#define ATUR_PHY_VER_NUM_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 61, 0, 8, data,TxMessage) + +#define ATUR_SNRMGN_FLAG 0x8 +#if 0 /* [ Ritesh. Use PLAM 45 0 for 0.1dB resolution rather than INFO 68 3 */ +#define ATUR_SNRMGN_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 4, 1, data,TxMessage) +#else +#define ATUR_SNRMGN_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, PLAM_SNRMargin_0_1db, 0, 1, data, TxMessage) +#endif + +#define ATUR_ATTN_FLAG 0x10 +#define ATUR_ATTN_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 2, 1, data,TxMessage) + +#define ATUR_CURR_STAT_FLAG 0x20 /* BIT 3 */ + +#define ATUR_CURR_OUT_PWR_FLAG 0x40 /* BIT 4 */ +#define ATUR_CURR_OUT_PWR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 5, 1, data,TxMessage) + +#define ATUR_CURR_ATTR_FLAG 0x80 /* BIT 5 */ +#define ATUR_CURR_ATTR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 0, 2, data,TxMessage) + +/* adslAtucChanTable Flags */ +#define ATUC_CHAN_INTLV_DELAY_FLAG 0x1 /* BIT 0th position */ +//KD #define ATUC_CHAN_INTLV_DELAY_FLAG_MAKECMV makeCMV(H2D_CMV_READ, RATE, 3, 1, 1, data,TxMessage) +#define ATUC_CHAN_INTLV_DELAY_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 92, 1, 1, data,TxMessage) + +#define ATUC_CHAN_CURR_TX_RATE_FLAG 0x2 /* BIT 1 */ +#define ATUC_CHAN_CURR_TX_RATE_FLAG_MAKECMV makeCMV(H2D_CMV_READ, RATE, 1, 0, 2, data,TxMessage) + +#define ATUC_CHAN_PREV_TX_RATE_FLAG 0x4 /* BIT 2 */ + +/* adslAturChanTable Flags */ +#define ATUR_CHAN_INTLV_DELAY_FLAG 0x1 /* BIT 0th position */ +//KD #define ATUR_CHAN_INTLV_DELAY_FLAG_MAKECMV makeCMV(H2D_CMV_READ, RATE, 2, 1, 1, data,TxMessage) +#define ATUR_CHAN_INTLV_DELAY_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 93, 1, 1, data,TxMessage) + +#define ATUR_CHAN_CURR_TX_RATE_FLAG 0x2 /* BIT 1 */ +#define ATUR_CHAN_CURR_TX_RATE_FLAG_MAKECMV makeCMV(H2D_CMV_READ, RATE, 0, 0, 2, data,TxMessage) + +#define ATUR_CHAN_PREV_TX_RATE_FLAG 0x4 /* BIT 2 */ + +#define ATUR_CHAN_CRC_BLK_LEN_FLAG 0x8 /* BIT 3 */ + +/* adslAtucPerfDataTable Flags */ +#define ATUC_PERF_LOFS_FLAG 0x1 /* BIT 0th position */ +#define ATUC_PERF_LOSS_FLAG 0x2 /* BIT 1 */ +#define ATUC_PERF_LO_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 0, 0, 1, data,TxMessage) +#define ATUC_PERF_ESS_FLAG 0x4 /* BIT 2 */ +#define ATUC_PERF_ESS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 7, 0, 1, data,TxMessage) +#define ATUC_PERF_INITS_FLAG 0x8 /* BIT 3 */ +#define ATUC_PERF_VALID_INTVLS_FLAG 0x10 /* BIT 4 */ +#define ATUC_PERF_INVALID_INTVLS_FLAG 0x20 /* BIT 5 */ +#define ATUC_PERF_CURR_15MIN_TIME_ELAPSED_FLAG 0x40 /* BIT 6 */ +#define ATUC_PERF_CURR_15MIN_LOFS_FLAG 0x80 /* BIT 7 */ +#define ATUC_PERF_CURR_15MIN_LOSS_FLAG 0x100 /* BIT 8 */ +#define ATUC_PERF_CURR_15MIN_ESS_FLAG 0x200 /* BIT 9 */ +#define ATUC_PERF_CURR_15MIN_INIT_FLAG 0x400 /* BIT 10 */ +#define ATUC_PERF_CURR_1DAY_TIME_ELAPSED_FLAG 0x800 /* BIT 11 */ +#define ATUC_PERF_CURR_1DAY_LOFS_FLAG 0x1000 /* BIT 12 */ +#define ATUC_PERF_CURR_1DAY_LOSS_FLAG 0x2000 /* BIT 13 */ +#define ATUC_PERF_CURR_1DAY_ESS_FLAG 0x4000 /* BIT 14 */ +#define ATUC_PERF_CURR_1DAY_INIT_FLAG 0x8000 /* BIT 15 */ +#define ATUC_PERF_PREV_1DAY_MON_SEC_FLAG 0x10000 /* BIT 16 */ +#define ATUC_PERF_PREV_1DAY_LOFS_FLAG 0x20000 /* BIT 17 */ +#define ATUC_PERF_PREV_1DAY_LOSS_FLAG 0x40000 /* BIT 18 */ +#define ATUC_PERF_PREV_1DAY_ESS_FLAG 0x80000 /* BIT 19 */ +#define ATUC_PERF_PREV_1DAY_INITS_FLAG 0x100000 /* BIT 20 */ + +/* adslAturPerfDataTable Flags */ +#define ATUR_PERF_LOFS_FLAG 0x1 /* BIT 0th position */ +#define ATUR_PERF_LOSS_FLAG 0x2 /* BIT 1 */ +#define ATUR_PERF_LPR_FLAG 0x4 /* BIT 2 */ +#define ATUR_PERF_LO_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 1, 0, 1, data,TxMessage) +#define ATUR_PERF_ESS_FLAG 0x8 /* BIT 3 */ +#define ATUR_PERF_ESS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 33, 0, 1, data,TxMessage) +#define ATUR_PERF_VALID_INTVLS_FLAG 0x10 /* BIT 4 */ +#define ATUR_PERF_INVALID_INTVLS_FLAG 0x20 /* BIT 5 */ +#define ATUR_PERF_CURR_15MIN_TIME_ELAPSED_FLAG 0x40 /* BIT 6 */ +#define ATUR_PERF_CURR_15MIN_LOFS_FLAG 0x80 /* BIT 7 */ +#define ATUR_PERF_CURR_15MIN_LOSS_FLAG 0x100 /* BIT 8 */ +#define ATUR_PERF_CURR_15MIN_LPR_FLAG 0x200 /* BIT 9 */ +#define ATUR_PERF_CURR_15MIN_ESS_FLAG 0x400 /* BIT 10 */ +#define ATUR_PERF_CURR_1DAY_TIME_ELAPSED_FLAG 0x800 /* BIT 11 */ +#define ATUR_PERF_CURR_1DAY_LOFS_FLAG 0x1000 /* BIT 12 */ +#define ATUR_PERF_CURR_1DAY_LOSS_FLAG 0x2000 /* BIT 13 */ +#define ATUR_PERF_CURR_1DAY_LPR_FLAG 0x4000 /* BIT 14 */ +#define ATUR_PERF_CURR_1DAY_ESS_FLAG 0x8000 /* BIT 15 */ +#define ATUR_PERF_PREV_1DAY_MON_SEC_FLAG 0x10000 /* BIT 16 */ +#define ATUR_PERF_PREV_1DAY_LOFS_FLAG 0x20000 /* BIT 17 */ +#define ATUR_PERF_PREV_1DAY_LOSS_FLAG 0x40000 /* BIT 18 */ +#define ATUR_PERF_PREV_1DAY_LPR_FLAG 0x80000 /* BIT 19 */ +#define ATUR_PERF_PREV_1DAY_ESS_FLAG 0x100000 /* BIT 20 */ + +/* adslAtucIntervalTable Flags */ +#define ATUC_INTVL_LOF_FLAG 0x1 /* BIT 0th position */ +#define ATUC_INTVL_LOS_FLAG 0x2 /* BIT 1 */ +#define ATUC_INTVL_ESS_FLAG 0x4 /* BIT 2 */ +#define ATUC_INTVL_INIT_FLAG 0x8 /* BIT 3 */ +#define ATUC_INTVL_VALID_DATA_FLAG 0x10 /* BIT 4 */ + +/* adslAturIntervalTable Flags */ +#define ATUR_INTVL_LOF_FLAG 0x1 /* BIT 0th position */ +#define ATUR_INTVL_LOS_FLAG 0x2 /* BIT 1 */ +#define ATUR_INTVL_LPR_FLAG 0x4 /* BIT 2 */ +#define ATUR_INTVL_ESS_FLAG 0x8 /* BIT 3 */ +#define ATUR_INTVL_VALID_DATA_FLAG 0x10 /* BIT 4 */ + +/* adslAtucChanPerfDataTable Flags */ +#define ATUC_CHAN_RECV_BLK_FLAG 0x01 /* BIT 0th position */ +#define ATUC_CHAN_TX_BLK_FLAG 0x02 /* BIT 1 */ +#define ATUC_CHAN_CORR_BLK_FLAG 0x04 /* BIT 2 */ +#define ATUC_CHAN_UNCORR_BLK_FLAG 0x08 /* BIT 3 */ +#define ATUC_CHAN_PERF_VALID_INTVL_FLAG 0x10 /* BIT 4 */ +#define ATUC_CHAN_PERF_INVALID_INTVL_FLAG 0x20 /* BIT 5 */ +#define ATUC_CHAN_PERF_CURR_15MIN_TIME_ELAPSED_FLAG 0x40 /* BIT 6 */ +#define ATUC_CHAN_PERF_CURR_15MIN_RECV_BLK_FLAG 0x80 /* BIT 7 */ +#define ATUC_CHAN_PERF_CURR_15MIN_TX_BLK_FLAG 0x100 /* BIT 8 */ +#define ATUC_CHAN_PERF_CURR_15MIN_CORR_BLK_FLAG 0x200 /* BIT 9 */ +#define ATUC_CHAN_PERF_CURR_15MIN_UNCORR_BLK_FLAG 0x400 /* BIT 10 */ +#define ATUC_CHAN_PERF_CURR_1DAY_TIME_ELAPSED_FLAG 0x800 /* BIT 11*/ +#define ATUC_CHAN_PERF_CURR_1DAY_RECV_BLK_FLAG 0x1000 /* BIT 12 */ +#define ATUC_CHAN_PERF_CURR_1DAY_TX_BLK_FLAG 0x2000 /* BIT 13 */ +#define ATUC_CHAN_PERF_CURR_1DAY_CORR_BLK_FLAG 0x4000 /* BIT 14 */ +#define ATUC_CHAN_PERF_CURR_1DAY_UNCORR_BLK_FLAG 0x8000 /* BIT 15 */ +#define ATUC_CHAN_PERF_PREV_1DAY_MONI_SEC_FLAG 0x10000 /* BIT 16 */ +#define ATUC_CHAN_PERF_PREV_1DAY_RECV_BLK_FLAG 0x20000 /* BIT 17 */ +#define ATUC_CHAN_PERF_PREV_1DAY_TX_BLK_FLAG 0x40000 /* BIT 18 */ +#define ATUC_CHAN_PERF_PREV_1DAY_CORR_BLK_FLAG 0x80000 /* BIT 19 */ +#define ATUC_CHAN_PERF_PREV_1DAY_UNCORR_BLK_FLAG 0x100000 /* BIT 20 */ + + +/* adslAturChanPerfDataTable Flags */ +#define ATUR_CHAN_RECV_BLK_FLAG 0x01 /* BIT 0th position */ +#define ATUR_CHAN_RECV_BLK_FLAG_MAKECMV_LSW makeCMV(H2D_CMV_READ, PLAM, 20, 0, 1, data,TxMessage) +#define ATUR_CHAN_RECV_BLK_FLAG_MAKECMV_MSW makeCMV(H2D_CMV_READ, PLAM, 21, 0, 1, data,TxMessage) +#define ATUR_CHAN_TX_BLK_FLAG 0x02 /* BIT 1 */ +#define ATUR_CHAN_TX_BLK_FLAG_MAKECMV_LSW makeCMV(H2D_CMV_READ, PLAM, 20, 0, 1, data,TxMessage) +#define ATUR_CHAN_TX_BLK_FLAG_MAKECMV_MSW makeCMV(H2D_CMV_READ, PLAM, 21, 0, 1, data,TxMessage) +#define ATUR_CHAN_CORR_BLK_FLAG 0x04 /* BIT 2 */ +#define ATUR_CHAN_CORR_BLK_FLAG_MAKECMV_INTL makeCMV(H2D_CMV_READ, PLAM, 3, 0, 1, data,TxMessage) +#define ATUR_CHAN_CORR_BLK_FLAG_MAKECMV_FAST makeCMV(H2D_CMV_READ, PLAM, 3, 1, 1, data,TxMessage) +#define ATUR_CHAN_UNCORR_BLK_FLAG 0x08 /* BIT 3 */ +#define ATUR_CHAN_UNCORR_BLK_FLAG_MAKECMV_INTL makeCMV(H2D_CMV_READ, PLAM, 2, 0, 1, data,TxMessage) +#define ATUR_CHAN_UNCORR_BLK_FLAG_MAKECMV_FAST makeCMV(H2D_CMV_READ, PLAM, 2, 1, 1, data,TxMessage) +#define ATUR_CHAN_PERF_VALID_INTVL_FLAG 0x10 /* BIT 4 */ +#define ATUR_CHAN_PERF_INVALID_INTVL_FLAG 0x20 /* BIT 5 */ +#define ATUR_CHAN_PERF_CURR_15MIN_TIME_ELAPSED_FLAG 0x40 /* BIT 6 */ +#define ATUR_CHAN_PERF_CURR_15MIN_RECV_BLK_FLAG 0x80 /* BIT 7 */ +#define ATUR_CHAN_PERF_CURR_15MIN_TX_BLK_FLAG 0x100 /* BIT 8 */ +#define ATUR_CHAN_PERF_CURR_15MIN_CORR_BLK_FLAG 0x200 /* BIT 9 */ +#define ATUR_CHAN_PERF_CURR_15MIN_UNCORR_BLK_FLAG 0x400 /* BIT 10 */ +#define ATUR_CHAN_PERF_CURR_1DAY_TIME_ELAPSED_FLAG 0x800 /* BIT 11 */ +#define ATUR_CHAN_PERF_CURR_1DAY_RECV_BLK_FLAG 0x1000 /* BIT 12 */ +#define ATUR_CHAN_PERF_CURR_1DAY_TX_BLK_FLAG 0x2000 /* BIT 13 */ +#define ATUR_CHAN_PERF_CURR_1DAY_CORR_BLK_FLAG 0x4000 /* BIT 14 */ +#define ATUR_CHAN_PERF_CURR_1DAY_UNCORR_BLK_FLAG 0x8000 /* BIT 15 */ +#define ATUR_CHAN_PERF_PREV_1DAY_MONI_SEC_FLAG 0x10000 /* BIT 16 */ +#define ATUR_CHAN_PERF_PREV_1DAY_RECV_BLK_FLAG 0x20000 /* BIT 17 */ +#define ATUR_CHAN_PERF_PREV_1DAY_TRANS_BLK_FLAG 0x40000 /* BIT 18 */ +#define ATUR_CHAN_PERF_PREV_1DAY_CORR_BLK_FLAG 0x80000 /* BIT 19 */ +#define ATUR_CHAN_PERF_PREV_1DAY_UNCORR_BLK_FLAG 0x100000 /* BIT 20 */ + +/* adslAtucChanIntervalTable Flags */ +#define ATUC_CHAN_INTVL_NUM_FLAG 0x1 /* BIT 0th position */ +#define ATUC_CHAN_INTVL_RECV_BLK_FLAG 0x2 /* BIT 1 */ +#define ATUC_CHAN_INTVL_TX_BLK_FLAG 0x4 /* BIT 2 */ +#define ATUC_CHAN_INTVL_CORR_BLK_FLAG 0x8 /* BIT 3 */ +#define ATUC_CHAN_INTVL_UNCORR_BLK_FLAG 0x10 /* BIT 4 */ +#define ATUC_CHAN_INTVL_VALID_DATA_FLAG 0x20 /* BIT 5 */ + +/* adslAturChanIntervalTable Flags */ +#define ATUR_CHAN_INTVL_NUM_FLAG 0x1 /* BIT 0th Position */ +#define ATUR_CHAN_INTVL_RECV_BLK_FLAG 0x2 /* BIT 1 */ +#define ATUR_CHAN_INTVL_TX_BLK_FLAG 0x4 /* BIT 2 */ +#define ATUR_CHAN_INTVL_CORR_BLK_FLAG 0x8 /* BIT 3 */ +#define ATUR_CHAN_INTVL_UNCORR_BLK_FLAG 0x10 /* BIT 4 */ +#define ATUR_CHAN_INTVL_VALID_DATA_FLAG 0x20 /* BIT 5 */ + +/* adslLineAlarmConfProfileTable Flags */ +#define ATUC_THRESH_15MIN_LOFS_FLAG 0x01 /* BIT 0th position */ +#define ATUC_THRESH_15MIN_LOSS_FLAG 0x02 /* BIT 1 */ +#define ATUC_THRESH_15MIN_ESS_FLAG 0x04 /* BIT 2 */ +#define ATUC_THRESH_FAST_RATEUP_FLAG 0x08 /* BIT 3 */ +#define ATUC_THRESH_INTERLEAVE_RATEUP_FLAG 0x10 /* BIT 4 */ +#define ATUC_THRESH_FAST_RATEDOWN_FLAG 0x20 /* BIT 5 */ +#define ATUC_THRESH_INTERLEAVE_RATEDOWN_FLAG 0x40 /* BIT 6 */ +#define ATUC_INIT_FAILURE_TRAP_ENABLE_FLAG 0x80 /* BIT 7 */ +#define ATUR_THRESH_15MIN_LOFS_FLAG 0x100 /* BIT 8 */ +#define ATUR_THRESH_15MIN_LOSS_FLAG 0x200 /* BIT 9 */ +#define ATUR_THRESH_15MIN_LPRS_FLAG 0x400 /* BIT 10 */ +#define ATUR_THRESH_15MIN_ESS_FLAG 0x800 /* BIT 11 */ +#define ATUR_THRESH_FAST_RATEUP_FLAG 0x1000 /* BIT 12 */ +#define ATUR_THRESH_INTERLEAVE_RATEUP_FLAG 0x2000 /* BIT 13 */ +#define ATUR_THRESH_FAST_RATEDOWN_FLAG 0x4000 /* BIT 14 */ +#define ATUR_THRESH_INTERLEAVE_RATEDOWN_FLAG 0x8000 /* BIT 15 */ +#define LINE_ALARM_CONF_PROFILE_ROWSTATUS_FLAG 0x10000 /* BIT 16 */ + + +/* adslAturTraps Flags */ +#define ATUC_PERF_LOFS_THRESH_FLAG 0x1 /* BIT 0th position */ +#define ATUC_PERF_LOSS_THRESH_FLAG 0x2 /* BIT 1 */ +#define ATUC_PERF_ESS_THRESH_FLAG 0x4 /* BIT 2 */ +#define ATUC_RATE_CHANGE_FLAG 0x8 /* BIT 3 */ +#define ATUR_PERF_LOFS_THRESH_FLAG 0x10 /* BIT 4 */ +#define ATUR_PERF_LOSS_THRESH_FLAG 0x20 /* BIT 5 */ +#define ATUR_PERF_LPRS_THRESH_FLAG 0x40 /* BIT 6 */ +#define ATUR_PERF_ESS_THRESH_FLAG 0x80 /* BIT 7 */ +#define ATUR_RATE_CHANGE_FLAG 0x100 /* BIT 8 */ + +//RFC- 3440 FLAG DEFINITIONS + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +/* adslLineExtTable flags */ +#define ATUC_LINE_TRANS_CAP_FLAG 0x1 /* BIT 0th position */ +#define ATUC_LINE_TRANS_CAP_FLAG_MAKECMV makeCMV(H2D_CMV_READ,INFO, 67, 0, 1, data,TxMessage) +#define ATUC_LINE_TRANS_CONFIG_FLAG 0x2 /* BIT 1 */ +#define ATUC_LINE_TRANS_CONFIG_FLAG_MAKECMV makeCMV(H2D_CMV_READ,INFO, 67, 0, 1, data,TxMessage) +#define ATUC_LINE_TRANS_CONFIG_FLAG_MAKECMV_WR makeCMV(H2D_CMV_WRITE,INFO, 67, 0, 1, data,TxMessage) +#define ATUC_LINE_TRANS_ACTUAL_FLAG 0x4 /* BIT 2 */ +#define ATUC_LINE_TRANS_ACTUAL_FLAG_MAKECMV makeCMV(H2D_CMV_READ,STAT, 1, 0, 1, data,TxMessage) +#define LINE_GLITE_POWER_STATE_FLAG 0x8 /* BIT 3 */ +#define LINE_GLITE_POWER_STATE_FLAG_MAKECMV makeCMV(H2D_CMV_READ,STAT, 0, 0, 1, data,TxMessage) + +/* adslAtucPerfDataExtTable flags */ +#define ATUC_PERF_STAT_FASTR_FLAG 0x1 /* BIT 0th position */ +#define ATUC_PERF_STAT_FASTR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, STAT, 0, 0, 1, data, TxMessage) +#define ATUC_PERF_STAT_FAILED_FASTR_FLAG 0x2 /* BIT 1 */ +#define ATUC_PERF_STAT_FAILED_FASTR_FLAG_MAKECMV makeCMV(H2D_CMV_READ, STAT, 0, 0, 1, data, TxMessage) +#define ATUC_PERF_STAT_SESL_FLAG 0X4 /* BIT 2 */ +#define ATUC_PERF_STAT_SESL_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 8, 0, 1, data, TxMessage) +#define ATUC_PERF_STAT_UASL_FLAG 0X8 /* BIT 3 */ +#define ATUC_PERF_STAT_UASL_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 10, 0, 1, data, TxMessage) +#define ATUC_PERF_CURR_15MIN_FASTR_FLAG 0X10 /* BIT 4 */ +#define ATUC_PERF_CURR_15MIN_FAILED_FASTR_FLAG 0X20 /* BIT 5 */ +#define ATUC_PERF_CURR_15MIN_SESL_FLAG 0X40 /* BIT 6 */ +#define ATUC_PERF_CURR_15MIN_UASL_FLAG 0X80 /* BIT 7 */ +#define ATUC_PERF_CURR_1DAY_FASTR_FLAG 0X100 /* BIT 8 */ +#define ATUC_PERF_CURR_1DAY_FAILED_FASTR_FLAG 0X200 /* BIT 9 */ +#define ATUC_PERF_CURR_1DAY_SESL_FLAG 0X400 /* BIT 10 */ +#define ATUC_PERF_CURR_1DAY_UASL_FLAG 0X800 /* BIT 11 */ +#define ATUC_PERF_PREV_1DAY_FASTR_FLAG 0X1000 /* BIT 12 */ +#define ATUC_PERF_PREV_1DAY_FAILED_FASTR_FLAG 0X2000 /* BIT 13 */ +#define ATUC_PERF_PREV_1DAY_SESL_FLAG 0X4000 /* BIT 14 */ +#define ATUC_PERF_PREV_1DAY_UASL_FLAG 0X8000 /* BIT 15 */ + +/* adslAturPerfDataExtTable */ +#define ATUR_PERF_STAT_SESL_FLAG 0X1 /* BIT 0th position */ +#define ATUR_PERF_STAT_SESL_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 34, 0, 1, data, TxMessage) +#define ATUR_PERF_STAT_UASL_FLAG 0X2 /* BIT 1 */ +#define ATUR_PERF_STAT_UASL_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 36, 0, 1, data, TxMessage) +#define ATUR_PERF_CURR_15MIN_SESL_FLAG 0X4 /* BIT 2 */ +#define ATUR_PERF_CURR_15MIN_UASL_FLAG 0X8 /* BIT 3 */ +#define ATUR_PERF_CURR_1DAY_SESL_FLAG 0X10 /* BIT 4 */ +#define ATUR_PERF_CURR_1DAY_UASL_FLAG 0X20 /* BIT 5 */ +#define ATUR_PERF_PREV_1DAY_SESL_FLAG 0X40 /* BIT 6 */ +#define ATUR_PERF_PREV_1DAY_UASL_FLAG 0X80 /* BIT 7 */ + +/* adslAutcIntervalExtTable flags */ +#define ATUC_INTERVAL_FASTR_FLAG 0x1 /* Bit 0 */ +#define ATUC_INTERVAL_FAILED_FASTR_FLAG 0x2 /* Bit 1 */ +#define ATUC_INTERVAL_SESL_FLAG 0x4 /* Bit 2 */ +#define ATUC_INTERVAL_UASL_FLAG 0x8 /* Bit 3 */ + +/* adslAturIntervalExtTable */ +#define ATUR_INTERVAL_SESL_FLAG 0X1 /* BIT 0th position */ +#define ATUR_INTERVAL_UASL_FLAG 0X2 /* BIT 1 */ + +/* adslAlarmConfProfileExtTable */ +#define ATUC_THRESH_15MIN_FAILED_FASTR_FLAG 0X1/* BIT 0th position */ +#define ATUC_THRESH_15MIN_SESL_FLAG 0X2 /* BIT 1 */ +#define ATUC_THRESH_15MIN_UASL_FLAG 0X4 /* BIT 2 */ +#define ATUR_THRESH_15MIN_SESL_FLAG 0X8 /* BIT 3 */ +#define ATUR_THRESH_15MIN_UASL_FLAG 0X10 /* BIT 4 */ + +/* adslAturExtTraps */ +#define ATUC_15MIN_FAILED_FASTR_TRAP_FLAG 0X1 /* BIT 0th position */ +#define ATUC_15MIN_SESL_TRAP_FLAG 0X2 /* BIT 1 */ +#define ATUC_15MIN_UASL_TRAP_FLAG 0X4 /* BIT 2 */ +#define ATUR_15MIN_SESL_TRAP_FLAG 0X8 /* BIT 3 */ +#define ATUR_15MIN_UASL_TRAP_FLAG 0X10 /* BIT 4 */ + +#endif + +/* adslLineStatus Flags */ +#define LINE_STAT_MODEM_STATUS_FLAG 0x1 /* BIT 0th position */ +#define LINE_STAT_MODEM_STATUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, STAT, 0, 0, 1, data, TxMessage) +#define LINE_STAT_MODE_SEL_FLAG 0x2 /* BIT 1 */ +#define LINE_STAT_MODE_SEL_FLAG_MAKECMV makeCMV(H2D_CMV_READ, STAT, 1, 0, 1, data, TxMessage) +#define LINE_STAT_TRELLCOD_ENABLE_FLAG 0x4 /* BIT 2 */ +#define LINE_STAT_TRELLCOD_ENABLE_FLAG_MAKECMV makeCMV(H2D_CMV_READ, OPTN, 2, 0, 1, data, TxMessage) +#define LINE_STAT_LATENCY_FLAG 0x8 /* BIT 3 */ +#define LINE_STAT_LATENCY_FLAG_MAKECMV makeCMV(H2D_CMV_READ, STAT, 12, 0, 1, data, TxMessage) + +/* adslLineRate Flags */ +#define LINE_RATE_DATA_RATEDS_FLAG 0x1 /* BIT 0th position */ +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL1_LP0_MAKECMV makeCMV(H2D_CMV_READ, RATE, 1, 0, 2, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL1_LP1_MAKECMV makeCMV(H2D_CMV_READ, RATE, 1, 2, 2, data, TxMessage) + + +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_RP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 12, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_MP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 13, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_LP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 14, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_TP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 15, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_KP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 17, 0, 2, data, TxMessage) + +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_RP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 12, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_MP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 13, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_LP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 14, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_TP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 15, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEDS_FLAG_ADSL2_KP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 17, 2, 2, data, TxMessage) + +#define LINE_RATE_DATA_RATEUS_FLAG 0x2 /* BIT 1 */ +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL1_LP0_MAKECMV makeCMV(H2D_CMV_READ, RATE, 0, 0, 2, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL1_LP1_MAKECMV makeCMV(H2D_CMV_READ, RATE, 0, 2, 2, data, TxMessage) + + +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_RP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 23, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_MP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 24, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_LP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 25, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_TP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 26, 0, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_KP_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 28, 0, 2, data, TxMessage) + +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_RP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 23, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_MP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 24, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_LP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 25, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_TP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 26, 1, 1, data, TxMessage) +#define LINE_RATE_DATA_RATEUS_FLAG_ADSL2_KP_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 28, 2, 2, data, TxMessage) + +#define LINE_RATE_ATTNDRDS_FLAG 0x4 /* BIT 2 */ +#define LINE_RATE_ATTNDRDS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 4, 2, data, TxMessage) + +#define LINE_RATE_ATTNDRUS_FLAG 0x8 /* BIT 3 */ +#define LINE_RATE_ATTNDRUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 4, 2, data, TxMessage) + +/* adslLineInformation Flags */ +#define LINE_INFO_INTLV_DEPTHDS_FLAG 0x1 /* BIT 0th position */ +#define LINE_INFO_INTLV_DEPTHDS_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 27, 0, 1, data, TxMessage) +#define LINE_INFO_INTLV_DEPTHDS_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 27, 1, 1, data, TxMessage) +#define LINE_INFO_INTLV_DEPTHUS_FLAG 0x2 /* BIT 1 */ +#define LINE_INFO_INTLV_DEPTHUS_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 16, 0, 1, data, TxMessage) +#define LINE_INFO_INTLV_DEPTHUS_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, CNFG, 16, 1, 1, data, TxMessage) +#define LINE_INFO_LATNDS_FLAG 0x4 /* BIT 2 */ +#define LINE_INFO_LATNDS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 1, 1, data, TxMessage) +#define LINE_INFO_LATNUS_FLAG 0x8 /* BIT 3 */ +#define LINE_INFO_LATNUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 1, 1, data, TxMessage) +#define LINE_INFO_SATNDS_FLAG 0x10 /* BIT 4 */ +#define LINE_INFO_SATNDS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 2, 1, data, TxMessage) +#define LINE_INFO_SATNUS_FLAG 0x20 /* BIT 5 */ +#define LINE_INFO_SATNUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 2, 1, data, TxMessage) +#define LINE_INFO_SNRMNDS_FLAG 0x40 /* BIT 6 */ +#define LINE_INFO_SNRMNDS_FLAG_ADSL1_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 3, 1, data, TxMessage) +#define LINE_INFO_SNRMNDS_FLAG_ADSL2_MAKECMV makeCMV(H2D_CMV_READ, RATE, 3, 0, 1, data, TxMessage) +#define LINE_INFO_SNRMNDS_FLAG_ADSL2PLUS_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 46, 0, 1, data, TxMessage) +#define LINE_INFO_SNRMNUS_FLAG 0x80 /* BIT 7 */ +#define LINE_INFO_SNRMNUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 3, 1, data, TxMessage) +#define LINE_INFO_ACATPDS_FLAG 0x100 /* BIT 8 */ +#define LINE_INFO_ACATPDS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 68, 6, 1, data, TxMessage) +#define LINE_INFO_ACATPUS_FLAG 0x200 /* BIT 9 */ +#define LINE_INFO_ACATPUS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, INFO, 69, 6, 1, data, TxMessage) + +/* adslNearEndPerformanceStats Flags */ +#define NEAREND_PERF_SUPERFRAME_FLAG_LSW_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 20, 0, 1, data, TxMessage) +#define NEAREND_PERF_SUPERFRAME_FLAG_MSW_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 21, 0, 1, data, TxMessage) +#define NEAREND_PERF_SUPERFRAME_FLAG 0x1 /* BIT 0th position */ +#define NEAREND_PERF_LOS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 0, 0, 1, data, TxMessage) +#define NEAREND_PERF_LOS_FLAG 0x2 /* BIT 1 */ +#define NEAREND_PERF_LOF_FLAG 0x4 /* BIT 2 */ +#define NEAREND_PERF_LPR_FLAG 0x8 /* BIT 3 */ +#define NEAREND_PERF_NCD_FLAG 0x10 /* BIT 4 */ +#define NEAREND_PERF_LCD_FLAG 0x20 /* BIT 5 */ +#define NEAREND_PERF_CRC_FLAG 0x40 /* BIT 6 */ +#define NEAREND_PERF_CRC_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 2, 0, 1, data, TxMessage) +#define NEAREND_PERF_CRC_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 2, 1, 1, data, TxMessage) +#define NEAREND_PERF_RSCORR_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 3, 0, 1, data, TxMessage) +#define NEAREND_PERF_RSCORR_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 3, 1, 1, data, TxMessage) +#define NEAREND_PERF_RSCORR_FLAG 0x80 /* BIT 7 */ +#define NEAREND_PERF_FECS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 6, 0, 1, data, TxMessage) +#define NEAREND_PERF_FECS_FLAG 0x100 /* BIT 8 */ +#define NEAREND_PERF_ES_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 7, 0, 1, data, TxMessage) +#define NEAREND_PERF_ES_FLAG 0x200 /* BIT 9 */ +#define NEAREND_PERF_SES_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 8, 0, 1, data, TxMessage) +#define NEAREND_PERF_SES_FLAG 0x400 /* BIT 10 */ +#define NEAREND_PERF_LOSS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 9, 0, 1, data, TxMessage) +#define NEAREND_PERF_LOSS_FLAG 0x800 /* BIT 11 */ +#define NEAREND_PERF_UAS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 10, 0, 1, data, TxMessage) +#define NEAREND_PERF_UAS_FLAG 0x1000 /* BIT 12 */ +#define NEAREND_PERF_HECERR_FLAG_BC0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 11, 0, 2, data, TxMessage) +#define NEAREND_PERF_HECERR_FLAG_BC1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 11, 2, 2, data, TxMessage) +#define NEAREND_PERF_HECERR_FLAG 0x2000 /* BIT 13 */ + +/* adslFarEndPerformanceStats Flags */ +#define FAREND_PERF_LOS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 1, 0, 1, data, TxMessage) +#define FAREND_PERF_LOS_FLAG 0x1 /* BIT 0th position */ +#define FAREND_PERF_LOF_FLAG 0x2 /* BIT 1 */ +#define FAREND_PERF_LPR_FLAG 0x4 /* BIT 2 */ +#define FAREND_PERF_NCD_FLAG 0x8 /* BIT 3 */ +#define FAREND_PERF_LCD_FLAG 0x10 /* BIT 4 */ +#define FAREND_PERF_CRC_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 24, 0, 1, data, TxMessage) +#define FAREND_PERF_CRC_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 24, 1, 1, data, TxMessage) +#define FAREND_PERF_CRC_FLAG 0x20 /* BIT 5 */ +#define FAREND_PERF_RSCORR_FLAG_LP0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 28, 0, 1, data, TxMessage) +#define FAREND_PERF_RSCORR_FLAG_LP1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 28, 1, 1, data, TxMessage) +#define FAREND_PERF_RSCORR_FLAG 0x40 /* BIT 6 */ +#define FAREND_PERF_FECS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 32, 0, 1, data, TxMessage) +#define FAREND_PERF_FECS_FLAG 0x80 /* BIT 7 */ +#define FAREND_PERF_ES_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 33, 0, 1, data, TxMessage) +#define FAREND_PERF_ES_FLAG 0x100 /* BIT 8 */ +#define FAREND_PERF_SES_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 34, 0, 1, data, TxMessage) +#define FAREND_PERF_SES_FLAG 0x200 /* BIT 9 */ +#define FAREND_PERF_LOSS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 35, 0, 1, data, TxMessage) +#define FAREND_PERF_LOSS_FLAG 0x400 /* BIT 10 */ +#define FAREND_PERF_UAS_FLAG_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 36, 0, 1, data, TxMessage) +#define FAREND_PERF_UAS_FLAG 0x800 /* BIT 11 */ +#define FAREND_PERF_HECERR_FLAG_BC0_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 37, 0, 2, data, TxMessage) +#define FAREND_PERF_HECERR_FLAG_BC1_MAKECMV makeCMV(H2D_CMV_READ, PLAM, 37, 2, 2, data, TxMessage) +#define FAREND_PERF_HECERR_FLAG 0x1000 /* BIT 12 */ +// 603221:tc.chen end +/* TR-69 related additional parameters - defines */ +/* Defines for struct adslATURSubcarrierInfo */ +#define NEAREND_HLINSC 0x1 +#define NEAREND_HLINSC_MAKECMV(mode) makeCMV(mode, INFO, 71, 2, 1, data, TxMessage) +#define NEAREND_HLINPS 0x2 +#define NEAREND_HLINPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 73, idx, size, data, TxMessage) +#define NEAREND_HLOGMT 0x4 +#define NEAREND_HLOGMT_MAKECMV(mode) makeCMV(mode, INFO, 80, 0, 1, data, TxMessage) +#define NEAREND_HLOGPS 0x8 +#define NEAREND_HLOGPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 75, idx, size, data, TxMessage) +#define NEAREND_QLNMT 0x10 +#define NEAREND_QLNMT_MAKECMV(mode) makeCMV(mode, INFO, 80, 1, 1, data, TxMessage) +#define NEAREND_QLNPS 0x20 +#define NEAREND_QLNPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 77, idx, size, data, TxMessage) +#define NEAREND_SNRMT 0x40 +#define NEAREND_SNRMT_MAKECMV(mode) makeCMV(mode, INFO, 80, 2, 1, data, TxMessage) +#define NEAREND_SNRPS 0x80 +#define NEAREND_SNRPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 78, idx, size, data, TxMessage) +#define NEAREND_BITPS 0x100 +#define NEAREND_BITPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 22, idx, size, data, TxMessage) +#define NEAREND_GAINPS 0x200 +#define NEAREND_GAINPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 24, idx, size, data, TxMessage) + +/* Defines for struct adslATUCSubcarrierInfo */ +#define FAREND_HLINSC 0x1 + +/* As per the feedback from Knut on 21/08/2006, the cmv command of HLINSC should be INFO 70 2 */ +#define FAREND_HLINSC_MAKECMV(mode) makeCMV(mode, INFO, 70, 2, 1, data, TxMessage) +#define FAREND_HLINPS 0x2 +#define FAREND_HLINPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 72, idx, size, data, TxMessage) +#define FAREND_HLOGMT 0x4 +#define FAREND_HLOGMT_MAKECMV(mode) makeCMV(mode, INFO, 79, 0, 1, data, TxMessage) +#define FAREND_HLOGPS 0x8 +#define FAREND_HLOGPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 74, idx, size, data, TxMessage) +#define FAREND_QLNMT 0x10 +#define FAREND_QLNMT_MAKECMV(mode) makeCMV(mode, INFO, 79, 1, 1, data, TxMessage) +#define FAREND_QLNPS 0x20 +#define FAREND_QLNPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 76, idx, size, data, TxMessage) +#define FAREND_SNRMT 0x40 +#define FAREND_SNRMT_MAKECMV(mode) makeCMV(mode, INFO, 79, 2, 1, data, TxMessage) +#define FAREND_SNRPS 0x80 +#define FAREND_SNRPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 11, idx, size, data, TxMessage) +#define FAREND_SNRPS_DIAG_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 10, idx, size, data, TxMessage) +#define FAREND_BITPS 0x100 +#define FAREND_BITPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 23, idx, size, data, TxMessage) +#define FAREND_GAINPS 0x200 +#define FAREND_GAINPS_MAKECMV(mode,idx,size) makeCMV(mode, INFO, 25, idx, size, data, TxMessage) + + +// GET_ADSL_POWER_SPECTRAL_DENSITY +#define NOMPSD_US_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 0, 1, data, TxMessage) +#define NOMPSD_DS_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 1, 1, data, TxMessage) +#define PCB_US_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 6, 1, data, TxMessage) +#define PCB_DS_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 7, 1, data, TxMessage) +#define RMSGI_US_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 10, 1, data, TxMessage) +#define RMSGI_DS_MAKECMV makeCMV(H2D_CMV_READ, INFO, 102, 11, 1, data, TxMessage) + +/////////////////////////////////////////////////Macro Definitions ? FLAG Setting & Testing + +#define SET_FLAG(flags, flag_val) ((*flags) = ((*flags) | flag_val)) +// -- This macro sets the flags with the flag_val. Here flags is passed as a pointer + +#define IS_FLAG_SET(flags, test_flag) (((*flags) & (test_flag)) == (test_flag)? test_flag:0) +// -- This macro verifies whether test_flag has been set in flags. Here flags is passed as a pointer + + +#define CLR_FLAG(flags, flag_bit) ((*flags) = (*flags) & (~flag_bit)) +// -- This macro resets the specified flag_bit in the flags. Here flags is passed as a pointer + + +////////////////////////////////////////////////DATA STRUCTURES ORGANIZATION + +//Here are the data structures used for accessing mib parameters. The ioctl call includes the third parameter as a void pointer. This parameter has to be type-casted in the driver code to the corresponding structure depending upon the command type. For Ex: consider the ioctl used to get the adslLineCode type, ioctl(fd,GET_ADSL_LINE_CODE,void *struct_adslLineTableEntry). In the driver code we check on the type of the command, i.e GET_ADSL_LINE_CODE and type-cast the void pointer to struct adslLineTableEntry type. + // +#define u32 unsigned int +#define u16 unsigned short +#define s16 short +#define u8 unsigned char + + +typedef u32 AdslPerfTimeElapsed; +typedef u32 AdslPerfPrevDayCount; +typedef u32 PerfCurrentCount; +typedef u32 PerfIntervalCount; +typedef u32 AdslPerfCurrDayCount; + + +//ioctl(int fd, GET_ADSL_LINE_CODE, void *struct_adslLineTableEntry) + +typedef struct adslLineTableEntry { + int ifIndex; + int adslLineCode; + u8 flags; +} adslLineTableEntry; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct adslLineExtTableEntry { + int ifIndex; + u16 adslLineTransAtucCap; + u16 adslLineTransAtucConfig; + u16 adslLineTransAtucActual; + int adslLineGlitePowerState; + u32 flags; +}adslLineExtTableEntry; +#endif +//ioctl(int fd, GET_ADSL_ATUC_PHY, void *struct_adslAtucPhysEntry) +#ifndef u_char +#define u_char u8 +#endif + +typedef struct adslVendorId { + u16 country_code; + u_char provider_id[4]; /* Ascii characters */ + u_char revision_info[2]; +}adslVendorId; + +typedef struct adslAtucPhysEntry { + int ifIndex; + char serial_no[32]; + union { + char vendor_id[16]; + adslVendorId vendor_info; + } vendor_id; + char version_no[16]; + u32 status; + int outputPwr; + u32 attainableRate; + u8 flags; +} adslAtucPhysEntry; + + +//ioctl(int fd, GET_ADSL_ATUR_PHY, void *struct_adslAturPhysEntry) + +typedef struct adslAturPhysEntry { + int ifIndex; + char serial_no[32]; + union { + char vendor_id[16]; + adslVendorId vendor_info; + } vendor_id; + char version_no[16]; + int SnrMgn; + u32 Attn; + u32 status; + int outputPwr; + u32 attainableRate; + u8 flags; +} adslAturPhysEntry; + + +//ioctl(int fd, GET_ADSL_ATUC_CHAN_INFO, void *struct_adslAtucChanInfo) + +typedef struct adslAtucChanInfo { + int ifIndex; + u32 interleaveDelay; + u32 currTxRate; + u32 prevTxRate; + u8 flags; +} adslAtucChanInfo; + + +//ioctl(int fd, GET_ADSL_ATUR_CHAN_INFO, void *struct_adslAturChanInfo) + +typedef struct adslAturChanInfo { + int ifIndex; + u32 interleaveDelay; + u32 currTxRate; + u32 prevTxRate; + u32 crcBlkLen; + u8 flags; +} adslAturChanInfo; + + +//ioctl(int fd, GET_ADSL_ATUC_PERF_DATA, void *struct_atucPerfDataEntry) + +typedef struct atucPerfDataEntry +{ + int ifIndex; + u32 adslAtucPerfLofs; + u32 adslAtucPerfLoss; + u32 adslAtucPerfESs; + u32 adslAtucPerfInits; + int adslAtucPerfValidIntervals; + int adslAtucPerfInvalidIntervals; + AdslPerfTimeElapsed adslAtucPerfCurr15MinTimeElapsed; + PerfCurrentCount adslAtucPerfCurr15MinLofs; + PerfCurrentCount adslAtucPerfCurr15MinLoss; + PerfCurrentCount adslAtucPerfCurr15MinESs; + PerfCurrentCount adslAtucPerfCurr15MinInits; + AdslPerfTimeElapsed adslAtucPerfCurr1DayTimeElapsed; + AdslPerfCurrDayCount adslAtucPerfCurr1DayLofs; + AdslPerfCurrDayCount adslAtucPerfCurr1DayLoss; + AdslPerfCurrDayCount adslAtucPerfCurr1DayESs; + AdslPerfCurrDayCount adslAtucPerfCurr1DayInits; + int adslAtucPerfPrev1DayMoniSecs; + AdslPerfPrevDayCount adslAtucPerfPrev1DayLofs; + AdslPerfPrevDayCount adslAtucPerfPrev1DayLoss; + AdslPerfPrevDayCount adslAtucPerfPrev1DayESs; + AdslPerfPrevDayCount adslAtucPerfPrev1DayInits; + u32 flags; +} atucPerfDataEntry; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct atucPerfDataExtEntry + { + int ifIndex; + u32 adslAtucPerfStatFastR; + u32 adslAtucPerfStatFailedFastR; + u32 adslAtucPerfStatSesL; + u32 adslAtucPerfStatUasL; + u32 adslAtucPerfCurr15MinFastR; + u32 adslAtucPerfCurr15MinFailedFastR; + u32 adslAtucPerfCurr15MinSesL; + u32 adslAtucPerfCurr15MinUasL; + u32 adslAtucPerfCurr1DayFastR; + u32 adslAtucPerfCurr1DayFailedFastR; + u32 adslAtucPerfCurr1DaySesL; + u32 adslAtucPerfCurr1DayUasL; + u32 adslAtucPerfPrev1DayFastR; + u32 adslAtucPerfPrev1DayFailedFastR; + u32 adslAtucPerfPrev1DaySesL; + u32 adslAtucPerfPrev1DayUasL; + u32 flags; +} atucPerfDataExtEntry; + +#endif +//ioctl(int fd, GET_ADSL_ATUR_PERF_DATA, void *struct_aturPerfDataEntry) + +typedef struct aturPerfDataEntry +{ + int ifIndex; + u32 adslAturPerfLofs; + u32 adslAturPerfLoss; + u32 adslAturPerfLprs; + u32 adslAturPerfESs; + int adslAturPerfValidIntervals; + int adslAturPerfInvalidIntervals; + AdslPerfTimeElapsed adslAturPerfCurr15MinTimeElapsed; + PerfCurrentCount adslAturPerfCurr15MinLofs; + PerfCurrentCount adslAturPerfCurr15MinLoss; + PerfCurrentCount adslAturPerfCurr15MinLprs; + PerfCurrentCount adslAturPerfCurr15MinESs; + AdslPerfTimeElapsed adslAturPerfCurr1DayTimeElapsed; + AdslPerfCurrDayCount adslAturPerfCurr1DayLofs; + AdslPerfCurrDayCount adslAturPerfCurr1DayLoss; + AdslPerfCurrDayCount adslAturPerfCurr1DayLprs; + AdslPerfCurrDayCount adslAturPerfCurr1DayESs; + int adslAturPerfPrev1DayMoniSecs; + AdslPerfPrevDayCount adslAturPerfPrev1DayLofs; + AdslPerfPrevDayCount adslAturPerfPrev1DayLoss; + AdslPerfPrevDayCount adslAturPerfPrev1DayLprs; + AdslPerfPrevDayCount adslAturPerfPrev1DayESs; + u32 flags; +} aturPerfDataEntry; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct aturPerfDataExtEntry + { + int ifIndex; + u32 adslAturPerfStatSesL; + u32 adslAturPerfStatUasL; + u32 adslAturPerfCurr15MinSesL; + u32 adslAturPerfCurr15MinUasL; + u32 adslAturPerfCurr1DaySesL; + u32 adslAturPerfCurr1DayUasL; + u32 adslAturPerfPrev1DaySesL; + u32 adslAturPerfPrev1DayUasL; + u32 flags; +} aturPerfDataExtEntry; +#endif +//ioctl(int fd, GET_ADSL_ATUC_INTVL_INFO, void *struct_adslAtucInvtInfo) + +typedef struct adslAtucIntvlInfo { + int ifIndex; + int IntervalNumber; + PerfIntervalCount intervalLOF; + PerfIntervalCount intervalLOS; + PerfIntervalCount intervalES; + PerfIntervalCount intervalInits; + int intervalValidData; + u8 flags; +} adslAtucIntvlInfo; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct adslAtucInvtlExtInfo + { + int ifIndex; + int IntervalNumber; + u32 adslAtucIntervalFastR; + u32 adslAtucIntervalFailedFastR; + u32 adslAtucIntervalSesL; + u32 adslAtucIntervalUasL; + u32 flags; +} adslAtucInvtlExtInfo; +#endif +//ioctl(int fd, GET_ADSL_ATUR_INTVL_INFO, void *struct_adslAturInvtlInfo) + +typedef struct adslAturIntvlInfo { + int ifIndex; + int IntervalNumber; + PerfIntervalCount intervalLOF; + PerfIntervalCount intervalLOS; + PerfIntervalCount intervalLPR; + PerfIntervalCount intervalES; + int intervalValidData; + u8 flags; +} adslAturIntvlInfo; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct adslAturInvtlExtInfo + { + int ifIndex; + int IntervalNumber; + u32 adslAturIntervalSesL; + u32 adslAturIntervalUasL; + u32 flags; +} adslAturInvtlExtInfo; +#endif +//ioctl(int fd, GET_ADSL_ATUC_CHAN_PERF_DATA, void *struct_atucChannelPerfDataEntry) + +typedef struct atucChannelPerfDataEntry +{ + int ifIndex; + u32 adslAtucChanReceivedBlks; + u32 adslAtucChanTransmittedBlks; + u32 adslAtucChanCorrectedBlks; + u32 adslAtucChanUncorrectBlks; + int adslAtucChanPerfValidIntervals; + int adslAtucChanPerfInvalidIntervals; + AdslPerfTimeElapsed adslAtucChanPerfCurr15MinTimeElapsed; + PerfCurrentCount adslAtucChanPerfCurr15MinReceivedBlks; + PerfCurrentCount adslAtucChanPerfCurr15MinTransmittedBlks; + PerfCurrentCount adslAtucChanPerfCurr15MinCorrectedBlks; + PerfCurrentCount adslAtucChanPerfCurr15MinUncorrectBlks; + AdslPerfTimeElapsed adslAtucChanPerfCurr1DayTimeElapsed; + AdslPerfCurrDayCount adslAtucChanPerfCurr1DayReceivedBlks; + AdslPerfCurrDayCount adslAtucChanPerfCurr1DayTransmittedBlks; + AdslPerfCurrDayCount adslAtucChanPerfCurr1DayCorrectedBlks; + AdslPerfCurrDayCount adslAtucChanPerfCurr1DayUncorrectBlks; + int adslAtucChanPerfPrev1DayMoniSecs; + AdslPerfPrevDayCount adslAtucChanPerfPrev1DayReceivedBlks; + AdslPerfPrevDayCount adslAtucChanPerfPrev1DayTransmittedBlks; + AdslPerfPrevDayCount adslAtucChanPerfPrev1DayCorrectedBlks; + AdslPerfPrevDayCount adslAtucChanPerfPrev1DayUncorrectBlks; + u32 flags; +}atucChannelPerfDataEntry; + + +//ioctl(int fd, GET_ADSL_ATUR_CHAN_PERF_DATA, void *struct_aturChannelPerfDataEntry) + +typedef struct aturChannelPerfDataEntry +{ + int ifIndex; + u32 adslAturChanReceivedBlks; + u32 adslAturChanTransmittedBlks; + u32 adslAturChanCorrectedBlks; + u32 adslAturChanUncorrectBlks; + int adslAturChanPerfValidIntervals; + int adslAturChanPerfInvalidIntervals; + AdslPerfTimeElapsed adslAturChanPerfCurr15MinTimeElapsed; + PerfCurrentCount adslAturChanPerfCurr15MinReceivedBlks; + PerfCurrentCount adslAturChanPerfCurr15MinTransmittedBlks; + PerfCurrentCount adslAturChanPerfCurr15MinCorrectedBlks; + PerfCurrentCount adslAturChanPerfCurr15MinUncorrectBlks; + AdslPerfTimeElapsed adslAturChanPerfCurr1DayTimeElapsed; + AdslPerfCurrDayCount adslAturChanPerfCurr1DayReceivedBlks; + AdslPerfCurrDayCount adslAturChanPerfCurr1DayTransmittedBlks; + AdslPerfCurrDayCount adslAturChanPerfCurr1DayCorrectedBlks; + AdslPerfCurrDayCount adslAturChanPerfCurr1DayUncorrectBlks; + int adslAturChanPerfPrev1DayMoniSecs; + AdslPerfPrevDayCount adslAturChanPerfPrev1DayReceivedBlks; + AdslPerfPrevDayCount adslAturChanPerfPrev1DayTransmittedBlks; + AdslPerfPrevDayCount adslAturChanPerfPrev1DayCorrectedBlks; + AdslPerfPrevDayCount adslAturChanPerfPrev1DayUncorrectBlks; + u32 flags; +} aturChannelPerfDataEntry; + + +//ioctl(int fd, GET_ADSL_ATUC_CHAN_INTVL_INFO, void *struct_adslAtucChanIntvlInfo) + +typedef struct adslAtucChanIntvlInfo { + int ifIndex; + int IntervalNumber; + PerfIntervalCount chanIntervalRecvdBlks; + PerfIntervalCount chanIntervalXmitBlks; + PerfIntervalCount chanIntervalCorrectedBlks; + PerfIntervalCount chanIntervalUncorrectBlks; + int intervalValidData; + u8 flags; +} adslAtucChanIntvlInfo; + + +//ioctl(int fd, GET_ADSL_ATUR_CHAN_INTVL_INFO, void *struct_adslAturChanIntvlInfo) + +typedef struct adslAturChanIntvlInfo { + int ifIndex; + int IntervalNumber; + PerfIntervalCount chanIntervalRecvdBlks; + PerfIntervalCount chanIntervalXmitBlks; + PerfIntervalCount chanIntervalCorrectedBlks; + PerfIntervalCount chanIntervalUncorrectBlks; + int intervalValidData; + u8 flags; +} adslAturChanIntvlInfo; + + +//ioctl(int fd, GET_ADSL_ALRM_CONF_PROF, void *struct_adslLineAlarmConfProfileEntry) +//ioctl(int fd, SET_ADSL_ALRM_CONF_PROF, void *struct_adslLineAlarmConfProfileEntry) + +typedef struct adslLineAlarmConfProfileEntry + { + unsigned char adslLineAlarmConfProfileName[32]; + int adslAtucThresh15MinLofs; + int adslAtucThresh15MinLoss; + int adslAtucThresh15MinESs; + u32 adslAtucThreshFastRateUp; + u32 adslAtucThreshInterleaveRateUp; + u32 adslAtucThreshFastRateDown; + u32 adslAtucThreshInterleaveRateDown; + int adslAtucInitFailureTrapEnable; + int adslAturThresh15MinLofs; + int adslAturThresh15MinLoss; + int adslAturThresh15MinLprs; + int adslAturThresh15MinESs; + u32 adslAturThreshFastRateUp; + u32 adslAturThreshInterleaveRateUp; + u32 adslAturThreshFastRateDown; + u32 adslAturThreshInterleaveRateDown; + int adslLineAlarmConfProfileRowStatus; + u32 flags; +} adslLineAlarmConfProfileEntry; + +#ifdef IFXMIPS_MEI_MIB_RFC3440 +typedef struct adslLineAlarmConfProfileExtEntry + { + u8 adslLineAlarmConfProfileExtName[32]; + u32 adslAtucThreshold15MinFailedFastR; + u32 adslAtucThreshold15MinSesL; + u32 adslAtucThreshold15MinUasL; + u32 adslAturThreshold15MinSesL; + u32 adslAturThreshold15MinUasL; + u32 flags; +} adslLineAlarmConfProfileExtEntry; +#endif +//TRAPS + +/* The following Data Sturctures are added to support the WEB related parameters for ADSL Statistics */ +typedef struct adslLineStatus + { + int adslModemStatus; + u32 adslModeSelected; + int adslAtucThresh15MinESs; + int adslTrellisCodeEnable; + int adslLatency; + u8 flags; + } adslLineStatusInfo; + +typedef struct adslLineRate + { + u32 adslDataRateds; + u32 adslDataRateus; + u32 adslATTNDRds; + u32 adslATTNDRus; + u8 flags; + } adslLineRateInfo; + +typedef struct adslLineInfo + { + u32 adslInterleaveDepthds; + u32 adslInterleaveDepthus; + u32 adslLATNds; + u32 adslLATNus; + u32 adslSATNds; + u32 adslSATNus; + int adslSNRMds; + int adslSNRMus; + int adslACATPds; + int adslACATPus; + u32 flags; + } adslLineInfo; + +typedef struct adslNearEndPerfStats + { + u32 adslSuperFrames; + u32 adslneLOS; + u32 adslneLOF; + u32 adslneLPR; + u32 adslneNCD; + u32 adslneLCD; + u32 adslneCRC; + u32 adslneRSCorr; + u32 adslneFECS; + u32 adslneES; + u32 adslneSES; + u32 adslneLOSS; + u32 adslneUAS; + u32 adslneHECErrors; + u32 flags; + } adslNearEndPerfStats; + +typedef struct adslFarEndPerfStats + { + u32 adslfeLOS; + u32 adslfeLOF; + u32 adslfeLPR; + u32 adslfeNCD; + u32 adslfeLCD; + u32 adslfeCRC; + u32 adslfeRSCorr; + u32 adslfeFECS; + u32 adslfeES; + u32 adslfeSES; + u32 adslfeLOSS; + u32 adslfeUAS; + u32 adslfeHECErrors; + u32 flags; + } adslFarEndPerfStats; + +/* The number of tones (and hence indexes) is dependent on the ADSL mode - G.992.1, G.992.2, G.992.3, * G.992.4 and G.992.5 */ +typedef struct adslATURSubcarrierInfo { + int ifindex; + u16 HLINSCds; + u16 HLINpsds[1024];/* Even index = real part; Odd Index + = imaginary part for each tone */ + u16 HLOGMTds; + u16 HLOGpsds[512]; + u16 QLNMTds; + u16 QLNpsds[512]; + u16 SNRMTds; + u16 SNRpsds[512]; + u16 BITpsds[512]; + s16 GAINpsds[512]; /* Signed value in 0.1dB units. i.e dB * 10. + Needs to be converted into linear scale*/ + u16 flags; +}adslATURSubcarrierInfo; + +typedef struct adslATUCSubcarrierInfo { + int ifindex; + u16 HLINSCus; + u16 HLINpsus[128];/* Even index = real part; Odd Index + = imaginary part for each tone */ + u16 HLOGMTus; + u16 HLOGpsus[64]; + u16 QLNMTus; + u16 QLNpsus[64]; + u16 SNRMTus; + u16 SNRpsus[64]; + u16 BITpsus[64]; + s16 GAINpsus[64]; /* Signed value in 0.1dB units. i.e dB * 10. + Needs to be converted into linear scale*/ + u16 flags; +}adslATUCSubcarrierInfo; + +#ifndef u_int16 +#define u_int16 u16 +#endif + +typedef struct adslInitStats { + u_int16 FullInitializationCount; + u_int16 FailedFullInitializationCount; + u_int16 LINIT_Errors; + u_int16 Init_Timeouts; +}adslInitStats; + +typedef struct adslPowerSpectralDensity { + int ACTPSDds; + int ACTPSDus; +}adslPowerSpectralDensity; + +//ioctl(int fd, ADSL_ATUR_TRAPS, void *uint16_flags) +typedef union structpts { + adslLineTableEntry * adslLineTableEntry_pt; + adslAtucPhysEntry * adslAtucPhysEntry_pt; + adslAturPhysEntry * adslAturPhysEntry_pt; + adslAtucChanInfo * adslAtucChanInfo_pt; + adslAturChanInfo * adslAturChanInfo_pt; + atucPerfDataEntry * atucPerfDataEntry_pt; + aturPerfDataEntry * aturPerfDataEntry_pt; + adslAtucIntvlInfo * adslAtucIntvlInfo_pt; + adslAturIntvlInfo * adslAturIntvlInfo_pt; + atucChannelPerfDataEntry * atucChannelPerfDataEntry_pt; + aturChannelPerfDataEntry * aturChannelPerfDataEntry_pt; + adslAtucChanIntvlInfo * adslAtucChanIntvlInfo_pt; + adslAturChanIntvlInfo * adslAturChanIntvlInfo_pt; + adslLineAlarmConfProfileEntry * adslLineAlarmConfProfileEntry_pt; + // RFC 3440 + + #ifdef IFXMIPS_MEI_MIB_RFC3440 + adslLineExtTableEntry * adslLineExtTableEntry_pt; + atucPerfDataExtEntry * atucPerfDataExtEntry_pt; + adslAtucInvtlExtInfo * adslAtucInvtlExtInfo_pt; + aturPerfDataExtEntry * aturPerfDataExtEntry_pt; + adslAturInvtlExtInfo * adslAturInvtlExtInfo_pt; + adslLineAlarmConfProfileExtEntry * adslLineAlarmConfProfileExtEntry_pt; + #endif + adslLineStatusInfo * adslLineStatusInfo_pt; + adslLineRateInfo * adslLineRateInfo_pt; + adslLineInfo * adslLineInfo_pt; + adslNearEndPerfStats * adslNearEndPerfStats_pt; + adslFarEndPerfStats * adslFarEndPerfStats_pt; + adslATUCSubcarrierInfo * adslATUCSubcarrierInfo_pt; + adslATURSubcarrierInfo * adslATURSubcarrierInfo_pt; + adslPowerSpectralDensity * adslPowerSpectralDensity_pt; +}structpts; + +#endif /* ] __IFXMIPS_MEI_APP_IOCTL_H */ diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_bsp.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_bsp.h new file mode 100644 index 0000000000..c34662013c --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_bsp.h @@ -0,0 +1,308 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_bsp.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#ifndef _IFXMIPS_MEI_BSP_H_ +#define _IFXMIPS_MEI_BSP_H_ + +/*** Register address offsets, relative to MEI_SPACE_ADDRESS ***/ +#define MEI_DATA_XFR_OFFSET (0x0000) +#define MEI_VERSION_OFFSET (0x0004) +#define MEI_ARC_GP_STAT_OFFSET (0x0008) +#define MEI_DATA_XFR_STAT_OFFSET (0x000C) +#define MEI_XFR_ADDR_OFFSET (0x0010) +#define MEI_MAX_WAIT_OFFSET (0x0014) +#define MEI_TO_ARC_INT_OFFSET (0x0018) +#define ARC_TO_MEI_INT_OFFSET (0x001C) +#define ARC_TO_MEI_INT_MASK_OFFSET (0x0020) +#define MEI_DEBUG_WAD_OFFSET (0x0024) +#define MEI_DEBUG_RAD_OFFSET (0x0028) +#define MEI_DEBUG_DATA_OFFSET (0x002C) +#define MEI_DEBUG_DEC_OFFSET (0x0030) +#define MEI_CONFIG_OFFSET (0x0034) +#define MEI_RST_CONTROL_OFFSET (0x0038) +#define MEI_DBG_MASTER_OFFSET (0x003C) +#define MEI_CLK_CONTROL_OFFSET (0x0040) +#define MEI_BIST_CONTROL_OFFSET (0x0044) +#define MEI_BIST_STAT_OFFSET (0x0048) +#define MEI_XDATA_BASE_SH_OFFSET (0x004c) +#define MEI_XDATA_BASE_OFFSET (0x0050) +#define MEI_XMEM_BAR_BASE_OFFSET (0x0054) +#define MEI_XMEM_BAR0_OFFSET (0x0054) +#define MEI_XMEM_BAR1_OFFSET (0x0058) +#define MEI_XMEM_BAR2_OFFSET (0x005C) +#define MEI_XMEM_BAR3_OFFSET (0x0060) +#define MEI_XMEM_BAR4_OFFSET (0x0064) +#define MEI_XMEM_BAR5_OFFSET (0x0068) +#define MEI_XMEM_BAR6_OFFSET (0x006C)) +#define MEI_XMEM_BAR7_OFFSET (0x0070) +#define MEI_XMEM_BAR8_OFFSET (0x0074) +#define MEI_XMEM_BAR9_OFFSET (0x0078) +#define MEI_XMEM_BAR10_OFFSET (0x007C) +#define MEI_XMEM_BAR11_OFFSET (0x0080) +#define MEI_XMEM_BAR12_OFFSET (0x0084) +#define MEI_XMEM_BAR13_OFFSET (0x0088) +#define MEI_XMEM_BAR14_OFFSET (0x008C) +#define MEI_XMEM_BAR15_OFFSET (0x0090) +#define MEI_XMEM_BAR16_OFFSET (0x0094) + +#define WHILE_DELAY 20000 +/* +** Define where in ME Processor's memory map the Stratify chip lives +*/ + +#define MAXSWAPSIZE 8 * 1024 //8k *(32bits) + +// Mailboxes +#define MSG_LENGTH 16 // x16 bits +#define YES_REPLY 1 +#define NO_REPLY 0 + +#define CMV_TIMEOUT 1000 //jiffies + +// Block size per BAR +#define SDRAM_SEGMENT_SIZE (64*1024) +// Number of Bar registers +#define MAX_BAR_REGISTERS (17) + +#define XDATA_REGISTER (15) + +#define IFXMIPS_MEI_IOCTL_CMV_WINHOST IFX_ADSL_IOC_CMV_WINHOST + +#define IFXMIPS_MEI_IOCTL_CMV_READ IFX_ADSL_IOC_CMV_READ +#define IFXMIPS_MEI_IOCTL_CMV_WRITE IFX_ADSL_IOC_CMV_WRITE + +#define IFXMIPS_MEI_IOCTL_GET_BASE_ADDRESS IFX_ADSL_IOC_GET_BASE_ADDRESS + +// ARC register addresss +#define ARC_STATUS 0x0 +#define ARC_LP_START 0x2 +#define ARC_LP_END 0x3 +#define ARC_DEBUG 0x5 +#define ARC_INT_MASK 0x10A + +#define IRAM0_BASE (0x00000) +#define IRAM1_BASE (0x04000) +#define BRAM_BASE (0x0A000) + +#define ADSL_BASE (0x20000) +#define CRI_BASE (ADSL_BASE + 0x11F00) +#define CRI_CCR0 (CRI_BASE + 0x00) +#define CRI_RST (CRI_BASE + 0x04*4) +#define ADSL_DILV_BASE (ADSL_BASE+0x20000) + +// +#define IRAM0_ADDR_BIT_MASK 0xFFF +#define IRAM1_ADDR_BIT_MASK 0xFFF +#define BRAM_ADDR_BIT_MASK 0xFFF +#define RX_DILV_ADDR_BIT_MASK 0x1FFF + +/*** Bit definitions ***/ + +#define FALSE 0 +#define TRUE 1 +#define BIT0 1<<0 +#define BIT1 1<<1 +#define BIT2 1<<2 +#define BIT3 1<<3 +#define BIT4 1<<4 +#define BIT5 1<<5 +#define BIT6 1<<6 +#define BIT7 1<<7 +#define BIT8 1<<8 +#define BIT9 1<<9 +#define BIT10 1<<10 +#define BIT11 1<<11 +#define BIT12 1<<12 +#define BIT13 1<<13 +#define BIT14 1<<14 +#define BIT15 1<<15 +#define BIT16 1<<16 +#define BIT17 1<<17 +#define BIT18 1<<18 +#define BIT19 1<<19 +#define BIT20 1<<20 +#define BIT21 1<<21 +#define BIT22 1<<22 +#define BIT23 1<<23 +#define BIT24 1<<24 +#define BIT25 1<<25 +#define BIT26 1<<26 +#define BIT27 1<<27 +#define BIT28 1<<28 +#define BIT29 1<<29 +#define BIT30 1<<30 +#define BIT31 1<<31 + +// CRI_CCR0 Register definitions +#define CLK_2M_MODE_ENABLE BIT6 +#define ACL_CLK_MODE_ENABLE BIT4 +#define FDF_CLK_MODE_ENABLE BIT2 +#define STM_CLK_MODE_ENABLE BIT0 + +// CRI_RST Register definitions +#define FDF_SRST BIT3 +#define MTE_SRST BIT2 +#define FCI_SRST BIT1 +#define AAI_SRST BIT0 + +// MEI_TO_ARC_INTERRUPT Register definitions +#define MEI_TO_ARC_INT1 BIT3 +#define MEI_TO_ARC_INT0 BIT2 +#define MEI_TO_ARC_CS_DONE BIT1 //need to check +#define MEI_TO_ARC_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT Register definitions +#define ARC_TO_MEI_INT1 BIT8 +#define ARC_TO_MEI_INT0 BIT7 +#define ARC_TO_MEI_CS_REQ BIT6 +#define ARC_TO_MEI_DBG_DONE BIT5 +#define ARC_TO_MEI_MSGACK BIT4 +#define ARC_TO_MEI_NO_ACCESS BIT3 +#define ARC_TO_MEI_CHECK_AAITX BIT2 +#define ARC_TO_MEI_CHECK_AAIRX BIT1 +#define ARC_TO_MEI_MSGAV BIT0 + +// ARC_TO_MEI_INTERRUPT_MASK Register definitions +#define GP_INT1_EN BIT8 +#define GP_INT0_EN BIT7 +#define CS_REQ_EN BIT6 +#define DBG_DONE_EN BIT5 +#define MSGACK_EN BIT4 +#define NO_ACC_EN BIT3 +#define AAITX_EN BIT2 +#define AAIRX_EN BIT1 +#define MSGAV_EN BIT0 + +#define MEI_SOFT_RESET BIT0 + +#define HOST_MSTR BIT0 + +#define JTAG_MASTER_MODE 0x0 +#define MEI_MASTER_MODE HOST_MSTR + +// MEI_DEBUG_DECODE Register definitions +#define MEI_DEBUG_DEC_MASK (0x3) +#define MEI_DEBUG_DEC_AUX_MASK (0x0) +#define MEI_DEBUG_DEC_DMP1_MASK (0x1) +#define MEI_DEBUG_DEC_DMP2_MASK (0x2) +#define MEI_DEBUG_DEC_CORE_MASK (0x3) + +#define AUX_STATUS (0x0) +// ARC_TO_MEI_MAILBOX[11] is a special location used to indicate +// page swap requests. +#define MEI_TO_ARC_MAILBOX (0xDFD0) +#define MEI_TO_ARC_MAILBOXR (MEI_TO_ARC_MAILBOX + 0x2C) + +#define ARC_TO_MEI_MAILBOX (0xDFA0) +#define ARC_MEI_MAILBOXR (ARC_TO_MEI_MAILBOX + 0x2C) + +// Codeswap request messages are indicated by setting BIT31 +#define OMB_CODESWAP_MESSAGE_MSG_TYPE_MASK (0x80000000) + +// Clear Eoc messages received are indicated by setting BIT17 +#define OMB_CLEAREOC_INTERRUPT_CODE (0x00020000) + +/* +** Swap page header +*/ +// Page must be loaded at boot time if size field has BIT31 set +#define BOOT_FLAG (BIT31) +#define BOOT_FLAG_MASK ~BOOT_FLAG + +#define FREE_RELOAD 1 +#define FREE_SHOWTIME 2 +#define FREE_ALL 3 + +// marcos +#define IFXMIPS_WRITE_REGISTER_L(data,addr) do{ *((volatile u32*)(addr)) = (u32)(data);} while (0) +#define IFXMIPS_READ_REGISTER_L(addr) (*((volatile u32*)(addr))) +#define SET_BIT(reg, mask) reg |= (mask) +#define CLEAR_BIT(reg, mask) reg &= (~mask) +#define CLEAR_BITS(reg, mask) CLEAR_BIT(reg, mask) +#define SET_BITS(reg, mask) SET_BIT(reg, mask) +#define SET_BITFIELD(reg, mask, off, val) {reg &= (~mask); reg |= (val << off);} + +#define ALIGN_SIZE ( 1L<<10 ) //1K size align +#define MEM_ALIGN(addr) (((addr) + ALIGN_SIZE - 1) & ~ (ALIGN_SIZE -1) ) + +// swap marco +#define MEI_HALF_WORD_SWAP(data) {data = ((data & 0xffff)<<16) + ((data & 0xffff0000)>>16);} +#define MEI_BYTE_SWAP(data) {data = ((data & 0xff)<<24) + ((data & 0xff00)<<8)+ ((data & 0xff0000)>>8)+ ((data & 0xff000000)>>24);} + +// Swap page header describes size in 32-bit words, load location, and image offset +// for program and/or data segments +typedef struct _arc_swp_page_hdr { + u32 p_offset; //Offset bytes of progseg from beginning of image + u32 p_dest; //Destination addr of progseg on processor + u32 p_size; //Size in 32-bitwords of program segment + u32 d_offset; //Offset bytes of dataseg from beginning of image + u32 d_dest; //Destination addr of dataseg on processor + u32 d_size; //Size in 32-bitwords of data segment +} ARC_SWP_PAGE_HDR; + +/* +** Swap image header +*/ +#define GET_PROG 0 // Flag used for program mem segment +#define GET_DATA 1 // Flag used for data mem segment + +// Image header contains size of image, checksum for image, and count of +// page headers. Following that are 'count' page headers followed by +// the code and/or data segments to be loaded +typedef struct _arc_img_hdr { + u32 size; // Size of binary image in bytes + u32 checksum; // Checksum for image + u32 count; // Count of swp pages in image + ARC_SWP_PAGE_HDR page[1]; // Should be "count" pages - '1' to make compiler happy +} ARC_IMG_HDR; + +typedef struct smmu_mem_info { + int type; + unsigned long nCopy; + unsigned long size; + unsigned char *address; + unsigned char *org_address; +} smmu_mem_info_t; + +typedef struct ifxmips_mei_device_private { + int modem_ready; + int arcmsgav; + int cmv_reply; + int cmv_waiting; + // Mei to ARC CMV count, reply count, ARC Indicator count + int indicator_count; + int cmv_count; + int reply_count; + unsigned long image_size; + int nBar; + u16 Recent_indicator[MSG_LENGTH]; + + u16 CMV_RxMsg[MSG_LENGTH] __attribute__ ((aligned (4))); + + smmu_mem_info_t adsl_mem_info[MAX_BAR_REGISTERS]; + ARC_IMG_HDR *img_hdr; + // to wait for arc cmv reply, sleep on wait_queue_arcmsgav; + wait_queue_head_t wait_queue_arcmsgav; + wait_queue_head_t wait_queue_modemready; + MEI_mutex_t mei_cmv_sema; +} ifxmips_mei_device_private_t; + +#endif //_IFXMIPS_MEI_BSP_H_ diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_ioctl.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_ioctl.h new file mode 100644 index 0000000000..d11f04ea97 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_ioctl.h @@ -0,0 +1,734 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_ioctl.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#ifndef _IFXMIPS_MEI_IOCTL_H +#define _IFXMIPS_MEI_IOCTL_H + +///////////////////////////////////////////////////////////////////////////////////////////////////// +#define PCM_BUFF_SIZE 1024 //bytes +// interrupt numbers + +#if !(defined(_IFXMIPS_ADSL_APP) || defined (_AMAZON_ADSL_APP)) + +// Number of intervals +#define INTERVAL_NUM 192 //two days +typedef struct ifxmips_mei_mib { + struct list_head list; + struct timeval start_time; //start of current interval + + int AtucPerfLof; + int AtucPerfLos; + int AtucPerfEs; + int AtucPerfInit; + + int AturPerfLof; + int AturPerfLos; + int AturPerfLpr; + int AturPerfEs; + + int AturChanPerfRxBlk; + int AturChanPerfTxBlk; + int AturChanPerfCorrBlk; + int AturChanPerfUncorrBlk; + + //RFC-3440 + int AtucPerfStatFastR; + int AtucPerfStatFailedFastR; + int AtucPerfStatSesL; + int AtucPerfStatUasL; + int AturPerfStatSesL; + int AturPerfStatUasL; +} ifxmips_mei_mib; + +typedef struct adslChanPrevTxRate { + u32 adslAtucChanPrevTxRate; + u32 adslAturChanPrevTxRate; +} adslChanPrevTxRate; + +typedef struct adslPhysCurrStatus { + u32 adslAtucCurrStatus; + u32 adslAturCurrStatus; +} adslPhysCurrStatus; + +typedef struct ChanType { + int interleave; + int fast; + int bearchannel0; + int bearchannel1; +} ChanType; + +typedef struct mib_previous_read { + u16 ATUC_PERF_ESS; + u16 ATUR_PERF_ESS; + u32 ATUR_CHAN_RECV_BLK; + u16 ATUR_CHAN_CORR_BLK_INTL; + u16 ATUR_CHAN_CORR_BLK_FAST; + u16 ATUR_CHAN_UNCORR_BLK_INTL; + u16 ATUR_CHAN_UNCORR_BLK_FAST; + u16 ATUC_PERF_STAT_FASTR; + u16 ATUC_PERF_STAT_FAILED_FASTR; + u16 ATUC_PERF_STAT_SESL; + u16 ATUC_PERF_STAT_UASL; + u16 ATUR_PERF_STAT_SESL; +} mib_previous_read; + +typedef struct mib_flags_pretime { + struct timeval ATUC_PERF_LOSS_PTIME; + struct timeval ATUC_PERF_LOFS_PTIME; + struct timeval ATUR_PERF_LOSS_PTIME; + struct timeval ATUR_PERF_LOFS_PTIME; + struct timeval ATUR_PERF_LPR_PTIME; +} mib_flags_pretime; + + // cmv message structures +#define MP_PAYLOAD_SIZE 12 +typedef struct mpmessage { + u16 iFunction; + u16 iGroup; + u16 iAddress; + u16 iIndex; + u16 iPayload[MP_PAYLOAD_SIZE]; +} MPMessage; +#endif + +typedef struct meireg { + u32 iAddress; + u32 iData; +} meireg; + +#define MEIDEBUG_BUFFER_SIZES 50 +typedef struct meidebug { + u32 iAddress; + u32 iCount; + u32 buffer[MEIDEBUG_BUFFER_SIZES]; +} meidebug; + +//============================================================================== +// Group definitions +//============================================================================== +#define OPTN 5 +#define CNFG 8 +#define CNTL 1 +#define STAT 2 +#define RATE 6 +#define PLAM 7 +#define INFO 3 +#define TEST 4 +//============================================================================== +// Opcode definitions +//============================================================================== +#define H2D_CMV_READ 0x00 +#define H2D_CMV_WRITE 0x04 +#define H2D_CMV_INDICATE_REPLY 0x10 +#define H2D_ERROR_OPCODE_UNKNOWN 0x20 +#define H2D_ERROR_CMV_UNKNOWN 0x30 + +#define D2H_CMV_READ_REPLY 0x01 +#define D2H_CMV_WRITE_REPLY 0x05 +#define D2H_CMV_INDICATE 0x11 +#define D2H_ERROR_OPCODE_UNKNOWN 0x21 +#define D2H_ERROR_CMV_UNKNOWN 0x31 +#define D2H_ERROR_CMV_READ_NOT_AVAILABLE 0x41 +#define D2H_ERROR_CMV_WRITE_ONLY 0x51 +#define D2H_ERROR_CMV_READ_ONLY 0x61 + +#define H2D_DEBUG_READ_DM 0x02 +#define H2D_DEBUG_READ_PM 0x06 +#define H2D_DEBUG_WRITE_DM 0x0a +#define H2D_DEBUG_WRITE_PM 0x0e + +#define D2H_DEBUG_READ_DM_REPLY 0x03 +#define D2H_DEBUG_READ_FM_REPLY 0x07 +#define D2H_DEBUG_WRITE_DM_REPLY 0x0b +#define D2H_DEBUG_WRITE_FM_REPLY 0x0f +#define D2H_ERROR_ADDR_UNKNOWN 0x33 + +#define D2H_AUTONOMOUS_MODEM_READY_MSG 0xf1 +//============================================================================== +// INFO register address field definitions +//============================================================================== + +#define INFO_TxState 0 +#define INFO_RxState 1 +#define INFO_TxNextState 2 +#define INFO_RxNextState 3 +#define INFO_TxStateJumpFrom 4 +#define INFO_RxStateJumpFrom 5 + +#define INFO_ReverbSnrBuf 8 +#define INFO_ReverbEchoSnrBuf 9 +#define INFO_MedleySnrBuf 10 +#define INFO_RxShowtimeSnrBuf 11 +#define INFO_DECdelay 12 +#define INFO_DECExponent 13 +#define INFO_DECTaps 14 +#define INFO_AECdelay 15 +#define INFO_AECExponent 16 +#define INFO_AECTaps 17 +#define INFO_TDQExponent 18 +#define INFO_TDQTaps 19 +#define INFO_FDQExponent 20 +#define INFO_FDQTaps 21 +#define INFO_USBat 22 +#define INFO_DSBat 23 +#define INFO_USFineGains 24 +#define INFO_DSFineGains 25 +#define INFO_BitloadFirstChannel 26 +#define INFO_BitloadLastChannel 27 +#define INFO_PollEOCData 28 // CO specific +#define INFO_CSNRMargin 29 // CO specific +#define INFO_RCMsgs1 30 +#define INFO_RMsgs1 31 +#define INFO_RMsgRA 32 +#define INFO_RCMsgRA 33 +#define INFO_RMsg2 34 +#define INFO_RCMsg2 35 +#define INFO_BitLoadOK 36 +#define INFO_RCRates1 37 +#define INFO_RRates1Tab 38 +#define INFO_RMsgs1Tab 39 +#define INFO_RMsgRATab 40 +#define INFO_RRatesRA 41 +#define INFO_RCRatesRA 42 +#define INFO_RRates2 43 +#define INFO_RCRates2 44 +#define INFO_PackedRMsg2 45 +#define INFO_RxBitSwapFlag 46 +#define INFO_TxBitSwapFlag 47 +#define INFO_ShowtimeSNRUpdateCount 48 +#define INFO_ShowtimeFDQUpdateCount 49 +#define INFO_ShowtimeDECUpdateCount 50 +#define INFO_CopyRxBuffer 51 +#define INFO_RxToneBuf 52 +#define INFO_TxToneBuf 53 +#define INFO_Version 54 +#define INFO_TimeStamp 55 +#define INFO_feVendorID 56 +#define INFO_feSerialNum 57 +#define INFO_feVersionNum 58 +#define INFO_BulkMemory 59 //Points to start of bulk memory +#define INFO_neVendorID 60 +#define INFO_neVersionNum 61 +#define INFO_neSerialNum 62 + +//============================================================================== +// RATE register address field definitions +//============================================================================== + +#define RATE_UsRate 0 +#define RATE_DsRate 1 + +//============================================================================== +// PLAM (Physical Layer Management) register address field definitions +// (See G997.1 for reference) +//============================================================================== + + // /// + // Failure Flags /// + // /// + +#define PLAM_NearEndFailureFlags 0 +#define PLAM_FarEndFailureFlags 1 + + // /// + // Near End Failure Flags Bit Definitions /// + // /// + +// ADSL Failures /// +#define PLAM_LOS_FailureBit 0x0001 +#define PLAM_LOF_FailureBit 0x0002 +#define PLAM_LPR_FailureBit 0x0004 +#define PLAM_RFI_FailureBit 0x0008 + +// ATM Failures /// +#define PLAM_NCD_LP0_FailureBit 0x0010 +#define PLAM_NCD_LP1_FailureBit 0x0020 +#define PLAM_LCD_LP0_FailureBit 0x0040 +#define PLAM_LCD_LP1_FailureBit 0x0080 + +#define PLAM_NCD_BC0_FailureBit 0x0100 +#define PLAM_NCD_BC1_FailureBit 0x0200 +#define PLAM_LCD_BC0_FailureBit 0x0400 +#define PLAM_LCD_BC1_FailureBit 0x0800 + // /// + // Performance Counts /// + // /// + +#define PLAM_NearEndCrcCnt 2 +#define PLAM_CorrectedRSErrors 3 + +#define PLAM_NearEndECSCnt 6 +#define PLAM_NearEndESCnt 7 +#define PLAM_NearEndSESCnt 8 +#define PLAM_NearEndLOSSCnt 9 +#define PLAM_NearEndUASLCnt 10 + +#define PLAM_NearEndHECErrCnt 11 + +#define PLAM_NearEndHECTotCnt 16 +#define PLAM_NearEndCellTotCnt 18 +#define PLAM_NearEndSfCntLSW 20 +#define PLAM_NearEndSfCntMSW 21 + +#define PLAM_FarEndFebeCnt 24 + +#define PLAM_FarEndFecCnt 28 + +#define PLAM_FarEndFECSCnt 32 +#define PLAM_FarEndESCnt 33 +#define PLAM_FarEndSESCnt 34 +#define PLAM_FarEndLOSSCnt 35 +#define PLAM_FarEndUASLCnt 36 + +#define PLAM_FarEndHECErrCnt 37 + +#define PLAM_FarEndHECTotCnt 41 + +#define PLAM_FarEndCellTotCnt 43 + +#define PLAM_SNRMargin_0_1db 45 + +#define PLAM_SNRMargin 46 + +//============================================================================== +// CNTL register address and bit field definitions +//============================================================================== + +#define CNTL_ModemControl 0 + +#define CNTL_ModemReset 0x0 +#define CNTL_ModemStart 0x2 + +//============================================================================== +// STAT register address and bit field definitions +//============================================================================== + +#define STAT_MacroState 0 +#define STAT_Mode 1 +#define STAT_DMTFramingMode 2 +#define STAT_SleepState 3 +#define STAT_Misc 4 +#define STAT_FailureState 5 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // STAT_OLRStatus provides status of OLR + //16-bit STAT_OLRStatus_DS + // [1:0] : OLR status 00=IDLE, 01=OLR_IN_PROGRESS, 10=OLR_Completed, 11=OLR_Aborted + // [3:2]: Reserved + // [5:4]: OLR_Type (1:bitswap; 2: DRR; 3: SRA) + // [7:6]: Reserved + // [10:8]: >0=Request. 0=not. For DS, # of request transmissions/retransmissions (3 bits). + // [11]: 1=Receive Response, 0=not + // [15:12]: Reserved + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// +#define STAT_OLRStatus_DS 6 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // STAT_OLRStatus provides status of OLR + // 16-bit STAT_OLRStatus_US CMV + // [1:0] : OLR status 00=IDLE, 01=OLR_IN_PROGRESS, 10=OLR_Completed, 11=OLR_Aborted + // [3:2]: Reserved + // [5:4]: OLR_Type (1:bitswap; 2: DRR; 3: SRA) + // [7:6]: Reserved + // [8]: 1=Request Received. 0=not. + // [10:9]: Reserved + // [11]: 1=Response Sent, 0=not + // [15:12]: Reserved + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +/// +#define STAT_OLRStatus_US 7 + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // STAT_PMStatus provides status of PM + // 16-bit STAT_PMStatus CMV + // [1:0] : PM Status 00=IDLE, 01=PM_IN_PROGRESS, 10=PM_Completed, 11=PM_Aborted + // [2] : 0=ATU_R initiated PM; 1 = ATU_C initiated PM + // [3]: Reserved + // [5:4]: PM_Type (1:Simple Request; 2: L2 request; 3: L2 trim) + // [7:6]: Reserved + // [10:8]: >0=Request. 0=not. # of request transmissions/retransmissions (3 bits). + // [11]: 1=Response, 0=not + // [15:12]: Reserved + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// +#define STAT_PMStatus 8 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // 16-bit STAT_OLRError_DS, STAT_OLRError_US, STAT_PMError + // [3:0]: OLR/PM response reason code + // [7:4]: OLR/PM Internal error code + // [15:8]: OLR/PM Reserved for future + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + /// +#define STAT_OLRError_DS 9 +#define STAT_OLRError_US 10 +#define STAT_PMError 11 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STAT_MacroState +// MacroState reflects the high level state of the modem + +#define STAT_InitState 0x0000 +#define STAT_ReadyState 0x0001 +#define STAT_FailState 0x0002 +#define STAT_IdleState 0x0003 +#define STAT_QuietState 0x0004 +#define STAT_GhsState 0x0005 +#define STAT_FullInitState 0x0006 +#define STAT_ShowTimeState 0x0007 +#define STAT_FastRetrainState 0x0008 +#define STAT_LoopDiagMode 0x0009 +#define STAT_ShortInit 0x000A // Bis short initialization /// + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STAT_Mode +// ConfigurationMode indicates the mode of the current ADSL Link. In general, a modem may use +// G.Hs or some other mechanism to negotiate the specific mode of operation. +// The OPTN_modeControl CMV is used to select a set of desired modes. +// The STAT_Mode CMV indicates which mode was actually selected. + +#define STAT_ConfigMode_T1413 0x0001 +#define STAT_ConfigMode_G992_2_AB 0x0002 +#define STAT_ConfigMode_G992_1_A 0x0004 +#define STAT_ConfigMode_G992_1_B 0x0008 +#define STAT_ConfigMode_G992_1_C 0x0010 +#define STAT_ConfigMode_G992_2_C 0x0020 + +#define STAT_ConfigMode_G992_3_A 0x0100 +#define STAT_ConfigMode_G992_3_B 0x0200 +#define STAT_ConfigMode_G992_3_I 0x0400 +#define STAT_ConfigMode_G992_3_J 0x0800 +#define STAT_ConfigMode_G992_3_L 0x1000 + +#define STAT_ConfigMode_G992_4_A 0x2000 +#define STAT_ConfigMode_G992_4_I 0x4000 + +#define STAT_ConfigMode_G992_5 0x8000 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STAT_DMTFramingMode +// FramingMode indicates the DMT framing mde negotiated during initialization. The framing mode +// status is not applicable in BIS mode and its value is undefined +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define STAT_FramingModeMask 0x0003 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STAT_Misc +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define STAT_OverlappedSpectrum 0x0008 +#define STAT_TCM 0x0010 +#define STAT_TDQ_at_1104 0x0020 +#define STAT_T1413_Signal_Detected 0x0040 +#define STAT_AnnexL_US_Mask1_PSD 0x1000 //indicate we actually selected G992.3 AnnexL US PSD mask1 +#define STAT_AnnexL_US_Mask2_PSD 0x2000 //indicate we actually selected G992.3 AnnexL US PSD mask2 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// STAT_FailureState +// when the MacroSTate indicates the fail state, FailureState provides a failure code +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define E_CODE_NO_ERROR 0 +#define E_CODE_BAT_TX 1 // TX BAT table is incorrect */ +#define E_CODE_BAT_RX 2 // RX BAT table is incorrect */ +#define E_CODE_PROFILE 3 // profile is not selected in fast retrain */ +#define E_CODE_TX_AOC_FIFO_OVERFLOW 4 +#define E_CODE_TRUNCATE_FR 5 //Fast Retrain truncated due to no stored profiles*/ +#define E_CODE_BITLOAD 6 // bit loading fails */ +#define E_CODE_ST_ERROR 7 // showtime CRC error */ +#define E_CODE_RESERVED 8 // using parameters reserved by the ITU-T */ +#define E_CODE_C_TONES 9 // detected C_TONES */ +#define E_CODE_CODESWAP_ERR 10 // codeswap not finished in time */ +#define E_CODE_FIFO_OVERFLOW 11 // we have run out of fifo space */ +#define E_CODE_C_BG_DECODE_ERR 12 // error in decoding C-BG message */ +#define E_CODE_C_RATES2_DECODE_ERR 13 // error in decoding C-MSGS2 and C-RATES2 */ +#define E_CODE_RCMedleyRx_C_SEGUE2_Failure 14 // Timeout after RCMedleyRx waiting for C_SEGUE2 */ +#define E_CODE_RReverbRATx_C_SEGUE2_Failure 15 // Timeout after RReverbRATx waiting for C_SEGUE2 */ +#define E_CODE_RReverb3Tx_C_SEGUE1_Failure 16 // Timeout after RReverb3Tx waiting for C_SEGUE1 */ +#define E_CODE_RCCRC2Rx_C_RATES1_DECOD_ERR 17 // Received CRC not equal to computed CRC */ +#define E_CODE_RCCRC1Rx_C_RATES1_DECOD_ERR 18 // Received CRC not equal to computed CRC */ +#define E_CODE_RReverb5Tx_C_SEGUE2_Failure 19 // Timeout after RReverb5Tx waiting for C_SEGUE2 */ +#define E_CODE_RReverb6Tx_C_SEGUE3_Failure 20 // Timeout after RReverb6Tx waiting for C_SEGUE3 */ +#define E_CODE_RSegue5Tx_C_SEGUE3_Failure 21 // Timeout after RSegue5Tx waiting for C_SEGUE3 */ +#define E_CODE_RCReverb5Rx_C_SEGUE_Failure 22 // Timeout after RCReverb5Rx waiting for C_SEGUE */ +#define E_CODE_RCReverbRARx_C_SEGUE2_Failure 23 // Timeout after RCReverbRARx waiting for C_SEGUE2 */ +#define E_CODE_RCCRC4Rx_CMSGS2_DECOD_ERR 24 // Received CRC not equal to computed CRC */ +#define E_CODE_RCCRC5Rx_C_BG_DECOD_ERR 25 // Received CRC not equal to computed CRC */ +#define E_CODE_RCCRC3Rx_DECOD_ERR 26 // Received CRC not equal to computed CRC */ +#define E_CODE_RCPilot3_DEC_PATH_DEL_TIMEOUT 27 // DEC Path Delay timeout */ +#define E_CODE_RCPilot3_DEC_TRAINING_TIMEOUT 28 // DEC Training timeout */ +#define E_CODE_RCReverb3Rx_C_SEGUE1_Failure 29 // Timeout after RCReverb3Rx waiting for C_SEGUE1 */ +#define E_CODE_RCReverb2Rx_SignalEnd_Failure 30 // Timeout waiting for the end of RCReverb2Rx signal */ +#define E_CODE_RQuiet2_SignalEnd_Failure 31 // Timeout waiting for the end of RQuiet2 signal */ +#define E_CODE_RCReverbFR1Rx_Failure 32 // Timeout waiting for the end of RCReverbFR1Rx signal */ +#define E_CODE_RCPilotFR1Rx_SignalEnd_Failure 33 // Timeout waiting for the end of RCPilotFR1Rx signal */ +#define E_CODE_RCReverbFR2Rx_C_Segue_Failure 34 // Timeout after RCReverbFR2Rx waiting for C_SEGUE */ +#define E_CODE_RCReverbFR5Rx_SignalEnd_TIMEOUT 35 // Timeout waiting for the end of RCReverbFR5Rx signal */ +#define E_CODE_RCReverbFR6Rx_C_SEGUE_Failure 36 // Timeout after RCReverbFR6Rx waiting for C_SEGUE */ +#define E_CODE_RCReverbFR8Rx_C_SEGUE_FR4_Failure 37 // Timeout after RCReverbFR8Rx waiting for C_SEGUE_FR4 */ +#define E_CODE_RCReverbFR8Rx_No_PROFILE 38 // Timeout since no profile was selected */ +#define E_CODE_RCReverbFR8Rx_SignalEnd_TIMEOUT 39 // Timeout waiting for the end of RCReverbFR8Rx signal */ +#define E_CODE_RCCRCFR1_DECOD_ERR 40 // Received CRC not equal to computed CRC */ +#define E_CODE_RCRecovRx_SingnalEnd_TIMEOUT 41 // Timeout waiting for the end of RCRecovRx signal */ +#define E_CODE_RSegueFR5Tx_TX_Not_Ready_TIMEOUT 42 // Timeout after RSegueFR5Tx waiting for C_SEGUE2 */ +#define E_CODE_RRecovTx_SignalEnd_TIMEOUT 43 // Timeout waiting for the end of RRecovTx signal */ +#define E_CODE_RCMedleyFRRx_C_SEGUE2_Failure 44 // Timeout after RCMedleyFRRx waiting for C_SEGUE2 */ +#define E_CODE_CONFIGURATION_PARAMETERS_ERROR 45 // one of the configuration parameters do not meet the standard */ +#define E_CODE_BAD_MEM_ACCESS 46 +#define E_CODE_BAD_INSTRUCTION_ACCESS 47 +#define E_CODE_TX_EOC_FIFO_OVERFLOW 48 +#define E_CODE_RX_EOC_FIFO_OVERFLOW 49 +#define E_CODE_GHS_CD_FLAG_TIME_OUT 50 // Timeout when transmitting Flag in handshake cleardown */ + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//STAT_OLRStatus: +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define STAT_OLRPM_IDLE 0x0000 +#define STAT_OLRPM_IN_PROGRESS 0x0001 +#define STAT_OLRPM_COMPLETE 0x0002 +#define STAT_OLRPM_ABORTED 0x0003 +#define STAT_OLRPM_RESPONSE 0x0800 + +#define STAT_OLR_BITSWAP 0x0010 +#define STAT_OLR_DRR 0x0020 +#define STAT_OLR_SRA 0x0030 + +//STAT_PMStatus_US: +#define STAT_PM_CO_REQ 0x0004 +#define STAT_PM_SIMPLE_REQ 0x0010 +#define STAT_PM_L2_REQ 0x0020 +#define STAT_PM_L2_TRIM_REQ 0x0030 + +// STAT_OLRError_DS, STAT_OLRError_US +//4 bit response reason code: +#define RESP_BUSY 0x01 +#define RESP_INVALID_PARAMETERS 0x02 +#define RESP_NOT_ENABLED 0x03 +#define RESP_NOT_SUPPORTED 0x04 + +//4 bit internal error code (common for OLR and PM) +#define REQ_INVALID_BiGi 0x10 +#define REQ_INVALID_Lp 0x20 +#define REQ_INVALID_Bpn 0x30 +#define REQ_INVALID_FRAMING_CONSTRAINT 0x40 +#define REQ_NOT_IN_L0_STATE 0x50 +#define REQ_NOT_IN_L2_STATE 0x60 +#define REQ_INVALID_PCB 0x70 +#define REQ_VIOLATES_MARGIN 0x80 + +//STAT_PMError +//4 bit response reason code: +#define RESP_STATE_NOT_DESIRED 0x03 +#define RESP_INFEASIBLE_PARAMETERS 0x04 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OPTN register address and bit field definitions +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define OPTN_ModeControl 0 +#define OPTN_DMTLnkCtl 1 +// Reserved 2 +#define OPTN_GhsControl 3 +// Reserved 4 +#define OPTN_PwrManControl 5 +#define OPTN_AnnexControl 6 +#define OPTN_ModeControl1 7 +// Reserved 8 +#define OPTN_StateMachineCtrl 9 +// Reserved 10 +// Reserved 11 +#define OPTN_BisLinkControl 12 +#define OPTN_ATMAddrConfig 13 +#define OPTN_ATMNumCellConfig 14 + +// Mode control defines the allowable operating modes of an ADSL link. In general, a modem may /// +// use G.Hs or some other mechanism to negotiate the specific mode of operation. /// +// The OPTN_ModeControl CMV is used to select a set of desired modes /// +// The STAT_ModeControl CMV indicates which mode was actually selected /// + +// OPTN_ModeControl +#define OPTN_ConfigMode_T1413 0x0001 +#define OPTN_ConfigMode_G992_2_AB 0x0002 +#define OPTN_ConfigMode_G992_1_A 0x0004 +#define OPTN_ConfigMode_G992_1_B 0x0008 +#define OPTN_ConfigMode_G992_1_C 0x0010 +#define OPTN_ConfigMode_G992_2_C 0x0020 + +#define OPTN_ConfigMode_G992_3_A 0x0100 +#define OPTN_ConfigMode_G992_3_B 0x0200 +#define OPTN_ConfigMode_G992_3_I 0x0400 +#define OPTN_ConfigMode_G992_3_J 0x0800 +#define OPTN_ConfigMode_G992_3_L 0x1000 + +#define OPTN_ConfigMode_G992_4_A 0x2000 +#define OPTN_ConfigMode_G992_4_I 0x4000 + +#define OPTN_ConfigMode_G992_5 0x8000 + +// OPTN_PwrManControl +#define OPTN_PwrManWakeUpGhs 0x1 +#define OPTN_PwrManWakeUpFR 0x2 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OPTN_DMT Link Control +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define OPTN_DMT_DualLatency_Dis 0x200 +#define OPTN_DMT_S_Dis 0x100 +#define OPTN_DMT_FRAMINGMODE 0x1 +#define OPTN_DMT_FRAMINGMODE_MASK 0x7 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OPTN_BIS Link Control +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#define OPTN_BisLinkContrl_LineProbeDis 0x1 +#define OPTN_BisLinkContrl_DSBlackBitsEn 0x2 +#define OPTN_BisLinkContrl_DiagnosticModeEn 0x4 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OPTN_GhsControl +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// +// for OPTN_GhsControl, we will assign 16bit word as follows +// bit 0~3: set the control over which start(initial) message CPE will send: +// +// BIT: 2 1 0 +// 0 0 1 CLR +// 0 1 0 MR +// 0 1 1 MS +// 1 0 0 MP +// +// // bit 4~6: set the control over which message will be sent when we get at lease one CL/CLR exchange +// BIT: 5 4 +// 0 1 MS +// 1 0 MR +// 1 1 MP +// +// // bit 15: RT initiated G.hs sample sessions one through eight. Session one is default. +// BIT: 15 +// 1 means session one +// +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define OPTN_GHS_ST_GHS 0x8000 +#define OPTN_GHS_INIT_MASK 0x000F +#define OPTN_GHS_RESP_MASK 0x00F0 + +#define OPTN_RTInitTxMsg_CLR 0x0001 +#define OPTN_RTInitTxMsg_MR 0x0002 +#define OPTN_RTInitTxMsg_MS 0x0003 +#define OPTN_RTInitTxMsg_MP 0x0004 + +#define OPTN_RTRespTxMsg_MS 0x0010 +#define OPTN_RTRespTxMsg_MR 0x0020 +#define OPTN_RTRespTxMsg_MP 0x0030 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// OPTN_AnnexControl +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// G.992.3 Annex A/L1/L2 US PSD Mask preferred + +#define OPTN_G992_3_AnnexA_PreferredModeMask 0x3000 +#define OPTN_G992_3_AnnexA_PreferredModeA 0x0000 // default AnnexA PSD mask /// +#define OPTN_G992_3_AnnexA_PreferredModeL1 0x1000 // AnnexL wide spectrum upstream PSD mask /// +#define OPTN_G992_3_AnnexA_PreferredModeL2 0x2000 // AnnexL narrow spectrum upstream PSD mask /// + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//OPTN_ATMAddrConfig +// Bits 4:0 are Utopia address for BC1 +// Bits 9:5 are Utopia address for BC0 +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define OPTN_UTPADDR_BC1 0x001F +#define OPTN_UTPADDR_BC0 0x03E0 + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//OPTN_ATMNumCellConfig +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define OPTN_BC1_NUM_CELL_PAGES 0x000F // Bits 0:3 /// +#define OPTN_BC0_NUM_CELL_PAGES 0x00F0 // Bits 4:7 /// + +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// CNFG register address field /// +////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////// +// these cmvs are used by bis handshake /// +/////////////////////////////////////////// + +// Each of the CNFG_TPS entries points to a structure of type (TPS_TC_BearerChannel_t) +#define CNFG_TPS_TC_DS0 0 +#define CNFG_TPS_TC_DS1 1 +#define CNFG_TPS_TC_US0 2 +#define CNFG_TPS_TC_US1 3 + +#define CNFG_HDLC_Overhead_Requirements 4 + +// Each of the CNFG_PMS entries points to a structure of type (PMS_TC_LatencyPath_t) +#define CNFG_PMS_TC_DS0 5 +#define CNFG_PMS_TC_DS1 6 +#define CNFG_PMS_TC_US0 7 +#define CNFG_PMS_TC_US1 8 + +// CNFG_PMD_PARAMETERS points to a structure of type (PMD_params_t) +#define CNFG_PMD_PARAMETERS 9 + +//////////////////////////////////////////////////////////// +// these cmvs are used by bis training and showtime code /// +//////////////////////////////////////////////////////////// + +//////////////// +// Tx Config /// +//////////////// +#define CNFG_tx_Cnfg_Nbc 10 +#define CNFG_tx_Cnfg_Nlp 11 +#define CNFG_tx_Cnfg_Rp 12 +#define CNFG_tx_Cnfg_Mp 13 +#define CNFG_tx_Cnfg_Lp 14 +#define CNFG_tx_Cnfg_Tp 15 +#define CNFG_tx_Cnfg_Dp 16 +#define CNFG_tx_Cnfg_Bpn 17 +#define CNFG_tx_Cnfg_FramingMode 18 +#define CNFG_tx_Cnfg_MSGLp 19 +#define CNFG_tx_Cnfg_MSGc 20 + +//////////////// +// Rx Config /// +//////////////// +#define CNFG_rx_Cnfg_Nbc 21 +#define CNFG_rx_Cnfg_Nlp 22 +#define CNFG_rx_Cnfg_Rp 23 +#define CNFG_rx_Cnfg_Mp 24 +#define CNFG_rx_Cnfg_Lp 25 +#define CNFG_rx_Cnfg_Tp 26 +#define CNFG_rx_Cnfg_Dp 27 +#define CNFG_rx_Cnfg_Bpn 28 +#define CNFG_rx_Cnfg_FramingMode 29 +#define CNFG_rx_Cnfg_MSGLp 30 +#define CNFG_rx_Cnfg_MSGc 31 + +#define CNFG_tx_Cnfg_BCnToLPp 32 +#define CNFG_rx_Cnfg_BCnToLPp 33 + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_linux.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_linux.h new file mode 100644 index 0000000000..79849ae4fb --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_mei_linux.h @@ -0,0 +1,112 @@ +/****************************************************************************** +** +** FILE NAME : ifxmips_mei_linux.h +** PROJECT : Danube +** MODULES : MEI +** +** DATE : 1 Jan 2006 +** AUTHOR : TC Chen +** DESCRIPTION : MEI Driver +** COPYRIGHT : Copyright (c) 2006 +** Infineon Technologies AG +** Am Campeon 1-12, 85579 Neubiberg, Germany +** +** 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. +** +** HISTORY +** $Version $Date $Author $Comment +*******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef CONFIG_DEVFS_FS //165204:henryhsu devfs will make mei open file fail. + +#ifdef CONFIG_DEVFS_FS +#include +#endif +#ifdef CONFIG_PROC_FS +#include +#endif + +#include +#include +#define __LINUX__ + +#ifdef CONFIG_PROC_FS +#define PROC_ITEMS 8 +#define MEI_DIRNAME "mei" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_DEVFS_FS +#define IFXMIPS_DEVNAME "ifxmips" +#endif //ifdef CONFIG_DEVFS_FS + +#define MEI_LOCKINT(var) \ + local_save_flags(var);\ + local_irq_disable() +#define MEI_UNLOCKINT(var) \ + local_irq_restore(var) + +#define MEI_MUTEX_INIT(id,flag) \ + sema_init(&id,flag) +#define MEI_MUTEX_LOCK(id) \ + down_interruptible(&id) +#define MEI_MUTEX_UNLOCK(id) \ + up(&id) + +#define MEI_MASK_AND_ACK_IRQ \ + ifxmips_mask_and_ack_irq + +#define MEI_DISABLE_IRQ \ + disable_irq +#define MEI_ENABLE_IRQ \ + enable_irq + +#define MEI_WAIT(ms) \ + {\ + set_current_state(TASK_INTERRUPTIBLE);\ + schedule_timeout(ms);\ + } + +#define MEI_INIT_WAKELIST(name,queue) \ + init_waitqueue_head(&queue) + +#define MEI_WAIT_EVENT_TIMEOUT(ev,timeout)\ + interruptible_sleep_on_timeout(&ev,timeout) + +#define MEI_WAIT_EVENT(ev)\ + interruptible_sleep_on(&ev) +#define MEI_WAKEUP_EVENT(ev)\ + wake_up_interruptible(&ev) + +typedef unsigned long MEI_intstat_t; +typedef struct semaphore MEI_mutex_t; +typedef struct file MEI_file_t; +typedef struct inode MEI_inode_t; + +extern void mask_and_ack_ifxmips_irq (unsigned int irq_nr); diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_pmu.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_pmu.h new file mode 100644 index 0000000000..b842734452 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_pmu.h @@ -0,0 +1,30 @@ +/* + * 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. + * + * Copyright (C) 2007 John Crispin + */ +#ifndef _IFXMIPS_PMU_H__ +#define _IFXMIPS_PMU_H__ + +#define IFXMIPS_PMU_PWDCR_DMA 0x20 +#define IFXMIPS_PMU_PWDCR_LED 0x800 +#define IFXMIPS_PMU_PWDCR_GPT 0x1000 +#define IFXMIPS_PMU_PWDCR_PPE 0x2000 +#define IFXMIPS_PMU_PWDCR_FPI 0x4000 + +void ifxmips_pmu_enable (unsigned int module); +void ifxmips_pmu_disable (unsigned int module); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_prom.h b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_prom.h new file mode 100644 index 0000000000..822ff0bca6 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/ifxmips/ifxmips_prom.h @@ -0,0 +1,26 @@ +/* + * 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. + * + * Copyright (C) 2008 John Crispin + */ +#ifndef _IFXPROM_H__ +#define _IFXPROM_H__ + +extern void prom_printf(const char * fmt, ...); +extern u32 *prom_get_cp1_base(void); +extern u32 prom_get_cp1_size(void); +extern int ifxmips_has_brn_block(void); + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/gpio.h b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/gpio.h new file mode 100644 index 0000000000..0dece372d1 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/gpio.h @@ -0,0 +1,94 @@ +/* + * include/asm-mips/mach-ifxmips/gpio.h + * + * 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. + * + * Copyright (C) 2007 John Crispin + * + */ + + +#ifndef _IFXMIPS_GPIO_H_ +#define _IFXMIPS_GPIO_H_ + +#include +#include + +#define GPIO_TO_PORT(x) ((x > 15)?(1):(0)) +#define GPIO_TO_GPIO(x) ((x > 15)?(x-16):(x)) + +static inline int gpio_direction_input(unsigned gpio) { + ifxmips_port_set_open_drain(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_clear_altsel0(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_clear_altsel1(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_set_dir_in(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + return 0; +} + +static inline int gpio_direction_output(unsigned gpio, int value) { + ifxmips_port_clear_open_drain(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_clear_altsel0(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_clear_altsel1(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + ifxmips_port_set_dir_out(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + return 0; +} + +static inline int gpio_get_value(unsigned gpio) { + ifxmips_port_get_input(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + return 0; +} + +static inline void gpio_set_value(unsigned gpio, int value) { + if(value) + ifxmips_port_set_output(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); + else + ifxmips_port_clear_output(GPIO_TO_PORT(gpio), GPIO_TO_GPIO(gpio)); +} + +static inline int gpio_request(unsigned gpio, const char *label) { + return 0; +} + +static inline void gpio_free(unsigned gpio) { +} + +static inline int gpio_to_irq(unsigned gpio) { + return 0; +} + +static inline int irq_to_gpio(unsigned irq) { + return 0; +} + +static inline int gpio_cansleep(unsigned gpio) { + return 0; +} + +static inline int gpio_get_value_cansleep(unsigned gpio) { + might_sleep(); + return gpio_get_value(gpio); +} + +static inline void gpio_set_value_cansleep(unsigned gpio, int value) { + might_sleep(); + gpio_set_value(gpio, value); +} + +static inline int gpio_is_valid(int number) +{ + return ((unsigned)number) < 8; +} + +#endif diff --git a/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/irq.h b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/irq.h new file mode 100644 index 0000000000..f178abf485 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/irq.h @@ -0,0 +1,29 @@ +/* + * include/asm-mips/mach-ifxmips/irq.h + * + * 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. + * + * Copyright (C) 2007 John Crispin + * + */ + +#ifndef __IFXMIPS_IRQ_H +#define __IFXMIPS_IRQ_H + +#define NR_IRQS 256 +#include_next + +#endif + diff --git a/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/war.h b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/war.h new file mode 100644 index 0000000000..de3584ecf6 --- /dev/null +++ b/target/linux/ifxmips/files/include/asm-mips/mach-ifxmips/war.h @@ -0,0 +1,24 @@ +/* + * 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. + * + */ +#ifndef __ASM_MIPS_MACH_IFXMIPS_WAR_H +#define __ASM_MIPS_MACH_IFXMIPS_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 diff --git a/target/linux/ifxmips/image/Makefile b/target/linux/ifxmips/image/Makefile new file mode 100644 index 0000000000..15e0bc5dc3 --- /dev/null +++ b/target/linux/ifxmips/image/Makefile @@ -0,0 +1,34 @@ +# +# Copyright (C) 2006 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# +include $(TOPDIR)/rules.mk +include $(INCLUDE_DIR)/image.mk + +define Image/BuildKernel + $(STAGING_DIR_HOST)/bin/lzma e $(KDIR)/vmlinux $(KDIR)/vmlinux.lzma + mkimage -A mips -O linux -T kernel -a 0x80002000 -C lzma -e \ + 0x80002000 \ + -n 'MIPS OpenWrt Linux-$(LINUX_VERSION)' \ + -d $(KDIR)/vmlinux.lzma $(KDIR)/uImage + + cp $(KDIR)/uImage $(BIN_DIR)/openwrt-$(BOARD)-uImage +endef + +define Image/Build/squashfs + cat $(KDIR)/uImage $(KDIR)/root.$(1) > $(BIN_DIR)/openwrt-$(BOARD)-$(1).image + $(call prepare_generic_squashfs,$(BIN_DIR)/openwrt-$(BOARD)-$(1).image) +endef + +define Image/Build/jffs2-64k + dd if=$(KDIR)/uImage of=$(KDIR)/uImage.$(1) bs=64k conv=sync + cat $(KDIR)/uImage.$(1) $(KDIR)/root.$(1) > $(BIN_DIR)/openwrt-$(BOARD)-$(1).image +endef + +define Image/Build + $(call Image/Build/$(1),$(1)) +endef + +$(eval $(call BuildImage)) diff --git a/target/linux/ifxmips/patches/100-board.patch b/target/linux/ifxmips/patches/100-board.patch new file mode 100644 index 0000000000..db43c90b2c --- /dev/null +++ b/target/linux/ifxmips/patches/100-board.patch @@ -0,0 +1,80 @@ +--- a/arch/mips/Kconfig ++++ b/arch/mips/Kconfig +@@ -78,6 +78,21 @@ + select SYS_SUPPORTS_LITTLE_ENDIAN + select GENERIC_HARDIRQS_NO__DO_IRQ + ++config IFXMIPS ++ bool "Infineon Twinpass, Danube, Amazon-SE" ++ select DMA_NONCOHERENT ++ select IRQ_CPU ++ select CEVT_R4K ++ select CSRC_R4K ++ select SYS_HAS_CPU_MIPS32_R1 ++ select HAVE_STD_PC_SERIAL_PORT ++ select SYS_SUPPORTS_BIG_ENDIAN ++ select SYS_SUPPORTS_32BIT_KERNEL ++ select SYS_HAS_EARLY_PRINTK ++ select HW_HAS_PCI ++ select GENERIC_GPIO ++ select SWAP_IO_SPACE ++ + config MACH_DECSTATION + bool "DECstations" + select BOOT_ELF32 +@@ -697,6 +712,7 @@ + source "arch/mips/tx4927/Kconfig" + source "arch/mips/tx4938/Kconfig" + source "arch/mips/vr41xx/Kconfig" ++source "arch/mips/ifxmips/Kconfig" + + endmenu + +--- a/arch/mips/Makefile ++++ b/arch/mips/Makefile +@@ -283,6 +283,13 @@ + load-$(CONFIG_MIPS_COBALT) += 0xffffffff80080000 + + # ++# Infineon IFXMIPS ++# ++core-$(CONFIG_IFXMIPS) += arch/mips/ifxmips/ ++cflags-$(CONFIG_IFXMIPS) += -Iinclude/asm-mips/mach-ifxmips ++load-$(CONFIG_IFXMIPS) += 0xffffffff80002000 ++ ++# + # DECstation family + # + core-$(CONFIG_MACH_DECSTATION) += arch/mips/dec/ +--- a/include/asm-mips/bootinfo.h ++++ b/include/asm-mips/bootinfo.h +@@ -94,6 +94,12 @@ + #define MACH_MSP7120_FPGA 5 /* PMC-Sierra MSP7120 Emulation */ + #define MACH_MSP_OTHER 255 /* PMC-Sierra unknown board type */ + ++/* ++ * Valid machtype for group IFXMIPS ++ */ ++#define MACH_GROUP_IFXMIPS 29 ++#define MACH_INFINEON_IFXMIPS 0 ++ + #define CL_SIZE COMMAND_LINE_SIZE + + extern char *system_type; +--- a/arch/mips/kernel/traps.c ++++ b/arch/mips/kernel/traps.c +@@ -1464,6 +1464,7 @@ + */ + if (cpu_has_mips_r2) { + cp0_compare_irq = (read_c0_intctl() >> 29) & 7; ++ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ; + cp0_perfcount_irq = (read_c0_intctl() >> 26) & 7; + if (cp0_perfcount_irq == cp0_compare_irq) + cp0_perfcount_irq = -1; +--- a/arch/mips/pci/Makefile ++++ b/arch/mips/pci/Makefile +@@ -48,3 +48,4 @@ + obj-$(CONFIG_VICTOR_MPC30X) += fixup-mpc30x.o + obj-$(CONFIG_ZAO_CAPCELLA) += fixup-capcella.o + obj-$(CONFIG_WR_PPMC) += fixup-wrppmc.o ++obj-$(CONFIG_IFXMIPS) += pci-ifxmips.o ops-ifxmips.o diff --git a/target/linux/ifxmips/patches/110-drivers.patch b/target/linux/ifxmips/patches/110-drivers.patch new file mode 100644 index 0000000000..a25c57003a --- /dev/null +++ b/target/linux/ifxmips/patches/110-drivers.patch @@ -0,0 +1,149 @@ +--- a/drivers/char/Makefile ++++ b/drivers/char/Makefile +@@ -114,6 +114,10 @@ + obj-$(CONFIG_JS_RTC) += js-rtc.o + js-rtc-y = rtc.o + ++obj-$(CONFIG_IFXMIPS_SSC) += ifxmips_ssc.o ++obj-$(CONFIG_IFXMIPS_EEPROM) += ifxmips_eeprom.o ++obj-$(CONFIG_IFXMIPS_MEI) += ifxmips_mei_core.o ++ + # Files generated that shall be removed upon make clean + clean-files := consolemap_deftbl.c defkeymap.c + +--- a/drivers/mtd/maps/Makefile ++++ b/drivers/mtd/maps/Makefile +@@ -67,3 +67,4 @@ + obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o + obj-$(CONFIG_MTD_MTX1) += mtx-1_flash.o + obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o ++obj-$(CONFIG_MTD_IFXMIPS) += ifxmips.o +--- a/drivers/net/Kconfig ++++ b/drivers/net/Kconfig +@@ -351,6 +351,12 @@ + + source "drivers/net/arm/Kconfig" + ++config IFXMIPS_MII0 ++ tristate "Infineon IFXMips eth0 driver" ++ depends on IFXMIPS ++ help ++ Support for the MII0 inside the IFXMips SOC ++ + config AX88796 + tristate "ASIX AX88796 NE2000 clone support" + depends on ARM || MIPS || SUPERH +--- a/drivers/serial/Kconfig ++++ b/drivers/serial/Kconfig +@@ -1334,6 +1334,14 @@ + Currently, only 8250 compatible ports are supported, but + others can easily be added. + ++config SERIAL_IFXMIPS ++ bool "IFXMips serial driver" ++ depends on IFXMIPS ++ select SERIAL_CORE ++ select SERIAL_CORE_CONSOLE ++ help ++ Driver for the ifxmipss built in ASC hardware ++ + config SERIAL_QE + tristate "Freescale QUICC Engine serial port support" + depends on QUICC_ENGINE +--- a/drivers/serial/Makefile ++++ b/drivers/serial/Makefile +@@ -68,3 +68,4 @@ + obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o + obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o + obj-$(CONFIG_SERIAL_QE) += ucc_uart.o ++obj-$(CONFIG_SERIAL_IFXMIPS) += ifxmips_asc.o +--- a/drivers/watchdog/Makefile ++++ b/drivers/watchdog/Makefile +@@ -97,6 +97,7 @@ + obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o + obj-$(CONFIG_AR7_WDT) += ar7_wdt.o + obj-$(CONFIG_TXX9_WDT) += txx9wdt.o ++obj-$(CONFIG_IFXMIPS_WDT) += ifxmips_wdt.o + + # PARISC Architecture + +--- a/drivers/net/Makefile ++++ b/drivers/net/Makefile +@@ -256,4 +256,4 @@ + obj-$(CONFIG_NIU) += niu.o + obj-$(CONFIG_VIRTIO_NET) += virtio_net.o + obj-$(CONFIG_SFC) += sfc/ +- ++obj-$(CONFIG_IFXMIPS_MII0) += ifxmips_mii0.o +--- a/drivers/crypto/Kconfig ++++ b/drivers/crypto/Kconfig +@@ -9,6 +9,9 @@ + If you say N, all options in this submenu will be skipped and disabled. + + if CRYPTO_HW ++config CRYPTO_DEV_IFXMIPS ++ tristate "Support for IFXMIPS Data Encryption Unit" ++ depends on IFXMIPS + + config CRYPTO_DEV_PADLOCK + tristate "Support for VIA PadLock ACE" +--- a/drivers/crypto/Makefile ++++ b/drivers/crypto/Makefile +@@ -4,3 +4,4 @@ + obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o + obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o + obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o ++obj-$(CONFIG_CRYPTO_DEV_IFXMIPS) += ifxdeu-aes.o ifxdeu-des.o ifxdeu-dma.o ifxdeu-generic.o ifxdeu-md5.o ifxdeu-sha1.o +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -305,3 +305,10 @@ + help + This driver enables support for the on-chip R8A66597 in the + SH7366 and SH7723 processors. ++ ++config USB_DWC_HCD ++ tristate "IFXMIPS USB Host Controller Driver" ++ depends on USB && IFXMIPS ++ default y ++ help ++ Danube USB Host Controller +--- a/drivers/leds/Kconfig ++++ b/drivers/leds/Kconfig +@@ -153,6 +153,12 @@ + To compile this driver as a module, choose M here: the + module will be called leds-clevo-mail. + ++config LEDS_IFXMIPS ++ tristate "LED Support for IFXMIPS LEDs" ++ depends on LEDS_CLASS && IFXMIPS ++ help ++ This option enables support for the CM-X270 LEDs. ++ + comment "LED Triggers" + + config LEDS_TRIGGERS +--- a/drivers/leds/Makefile ++++ b/drivers/leds/Makefile +@@ -22,6 +22,7 @@ + obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o + obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o + obj-$(CONFIG_LEDS_FSG) += leds-fsg.o ++obj-$(CONFIG_LEDS_IFXMIPS) += leds-ifxmips.o + + # LED Triggers + obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o +--- a/drivers/watchdog/Kconfig ++++ b/drivers/watchdog/Kconfig +@@ -683,6 +683,12 @@ + help + Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs. + ++config IFXMIPS_WDT ++ bool "IFXMips watchdog" ++ depends on IFXMIPS ++ help ++ Hardware driver for the IFXMIPS Watchdog Timer. ++ + # PARISC Architecture + + # POWERPC Architecture diff --git a/target/linux/ifxmips/patches/160-cfi-swap.patch b/target/linux/ifxmips/patches/160-cfi-swap.patch new file mode 100644 index 0000000000..7649ec1ff4 --- /dev/null +++ b/target/linux/ifxmips/patches/160-cfi-swap.patch @@ -0,0 +1,13 @@ +--- a/drivers/mtd/chips/cfi_cmdset_0002.c ++++ b/drivers/mtd/chips/cfi_cmdset_0002.c +@@ -1041,7 +1041,9 @@ + int retry_cnt = 0; + + adr += chip->start; +- ++#ifdef CONFIG_IFXMIPS ++ adr ^= 2; ++#endif + spin_lock(chip->mutex); + ret = get_chip(map, chip, adr, FL_WRITING); + if (ret) { diff --git a/target/linux/ifxmips/patches/170-dma_hack.patch b/target/linux/ifxmips/patches/170-dma_hack.patch new file mode 100644 index 0000000000..38c58bb5cc --- /dev/null +++ b/target/linux/ifxmips/patches/170-dma_hack.patch @@ -0,0 +1,11 @@ +--- a/arch/mips/mm/cache.c ++++ b/arch/mips/mm/cache.c +@@ -50,6 +50,8 @@ + void (*_dma_cache_inv)(unsigned long start, unsigned long size); + + EXPORT_SYMBOL(_dma_cache_wback_inv); ++EXPORT_SYMBOL(_dma_cache_wback); ++EXPORT_SYMBOL(_dma_cache_inv); + + #endif /* CONFIG_DMA_NONCOHERENT */ + diff --git a/target/linux/ifxmips/profiles/100-Atheros.mk b/target/linux/ifxmips/profiles/100-Atheros.mk new file mode 100644 index 0000000000..71804b294f --- /dev/null +++ b/target/linux/ifxmips/profiles/100-Atheros.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Atheros + NAME:=Atheros WiFi (default) + PACKAGES:=kmod-madwifi +endef + +define Profile/Atheros/Description + Package set compatible with hardware using Atheros WiFi cards +endef +$(eval $(call Profile,Atheros)) + diff --git a/target/linux/ifxmips/profiles/200-Ralink.mk b/target/linux/ifxmips/profiles/200-Ralink.mk new file mode 100644 index 0000000000..dd9716ab59 --- /dev/null +++ b/target/linux/ifxmips/profiles/200-Ralink.mk @@ -0,0 +1,17 @@ +# +# Copyright (C) 2008 OpenWrt.org +# +# This is free software, licensed under the GNU General Public License v2. +# See /LICENSE for more information. +# + +define Profile/Ralink + NAME:=Ralink RT61 Wifi (ARV452) + PACKAGES:=kmod-rt61-pci +endef + +define Profile/Ralink/Description + Package set compatible with hardware using Ralink WiFi cards +endef +$(eval $(call Profile,Ralink)) + diff --git a/target/linux/ifxmips/series b/target/linux/ifxmips/series new file mode 100644 index 0000000000..19bcf21175 --- /dev/null +++ b/target/linux/ifxmips/series @@ -0,0 +1,88 @@ +Makefile +base-files/etc/config/network +config-2.6.23 +files/arch/mips/danube/Kconfig +files/arch/mips/danube/Makefile +files/arch/mips/danube/built-in.o +files/arch/mips/danube/dma-core.c +files/arch/mips/danube/dma-core.h +files/arch/mips/danube/dma-core.o +files/arch/mips/danube/interrupt.c +files/arch/mips/danube/interrupt.o +files/arch/mips/danube/kgdb_serial.c +files/arch/mips/danube/pci.c +files/arch/mips/danube/prom.c +files/arch/mips/danube/prom.o +files/arch/mips/danube/reset.c +files/arch/mips/danube/reset.o +files/arch/mips/danube/setup.c +files/arch/mips/danube/setup.o +files/drivers/mtd/maps/danube.c +files/drivers/serial/danube_asc.c +files/drivers/serial/danube_asc.c~ +files/drivers/serial/danube_asc.o +files/include/asm-mips/danube/adm6996.h +files/include/asm-mips/danube/atm_mib.h +files/include/asm-mips/danube/danube.h +files/include/asm-mips/danube/danube_bcu.h +files/include/asm-mips/danube/danube_cgu.h +files/include/asm-mips/danube/danube_deu.h +files/include/asm-mips/danube/danube_deu_structs.h +files/include/asm-mips/danube/danube_dma.h +files/include/asm-mips/danube/danube_eth2.h +files/include/asm-mips/danube/danube_eth2_fw.h +files/include/asm-mips/danube/danube_eth2_fw_with_dplus.h +files/include/asm-mips/danube/danube_eth2_fw_with_dplus_sb.h +files/include/asm-mips/danube/danube_eth_d2.h +files/include/asm-mips/danube/danube_eth_fw_d2.h +files/include/asm-mips/danube/danube_gpio.h +files/include/asm-mips/danube/danube_gptu.h +files/include/asm-mips/danube/danube_icu.h +files/include/asm-mips/danube/danube_led.h +files/include/asm-mips/danube/danube_mei.h +files/include/asm-mips/danube/danube_mei_app.h +files/include/asm-mips/danube/danube_mei_app_ioctl.h +files/include/asm-mips/danube/danube_mei_bsp.h +files/include/asm-mips/danube/danube_mei_ioctl.h +files/include/asm-mips/danube/danube_mei_linux.h +files/include/asm-mips/danube/danube_misc.h +files/include/asm-mips/danube/danube_pmu.h +files/include/asm-mips/danube/danube_ppa_api.h +files/include/asm-mips/danube/danube_ppa_eth_fw_d2.h +files/include/asm-mips/danube/danube_ppa_eth_fw_d3.h +files/include/asm-mips/danube/danube_ppa_hook.h +files/include/asm-mips/danube/danube_ppa_ppe_d3_hal.h +files/include/asm-mips/danube/danube_ppa_ppe_hal.h +files/include/asm-mips/danube/danube_ppa_stack_al.h +files/include/asm-mips/danube/danube_ppe.h +files/include/asm-mips/danube/danube_ppe_fw.h +files/include/asm-mips/danube/danube_ppe_fw_fix_for_pci.h +files/include/asm-mips/danube/danube_rcu.h +files/include/asm-mips/danube/danube_sdio_controller.h +files/include/asm-mips/danube/danube_sdio_controller_registers.h +files/include/asm-mips/danube/danube_ssc.h +files/include/asm-mips/danube/danube_sw.h +files/include/asm-mips/danube/danube_wdt.h +files/include/asm-mips/danube/danube_ws.h +files/include/asm-mips/danube/emulation.h +files/include/asm-mips/danube/ifx_mps.h +files/include/asm-mips/danube/ifx_peripheral_definitions.h +files/include/asm-mips/danube/ifx_sd_card.h +files/include/asm-mips/danube/ifx_serial.h +files/include/asm-mips/danube/ifx_ssc.h +files/include/asm-mips/danube/ifx_ssc_defines.h +files/include/asm-mips/danube/ifx_types.h +files/include/asm-mips/danube/infineon_sdio.h +files/include/asm-mips/danube/infineon_sdio_card.h +files/include/asm-mips/danube/infineon_sdio_cmds.h +files/include/asm-mips/danube/infineon_sdio_controller.h +files/include/asm-mips/danube/irq.h +files/include/asm-mips/danube/memcopy.h +files/include/asm-mips/danube/mps.h +files/include/asm-mips/danube/port.h +files/include/asm-mips/danube/ppe.h +files/include/asm-mips/danube/serial.h +files/include/asm-mips/mach-danube/irq.h +image/Makefile +patches/100-board.patch +patches/110-drivers.patch diff --git a/target/linux/ifxmips/wget-log b/target/linux/ifxmips/wget-log new file mode 100644 index 0000000000..83f0d554e2 --- /dev/null +++ b/target/linux/ifxmips/wget-log @@ -0,0 +1,25 @@ +HTTP request sent, awaiting response... 200 OK +Length: 49450713 (47M) [application/x-tar] +Saving to: `STDOUT' + + + +2008-09-28 21:04:13 (10.2 KB/s) - Read error at byte 519095/49450713 (Connection timed out). Retrying. + +--2008-09-28 21:04:14-- (try: 2) http://ftp.de.kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.5.tar.bz2 +Connecting to ftp.de.kernel.org|195.71.9.196|:80... connected. +HTTP request sent, awaiting response... 206 Partial Content +Length: 49450713 (47M), 48931618 (47M) remaining [application/x-tar] +Saving to: `STDOUT' + + + +2008-09-28 21:06:22 (12.7 KB/s) - Read error at byte 2177730/49450713 (Connection timed out). Retrying. + +--2008-09-28 21:06:24-- (try: 3) http://ftp.de.kernel.org/pub/linux/kernel/v2.6/linux-2.6.26.5.tar.bz2 +Connecting to ftp.de.kernel.org|195.71.9.196|:80... connected. +HTTP request sent, awaiting response... 206 Partial Content +Length: 49450713 (47M), 47272983 (45M) remaining [application/x-tar] +Saving to: `STDOUT' + + 5% [++ ] 2,836,764 16.7K/s eta 1h 55m 5% [++ ] 2,836,764 15.5K/s eta 1h 55m 5% [++ ] 2,836,764 14.4K/s eta 1h 57m 5% [++ ] 2,836,764 --.-K/s eta 1h 57m 5% [++ ] 2,836,764 --.-K/s eta 1h 59m 5% [++ ] 2,836,764 --.-K/s eta 1h 59m 5% [++ ] 2,836,764 --.-K/s eta 2h 2m \ No newline at end of file -- 2.30.2