diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2011-10-09 03:58:49 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2011-10-09 03:58:49 +0200 |
commit | 597da1b76ebd0083f929e59801f72a6dd6aef5cd (patch) | |
tree | 533372bf174baae1b81bccae1b6ba300a518d642 | |
parent | 0e7c77a3fdfa0504c31594dd800e460820a5fff1 (diff) | |
parent | 502ecda2d17ed4b50b6c4d5afb04832013996173 (diff) | |
download | barebox-597da1b76ebd0083f929e59801f72a6dd6aef5cd.tar.gz barebox-597da1b76ebd0083f929e59801f72a6dd6aef5cd.tar.xz |
Merge branch 'next'
282 files changed, 6494 insertions, 1154 deletions
diff --git a/.gitignore b/.gitignore index 84d9f73580..cc1f2e2446 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ cross_compile barebox barebox.S barebox.bin +barebox.srec barebox.netx barebox.map System.map @@ -689,6 +689,9 @@ barebox: $(barebox-lds) $(barebox-head) $(barebox-common) $(kallsyms.o) FORCE $(call if_changed_rule,barebox__) $(Q)rm -f .old_version +barebox.srec: barebox + $(OBJCOPY) -O srec $< $@ + # The actual objects are generated when descending, # make sure no implicit rule kicks in $(sort $(barebox-head) $(barebox-common) ) $(barebox-lds): $(barebox-dirs) ; diff --git a/arch/arm/Makefile b/arch/arm/Makefile index f1c045e04f..d25412d11f 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -105,6 +105,9 @@ board-$(CONFIG_MACH_FREESCALE_MX51_PDK) := freescale-mx51-pdk board-$(CONFIG_MACH_FREESCALE_MX53_LOCO) := freescale-mx53-loco board-$(CONFIG_MACH_GUF_CUPID) := guf-cupid board-$(CONFIG_MACH_MINI2440) := mini2440 +board-$(CONFIG_MACH_USB_A9260) := usb-a926x +board-$(CONFIG_MACH_USB_A9263) := usb-a926x +board-$(CONFIG_MACH_USB_A9G20) := usb-a926x board-$(CONFIG_MACH_VERSATILEPB) := versatile board-$(CONFIG_MACH_TX25) := karo-tx25 diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c index 44ac44bcbc..bbe16044ef 100644 --- a/arch/arm/boards/a9m2410/a9m2410.c +++ b/arch/arm/boards/a9m2410/a9m2410.c @@ -31,7 +31,7 @@ #include <generated/mach-types.h> #include <partition.h> #include <nand.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24x0-iomap.h> #include <mach/s3c24x0-nand.h> diff --git a/arch/arm/boards/a9m2440/a9m2410dev.c b/arch/arm/boards/a9m2440/a9m2410dev.c index 1220bd9777..5f7c53b9f6 100644 --- a/arch/arm/boards/a9m2440/a9m2410dev.c +++ b/arch/arm/boards/a9m2440/a9m2410dev.c @@ -27,7 +27,7 @@ #include <common.h> #include <driver.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24x0-iomap.h> /** diff --git a/arch/arm/boards/a9m2440/a9m2440.c b/arch/arm/boards/a9m2440/a9m2440.c index 89c9cdf57e..964d376412 100644 --- a/arch/arm/boards/a9m2440/a9m2440.c +++ b/arch/arm/boards/a9m2440/a9m2440.c @@ -31,7 +31,7 @@ #include <generated/mach-types.h> #include <partition.h> #include <nand.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24x0-iomap.h> #include <mach/s3c24x0-nand.h> #include <mach/s3c24xx-generic.h> diff --git a/arch/arm/boards/at91rm9200ek/init.c b/arch/arm/boards/at91rm9200ek/init.c index cff7ede4d3..b2008a4394 100644 --- a/arch/arm/boards/at91rm9200ek/init.c +++ b/arch/arm/boards/at91rm9200ek/init.c @@ -27,7 +27,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <mach/at91_pmc.h> #include <mach/board.h> diff --git a/arch/arm/boards/at91sam9260ek/init.c b/arch/arm/boards/at91sam9260ek/init.c index 861e8980a5..ea80a1b039 100644 --- a/arch/arm/boards/at91sam9260ek/init.c +++ b/arch/arm/boards/at91sam9260ek/init.c @@ -28,7 +28,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> @@ -63,8 +63,6 @@ static struct atmel_nand_data nand_pdata = { .ale = 21, .cle = 22, /* .det_pin = ... not connected */ - .ecc_base = (void __iomem *)(AT91_BASE_SYS + AT91_ECC), - .ecc_mode = NAND_ECC_HW, .rdy_pin = AT91_PIN_PC13, .enable_pin = AT91_PIN_PC14, #if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) diff --git a/arch/arm/boards/at91sam9261ek/init.c b/arch/arm/boards/at91sam9261ek/init.c index 73b411add0..0bef84d132 100644 --- a/arch/arm/boards/at91sam9261ek/init.c +++ b/arch/arm/boards/at91sam9261ek/init.c @@ -27,7 +27,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> @@ -43,7 +43,6 @@ static struct atmel_nand_data nand_pdata = { .ale = 22, .cle = 21, /* .det_pin = ... not connected */ - .ecc_mode = NAND_ECC_SOFT, .rdy_pin = AT91_PIN_PC15, .enable_pin = AT91_PIN_PC14, #if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) diff --git a/arch/arm/boards/at91sam9263ek/init.c b/arch/arm/boards/at91sam9263ek/init.c index 46f3a7ede2..40c0b7b6f2 100644 --- a/arch/arm/boards/at91sam9263ek/init.c +++ b/arch/arm/boards/at91sam9263ek/init.c @@ -29,7 +29,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> @@ -44,8 +44,6 @@ static struct atmel_nand_data nand_pdata = { .ale = 21, .cle = 22, /* .det_pin = ... not connected */ - .ecc_base = (void __iomem *)(AT91_BASE_SYS + AT91_ECC0), - .ecc_mode = NAND_ECC_HW, .rdy_pin = AT91_PIN_PA22, .enable_pin = AT91_PIN_PD15, #if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) diff --git a/arch/arm/boards/at91sam9m10g45ek/init.c b/arch/arm/boards/at91sam9m10g45ek/init.c index ba7c2fff48..073ff42374 100644 --- a/arch/arm/boards/at91sam9m10g45ek/init.c +++ b/arch/arm/boards/at91sam9m10g45ek/init.c @@ -30,7 +30,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> diff --git a/arch/arm/boards/chumby_falconwing/falconwing.c b/arch/arm/boards/chumby_falconwing/falconwing.c index 1c66eb231a..38f28be9c5 100644 --- a/arch/arm/boards/chumby_falconwing/falconwing.c +++ b/arch/arm/boards/chumby_falconwing/falconwing.c @@ -25,7 +25,7 @@ #include <sizes.h> #include <usb/ehci.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <generated/mach-types.h> #include <mach/imx-regs.h> diff --git a/arch/arm/boards/edb93xx/edb93xx.c b/arch/arm/boards/edb93xx/edb93xx.c index 3e4e0b04a0..70fd12c1bf 100644 --- a/arch/arm/boards/edb93xx/edb93xx.c +++ b/arch/arm/boards/edb93xx/edb93xx.c @@ -27,7 +27,7 @@ #include <init.h> #include <partition.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <generated/mach-types.h> #include <mach/ep93xx-regs.h> #include "edb93xx.h" diff --git a/arch/arm/boards/edb93xx/flash_cfg.c b/arch/arm/boards/edb93xx/flash_cfg.c index 91a6a4ea96..56bf0b57c2 100644 --- a/arch/arm/boards/edb93xx/flash_cfg.c +++ b/arch/arm/boards/edb93xx/flash_cfg.c @@ -24,7 +24,7 @@ #include <common.h> #include <mach/ep93xx-regs.h> -#include <asm/io.h> +#include <io.h> #define SMC_BCR6_VALUE (2 << SMC_BCR_IDCY_SHIFT | 5 << SMC_BCR_WST1_SHIFT | \ SMC_BCR_BLE | 2 << SMC_BCR_WST2_SHIFT | \ diff --git a/arch/arm/boards/edb93xx/pll_cfg.c b/arch/arm/boards/edb93xx/pll_cfg.c index a687af0a01..a53efa69c1 100644 --- a/arch/arm/boards/edb93xx/pll_cfg.c +++ b/arch/arm/boards/edb93xx/pll_cfg.c @@ -25,7 +25,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include "pll_cfg.h" #include "early_udelay.h" diff --git a/arch/arm/boards/edb93xx/sdram_cfg.c b/arch/arm/boards/edb93xx/sdram_cfg.c index 3d4fe08e19..8342d446b3 100644 --- a/arch/arm/boards/edb93xx/sdram_cfg.c +++ b/arch/arm/boards/edb93xx/sdram_cfg.c @@ -23,7 +23,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include "sdram_cfg.h" #include "early_udelay.h" diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c index 1c54202dfa..6355e3c205 100644 --- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c +++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c @@ -29,7 +29,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <led.h> diff --git a/arch/arm/boards/eukrea_cpuimx25/lowlevel.c b/arch/arm/boards/eukrea_cpuimx25/lowlevel.c index 4ebf247776..12219737c0 100644 --- a/arch/arm/boards/eukrea_cpuimx25/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx25/lowlevel.c @@ -26,7 +26,7 @@ #include <mach/imx-regs.h> #include <mach/imx-pll.h> #include <mach/esdctl.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm-generic/memory_layout.h> diff --git a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c index a5aadac0d9..994f45629b 100644 --- a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c +++ b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c @@ -37,7 +37,7 @@ #include <fcntl.h> #include <nand.h> #include <command.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <mach/imx-pll.h> #include <mach/imxfb.h> diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c index 426445f59d..5f654d47c1 100644 --- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c +++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c @@ -39,7 +39,7 @@ #include <partition.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <generated/mach-types.h> #include <asm/mmu.h> diff --git a/arch/arm/boards/eukrea_cpuimx35/lowlevel.c b/arch/arm/boards/eukrea_cpuimx35/lowlevel.c index 6c0e106f67..a909a8784e 100644 --- a/arch/arm/boards/eukrea_cpuimx35/lowlevel.c +++ b/arch/arm/boards/eukrea_cpuimx35/lowlevel.c @@ -26,7 +26,7 @@ #include <mach/imx-pll.h> #include <mach/esdctl.h> #include <asm/cache-l2x0.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm-generic/memory_layout.h> diff --git a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c index 727db29241..a128d500ad 100644 --- a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c +++ b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c @@ -34,7 +34,7 @@ #include <nand.h> #include <spi/spi.h> #include <mfd/mc13892.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <mach/imx-nand.h> #include <mach/spi.h> diff --git a/arch/arm/boards/freescale-mx25-3-stack/3stack.c b/arch/arm/boards/freescale-mx25-3-stack/3stack.c index 979115d927..5aa54e43ff 100644 --- a/arch/arm/boards/freescale-mx25-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx25-3-stack/3stack.c @@ -28,7 +28,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <partition.h> #include <generated/mach-types.h> #include <mach/imx-nand.h> diff --git a/arch/arm/boards/freescale-mx35-3-stack/3stack.c b/arch/arm/boards/freescale-mx35-3-stack/3stack.c index ab702650ab..030a1a7acf 100644 --- a/arch/arm/boards/freescale-mx35-3-stack/3stack.c +++ b/arch/arm/boards/freescale-mx35-3-stack/3stack.c @@ -37,7 +37,7 @@ #include <partition.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <generated/mach-types.h> #include <mach/gpio.h> diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c index 646f807c7a..d56effaaf9 100644 --- a/arch/arm/boards/freescale-mx51-pdk/board.c +++ b/arch/arm/boards/freescale-mx51-pdk/board.c @@ -32,7 +32,7 @@ #include <nand.h> #include <spi/spi.h> #include <mfd/mc13892.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <mach/imx-nand.h> #include <mach/spi.h> diff --git a/arch/arm/boards/freescale-mx53-loco/board.c b/arch/arm/boards/freescale-mx53-loco/board.c index b5240f4f3a..24df9ae0b0 100644 --- a/arch/arm/boards/freescale-mx53-loco/board.c +++ b/arch/arm/boards/freescale-mx53-loco/board.c @@ -36,7 +36,7 @@ #include <mach/iim.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> static struct fec_platform_data fec_info = { diff --git a/arch/arm/boards/guf-cupid/board.c b/arch/arm/boards/guf-cupid/board.c index 706707d0bb..158adfcda4 100644 --- a/arch/arm/boards/guf-cupid/board.c +++ b/arch/arm/boards/guf-cupid/board.c @@ -32,7 +32,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <partition.h> #include <nand.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/guf-cupid/lowlevel.c b/arch/arm/boards/guf-cupid/lowlevel.c index 8d403ee821..396604d59f 100644 --- a/arch/arm/boards/guf-cupid/lowlevel.c +++ b/arch/arm/boards/guf-cupid/lowlevel.c @@ -26,7 +26,7 @@ #include <mach/imx-pll.h> #include <mach/esdctl.h> #include <asm/cache-l2x0.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm-generic/memory_layout.h> diff --git a/arch/arm/boards/guf-neso/board.c b/arch/arm/boards/guf-neso/board.c index 446b333f1f..e524b70aac 100644 --- a/arch/arm/boards/guf-neso/board.c +++ b/arch/arm/boards/guf-neso/board.c @@ -32,7 +32,7 @@ #include <spi/spi.h> #include <usb/isp1504.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <asm/armlinux.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/guf-neso/lowlevel.c b/arch/arm/boards/guf-neso/lowlevel.c index d366d440af..b1ad621e06 100644 --- a/arch/arm/boards/guf-neso/lowlevel.c +++ b/arch/arm/boards/guf-neso/lowlevel.c @@ -26,7 +26,7 @@ #include <mach/imx-pll.h> #include <mach/esdctl.h> #include <asm/cache-l2x0.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm/system.h> diff --git a/arch/arm/boards/imx21ads/imx21ads.c b/arch/arm/boards/imx21ads/imx21ads.c index d58831e748..fc34709630 100644 --- a/arch/arm/boards/imx21ads/imx21ads.c +++ b/arch/arm/boards/imx21ads/imx21ads.c @@ -27,7 +27,7 @@ #include <environment.h> #include <mach/imx-regs.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <mach/gpio.h> #include <partition.h> #include <fs.h> diff --git a/arch/arm/boards/imx27ads/imx27ads.c b/arch/arm/boards/imx27ads/imx27ads.c index da4260fa58..e93f07a078 100644 --- a/arch/arm/boards/imx27ads/imx27ads.c +++ b/arch/arm/boards/imx27ads/imx27ads.c @@ -24,7 +24,7 @@ #include <environment.h> #include <mach/imx-regs.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <fec.h> #include <mach/gpio.h> #include <partition.h> diff --git a/arch/arm/boards/karo-tx25/board.c b/arch/arm/boards/karo-tx25/board.c index 22bc27a291..1eece1dfed 100644 --- a/arch/arm/boards/karo-tx25/board.c +++ b/arch/arm/boards/karo-tx25/board.c @@ -28,7 +28,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <partition.h> #include <generated/mach-types.h> #include <mach/imx-nand.h> diff --git a/arch/arm/boards/karo-tx25/lowlevel.c b/arch/arm/boards/karo-tx25/lowlevel.c index 868ba08dd7..09c0339659 100644 --- a/arch/arm/boards/karo-tx25/lowlevel.c +++ b/arch/arm/boards/karo-tx25/lowlevel.c @@ -24,7 +24,7 @@ #include <init.h> #include <mach/imx-regs.h> #include <mach/esdctl.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm/system.h> diff --git a/arch/arm/boards/karo-tx28/tx28-stk5.c b/arch/arm/boards/karo-tx28/tx28-stk5.c index 8427dc2391..b36d8226e5 100644 --- a/arch/arm/boards/karo-tx28/tx28-stk5.c +++ b/arch/arm/boards/karo-tx28/tx28-stk5.c @@ -20,8 +20,7 @@ #include <mci.h> #include <fec.h> #include <sizes.h> -#include <reloc.h> -#include <asm/io.h> +#include <io.h> #include <asm/sections.h> #include <mach/imx-regs.h> #include <mach/clock.h> diff --git a/arch/arm/boards/karo-tx28/tx28.c b/arch/arm/boards/karo-tx28/tx28.c index def388a8d9..a62cb8257f 100644 --- a/arch/arm/boards/karo-tx28/tx28.c +++ b/arch/arm/boards/karo-tx28/tx28.c @@ -18,7 +18,7 @@ #include <environment.h> #include <errno.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <generated/mach-types.h> #include <mach/imx-regs.h> #include <asm/mmu.h> diff --git a/arch/arm/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c index fd1f2f27c3..43510238e0 100644 --- a/arch/arm/boards/mini2440/mini2440.c +++ b/arch/arm/boards/mini2440/mini2440.c @@ -36,7 +36,7 @@ #include <mci.h> #include <fb.h> #include <asm/armlinux.h> -#include <asm/io.h> +#include <io.h> #include <mach/gpio.h> #include <mach/s3c24x0-iomap.h> #include <mach/s3c24x0-nand.h> diff --git a/arch/arm/boards/mmccpu/init.c b/arch/arm/boards/mmccpu/init.c index 36bc193bfc..51dbf24621 100644 --- a/arch/arm/boards/mmccpu/init.c +++ b/arch/arm/boards/mmccpu/init.c @@ -28,7 +28,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> diff --git a/arch/arm/boards/nhk8815/setup.c b/arch/arm/boards/nhk8815/setup.c index dcf716620d..42d981cbfd 100644 --- a/arch/arm/boards/nhk8815/setup.c +++ b/arch/arm/boards/nhk8815/setup.c @@ -26,7 +26,7 @@ #include <nand.h> #include <asm/armlinux.h> #include <generated/mach-types.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #include <mach/board.h> diff --git a/arch/arm/boards/omap/board-beagle.c b/arch/arm/boards/omap/board-beagle.c index 4e7f179a6f..bfb08f7042 100644 --- a/arch/arm/boards/omap/board-beagle.c +++ b/arch/arm/boards/omap/board-beagle.c @@ -57,7 +57,7 @@ #include <init.h> #include <driver.h> #include <sizes.h> -#include <asm/io.h> +#include <io.h> #include <ns16550.h> #include <asm/armlinux.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/omap/board-omap3evm.c b/arch/arm/boards/omap/board-omap3evm.c index 71d6ca9e40..d2f041ad71 100644 --- a/arch/arm/boards/omap/board-omap3evm.c +++ b/arch/arm/boards/omap/board-omap3evm.c @@ -48,7 +48,7 @@ #include <console.h> #include <init.h> #include <driver.h> -#include <asm/io.h> +#include <io.h> #include <ns16550.h> #include <asm/armlinux.h> #include <mach/silicon.h> diff --git a/arch/arm/boards/omap/board-sdp343x.c b/arch/arm/boards/omap/board-sdp343x.c index 83efe62233..d486c20d74 100644 --- a/arch/arm/boards/omap/board-sdp343x.c +++ b/arch/arm/boards/omap/board-sdp343x.c @@ -51,7 +51,7 @@ #include <console.h> #include <init.h> #include <driver.h> -#include <asm/io.h> +#include <io.h> #include <ns16550.h> #include <asm/armlinux.h> #include <mach/silicon.h> diff --git a/arch/arm/boards/panda/board.c b/arch/arm/boards/panda/board.c index 33ec144db4..6a149aaeaa 100644 --- a/arch/arm/boards/panda/board.c +++ b/arch/arm/boards/panda/board.c @@ -3,7 +3,7 @@ #include <init.h> #include <fs.h> #include <driver.h> -#include <asm/io.h> +#include <io.h> #include <ns16550.h> #include <asm/armlinux.h> #include <linux/stat.h> diff --git a/arch/arm/boards/panda/lowlevel.c b/arch/arm/boards/panda/lowlevel.c index cc0c374a03..45ea221d87 100644 --- a/arch/arm/boards/panda/lowlevel.c +++ b/arch/arm/boards/panda/lowlevel.c @@ -21,7 +21,7 @@ * MA 02111-1307 USA */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-mux.h> #include <mach/omap4-silicon.h> #include <mach/omap4-clock.h> diff --git a/arch/arm/boards/panda/mux.c b/arch/arm/boards/panda/mux.c index a03104011d..7586e86745 100644 --- a/arch/arm/boards/panda/mux.c +++ b/arch/arm/boards/panda/mux.c @@ -1,6 +1,6 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-mux.h> diff --git a/arch/arm/boards/pcm037/pcm037.c b/arch/arm/boards/pcm037/pcm037.c index 85f004fe48..42a543d2cc 100644 --- a/arch/arm/boards/pcm037/pcm037.c +++ b/arch/arm/boards/pcm037/pcm037.c @@ -32,7 +32,7 @@ #include <mach/iomux-mx31.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <partition.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/pcm038/lowlevel.c b/arch/arm/boards/pcm038/lowlevel.c index b50e1c8386..32392636e7 100644 --- a/arch/arm/boards/pcm038/lowlevel.c +++ b/arch/arm/boards/pcm038/lowlevel.c @@ -25,7 +25,7 @@ #include <mach/imx-regs.h> #include <mach/imx-pll.h> #include <mach/esdctl.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm/system.h> diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c index 6fee5c2d61..0b07a6378a 100644 --- a/arch/arm/boards/pcm038/pcm038.c +++ b/arch/arm/boards/pcm038/pcm038.c @@ -35,7 +35,7 @@ #include <nand.h> #include <command.h> #include <spi/spi.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <mach/imx-pll.h> #include <mach/imxfb.h> diff --git a/arch/arm/boards/pcm043/lowlevel.c b/arch/arm/boards/pcm043/lowlevel.c index e488681c13..40e3204425 100644 --- a/arch/arm/boards/pcm043/lowlevel.c +++ b/arch/arm/boards/pcm043/lowlevel.c @@ -26,7 +26,7 @@ #include <mach/imx-pll.h> #include <mach/esdctl.h> #include <asm/cache-l2x0.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <asm/barebox-arm.h> #include <asm-generic/memory_layout.h> diff --git a/arch/arm/boards/pcm043/pcm043.c b/arch/arm/boards/pcm043/pcm043.c index fbe8cea12f..23580c9f6f 100644 --- a/arch/arm/boards/pcm043/pcm043.c +++ b/arch/arm/boards/pcm043/pcm043.c @@ -32,7 +32,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <partition.h> #include <nand.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c index 3d0277988e..8de333f0d9 100644 --- a/arch/arm/boards/pcm049/board.c +++ b/arch/arm/boards/pcm049/board.c @@ -22,7 +22,7 @@ #include <console.h> #include <init.h> #include <driver.h> -#include <asm/io.h> +#include <io.h> #include <ns16550.h> #include <asm/armlinux.h> #include <generated/mach-types.h> diff --git a/arch/arm/boards/pcm049/lowlevel.c b/arch/arm/boards/pcm049/lowlevel.c index e036ba742d..bea895e31f 100644 --- a/arch/arm/boards/pcm049/lowlevel.c +++ b/arch/arm/boards/pcm049/lowlevel.c @@ -21,7 +21,7 @@ * MA 02111-1307 USA */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-mux.h> #include <mach/omap4-silicon.h> #include <mach/omap4-clock.h> diff --git a/arch/arm/boards/pcm049/mux.c b/arch/arm/boards/pcm049/mux.c index d93d4589eb..9911b62e5a 100644 --- a/arch/arm/boards/pcm049/mux.c +++ b/arch/arm/boards/pcm049/mux.c @@ -1,6 +1,6 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-mux.h> diff --git a/arch/arm/boards/phycard-i.MX27/pca100.c b/arch/arm/boards/phycard-i.MX27/pca100.c index f285466641..41567673a7 100644 --- a/arch/arm/boards/phycard-i.MX27/pca100.c +++ b/arch/arm/boards/phycard-i.MX27/pca100.c @@ -32,7 +32,7 @@ #include <fcntl.h> #include <nand.h> #include <spi/spi.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-nand.h> #include <mach/imx-pll.h> #include <gpio.h> diff --git a/arch/arm/boards/pm9261/init.c b/arch/arm/boards/pm9261/init.c index efc5dcc1fb..2766f473d8 100644 --- a/arch/arm/boards/pm9261/init.c +++ b/arch/arm/boards/pm9261/init.c @@ -27,7 +27,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> diff --git a/arch/arm/boards/pm9263/init.c b/arch/arm/boards/pm9263/init.c index aeca4e7d79..92d7e9f166 100644 --- a/arch/arm/boards/pm9263/init.c +++ b/arch/arm/boards/pm9263/init.c @@ -28,7 +28,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> @@ -43,8 +43,6 @@ static struct atmel_nand_data nand_pdata = { .ale = 21, .cle = 22, /* .det_pin = ... not connected */ - .ecc_base = (void __iomem *)(AT91_BASE_SYS + AT91_ECC0), - .ecc_mode = NAND_ECC_HW, .rdy_pin = AT91_PIN_PB30, .enable_pin = AT91_PIN_PD15, #if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) diff --git a/arch/arm/boards/pm9g45/init.c b/arch/arm/boards/pm9g45/init.c index 35c9ce9f83..480c7513e3 100644 --- a/arch/arm/boards/pm9g45/init.c +++ b/arch/arm/boards/pm9g45/init.c @@ -29,7 +29,7 @@ #include <partition.h> #include <fs.h> #include <fcntl.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware.h> #include <nand.h> #include <linux/mtd/nand.h> diff --git a/arch/arm/boards/scb9328/scb9328.c b/arch/arm/boards/scb9328/scb9328.c index e90417f01e..906a17e07e 100644 --- a/arch/arm/boards/scb9328/scb9328.c +++ b/arch/arm/boards/scb9328/scb9328.c @@ -26,7 +26,7 @@ #include <mach/imx-regs.h> #include <asm/armlinux.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <partition.h> #include <fs.h> #include <fcntl.h> diff --git a/arch/arm/boards/usb-a926x/Makefile b/arch/arm/boards/usb-a926x/Makefile new file mode 100644 index 0000000000..eb072c0161 --- /dev/null +++ b/arch/arm/boards/usb-a926x/Makefile @@ -0,0 +1 @@ +obj-y += init.o diff --git a/arch/arm/boards/usb-a926x/config.h b/arch/arm/boards/usb-a926x/config.h new file mode 100644 index 0000000000..d97181032f --- /dev/null +++ b/arch/arm/boards/usb-a926x/config.h @@ -0,0 +1,6 @@ +#ifndef __CONFIG_H +#define __CONFIG_H + +#define AT91_MAIN_CLOCK 12000000 /* 12 MHz crystal */ + +#endif /* __CONFIG_H */ diff --git a/arch/arm/boards/usb-a926x/env/config b/arch/arm/boards/usb-a926x/env/config new file mode 100644 index 0000000000..d77f6785f5 --- /dev/null +++ b/arch/arm/boards/usb-a926x/env/config @@ -0,0 +1,41 @@ +#!/bin/sh + +# use 'dhcp' to do dhcp in barebox and in kernel +# use 'none' if you want to skip kernel ip autoconfiguration +ip=dhcp + +# or set your networking parameters here +#eth0.ipaddr=a.b.c.d +#eth0.netmask=a.b.c.d +#eth0.gateway=a.b.c.d +#eth0.serverip=a.b.c.d + +# can be either 'nfs', 'tftp', 'nor' or 'nand' +kernel_loc=tftp +# can be either 'net', 'nor', 'nand' or 'initrd' +rootfs_loc=net + +# can be either 'jffs2' or 'ubifs' +rootfs_type=ubifs +rootfsimage=root.$rootfs_type + +# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo +#kernelimage_type=zimage +#kernelimage=zImage +kernelimage_type=uimage +kernelimage=uImage +#kernelimage_type=raw +#kernelimage=Image +#kernelimage_type=raw_lzo +#kernelimage=Image.lzo + +nand_device=atmel_nand +nand_parts="128k(at91bootstrap),256k(barebox)ro,128k(bareboxenv),128k(bareboxenv2),4M(kernel),120M(rootfs),-(data)" +rootfs_mtdblock_nand=5 + +autoboot_timeout=3 + +bootargs="console=ttyS0,115200" + +# set a fancy prompt (if support is compiled in) +PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m\n# " diff --git a/arch/arm/boards/usb-a926x/init.c b/arch/arm/boards/usb-a926x/init.c new file mode 100644 index 0000000000..535458226c --- /dev/null +++ b/arch/arm/boards/usb-a926x/init.c @@ -0,0 +1,202 @@ +/* + * Copyright (C) 2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com> + * + * 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 <common.h> +#include <net.h> +#include <init.h> +#include <environment.h> +#include <asm/armlinux.h> +#include <generated/mach-types.h> +#include <partition.h> +#include <fs.h> +#include <fcntl.h> +#include <io.h> +#include <asm/hardware.h> +#include <nand.h> +#include <sizes.h> +#include <linux/mtd/nand.h> +#include <linux/clk.h> +#include <mach/board.h> +#include <mach/at91sam9_smc.h> +#include <mach/sam9_smc.h> +#include <gpio.h> +#include <mach/io.h> +#include <mach/at91_pmc.h> +#include <mach/at91_rstc.h> + +static void usb_a9260_set_board_type(void) +{ + if (machine_is_usb_a9g20()) + armlinux_set_architecture(MACH_TYPE_USB_A9G20); + else if (machine_is_usb_a9263()) + armlinux_set_architecture(MACH_TYPE_USB_A9263); + else + armlinux_set_architecture(MACH_TYPE_USB_A9260); +} + +static struct atmel_nand_data nand_pdata = { + .ale = 21, + .cle = 22, +/* .det_pin = ... not connected */ + .rdy_pin = AT91_PIN_PC13, + .enable_pin = AT91_PIN_PC14, +}; + +static struct sam9_smc_config usb_a9260_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 1, + .ncs_write_setup = 0, + .nwe_setup = 1, + + .ncs_read_pulse = 3, + .nrd_pulse = 3, + .ncs_write_pulse = 3, + .nwe_pulse = 3, + + .read_cycle = 5, + .write_cycle = 5, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 2, +}; + +static struct sam9_smc_config usb_a9g20_nand_smc_config = { + .ncs_read_setup = 0, + .nrd_setup = 2, + .ncs_write_setup = 0, + .nwe_setup = 2, + + .ncs_read_pulse = 4, + .nrd_pulse = 4, + .ncs_write_pulse = 4, + .nwe_pulse = 2, + + .read_cycle = 7, + .write_cycle = 7, + + .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE | AT91_SMC_DBW_8, + .tdf_cycles = 3, +}; + +static void usb_a9260_add_device_nand(void) +{ + /* configure chip-select 3 (NAND) */ + if (machine_is_usb_a9g20()) + sam9_smc_configure(3, &usb_a9g20_nand_smc_config); + else + sam9_smc_configure(3, &usb_a9260_nand_smc_config); + + if (machine_is_usb_a9263()) { + nand_pdata.rdy_pin = AT91_PIN_PA22; + nand_pdata.enable_pin = AT91_PIN_PD15; + } + + at91_add_device_nand(&nand_pdata); +} + +static struct at91_ether_platform_data macb_pdata = { + .flags = AT91SAM_ETHER_RMII, + .phy_addr = 0, +}; + +static void usb_a9260_phy_reset(void) +{ + unsigned long rstc; + struct clk *clk = clk_get(NULL, "macb_clk"); + + clk_enable(clk); + + at91_set_gpio_input(AT91_PIN_PA14, 0); + at91_set_gpio_input(AT91_PIN_PA15, 0); + at91_set_gpio_input(AT91_PIN_PA17, 0); + at91_set_gpio_input(AT91_PIN_PA25, 0); + at91_set_gpio_input(AT91_PIN_PA26, 0); + at91_set_gpio_input(AT91_PIN_PA28, 0); + + rstc = at91_sys_read(AT91_RSTC_MR) & AT91_RSTC_ERSTL; + + /* Need to reset PHY -> 500ms reset */ + at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | + (AT91_RSTC_ERSTL & (0x0d << 8)) | + AT91_RSTC_URSTEN); + + at91_sys_write(AT91_RSTC_CR, AT91_RSTC_KEY | AT91_RSTC_EXTRST); + + /* Wait for end hardware reset */ + while (!(at91_sys_read(AT91_RSTC_SR) & AT91_RSTC_NRSTL)); + + /* Restore NRST value */ + at91_sys_write(AT91_RSTC_MR, AT91_RSTC_KEY | + (rstc) | + AT91_RSTC_URSTEN); +} + +#if defined(CONFIG_MCI_ATMEL) +static struct atmel_mci_platform_data __initdata usb_a9260_mci_data = { + .bus_width = 4, +}; + +static void usb_a9260_add_device_mci(void) +{ + at91_add_device_mci(0, &usb_a9260_mci_data); +} +#else +static void usb_a9260_add_device_mci(void) {} +#endif + +static struct at91_usbh_data ek_usbh_data = { + .ports = 2, +}; + +static int usb_a9260_devices_init(void) +{ + usb_a9260_add_device_nand(); + usb_a9260_phy_reset(); + at91_add_device_eth(&macb_pdata); + usb_a9260_add_device_mci(); + at91_add_device_usbh_ohci(&ek_usbh_data); + +#ifdef CONFIG_AT91_HAVE_SRAM_128M + at91_add_device_sdram(128 * 1024 * 1024); +#else + at91_add_device_sdram(64 * 1024 * 1024); +#endif + armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100)); + usb_a9260_set_board_type(); + + devfs_add_partition("nand0", 0x00000, SZ_128K, PARTITION_FIXED, "at91bootstrap_raw"); + dev_add_bb_dev("at91bootstrap_raw", "at91bootstrap"); + devfs_add_partition("nand0", SZ_128K, SZ_256K, PARTITION_FIXED, "self_raw"); + dev_add_bb_dev("self_raw", "self0"); + devfs_add_partition("nand0", SZ_256K + SZ_128K, SZ_128K, PARTITION_FIXED, "env_raw"); + dev_add_bb_dev("env_raw", "env0"); + devfs_add_partition("nand0", SZ_512K, SZ_128K, PARTITION_FIXED, "env_raw1"); + dev_add_bb_dev("env_raw1", "env1"); + + return 0; +} +device_initcall(usb_a9260_devices_init); + +static int usb_a9260_console_init(void) +{ + at91_register_uart(0, 0); + return 0; +} +console_initcall(usb_a9260_console_init); diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig index 6038aec3fe..2d04206cfa 100644 --- a/arch/arm/configs/at91sam9260ek_defconfig +++ b/arch/arm/configs/at91sam9260ek_defconfig @@ -1,3 +1,4 @@ +CONFIG_ARCH_AT91SAM9260=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_LONGHELP=y CONFIG_GLOB=y diff --git a/arch/arm/configs/usb_a9260_defconfig b/arch/arm/configs/usb_a9260_defconfig new file mode 100644 index 0000000000..adcb6036f5 --- /dev/null +++ b/arch/arm/configs/usb_a9260_defconfig @@ -0,0 +1,58 @@ +CONFIG_ARCH_AT91SAM9260=y +CONFIG_MACH_USB_A9260=y +CONFIG_AEABI=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MMU=y +CONFIG_KALLSYMS=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y diff --git a/arch/arm/configs/usb_a9263_128mib_defconfig b/arch/arm/configs/usb_a9263_128mib_defconfig new file mode 100644 index 0000000000..8d5342e38c --- /dev/null +++ b/arch/arm/configs/usb_a9263_128mib_defconfig @@ -0,0 +1,59 @@ +CONFIG_ARCH_AT91SAM9263=y +CONFIG_MACH_USB_A9263=y +CONFIG_AEABI=y +CONFIG_AT91_HAVE_SRAM_128M=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MMU=y +CONFIG_KALLSYMS=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y diff --git a/arch/arm/configs/usb_a9263_defconfig b/arch/arm/configs/usb_a9263_defconfig new file mode 100644 index 0000000000..9f53431b93 --- /dev/null +++ b/arch/arm/configs/usb_a9263_defconfig @@ -0,0 +1,58 @@ +CONFIG_ARCH_AT91SAM9263=y +CONFIG_MACH_USB_A9263=y +CONFIG_AEABI=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MMU=y +CONFIG_KALLSYMS=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y diff --git a/arch/arm/configs/usb_a9g20_128mib_defconfig b/arch/arm/configs/usb_a9g20_128mib_defconfig new file mode 100644 index 0000000000..3c0e6f72a3 --- /dev/null +++ b/arch/arm/configs/usb_a9g20_128mib_defconfig @@ -0,0 +1,59 @@ +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_USB_A9G20=y +CONFIG_AEABI=y +CONFIG_AT91_HAVE_SRAM_128M=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MMU=y +CONFIG_KALLSYMS=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y diff --git a/arch/arm/configs/usb_a9g20_defconfig b/arch/arm/configs/usb_a9g20_defconfig new file mode 100644 index 0000000000..2bcb8eb797 --- /dev/null +++ b/arch/arm/configs/usb_a9g20_defconfig @@ -0,0 +1,58 @@ +CONFIG_ARCH_AT91SAM9G20=y +CONFIG_MACH_USB_A9G20=y +CONFIG_AEABI=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_MMU=y +CONFIG_KALLSYMS=y +CONFIG_PROMPT="USB-9G20:" +CONFIG_LONGHELP=y +CONFIG_GLOB=y +CONFIG_PROMPT_HUSH_PS2="y" +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +CONFIG_PARTITION=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y +CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env" +CONFIG_CMD_EDIT=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENU_MANAGEMENT=y +CONFIG_CMD_PASSWD=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_SHA256SUM=y +CONFIG_CMD_MTEST=y +CONFIG_CMD_MTEST_ALTERNATIVE=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_BOOTM_ZLIB=y +CONFIG_CMD_BOOTM_BZLIB=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_RESET=y +CONFIG_CMD_GO=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_GPIO=y +CONFIG_NET=y +CONFIG_NET_DHCP=y +CONFIG_NET_NFS=y +CONFIG_NET_PING=y +CONFIG_NET_TFTP=y +CONFIG_NET_TFTP_PUSH=y +CONFIG_NET_NETCONSOLE=y +CONFIG_NET_RESOLV=y +CONFIG_DRIVER_NET_MACB=y +# CONFIG_SPI is not set +CONFIG_MTD=y +CONFIG_NAND=y +CONFIG_NAND_ATMEL=y +CONFIG_UBI=y diff --git a/arch/arm/cpu/cache-l2x0.c b/arch/arm/cpu/cache-l2x0.c index 1ea7bab362..b300e6ffb0 100644 --- a/arch/arm/cpu/cache-l2x0.c +++ b/arch/arm/cpu/cache-l2x0.c @@ -1,6 +1,6 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #define CACHE_LINE_SIZE 32 diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c index 3df0c0f647..d4a3b14819 100644 --- a/arch/arm/cpu/cpu.c +++ b/arch/arm/cpu/cpu.c @@ -90,19 +90,6 @@ void arch_shutdown(void) #endif } -LIST_HEAD(memory_list); - -void armlinux_add_dram(struct device_d *dev) -{ - struct arm_memory *mem = xzalloc(sizeof(*mem)); - - mem->dev = dev; - mem->start = dev->resource[0].start; - mem->size = dev->resource[0].size; - - list_add_tail(&mem->list, &memory_list); -} - /** * @page arm_boot_preparation Linux Preparation on ARM * diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index b6693495b6..4446813d0a 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -5,6 +5,7 @@ #include <sizes.h> #include <asm/memory.h> #include <asm/system.h> +#include <memory.h> static unsigned long *ttb; @@ -76,28 +77,28 @@ static u32 *arm_create_pte(unsigned long virt) return table; } +static u32 *find_pte(unsigned long adr) +{ + u32 *table; + + if ((ttb[adr >> 20] & PMD_TYPE_MASK) != PMD_TYPE_TABLE) + BUG(); + + /* find the coarse page table base address */ + table = (u32 *)(ttb[adr >> 20] & ~0x3ff); + + /* find second level descriptor */ + return &table[(adr >> PAGE_SHIFT) & 0xff]; +} + static void remap_range(void *_start, size_t size, uint32_t flags) { - u32 pteentry; - struct arm_memory *mem; unsigned long start = (unsigned long)_start; u32 *p; int numentries, i; - for_each_sdram_bank(mem) { - if (start >= mem->start && start < mem->start + mem->size) - goto found; - } - - BUG(); - return; - -found: - pteentry = (start - mem->start) >> PAGE_SHIFT; - numentries = size >> PAGE_SHIFT; - - p = mem->ptes + pteentry; + p = find_pte(start); for (i = 0; i < numentries; i++) { p[i] &= ~PTE_MASK; @@ -114,38 +115,39 @@ found: * remap the memory bank described by mem cachable and * bufferable */ -static int arm_mmu_remap_sdram(struct arm_memory *mem) +static int arm_mmu_remap_sdram(struct memory_bank *bank) { - unsigned long phys = (unsigned long)mem->start; + unsigned long phys = (unsigned long)bank->start; unsigned long ttb_start = phys >> 20; - unsigned long ttb_end = (phys + mem->size) >> 20; - unsigned long num_ptes = mem->size >> 10; + unsigned long ttb_end = (phys + bank->size) >> 20; + unsigned long num_ptes = bank->size >> 10; int i, pte; + u32 *ptes; debug("remapping SDRAM from 0x%08lx (size 0x%08lx)\n", - phys, mem->size); + phys, bank->size); /* * We replace each 1MiB section in this range with second level page * tables, therefore we must have 1Mib aligment here. */ - if ((phys & (SZ_1M - 1)) || (mem->size & (SZ_1M - 1))) + if ((phys & (SZ_1M - 1)) || (bank->size & (SZ_1M - 1))) return -EINVAL; - mem->ptes = memalign(0x400, num_ptes * sizeof(u32)); + ptes = memalign(0x400, num_ptes * sizeof(u32)); debug("ptes: 0x%p ttb_start: 0x%08lx ttb_end: 0x%08lx\n", - mem->ptes, ttb_start, ttb_end); + ptes, ttb_start, ttb_end); for (i = 0; i < num_ptes; i++) { - mem->ptes[i] = (phys + i * 4096) | PTE_TYPE_SMALL | + ptes[i] = (phys + i * 4096) | PTE_TYPE_SMALL | PTE_FLAGS_CACHED; } pte = 0; for (i = ttb_start; i < ttb_end; i++) { - ttb[i] = (unsigned long)(&mem->ptes[pte]) | PMD_TYPE_TABLE | + ttb[i] = (unsigned long)(&ptes[pte]) | PMD_TYPE_TABLE | (0 << 4); pte += 256; } @@ -209,7 +211,7 @@ static void vectors_init(void) */ static int mmu_init(void) { - struct arm_memory *mem; + struct memory_bank *bank; int i; ttb = memalign(0x10000, 0x4000); @@ -234,8 +236,8 @@ static int mmu_init(void) * This is to speed up the generation of 2nd level page tables * below */ - for_each_sdram_bank(mem) - create_section(mem->start, mem->start, mem->size >> 20, + for_each_memory_bank(bank) + create_section(bank->start, bank->start, bank->size >> 20, PMD_SECT_DEF_CACHED); asm volatile ( @@ -249,8 +251,8 @@ static int mmu_init(void) * Now that we have the MMU and caches on remap sdram again using * page tables */ - for_each_sdram_bank(mem) - arm_mmu_remap_sdram(mem); + for_each_memory_bank(bank) + arm_mmu_remap_sdram(bank); return 0; } diff --git a/arch/arm/include/asm/armlinux.h b/arch/arm/include/asm/armlinux.h index bb25f9a87d..ba3a424e26 100644 --- a/arch/arm/include/asm/armlinux.h +++ b/arch/arm/include/asm/armlinux.h @@ -31,7 +31,4 @@ struct image_data; void start_linux(void *adr, int swap, struct image_data *data); -struct device_d *arm_add_mem_device(const char* name, resource_size_t start, - resource_size_t size); - #endif /* __ARCH_ARMLINUX_H */ diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h index e8e82f6f8b..ab78be3848 100644 --- a/arch/arm/include/asm/io.h +++ b/arch/arm/include/asm/io.h @@ -1,53 +1,6 @@ -/* - * linux/include/asm-arm/io.h - * - * Copyright (C) 1996-2000 Russell King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Modifications: - * 16-Sep-1996 RMK Inlined the inx/outx functions & optimised for both - * constant addresses and variable addresses. - * 04-Dec-1997 RMK Moved a lot of this stuff to the new architecture - * specific IO header files. - * 27-Mar-1999 PJB Second parameter of memcpy_toio is const.. - * 04-Apr-1999 PJB Added check_signature. - * 12-Dec-1999 RMK More cleanups - * 18-Jun-2000 RMK Removed virt_to_* and friends definitions - */ - -/** - * @file - * @brief ARM IO access functions - */ - #ifndef __ASM_ARM_IO_H #define __ASM_ARM_IO_H -#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v)) -#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)) -#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) - -#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) -#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) -#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) - -#define writeb(v,a) __raw_writeb(v,a) -#define writew(v,a) __raw_writew(v,a) -#define writel(v,a) __raw_writel(v,a) - -#define readb(a) __raw_readb(a) -#define readw(a) __raw_readw(a) -#define readl(a) __raw_readl(a) - -/* for the ARM architecture the string functions are library based */ -extern void writesb(void __iomem*, const void*, int); -extern void writesw(void __iomem*, const void*, int); -extern void writesl(void __iomem*, const void*, int); -extern void readsb(const void __iomem*, void*, int); -extern void readsw(const void __iomem*, void*, int); -extern void readsl(const void __iomem*, void*, int); +#include <asm-generic/io.h> #endif /* __ASM_ARM_IO_H */ diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index 93c2fe6007..28afaa39e4 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -1,18 +1,12 @@ #ifndef __ASM_ARM_MEMORY_H #define __ASM_ARM_MEMORY_H -struct arm_memory { - struct list_head list; - struct device_d *dev; - u32 *ptes; - unsigned long start; - unsigned long size; -}; +#include <memory.h> -extern struct list_head memory_list; - -void armlinux_add_dram(struct device_d *dev); - -#define for_each_sdram_bank(mem) list_for_each_entry(mem, &memory_list, list) +static inline void arm_add_mem_device(const char* name, resource_size_t start, + resource_size_t size) +{ + barebox_add_memory_bank(name, start, size); +} #endif /* __ASM_ARM_MEMORY_H */ diff --git a/arch/arm/lib/arm.c b/arch/arm/lib/arm.c index 6549118b83..c85aae14a0 100644 --- a/arch/arm/lib/arm.c +++ b/arch/arm/lib/arm.c @@ -1,6 +1,6 @@ #include <common.h> #include <init.h> -#include <mem_malloc.h> +#include <memory.h> #include <asm/barebox-arm.h> #include <asm-generic/memory_layout.h> diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c index 5bdbb92bff..e3a74f4ffb 100644 --- a/arch/arm/lib/armlinux.c +++ b/arch/arm/lib/armlinux.c @@ -35,13 +35,13 @@ #include <malloc.h> #include <fcntl.h> #include <errno.h> +#include <memory.h> #include <asm/byteorder.h> #include <asm/setup.h> #include <asm/barebox-arm.h> #include <asm/armlinux.h> #include <asm/system.h> -#include <asm/memory.h> static struct tag *params; static int armlinux_architecture = 0; @@ -66,14 +66,14 @@ static void setup_start_tag(void) static void setup_memory_tags(void) { - struct arm_memory *mem; + struct memory_bank *bank; - for_each_sdram_bank(mem) { + for_each_memory_bank(bank) { params->hdr.tag = ATAG_MEM; params->hdr.size = tag_size(tag_mem32); - params->u.mem.start = mem->dev->resource[0].start; - params->u.mem.size = mem->dev->resource[0].size; + params->u.mem.start = bank->start; + params->u.mem.size = bank->size; params = tag_next(params); } @@ -186,7 +186,14 @@ void armlinux_set_bootparams(void *params) void armlinux_set_architecture(int architecture) { + char *arch_number = asprintf("%d", architecture); + armlinux_architecture = architecture; + + setenv("arch_number", arch_number); + export("arch_number"); + + kfree(arch_number); } void armlinux_set_revision(unsigned int rev) diff --git a/arch/arm/lib/bootz.c b/arch/arm/lib/bootz.c index 13bed25aeb..fc14487bfa 100644 --- a/arch/arm/lib/bootz.c +++ b/arch/arm/lib/bootz.c @@ -9,6 +9,7 @@ #include <asm/armlinux.h> #include <asm/system.h> #include <asm-generic/memory_layout.h> +#include <memory.h> struct zimage_header { u32 unused[9]; @@ -26,7 +27,7 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[]) void *zimage; u32 end; int usemap = 0; - struct arm_memory *mem = list_first_entry(&memory_list, struct arm_memory, list); + struct memory_bank *bank = list_first_entry(&memory_banks, struct memory_bank, list); if (argc != 2) { barebox_cmd_usage(cmdtp); @@ -44,8 +45,8 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[]) * the first 128MB of SDRAM. */ zimage = memmap(fd, PROT_READ); - if (zimage && (unsigned long)zimage >= mem->start && - (unsigned long)zimage < mem->start + SZ_128M) { + if (zimage && (unsigned long)zimage >= bank->start && + (unsigned long)zimage < bank->start + SZ_128M) { usemap = 1; header = zimage; } @@ -78,11 +79,11 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[]) end = swab32(end); if (!usemap) { - if (mem->size <= SZ_128M) { + if (bank->size <= SZ_128M) { zimage = xmalloc(end); } else { - zimage = (void *)mem->start + SZ_8M; - if (mem->start + SZ_8M + end >= MALLOC_BASE) { + zimage = (void *)bank->start + SZ_8M; + if (bank->start + SZ_8M + end >= MALLOC_BASE) { printf("won't overwrite malloc space with image\n"); goto err_out1; } diff --git a/arch/arm/mach-at91/Kconfig b/arch/arm/mach-at91/Kconfig index ee46002819..2ac23b5f19 100644 --- a/arch/arm/mach-at91/Kconfig +++ b/arch/arm/mach-at91/Kconfig @@ -14,6 +14,9 @@ config BOARDINFO default "Atmel at91sam9g20-ek" if MACH_AT91SAM9G20EK default "Atmel at91sam9m10g45-ek" if MACH_AT91SAM9M10G45EK default "Bucyrus MMC-CPU" if MACH_MMCCPU + default "Calao USB-A9260" if MACH_USB_A9260 + default "Calao USB-A9263" if MACH_USB_A9263 + default "Calao USB-A9G20" if MACH_USB_A9G20 default "Ronetix PM9261" if MACH_PM9261 default "Ronetix PM9263" if MACH_PM9263 default "Ronetix PM9G45" if MACH_PM9G45 @@ -96,6 +99,12 @@ config MACH_AT91SAM9260EK help Say y here if you are using Atmel's AT91SAM9260-EK Evaluation board +config MACH_USB_A9260 + bool "CALAO USB-A9260" + help + Select this if you are using a Calao Systems USB-A9260. + <http://www.calao-systems.com> + endchoice endif @@ -160,6 +169,12 @@ config MACH_AT91SAM9G20EK Select this if you are using Atmel's AT91SAM9G20-EK Evaluation Kit that embeds only one SD/MMC slot. +config MACH_USB_A9G20 + bool "CALAO USB-A9G20" + help + Select this if you are using a Calao Systems USB-A9G20. + <http://www.calao-systems.com> + endchoice endif @@ -189,6 +204,12 @@ config MACH_PM9263 help Say y here if you are using the Ronetix PM9263 Board +config MACH_USB_A9263 + bool "CALAO USB-A9263" + help + Select this if you are using a Calao Systems USB-A9263. + <http://www.calao-systems.com> + endchoice endif @@ -234,6 +255,12 @@ config AT91_HAVE_2MMC with 2 SD/MMC Slots. This is the case for AT91SAM9G20-EK rev. C and onwards. +config AT91_HAVE_SRAM_128M + bool "Have 128 of ram" + depends on MACH_USB_A9G20 || MACH_USB_A9263 + help + Select this if you board have 128 MiB of Ram (as USB_A9G20 C11) + choice prompt "LCD type" depends on MACH_AT91SAM9M10G45EK diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c index 453c10a5de..bd7d3f05e4 100644 --- a/arch/arm/mach-at91/at91rm9200_devices.c +++ b/arch/arm/mach-at91/at91rm9200_devices.c @@ -26,6 +26,24 @@ void at91_add_device_sdram(u32 size) } /* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + if (!data) + return; + + add_generic_device("at91_ohci", -1, NULL, AT91RM9200_UHP_BASE, 1024 * 1024, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + + +/* -------------------------------------------------------------------- * Ethernet * -------------------------------------------------------------------- */ diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c index 92b9e663a4..b6e7f552e1 100644 --- a/arch/arm/mach-at91/at91rm9200_time.c +++ b/arch/arm/mach-at91/at91rm9200_time.c @@ -37,7 +37,7 @@ #include <mach/at91_st.h> #include <mach/at91_pmc.h> #include <mach/io.h> -#include <asm/io.h> +#include <io.h> /* * The ST_CRTR is updated asynchronously to the master clock ... but diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c index 44d3f1e989..9d1acda7fe 100644 --- a/arch/arm/mach-at91/at91sam9260_devices.c +++ b/arch/arm/mach-at91/at91sam9260_devices.c @@ -26,6 +26,19 @@ void at91_add_device_sdram(u32 size) arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); } +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + if (!data) + return; + + add_generic_device("at91_ohci", -1, NULL, AT91SAM9260_UHP_BASE, 1024 * 1024, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + #if defined(CONFIG_DRIVER_NET_MACB) void at91_add_device_eth(struct at91_ether_platform_data *data) { @@ -63,6 +76,19 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) +static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, + .size = SZ_256M, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC, + .size = 512, + .flags = IORESOURCE_MEM, + } +}; + void at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa; @@ -85,8 +111,8 @@ void at91_add_device_nand(struct atmel_nand_data *data) if (data->det_pin) at91_set_gpio_input(data->det_pin, 1); - add_generic_device("atmel_nand", 0, NULL, AT91_CHIPSELECT_3, 0x10, - IORESOURCE_MEM, data); + add_generic_device_res("atmel_nand", 0, nand_resources, + ARRAY_SIZE(nand_resources), data); } #else void at91_add_device_nand(struct atmel_nand_data *data) {} diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c index c6a3dba901..3f69b1886c 100644 --- a/arch/arm/mach-at91/at91sam9261_devices.c +++ b/arch/arm/mach-at91/at91sam9261_devices.c @@ -26,6 +26,23 @@ void at91_add_device_sdram(u32 size) arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); } +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + if (!data) + return; + + add_generic_device("at91_ohci", -1, NULL, AT91SAM9261_UHP_BASE, 1024 * 1024, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + #if defined(CONFIG_NAND_ATMEL) void at91_add_device_nand(struct atmel_nand_data *data) { diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c index c7ae45ad30..994a975cf9 100644 --- a/arch/arm/mach-at91/at91sam9263_devices.c +++ b/arch/arm/mach-at91/at91sam9263_devices.c @@ -26,6 +26,31 @@ void at91_add_device_sdram(u32 size) arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size); } +/* -------------------------------------------------------------------- + * USB Host + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + add_generic_device("at91_ohci", -1, NULL, AT91SAM9263_UHP_BASE, 1024 * 1024, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + #if defined(CONFIG_DRIVER_NET_MACB) void at91_add_device_eth(struct at91_ether_platform_data *data) { @@ -62,6 +87,19 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) +static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, + .size = SZ_256M, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC0, + .size = 512, + .flags = IORESOURCE_MEM, + } +}; + void at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa; @@ -84,8 +122,8 @@ void at91_add_device_nand(struct atmel_nand_data *data) if (data->det_pin) at91_set_gpio_input(data->det_pin, 1); - add_generic_device("atmel_nand", -1, NULL, AT91_CHIPSELECT_3, 0x10, - IORESOURCE_MEM, data); + add_generic_device_res("atmel_nand", -1, nand_resources, + ARRAY_SIZE(nand_resources), data); } #else void at91_add_device_nand(struct atmel_nand_data *data) {} diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c index 7a1d6dd2f4..7ca2ef4f48 100644 --- a/arch/arm/mach-at91/at91sam926x_time.c +++ b/arch/arm/mach-at91/at91sam926x_time.c @@ -37,7 +37,7 @@ #include <mach/at91_pmc.h> #include <mach/at91_rstc.h> #include <mach/io.h> -#include <asm/io.h> +#include <io.h> uint64_t at91sam9_clocksource_read(void) { diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c index 022f3e1875..1d47dcfa10 100644 --- a/arch/arm/mach-at91/at91sam9g45_devices.c +++ b/arch/arm/mach-at91/at91sam9g45_devices.c @@ -26,6 +26,31 @@ void at91_add_device_sdram(u32 size) arm_add_mem_device("ram0", AT91_CHIPSELECT_6, size); } +/* -------------------------------------------------------------------- + * USB Host (OHCI) + * -------------------------------------------------------------------- */ + +#if defined(CONFIG_USB_OHCI) +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) +{ + int i; + + if (!data) + return; + + /* Enable VBus control for UHP ports */ + for (i = 0; i < data->ports; i++) { + if (data->vbus_pin[i]) + at91_set_gpio_output(data->vbus_pin[i], 0); + } + + add_generic_device("at91_ohci", -1, NULL, AT91SAM9G45_OHCI_BASE, 1024 * 1024, + IORESOURCE_MEM, data); +} +#else +void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {} +#endif + #if defined(CONFIG_DRIVER_NET_MACB) void at91_add_device_eth(struct at91_ether_platform_data *data) { @@ -63,6 +88,19 @@ void at91_add_device_eth(struct at91_ether_platform_data *data) {} #endif #if defined(CONFIG_NAND_ATMEL) +static struct resource nand_resources[] = { + [0] = { + .start = AT91_CHIPSELECT_3, + .size = SZ_256M, + .flags = IORESOURCE_MEM, + }, + [1] = { + .start = AT91_BASE_SYS + AT91_ECC, + .size = 512, + .flags = IORESOURCE_MEM, + } +}; + void at91_add_device_nand(struct atmel_nand_data *data) { unsigned long csa; @@ -70,9 +108,6 @@ void at91_add_device_nand(struct atmel_nand_data *data) if (!data) return; - data->ecc_base = (void __iomem *)(AT91_BASE_SYS + AT91_ECC); - data->ecc_mode = NAND_ECC_HW; - csa = at91_sys_read(AT91_MATRIX_EBICSA); at91_sys_write(AT91_MATRIX_EBICSA, csa | AT91_MATRIX_EBI_CS3A_SMC_SMARTMEDIA); @@ -88,8 +123,8 @@ void at91_add_device_nand(struct atmel_nand_data *data) if (data->det_pin) at91_set_gpio_input(data->det_pin, 1); - add_generic_device("atmel_nand", -1, NULL, AT91_CHIPSELECT_3, 0x10, - IORESOURCE_MEM, data); + add_generic_device_res("atmel_nand", -1, nand_resources, + ARRAY_SIZE(nand_resources), data); } #else void at91_add_device_nand(struct atmel_nand_data *data) {} @@ -256,3 +291,44 @@ void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) {} #endif +#if defined(CONFIG_DRIVER_SPI_ATMEL) +/* SPI */ +void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata) +{ + int i; + int cs_pin; + resource_size_t start; + + for (i = 0; i < pdata->num_chipselect; i++) { + cs_pin = pdata->chipselect[i]; + + /* enable chip-select pin */ + if (cs_pin > 0) + at91_set_gpio_output(cs_pin, 1); + } + + /* Configure SPI bus(es) */ + if (spi_id == 0) { + start = AT91SAM9G45_BASE_SPI0; + at91_set_A_periph(AT91_PIN_PB0, 0); /* SPI0_MISO */ + at91_set_A_periph(AT91_PIN_PB1, 0); /* SPI0_MOSI */ + at91_set_A_periph(AT91_PIN_PB2, 0); /* SPI0_SPCK */ + + add_generic_device("atmel_spi", spi_id, NULL, start, SZ_16K, + IORESOURCE_MEM, pdata); + } + + else if (spi_id == 1) { + start = AT91SAM9G45_BASE_SPI1; + at91_set_A_periph(AT91_PIN_PB14, 0); /* SPI1_MISO */ + at91_set_A_periph(AT91_PIN_PB15, 0); /* SPI1_MOSI */ + at91_set_A_periph(AT91_PIN_PB16, 0); /* SPI1_SPCK */ + + add_generic_device("atmel_spi", spi_id, NULL, start, SZ_16K, + IORESOURCE_MEM, pdata); + } +} + +#else +void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata) {} +#endif diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 528994f630..0406382daf 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -530,11 +530,12 @@ static void at91_upll_usbfs_clock_init(unsigned long main_clock) /* Now set uhpck values */ uhpck.parent = &utmi_clk; uhpck.pmc_mask = AT91SAM926x_PMC_UHP; - uhpck.rate_hz = utmi_clk.parent->rate_hz; + uhpck.rate_hz = utmi_clk.rate_hz; uhpck.rate_hz /= 1 + ((at91_sys_read(AT91_PMC_USB) & AT91_PMC_OHCIUSBDIV) >> 8); } static int pll_overclock = 0; +static u32 cpu_freq = 0; int at91_clock_init(unsigned long main_clock) { @@ -622,6 +623,8 @@ int at91_clock_init(unsigned long main_clock) mck.rate_hz = freq / (1 << ((mckr & AT91_PMC_MDIV) >> 8)); /* mdiv */ } + cpu_freq = freq; + /* Register the PMC's standard clocks */ for (i = 0; i < ARRAY_SIZE(standard_pmc_clocks); i++) at91_clk_add(standard_pmc_clocks[i]); @@ -649,8 +652,8 @@ static int at91_clock_display(void) if (pll_overclock) pr_info("Clocks: PLLA overclocked, %ld MHz\n", plla.rate_hz / 1000000); - printf("Clocks: CPU %lu MHz, master %u MHz, main %u.%03u MHz\n", - mck.parent->rate_hz / 1000000, (unsigned) mck.rate_hz / 1000000, + printf("Clocks: CPU %u MHz, master %u MHz, main %u.%03u MHz\n", + cpu_freq / 1000000, (unsigned) mck.rate_hz / 1000000, (unsigned) main_clk.rate_hz / 1000000, ((unsigned) main_clk.rate_hz % 1000000) / 1000); diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c index b257128da6..c34df0520e 100644 --- a/arch/arm/mach-at91/gpio.c +++ b/arch/arm/mach-at91/gpio.c @@ -24,7 +24,7 @@ #include <common.h> #include <linux/clk.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/gpio.h> #include <gpio.h> diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h index 89caebb9c2..546fe90e82 100644 --- a/arch/arm/mach-at91/include/mach/board.h +++ b/arch/arm/mach-at91/include/mach/board.h @@ -22,13 +22,20 @@ #define __ASM_ARCH_BOARD_H #include <net.h> +#include <spi/spi.h> #include <linux/mtd/mtd.h> + /* USB Host */ +struct at91_usbh_data { + u8 ports; /* number of ports on root hub */ + u8 vbus_pin[2]; /* port power-control pin */ +}; +extern void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data); + void atmel_nand_load_image(void *dest, int size, int pagesize, int blocksize); /* NAND / SmartMedia */ struct atmel_nand_data { - void __iomem *ecc_base; u8 enable_pin; /* chip enable */ u8 det_pin; /* card detect */ u8 rdy_pin; /* ready/busy */ @@ -75,4 +82,12 @@ struct atmel_mci_platform_data { }; void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data); + +/* SPI Master platform data */ +struct at91_spi_platform_data { + int *chipselect; /* array of gpio_pins */ + int num_chipselect; /* chipselect array entry count */ +}; + +void at91_add_device_spi(int spi_id, struct at91_spi_platform_data *pdata); #endif diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h index 7e1a9a8acd..f3239f5f42 100644 --- a/arch/arm/mach-at91/include/mach/gpio.h +++ b/arch/arm/mach-at91/include/mach/gpio.h @@ -13,7 +13,7 @@ #ifndef __ASM_ARCH_AT91_GPIO_H #define __ASM_ARCH_AT91_GPIO_H -#include <asm/io.h> +#include <io.h> #include <asm-generic/errno.h> #include <mach/at91_pio.h> #include <mach/hardware.h> diff --git a/arch/arm/mach-at91/include/mach/io.h b/arch/arm/mach-at91/include/mach/io.h index f09b2df0e3..7b0cd9dcbb 100644 --- a/arch/arm/mach-at91/include/mach/io.h +++ b/arch/arm/mach-at91/include/mach/io.h @@ -21,7 +21,7 @@ #ifndef __ASM_ARCH_IO_H #define __ASM_ARCH_IO_H -#include <asm/io.h> +#include <io.h> static inline unsigned int at91_sys_read(unsigned int reg_offset) { diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c index 3e7de2fc58..c397fe46b5 100644 --- a/arch/arm/mach-at91/sam9_smc.c +++ b/arch/arm/mach-at91/sam9_smc.c @@ -9,7 +9,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #include <mach/io.h> diff --git a/arch/arm/mach-ep93xx/clocksource.c b/arch/arm/mach-ep93xx/clocksource.c index b500948968..ce8a29fee7 100644 --- a/arch/arm/mach-ep93xx/clocksource.c +++ b/arch/arm/mach-ep93xx/clocksource.c @@ -23,7 +23,7 @@ #include <common.h> #include <init.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <mach/ep93xx-regs.h> #define TIMER_CLKSEL (1 << 3) diff --git a/arch/arm/mach-ep93xx/gpio.c b/arch/arm/mach-ep93xx/gpio.c index 5d57434031..f4def289e4 100644 --- a/arch/arm/mach-ep93xx/gpio.c +++ b/arch/arm/mach-ep93xx/gpio.c @@ -20,7 +20,7 @@ #include <common.h> #include <errno.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/ep93xx-regs.h> #define EP93XX_GPIO_NUM_PORTS 8 diff --git a/arch/arm/mach-ep93xx/led.c b/arch/arm/mach-ep93xx/led.c index 6d6b90235f..91f33d1aea 100644 --- a/arch/arm/mach-ep93xx/led.c +++ b/arch/arm/mach-ep93xx/led.c @@ -21,7 +21,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/ep93xx-regs.h> #define GREEN_LED_POS 0x01 diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 8dc6a24fb5..8d5bd744e8 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -497,6 +497,12 @@ config IMX_IIM Device driver for the IC Identification Module (IIM) fusebox. Use the regular md/mw commands to program and read the fusebox. + Fuses are grouped in "rows", 8 bits per row. When using md/mw commands, + employ the -b switch and consider the region to be specifying the "Fuse + Row Index" rather than "Fuse Row Offset" (which is FRI * 4). You should + consult the documentation for your chip for more elaborate description, + including the eFuse map, e.g. see AN3682 for i.MX25. + config IMX_IIM_FUSE_BLOW bool "IIM fuses blow support" depends on IMX_IIM @@ -507,6 +513,10 @@ config IMX_IIM_FUSE_BLOW Warning: blown fuses can not be unblown. Using this option may damage your CPU, or make it unbootalbe. Use with care. + Before being actually able to blow the fuses, you need to explicitely + enable it: + imx_iim0.permanent_write_enable=1 + endmenu endif diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index 8482b60f40..f13d956bf1 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -19,7 +19,7 @@ #include <environment.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #if defined(CONFIG_ARCH_IMX25) || defined(CONFIG_ARCH_IMX35) diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 5397da03d7..4f5895c2a5 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -35,7 +35,7 @@ #include <notifier.h> #include <mach/imx-regs.h> #include <mach/clock.h> -#include <asm/io.h> +#include <io.h> #define GPT(x) __REG(IMX_TIM1_BASE + (x)) #define timer_base (IMX_TIM1_BASE) diff --git a/arch/arm/mach-imx/gpio.c b/arch/arm/mach-imx/gpio.c index 0a3e0461eb..fdee20b865 100644 --- a/arch/arm/mach-imx/gpio.c +++ b/arch/arm/mach-imx/gpio.c @@ -25,7 +25,7 @@ #include <common.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/gpio.h> diff --git a/arch/arm/mach-imx/iim.c b/arch/arm/mach-imx/iim.c index ca89710329..f2ace8aa0f 100644 --- a/arch/arm/mach-imx/iim.c +++ b/arch/arm/mach-imx/iim.c @@ -25,7 +25,7 @@ #include <fcntl.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <mach/iim.h> @@ -51,8 +51,8 @@ static int do_fuse_sense(void __iomem *reg_base, unsigned int bank, return -EINVAL; } - if (row > 0x3ff) { - printf("%s: invalid row offset\n", __func__); + if (row > 255) { + printf("%s: invalid row index\n", __func__); return -EINVAL; } @@ -61,8 +61,8 @@ static int do_fuse_sense(void __iomem *reg_base, unsigned int bank, writeb(0xfe, reg_base + IIM_ERR); /* upper and lower address halves */ - writeb((bank << 3) | (row >> 7), reg_base + IIM_UA); - writeb((row << 1) & 0xf8, reg_base + IIM_LA); + writeb((bank << 3) | (row >> 5), reg_base + IIM_UA); + writeb((row << 3) & 0xf8, reg_base + IIM_LA); /* start fuse sensing */ writeb(0x08, reg_base + IIM_FCTL); @@ -100,7 +100,7 @@ static ssize_t imx_iim_cdev_read(struct cdev *cdev, void *buf, size_t count, int row_val; row_val = do_fuse_sense(priv->base, - priv->bank, (offset + i) * 4); + priv->bank, offset + i); if (row_val < 0) return row_val; ((u8 *)buf)[i] = (u8)row_val; @@ -125,8 +125,8 @@ static int do_fuse_blow(void __iomem *reg_base, unsigned int bank, return -EINVAL; } - if (row > 0x3ff) { - printf("%s: invalid row offset\n", __func__); + if (row > 255) { + printf("%s: invalid row index\n", __func__); return -EINVAL; } @@ -138,14 +138,14 @@ static int do_fuse_blow(void __iomem *reg_base, unsigned int bank, writeb(0xaa, reg_base + IIM_PREG_P); /* upper half address register */ - writeb((bank << 3) | (row >> 7), reg_base + IIM_UA); + writeb((bank << 3) | (row >> 5), reg_base + IIM_UA); for (bit = 0; bit < 8; bit++) { if (((value >> bit) & 1) == 0) continue; /* lower half address register */ - writeb(((row << 1) | bit), reg_base + IIM_LA); + writeb(((row << 3) | bit), reg_base + IIM_LA); /* start fuse programing */ writeb(0x71, reg_base + IIM_FCTL); @@ -193,7 +193,7 @@ static ssize_t imx_iim_cdev_write(struct cdev *cdev, const void *buf, size_t cou int ret; ret = do_fuse_blow(priv->base, priv->bank, - (offset + i) * 4, ((u8 *)buf)[i]); + offset + i, ((u8 *)buf)[i]); if (ret < 0) return ret; } diff --git a/arch/arm/mach-imx/imx25.c b/arch/arm/mach-imx/imx25.c index 75ec8c7f45..19a2909e18 100644 --- a/arch/arm/mach-imx/imx25.c +++ b/arch/arm/mach-imx/imx25.c @@ -19,7 +19,7 @@ #include <init.h> #include <mach/imx-regs.h> #include <mach/iim.h> -#include <asm/io.h> +#include <io.h> #include <sizes.h> #include "gpio.h" diff --git a/arch/arm/mach-imx/imx35.c b/arch/arm/mach-imx/imx35.c index c846260682..381a564580 100644 --- a/arch/arm/mach-imx/imx35.c +++ b/arch/arm/mach-imx/imx35.c @@ -18,7 +18,7 @@ #include <common.h> #include <sizes.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/iim.h> #include <mach/generic.h> diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index a42ff41400..2c1efed150 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -19,7 +19,7 @@ #include <common.h> #include <sizes.h> #include <environment.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx51-regs.h> #include "gpio.h" diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 7a822c2c85..8fb64bb96a 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -17,7 +17,7 @@ #include <init.h> #include <common.h> -#include <asm/io.h> +#include <io.h> #include <sizes.h> #include <mach/imx53-regs.h> diff --git a/arch/arm/mach-imx/include/mach/clock-imx51_53.h b/arch/arm/mach-imx/include/mach/clock-imx51_53.h index 34ca1bb94f..1e90d21d4a 100644 --- a/arch/arm/mach-imx/include/mach/clock-imx51_53.h +++ b/arch/arm/mach-imx/include/mach/clock-imx51_53.h @@ -606,6 +606,10 @@ #define MX5_PLL_DP_MFD_665 (96 - 1) #define MX5_PLL_DP_MFN_665 89 +#define MX5_PLL_DP_OP_600 ((6 << 4) + ((1 - 1) << 0)) +#define MX5_PLL_DP_MFD_600 (4 - 1) +#define MX5_PLL_DP_MFN_600 1 + #define MX5_PLL_DP_OP_532 ((5 << 4) + ((1 - 1) << 0)) #define MX5_PLL_DP_MFD_532 (24 - 1) #define MX5_PLL_DP_MFN_532 13 diff --git a/arch/arm/mach-imx/include/mach/clock.h b/arch/arm/mach-imx/include/mach/clock.h index 5b590a251e..10821782fe 100644 --- a/arch/arm/mach-imx/include/mach/clock.h +++ b/arch/arm/mach-imx/include/mach/clock.h @@ -29,6 +29,7 @@ ulong imx_get_uartclk(void); ulong imx_get_lcdclk(void); ulong imx_get_i2cclk(void); ulong imx_get_mmcclk(void); +ulong imx_get_cspiclk(void); int imx_clko_set_div(int div); void imx_clko_set_src(int src); diff --git a/arch/arm/mach-imx/include/mach/devices-imx25.h b/arch/arm/mach-imx/include/mach/devices-imx25.h index 87f5ba0e5e..eff59773f7 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx25.h +++ b/arch/arm/mach-imx/include/mach/devices-imx25.h @@ -6,6 +6,11 @@ static inline struct device_d *imx25_add_i2c0(struct i2c_platform_data *pdata) return imx_add_i2c((void *)IMX_I2C1_BASE, 0, pdata); } +static inline struct device_d *imx25_add_spi0(struct spi_imx_master *pdata) +{ + return imx_add_spi((void *)IMX_CSPI1_BASE, 0, pdata); +} + static inline struct device_d *imx25_add_uart0(void) { return imx_add_uart((void *)IMX_UART1_BASE, 0); diff --git a/arch/arm/mach-imx/include/mach/devices-imx51.h b/arch/arm/mach-imx/include/mach/devices-imx51.h index a5deb5c863..54ea647461 100644 --- a/arch/arm/mach-imx/include/mach/devices-imx51.h +++ b/arch/arm/mach-imx/include/mach/devices-imx51.h @@ -1,5 +1,6 @@ #include <mach/devices.h> +#include <sizes.h> static inline struct device_d *imx51_add_spi0(struct spi_imx_master *pdata) { @@ -53,6 +54,28 @@ static inline struct device_d *imx51_add_mmc1(void *pdata) static inline struct device_d *imx51_add_nand(struct imx_nand_platform_data *pdata) { - return imx_add_nand((void *)MX51_NFC_AXI_BASE_ADDR, pdata); + struct resource res[] = { + { + .start = MX51_NFC_BASE_ADDR, + .size = SZ_4K, + .flags = IORESOURCE_MEM, + }, { + .start = MX51_NFC_AXI_BASE_ADDR, + .size = SZ_4K, + .flags = IORESOURCE_MEM, + }, + }; + struct device_d *dev = xzalloc(sizeof(*dev)); + + dev->resource = xzalloc(sizeof(struct resource) * ARRAY_SIZE(res)); + memcpy(dev->resource, res, sizeof(struct resource) * ARRAY_SIZE(res)); + dev->num_resources = ARRAY_SIZE(res); + strcpy(dev->name, "imx_nand"); + dev->id = -1; + dev->platform_data = pdata; + + register_device(dev); + + return dev; } diff --git a/arch/arm/mach-imx/include/mach/imx25-regs.h b/arch/arm/mach-imx/include/mach/imx25-regs.h index 78ec0cdbf1..73307c452e 100644 --- a/arch/arm/mach-imx/include/mach/imx25-regs.h +++ b/arch/arm/mach-imx/include/mach/imx25-regs.h @@ -47,6 +47,7 @@ #define IMX_NFC_BASE 0xBB000000 #define IMX_FEC_BASE 0x50038000 #define IMX_I2C1_BASE 0x43F80000 +#define IMX_CSPI1_BASE 0x43FA4000 /* * Clock Controller Module (CCM) diff --git a/arch/arm/mach-imx/include/mach/imx51-regs.h b/arch/arm/mach-imx/include/mach/imx51-regs.h index 2e6cacb5bf..c6d14cdc6b 100644 --- a/arch/arm/mach-imx/include/mach/imx51-regs.h +++ b/arch/arm/mach-imx/include/mach/imx51-regs.h @@ -12,6 +12,16 @@ #define GPT_TCN 0x24 #define GPT_TSTAT 0x08 +/* WEIM registers */ +#define WEIM_CSxGCR1(n) (((n) * 0x18) + 0x00) +#define WEIM_CSxGCR2(n) (((n) * 0x18) + 0x04) +#define WEIM_CSxRCR1(n) (((n) * 0x18) + 0x08) +#define WEIM_CSxRCR2(n) (((n) * 0x18) + 0x0c) +#define WEIM_CSxWCR1(n) (((n) * 0x18) + 0x10) +#define WEIM_WCR 0x90 +#define WEIM_WIAR 0x94 +#define WEIM_EAR 0x98 + /* Part 2: Bitfields */ #define TCTL_SWR (1<<15) /* Software reset */ #define TCTL_FRR (1<<9) /* Freerun / restart */ @@ -134,4 +144,3 @@ #define MX51_CHIP_REV_3_2 0x32 #endif /* __MACH_IMX51_REGS_H */ - diff --git a/arch/arm/mach-imx/internal-nand-boot.c b/arch/arm/mach-imx/internal-nand-boot.c index 0d71b99f92..c55a0e7682 100644 --- a/arch/arm/mach-imx/internal-nand-boot.c +++ b/arch/arm/mach-imx/internal-nand-boot.c @@ -17,7 +17,7 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <linux/mtd/nand.h> #include <mach/imx-nand.h> #include <mach/generic.h> diff --git a/arch/arm/mach-imx/iomux-v2.c b/arch/arm/mach-imx/iomux-v2.c index abb2ebe195..1b49ccb328 100644 --- a/arch/arm/mach-imx/iomux-v2.c +++ b/arch/arm/mach-imx/iomux-v2.c @@ -18,7 +18,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/iomux-mx31.h> diff --git a/arch/arm/mach-imx/iomux-v3.c b/arch/arm/mach-imx/iomux-v3.c index a74f942509..bb2307a370 100644 --- a/arch/arm/mach-imx/iomux-v3.c +++ b/arch/arm/mach-imx/iomux-v3.c @@ -19,7 +19,7 @@ * MA 02110-1301, USA. */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/iomux-v3.h> #include <mach/imx-regs.h> diff --git a/arch/arm/mach-imx/nand.c b/arch/arm/mach-imx/nand.c index c52b8b06c2..fcbb85ef68 100644 --- a/arch/arm/mach-imx/nand.c +++ b/arch/arm/mach-imx/nand.c @@ -17,7 +17,7 @@ #include <common.h> #include <mach/imx-regs.h> -#include <asm/io.h> +#include <io.h> #if defined(CONFIG_ARCH_IMX35) || defined (CONFIG_ARCH_IMX25) diff --git a/arch/arm/mach-imx/speed-imx25.c b/arch/arm/mach-imx/speed-imx25.c index 68b50e943b..f6dcacb71b 100644 --- a/arch/arm/mach-imx/speed-imx25.c +++ b/arch/arm/mach-imx/speed-imx25.c @@ -1,6 +1,6 @@ #include <common.h> #include <mach/imx-regs.h> -#include <asm/io.h> +#include <io.h> #include <mach/clock.h> #include <init.h> @@ -87,6 +87,11 @@ unsigned long imx_get_mmcclk(void) return imx_get_perclk(3); } +unsigned long imx_get_cspiclk(void) +{ + return imx_get_ipgclk(); +} + void imx_dump_clocks(void) { printf("mpll: %10ld Hz\n", imx_get_mpllclk()); diff --git a/arch/arm/mach-imx/speed-imx31.c b/arch/arm/mach-imx/speed-imx31.c index 32a517d724..d3f168c4ae 100644 --- a/arch/arm/mach-imx/speed-imx31.c +++ b/arch/arm/mach-imx/speed-imx31.c @@ -16,7 +16,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/clock.h> #include <init.h> diff --git a/arch/arm/mach-imx/speed-imx35.c b/arch/arm/mach-imx/speed-imx35.c index b2a339c6c2..1e1c39ff82 100644 --- a/arch/arm/mach-imx/speed-imx35.c +++ b/arch/arm/mach-imx/speed-imx35.c @@ -17,7 +17,7 @@ #include <common.h> #include <mach/imx-regs.h> -#include <asm/io.h> +#include <io.h> #include <mach/clock.h> #include <mach/generic.h> #include <init.h> diff --git a/arch/arm/mach-imx/speed-imx51.c b/arch/arm/mach-imx/speed-imx51.c index f1fb74c474..643ad8f39b 100644 --- a/arch/arm/mach-imx/speed-imx51.c +++ b/arch/arm/mach-imx/speed-imx51.c @@ -1,5 +1,5 @@ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <asm-generic/div64.h> #include <mach/imx51-regs.h> #include <mach/clock-imx51_53.h> @@ -156,6 +156,11 @@ unsigned long imx_get_fecclk(void) return imx_get_ipgclk(); } +unsigned long imx_get_i2cclk(void) +{ + return imx_get_ipgclk(); +} + unsigned long imx_get_mmcclk(void) { u32 reg, prediv, podf, rate; diff --git a/arch/arm/mach-imx/speed-imx53.c b/arch/arm/mach-imx/speed-imx53.c index 7b099f5fa6..0d6ac24944 100644 --- a/arch/arm/mach-imx/speed-imx53.c +++ b/arch/arm/mach-imx/speed-imx53.c @@ -1,5 +1,5 @@ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <asm-generic/div64.h> #include <mach/imx-regs.h> #include "mach/clock-imx51_53.h" diff --git a/arch/arm/mach-mxs/clocksource-imx23.c b/arch/arm/mach-mxs/clocksource-imx23.c index f7c94c1d75..66e534bda3 100644 --- a/arch/arm/mach-mxs/clocksource-imx23.c +++ b/arch/arm/mach-mxs/clocksource-imx23.c @@ -23,7 +23,7 @@ #include <notifier.h> #include <mach/imx-regs.h> #include <mach/clock.h> -#include <asm/io.h> +#include <io.h> #define TIMROTCTRL 0x00 #define TIMCTRL1 0x40 diff --git a/arch/arm/mach-mxs/clocksource-imx28.c b/arch/arm/mach-mxs/clocksource-imx28.c index 15ae951004..328ca5d023 100644 --- a/arch/arm/mach-mxs/clocksource-imx28.c +++ b/arch/arm/mach-mxs/clocksource-imx28.c @@ -18,7 +18,7 @@ #include <notifier.h> #include <mach/imx-regs.h> #include <mach/clock.h> -#include <asm/io.h> +#include <io.h> #define TIMROTCTRL 0x00 # define TIMROTCTRL_SFTRST diff --git a/arch/arm/mach-mxs/imx_lcd_clk.c b/arch/arm/mach-mxs/imx_lcd_clk.c index 65bfc6ee3d..455dfcb9c7 100644 --- a/arch/arm/mach-mxs/imx_lcd_clk.c +++ b/arch/arm/mach-mxs/imx_lcd_clk.c @@ -16,7 +16,7 @@ #include <init.h> #include <mach/imx-regs.h> #include <mach/clock.h> -#include <asm/io.h> +#include <io.h> #ifdef CONFIG_ARCH_IMX23 diff --git a/arch/arm/mach-mxs/iomux-imx.c b/arch/arm/mach-mxs/iomux-imx.c index bf6165f8d2..3161a5d3cc 100644 --- a/arch/arm/mach-mxs/iomux-imx.c +++ b/arch/arm/mach-mxs/iomux-imx.c @@ -21,7 +21,7 @@ #include <init.h> #include <gpio.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #define HW_PINCTRL_CTRL 0x000 diff --git a/arch/arm/mach-mxs/reset-imx.c b/arch/arm/mach-mxs/reset-imx.c index b35f796b40..cfb3548f2a 100644 --- a/arch/arm/mach-mxs/reset-imx.c +++ b/arch/arm/mach-mxs/reset-imx.c @@ -21,7 +21,7 @@ #include <init.h> #include <notifier.h> #include <mach/imx-regs.h> -#include <asm/io.h> +#include <io.h> #define HW_RTC_CTRL 0x000 # define BM_RTC_CTRL_WATCHDOGEN (1 << 4) diff --git a/arch/arm/mach-mxs/speed-imx23.c b/arch/arm/mach-mxs/speed-imx23.c index a31139d7a7..b10c78643c 100644 --- a/arch/arm/mach-mxs/speed-imx23.c +++ b/arch/arm/mach-mxs/speed-imx23.c @@ -24,7 +24,7 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/generic.h> #include <mach/clock.h> diff --git a/arch/arm/mach-mxs/speed-imx28.c b/arch/arm/mach-mxs/speed-imx28.c index 63c6b0754b..67cdbdf81d 100644 --- a/arch/arm/mach-mxs/speed-imx28.c +++ b/arch/arm/mach-mxs/speed-imx28.c @@ -18,7 +18,7 @@ */ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/generic.h> #include <mach/clock.h> diff --git a/arch/arm/mach-mxs/usb.c b/arch/arm/mach-mxs/usb.c index d232bb6075..b7a93769b7 100644 --- a/arch/arm/mach-mxs/usb.c +++ b/arch/arm/mach-mxs/usb.c @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #define POWER_CTRL (IMX_POWER_BASE + 0x0) diff --git a/arch/arm/mach-nomadik/reset.c b/arch/arm/mach-nomadik/reset.c index d55f278293..6ea74dd6c0 100644 --- a/arch/arm/mach-nomadik/reset.c +++ b/arch/arm/mach-nomadik/reset.c @@ -18,7 +18,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> void __noreturn reset_cpu(unsigned long addr) diff --git a/arch/arm/mach-nomadik/timer.c b/arch/arm/mach-nomadik/timer.c index 7de1f391a6..becd36357a 100644 --- a/arch/arm/mach-nomadik/timer.c +++ b/arch/arm/mach-nomadik/timer.c @@ -11,7 +11,7 @@ #include <common.h> #include <init.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #include <mach/mtu.h> #include <mach/timex.h> diff --git a/arch/arm/mach-omap/devices-gpmc-nand.c b/arch/arm/mach-omap/devices-gpmc-nand.c index 76ceb20024..197d4be418 100644 --- a/arch/arm/mach-omap/devices-gpmc-nand.c +++ b/arch/arm/mach-omap/devices-gpmc-nand.c @@ -31,7 +31,7 @@ #include <init.h> #include <driver.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/gpmc.h> diff --git a/arch/arm/mach-omap/gpio.c b/arch/arm/mach-omap/gpio.c index b0bd805628..142cf524eb 100644 --- a/arch/arm/mach-omap/gpio.c +++ b/arch/arm/mach-omap/gpio.c @@ -37,7 +37,7 @@ */ #include <common.h> #include <mach/gpio.h> -#include <asm/io.h> +#include <io.h> #include <errno.h> #ifdef CONFIG_ARCH_OMAP3 diff --git a/arch/arm/mach-omap/gpmc.c b/arch/arm/mach-omap/gpmc.c index 2b9964950d..e8946d7c56 100644 --- a/arch/arm/mach-omap/gpmc.c +++ b/arch/arm/mach-omap/gpmc.c @@ -29,7 +29,7 @@ */ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/gpmc.h> #include <mach/sys_info.h> diff --git a/arch/arm/mach-omap/include/mach/omap3-silicon.h b/arch/arm/mach-omap/include/mach/omap3-silicon.h index 0e6a45f8fd..67f77476a9 100644 --- a/arch/arm/mach-omap/include/mach/omap3-silicon.h +++ b/arch/arm/mach-omap/include/mach/omap3-silicon.h @@ -132,5 +132,8 @@ #define OMAP_SDRC_CS0 0x80000000 #define OMAP_SDRC_CS1 0xA0000000 +/* PRM */ +#define PRM_RSTCTRL_RESET 0x04 + #endif /* __ASM_ARCH_OMAP3_H */ diff --git a/arch/arm/mach-omap/include/mach/omap_hsmmc.h b/arch/arm/mach-omap/include/mach/omap_hsmmc.h new file mode 100644 index 0000000000..a15f8e62a2 --- /dev/null +++ b/arch/arm/mach-omap/include/mach/omap_hsmmc.h @@ -0,0 +1,28 @@ +/** + * @file + * @brief This file contains exported structure for OMAP hsmmc + * + * FileName: include/asm-arm/arch-omap/omap_hsmmc.h + * + * OMAP3 and OMAP4 has a MMC/SD controller embedded. + * This file provides the platform data structure required to + * addapt to platform specialities. + */ +/* + * (C) Copyright 2011 + * Phytec Messtechnik GmbH, <www.phytec.de> + * Juergen Kilb <j.kilb@phytec.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#ifndef __ASM_OMAP_HSMMC_H +#define __ASM_OMAP_HSMMC_H + +/** omapmmc platform data structure */ +struct omap_hsmmc_platform_data { + unsigned f_max; /* host interface upper limit */ +}; +#endif /* __ASM_OMAP_HSMMC_H */ diff --git a/arch/arm/mach-omap/include/mach/sys_info.h b/arch/arm/mach-omap/include/mach/sys_info.h index f557068345..f0594bf2b7 100644 --- a/arch/arm/mach-omap/include/mach/sys_info.h +++ b/arch/arm/mach-omap/include/mach/sys_info.h @@ -91,6 +91,7 @@ u32 get_cpu_type(void); u32 get_cpu_rev(void); u32 get_sdr_cs_size(u32 offset); +u32 get_sdr_cs1_base(void); inline u32 get_sysboot_value(void); u32 get_gpmc0_base(void); u32 get_base(void); diff --git a/arch/arm/mach-omap/include/mach/syslib.h b/arch/arm/mach-omap/include/mach/syslib.h index 65aca0297f..1909f172a6 100644 --- a/arch/arm/mach-omap/include/mach/syslib.h +++ b/arch/arm/mach-omap/include/mach/syslib.h @@ -30,7 +30,7 @@ */ #ifndef __ASM_ARCH_OMAP_SYSLIB_H_ #define __ASM_ARCH_OMAP_SYSLIB_H_ -#include <asm/io.h> +#include <io.h> /** System Independent functions */ diff --git a/arch/arm/mach-omap/omap3_clock.c b/arch/arm/mach-omap/omap3_clock.c index 3a0ab24e58..412d7b714c 100644 --- a/arch/arm/mach-omap/omap3_clock.c +++ b/arch/arm/mach-omap/omap3_clock.c @@ -39,7 +39,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/clocks.h> #include <mach/timers.h> diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c index 661a971fc0..fc83d23713 100644 --- a/arch/arm/mach-omap/omap3_generic.c +++ b/arch/arm/mach-omap/omap3_generic.c @@ -36,7 +36,7 @@ */ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/gpmc.h> #include <mach/sdrc.h> @@ -59,8 +59,9 @@ */ void __noreturn reset_cpu(unsigned long addr) { - /* FIXME: Enable WDT and cause reset */ - hang(); + writel(PRM_RSTCTRL_RESET, PRM_REG(RSTCTRL)); + + while (1); } EXPORT_SYMBOL(reset_cpu); @@ -177,7 +178,26 @@ u32 get_sdr_cs_size(u32 offset) size *= 2 * (1024 * 1024); /* find size in MB */ return size; } +EXPORT_SYMBOL(get_sdr_cs_size); +/** + * @brief base address of chip select 1 (cs0 is defined at 0x80000000) + * + * @return return the CS1 base address. + */ +u32 get_sdr_cs1_base(void) +{ + u32 base; + u32 cs_cfg; + cs_cfg = readl(SDRC_REG(CS_CFG)); + /* get ram size field */ + base = (cs_cfg & 0x0000000F) << 2; /* get CS1STARTHIGH */ + base = base | ((cs_cfg & 0x00000300) >> 8); /* get CS1STARTLOW */ + base = base << 25; + base += 0x80000000; + return base; +} +EXPORT_SYMBOL(get_sdr_cs1_base); /** * @brief Get the initial SYSBOOT value * diff --git a/arch/arm/mach-omap/omap4_clock.c b/arch/arm/mach-omap/omap4_clock.c index 23a77d06f1..f8bab5f93a 100644 --- a/arch/arm/mach-omap/omap4_clock.c +++ b/arch/arm/mach-omap/omap4_clock.c @@ -1,6 +1,6 @@ #include <common.h> #include <mach/syslib.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-clock.h> #define LDELAY 12000000 diff --git a/arch/arm/mach-omap/omap4_generic.c b/arch/arm/mach-omap/omap4_generic.c index 313e5e997b..5223c7e757 100644 --- a/arch/arm/mach-omap/omap4_generic.c +++ b/arch/arm/mach-omap/omap4_generic.c @@ -1,7 +1,7 @@ #include <common.h> #include <init.h> #include <mach/silicon.h> -#include <asm/io.h> +#include <io.h> #include <mach/omap4-silicon.h> #include <mach/omap4-clock.h> #include <mach/syslib.h> diff --git a/arch/arm/mach-omap/s32k_clksource.c b/arch/arm/mach-omap/s32k_clksource.c index 094b76d6b7..3ed9448949 100644 --- a/arch/arm/mach-omap/s32k_clksource.c +++ b/arch/arm/mach-omap/s32k_clksource.c @@ -33,7 +33,7 @@ #include <common.h> #include <clock.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/clocks.h> #include <mach/timers.h> diff --git a/arch/arm/mach-omap/syslib.c b/arch/arm/mach-omap/syslib.c index 677de6a27d..765a816147 100644 --- a/arch/arm/mach-omap/syslib.c +++ b/arch/arm/mach-omap/syslib.c @@ -32,7 +32,7 @@ #include <config.h> #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/syslib.h> /** diff --git a/arch/arm/mach-s3c24xx/generic.c b/arch/arm/mach-s3c24xx/generic.c index 4c7e799850..d2f2ac7ac0 100644 --- a/arch/arm/mach-s3c24xx/generic.c +++ b/arch/arm/mach-s3c24xx/generic.c @@ -26,7 +26,7 @@ #include <common.h> #include <init.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24x0-iomap.h> /** diff --git a/arch/arm/mach-s3c24xx/gpio-s3c24x0.c b/arch/arm/mach-s3c24xx/gpio-s3c24x0.c index 3d5e5e5c96..946ec3396e 100644 --- a/arch/arm/mach-s3c24xx/gpio-s3c24x0.c +++ b/arch/arm/mach-s3c24xx/gpio-s3c24x0.c @@ -17,7 +17,7 @@ #include <common.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24x0-iomap.h> #include <mach/gpio.h> diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c index 1231a7db63..bdf48f97a2 100644 --- a/arch/arm/mach-versatile/core.c +++ b/arch/arm/mach-versatile/core.c @@ -35,7 +35,7 @@ #include <linux/clk.h> #include <linux/err.h> -#include <asm/io.h> +#include <io.h> #include <asm/hardware/arm_timer.h> #include <asm/armlinux.h> diff --git a/arch/arm/mach-versatile/include/mach/debug_ll.h b/arch/arm/mach-versatile/include/mach/debug_ll.h index 1f6162b9db..30762c93fb 100644 --- a/arch/arm/mach-versatile/include/mach/debug_ll.h +++ b/arch/arm/mach-versatile/include/mach/debug_ll.h @@ -20,7 +20,7 @@ #define __MACH_DEBUG_LL_H__ #include <linux/amba/serial.h> -#include <asm/io.h> +#include <io.h> static inline void putc(char c) { diff --git a/arch/blackfin/lib/board.c b/arch/blackfin/lib/board.c index 581947be26..d1b39fa347 100644 --- a/arch/blackfin/lib/board.c +++ b/arch/blackfin/lib/board.c @@ -31,7 +31,7 @@ #include <net.h> #include <init.h> #include <environment.h> -#include <mem_malloc.h> +#include <memory.h> #include <asm/cpu.h> #include <asm-generic/memory_layout.h> diff --git a/arch/mips/boards/dlink-dir-320/serial.c b/arch/mips/boards/dlink-dir-320/serial.c index ebe8c06c7a..3eaab2a129 100644 --- a/arch/mips/boards/dlink-dir-320/serial.c +++ b/arch/mips/boards/dlink-dir-320/serial.c @@ -24,7 +24,7 @@ #include <init.h> #include <ns16550.h> #include <mach/hardware.h> -#include <asm/io.h> +#include <io.h> #include <asm/common.h> static struct NS16550_plat serial_plat = { diff --git a/arch/mips/boards/qemu-malta/serial.c b/arch/mips/boards/qemu-malta/serial.c index ef6be17f1f..502b3468bb 100644 --- a/arch/mips/boards/qemu-malta/serial.c +++ b/arch/mips/boards/qemu-malta/serial.c @@ -24,7 +24,7 @@ #include <init.h> #include <ns16550.h> #include <mach/hardware.h> -#include <asm/io.h> +#include <io.h> #include <asm/common.h> static struct NS16550_plat serial_plat = { diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index dd9eab7970..ba4c0afc11 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -64,10 +64,6 @@ SECTIONS __usymtab : { BAREBOX_SYMS } __usymtab_end = .; - __early_init_data_begin = .; - .early_init_data : { *(.early_init_data) } - __early_init_data_end = .; - . = ALIGN(4); __bss_start = .; .bss : { *(.bss*) } diff --git a/arch/mips/lib/csrc-r4k.c b/arch/mips/lib/csrc-r4k.c index 8e93e6f6c4..1dd0928949 100644 --- a/arch/mips/lib/csrc-r4k.c +++ b/arch/mips/lib/csrc-r4k.c @@ -25,7 +25,7 @@ #include <init.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <asm/mipsregs.h> static uint64_t c0_hpt_read(void) diff --git a/arch/mips/lib/memory.c b/arch/mips/lib/memory.c index 23a995c45d..ad9f6a6a40 100644 --- a/arch/mips/lib/memory.c +++ b/arch/mips/lib/memory.c @@ -20,7 +20,7 @@ #include <common.h> #include <init.h> -#include <mem_malloc.h> +#include <memory.h> #include <asm-generic/memory_layout.h> static int mips_mem_malloc_init(void) diff --git a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h index 32d13c1a87..ccc9d9bfc7 100644 --- a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h +++ b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h @@ -24,7 +24,7 @@ #ifndef __INCLUDE_ARCH_DEBUG_LL_H__ #define __INCLUDE_ARCH_DEBUG_LL_H__ -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #define rbr 0 diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c index 2818e7cfa3..d6fcd8dec2 100644 --- a/arch/mips/mach-bcm47xx/reset.c +++ b/arch/mips/mach-bcm47xx/reset.c @@ -24,7 +24,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> void __noreturn reset_cpu(ulong addr) diff --git a/arch/mips/mach-malta/include/mach/debug_ll.h b/arch/mips/mach-malta/include/mach/debug_ll.h index 32d13c1a87..ccc9d9bfc7 100644 --- a/arch/mips/mach-malta/include/mach/debug_ll.h +++ b/arch/mips/mach-malta/include/mach/debug_ll.h @@ -24,7 +24,7 @@ #ifndef __INCLUDE_ARCH_DEBUG_LL_H__ #define __INCLUDE_ARCH_DEBUG_LL_H__ -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #define rbr 0 diff --git a/arch/mips/mach-malta/reset.c b/arch/mips/mach-malta/reset.c index 2818e7cfa3..d6fcd8dec2 100644 --- a/arch/mips/mach-malta/reset.c +++ b/arch/mips/mach-malta/reset.c @@ -24,7 +24,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> void __noreturn reset_cpu(ulong addr) diff --git a/arch/nios2/cpu/interrupts.c b/arch/nios2/cpu/interrupts.c index 5efbd5e354..f443bfdec5 100644 --- a/arch/nios2/cpu/interrupts.c +++ b/arch/nios2/cpu/interrupts.c @@ -27,7 +27,7 @@ #include <nios2.h> #include <asm/nios2-io.h> #include <asm/types.h> -#include <asm/io.h> +#include <io.h> #include <asm/ptrace.h> #include <common.h> #include <command.h> diff --git a/arch/nios2/lib/board.c b/arch/nios2/lib/board.c index 7cbff4032b..07f045b3aa 100644 --- a/arch/nios2/lib/board.c +++ b/arch/nios2/lib/board.c @@ -23,7 +23,7 @@ #include <common.h> #include <malloc.h> #include <init.h> -#include <mem_malloc.h> +#include <memory.h> #include <asm-generic/memory_layout.h> #include <cache.h> diff --git a/arch/nios2/lib/clock.c b/arch/nios2/lib/clock.c index 05008be793..52f52fd145 100644 --- a/arch/nios2/lib/clock.c +++ b/arch/nios2/lib/clock.c @@ -24,7 +24,7 @@ #include <clock.h> #include <init.h> #include <asm/nios2-io.h> -#include <asm/io.h> +#include <io.h> static struct nios_timer *timer = (struct nios_timer *)NIOS_SOPC_TIMER_BASE; diff --git a/arch/nios2/lib/early_printf.c b/arch/nios2/lib/early_printf.c index 637bb73b0d..50b071ba5e 100644 --- a/arch/nios2/lib/early_printf.c +++ b/arch/nios2/lib/early_printf.c @@ -23,7 +23,7 @@ #include <stdio.h> #include <common.h> #include <asm/nios2-io.h> -#include <asm/io.h> +#include <io.h> void early_putc(char ch) { diff --git a/arch/ppc/Kconfig b/arch/ppc/Kconfig index cda14de25d..50ccaac5f3 100644 --- a/arch/ppc/Kconfig +++ b/arch/ppc/Kconfig @@ -7,15 +7,6 @@ config ARCH_TEXT_BASE default 0x00000000 if RELOCATABLE default 0x01000000 if MACH_PHYCORE_MPC5200B_TINY -config MPC5XXX_EARLY_CONSOLE - bool - depends on ARCH_MPC5200 - default y - -config HAS_EARLY_INIT - bool - default y - config PPC bool select HAVE_CONFIGURABLE_TEXT_BASE diff --git a/arch/ppc/boards/pcm030/barebox.lds.S b/arch/ppc/boards/pcm030/barebox.lds.S index 21bf4a75c7..4aacfc5f12 100644 --- a/arch/ppc/boards/pcm030/barebox.lds.S +++ b/arch/ppc/boards/pcm030/barebox.lds.S @@ -111,10 +111,6 @@ SECTIONS __usymtab : { BAREBOX_SYMS } __usymtab_end = .; - __early_init_data_begin = .; - .early_init_data : { *(.early_init_data) } - __early_init_data_end = .; - __start___ex_table = .; __ex_table : { *(__ex_table) } __stop___ex_table = .; diff --git a/arch/ppc/boards/pcm030/config.h b/arch/ppc/boards/pcm030/config.h index a772ee6d96..508e017161 100644 --- a/arch/ppc/boards/pcm030/config.h +++ b/arch/ppc/boards/pcm030/config.h @@ -29,79 +29,15 @@ #include <mach/mpc5xxx.h> -/* #define DEBUG */ - -/*------------------------------------------------------------------------------------------------------------------------------------------------------ -High Level Configuration Options -(easy to change) - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CONFIG_MPC5200_DDR 1 /* (with DDR-SDRAM) */ #define CFG_MPC5XXX_CLKIN 33333333 /* ... running at 33.333333MHz */ -#define BOOTFLAG_COLD 0x01 /* Normal Power-On: Boot from FLASH */ -#define BOOTFLAG_WARM 0x02 /* Software reboot */ - -/*------------------------------------------------------------------------------------------------------------------------------------------------------ -Serial console configuration - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ - -#if (TEXT_BASE == 0xFF000000) /* Boot low */ -#define CFG_LOWBOOT 1 -#endif -/* RAMBOOT will be defined automatically in memory section */ - -/*------------------------------------------------------------------------------------------------------------------------------------------------------ -IPB Bus clocking configuration. - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CFG_IPBSPEED_133 /* define for 133MHz speed */ -#if defined(CFG_IPBSPEED_133) -/* - * PCI Bus clocking configuration - * - * Actually a PCI Clock of 66 MHz is only set (in cpu_init.c) if - * CFG_IPBSPEED_133 is defined. This is because a PCI Clock of 66 MHz yet hasn't - * been tested with a IPB Bus Clock of 66 MHz. - */ -#define CFG_PCISPEED_66 /* define for 66MHz speed */ -#else -#undef CFG_PCISPEED_66 /* for 33MHz speed */ -#endif -/* we only use CS-Boot */ -#define CFG_BOOTCS_START 0xFF000000 -#define CFG_BOOTCS_SIZE 0x01000000 - -#if CONFIG_MACH_PHYCORE_MPC5200B_TINY_REV == 1 -#define CFG_BOOTCS_CFG 0x0008FD00 -#else -#define CFG_BOOTCS_CFG 0x00083800 -#endif - -/*------------------------------------------------------------------------------------------------------------------------------------------------------ - Memory map - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CFG_MBAR 0xF0000000 /* MBAR hast to be switched by other bootloader or debugger config */ -#define CFG_SDRAM_BASE 0x00000000 - -/* Use SRAM until RAM will be available */ -#define CFG_INIT_RAM_ADDR MPC5XXX_SRAM -#define CFG_INIT_RAM_SIZE MPC5XXX_SRAM_SIZE /* End of used area in DPRAM */ -#define CONFIG_EARLY_INITDATA_SIZE 0x100 - -#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ - -/*------------------------------------------------------------------------------------------------------------------------------------------------------ - GPIO configuration - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CFG_GPS_PORT_CONFIG 0x00558c10 /* PSC6=UART, PSC3=UART ; Ether=100MBit with MD */ -/*------------------------------------------------------------------------------------------------------------------------------------------------------ - Various low-level settings - ------------------------------------------------------------------------------------------------------------------------------------------------------*/ #define CFG_HID0_INIT HID0_ICE | HID0_ICFI #define CFG_HID0_FINAL HID0_ICE -#define CFG_CS_BURST 0x00000000 -#define CFG_CS_DEADCYCLE 0x33333333 + +#define CFG_BOOTMAPSZ (8 << 20) /* Initial Memory map for Linux */ #define OF_CPU "PowerPC,5200@0" #define OF_TBCLK CFG_MPC5XXX_CLKIN diff --git a/arch/ppc/boards/pcm030/pcm030.c b/arch/ppc/boards/pcm030/pcm030.c index ba59bfe101..61fb11620f 100644 --- a/arch/ppc/boards/pcm030/pcm030.c +++ b/arch/ppc/boards/pcm030/pcm030.c @@ -34,8 +34,10 @@ #include <mach/fec.h> #include <types.h> #include <partition.h> -#include <mem_malloc.h> -#include <reloc.h> +#include <memory.h> +#include <sizes.h> +#include <linux/stat.h> +#include <fs.h> static struct mpc5xxx_fec_platform_data fec_info = { .xcv_type = MII100, @@ -43,14 +45,29 @@ static struct mpc5xxx_fec_platform_data fec_info = { static int devices_init (void) { - add_cfi_flash_device(-1, 0xff000000, 16 * 1024 * 1024, 0); - add_mem_device("ram0", 0x0, 64 * 1024 * 1024, - IORESOURCE_MEM_WRITEABLE); + unsigned long sdramsize; + struct stat s; + int ret; + + /* + * Flash can be 16MB or 32MB, setup for the last 32MB no matter + * what we find later. + */ + mpc5200_setup_cs(MPC5200_BOOTCS, 0xfe000000, SZ_32M, 0x0008fd00); + add_cfi_flash_device(-1, 0xfe000000, 32 * 1024 * 1024, 0); + + sdramsize = mpc5200_get_sdram_size(0) + mpc5200_get_sdram_size(1); + barebox_add_memory_bank("ram0", 0x0, sdramsize); + add_generic_device("fec_mpc5xxx", -1, NULL, MPC5XXX_FEC, 0, IORESOURCE_MEM, &fec_info); - devfs_add_partition("nor0", 0x00f00000, 0x40000, PARTITION_FIXED, "self0"); - devfs_add_partition("nor0", 0x00f60000, 0x20000, PARTITION_FIXED, "env0"); + ret = stat("/dev/nor0", &s); + if (ret) + return 0; + + devfs_add_partition("nor0", s.st_size - SZ_1M, SZ_512K, PARTITION_FIXED, "self0"); + devfs_add_partition("nor0", s.st_size - SZ_512K, SZ_512K, PARTITION_FIXED, "env0"); return 0; } @@ -68,15 +85,6 @@ static int console_init(void) console_initcall(console_init); -void *get_early_console_base(const char *name) -{ - if (!strcmp(name, RELOC("psc3"))) - return (void *)MPC5XXX_PSC3; - if (!strcmp(name, RELOC("psc6"))) - return (void *)MPC5XXX_PSC6; - return NULL; -} - #include "mt46v32m16-75.h" static void sdram_start (int hi_addr) @@ -118,20 +126,22 @@ static void sdram_start (int hi_addr) __asm__ volatile ("sync"); } -/* - * ATTENTION: Although partially referenced initdram does NOT make real use - * use of CFG_SDRAM_BASE. The code does not work if CFG_SDRAM_BASE - * is something else than 0x00000000. - */ - -long int initdram (int board_type) +void initdram (int board_type) { ulong dramsize = 0; - ulong dramsize2 = 0; ulong test1, test2; - if ((ulong)RELOC(initdram) > (2 << 30)) { + /* Setup pin multiplexing */ + + /* PSC6=UART, PSC3=UART ; Ether=100MBit with MD */ + *(vu_long *)MPC5XXX_GPS_PORT_CONFIG = 0x00558c10; + *(vu_long *)MPC5XXX_CS_BURST = 0x00000000; + *(vu_long *)MPC5XXX_CS_DEADCYCLE = 0x33333333; + + mpc5200_setup_bus_clocks(1, 4); + + if (get_pc() > SZ_128M) { /* setup SDRAM chip selects */ *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0x0000001b;/* 256MB at 0x0 */ *(vu_long *)MPC5XXX_SDRAM_CS1CFG = 0x10000000;/* disabled */ @@ -150,9 +160,9 @@ long int initdram (int board_type) /* find RAM size using SDRAM CS0 only */ sdram_start(0); - test1 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x10000000); + test1 = get_ram_size((ulong *)0, 0x10000000); sdram_start(1); - test2 = get_ram_size((ulong *)CFG_SDRAM_BASE, 0x10000000); + test2 = get_ram_size((ulong *)0, 0x10000000); if (test1 > test2) { sdram_start(0); dramsize = test1; @@ -171,26 +181,7 @@ long int initdram (int board_type) } else { *(vu_long *)MPC5XXX_SDRAM_CS0CFG = 0; /* disabled */ } - } else - puts(RELOC("skipping sdram initialization\n")); - - /* retrieve size of memory connected to SDRAM CS0 */ - dramsize = *(vu_long *)MPC5XXX_SDRAM_CS0CFG & 0xFF; - if (dramsize >= 0x13) { - dramsize = (1 << (dramsize - 0x13)) << 20; - } else { - dramsize = 0; - } - - /* retrieve size of memory connected to SDRAM CS1 */ - dramsize2 = *(vu_long *)MPC5XXX_SDRAM_CS1CFG & 0xFF; - if (dramsize2 >= 0x13) { - dramsize2 = (1 << (dramsize2 - 0x13)) << 20; - } else { - dramsize2 = 0; } - - return dramsize + dramsize2; } #if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP) diff --git a/arch/ppc/include/asm/common.h b/arch/ppc/include/asm/common.h index 96de5c6568..b7c524a646 100644 --- a/arch/ppc/include/asm/common.h +++ b/arch/ppc/include/asm/common.h @@ -3,14 +3,10 @@ #include <asm/barebox.h> -void upmconfig (unsigned int, unsigned int *, unsigned int); -ulong get_tbclk (void); +extern unsigned long _text_base; unsigned long long get_ticks(void); -int get_clocks (void); -ulong get_bus_freq (ulong); - int cpu_init (void); uint get_pvr (void); @@ -21,4 +17,21 @@ void trap_init (ulong); int cpu_init_board_data(bd_t *bd); int init_board_data(bd_t *bd); +static inline unsigned long get_pc(void) +{ + unsigned long pc; + + __asm__ __volatile__( + " mflr 0\n" + " bl 1f\n" + "1:\n" + " mflr %0\n" + " mtlr 0\n" + : "=r" (pc) + : + : "0", "memory"); + + return pc; +} + #endif /* __ASM_COMMON_H */ diff --git a/arch/ppc/include/asm/mc146818rtc.h b/arch/ppc/include/asm/mc146818rtc.h index 5f806c4ec2..adc4e24db7 100644 --- a/arch/ppc/include/asm/mc146818rtc.h +++ b/arch/ppc/include/asm/mc146818rtc.h @@ -4,7 +4,7 @@ #ifndef __ASM_PPC_MC146818RTC_H #define __ASM_PPC_MC146818RTC_H -#include <asm/io.h> +#include <io.h> #ifndef RTC_PORT #define RTC_PORT(x) (0x70 + (x)) diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c index 7f8118e16f..82ba458fcc 100644 --- a/arch/ppc/lib/board.c +++ b/arch/ppc/lib/board.c @@ -26,10 +26,9 @@ #include <watchdog.h> #include <command.h> #include <malloc.h> -#include <mem_malloc.h> +#include <memory.h> #include <init.h> #include <net.h> -#include <reloc.h> #include <asm-generic/memory_layout.h> /************************************************************************ @@ -48,8 +47,6 @@ void board_init_r (ulong end_of_ram) asm ("sync ; isync"); - _text_base += reloc_offset(); - /* * FIXME: 128k stack size. Is this enough? should * it be configurable? diff --git a/arch/ppc/lib/board_data.c b/arch/ppc/lib/board_data.c index b28830f792..ff9f0d0f0c 100644 --- a/arch/ppc/lib/board_data.c +++ b/arch/ppc/lib/board_data.c @@ -4,7 +4,7 @@ int init_board_data(bd_t *bd) { cpu_init_board_data(bd); - bd->bi_memstart = CFG_SDRAM_BASE; /* start of DRAM memory */ + bd->bi_memstart = 0; /* start of DRAM memory */ // bd->bi_memsize = gd->ram_size; /* size of DRAM memory in bytes */ /* FIXME */ #ifdef CONFIG_IP860 diff --git a/arch/ppc/mach-mpc5xxx/Kconfig b/arch/ppc/mach-mpc5xxx/Kconfig index 5da6a5b5b2..632fb857f1 100644 --- a/arch/ppc/mach-mpc5xxx/Kconfig +++ b/arch/ppc/mach-mpc5xxx/Kconfig @@ -10,6 +10,3 @@ config MACH_PHYCORE_MPC5200B_TINY_REV old board you should set this option to 1 endmenu - -config EARLY_CONSOLE_PORT - default "psc3" if MACH_PHYCORE_MPC5200B_TINY
\ No newline at end of file diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c index be7c19d136..d695b9b545 100644 --- a/arch/ppc/mach-mpc5xxx/cpu.c +++ b/arch/ppc/mach-mpc5xxx/cpu.c @@ -30,8 +30,10 @@ #include <mach/mpc5xxx.h> #include <asm/processor.h> #include <asm/byteorder.h> +#include <asm/io.h> #include <init.h> #include <types.h> +#include <errno.h> #include <mach/clocks.h> #if defined(CONFIG_OF_FLAT_TREE) @@ -41,16 +43,10 @@ int checkcpu (void) { ulong clock = get_cpu_clock(); -#ifndef CONFIG_MGT5100 uint svr, pvr; -#endif puts ("CPU: "); -#ifdef CONFIG_MGT5100 - puts (CPU_ID_STR); - printf (" (JTAG ID %08lx)", *(vu_long *)MPC5XXX_CDM_JTAGID); -#else svr = get_svr(); pvr = get_pvr(); switch (SVR_VER (svr)) { @@ -64,7 +60,6 @@ int checkcpu (void) printf (" v%d.%d, Core v%d.%d", SVR_MJREV (svr), SVR_MNREV (svr), PVR_MAJ(pvr), PVR_MIN(pvr)); -#endif printf (" at %ld Hz\n", clock); return 0; } @@ -120,3 +115,126 @@ int cpu_init_board_data(bd_t *bd) bd->bi_pcifreq = get_pci_clock(); return 0; } + +unsigned long mpc5200_get_sdram_size(unsigned int cs) +{ + unsigned long size; + + if (cs > 1) + return 0; + + /* retrieve size of memory connected to SDRAM CS0 */ + size = *(vu_long *)(MPC5XXX_SDRAM_CS0CFG + (cs * 4)) & 0xFF; + if (size >= 0x13) + size = (1 << (size - 0x13)) << 20; + else + size = 0; + + return size; +} + +int mpc5200_setup_bus_clocks(unsigned int ipbdiv, unsigned long pcidiv) +{ + u32 cdmcfg = *(vu_long *)MPC5XXX_CDM_CFG; + + cdmcfg &= ~0x103; + + switch (ipbdiv) { + case 1: + break; + case 2: + cdmcfg |= 0x100; + break; + default: + return -EINVAL; + } + + switch (pcidiv) { + case 1: + if (ipbdiv == 2) + return -EINVAL; + break; + case 2: + if (ipbdiv == 1) + cdmcfg |= 0x1; /* ipb / 2 */ + break; + case 4: + cdmcfg |= 0x2; /* xlb / 4 */ + break; + default: + return -EINVAL; + } + + *(vu_long *)MPC5XXX_CDM_CFG = cdmcfg; + + return 0; +} + +struct mpc5200_cs { + void *start; + void *stop; + void *cfg; + unsigned int addecr; +}; + +static struct mpc5200_cs chipselects[] = { + { + .start = (void *)MPC5XXX_CS0_START, + .stop = (void *)MPC5XXX_CS0_STOP, + .cfg = (void *)MPC5XXX_CS0_CFG, + .addecr = 1 << 16, + }, { + .start = (void *)MPC5XXX_CS1_START, + .stop = (void *)MPC5XXX_CS1_STOP, + .cfg = (void *)MPC5XXX_CS1_CFG, + .addecr = 1 << 17, + }, { + .start = (void *)MPC5XXX_CS2_START, + .stop = (void *)MPC5XXX_CS2_STOP, + .cfg = (void *)MPC5XXX_CS2_CFG, + .addecr = 1 << 18, + }, { + .start = (void *)MPC5XXX_CS3_START, + .stop = (void *)MPC5XXX_CS3_STOP, + .cfg = (void *)MPC5XXX_CS3_CFG, + .addecr = 1 << 19, + }, { + .start = (void *)MPC5XXX_CS4_START, + .stop = (void *)MPC5XXX_CS4_STOP, + .cfg = (void *)MPC5XXX_CS4_CFG, + .addecr = 1 << 20, + }, { + .start = (void *)MPC5XXX_CS5_START, + .stop = (void *)MPC5XXX_CS5_STOP, + .cfg = (void *)MPC5XXX_CS5_CFG, + .addecr = 1 << 21, + }, { + .start = (void *)MPC5XXX_CS6_START, + .stop = (void *)MPC5XXX_CS6_STOP, + .cfg = (void *)MPC5XXX_CS6_CFG, + .addecr = 1 << 26, + }, { + .start = (void *)MPC5XXX_CS7_START, + .stop = (void *)MPC5XXX_CS7_STOP, + .cfg = (void *)MPC5XXX_CS7_CFG, + .addecr = 1 << 27, + }, { + .start = (void *)MPC5XXX_BOOTCS_START, + .stop = (void *)MPC5XXX_BOOTCS_STOP, + .cfg = (void *)MPC5XXX_CS0_CFG, + .addecr = 1 << 25, + }, +}; + +void mpc5200_setup_cs(int cs, unsigned long start, unsigned long size, u32 cfg) +{ + u32 addecr; + + out_be32(chipselects[cs].start, START_REG(start)); + out_be32(chipselects[cs].stop, STOP_REG(start, size)); + out_be32(chipselects[cs].cfg, cfg); + + addecr = in_be32((void *)MPC5XXX_ADDECR); + addecr |= chipselects[cs].addecr | 1; + out_be32((void *)MPC5XXX_ADDECR, addecr); +} diff --git a/arch/ppc/mach-mpc5xxx/cpu_init.c b/arch/ppc/mach-mpc5xxx/cpu_init.c index fc5db0ec3e..a6c270b3ef 100644 --- a/arch/ppc/mach-mpc5xxx/cpu_init.c +++ b/arch/ppc/mach-mpc5xxx/cpu_init.c @@ -24,172 +24,35 @@ #include <common.h> #include <mach/mpc5xxx.h> #include <types.h> -#include <reloc.h> /* * Breath some life into the CPU... * - * Set up the memory map, * initialize a bunch of registers. */ int cpu_init(void) { unsigned long addecr = (1 << 25); /* Boot_CS */ -#if defined(CFG_RAMBOOT) && defined(CONFIG_MGT5100) - addecr |= (1 << 22); /* SDRAM enable */ -#endif - - /* - * Memory Controller: configure chip selects and enable them - */ -#if defined(CFG_BOOTCS_START) && defined(CFG_BOOTCS_SIZE) - *(vu_long *)MPC5XXX_BOOTCS_START = START_REG(CFG_BOOTCS_START); - *(vu_long *)MPC5XXX_BOOTCS_STOP = STOP_REG(CFG_BOOTCS_START, - CFG_BOOTCS_SIZE); -#endif -#if defined(CFG_BOOTCS_CFG) - *(vu_long *)MPC5XXX_BOOTCS_CFG = CFG_BOOTCS_CFG; -#endif - -#if defined(CFG_CS0_START) && defined(CFG_CS0_SIZE) - *(vu_long *)MPC5XXX_CS0_START = START_REG(CFG_CS0_START); - *(vu_long *)MPC5XXX_CS0_STOP = STOP_REG(CFG_CS0_START, CFG_CS0_SIZE); - /* CS0 and BOOT_CS cannot be enabled at once. */ - /* addecr |= (1 << 16); */ -#endif -#if defined(CFG_CS0_CFG) - *(vu_long *)MPC5XXX_CS0_CFG = CFG_CS0_CFG; -#endif - -#if defined(CFG_CS1_START) && defined(CFG_CS1_SIZE) - *(vu_long *)MPC5XXX_CS1_START = START_REG(CFG_CS1_START); - *(vu_long *)MPC5XXX_CS1_STOP = STOP_REG(CFG_CS1_START, CFG_CS1_SIZE); - addecr |= (1 << 17); -#endif -#if defined(CFG_CS1_CFG) - *(vu_long *)MPC5XXX_CS1_CFG = CFG_CS1_CFG; -#endif - -#if defined(CFG_CS2_START) && defined(CFG_CS2_SIZE) - *(vu_long *)MPC5XXX_CS2_START = START_REG(CFG_CS2_START); - *(vu_long *)MPC5XXX_CS2_STOP = STOP_REG(CFG_CS2_START, CFG_CS2_SIZE); - addecr |= (1 << 18); -#endif -#if defined(CFG_CS2_CFG) - *(vu_long *)MPC5XXX_CS2_CFG = CFG_CS2_CFG; -#endif - -#if defined(CFG_CS3_START) && defined(CFG_CS3_SIZE) - *(vu_long *)MPC5XXX_CS3_START = START_REG(CFG_CS3_START); - *(vu_long *)MPC5XXX_CS3_STOP = STOP_REG(CFG_CS3_START, CFG_CS3_SIZE); - addecr |= (1 << 19); -#endif -#if defined(CFG_CS3_CFG) - *(vu_long *)MPC5XXX_CS3_CFG = CFG_CS3_CFG; -#endif - -#if defined(CFG_CS4_START) && defined(CFG_CS4_SIZE) - *(vu_long *)MPC5XXX_CS4_START = START_REG(CFG_CS4_START); - *(vu_long *)MPC5XXX_CS4_STOP = STOP_REG(CFG_CS4_START, CFG_CS4_SIZE); - addecr |= (1 << 20); -#endif -#if defined(CFG_CS4_CFG) - *(vu_long *)MPC5XXX_CS4_CFG = CFG_CS4_CFG; -#endif - -#if defined(CFG_CS5_START) && defined(CFG_CS5_SIZE) - *(vu_long *)MPC5XXX_CS5_START = START_REG(CFG_CS5_START); - *(vu_long *)MPC5XXX_CS5_STOP = STOP_REG(CFG_CS5_START, CFG_CS5_SIZE); - addecr |= (1 << 21); -#endif -#if defined(CFG_CS5_CFG) - *(vu_long *)MPC5XXX_CS5_CFG = CFG_CS5_CFG; -#endif - -#if defined(CONFIG_MPC5200) - addecr |= 1; -#if defined(CFG_CS6_START) && defined(CFG_CS6_SIZE) - *(vu_long *)MPC5XXX_CS6_START = START_REG(CFG_CS6_START); - *(vu_long *)MPC5XXX_CS6_STOP = STOP_REG(CFG_CS6_START, CFG_CS6_SIZE); - addecr |= (1 << 26); -#endif -#if defined(CFG_CS6_CFG) - *(vu_long *)MPC5XXX_CS6_CFG = CFG_CS6_CFG; -#endif - -#if defined(CFG_CS7_START) && defined(CFG_CS7_SIZE) - *(vu_long *)MPC5XXX_CS7_START = START_REG(CFG_CS5_START); - *(vu_long *)MPC5XXX_CS7_STOP = STOP_REG(CFG_CS7_START, CFG_CS7_SIZE); - addecr |= (1 << 27); -#endif -#if defined(CFG_CS7_CFG) - *(vu_long *)MPC5XXX_CS7_CFG = CFG_CS7_CFG; -#endif - -#if defined(CFG_CS_BURST) - *(vu_long *)MPC5XXX_CS_BURST = CFG_CS_BURST; -#endif -#if defined(CFG_CS_DEADCYCLE) - *(vu_long *)MPC5XXX_CS_DEADCYCLE = CFG_CS_DEADCYCLE; -#endif -#endif /* CONFIG_MPC5200 */ - - /* Enable chip selects */ - *(vu_long *)MPC5XXX_ADDECR = addecr; - *(vu_long *)MPC5XXX_CS_CTRL = (1 << 24); - - /* Setup pin multiplexing */ -#if defined(CFG_GPS_PORT_CONFIG) - *(vu_long *)MPC5XXX_GPS_PORT_CONFIG = CFG_GPS_PORT_CONFIG; -#endif - -#if defined(CONFIG_MPC5200) /* enable timebase */ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 13); /* Enable snooping for RAM */ *(vu_long *)(MPC5XXX_XLBARB + 0x40) |= (1 << 15); - *(vu_long *)(MPC5XXX_XLBARB + 0x70) = CFG_SDRAM_BASE | 0x1d; + *(vu_long *)(MPC5XXX_XLBARB + 0x70) = 0 | 0x1d; -# if defined(CFG_IPBSPEED_133) - /* Motorola reports IPB should better run at 133 MHz. */ - *(vu_long *)MPC5XXX_ADDECR |= 1; - /* pci_clk_sel = 0x02, ipb_clk_sel = 0x00; */ - addecr = *(vu_long *)MPC5XXX_CDM_CFG; - addecr &= ~0x103; -# if defined(CFG_PCISPEED_66) - /* pci_clk_sel = 0x01 -> IPB_CLK/2 */ - addecr |= 0x01; -# else - /* pci_clk_sel = 0x02 -> XLB_CLK/4 = IPB_CLK/4 */ - addecr |= 0x02; -# endif /* CFG_PCISPEED_66 */ - *(vu_long *)MPC5XXX_CDM_CFG = addecr; -# endif /* CFG_IPBSPEED_133 */ /* Configure the XLB Arbiter */ *(vu_long *)MPC5XXX_XLBARB_MPRIEN = 0xff; *(vu_long *)MPC5XXX_XLBARB_MPRIVAL = 0x11111111; -# if defined(CFG_XLB_PIPELINING) - /* Enable piplining */ - *(vu_long *)(MPC5XXX_XLBARB + 0x40) &= ~(1 << 31); -# endif -#endif /* CONFIG_MPC5200 */ - /* mask all interrupts */ -#if defined(CONFIG_MGT5100) - *(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xfffffc00; -#elif defined(CONFIG_MPC5200) *(vu_long *)MPC5XXX_ICTL_PER_MASK = 0xffffff00; -#endif + *(vu_long *)MPC5XXX_ICTL_CRIT |= 0x0001ffff; *(vu_long *)MPC5XXX_ICTL_EXT &= ~0x00000f00; /* route critical ints to normal ints */ *(vu_long *)MPC5XXX_ICTL_EXT |= 0x00000001; - early_init(); - return 0; } diff --git a/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx.h b/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx.h index d7d081137b..cef02d8b18 100644 --- a/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx.h +++ b/arch/ppc/mach-mpc5xxx/include/mach/mpc5xxx.h @@ -40,6 +40,8 @@ /* Exception offsets (PowerPC standard) */ #define EXC_OFF_SYS_RESET 0x0100 +#define CFG_MBAR 0xf0000000 + /* useful macros for manipulating CSx_START/STOP */ #if defined(CONFIG_MGT5100) #define START_REG(start) ((start) >> 15) @@ -779,6 +781,16 @@ struct mpc5xxx_mscan { /* function prototypes */ void loadtask(int basetask, int tasks); +/* retrieve configured sdram size connected to a chipselect */ +unsigned long mpc5200_get_sdram_size(unsigned int cs); + +/* configure a local plus bus chip select */ +#define MPC5200_BOOTCS 8 +void mpc5200_setup_cs(int cs, unsigned long start, unsigned long size, u32 cfg); + +/* configure bus speeds. Both dividers are relative to xlb clock */ +int mpc5200_setup_bus_clocks(unsigned int ipbdiv, unsigned long pcidiv); + #endif /* __ASSEMBLY__ */ #endif /* __ASMPPC_MPC5XXX_H */ diff --git a/arch/ppc/mach-mpc5xxx/interrupts.c b/arch/ppc/mach-mpc5xxx/interrupts.c index e484b6ecde..4838bc5f70 100644 --- a/arch/ppc/mach-mpc5xxx/interrupts.c +++ b/arch/ppc/mach-mpc5xxx/interrupts.c @@ -39,7 +39,7 @@ #include <common.h> #include <asm/processor.h> -#include <asm/io.h> +#include <io.h> #include <command.h> #include <mach/sdma.h> #include <asm/bitops.h> diff --git a/arch/ppc/mach-mpc5xxx/pci_mpc5200.c b/arch/ppc/mach-mpc5xxx/pci_mpc5200.c index a7de4a2268..d8f3b00759 100644 --- a/arch/ppc/mach-mpc5xxx/pci_mpc5200.c +++ b/arch/ppc/mach-mpc5xxx/pci_mpc5200.c @@ -26,7 +26,7 @@ #if defined(CONFIG_PCI) && defined(CONFIG_MPC5200) #include <asm/processor.h> -#include <asm/io.h> +#include <io.h> #include <pci.h> #include <mpc5xxx.h> diff --git a/arch/ppc/mach-mpc5xxx/start.S b/arch/ppc/mach-mpc5xxx/start.S index 8fca31b7a6..dc53c8a226 100644 --- a/arch/ppc/mach-mpc5xxx/start.S +++ b/arch/ppc/mach-mpc5xxx/start.S @@ -66,76 +66,32 @@ * Exception vectors */ .text + /* + * Second stage loader entry. When entered here we assume that spr 311 + * is set to the current MBAR address. + */ + mfspr r4, MBAR + b setup_mbar . = EXC_OFF_SYS_RESET .globl _start _start: - li r21, BOOTFLAG_COLD /* Normal Power-On */ - nop - b boot_cold - - . = EXC_OFF_SYS_RESET + 0x10 - - .globl _start_warm -_start_warm: - li r21, BOOTFLAG_WARM /* Software reboot */ - b boot_warm + /* + * Reset entry. When entered here we assume that MBAR is at reset default + * 0x80000000. + */ + lis r4, 0x80000000@h + ori r4, r4, 0x80000000@l -boot_cold: -boot_warm: +setup_mbar: + /* r4 == current MBAR */ mfmsr r5 /* save msr contents */ - /* Move CSBoot and adjust instruction pointer */ - /*--------------------------------------------------------------*/ - -#if defined(CFG_LOWBOOT) -# if defined(CFG_RAMBOOT) -# error CFG_LOWBOOT is incompatible with CFG_RAMBOOT -# endif /* CFG_RAMBOOT */ -# if defined(CONFIG_MGT5100) -# error CFG_LOWBOOT is incompatible with MGT5100 -# endif /* CONFIG_MGT5100 */ - lis r4, CFG_DEFAULT_MBAR@h - lis r3, START_REG(CFG_BOOTCS_START)@h - ori r3, r3, START_REG(CFG_BOOTCS_START)@l - stw r3, 0x4(r4) /* CS0 start */ - lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h - ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l - stw r3, 0x8(r4) /* CS0 stop */ - lis r3, 0x02010000@h - ori r3, r3, 0x02010000@l - stw r3, 0x54(r4) /* CS0 and Boot enable */ - - lis r3, lowboot_reentry@h /* jump from bootlow address space (0x0000xxxx) */ - ori r3, r3, lowboot_reentry@l /* to the address space the linker used */ - mtlr r3 - blr - -lowboot_reentry: - lis r3, START_REG(CFG_BOOTCS_START)@h - ori r3, r3, START_REG(CFG_BOOTCS_START)@l - stw r3, 0x4c(r4) /* Boot start */ - lis r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@h - ori r3, r3, STOP_REG(CFG_BOOTCS_START, CFG_BOOTCS_SIZE)@l - stw r3, 0x50(r4) /* Boot stop */ - lis r3, 0x02000001@h - ori r3, r3, 0x02000001@l - stw r3, 0x54(r4) /* Boot enable, CS0 disable */ -#endif /* CFG_LOWBOOT */ - -#if defined(CFG_DEFAULT_MBAR) && !defined(CFG_RAMBOOT) - lis r3, CFG_MBAR@h - ori r3, r3, CFG_MBAR@l -#if defined(CONFIG_MPC5200) - /* MBAR is mirrored into the MBAR SPR */ - mtspr MBAR,r3 + /* Switch MBAR to 0xf0000000 */ + lis r3, 0xf0000000@h + ori r3, r3, 0xf0000000@l + mtspr MBAR, r3 rlwinm r3, r3, 16, 16, 31 -#endif -#if defined(CONFIG_MGT5100) - rlwinm r3, r3, 17, 15, 31 -#endif - lis r4, CFG_DEFAULT_MBAR@h stw r3, 0(r4) -#endif /* CFG_DEFAULT_MBAR */ /* Initialise the MPC5xxx processor core */ /*--------------------------------------------------------------*/ @@ -146,9 +102,8 @@ lowboot_reentry: /*--------------------------------------------------------------*/ /* set up stack in on-chip SRAM */ - lis r3, (CFG_INIT_RAM_ADDR + CFG_INIT_RAM_SIZE)@h - ori r3, r3, (CFG_INIT_RAM_ADDR + CFG_INIT_RAM_SIZE)@l - subi r1, r3, CONFIG_EARLY_INITDATA_SIZE + lis r1, (MPC5XXX_SRAM + MPC5XXX_SRAM_SIZE)@h + ori r1, r1, (MPC5XXX_SRAM + MPC5XXX_SRAM_SIZE)@l li r0, 0 /* Make room for stack frame header and */ stwu r0, -4(r1) /* clear final stack frame so that */ stwu r0, -4(r1) /* stack backtraces terminate cleanly */ @@ -809,21 +764,6 @@ trap_reloc: blr - .globl reloc_offset -reloc_offset: - mfspr r4, LR - bl pc -pc: - mfspr r3, LR - mtspr LR, r4 - addi r4, r3, (_text_base - pc) - subi r3, r3, (pc - _start) - lwz r4, 0(r4) - - sub r3, r3, r4 - subi r3, r3, 0x100 - blr - .globl _text_base _text_base: .long TEXT_BASE diff --git a/arch/x86/boot/a20.c b/arch/x86/boot/a20.c index 4b61d91930..ddb40ee5c2 100644 --- a/arch/x86/boot/a20.c +++ b/arch/x86/boot/a20.c @@ -14,7 +14,7 @@ */ #include <asm/segment.h> -#include <asm/io.h> +#include <io.h> #include "boot.h" #define MAX_8042_LOOPS 100000 diff --git a/arch/x86/boot/prepare_uboot.c b/arch/x86/boot/prepare_uboot.c index a68aceddb6..79e6fb0cbe 100644 --- a/arch/x86/boot/prepare_uboot.c +++ b/arch/x86/boot/prepare_uboot.c @@ -13,7 +13,7 @@ */ #include <asm/segment.h> #include <asm/modes.h> -#include <asm/io.h> +#include <io.h> #include "boot.h" /* be aware of: */ diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h index 27ea642527..9cb78e41ec 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -10,6 +10,8 @@ #ifndef __ASM_X86_IO_H #define __ASM_X86_IO_H +#include <asm/byteorder.h> + static inline void outb(unsigned char value, int port) { asm volatile("outb %b0, %w1" : : "a"(value), "Nd"(port)); diff --git a/arch/x86/lib/memory.c b/arch/x86/lib/memory.c index 9496d2277f..fa7bc03962 100644 --- a/arch/x86/lib/memory.c +++ b/arch/x86/lib/memory.c @@ -27,7 +27,7 @@ #include <init.h> #include <stdio.h> -#include <mem_malloc.h> +#include <memory.h> #include <asm/syslib.h> #include <asm-generic/memory_layout.h> diff --git a/arch/x86/mach-i386/generic.c b/arch/x86/mach-i386/generic.c index edeacc4275..376de58964 100644 --- a/arch/x86/mach-i386/generic.c +++ b/arch/x86/mach-i386/generic.c @@ -23,7 +23,7 @@ * @brief x86 Architecture Initialization routines */ -#include <asm/io.h> +#include <io.h> /** to work with the 8250 UART driver implementation we need this function */ unsigned int x86_uart_read(unsigned long base, unsigned char reg_idx) diff --git a/arch/x86/mach-i386/pit_timer.c b/arch/x86/mach-i386/pit_timer.c index ec97cee49b..36019b0ede 100644 --- a/arch/x86/mach-i386/pit_timer.c +++ b/arch/x86/mach-i386/pit_timer.c @@ -32,7 +32,7 @@ #include <init.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> /** base address of the PIT in a standard PC */ #define PIT 0x40 diff --git a/commands/bootm.c b/commands/bootm.c index e5ffacb022..755932b505 100644 --- a/commands/bootm.c +++ b/commands/bootm.c @@ -95,16 +95,28 @@ fixup_silent_linux () } #endif /* CONFIG_SILENT_CONSOLE */ +struct image_handle_data* image_handle_data_get_by_num(struct image_handle* handle, int num) +{ + if (!handle || num < 0 || num >= handle->nb_data_entries) + return NULL; + + return &handle->data_entries[num]; +} + int relocate_image(struct image_handle *handle, void *load_address) { image_header_t *hdr = &handle->header; unsigned long len = image_get_size(hdr); - unsigned long data = (unsigned long)(handle->data); + struct image_handle_data *iha; + unsigned long data; #if defined CONFIG_CMD_BOOTM_ZLIB || defined CONFIG_CMD_BOOTM_BZLIB uint unc_len = CFG_BOOTM_LEN; #endif + iha = image_handle_data_get_by_num(handle, 0); + data = (unsigned long)(iha->data); + switch (image_get_comp(hdr)) { case IH_COMP_NONE: if(image_get_load(hdr) == data) { @@ -146,91 +158,32 @@ int relocate_image(struct image_handle *handle, void *load_address) } EXPORT_SYMBOL(relocate_image); -struct image_handle *map_image(const char *filename, int verify) +static LIST_HEAD(handler_list); + +int register_image_handler(struct image_handler *handler) +{ + list_add_tail(&handler->list, &handler_list); + return 0; +} + +/* + * generate a image_handle from a multi_image + * this image_handle can be free by unmap_image + */ +static struct image_handle *get_fake_image_handle(struct image_data *data, int num) { - int fd; - uint32_t checksum, len; struct image_handle *handle; + struct image_handle_data* iha; image_header_t *header; - fd = open(filename, O_RDONLY); - if (fd < 0) { - printf("could not open: %s\n", errno_str()); - return NULL; - } + iha = image_handle_data_get_by_num(data->os, num); handle = xzalloc(sizeof(struct image_handle)); header = &handle->header; - - if (read(fd, header, image_get_header_size()) < 0) { - printf("could not read: %s\n", errno_str()); - goto err_out; - } - - if (image_get_magic(header) != IH_MAGIC) { - puts ("Bad Magic Number\n"); - goto err_out; - } - - checksum = image_get_hcrc(header); - header->ih_hcrc = 0; - - if (crc32 (0, (uchar *)header, image_get_header_size()) != checksum) { - puts ("Bad Header Checksum\n"); - goto err_out; - } - len = image_get_size(header); - - handle->data = memmap(fd, PROT_READ); - if (handle->data == (void *)-1) { - handle->data = xmalloc(len); - handle->flags = IH_MALLOC; - if (read(fd, handle->data, len) < 0) { - printf("could not read: %s\n", errno_str()); - goto err_out; - } - } else { - handle->data = (void *)((unsigned long)handle->data + - image_get_header_size()); - } - - if (verify) { - puts (" Verifying Checksum ... "); - if (crc32 (0, handle->data, len) != image_get_dcrc(header)) { - printf ("Bad Data CRC\n"); - goto err_out; - } - puts ("OK\n"); - } - - image_print_contents(header); - - close(fd); + handle->data_entries = gen_image_handle_data(iha->data, iha->len); + handle->data = handle->data_entries[0].data; return handle; -err_out: - close(fd); - if (handle->flags & IH_MALLOC) - free(handle->data); - free(handle); - return NULL; -} -EXPORT_SYMBOL(map_image); - -void unmap_image(struct image_handle *handle) -{ - if (handle->flags & IH_MALLOC) - free(handle->data); - free(handle); -} -EXPORT_SYMBOL(unmap_image); - -static LIST_HEAD(handler_list); - -int register_image_handler(struct image_handler *handler) -{ - list_add_tail(&handler->list, &handler_list); - return 0; } static int initrd_handler_parse_options(struct image_data *data, int opt, @@ -239,7 +192,14 @@ static int initrd_handler_parse_options(struct image_data *data, int opt, switch(opt) { case 'r': printf("use initrd %s\n", optarg); - data->initrd = map_image(optarg, data->verify); + /* check for multi image @<num> */ + if (optarg[0] == '@') { + int num = simple_strtol(optarg + 1, NULL, 0); + + data->initrd = get_fake_image_handle(data, num); + } else { + data->initrd = map_image(optarg, data->verify); + } if (!data->initrd) return -1; return 0; diff --git a/common/Kconfig b/common/Kconfig index 422d1856b1..8e96920e48 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -42,6 +42,15 @@ config HAVE_NOSHELL menu "General Settings " +config LOCALVERSION + string "Local version - append to the version string" + help + Append an extra string to the end of your version string. + The string you set here will be appended after the contents of + any files with a filename matching localversion* in your + object and source tree, in that order. Your total string can + be a maximum of 64 characters. + config LOCALVERSION_AUTO bool "Automatically append version information to the version string" default y @@ -389,23 +398,6 @@ config CONSOLE_ACTIVATE_ALL Enabling this options activates all consoles on startup, so you will get output and a prompt on all consoles simultaneously. -config EARLY_CONSOLE_PORT - string - depends on HAS_EARLY_INIT - prompt "Console device for early output" - help - Choose the device on which you want to have early output printed - to. This is only used during startup when no device information - is available. - -config EARLY_CONSOLE_BAUDRATE - int - default 115200 - depends on HAS_EARLY_INIT - prompt "Early console baudrate" - help - Choose the baudrate for your early console. - config OF_FLAT_TREE bool prompt "Open Firmware flat device tree support" diff --git a/common/console.c b/common/console.c index 1f6ee93b4b..06e9c29e8c 100644 --- a/common/console.c +++ b/common/console.c @@ -29,7 +29,6 @@ #include <console.h> #include <driver.h> #include <fs.h> -#include <reloc.h> #include <init.h> #include <clock.h> #include <kfifo.h> @@ -42,10 +41,9 @@ LIST_HEAD(console_list); EXPORT_SYMBOL(console_list); #define CONSOLE_UNINITIALIZED 0 -#define CONSOLE_INIT_EARLY 1 -#define CONSOLE_INIT_FULL 2 +#define CONSOLE_INIT_FULL 1 -static int __early_initdata initialized = 0; +static int initialized = 0; static int console_std_set(struct device_d *dev, struct param_d *param, const char *val) @@ -163,10 +161,8 @@ int console_register(struct console_device *newcdev) console_output_buffer = NULL; } -#ifndef CONFIG_HAS_EARLY_INIT if (first) barebox_banner(); -#endif return 0; } @@ -250,26 +246,16 @@ int tstc(void) } EXPORT_SYMBOL(tstc); -#ifdef CONFIG_HAS_EARLY_INIT -static void __early_initdata *early_console_base; -#endif - void console_putc(unsigned int ch, char c) { struct console_device *cdev; - int init = INITDATA(initialized); + int init = initialized; switch (init) { case CONSOLE_UNINITIALIZED: kfifo_putc(console_output_buffer, c); return; -#ifdef CONFIG_HAS_EARLY_INIT - case CONSOLE_INIT_EARLY: - early_console_putc(INITDATA(early_console_base), c); - return; -#endif - case CONSOLE_INIT_FULL: for_each_console(cdev) { if (cdev->f_active & ch) { @@ -410,19 +396,3 @@ int ctrlc (void) } EXPORT_SYMBOL(ctrlc); #endif /* ARCH_HAS_CTRC */ - -#ifdef CONFIG_HAS_EARLY_INIT - -void early_console_start(const char *name, int baudrate) -{ - void *base = get_early_console_base(name); - - if (base) { - early_console_init(base, baudrate); - INITDATA(initialized) = CONSOLE_INIT_EARLY; - INITDATA(early_console_base) = base; - barebox_banner(); - } -} - -#endif diff --git a/common/dlmalloc.c b/common/dlmalloc.c index f9e1828cbf..7ad368ee53 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -2,7 +2,7 @@ #include <config.h> #include <malloc.h> #include <string.h> -#include <mem_malloc.h> +#include <memory.h> #include <stdio.h> #include <module.h> diff --git a/common/image.c b/common/image.c index a4c8b95210..4a6402d8b9 100644 --- a/common/image.c +++ b/common/image.c @@ -27,6 +27,10 @@ #include <common.h> #include <image.h> #include <rtc.h> +#include <errno.h> +#include <fcntl.h> +#include <malloc.h> +#include <fs.h> #else #include <time.h> #endif @@ -154,14 +158,14 @@ const char *image_get_comp_name(uint8_t comp) * returns: * number of components */ -ulong image_multi_count(const image_header_t *hdr) +ulong image_multi_count(void *data) { ulong i, count = 0; uint32_t *size; /* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ - size = (uint32_t *)image_get_data (hdr); + size = (uint32_t *)data; /* count non empty slots */ for (i = 0; size[i]; ++i) @@ -187,23 +191,23 @@ ulong image_multi_count(const image_header_t *hdr) * data address and size of the component, if idx is valid * 0 in data and len, if idx is out of range */ -void image_multi_getimg(const image_header_t *hdr, ulong idx, - ulong *data, ulong *len) +void image_multi_getimg(void *data, ulong idx, + ulong *img_data, ulong *len) { int i; uint32_t *size; - ulong offset, count, img_data; + ulong offset, count, tmp_img_data; /* get number of component */ - count = image_multi_count(hdr); + count = image_multi_count(data); /* get start of the image payload, which in case of multi * component images that points to a table of component sizes */ - size = (uint32_t *)image_get_data(hdr); + size = (uint32_t *)data; /* get address of the proper component data start, which means * skipping sizes table (add 1 for last, null entry) */ - img_data = image_get_data(hdr) + (count + 1) * sizeof (uint32_t); + tmp_img_data = (ulong)data + (count + 1) * sizeof (uint32_t); if (idx < count) { *len = uimage_to_cpu(size[idx]); @@ -216,10 +220,10 @@ void image_multi_getimg(const image_header_t *hdr, ulong idx, } /* calculate idx-th component data address */ - *data = img_data + offset; + *img_data = tmp_img_data + offset; } else { *len = 0; - *data = 0; + *img_data = 0; } } @@ -262,9 +266,8 @@ void image_print_size(uint32_t size) #endif } -void image_print_contents(const void *ptr) +void image_print_contents(const image_header_t *hdr, void *data) { - const image_header_t *hdr = (const image_header_t *)ptr; const char *p; int type; @@ -289,12 +292,12 @@ void image_print_contents(const void *ptr) type = image_get_type(hdr); if (type == IH_TYPE_MULTI || type == IH_TYPE_SCRIPT) { int i; - ulong data, len; - ulong count = image_multi_count(hdr); + ulong img_data, len; + ulong count = image_multi_count(data); printf ("%sContents:\n", p); for (i = 0; i < count; i++) { - image_multi_getimg(hdr, i, &data, &len); + image_multi_getimg(data, i, &img_data, &len); printf("%s Image %d: ", p, i); image_print_size(len); @@ -305,8 +308,125 @@ void image_print_contents(const void *ptr) * if planning to do something with * multiple files */ - printf("%s Offset = 0x%08lx\n", p, data); + printf("%s Offset = 0x%08lx\n", p, img_data); } } } } + +#ifdef __BAREBOX__ +struct image_handle *map_image(const char *filename, int verify) +{ + int fd; + uint32_t checksum, len; + struct image_handle *handle; + image_header_t *header; + int type; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("could not open: %s\n", errno_str()); + return NULL; + } + + handle = xzalloc(sizeof(struct image_handle)); + header = &handle->header; + + if (read(fd, header, image_get_header_size()) < 0) { + printf("could not read: %s\n", errno_str()); + goto err_out; + } + + if (image_get_magic(header) != IH_MAGIC) { + puts ("Bad Magic Number\n"); + goto err_out; + } + + checksum = image_get_hcrc(header); + header->ih_hcrc = 0; + + if (crc32 (0, (uchar *)header, image_get_header_size()) != checksum) { + puts ("Bad Header Checksum\n"); + goto err_out; + } + len = image_get_size(header); + + handle->data = memmap(fd, PROT_READ); + if (handle->data == (void *)-1) { + handle->data = xmalloc(len); + handle->flags = IH_MALLOC; + if (read(fd, handle->data, len) < 0) { + printf("could not read: %s\n", errno_str()); + goto err_out; + } + } else { + handle->data = (void *)((unsigned long)handle->data + + image_get_header_size()); + } + + type = image_get_type(header); + if (type == IH_TYPE_MULTI) { + struct image_handle_data *data_entries; + int i; + ulong img_data; + ulong count = image_multi_count(handle->data); + + data_entries = xzalloc(sizeof(struct image_handle_data) * count); + + for (i = 0; i < count; i++) { + image_multi_getimg(handle->data, i, &img_data, + &data_entries[i].len); + + data_entries[i].data = (void*)img_data; + } + handle->data_entries = data_entries; + handle->nb_data_entries = count; + } else { + handle->data_entries = gen_image_handle_data(handle->data, len); + handle->nb_data_entries = 1; + } + + if (verify) { + puts (" Verifying Checksum ... "); + if (crc32 (0, handle->data, len) != image_get_dcrc(header)) { + printf ("Bad Data CRC\n"); + goto err_out; + } + puts ("OK\n"); + } + + image_print_contents(header, handle->data); + + close(fd); + + return handle; +err_out: + close(fd); + if (handle->flags & IH_MALLOC) + free(handle->data); + free(handle); + return NULL; +} +EXPORT_SYMBOL(map_image); + +void unmap_image(struct image_handle *handle) +{ + if (handle->flags & IH_MALLOC) + free(handle->data); + free(handle->data_entries); + free(handle); +} +EXPORT_SYMBOL(unmap_image); + +struct image_handle_data * gen_image_handle_data(void* data, ulong len) +{ + struct image_handle_data *iha; + + iha = xzalloc(sizeof(struct image_handle_data)); + iha->data = data; + iha->len = len; + + return iha; +} +EXPORT_SYMBOL(gen_image_handle_data); +#endif diff --git a/common/memory.c b/common/memory.c index 8f4a7681b0..4d59f15fec 100644 --- a/common/memory.c +++ b/common/memory.c @@ -21,6 +21,7 @@ */ #include <common.h> +#include <memory.h> /* * Begin and End of memory area for malloc(), and current "brk" @@ -69,3 +70,20 @@ void *sbrk(ptrdiff_t increment) return old; } + +LIST_HEAD(memory_banks); + +void barebox_add_memory_bank(const char *name, resource_size_t start, + resource_size_t size) +{ + struct memory_bank *bank = xzalloc(sizeof(*bank)); + struct device_d *dev; + + dev = add_mem_device(name, start, size, IORESOURCE_MEM_WRITEABLE); + + bank->dev = dev; + bank->start = start; + bank->size = size; + + list_add_tail(&bank->list, &memory_banks); +} diff --git a/common/startup.c b/common/startup.c index bf67aef152..13783fb27a 100644 --- a/common/startup.c +++ b/common/startup.c @@ -33,12 +33,11 @@ #include <init.h> #include <command.h> #include <malloc.h> -#include <mem_malloc.h> +#include <memory.h> #include <debug_ll.h> #include <fs.h> #include <linux/stat.h> #include <environment.h> -#include <reloc.h> #include <asm-generic/memory_layout.h> #include <asm/sections.h> @@ -62,23 +61,6 @@ static void display_meminfo(void) #endif } -#ifdef CONFIG_HAS_EARLY_INIT - -#define EARLY_INITDATA (CFG_INIT_RAM_ADDR + CFG_INIT_RAM_SIZE \ - - CONFIG_EARLY_INITDATA_SIZE) - -void *init_data_ptr = (void *)EARLY_INITDATA; - -void early_init (void) -{ - /* copy the early initdata segment to early init RAM */ - memcpy((void *)EARLY_INITDATA, RELOC(&__early_init_data_begin), - (ulong)&__early_init_data_end - - (ulong)&__early_init_data_begin); -} - -#endif /* CONFIG_HAS_EARLY_INIT */ - #ifdef CONFIG_DEFAULT_ENVIRONMENT #include <generated/barebox_default_env.h> @@ -112,16 +94,6 @@ void start_barebox (void) struct stat s; #endif -#ifdef CONFIG_HAS_EARLY_INIT - /* We are running from RAM now, copy early initdata from - * early RAM to RAM - */ - memcpy(&__early_init_data_begin, init_data_ptr, - (ulong)&__early_init_data_end - - (ulong)&__early_init_data_begin); - init_data_ptr = &__early_init_data_begin; -#endif /* CONFIG_HAS_EARLY_INIT */ - for (initcall = __barebox_initcalls_start; initcall < __barebox_initcalls_end; initcall++) { PUTS_LL("<<"); diff --git a/common/version.c b/common/version.c index 945475fc3d..0af8ec160a 100644 --- a/common/version.c +++ b/common/version.c @@ -1,5 +1,4 @@ #include <common.h> -#include <reloc.h> #include <generated/utsrelease.h> const char version_string[] = @@ -7,7 +6,7 @@ const char version_string[] = void barebox_banner (void) { - printf (RELOC("\n\n%s\n\n"), RELOC_VAR(version_string)); - printf(RELOC("Board: " CONFIG_BOARDINFO "\n")); + printf("\n\n%s\n\n", version_string); + printf("Board: " CONFIG_BOARDINFO "\n"); } diff --git a/defaultenv/bin/_update_help b/defaultenv/bin/_update_help index 98096daecc..92d677234a 100644 --- a/defaultenv/bin/_update_help +++ b/defaultenv/bin/_update_help @@ -7,7 +7,7 @@ echo "options" echo " -c to check the crc32 for the image and flashed one" echo "" echo "default mode is tftp" -echo "type update -t kernel -d <nor|nand> [-m tftp|xmodem] [-f imagename] to update kernel into flash" +echo "type update -t kernel -d <nor|nand|disk> [-m tftp|xmodem] [-f imagename] to update kernel into flash" echo "type update -t rootfs -d <nor|nand> [-m tftp|xmodem] [-f imagename] to update rootfs into flash" echo "type update -t barebox -d <nor|nand> [-m tftp|xmodem] [-f imagename] to update barebox into flash" echo "type update -t bareboxenv -d <nor|nand> [-m tftp|xmodem] [-f imagename] to update bareboxenv into flash" diff --git a/defaultenv/bin/boot b/defaultenv/bin/boot index de4fa24f27..652ae0c2ba 100644 --- a/defaultenv/bin/boot +++ b/defaultenv/bin/boot @@ -2,6 +2,10 @@ . /env/config +if [ x$kernel_loc = xnet ]; then + kernel_loc=tftp +fi + if [ x$1 = xnand ]; then rootfs_loc=nand kernel_loc=nand @@ -14,6 +18,9 @@ elif [ x$1 = xnfs ]; then elif [ x$1 = xtftp ]; then rootfs_loc=net kernel_loc=tftp +elif [ x$1 = xdisk ]; then + rootfs_loc=disk + kernel_loc=disk fi if [ x$ip = xdhcp ]; then @@ -21,12 +28,14 @@ if [ x$ip = xdhcp ]; then elif [ x$ip = xnone ]; then bootargs="$bootargs ip=none" else - bootargs="$bootargs ip=$eth0.ipaddr::$eth0.gateway:$eth0.netmask:::" + bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask::eth0:" fi if [ x$rootfs_loc = xnet ]; then bootargs="$bootargs root=/dev/nfs nfsroot=$nfsroot,v3,tcp noinitrd" +elif [ x$rootfs_loc = xdisk ]; then + bootargs="$bootargs root=/dev/$rootfs_part_linux_dev rootfstype=$rootfs_type noinitrd rootwait" elif [ x$rootfs_loc = xinitrd ]; then bootargs="$bootargs root=/dev/ram0 rdinit=/sbin/init" else @@ -74,7 +83,7 @@ if [ ! -e /dev/ram0.kernel ]; then addpart /dev/ram0 8M@8M(kernel) fi -if [ x$kernel_loc = xnfs ] || [ x$kernel_loc = xtftp ]; then +if [ x$kernel_loc = xnfs -o x$kernel_loc = xtftp ]; then if [ x$ip = xdhcp ]; then dhcp fi @@ -96,8 +105,10 @@ elif [ x$kernel_loc = xnor ]; then kdev="/dev/nor0.kernel" elif [ x$kernel_loc = xnand ]; then kdev="/dev/nand0.kernel.bb" +elif [ x$kernel_loc = xdisk ]; then + kdev="/dev/$kernel_part" else - echo "error: set kernel_loc to one of 'nfs', 'tftp', 'nand' or 'nor'" + echo "error: set kernel_loc to one of 'tftp', 'nfs', 'nand', 'nor' or 'disk'" exit 1 fi diff --git a/defaultenv/bin/update b/defaultenv/bin/update index 55ac10b95d..39e759145f 100644 --- a/defaultenv/bin/update +++ b/defaultenv/bin/update @@ -27,17 +27,18 @@ done if [ x${type} = xkernel ]; then image=$kernelimage + disk_part=$kernel_part elif [ x${type} = xrootfs ]; then image=$rootfsimage type=root elif [ x${type} = xbarebox ]; then image=$bareboximage - if [ x${image} = x ]; then + if [ -z ${image} ]; then image=barebox.bin fi elif [ x${type} = xbareboxenv ]; then image=$bareboxenvimage - if [ x${image} = x ]; then + if [ -z ${image} ]; then image=bareboxenv.bin fi elif [ x${type} = xxload ]; then @@ -47,7 +48,7 @@ else exit 1 fi -if [ x${imagename} != x ]; then +if [ -n ${imagename} ]; then image=${imagename} fi @@ -55,12 +56,14 @@ if [ x${device_type} = xnand ]; then part=/dev/nand0.${type}.bb elif [ x${device_type} = xnor ]; then part=/dev/nor0.${type} +elif [ x${device_type} = xdisk ]; then + part=/dev/${disk_part} else . /env/bin/_update_help exit 1 fi -if [ x${mode} != xtftp ] && [ x${mode} != xxmodem ] ; then +if [ x${mode} != xtftp -a x${mode} != xxmodem ] ; then echo "unsupported mode ${mode}." . /env/bin/_update_help exit 1 diff --git a/defaultenv/config b/defaultenv/config new file mode 100644 index 0000000000..0aaead5ccb --- /dev/null +++ b/defaultenv/config @@ -0,0 +1,69 @@ +#!/bin/sh + +machine=FIXME +#user= + +# Enter MAC address here if not retrieved automatically +#eth0.ethaddr=de:ad:be:ef:00:00 + +# use 'dhcp' to do dhcp in barebox and in kernel +# use 'none' if you want to skip kernel ip autoconfiguration +ip=dhcp + +# or set your networking parameters here +#eth0.ipaddr=a.b.c.d +#eth0.netmask=a.b.c.d +#eth0.serverip=a.b.c.d +#eth0.gateway=a.b.c.d + +# can be either 'tftp', 'nfs', 'nand', 'nor' or 'disk' +kernel_loc=tftp +# can be either 'net', 'nand', 'nor', 'disk' or 'initrd' +rootfs_loc=net + +# for flash based rootfs: 'jffs2' or 'ubifs' +# in case of disk any regular filesystem like 'ext2', 'ext3', 'reiserfs' +rootfs_type=ubifs +# where is the rootfs in case of 'rootfs_loc=disk' (linux name) +rootfs_part_linux_dev=mmcblk0p4 +rootfsimage=rootfs-${machine}.$rootfs_type + +# where is the kernel image in case of 'kernel_loc=disk' +kernel_part=disk0.2 + +# The image type of the kernel. Can be uimage, zimage, raw, or raw_lzo +kernelimage_type=zimage +kernelimage=zImage-$machine +#kernelimage_type=uimage +#kernelimage=uImage-$machine +#kernelimage_type=raw +#kernelimage=Image-$machine +#kernelimage_type=raw_lzo +#kernelimage=Image-$machine.lzo + +bareboximage=barebox-${machine}.bin +bareboxenvimage=barebox-${machine}.bin + +if [ -n $user ]; then + bareboximage="$user"-"$bareboximage" + bareboxenvimage="$user"-"$bareboxenvimage" + kernelimage="$user"-"$kernelimage" + rootfsimage="$user"-"$rootfsimage" + nfsroot="/home/$user/nfsroot/$machine" +else + nfsroot="/path/to/nfs/root" +fi + +autoboot_timeout=3 + +bootargs="console=ttyFIXME,115200" + +nor_parts="256k(barebox)ro,128k(bareboxenv),3M(kernel),-(root)" +rootfs_mtdblock_nor=3 + +nand_parts="256k(barebox)ro,128k(bareboxenv),3M(kernel),-(root)" +nand_device="FIXME" +rootfs_mtdblock_nand=7 + +# set a fancy prompt (if support is compiled in) +PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m " diff --git a/drivers/base/resource.c b/drivers/base/resource.c index 175beb9c2d..5c9c16c591 100644 --- a/drivers/base/resource.c +++ b/drivers/base/resource.c @@ -41,33 +41,42 @@ struct device_d *add_generic_device(const char* devname, int id, const char *res resource_size_t start, resource_size_t size, unsigned int flags, void *pdata) { + struct resource *res; + + res = xzalloc(sizeof(struct resource)); + if (resname) + res[0].name = xstrdup(resname); + res[0].start = start; + res[0].size = size; + res[0].flags = flags; + + return add_generic_device_res(devname, id, res, 1, pdata); +} +EXPORT_SYMBOL(add_generic_device); + +struct device_d *add_generic_device_res(const char* devname, int id, + struct resource *res, int nb, void *pdata) +{ struct device_d *dev; dev = alloc_device(devname, id, pdata); - dev->resource = xzalloc(sizeof(struct resource)); - dev->num_resources = 1; - if (resname) - dev->resource[0].name = xstrdup(resname); - dev->resource[0].start = start; - dev->resource[0].size = size; - dev->resource[0].flags = flags; + dev->resource = res; + dev->num_resources = nb; register_device(dev); return dev; } -EXPORT_SYMBOL(add_generic_device); +EXPORT_SYMBOL(add_generic_device_res); #ifdef CONFIG_DRIVER_NET_DM9000 struct device_d *add_dm9000_device(int id, resource_size_t base, resource_size_t data, int flags, void *pdata) { - struct device_d *dev; + struct resource *res; resource_size_t size; - dev = alloc_device("dm9000", id, pdata); - dev->resource = xzalloc(sizeof(struct resource) * 2); - dev->num_resources = 2; + res = xzalloc(sizeof(struct resource) * 2); switch (flags) { case IORESOURCE_MEM_32BIT: @@ -84,16 +93,14 @@ struct device_d *add_dm9000_device(int id, resource_size_t base, return NULL; } - dev->resource[0].start = base; - dev->resource[0].size = size; - dev->resource[0].flags = IORESOURCE_MEM | flags; - dev->resource[1].start = data; - dev->resource[1].size = size; - dev->resource[1].flags = IORESOURCE_MEM | flags; + res[0].start = base; + res[0].size = size; + res[0].flags = IORESOURCE_MEM | flags; + res[1].start = data; + res[1].size = size; + res[1].flags = IORESOURCE_MEM | flags; - register_device(dev); - - return dev; + return add_generic_device_res("dm9000", id, res, 2, pdata); } EXPORT_SYMBOL(add_dm9000_device); #endif @@ -102,34 +109,15 @@ EXPORT_SYMBOL(add_dm9000_device); struct device_d *add_usb_ehci_device(int id, resource_size_t hccr, resource_size_t hcor, void *pdata) { - struct device_d *dev; - - dev = alloc_device("ehci", id, pdata); - dev->resource = xzalloc(sizeof(struct resource) * 2); - dev->num_resources = 2; - dev->resource[0].start = hccr; - dev->resource[0].flags = IORESOURCE_MEM; - dev->resource[1].start = hcor; - dev->resource[1].flags = IORESOURCE_MEM; + struct resource *res; - register_device(dev); + res = xzalloc(sizeof(struct resource) * 2); + res[0].start = hccr; + res[0].flags = IORESOURCE_MEM; + res[1].start = hcor; + res[1].flags = IORESOURCE_MEM; - return dev; + return add_generic_device_res("ehci", id, res, 2, pdata); } EXPORT_SYMBOL(add_usb_ehci_device); #endif - -#ifdef CONFIG_ARM -#include <asm/armlinux.h> - -struct device_d *arm_add_mem_device(const char* name, resource_size_t start, - resource_size_t size) -{ - struct device_d *dev; - - dev = add_mem_device(name, start, size, IORESOURCE_MEM_WRITEABLE); - armlinux_add_dram(dev); - - return dev; -} -#endif diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c index 2d075f72ca..da6218f43c 100644 --- a/drivers/i2c/busses/i2c-imx.c +++ b/drivers/i2c/busses/i2c-imx.c @@ -44,7 +44,7 @@ #include <linux/err.h> -#include <asm/io.h> +#include <io.h> #include <i2c/i2c.h> #include <mach/generic.h> #include <mach/clock.h> @@ -314,19 +314,21 @@ static int i2c_imx_write(struct i2c_adapter *adapter, struct i2c_msg *msgs) void __iomem *base = i2c_imx->base; int i, result; - dev_dbg(adapter->dev, - "<%s> write slave address: addr=0x%02x\n", - __func__, msgs->addr << 1); + if ( !(msgs->flags & I2C_M_DATA_ONLY) ) { + dev_dbg(adapter->dev, + "<%s> write slave address: addr=0x%02x\n", + __func__, msgs->addr << 1); - /* write slave address */ - writeb(msgs->addr << 1, base + IMX_I2C_I2DR); + /* write slave address */ + writeb(msgs->addr << 1, base + IMX_I2C_I2DR); - result = i2c_imx_trx_complete(adapter); - if (result) - return result; - result = i2c_imx_acked(adapter); - if (result) - return result; + result = i2c_imx_trx_complete(adapter); + if (result) + return result; + result = i2c_imx_acked(adapter); + if (result) + return result; + } /* write data */ for (i = 0; i < msgs->len; i++) { @@ -352,22 +354,24 @@ static int i2c_imx_read(struct i2c_adapter *adapter, struct i2c_msg *msgs) int i, result; unsigned int temp; - dev_dbg(adapter->dev, - "<%s> write slave address: addr=0x%02x\n", - __func__, (msgs->addr << 1) | 0x01); - /* clear IIF */ writeb(0x0, base + IMX_I2C_I2SR); - /* write slave address */ - writeb((msgs->addr << 1) | 0x01, base + IMX_I2C_I2DR); + if ( !(msgs->flags & I2C_M_DATA_ONLY) ) { + dev_dbg(adapter->dev, + "<%s> write slave address: addr=0x%02x\n", + __func__, (msgs->addr << 1) | 0x01); - result = i2c_imx_trx_complete(adapter); - if (result) - return result; - result = i2c_imx_acked(adapter); - if (result) - return result; + /* write slave address */ + writeb((msgs->addr << 1) | 0x01, base + IMX_I2C_I2DR); + + result = i2c_imx_trx_complete(adapter); + if (result) + return result; + result = i2c_imx_acked(adapter); + if (result) + return result; + } /* setup bus to read data */ temp = readb(base + IMX_I2C_I2CR); @@ -428,7 +432,7 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter, /* read/write data */ for (i = 0; i < num; i++) { - if (i) { + if (i && !(msgs[i].flags & I2C_M_DATA_ONLY)) { temp = readb(base + IMX_I2C_I2CR); temp |= I2CR_RSTA; writeb(temp, base + IMX_I2C_I2CR); diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 95c4fdf782..2a1ae7af75 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -43,7 +43,7 @@ #include <linux/err.h> -#include <asm/io.h> +#include <io.h> #include <i2c/i2c.h> #include <mach/generic.h> #include <mach/omap3-clock.h> diff --git a/drivers/mci/atmel_mci.c b/drivers/mci/atmel_mci.c index 71aec16fa2..4a29cad18f 100644 --- a/drivers/mci/atmel_mci.c +++ b/drivers/mci/atmel_mci.c @@ -20,9 +20,10 @@ #include <errno.h> #include <clock.h> #include <gpio.h> -#include <asm/io.h> +#include <io.h> #include <mach/board.h> #include <linux/clk.h> +#include <linux/err.h> #include "at91_mci.h" @@ -461,9 +462,9 @@ static int mci_probe(struct device_d *hw_dev) host->hw_dev = hw_dev; hw_dev->priv = host; host->clk = clk_get(hw_dev, "mci_clk"); - if (host->clk == NULL) { + if (IS_ERR(host->clk)) { dev_err(hw_dev, "no mci_clk\n"); - return -EINVAL; + return PTR_ERR(host->clk); } clk_rate = clk_get_rate(host->clk); diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c index 358f0dc25c..a0e61f0d01 100644 --- a/drivers/mci/imx-esdhc.c +++ b/drivers/mci/imx-esdhc.c @@ -32,7 +32,7 @@ #include <malloc.h> #include <mci.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <asm/mmu.h> #include <mach/clock.h> #include <mach/generic.h> diff --git a/drivers/mci/imx.c b/drivers/mci/imx.c index 905c251db3..50c98e1cef 100644 --- a/drivers/mci/imx.c +++ b/drivers/mci/imx.c @@ -26,7 +26,7 @@ #include <init.h> #include <driver.h> #include <mach/clock.h> -#include <asm/io.h> +#include <io.h> #define DRIVER_NAME "imx-mmc" diff --git a/drivers/mci/mxs.c b/drivers/mci/mxs.c index eda9250885..4b8bd75b34 100644 --- a/drivers/mci/mxs.c +++ b/drivers/mci/mxs.c @@ -39,7 +39,7 @@ #include <mci.h> #include <errno.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <asm/bitops.h> #include <mach/imx-regs.h> #include <mach/mci.h> diff --git a/drivers/mci/omap_hsmmc.c b/drivers/mci/omap_hsmmc.c index 5fdf445c70..3f70e22629 100644 --- a/drivers/mci/omap_hsmmc.c +++ b/drivers/mci/omap_hsmmc.c @@ -29,7 +29,9 @@ #include <mci.h> #include <clock.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> + +#include <mach/omap_hsmmc.h> struct hsmmc { unsigned char res1[0x10]; @@ -549,6 +551,7 @@ static void mmc_set_ios(struct mci_host *mci, struct device_d *dev, static int omap_mmc_probe(struct device_d *dev) { struct omap_hsmmc *hsmmc; + struct omap_hsmmc_platform_data *pdata; hsmmc = xzalloc(sizeof(*hsmmc)); @@ -564,7 +567,12 @@ static int omap_mmc_probe(struct device_d *dev) hsmmc->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34; hsmmc->mci.f_min = 400000; - hsmmc->mci.f_max = 52000000; + + pdata = (struct omap_hsmmc_platform_data *)dev->platform_data; + if (pdata->f_max) + hsmmc->mci.f_max = pdata->f_max; + else + hsmmc->mci.f_max = 52000000; mci_register(&hsmmc->mci); diff --git a/drivers/mci/s3c.c b/drivers/mci/s3c.c index c621445e5c..f97e13a6dd 100644 --- a/drivers/mci/s3c.c +++ b/drivers/mci/s3c.c @@ -39,7 +39,7 @@ #include <mci.h> #include <errno.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <mach/mci.h> #include <mach/s3c24xx-generic.h> #include <mach/s3c24x0-iomap.h> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c index f79be9a3c6..8cc1b51f7f 100644 --- a/drivers/mtd/nand/atmel_nand.c +++ b/drivers/mtd/nand/atmel_nand.c @@ -31,7 +31,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> -#include <asm/io.h> +#include <io.h> #include <mach/board.h> #include <errno.h> @@ -399,13 +399,13 @@ static int __init atmel_nand_probe(struct device_d *dev) if (host->board->rdy_pin) nand_chip->dev_ready = atmel_nand_device_ready; - nand_chip->ecc.mode = pdata->ecc_mode; + nand_chip->ecc.mode = NAND_ECC_SOFT; if (pdata->ecc_mode == NAND_ECC_HW) { - if (!pdata->ecc_base) - return -ENODEV; + host->ecc = dev_request_mem_region(dev, 1); - host->ecc = pdata->ecc_base; + if (!host->ecc) + return -ENODEV; nand_chip->ecc.mode = NAND_ECC_HW; nand_chip->ecc.calculate = atmel_nand_calculate; diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index e762524540..2433945571 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -29,7 +29,7 @@ #include <linux/delay.h> #include <linux/rslib.h> #include <linux/moduleparam.h> -#include <asm/io.h> +#include <io.h> #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5e122a10a5..2710f6a309 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -39,7 +39,7 @@ #include <linux/err.h> #include <linux/mtd/nand_ecc.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include <module.h> diff --git a/drivers/mtd/nand/nand_hwecc.c b/drivers/mtd/nand/nand_hwecc.c index 95b08d3a79..5ead49c60c 100644 --- a/drivers/mtd/nand/nand_hwecc.c +++ b/drivers/mtd/nand/nand_hwecc.c @@ -6,7 +6,7 @@ #include <linux/err.h> #include <linux/mtd/nand_ecc.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include "nand.h" diff --git a/drivers/mtd/nand/nand_hwecc_syndrome.c b/drivers/mtd/nand/nand_hwecc_syndrome.c index 9a66180952..dd067c9970 100644 --- a/drivers/mtd/nand/nand_hwecc_syndrome.c +++ b/drivers/mtd/nand/nand_hwecc_syndrome.c @@ -6,7 +6,7 @@ #include <linux/err.h> #include <linux/mtd/nand_ecc.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include <module.h> diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c index e471c8a719..581136aed4 100644 --- a/drivers/mtd/nand/nand_imx.c +++ b/drivers/mtd/nand/nand_imx.c @@ -27,7 +27,7 @@ #include <mach/generic.h> #include <mach/imx-nand.h> #include <mach/imx-regs.h> -#include <asm/io.h> +#include <io.h> #include <errno.h> #define NFC_V3_FLASH_CMD (host->regs_axi + 0x00) @@ -1034,9 +1034,6 @@ static int __init imxnd_probe(struct device_d *dev) return -ENOMEM; host->data_buf = (uint8_t *)(host + 1); - host->base = dev_request_mem_region(dev, 0); - - host->main_area0 = host->base; if (nfc_is_v1() || nfc_is_v21()) { host->preset = preset_v1_v2; @@ -1049,21 +1046,32 @@ static int __init imxnd_probe(struct device_d *dev) } if (nfc_is_v21()) { + host->base = dev_request_mem_region(dev, 0); + host->main_area0 = host->base; host->regs = host->base + 0x1e00; host->spare0 = host->base + 0x1000; host->spare_len = 64; oob_smallpage = &nandv2_hw_eccoob_smallpage; oob_largepage = &nandv2_hw_eccoob_largepage; } else if (nfc_is_v1()) { + host->base = dev_request_mem_region(dev, 0); + host->main_area0 = host->base; host->regs = host->base + 0xe00; host->spare0 = host->base + 0x800; host->spare_len = 16; oob_smallpage = &nandv1_hw_eccoob_smallpage; oob_largepage = &nandv1_hw_eccoob_largepage; } else if (nfc_is_v3_2()) { -#ifdef CONFIG_ARCH_IMX51 - host->regs_ip = (void *)MX51_NFC_BASE_ADDR; -#endif + host->regs_ip = dev_request_mem_region(dev, 0); + host->base = dev_request_mem_region(dev, 1); + host->main_area0 = host->base; + + if (!host->regs_ip) { + dev_err(dev, "no second mem region\n"); + err = -ENODEV; + goto escan; + } + host->regs_axi = host->base + 0x1e00; host->spare0 = host->base + 0x1000; host->spare_len = 64; @@ -1083,6 +1091,7 @@ static int __init imxnd_probe(struct device_d *dev) this = &host->nand; mtd = &host->mtd; mtd->priv = this; + mtd->dev = dev; /* 50 us command delay time */ this->chip_delay = 5; diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c index 083aa57520..a012c03dec 100644 --- a/drivers/mtd/nand/nand_omap_gpmc.c +++ b/drivers/mtd/nand/nand_omap_gpmc.c @@ -71,7 +71,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> #include <linux/mtd/nand_ecc.h> -#include <asm/io.h> +#include <io.h> #include <mach/silicon.h> #include <mach/gpmc.h> #include <mach/gpmc_nand.h> diff --git a/drivers/mtd/nand/nand_s3c2410.c b/drivers/mtd/nand/nand_s3c2410.c index 0ce20d42c3..c5f5d97db3 100644 --- a/drivers/mtd/nand/nand_s3c2410.c +++ b/drivers/mtd/nand/nand_s3c2410.c @@ -33,7 +33,7 @@ #include <mach/s3c24xx-generic.h> #include <mach/s3c24x0-iomap.h> #include <mach/s3c24x0-nand.h> -#include <asm/io.h> +#include <io.h> #include <asm-generic/errno.h> #ifdef CONFIG_S3C24XX_NAND_BOOT diff --git a/drivers/mtd/nand/nand_swecc.c b/drivers/mtd/nand/nand_swecc.c index 93511cbe3d..a5edffaece 100644 --- a/drivers/mtd/nand/nand_swecc.c +++ b/drivers/mtd/nand/nand_swecc.c @@ -6,7 +6,7 @@ #include <linux/err.h> #include <linux/mtd/nand_ecc.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include "nand.h" diff --git a/drivers/mtd/nand/nand_write.c b/drivers/mtd/nand/nand_write.c index 3ede8d02f0..13b6c8984f 100644 --- a/drivers/mtd/nand/nand_write.c +++ b/drivers/mtd/nand/nand_write.c @@ -6,7 +6,7 @@ #include <linux/err.h> #include <linux/mtd/nand_ecc.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include <module.h> diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c index 3073011614..c1e93ad076 100644 --- a/drivers/mtd/nand/nomadik_nand.c +++ b/drivers/mtd/nand/nomadik_nand.c @@ -30,7 +30,7 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/nand.h> -#include <asm/io.h> +#include <io.h> #include <mach/nand.h> #include <mach/fsmc.h> diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c index 7e456c762e..5163488183 100644 --- a/drivers/net/altera_tse.c +++ b/drivers/net/altera_tse.c @@ -31,7 +31,7 @@ #include <clock.h> #include <linux/mii.h> -#include <asm/io.h> +#include <io.h> #include <asm/dma-mapping.h> #include "altera_tse.h" diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c index 33afc5e0f3..da23755a5e 100644 --- a/drivers/net/cs8900.c +++ b/drivers/net/cs8900.c @@ -27,7 +27,7 @@ #include <net.h> #include <malloc.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #include <errno.h> /* I/O ports for I/O Space operation */ diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index e9ec61b37d..f32778135d 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -50,7 +50,7 @@ #include <malloc.h> #include <net.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <xfuncs.h> #include <dm9000.h> #include <errno.h> diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c index 954ec789f3..227e317492 100644 --- a/drivers/net/ep93xx.c +++ b/drivers/net/ep93xx.c @@ -35,7 +35,7 @@ #include <init.h> #include <malloc.h> #include <miidev.h> -#include <asm/io.h> +#include <io.h> #include <linux/types.h> #include <mach/ep93xx-regs.h> #include "ep93xx.h" diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c index 3b0f266a2b..ae63fdc3b5 100644 --- a/drivers/net/fec_imx.c +++ b/drivers/net/fec_imx.c @@ -28,7 +28,7 @@ #include <fec.h> #include <asm/mmu.h> -#include <asm/io.h> +#include <io.h> #include <mach/generic.h> #include <mach/imx-regs.h> #include <clock.h> diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c index 403aad5235..001a3a0355 100644 --- a/drivers/net/fec_mpc5200.c +++ b/drivers/net/fec_mpc5200.c @@ -697,9 +697,17 @@ int mpc5xxx_fec_probe(struct device_d *dev) return 0; } +static void mpc5xxx_fec_remove(struct device_d *dev) +{ + struct eth_device *edev = dev->type_data; + + mpc5xxx_fec_halt(edev); +} + static struct driver_d mpc5xxx_driver = { .name = "fec_mpc5xxx", .probe = mpc5xxx_fec_probe, + .remove = mpc5xxx_fec_remove, }; static int mpc5xxx_fec_register(void) diff --git a/drivers/net/macb.c b/drivers/net/macb.c index 898cf3d1ab..c1f7f68484 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -46,9 +46,10 @@ #include <init.h> #include <miidev.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/board.h> #include <linux/clk.h> +#include <linux/err.h> #include "macb.h" @@ -392,7 +393,7 @@ static int macb_get_ethaddr(struct eth_device *edev, unsigned char *adr) static int macb_set_ethaddr(struct eth_device *edev, unsigned char *adr) { - struct macb_device *macb = edev->priv; + struct macb_device *macb = edev->priv; debug("%s\n", __func__); @@ -444,7 +445,7 @@ static int macb_probe(struct device_d *dev) macb->miidev.parent = dev; macb->flags = pdata->flags; - macb->rx_buffer = xmalloc(CFG_MACB_RX_BUFFER_SIZE); + macb->rx_buffer = xmalloc(CFG_MACB_RX_BUFFER_SIZE); macb->rx_ring = xmalloc(CFG_MACB_RX_RING_SIZE * sizeof(struct macb_dma_desc)); macb->tx_ring = xmalloc(sizeof(struct macb_dma_desc)); @@ -456,6 +457,11 @@ static int macb_probe(struct device_d *dev) */ #if defined(CONFIG_ARCH_AT91) pclk = clk_get(dev, "macb_clk"); + if (IS_ERR(pclk)) { + dev_err(dev, "no macb_clk\n"); + return PTR_ERR(pclk); + } + clk_enable(pclk); macb_hz = clk_get_rate(pclk); #else @@ -479,15 +485,15 @@ static int macb_probe(struct device_d *dev) } static struct driver_d macb_driver = { - .name = "macb", - .probe = macb_probe, + .name = "macb", + .probe = macb_probe, }; static int macb_driver_init(void) { debug("%s\n", __func__); - register_driver(&macb_driver); - return 0; + register_driver(&macb_driver); + return 0; } device_initcall(macb_driver_init); diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c index 5503bc94dd..81a7ff4fcd 100644 --- a/drivers/net/netx_eth.c +++ b/drivers/net/netx_eth.c @@ -1,7 +1,7 @@ #include <common.h> #include <command.h> #include <net.h> -#include <asm/io.h> +#include <io.h> #include <miidev.h> #include <mach/netx-xc.h> #include <mach/netx-eth.h> diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c index 2313aaeb63..c51f8c7291 100644 --- a/drivers/net/smc91111.c +++ b/drivers/net/smc91111.c @@ -73,7 +73,7 @@ #include <xfuncs.h> #include <errno.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> /*--------------------------------------------------------------- . diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index fba61c460f..e34c0df90d 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -36,7 +36,7 @@ #include <xfuncs.h> #include <errno.h> #include <clock.h> -#include <asm/io.h> +#include <io.h> #define AS CONFIG_DRIVER_NET_SMC911X_ADDRESS_SHIFT diff --git a/drivers/nor/cfi_flash.c b/drivers/nor/cfi_flash.c index 7b25adb3ac..654e6470c1 100644 --- a/drivers/nor/cfi_flash.c +++ b/drivers/nor/cfi_flash.c @@ -40,7 +40,7 @@ #include <clock.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <errno.h> #include <progress.h> #include "cfi_flash.h" @@ -822,26 +822,12 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector, */ void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf) { - int i; - int cp_offset; - int cword_offset; - uchar val; - uchar *cp; - - *cmdbuf = 0; - cp = (uchar *)cmdbuf; + cfiword_t result = 0; + int i = info->portwidth / info->chipwidth; - for (i = info->portwidth; i > 0; i--) { - cword_offset = (info->portwidth-i) % info->chipwidth; -#if __BYTE_ORDER == __LITTLE_ENDIAN - cp_offset = info->portwidth - i; - val = *((uchar *)&cmd + cword_offset); -#else - cp_offset = i - 1; - val = *((uchar *)&cmd + sizeof(u32) - cword_offset - 1); -#endif - cp[cp_offset] = (cword_offset >= sizeof(u32)) ? 0x00 : val; - } + while (i--) + result = (result << (8 * info->chipwidth)) | cmd; + *cmdbuf = result; } /* diff --git a/drivers/nor/cfi_flash.h b/drivers/nor/cfi_flash.h index 32dcc8c5e0..df482b6c56 100644 --- a/drivers/nor/cfi_flash.h +++ b/drivers/nor/cfi_flash.h @@ -26,7 +26,7 @@ #include <driver.h> #include <asm/byteorder.h> -#include <asm/io.h> +#include <io.h> #include <linux/mtd/mtd.h> typedef unsigned long flash_sect_t; @@ -247,17 +247,17 @@ void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf); static inline void flash_write8(u8 value, void *addr) { - writeb(value, addr); + cpu_writeb(value, addr); } static inline void flash_write16(u16 value, void *addr) { - writew(value, addr); + cpu_writew(value, addr); } static inline void flash_write32(u32 value, void *addr) { - writel(value, addr); + cpu_writel(value, addr); } static inline void flash_write64(u64 value, void *addr) @@ -267,17 +267,17 @@ static inline void flash_write64(u64 value, void *addr) static inline u8 flash_read8(void *addr) { - return readb(addr); + return cpu_readb(addr); } static inline u16 flash_read16(void *addr) { - return readw(addr); + return cpu_readw(addr); } static inline u32 flash_read32(void *addr) { - return readl(addr); + return cpu_readl(addr); } static inline u64 flash_read64(void *addr) diff --git a/drivers/serial/amba-pl011.c b/drivers/serial/amba-pl011.c index 2b6d5d384c..148bdbf576 100644 --- a/drivers/serial/amba-pl011.c +++ b/drivers/serial/amba-pl011.c @@ -31,7 +31,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <linux/amba/serial.h> #include <linux/clk.h> #include <linux/err.h> diff --git a/drivers/serial/atmel.c b/drivers/serial/atmel.c index 2d4b842420..9ba4ca9dab 100644 --- a/drivers/serial/atmel.c +++ b/drivers/serial/atmel.c @@ -21,7 +21,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <linux/clk.h> /* USART3 register offsets */ diff --git a/drivers/serial/serial_altera.c b/drivers/serial/serial_altera.c index 1148564b9e..8fd5d8a1a0 100644 --- a/drivers/serial/serial_altera.c +++ b/drivers/serial/serial_altera.c @@ -24,7 +24,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <asm/nios2-io.h> struct altera_serial_priv { diff --git a/drivers/serial/serial_altera_jtag.c b/drivers/serial/serial_altera_jtag.c index 2e34c894a4..3e1b0cf6e1 100644 --- a/drivers/serial/serial_altera_jtag.c +++ b/drivers/serial/serial_altera_jtag.c @@ -27,7 +27,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <asm/nios2-io.h> struct altera_serial_jtag_priv { diff --git a/drivers/serial/serial_at91rm9200.c b/drivers/serial/serial_at91rm9200.c index f5546aa758..9bdc626e4d 100644 --- a/drivers/serial/serial_at91rm9200.c +++ b/drivers/serial/serial_at91rm9200.c @@ -30,7 +30,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <mach/hardware.h> #if !defined(CONFIG_DBGU) && !defined(CONFIG_USART0) && !defined(CONFIG_USART1) diff --git a/drivers/serial/serial_blackfin.c b/drivers/serial/serial_blackfin.c index 59b2fbb1ec..9ad55792ac 100644 --- a/drivers/serial/serial_blackfin.c +++ b/drivers/serial/serial_blackfin.c @@ -25,7 +25,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <asm/blackfin.h> #define UART_IER_ERBFI 0x01 diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c index e3edac951f..4923dcbd94 100644 --- a/drivers/serial/serial_imx.c +++ b/drivers/serial/serial_imx.c @@ -24,7 +24,7 @@ #include <init.h> #include <malloc.h> #include <notifier.h> -#include <asm/io.h> +#include <io.h> #define URXD0 0x0 /* Receiver Register */ #define URTX0 0x40 /* Transmitter Register */ diff --git a/drivers/serial/serial_mpc5xxx.c b/drivers/serial/serial_mpc5xxx.c index fb580cf1fd..b00b442bce 100644 --- a/drivers/serial/serial_mpc5xxx.c +++ b/drivers/serial/serial_mpc5xxx.c @@ -39,7 +39,6 @@ #include <init.h> #include <console.h> #include <xfuncs.h> -#include <reloc.h> #include <mach/clocks.h> static int __mpc5xxx_serial_setbaudrate(struct mpc5xxx_psc *psc, int baudrate) @@ -180,27 +179,3 @@ static int mpc5xxx_serial_register(void) } console_initcall(mpc5xxx_serial_register); - -#ifdef CONFIG_MPC5XXX_EARLY_CONSOLE - -void early_console_putc(void *base, char c) -{ - struct mpc5xxx_psc *psc = - (struct mpc5xxx_psc *)base; - - /* Wait for last character to go. */ - while (!(psc->psc_status & PSC_SR_TXEMP)) - ; - - psc->psc_buffer_8 = c; -} - -void early_console_init(void *base, int baudrate) -{ - struct mpc5xxx_psc *psc = - (struct mpc5xxx_psc *)base; - __mpc5xxx_serial_init(psc); - __mpc5xxx_serial_setbaudrate(psc, baudrate); -} - -#endif diff --git a/drivers/serial/serial_netx.c b/drivers/serial/serial_netx.c index fbbc4efdac..a3273e9602 100644 --- a/drivers/serial/serial_netx.c +++ b/drivers/serial/serial_netx.c @@ -26,7 +26,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> enum uart_regs { UART_DR = 0x00, diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 36d39cd125..1217a5f249 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -41,7 +41,7 @@ #include <init.h> #include <errno.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include "serial_ns16550.h" #include <ns16550.h> diff --git a/drivers/serial/serial_pl010.c b/drivers/serial/serial_pl010.c index 9f7b7d3b02..cb875410ea 100644 --- a/drivers/serial/serial_pl010.c +++ b/drivers/serial/serial_pl010.c @@ -32,7 +32,7 @@ #include <common.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include "serial_pl010.h" static int pl010_setbaudrate(struct console_device *cdev, int baudrate) diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c24x0.c index 21bca12f39..3a703b6fe8 100644 --- a/drivers/serial/serial_s3c24x0.c +++ b/drivers/serial/serial_s3c24x0.c @@ -24,7 +24,7 @@ #include <driver.h> #include <init.h> #include <malloc.h> -#include <asm/io.h> +#include <io.h> #include <mach/s3c24xx-generic.h> #include <mach/s3c24x0-iomap.h> diff --git a/drivers/serial/stm-serial.c b/drivers/serial/stm-serial.c index 4264345182..1563d2a93b 100644 --- a/drivers/serial/stm-serial.c +++ b/drivers/serial/stm-serial.c @@ -30,7 +30,7 @@ #include <init.h> #include <notifier.h> #include <gpio.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/clock.h> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c72493c016..609bafd07f 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -14,6 +14,11 @@ config DRIVER_SPI_IMX_0_0 depends on ARCH_IMX27 default y +config DRIVER_SPI_IMX_0_7 + bool + depends on ARCH_IMX25 + default y + config DRIVER_SPI_IMX_2_3 bool depends on ARCH_IMX51 || ARCH_IMX53 @@ -24,4 +29,9 @@ config DRIVER_SPI_ALTERA depends on NIOS2 depends on SPI +config DRIVER_SPI_ATMEL + bool "Atmel (AT91) SPI Master driver" + depends on ARCH_AT91 + depends on SPI + endmenu diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 90e141dae6..101652ff85 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_SPI) += spi.o obj-$(CONFIG_DRIVER_SPI_IMX) += imx_spi.o obj-$(CONFIG_DRIVER_SPI_ALTERA) += altera_spi.o +obj-$(CONFIG_DRIVER_SPI_ATMEL) += atmel_spi.o diff --git a/drivers/spi/altera_spi.c b/drivers/spi/altera_spi.c index 2c02d7af63..4fd82fb905 100644 --- a/drivers/spi/altera_spi.c +++ b/drivers/spi/altera_spi.c @@ -22,7 +22,7 @@ #include <init.h> #include <driver.h> #include <spi/spi.h> -#include <asm/io.h> +#include <io.h> #include <asm/spi.h> #include <asm/nios2-io.h> diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c new file mode 100644 index 0000000000..faa03b1c9e --- /dev/null +++ b/drivers/spi/atmel_spi.c @@ -0,0 +1,321 @@ +/* + * Driver for Atmel AT32 and AT91 SPI Controllers + * + * Copyright (C) 2011 Hubert Feurstein <h.feurstein@gmail.com> + * + * based on imx_spi.c by: + * Copyright (C) 2008 Sascha Hauer, Pengutronix + * + * based on atmel_spi.c from the linux kernel by: + * Copyright (C) 2006 Atmel Corporation + * + * 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 <common.h> +#include <init.h> +#include <driver.h> +#include <errno.h> +#include <clock.h> +#include <xfuncs.h> +#include <gpio.h> +#include <io.h> +#include <spi/spi.h> +#include <mach/io.h> +#include <mach/board.h> +#include <mach/cpu.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include "atmel_spi.h" + +struct atmel_spi { + struct spi_master master; + void __iomem *regs; + struct clk *clk; + int *cs_pins; +}; + +#define to_atmel_spi(p) container_of(p, struct atmel_spi, master) +#define SPI_XCHG_TIMEOUT (100 * MSECOND) + +/* + * Version 2 of the SPI controller has + * - CR.LASTXFER + * - SPI_MR.DIV32 may become FDIV or must-be-zero (here: always zero) + * - SPI_SR.TXEMPTY, SPI_SR.NSSR (and corresponding irqs) + * - SPI_CSRx.CSAAT + * - SPI_CSRx.SBCR allows faster clocking + * + * We can determine the controller version by reading the VERSION + * register, but I haven't checked that it exists on all chips, and + * this is cheaper anyway. + */ +static inline bool atmel_spi_is_v2(void) +{ + return !cpu_is_at91rm9200(); +} + +static int atmel_spi_setup(struct spi_device *spi) +{ + struct spi_master *master = spi->master; + struct atmel_spi *as = to_atmel_spi(master); + + u32 scbr, csr; + unsigned int bits = spi->bits_per_word; + unsigned long bus_hz; + + if (spi->controller_data) { + csr = (u32)spi->controller_data; + spi_writel(as, CSR0, csr); + return 0; + } + + dev_dbg(master->dev, "%s mode 0x%08x bits_per_word: %d speed: %d\n", + __func__, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + + bus_hz = clk_get_rate(as->clk); + if (!atmel_spi_is_v2()) + bus_hz /= 2; + + if (spi->max_speed_hz) { + /* + * Calculate the lowest divider that satisfies the + * constraint, assuming div32/fdiv/mbz == 0. + */ + scbr = DIV_ROUND_UP(bus_hz, spi->max_speed_hz); + + /* + * If the resulting divider doesn't fit into the + * register bitfield, we can't satisfy the constraint. + */ + if (scbr >= (1 << SPI_SCBR_SIZE)) { + dev_dbg(master->dev, + "setup: %d Hz too slow, scbr %u; min %ld Hz\n", + spi->max_speed_hz, scbr, bus_hz/255); + return -EINVAL; + } + } else { + /* speed zero means "as slow as possible" */ + scbr = 0xff; + } + + csr = SPI_BF(SCBR, scbr) | SPI_BF(BITS, bits - 8); + if (spi->mode & SPI_CPOL) + csr |= SPI_BIT(CPOL); + if (!(spi->mode & SPI_CPHA)) + csr |= SPI_BIT(NCPHA); + + /* DLYBS is mostly irrelevant since we manage chipselect using GPIOs. + * + * DLYBCT would add delays between words, slowing down transfers. + * It could potentially be useful to cope with DMA bottlenecks, but + * in those cases it's probably best to just use a lower bitrate. + */ + csr |= SPI_BF(DLYBS, 0); + csr |= SPI_BF(DLYBCT, 0); + + /* gpio_direction_output(npcs_pin, !(spi->mode & SPI_CS_HIGH)); */ + dev_dbg(master->dev, + "setup: %lu Hz bpw %u mode 0x%x -> csr%d %08x\n", + bus_hz / scbr, bits, spi->mode, spi->chip_select, csr); + + spi_writel(as, CSR0, csr); + + /* + * store the csr-setting when bits are defined. This happens usually + * after the specific spi_device driver has been probed. + */ + if (bits > 0) + spi->controller_data = (void *)csr; + + return 0; +} + +static void atmel_spi_chipselect(struct spi_device *spi, struct atmel_spi *as, int on) +{ + struct spi_master *master = &as->master; + int cs_pin; + int val = ((spi->mode & SPI_CS_HIGH) != 0) == on; + + BUG_ON(spi->chip_select >= master->num_chipselect); + cs_pin = as->cs_pins[spi->chip_select]; + + gpio_direction_output(cs_pin, val); +} + +static int atmel_spi_xchg(struct atmel_spi *as, u32 tx_val) +{ + uint64_t start; + + start = get_time_ns(); + while (!(spi_readl(as, SR) & SPI_BIT(TDRE))) { + if (is_timeout(start, SPI_XCHG_TIMEOUT)) { + dev_err(as->master.dev, "tx timeout\n"); + return -ETIMEDOUT; + } + } + spi_writel(as, TDR, tx_val); + + start = get_time_ns(); + while (!(spi_readl(as, SR) & SPI_BIT(RDRF))) { + if (is_timeout(start, SPI_XCHG_TIMEOUT)) { + dev_err(as->master.dev, "rx timeout\n"); + return -ETIMEDOUT; + } + } + return spi_readl(as, RDR) & 0xffff; +} + +static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *mesg) +{ + int ret; + struct spi_master *master = spi->master; + struct atmel_spi *as = to_atmel_spi(master); + struct spi_transfer *t = NULL; + unsigned int bits = spi->bits_per_word; + + ret = master->setup(spi); + if (ret < 0) { + dev_dbg(master->dev, "transfer: master setup failed\n"); + return ret; + } + + dev_dbg(master->dev, " csr0: %08x\n", spi_readl(as, CSR0)); + +#ifdef VERBOSE + list_for_each_entry(t, &mesg->transfers, transfer_list) { + dev_dbg(master->dev, + " xfer %p: len %u tx %p rx %p\n", + t, t->len, t->tx_buf, t->rx_buf); + } +#endif + atmel_spi_chipselect(spi, as, 1); + list_for_each_entry(t, &mesg->transfers, transfer_list) { + u32 tx_val; + int i = 0, rx_val; + + if (bits <= 8) { + const u8 *txbuf = t->tx_buf; + u8 *rxbuf = t->rx_buf; + + while (i < t->len) { + tx_val = txbuf ? txbuf[i] : 0; + + rx_val = atmel_spi_xchg(as, tx_val); + if (rx_val < 0) { + ret = rx_val; + goto out; + } + + if (rxbuf) + rxbuf[i] = rx_val; + i++; + } + } else if (bits <= 16) { + const u16 *txbuf = t->tx_buf; + u16 *rxbuf = t->rx_buf; + + while (i < t->len >> 1) { + tx_val = txbuf ? txbuf[i] : 0; + + rx_val = atmel_spi_xchg(as, tx_val); + if (rx_val < 0) { + ret = rx_val; + goto out; + } + + if (rxbuf) + rxbuf[i] = rx_val; + i++; + } + } + } +out: + atmel_spi_chipselect(spi, as, 0); + return ret; +} + +static int atmel_spi_probe(struct device_d *dev) +{ + int ret = 0; + struct spi_master *master; + struct atmel_spi *as; + struct at91_spi_platform_data *pdata = dev->platform_data; + + if (!pdata) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } + + as = xzalloc(sizeof(*as)); + + master = &as->master; + master->dev = dev; + + as->clk = clk_get(dev, "spi_clk"); + if (IS_ERR(as->clk)) { + dev_err(dev, "no spi_clk\n"); + ret = PTR_ERR(as->clk); + goto out_free; + } + + master->setup = atmel_spi_setup; + master->transfer = atmel_spi_transfer; + master->num_chipselect = pdata->num_chipselect; + as->cs_pins = pdata->chipselect; + as->regs = dev_request_mem_region(dev, 0); + + /* Initialize the hardware */ + clk_enable(as->clk); + spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ + spi_writel(as, MR, SPI_BIT(MSTR) | SPI_BIT(MODFDIS)); + spi_writel(as, PTCR, SPI_BIT(RXTDIS) | SPI_BIT(TXTDIS)); + spi_writel(as, CR, SPI_BIT(SPIEN)); + + dev_dbg(dev, "Atmel SPI Controller at initialized\n"); + + ret = spi_register_master(master); + if (ret) + goto out_reset_hw; + + return 0; + +out_reset_hw: + spi_writel(as, CR, SPI_BIT(SWRST)); + spi_writel(as, CR, SPI_BIT(SWRST)); /* AT91SAM9263 Rev B workaround */ + clk_disable(as->clk); + clk_put(as->clk); +out_free: + free(as); + return ret; +} + +static struct driver_d atmel_spi_driver = { + .name = "atmel_spi", + .probe = atmel_spi_probe, +}; + +static int atmel_spi_init(void) +{ + register_driver(&atmel_spi_driver); + return 0; +} + +device_initcall(atmel_spi_init); diff --git a/drivers/spi/atmel_spi.h b/drivers/spi/atmel_spi.h new file mode 100644 index 0000000000..38ce11998a --- /dev/null +++ b/drivers/spi/atmel_spi.h @@ -0,0 +1,167 @@ +/* + * Register definitions for Atmel Serial Peripheral Interface (SPI) + * + * Copyright (C) 2006 Atmel Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#ifndef __ATMEL_SPI_H__ +#define __ATMEL_SPI_H__ + +/* SPI register offsets */ +#define SPI_CR 0x0000 +#define SPI_MR 0x0004 +#define SPI_RDR 0x0008 +#define SPI_TDR 0x000c +#define SPI_SR 0x0010 +#define SPI_IER 0x0014 +#define SPI_IDR 0x0018 +#define SPI_IMR 0x001c +#define SPI_CSR0 0x0030 +#define SPI_CSR1 0x0034 +#define SPI_CSR2 0x0038 +#define SPI_CSR3 0x003c +#define SPI_RPR 0x0100 +#define SPI_RCR 0x0104 +#define SPI_TPR 0x0108 +#define SPI_TCR 0x010c +#define SPI_RNPR 0x0110 +#define SPI_RNCR 0x0114 +#define SPI_TNPR 0x0118 +#define SPI_TNCR 0x011c +#define SPI_PTCR 0x0120 +#define SPI_PTSR 0x0124 + +/* Bitfields in CR */ +#define SPI_SPIEN_OFFSET 0 +#define SPI_SPIEN_SIZE 1 +#define SPI_SPIDIS_OFFSET 1 +#define SPI_SPIDIS_SIZE 1 +#define SPI_SWRST_OFFSET 7 +#define SPI_SWRST_SIZE 1 +#define SPI_LASTXFER_OFFSET 24 +#define SPI_LASTXFER_SIZE 1 + +/* Bitfields in MR */ +#define SPI_MSTR_OFFSET 0 +#define SPI_MSTR_SIZE 1 +#define SPI_PS_OFFSET 1 +#define SPI_PS_SIZE 1 +#define SPI_PCSDEC_OFFSET 2 +#define SPI_PCSDEC_SIZE 1 +#define SPI_FDIV_OFFSET 3 +#define SPI_FDIV_SIZE 1 +#define SPI_MODFDIS_OFFSET 4 +#define SPI_MODFDIS_SIZE 1 +#define SPI_LLB_OFFSET 7 +#define SPI_LLB_SIZE 1 +#define SPI_PCS_OFFSET 16 +#define SPI_PCS_SIZE 4 +#define SPI_DLYBCS_OFFSET 24 +#define SPI_DLYBCS_SIZE 8 + +/* Bitfields in RDR */ +#define SPI_RD_OFFSET 0 +#define SPI_RD_SIZE 16 + +/* Bitfields in TDR */ +#define SPI_TD_OFFSET 0 +#define SPI_TD_SIZE 16 + +/* Bitfields in SR */ +#define SPI_RDRF_OFFSET 0 +#define SPI_RDRF_SIZE 1 +#define SPI_TDRE_OFFSET 1 +#define SPI_TDRE_SIZE 1 +#define SPI_MODF_OFFSET 2 +#define SPI_MODF_SIZE 1 +#define SPI_OVRES_OFFSET 3 +#define SPI_OVRES_SIZE 1 +#define SPI_ENDRX_OFFSET 4 +#define SPI_ENDRX_SIZE 1 +#define SPI_ENDTX_OFFSET 5 +#define SPI_ENDTX_SIZE 1 +#define SPI_RXBUFF_OFFSET 6 +#define SPI_RXBUFF_SIZE 1 +#define SPI_TXBUFE_OFFSET 7 +#define SPI_TXBUFE_SIZE 1 +#define SPI_NSSR_OFFSET 8 +#define SPI_NSSR_SIZE 1 +#define SPI_TXEMPTY_OFFSET 9 +#define SPI_TXEMPTY_SIZE 1 +#define SPI_SPIENS_OFFSET 16 +#define SPI_SPIENS_SIZE 1 + +/* Bitfields in CSR0 */ +#define SPI_CPOL_OFFSET 0 +#define SPI_CPOL_SIZE 1 +#define SPI_NCPHA_OFFSET 1 +#define SPI_NCPHA_SIZE 1 +#define SPI_CSAAT_OFFSET 3 +#define SPI_CSAAT_SIZE 1 +#define SPI_BITS_OFFSET 4 +#define SPI_BITS_SIZE 4 +#define SPI_SCBR_OFFSET 8 +#define SPI_SCBR_SIZE 8 +#define SPI_DLYBS_OFFSET 16 +#define SPI_DLYBS_SIZE 8 +#define SPI_DLYBCT_OFFSET 24 +#define SPI_DLYBCT_SIZE 8 + +/* Bitfields in RCR */ +#define SPI_RXCTR_OFFSET 0 +#define SPI_RXCTR_SIZE 16 + +/* Bitfields in TCR */ +#define SPI_TXCTR_OFFSET 0 +#define SPI_TXCTR_SIZE 16 + +/* Bitfields in RNCR */ +#define SPI_RXNCR_OFFSET 0 +#define SPI_RXNCR_SIZE 16 + +/* Bitfields in TNCR */ +#define SPI_TXNCR_OFFSET 0 +#define SPI_TXNCR_SIZE 16 + +/* Bitfields in PTCR */ +#define SPI_RXTEN_OFFSET 0 +#define SPI_RXTEN_SIZE 1 +#define SPI_RXTDIS_OFFSET 1 +#define SPI_RXTDIS_SIZE 1 +#define SPI_TXTEN_OFFSET 8 +#define SPI_TXTEN_SIZE 1 +#define SPI_TXTDIS_OFFSET 9 +#define SPI_TXTDIS_SIZE 1 + +/* Constants for BITS */ +#define SPI_BITS_8_BPT 0 +#define SPI_BITS_9_BPT 1 +#define SPI_BITS_10_BPT 2 +#define SPI_BITS_11_BPT 3 +#define SPI_BITS_12_BPT 4 +#define SPI_BITS_13_BPT 5 +#define SPI_BITS_14_BPT 6 +#define SPI_BITS_15_BPT 7 +#define SPI_BITS_16_BPT 8 + +/* Bit manipulation macros */ +#define SPI_BIT(name) \ + (1 << SPI_##name##_OFFSET) +#define SPI_BF(name, value) \ + (((value) & ((1 << SPI_##name##_SIZE) - 1)) << SPI_##name##_OFFSET) +#define SPI_BFEXT(name, value) \ + (((value) >> SPI_##name##_OFFSET) & ((1 << SPI_##name##_SIZE) - 1)) +#define SPI_BFINS(name, value, old) \ + (((old) & ~(((1 << SPI_##name##_SIZE) - 1) << SPI_##name##_OFFSET)) \ + | SPI_BF(name, value)) + +/* Register access macros */ +#define spi_readl(port, reg) \ + __raw_readl((port)->regs + SPI_##reg) +#define spi_writel(port, reg, value) \ + __raw_writel((value), (port)->regs + SPI_##reg) + +#endif /* __ATMEL_SPI_H__ */ diff --git a/drivers/spi/imx_spi.c b/drivers/spi/imx_spi.c index 6dc41b92f5..3b33b669fb 100644 --- a/drivers/spi/imx_spi.c +++ b/drivers/spi/imx_spi.c @@ -23,10 +23,11 @@ #include <driver.h> #include <spi/spi.h> #include <xfuncs.h> -#include <asm/io.h> +#include <io.h> #include <gpio.h> #include <mach/spi.h> #include <mach/generic.h> +#include <mach/clock.h> #define CSPI_0_0_RXDATA 0x00 #define CSPI_0_0_TXDATA 0x04 @@ -65,6 +66,22 @@ #define CSPI_0_0_TEST_LBC (1 << 14) +#define CSPI_0_7_RXDATA 0x00 +#define CSPI_0_7_TXDATA 0x04 +#define CSPI_0_7_CTRL 0x08 +#define CSPI_0_7_CTRL_ENABLE (1 << 0) +#define CSPI_0_7_CTRL_MASTER (1 << 1) +#define CSPI_0_7_CTRL_XCH (1 << 2) +#define CSPI_0_7_CTRL_POL (1 << 4) +#define CSPI_0_7_CTRL_PHA (1 << 5) +#define CSPI_0_7_CTRL_SSCTL (1 << 6) +#define CSPI_0_7_CTRL_SSPOL (1 << 7) +#define CSPI_0_7_CTRL_CS_SHIFT 12 +#define CSPI_0_7_CTRL_DR_SHIFT 16 +#define CSPI_0_7_CTRL_BL_SHIFT 20 +#define CSPI_0_7_STAT 0x14 +#define CSPI_0_7_STAT_RR (1 << 3) + #define CSPI_2_3_RXDATA 0x00 #define CSPI_2_3_TXDATA 0x04 #define CSPI_2_3_CTRL 0x08 @@ -206,6 +223,89 @@ static void cspi_0_0_init(struct imx_spi *imx) } #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 +static unsigned int cspi_0_7_xchg_single(struct imx_spi *imx, unsigned int data) +{ + void __iomem *base = imx->regs; + + unsigned int cfg_reg = readl(base + CSPI_0_7_CTRL); + + writel(data, base + CSPI_0_7_TXDATA); + + cfg_reg |= CSPI_0_7_CTRL_XCH; + + writel(cfg_reg, base + CSPI_0_7_CTRL); + + while (!(readl(base + CSPI_0_7_STAT) & CSPI_0_7_STAT_RR)) + ; + + return readl(base + CSPI_0_7_RXDATA); +} + +/* MX1, MX31, MX35, MX51 CSPI */ +static unsigned int spi_imx_clkdiv_2(unsigned int fin, + unsigned int fspi) +{ + int i, div = 4; + + for (i = 0; i < 7; i++) { + if (fspi * div >= fin) + return i; + div <<= 1; + } + + return 7; +} + +static void cspi_0_7_chipselect(struct spi_device *spi, int is_active) +{ + struct spi_master *master = spi->master; + struct imx_spi *imx = container_of(master, struct imx_spi, master); + void __iomem *base = imx->regs; + unsigned int cs = 0; + int gpio = imx->cs_array[spi->chip_select]; + unsigned int reg = CSPI_0_7_CTRL_ENABLE | CSPI_0_7_CTRL_MASTER; + + if (spi->mode & SPI_CS_HIGH) + cs = 1; + + if (!is_active) { + if (gpio >= 0) + gpio_set_value(gpio, !cs); + return; + } + + reg |= spi_imx_clkdiv_2(imx_get_cspiclk(), spi->max_speed_hz) << + CSPI_0_7_CTRL_DR_SHIFT; + + reg |= (spi->bits_per_word - 1) << CSPI_0_7_CTRL_BL_SHIFT; + reg |= CSPI_0_7_CTRL_SSCTL; + + if (spi->mode & SPI_CPHA) + reg |= CSPI_0_7_CTRL_PHA; + if (spi->mode & SPI_CPOL) + reg |= CSPI_0_7_CTRL_POL; + if (spi->mode & SPI_CS_HIGH) + reg |= CSPI_0_7_CTRL_SSPOL; + if (gpio < 0) + reg |= (gpio + 32) << CSPI_0_7_CTRL_CS_SHIFT; + + writel(reg, base + CSPI_0_7_CTRL); + + if (gpio >= 0) + gpio_set_value(gpio, cs); +} + +static void cspi_0_7_init(struct imx_spi *imx) +{ + void __iomem *base = imx->regs; + + /* drain receive buffer */ + while (readl(base + CSPI_0_7_STAT) & CSPI_0_7_STAT_RR) + readl(base + CSPI_0_7_RXDATA); +} +#endif + #ifdef CONFIG_DRIVER_SPI_IMX_2_3 static unsigned int cspi_2_3_xchg_single(struct imx_spi *imx, unsigned int data) { @@ -310,23 +410,56 @@ static void cspi_2_3_init(struct imx_spi *imx) } #endif +static void imx_spi_do_transfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + unsigned i; + + if (spi->bits_per_word <= 8) { + const u8 *tx_buf = t->tx_buf; + u8 *rx_buf = t->rx_buf; + u8 rx_val; + + for (i = 0; i < t->len; i++) { + rx_val = imx->xchg_single(imx, tx_buf ? tx_buf[i] : 0); + if (rx_buf) + rx_buf[i] = rx_val; + } + } else if (spi->bits_per_word <= 16) { + const u16 *tx_buf = t->tx_buf; + u16 *rx_buf = t->rx_buf; + u16 rx_val; + + for (i = 0; i < t->len >> 1; i++) { + rx_val = imx->xchg_single(imx, tx_buf ? tx_buf[i] : 0); + if (rx_buf) + rx_buf[i] = rx_val; + } + } else if (spi->bits_per_word <= 32) { + const u32 *tx_buf = t->tx_buf; + u32 *rx_buf = t->rx_buf; + u32 rx_val; + + for (i = 0; i < t->len >> 2; i++) { + rx_val = imx->xchg_single(imx, tx_buf ? tx_buf[i] : 0); + if (rx_buf) + rx_buf[i] = rx_val; + } + } +} + static int imx_spi_transfer(struct spi_device *spi, struct spi_message *mesg) { - struct spi_master *master = spi->master; - struct imx_spi *imx = container_of(master, struct imx_spi, master); - struct spi_transfer *t = NULL; + struct imx_spi *imx = container_of(spi->master, struct imx_spi, master); + struct spi_transfer *t = NULL; imx->chipselect(spi, 1); - list_for_each_entry (t, &mesg->transfers, transfer_list) { - const u32 *txbuf = t->tx_buf; - u32 *rxbuf = t->rx_buf; - int i = 0; + mesg->actual_length = 0; - while(i < t->len >> 2) { - rxbuf[i] = imx->xchg_single(imx, txbuf[i]); - i++; - } + list_for_each_entry(t, &mesg->transfers, transfer_list) { + imx_spi_do_transfer(spi, t); + mesg->actual_length += t->len; } imx->chipselect(spi, 0); @@ -342,6 +475,13 @@ static struct spi_imx_devtype_data spi_imx_devtype_data[] = { .init = cspi_0_0_init, }, #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 + [SPI_IMX_VER_0_7] = { + .chipselect = cspi_0_7_chipselect, + .xchg_single = cspi_0_7_xchg_single, + .init = cspi_0_7_init, + }, +#endif #ifdef CONFIG_DRIVER_SPI_IMX_2_3 [SPI_IMX_VER_2_3] = { .chipselect = cspi_2_3_chipselect, @@ -372,6 +512,10 @@ static int imx_spi_probe(struct device_d *dev) if (cpu_is_mx27()) version = SPI_IMX_VER_0_0; #endif +#ifdef CONFIG_DRIVER_SPI_IMX_0_7 + if (cpu_is_mx25()) + version = SPI_IMX_VER_0_7; +#endif #ifdef CONFIG_DRIVER_SPI_IMX_2_3 if (cpu_is_mx51() || cpu_is_mx53()) version = SPI_IMX_VER_2_3; diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index b561f9da2d..7a8aed42e2 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -75,12 +75,11 @@ struct spi_device *spi_new_device(struct spi_master *master, proxy->chip_select = chip->chip_select; proxy->max_speed_hz = chip->max_speed_hz; proxy->mode = chip->mode; - proxy->bits_per_word = chip->bits_per_word; + proxy->bits_per_word = chip->bits_per_word ? chip->bits_per_word : 8; proxy->dev.platform_data = chip->platform_data; strcpy(proxy->dev.name, chip->name); proxy->dev.type_data = proxy; dev_add_child(master->dev, &proxy->dev); - status = register_device(&proxy->dev); /* drivers may modify this initial i/o setup */ status = master->setup(proxy); @@ -90,10 +89,10 @@ struct spi_device *spi_new_device(struct spi_master *master, goto fail; } - return proxy; + register_device(&proxy->dev); + return proxy; fail: - unregister_device(&proxy->dev); free(proxy); return NULL; } diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index c7b2c52660..254b196415 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -7,6 +7,8 @@ source drivers/usb/host/Kconfig source drivers/usb/otg/Kconfig +source drivers/usb/storage/Kconfig + endif source drivers/usb/gadget/Kconfig diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index e6f683bb29..be4b371413 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -1,5 +1,6 @@ obj-$(CONFIG_USB) += core/ obj-$(CONFIG_USB_GADGET) += gadget/ +obj-$(CONFIG_USB_STORAGE) += storage/ obj-y += host/ obj-y += otg/ diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 5dc8afee00..7039a2cb75 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -78,13 +78,14 @@ static LIST_HEAD(usb_device_list); static void print_usb_device(struct usb_device *dev) { - printf("%s: %04x:%04x %s\n", dev->dev.name, - dev->descriptor.idVendor, - dev->descriptor.idProduct, - dev->prod); + printf("Bus %03d Device %03d: ID %04x:%04x %s\n", + dev->host->busnum, dev->devnum, + dev->descriptor.idVendor, + dev->descriptor.idProduct, + dev->prod); } -static int host_busnum; +static int host_busnum = 1; int usb_register_host(struct usb_host *host) { @@ -530,6 +531,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout) { struct usb_host *host = dev->host; + int ret; if ((timeout == 0) && (!asynch_allowed)) { /* request for a asynch control pipe is not allowed */ @@ -547,18 +549,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, request, requesttype, value, index, size); dev->status = USB_ST_NOT_PROC; /*not yet processed */ - host->submit_control_msg(dev, pipe, data, size, &setup_packet); - if (timeout == 0) - return (int)size; - - if (dev->status != 0) { - /* - * Let's wait a while for the timeout to elapse. - * It has no real use, but it keeps the interface happy. - */ - wait_ms(timeout); - return -1; - } + ret = host->submit_control_msg(dev, pipe, data, size, &setup_packet, timeout); + if (ret) + return ret; return dev->act_len; } @@ -578,7 +571,7 @@ int usb_bulk_msg(struct usb_device *dev, unsigned int pipe, return -1; dev->status = USB_ST_NOT_PROC; /* not yet processed */ - ret = host->submit_bulk_msg(dev, pipe, data, len); + ret = host->submit_bulk_msg(dev, pipe, data, len, timeout); if (ret) return ret; @@ -1300,10 +1293,13 @@ static int usb_match_device(struct usb_device *dev, const struct usb_device_id * return 1; } + /* returns 0 if no match, 1 if match */ static int usb_match_one_id(struct usb_device *usbdev, const struct usb_device_id *id) { + int ifno; + /* proc_connectinfo in devio.c may call us with id == NULL. */ if (id == NULL) return 0; @@ -1311,6 +1307,37 @@ static int usb_match_one_id(struct usb_device *usbdev, if (!usb_match_device(usbdev, id)) return 0; + /* The interface class, subclass, and protocol should never be + * checked for a match if the device class is Vendor Specific, + * unless the match record specifies the Vendor ID. */ + if (usbdev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC && + !(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) && + (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO)) + return 0; + + if ( (id->match_flags & USB_DEVICE_ID_MATCH_INT_INFO) ) { + /* match any interface */ + for (ifno=0; ifno<usbdev->config.no_of_if; ifno++) { + struct usb_interface_descriptor *intf; + intf = &usbdev->config.if_desc[ifno]; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && + (id->bInterfaceClass != intf->bInterfaceClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) && + (id->bInterfaceSubClass != intf->bInterfaceSubClass)) + continue; + + if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) && + (id->bInterfaceProtocol != intf->bInterfaceProtocol)) + continue; + break; + } + if (ifno >= usbdev->config.no_of_if) + return 0; + } + return 1; } EXPORT_SYMBOL(usb_match_one_id); diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c index 1e4d4b08f3..fbc6e4ecc7 100644 --- a/drivers/usb/gadget/fsl_udc.c +++ b/drivers/usb/gadget/fsl_udc.c @@ -5,7 +5,7 @@ #include <usb/ch9.h> #include <usb/gadget.h> #include <usb/fsl_usb2.h> -#include <asm/io.h> +#include <io.h> #include <asm/byteorder.h> #include <asm/mmu.h> diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 145f7d1c69..929eb89a3a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -4,3 +4,6 @@ config USB_EHCI config USB_EHCI_OMAP depends on ARCH_OMAP3 bool "OMAP EHCI driver" + +config USB_OHCI + bool "OHCI driver" diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index a334b08115..1c7e18f75f 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile @@ -1,2 +1,4 @@ obj-$(CONFIG_USB_EHCI) += ehci-hcd.o obj-$(CONFIG_USB_EHCI_OMAP) += ehci-omap.o +obj-$(CONFIG_USB_OHCI) += ohci-hcd.o +obj-$(CONFIG_ARCH_AT91) += ohci-at91.o diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index 60fc1819eb..72f1c14359 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -24,7 +24,7 @@ #include <common.h> #include <asm/byteorder.h> #include <usb/usb.h> -#include <asm/io.h> +#include <io.h> #include <malloc.h> #include <driver.h> #include <init.h> @@ -298,7 +298,7 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, uint32_t c, toggle; uint32_t cmd; int ret = 0; - uint64_t start; + uint64_t start, timeout_val; static struct QH __qh __attribute__((aligned(32))); static struct qTD __td[3] __attribute__((aligned(32))); @@ -415,13 +415,14 @@ ehci_submit_async(struct usb_device *dev, unsigned long pipe, void *buffer, } /* Wait for TDs to be processed. */ + timeout_val = usb_pipebulk(pipe) ? (SECOND << 2) : (SECOND >> 2); start = get_time_ns(); vtd = td; do { /* Invalidate dcache */ ehci_invalidate_dcache(ehci->qh_list); token = hc32_to_cpu(vtd->qt_token); - if (is_timeout(start, SECOND >> 2)) { + if (is_timeout(start, timeout_val)) { /* Disable async schedule. */ cmd = ehci_readl(&ehci->hcor->or_usbcmd); cmd &= ~CMD_ASE; @@ -850,7 +851,7 @@ static int ehci_init(struct usb_host *host) static int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length) + int length, int timeout) { if (usb_pipetype(pipe) != PIPE_BULK) { @@ -862,7 +863,7 @@ submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, static int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, - int length, struct devrequest *setup) + int length, struct devrequest *setup, int timeout) { struct usb_host *host = dev->host; struct ehci_priv *ehci = to_ehci(host); @@ -922,10 +923,7 @@ static int ehci_probe(struct device_d *dev) host->submit_bulk_msg = submit_bulk_msg; if (ehci->flags & EHCI_HAS_TT) { - /* Set to host mode */ - reg = ehci_readl(ehci->hcor + USBMODE); - reg |= USBMODE_CM_HC; - writel(reg, ehci->hcor + USBMODE); + ehci_reset(ehci); } usb_register_host(host); diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c index 94aa356dd3..e2ce65f864 100644 --- a/drivers/usb/host/ehci-omap.c +++ b/drivers/usb/host/ehci-omap.c @@ -15,7 +15,7 @@ #include <usb/twl4030.h> #include <mach/ehci.h> #include <common.h> -#include <asm/io.h> +#include <io.h> #include <clock.h> #include <gpio.h> #include <mach/omap3-silicon.h> diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c new file mode 100644 index 0000000000..7465182a7b --- /dev/null +++ b/drivers/usb/host/ohci-at91.c @@ -0,0 +1,98 @@ +/* + * (C) Copyright 2010 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.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; version 2 of + * the License. + * + * 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 <common.h> +#include <linux/clk.h> +#include <driver.h> +#include <init.h> +#include <usb/usb.h> +#include <usb/usb_defs.h> +#include <errno.h> +#include <io.h> + +#include "ohci.h" + +/* interface and function clocks; sometimes also an AHB clock */ +static struct clk *iclk, *fclk; + +static void at91_start_clock(void) +{ + clk_enable(iclk); + clk_enable(fclk); +} + +static void at91_stop_clock(void) +{ + clk_disable(fclk); + clk_disable(iclk); +} + +static int at91_ohci_probe(struct device_d *dev) +{ + struct ohci_regs __iomem *regs = (struct ohci_regs __iomem *)dev->resource[0].start; + + iclk = clk_get(NULL, "ohci_clk"); + fclk = clk_get(NULL, "uhpck"); + + /* + * Start the USB clocks. + */ + at91_start_clock(); + + /* + * The USB host controller must remain in reset. + */ + writel(0, ®s->control); + + add_generic_device("ohci", -1, NULL, dev->resource[0].start, + dev->resource[0].size, IORESOURCE_MEM, NULL); + + return 0; +} + +static void at91_ohci_remove(struct device_d *dev) +{ + struct ohci_regs __iomem *regs = (struct ohci_regs __iomem *)dev->resource[0].start; + + /* + * Put the USB host controller into reset. + */ + writel(0, ®s->control); + + /* + * Stop the USB clocks. + */ + at91_stop_clock(); +} + +static struct driver_d at91_ohci_driver = { + .name = "at91_ohci", + .probe = at91_ohci_probe, + .remove = at91_ohci_remove, +}; + +static int at91_ohci_init(void) +{ + register_driver(&at91_ohci_driver); + return 0; +} +device_initcall(at91_ohci_init); diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c new file mode 100644 index 0000000000..f103101464 --- /dev/null +++ b/drivers/usb/host/ohci-hcd.c @@ -0,0 +1,1856 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB on the AT91RM9200 and PCI bus. + * + * Interrupt support is added. Now, it has been tested + * on ULI1575 chip and works well with USB keyboard. + * + * (C) Copyright 2007 + * Zhang Wei, Freescale Semiconductor, Inc. <wei.zhang@freescale.com> + * + * (C) Copyright 2003 + * Gary Jennejohn, DENX Software Engineering <garyj@denx.de> + * + * Note: Much of this code has been derived from Linux 2.4 + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2002 David Brownell + * + * Modified for the MP2USB by (C) Copyright 2005 Eric Benard + * ebenard@eukrea.com - based on s3c24x0's driver + * + * 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 + * + */ +/* + * IMPORTANT NOTES + * 1 - Read doc/README.generic_usb_ohci + * 2 - this driver is intended for use with USB Mass Storage Devices + * (BBB) and USB keyboard. There is NO support for Isochronous pipes! + * 2 - when running on a PQFP208 AT91RM9200, define CONFIG_AT91C_PQFP_UHPBUG + * to activate workaround for bug #41 or this driver will NOT work! + */ +#include <common.h> +#include <clock.h> +#include <malloc.h> +#include <usb/usb.h> +#include <usb/usb_defs.h> +#include <init.h> +#include <errno.h> + +#include <asm/byteorder.h> +#include <io.h> +#include <asm/mmu.h> + +#include "ohci.h" + +#undef OHCI_VERBOSE_DEBUG /* not always helpful */ +#undef SHOW_INFO +#undef OHCI_FILL_TRACE + +/* For initializing controller (mask in an HCFS mode too) */ +#define OHCI_CONTROL_INIT \ + ((OHCI_CTRL_CBSR & 0x3) | OHCI_CTRL_IE | OHCI_CTRL_PLE) + +#define err(format, arg...) printf("ERROR: " format, ## arg) +#ifdef SHOW_INFO +#define info(format, arg...) printf("INFO: " format, ## arg) +#else +#define info(format, arg...) do {} while (0) +#endif + +#define to_ohci(ptr) container_of(ptr, struct ohci, host) + +static inline u32 roothub_a(struct ohci *hc) +{ + return readl(&hc->regs->roothub.a); +} + +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 inline u32 roothub_portstatus(struct ohci *hc, int i) +{ + return readl(&hc->regs->roothub.portstatus[i]); +} + +/* forward declaration */ +static int hc_interrupt(struct ohci *ohci); +static void td_submit_job(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, struct urb_priv *urb, + int interval); + +static int ep_link(struct ohci *ohci, struct ed *ed); +static int ep_unlink(struct ohci *ohci, struct ed *ed); +static struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, + int interval, int load); + +#ifdef CONFIG_SYS_OHCI_BE_CONTROLLER +# define m16_swap(x) cpu_to_be16(x) +# define m32_swap(x) cpu_to_be32(x) +#else +# define m16_swap(x) cpu_to_le16(x) +# define m32_swap(x) cpu_to_le32(x) +#endif /* CONFIG_SYS_OHCI_BE_CONTROLLER */ + +/*-------------------------------------------------------------------------* + * URB support functions + *-------------------------------------------------------------------------*/ + +/* TDs ... */ +static inline struct td *td_alloc(struct usb_device *usb_dev) +{ + int i; + struct usb_host *host = usb_dev->host; + struct ohci *ohci = to_ohci(host); + struct td *ptd = ohci->ptd; + struct td *td = NULL; + + for (i = 0; i < NUM_TD; i++) { + if (!ptd[i].usb_dev) { + td = &ptd[i]; + td->usb_dev = usb_dev; + break; + } + } + + return td; +} + +static inline void ed_free(struct ed *ed) +{ + ed->usb_dev = NULL; +} + +/* free HCD-private data associated with this URB */ + +static void urb_free_priv(struct urb_priv *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; + } + } + } + free(urb); +} + +/*-------------------------------------------------------------------------*/ + +#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 urb_priv *purb, struct usb_device *dev, + unsigned long pipe, void *buffer, int transfer_len, + struct devrequest *setup, char *str, int small) +{ + debug("%s URB:[%4x] dev:%2lu,ep:%2lu-%c,type:%s,len:%d/%d stat:%#lx\n", + 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 ? purb->actual_length : 0), + 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 ? purb->actual_length : 0), + transfer_len); + len = usb_pipeout(pipe) ? transfer_len : + (purb ? purb->actual_length : 0); + for (i = 0; i < 16 && i < len; i++) + printf(" %02x", ((__u8 *) buffer)[i]); + printf("%s\n", i < leni ? "..." : ""); + } + } +#endif +} + +/* just for debugging; prints non-empty branches of the int ed tree + * inclusive iso eds */ +void ep_print_int_eds(struct ohci *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--) { + struct ed *ed = (struct ed *)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) +{ + debug("%s: 0x%08x%s%s%s%s%s%s%s%s%s\n", + 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) +{ + struct ed *edp = (struct ed *)value; + + if (value) { + debug("%s %08x\n", label, value); + debug("%08x\n", edp->hwINFO); + debug("%08x\n", edp->hwTailP); + debug("%08x\n", edp->hwHeadP); + debug("%08x\n", 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(struct ohci *controller) +{ + struct ohci_regs *regs = controller->regs; + __u32 temp; + + temp = readl(®s->revision) & 0xff; + if (temp != 0x10) + debug("spec %d.%d\n", (temp >> 4), (temp & 0x0f)); + + temp = readl(®s->control); + debug("control: 0x%08x%s%s%s HCFS=%s%s%s%s%s CBSR=%d\n", 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); + debug("cmdstatus: 0x%08x SOC=%d%s%s%s%s\n", 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(struct ohci *controller, int verbose) +{ + __u32 temp, ndp, i; + + temp = roothub_a(controller); + ndp = (temp & RH_A_NDP); +#ifdef CONFIG_AT91C_PQFP_UHPBUG + ndp = (ndp == 2) ? 1 : 0; +#endif + if (verbose) { + debug("roothub.a: %08x POTPGT=%d%s%s%s%s%s NDP=%d\n", 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); + debug("roothub.b: %08x PPCM=%04x DR=%04x\n", + temp, + (temp & RH_B_PPCM) >> 16, + (temp & RH_B_DR) + ); + temp = roothub_status(controller); + debug("roothub.status: %08x%s%s%s%s%s%s\n", + 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); + debug("roothub.portstatus [%d] = 0x%08x%s%s%s%s%s%s%s%s%s%s%s%s\n", + 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(struct ohci *controller, int verbose) +{ + debug("OHCI controller usb-%s state\n", controller->slot_name); + + /* dumps some of the state we know about */ + ohci_dump_status(controller); + if (verbose) + ep_print_int_eds(controller, "hcca"); + debug("hcca frame #%04x\n", controller->hcca->frame_no); + ohci_dump_roothub(controller, 1); +} +#else /* DEBUG */ +static void pkt_print(struct urb_priv *purb, struct usb_device *dev, + unsigned long pipe, void *buffer, int transfer_len, + struct devrequest *setup, char *str, int small) +{ +} + +static void ohci_dump_roothub(struct ohci *controller, int verbose) +{ +} + +static void ohci_dump(struct ohci *controller, int verbose) +{ +} +#endif + +/*-------------------------------------------------------------------------* + * Interface functions (URB) + *-------------------------------------------------------------------------*/ + +/* get a transfer request */ + +int sohci_submit_job(struct urb_priv *urb, struct devrequest *setup) +{ + struct ed *ed; + int i, size = 0; + struct usb_device *dev = urb->dev; + struct usb_host *host = dev->host; + struct ohci *ohci = to_ohci(host); + unsigned long pipe = urb->pipe; + void *buffer = urb->transfer_buffer; + int transfer_len = urb->transfer_buffer_length; + int interval = urb->interval; + + /* when controller's hung, permit only roothub cleanup attempts + * such as powering down ports */ + if (ohci->disabled) + return -EPIPE; + + /* we're about to begin a new transaction here so mark the + * URB unfinished */ + urb->finished = 0; + + /* every endpoint has a ed, locate and fill it */ + ed = ep_add_ed(dev, pipe, interval, 1); + if (!ed) + return -ENOMEM; + + /* 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; + case PIPE_INTERRUPT: /* 1 TD */ + size = 1; + break; + } + + ed->purb = urb; + + if (size >= (N_URB_TD - 1)) { + err("need %d TDs, only have %d\n", size, N_URB_TD); + return -EINVAL; + } + urb->pipe = pipe; + + /* fill the private part of the URB */ + urb->length = size; + urb->ed = ed; + urb->actual_length = 0; + + /* allocate the TDs */ + /* note that td[0] was allocated in ep_add_ed */ + for (i = 0; i < size; i++) { + urb->td[i] = td_alloc(dev); + if (!urb->td[i]) { + urb->length = i; + urb_free_priv(urb); + return -ENOMEM; + } + } + + if (ed->state == ED_NEW || (ed->state & ED_DEL)) { + urb_free_priv(urb); + return -EINVAL; + } + + /* 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, urb, interval); + + return 0; +} + +static inline int sohci_return_job(struct ohci *hc, struct urb_priv *urb) +{ +#ifdef ENBALE_PIPE_INTERRUPT + struct ohci_regs *regs = hc->regs; +#endif + + switch (usb_pipetype(urb->pipe)) { + case PIPE_INTERRUPT: +#ifdef ENBALE_PIPE_INTERRUPT + /* implicitly requeued */ + if (urb->dev->irq_handle && + (urb->dev->irq_act_len == urb->actual_length)) { + writel(OHCI_INTR_WDH, ®s->intrenable); + readl(®s->intrenable); /* PCI posting flush */ + urb->dev->irq_handle(urb->dev); + writel(OHCI_INTR_WDH, ®s->intrdisable); + readl(®s->intrdisable); /* PCI posting flush */ + } + urb->actual_length = 0; + td_submit_job( + urb->dev, + urb->pipe, + urb->transfer_buffer, + urb->transfer_buffer_length, + NULL, + urb, + urb->interval); +#endif + break; + case PIPE_CONTROL: + case PIPE_BULK: + break; + default: + return 0; + } + return 1; +} + +#ifdef DEBUG +/* tell us the current USB frame number */ + +static int sohci_get_current_frame_number(struct usb_device *usb_dev) +{ + struct usb_host *host = usb_dev->host; + struct ohci *ohci = to_ohci(host); + + return m16_swap(ohci->hcca->frame_no); +} +#endif + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* search for the right branch to insert an interrupt ed into the int tree + * do some load ballancing; + * returns the branch and + * sets the interval to interval = 2^integer (ld (interval)) */ + +static int ep_int_ballance(struct ohci *ohci, int interval, int load) +{ + int i, branch = 0; + + /* search for the least loaded interrupt endpoint + * branch of all 32 branches + */ + for (i = 0; i < 32; i++) + if (ohci->ohci_int_load[branch] > ohci->ohci_int_load[i]) + branch = i; + + branch = branch % interval; + for (i = branch; i < 32; i += interval) + ohci->ohci_int_load[i] += load; + + return branch; +} + +/* 2^int( ld (inter)) */ + +static int ep_2_n_interval(int inter) +{ + int i; + + for (i = 0; ((inter >> i) > 1) && (i < 5); i++) + ; + + return 1 << i; +} + +/* the int tree is a binary tree + * in order to process it sequentially the indexes of the branches have to + * be mapped the mapping reverses the bits of a word of num_bits length */ +static int ep_rev(int num_bits, int word) +{ + int i, wout = 0; + + for (i = 0; i < num_bits; i++) + wout |= (((word >> i) & 1) << (num_bits - i - 1)); + return wout; +} + +/*-------------------------------------------------------------------------* + * ED handling functions + *-------------------------------------------------------------------------*/ + +/* link an ed into one of the HC chains */ + +static int ep_link(struct ohci *ohci, struct ed *edi) +{ + volatile struct ed *ed = edi; + int int_branch; + int i; + int inter; + int interval; + int load; + __u32 *ed_p; + + ed->state = ED_OPER; + ed->int_interval = 0; + + switch (ed->type) { + case PIPE_CONTROL: + ed->hwNextED = 0; + if (ohci->ed_controltail == NULL) + writel(virt_to_phys((void *)ed), &ohci->regs->ed_controlhead); + else + ohci->ed_controltail->hwNextED = + virt_to_phys((void *)m32_swap((unsigned long)ed)); + + ed->ed_prev = ohci->ed_controltail; + if (!ohci->ed_controltail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1]) { + 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(virt_to_phys((void *)ed), &ohci->regs->ed_bulkhead); + else + ohci->ed_bulktail->hwNextED = + virt_to_phys((void *)m32_swap((unsigned long)ed)); + + ed->ed_prev = ohci->ed_bulktail; + if (!ohci->ed_bulktail && !ohci->ed_rm_list[0] && + !ohci->ed_rm_list[1]) { + ohci->hc_control |= OHCI_CTRL_BLE; + writel(ohci->hc_control, &ohci->regs->control); + } + ohci->ed_bulktail = edi; + break; + + case PIPE_INTERRUPT: + load = ed->int_load; + interval = ep_2_n_interval(ed->int_period); + ed->int_interval = interval; + int_branch = ep_int_ballance(ohci, interval, load); + ed->int_branch = int_branch; + + for (i = 0; i < ep_rev(6, interval); i += inter) { + inter = 1; + for (ed_p = &(ohci->hcca->int_table[ep_rev(5, i) + int_branch]); + (*ed_p != 0) && + (((struct ed *)ed_p)->int_interval >= interval); + ed_p = &(((struct ed *)ed_p)->hwNextED)) + inter = ep_rev(6, + ((struct ed *)ed_p)->int_interval); + ed->hwNextED = *ed_p; + *ed_p = m32_swap((unsigned long)ed); + } + break; + } + return 0; +} + +/* scan the periodic table to find and unlink this ED */ +static void periodic_unlink(struct ohci *ohci, volatile struct ed *ed, + unsigned index, unsigned period) +{ + for (; index < NUM_INTS; index += period) { + __u32 *ed_p = &ohci->hcca->int_table[index]; + + /* ED might have been unlinked through another path */ + while (*ed_p != 0) { + if (((struct ed *) + m32_swap((unsigned long)ed_p)) == ed) { + *ed_p = ed->hwNextED; + break; + } + ed_p = &(((struct ed *) + m32_swap((unsigned long)ed_p))->hwNextED); + } + } +} + +/* + * 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(struct ohci *ohci, struct ed *edi) +{ + volatile struct ed *ed = edi; + int i; + + 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 { + ((struct ed *)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 { + ((struct ed *)m32_swap( + *((__u32 *)&ed->hwNextED)))->ed_prev = ed->ed_prev; + } + break; + + case PIPE_INTERRUPT: + periodic_unlink(ohci, ed, 0, 1); + for (i = ed->int_branch; i < 32; i += ed->int_interval) + ohci->ohci_int_load[i] -= ed->int_load; + 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 struct ed *ep_add_ed(struct usb_device *usb_dev, unsigned long pipe, + int interval, int load) +{ + struct usb_host *host = usb_dev->host; + struct ohci *ohci = to_ohci(host); + struct ohci_device *ohci_dev = ohci->ohci_dev; + struct td *td; + struct ed *ed_ret; + volatile struct ed *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\n"); + /* pending delete request */ + return NULL; + } + + if (ed->state == ED_NEW) { + /* dummy td; end of td list for ed */ + td = td_alloc(usb_dev); + ed->hwTailP = virt_to_phys((void *)m32_swap((unsigned long)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); + + if (ed->type == PIPE_INTERRUPT && ed->state == ED_UNLINK) { + ed->int_period = interval; + ed->int_load = load; + } + + return ed_ret; +} + +/*-------------------------------------------------------------------------* + * TD handling functions + *-------------------------------------------------------------------------*/ + +/* + * enqueue next TD for this URB (OHCI spec 5.2.8.2) + */ +static void td_fill(struct ohci *ohci, unsigned int info, + void *data, int len, + struct usb_device *dev, int index, struct urb_priv *urb_priv) +{ + volatile struct td *td, *td_pt; +#ifdef OHCI_FILL_TRACE + int i; +#endif + if (index > urb_priv->length) { + err("index > length\n"); + 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] = + (struct td *)(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 (usb_pipebulk(urb_priv->pipe) && usb_pipeout(urb_priv->pipe)) { + for (i = 0; i < len; i++) + printf("td->data[%d] %#2x ", i, ((unsigned char *)td->data)[i]); + printf("\n"); + } +#endif + if (!len) + data = 0; + + td->hwINFO = m32_swap(info); + td->hwCBP = virt_to_phys((void *)m32_swap((unsigned long)data)); + if (data) + td->hwBE = virt_to_phys((void *)m32_swap((unsigned long)(data + len - 1))); + else + td->hwBE = 0; + + td->hwNextTD = virt_to_phys((void *)m32_swap((unsigned long)td_pt)); + + /* append to queue */ + td->ed->hwTailP = td->hwNextTD; +} + +/* + * Prepare all TDs of a transfer + */ +static void td_submit_job(struct usb_device *dev, unsigned long pipe, + void *buffer, int transfer_len, + struct devrequest *setup, struct urb_priv *urb, + int interval) +{ + struct usb_host *host = dev->host; + struct ohci *ohci = to_ohci(host); + 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 = 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++; + + /* start bulk list */ + writel(OHCI_BLF, &ohci->regs->cmdstatus); + + break; + + case PIPE_CONTROL: + /* Setup phase */ + info = TD_CC | TD_DP_SETUP | TD_T_DATA0; + td_fill(ohci, info, setup, 8, dev, cnt++, urb); + + /* Optional Data phase */ + 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); + } + + /* Status phase */ + 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); + + /* start Control list */ + writel(OHCI_CLF, &ohci->regs->cmdstatus); + + break; + + case PIPE_INTERRUPT: + info = usb_pipeout(urb->pipe) ? + TD_CC | TD_DP_OUT | toggle : + TD_CC | TD_R | TD_DP_IN | toggle; + td_fill(ohci, info, data, data_len, dev, cnt++, urb); + break; + } + if (urb->length != cnt) + debug("TD LENGTH %d != CNT %d\n", urb->length, cnt); +} + +/*-------------------------------------------------------------------------* + * Done List handling functions + *-------------------------------------------------------------------------*/ + +/* calculate the transfer length and update the urb */ + +static void dl_transfer_length(struct td *td) +{ + __u32 tdINFO, tdBE, tdCBP; + struct urb_priv *lurb_priv = td->ed->purb; + + tdINFO = m32_swap(td->hwINFO); + tdBE = m32_swap(td->hwBE); + tdCBP = m32_swap(td->hwCBP); + + if (!(usb_pipecontrol(lurb_priv->pipe) && + ((td->index == 0) || (td->index == lurb_priv->length - 1)))) { + if (tdBE != 0) { + __u32 data = virt_to_phys((void *)td->data); + if (td->hwCBP == 0) + lurb_priv->actual_length += tdBE - data + 1; + else + lurb_priv->actual_length += tdCBP - data; + } + } +} + +static void check_status(struct td *td_list) +{ + struct urb_priv *lurb_priv = td_list->ed->purb; + int urb_len = lurb_priv->length; + __u32 *phwHeadP = &td_list->ed->hwHeadP; + int cc; + + cc = TD_CC_GET(m32_swap(td_list->hwINFO)); + if (cc) { + err(" USB-error: %s (%x)\n", cc_to_string[cc], cc); + + if (*phwHeadP & m32_swap(0x1)) { + if (lurb_priv && + ((td_list->index + 1) < urb_len)) { + *phwHeadP = + (lurb_priv->td[urb_len - 1]->hwNextTD &\ + m32_swap(0xfffffff0)) | + (*phwHeadP & m32_swap(0x2)); + + lurb_priv->td_cnt += urb_len - + td_list->index - 1; + } else + *phwHeadP &= m32_swap(0xfffffff2); + } +#ifdef CONFIG_MPC5200 + td_list->hwNextTD = 0; +#endif + } +} + +/* replies to the request have to be on a FIFO basis so + * we reverse the reversed done-list */ +static struct td *dl_reverse_done_list(struct ohci *ohci) +{ + __u32 td_list_hc; + struct td *td_rev = NULL; + struct td *td_list = NULL; + + td_list_hc = m32_swap(ohci->hcca->done_head) & 0xfffffff0; + + ohci->hcca->done_head = 0; + + while (td_list_hc) { + td_list = (struct td *)td_list_hc; + check_status(td_list); + td_list->next_dl_td = td_rev; + td_rev = td_list; + td_list_hc = m32_swap(td_list->hwNextTD) & 0xfffffff0; + } + return td_list; +} + +static void finish_urb(struct ohci *ohci, struct urb_priv *urb, int status) +{ + if ((status & (ED_OPER | ED_UNLINK)) && (urb->state != URB_DEL)) + urb->finished = sohci_return_job(ohci, urb); + else + debug("finish_urb: strange.., ED state %x, \n", status); +} + +/* + * Used to take back a TD from the host controller. This would normally be + * called from within dl_done_list, however it may be called directly if the + * HC no longer sees the TD and it has not appeared on the donelist (after + * two frames). This bug has been observed on ZF Micro systems. + */ +static int takeback_td(struct ohci *ohci, struct td *td_list) +{ + struct ed *ed; + int cc; + int stat = 0; + struct urb_priv *lurb_priv; + __u32 tdINFO, edHeadP, edTailP; + + tdINFO = m32_swap(td_list->hwINFO); + + ed = td_list->ed; + lurb_priv = ed->purb; + + dl_transfer_length(td_list); + + lurb_priv->td_cnt++; + + /* error code of transfer */ + cc = TD_CC_GET(tdINFO); + if (cc) { + err("USB-error: %s (%x)\n", cc_to_string[cc], cc); + stat = cc_to_error[cc]; + } + + /* see if this done list makes for all TD's of current URB, + * and mark the URB finished if so */ + if (lurb_priv->td_cnt == lurb_priv->length) + finish_urb(ohci, lurb_priv, ed->state); + + debug("dl_done_list: processing TD %x, len %x\n", + lurb_priv->td_cnt, lurb_priv->length); + + if (ed->state != ED_NEW && (!usb_pipeint(lurb_priv->pipe))) { + 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); + } + return stat; +} + +static int dl_done_list(struct ohci *ohci) +{ + struct td *ptd = ohci->ptd; + int stat = 0; + unsigned long ptdphys = virt_to_phys(ptd); + struct td *td_list; + + dma_clean_range(ptdphys, ptdphys + (sizeof(struct td) * NUM_TD)); + + td_list = dl_reverse_done_list(ohci); + + while (td_list) { + struct td *td_next = td_list->next_dl_td; + stat = takeback_td(ohci, td_list); + td_list = td_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 */ + +static inline void wr_rh_portstat(struct ohci *ohci, int wIndex, __u32 value) +{ + info("WR:portstatus[%d] %#8x\n", wIndex - 1, value); + writel(value, &ohci->regs->roothub.portstatus[wIndex-1]); +} + +/* request to virtual root hub */ + +int rh_check_port_status(struct ohci *controller) +{ + __u32 temp, ndp, i; + int res; + + res = -1; + temp = roothub_a(controller); + ndp = (temp & RH_A_NDP); +#ifdef CONFIG_AT91C_PQFP_UHPBUG + ndp = (ndp == 2) ? 1 : 0; +#endif + 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) +{ + struct usb_host *host = dev->host; + struct ohci *ohci = to_ohci(host); + 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; + + pkt_print(NULL, dev, pipe, buffer, transfer_len, + cmd, "SUB(rh)", usb_pipein(pipe)); + + if (usb_pipeint(pipe)) { + info("Root-Hub submit IRQ: NOT implemented\n"); + return 0; + } + + bmRType_bReq = cmd->requesttype | (cmd->request << 8); + wValue = le16_to_cpu(cmd->value); + wIndex = le16_to_cpu(cmd->index); + wLength = le16_to_cpu(cmd->length); + + info("Root-Hub: adr: %2x cmd(%1x): %08x %04x %04x %04x\n", + 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 = cpu_to_le16(1); + len = 2; + break; + case RH_GET_STATUS | RH_INTERFACE: + *(__u16 *) data_buf = cpu_to_le16(0); + len = 2; + break; + case RH_GET_STATUS | RH_ENDPOINT: + *(__u16 *) data_buf = cpu_to_le16(0); + len = 2; + break; + case RH_GET_STATUS | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32( + roothub_status(ohci) & ~(RH_HS_CRWE | RH_HS_DRWE)); + len = 4; + break; + case RH_GET_STATUS | RH_OTHER | RH_CLASS: + *(__u32 *) data_buf = cpu_to_le32(roothub_portstatus(ohci, wIndex - 1)); + len = 4; + break; + + case RH_CLEAR_FEATURE | RH_ENDPOINT: + switch (wValue) { + case RH_ENDPOINT_STALL: + len = 0; + break; + } + break; + + case RH_CLEAR_FEATURE | RH_CLASS: + switch (wValue) { + case RH_C_HUB_LOCAL_POWER: + len = 0; + break; + case RH_C_HUB_OVER_CURRENT: + writel(RH_HS_OCIC, &ohci->regs->roothub.status); + len = 0; + break; + } + break; + + case RH_CLEAR_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case RH_PORT_ENABLE: + wr_rh_portstat(ohci, wIndex, RH_PS_CCS); + len = 0; + break; + case RH_PORT_SUSPEND: + wr_rh_portstat(ohci, wIndex, RH_PS_POCI); + len = 0; + break; + case RH_PORT_POWER: + wr_rh_portstat(ohci, wIndex, RH_PS_LSDA); + len = 0; + break; + case RH_C_PORT_CONNECTION: + wr_rh_portstat(ohci, wIndex, RH_PS_CSC); + len = 0; + break; + case RH_C_PORT_ENABLE: + wr_rh_portstat(ohci, wIndex, RH_PS_PESC); + len = 0; + break; + case RH_C_PORT_SUSPEND: + wr_rh_portstat(ohci, wIndex, RH_PS_PSSC); + len = 0; + break; + case RH_C_PORT_OVER_CURRENT: + wr_rh_portstat(ohci, wIndex, RH_PS_OCIC); + len = 0; + break; + case RH_C_PORT_RESET: + wr_rh_portstat(ohci, wIndex, RH_PS_PRSC); + len = 0; + break; + } + break; + + case RH_SET_FEATURE | RH_OTHER | RH_CLASS: + switch (wValue) { + case RH_PORT_SUSPEND: + wr_rh_portstat(ohci, wIndex, RH_PS_PSS); + len = 0; + break; + case RH_PORT_RESET: /* BUG IN HUP CODE *********/ + if (roothub_portstatus(ohci, wIndex - 1) & RH_PS_CCS) + wr_rh_portstat(ohci, wIndex, RH_PS_PRS); + len = 0; + break; + case RH_PORT_POWER: + wr_rh_portstat(ohci, wIndex, RH_PS_PPS); + mdelay(100); + len = 0; + break; + case RH_PORT_ENABLE: /* BUG IN HUP CODE *********/ + if (roothub_portstatus(ohci, wIndex - 1) & RH_PS_CCS) + wr_rh_portstat(ohci, wIndex, RH_PS_PES); + len = 0; + break; + } + break; + + case RH_SET_ADDRESS: + ohci->rh.devnum = wValue; + len = 0; + break; + + 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; + break; + 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; + break; + 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; + break; + } + 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; + break; + } + default: + stat = USB_ST_STALLED; + } + break; + + case RH_GET_DESCRIPTOR | RH_CLASS: + { + __u32 temp = roothub_a(ohci); + + data_buf[0] = 9; /* min length; */ + data_buf[1] = 0x29; + data_buf[2] = temp & RH_A_NDP; +#ifdef CONFIG_AT91C_PQFP_UHPBUG + data_buf[2] = (data_buf[2] == 2) ? 1 : 0; +#endif + 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(ohci); + 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)); + break; + } + + case RH_GET_CONFIGURATION: + *(__u8 *) data_buf = 0x01; + len = 1; + break; + + case RH_SET_CONFIGURATION: + writel(0x10000, &ohci->regs->roothub.status); + len = 0; + break; + + default: + debug("unsupported root hub command\n"); + stat = USB_ST_STALLED; + } + + ohci_dump_roothub(ohci, 1); + + len = min_t(int, len, leni); + + if (data != data_buf) + memcpy(data, data_buf, len); + + dev->act_len = len; + dev->status = stat; + + pkt_print(NULL, dev, pipe, buffer, + transfer_len, cmd, "RET(rh)", 0/*usb_pipein(pipe)*/); + + 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 timeout) +{ + struct usb_host *host = dev->host; + struct ohci *ohci = to_ohci(host); + int ret, stat = 0; + int maxsize = usb_maxpacket(dev, pipe); + struct urb_priv *urb; + uint64_t start; + + urb = xzalloc(sizeof(struct urb_priv)); + + urb->dev = dev; + urb->pipe = pipe; + urb->transfer_buffer = buffer; + urb->transfer_buffer_length = transfer_len; + urb->interval = interval; + + urb->actual_length = 0; + + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); + + if (!maxsize) + return -EINVAL; + + ret = sohci_submit_job(urb, setup); + if (ret) { + err("sohci_submit_job failed with %d\n", ret); + return ret; + } + + start = get_time_ns(); + + /* wait for it to complete */ + for (;;) { + /* check whether the controller is done */ + stat = hc_interrupt(ohci); + if (stat < 0 || urb->finished) + break; + + if (is_timeout(start, timeout * MSECOND)) { + info("CTL:TIMEOUT\n"); + debug("%s: TO status %x\n", __func__, stat); + urb->finished = 1; + ep_unlink(ohci, urb->ed); + stat = USB_ST_CRC_ERR; + break; + } + } + + dev->status = stat; + dev->act_len = urb->actual_length; + + pkt_print(urb, dev, pipe, buffer, transfer_len, + setup, "RET(ctlr)", usb_pipein(pipe)); + + /* free TDs in urb_priv */ + if (!usb_pipeint(pipe)) + urb_free_priv(urb); + + return 0; +} + +/* submit routines called from usb.c */ +static int submit_bulk_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int timeout) +{ + info("submit_bulk_msg\n"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, 0, timeout); +} + +static int submit_control_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, struct devrequest *setup, int timeout) +{ + struct usb_host *host = dev->host; + struct ohci *ohci = to_ohci(host); + int maxsize = usb_maxpacket(dev, pipe); + + info("submit_control_msg\n"); + + pkt_print(NULL, dev, pipe, buffer, transfer_len, + setup, "SUB", usb_pipein(pipe)); + + if (!maxsize) { + err("submit_control_message: pipesize for pipe %lx is zero\n", + pipe); + return -1; + } + if (((pipe >> 8) & 0x7f) == ohci->rh.devnum) { + ohci->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, timeout); +} + +static int submit_int_msg(struct usb_device *dev, unsigned long pipe, void *buffer, + int transfer_len, int interval) +{ + info("submit_int_msg\n"); + return submit_common_msg(dev, pipe, buffer, transfer_len, NULL, + interval, 100); +} + +/*-------------------------------------------------------------------------* + * HC functions + *-------------------------------------------------------------------------*/ + +/* reset the HC and BUS */ + +static int hc_reset(struct ohci *ohci) +{ + int timeout = 30; + int smm_timeout = 50; /* 0,5 sec */ + + debug("%s\n", __func__); + + 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\n"); + while (readl(&ohci->regs->control) & OHCI_CTRL_IR) { + mdelay(10); + if (--smm_timeout == 0) { + err("USB HC TakeOver failed!\n"); + return -1; + } + } + } + + /* Disable HC interrupts */ + writel(OHCI_INTR_MIE, &ohci->regs->intrdisable); + + debug("USB HC reset_hc usb-%s: ctrl = 0x%X ;\n", + ohci->slot_name, + readl(&ohci->regs->control)); + + /* Reset USB (needed by some controllers) */ + ohci->hc_control = 0; + writel(ohci->hc_control, &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!\n"); + 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(struct ohci *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(virt_to_phys((void *)(__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 */ + + /* 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; +} + +static int hc_interrupt(struct ohci *ohci) +{ + struct ohci_regs *regs = ohci->regs; + int ints; + int stat = 0; + + ints = readl(®s->intrstatus); + ints &= readl(®s->intrenable); + + if (!ints) + return 0; + + debug("Interrupt: %x frame: %x", ints, + le16_to_cpu(ohci->hcca->frame_no)); + + if (ints & OHCI_INTR_UE) { + ohci->disabled++; + err("OHCI Unrecoverable Error, controller usb-%s disabled\n", + ohci->slot_name); + /* e.g. due to PCI Master/Target Abort */ + + ohci_dump(ohci, 1); + + /* 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 -EIO; + } + + if (ints & OHCI_INTR_WDH) { + writel(OHCI_INTR_WDH, ®s->intrdisable); + readl(®s->intrdisable); /* flush */ + + stat = dl_done_list(ohci); + + writel(OHCI_INTR_WDH, ®s->intrenable); + readl(®s->intrdisable); /* flush */ + } + + if (ints & OHCI_INTR_SO) { + debug("USB Schedule overrun\n"); + writel(OHCI_INTR_SO, ®s->intrenable); + stat = -EINVAL; + } + + writel(ints, ®s->intrstatus); + + return stat; +} + +/* De-allocate all resources.. */ + +static void hc_release_ohci(struct ohci *ohci) +{ + debug("USB HC release ohci usb-%s\n", ohci->slot_name); + + if (!ohci->disabled) + hc_reset(ohci); +} + +static int ohci_init(struct usb_host *host) +{ + struct ohci *ohci = to_ohci(host); + + info("%s\n", __func__); + + ohci->ptd = dma_alloc_coherent(sizeof(struct td) * NUM_TD); + if (!ohci->ptd) + return -ENOMEM; + memset(ohci->ptd, 0, sizeof(struct td) * NUM_TD); + + ohci->disabled = 1; + ohci->irq = -1; + + ohci->flags = 0; + ohci->slot_name = "ohci"; /* FIXME */ + + if (hc_reset(ohci) < 0) { + hc_release_ohci(ohci); + err("can't reset usb-%s\n", ohci->slot_name); + return -1; + } + + if (hc_start(ohci) < 0) { + err("can't start usb-%s\n", ohci->slot_name); + hc_release_ohci(ohci); + /* Initialization failed */ + return -1; + } + + ohci_dump(ohci, 1); + + return 0; +} + +static int ohci_probe(struct device_d *dev) +{ + struct usb_host *host; + struct ohci *ohci; + + ohci = xzalloc(sizeof(struct ohci)); + host = &ohci->host; + + host->init = ohci_init; + host->submit_int_msg = submit_int_msg; + host->submit_control_msg = submit_control_msg; + host->submit_bulk_msg = submit_bulk_msg; + + ohci->hcca = dma_alloc_coherent(sizeof(*ohci->hcca)); + if (!ohci->hcca) + return -ENOMEM; + + ohci->ohci_dev = dma_alloc_coherent(sizeof(*ohci->ohci_dev)); + if (!ohci->ohci_dev) + return -ENOMEM; + memset(ohci->ohci_dev, 0, sizeof(*ohci->ohci_dev)); + + usb_register_host(host); + + ohci->regs = (void *)dev->resource[0].start; + + return 0; +} + +static struct driver_d ohci_driver = { + .name = "ohci", + .probe = ohci_probe, +}; + +static int ohcil_init(void) +{ + register_driver(&ohci_driver); + return 0; +} + +device_initcall(ohcil_init); + diff --git a/drivers/usb/host/ohci.h b/drivers/usb/host/ohci.h new file mode 100644 index 0000000000..913296319e --- /dev/null +++ b/drivers/usb/host/ohci.h @@ -0,0 +1,428 @@ +/* + * URB OHCI HCD (Host Controller Driver) for USB. + * + * (C) Copyright 1999 Roman Weissgaerber <weissg@vienna.at> + * (C) Copyright 2000-2001 David Brownell <dbrownell@users.sourceforge.net> + * + * usb-ohci.h + */ + +/* functions for doing board or CPU specific setup/cleanup */ +extern int usb_board_init(void); +extern int usb_board_stop(void); +extern int usb_board_init_fail(void); + +extern int usb_cpu_init(void); +extern int usb_cpu_stop(void); +extern int usb_cpu_init_fail(void); + +/* map OHCI TD status codes (CC) to errno values */ +static const int __maybe_unused cc_to_error[16] = { + /* No Error */ 0, + /* CRC Error */ -EILSEQ, + /* Bit Stuff */ -EPROTO, + /* Data Togg */ -EILSEQ, + /* Stall */ -EPIPE, + /* DevNotResp */ -ETIME, + /* PIDCheck */ -EPROTO, + /* UnExpPID */ -EPROTO, + /* DataOver */ -EOVERFLOW, + /* DataUnder */ -EREMOTEIO, + /* (for hw) */ -EIO, + /* (for hw) */ -EIO, + /* BufferOver */ -ECOMM, + /* BuffUnder */ -ENOSR, + /* (for HCD) */ -EALREADY, + /* (for HCD) */ -EALREADY +}; + +static const char __maybe_unused *cc_to_string[16] = { + "No Error", + "CRC: Last data packet from endpoint contained a CRC error.", + "BITSTUFFING: Last data packet from endpoint contained a bit " \ + "stuffing violation", + "DATATOGGLEMISMATCH: Last packet from endpoint had data toggle PID\n" \ + "that did not match the expected value.", + "STALL: TD was moved to the Done Queue because the endpoint returned" \ + " a STALL PID", + "DEVICENOTRESPONDING: Device did not respond to token (IN) or did\n" \ + "not provide a handshake (OUT)", + "PIDCHECKFAILURE: Check bits on PID from endpoint failed on data PID\n"\ + "(IN) or handshake (OUT)", + "UNEXPECTEDPID: Receive PID was not valid when encountered or PID\n" \ + "value is not defined.", + "DATAOVERRUN: The amount of data returned by the endpoint exceeded\n" \ + "either the size of the maximum data packet allowed\n" \ + "from the endpoint (found in MaximumPacketSize field\n" \ + "of ED) or the remaining buffer size.", + "DATAUNDERRUN: The endpoint returned less than MaximumPacketSize\n" \ + "and that amount was not sufficient to fill the\n" \ + "specified buffer", + "reserved1", + "reserved2", + "BUFFEROVERRUN: During an IN, HC received data from endpoint faster\n" \ + "than it could be written to system memory", + "BUFFERUNDERRUN: During an OUT, HC could not retrieve data from\n" \ + "system memory fast enough to keep up with data USB " \ + "data rate.", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(1)", + "NOT ACCESSED: This code is set by software before the TD is placed" \ + "on a list to be processed by the HC.(2)", +}; + +/* 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; + void *purb; + __u32 unused[2]; +} __attribute__((aligned(16))); + +/* TD info field */ +#define TD_CC 0xf0000000 +#define TD_CC_GET(td_p) ((td_p >> 28) & 0x0f) +#define TD_CC_SET(td_p, cc) do { \ + (td_p) = ((td_p) & 0x0fffffff) | (((cc) & 0x0f) << 28); \ + } while (0); +#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))); + +#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 */ + /* + * OHCI defines u16 frame_no, followed by u16 zero pad. + * Since some processors can't do 16 bit bus accesses, + * portable access must be a 32 bits wide. + */ + __u16 frame_no; /* current frame number */ + __u16 pad1; + __u32 done_head; /* info returned for an interrupt */ + u8 reserved_for_hc[116]; +} __attribute__((aligned(256))); + +/* + * 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[15]; + } roothub; +} __attribute__((aligned(32))); + +/* Some EHCI controls */ +#define EHCI_USBCMD_OFF 0x20 +#define EHCI_USBCMD_HCRESET (1 << 1) + +/* 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 +struct urb_priv { + struct ed *ed; + __u16 length; /* number of tds associated with this request */ + __u16 td_cnt; /* number of tds already serviced */ + struct usb_device *dev; + int state; + unsigned long pipe; + void *transfer_buffer; + int transfer_buffer_length; + int interval; + int actual_length; + int finished; + struct td *td[N_URB_TD]; /* list pointer to all corresponding TDs associated with this request */ +}; +#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) + */ + +#define NUM_EDS 8 /* num of preallocated endpoint descriptors */ + +struct ohci_device { + struct ed ed[NUM_EDS]; + int ed_cnt; +}; + +struct ohci { + struct usb_host host; + struct ohci_hcca *hcca; /* hcca */ + /*dma_addr_t hcca_dma;*/ + + int irq; + int disabled; /* e.g. got a UE, we're hung */ + unsigned long flags; /* for HC bugs */ + + struct ohci_regs *regs; /* OHCI controller's memory */ + + int ohci_int_load[32]; /* load of the 32 Interrupt Chains (for load balancing)*/ + struct ed *ed_rm_list[2]; /* lists of all endpoints to be removed */ + struct ed *ed_bulktail; /* last endpoint of bulk list */ + struct ed *ed_controltail; /* last endpoint of control list */ + int intrstatus; + __u32 hc_control; /* copy of the hc control reg */ + struct virt_root_hub rh; + + const char *slot_name; + struct ohci_device *ohci_dev; + struct td *ptd; +}; + +/* we need more TDs than EDs */ +#define NUM_TD 64 + diff --git a/drivers/usb/otg/ulpi.c b/drivers/usb/otg/ulpi.c index 4a898fb223..6ed6f01e8e 100644 --- a/drivers/usb/otg/ulpi.c +++ b/drivers/usb/otg/ulpi.c @@ -17,7 +17,7 @@ */ #include <common.h> -#include <asm/io.h> +#include <io.h> #include <errno.h> #include <usb/ulpi.h> diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig new file mode 100644 index 0000000000..f6c8c06b1e --- /dev/null +++ b/drivers/usb/storage/Kconfig @@ -0,0 +1,2 @@ +config USB_STORAGE + tristate "USB Mass Storage support" diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile new file mode 100644 index 0000000000..adf08433d5 --- /dev/null +++ b/drivers/usb/storage/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_USB_STORAGE) += usb-storage.o + +usb-storage-objs := usb.o transport.o + diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c new file mode 100644 index 0000000000..e7a5972750 --- /dev/null +++ b/drivers/usb/storage/transport.c @@ -0,0 +1,251 @@ +/* + * Most of this source has been derived from the Linux and + * U-Boot USB Mass Storage driver implementations. + * + * Adapted for barebox: + * Copyright (c) 2011, AMK Drives & Controls Ltd. + * + * 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 <common.h> +#include <clock.h> +#include <scsi.h> +#include <errno.h> + +#undef USB_STOR_DEBUG + +#include "usb.h" +#include "transport.h" + + +/* The timeout argument of usb_bulk_msg() is actually ignored + and the timeout is hardcoded in the host driver */ +#define USB_BULK_TO 5000 + +static __u32 cbw_tag = 0; + +/* direction table -- this indicates the direction of the data + * transfer for each command code (bit-encoded) -- 1 indicates input + * note that this doesn't work for shared command codes + */ +static const unsigned char us_direction[256/8] = { + 0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77, + 0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x40, 0x09, 0x01, 0x80, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; +#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1) + + +/* + * Bulk only transport + */ + +/* Clear a stall on an endpoint - special for bulk-only devices */ +int usb_stor_Bulk_clear_endpt_stall(struct us_data *us, unsigned int pipe) +{ + return usb_clear_halt(us->pusb_dev, pipe); +} + +/* Determine what the maximum LUN supported is */ +int usb_stor_Bulk_max_lun(struct us_data *us) +{ + int len; + unsigned char iobuf[1]; + + /* issue the command */ + iobuf[0] = 0; + len = usb_control_msg(us->pusb_dev, + usb_rcvctrlpipe(us->pusb_dev, 0), + US_BULK_GET_MAX_LUN, + USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, iobuf, 1, USB_CNTL_TIMEOUT); + + US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", + len, (int)iobuf[0]); + + /* if we have a successful request, return the result */ + if (len > 0) + return (int)iobuf[0]; + + /* + * Some devices don't like GetMaxLUN. They may STALL the control + * pipe, they may return a zero-length result, they may do nothing at + * all and timeout, or they may fail in even more bizarrely creative + * ways. In these cases the best approach is to use the default + * value: only one LUN. + */ + return 0; +} + +int usb_stor_Bulk_transport(ccb *srb, struct us_data *us) +{ + struct bulk_cb_wrap cbw; + struct bulk_cs_wrap csw; + int actlen, data_actlen; + int result; + unsigned int residue; + unsigned int pipein = usb_rcvbulkpipe(us->pusb_dev, us->recv_bulk_ep); + unsigned int pipeout = usb_sndbulkpipe(us->pusb_dev, us->send_bulk_ep); + int dir_in = US_DIRECTION(srb->cmd[0]); + + srb->trans_bytes = 0; + + /* set up the command wrapper */ + cbw.Signature = cpu_to_le32(US_BULK_CB_SIGN); + cbw.DataTransferLength = cpu_to_le32(srb->datalen); + cbw.Flags = (dir_in ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT); + cbw.Tag = ++cbw_tag; + cbw.Lun = srb->lun; + cbw.Length = srb->cmdlen; + + /* copy the command payload */ + memcpy(cbw.CDB, srb->cmd, cbw.Length); + + /* send it to out endpoint */ + US_DEBUGP("Bulk Command S 0x%x T 0x%x L %d F %d Trg %d LUN %d CL %d\n", + le32_to_cpu(cbw.Signature), cbw.Tag, + le32_to_cpu(cbw.DataTransferLength), cbw.Flags, + (cbw.Lun >> 4), (cbw.Lun & 0x0F), + cbw.Length); + result = usb_bulk_msg(us->pusb_dev, pipeout, &cbw, US_BULK_CB_WRAP_LEN, + &actlen, USB_BULK_TO); + US_DEBUGP("Bulk command transfer result=%d\n", result); + if (result < 0) { + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_FAILED; + } + + /* DATA STAGE */ + /* send/receive data payload, if there is any */ + + wait_ms(1); + + data_actlen = 0; + if (srb->datalen) { + unsigned int pipe = dir_in ? pipein : pipeout; + result = usb_bulk_msg(us->pusb_dev, pipe, srb->pdata, + srb->datalen, &data_actlen, USB_BULK_TO); + US_DEBUGP("Bulk data transfer result 0x%x\n", result); + /* special handling of STALL in DATA phase */ + if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) { + US_DEBUGP("DATA: stall\n"); + /* clear the STALL on the endpoint */ + result = usb_stor_Bulk_clear_endpt_stall(us, pipe); + } + if (result < 0) { + US_DEBUGP("Device status: %lx\n", us->pusb_dev->status); + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_FAILED; + } + } + + /* STATUS phase + error handling */ + US_DEBUGP("Attempting to get CSW...\n"); + result = usb_bulk_msg(us->pusb_dev, pipein, &csw, US_BULK_CS_WRAP_LEN, + &actlen, USB_BULK_TO); + + /* did the endpoint stall? */ + if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) { + US_DEBUGP("STATUS: stall\n"); + /* clear the STALL on the endpoint */ + result = usb_stor_Bulk_clear_endpt_stall(us, pipein); + if (result >= 0) { + US_DEBUGP("Attempting to get CSW...\n"); + result = usb_bulk_msg(us->pusb_dev, pipein, + &csw, US_BULK_CS_WRAP_LEN, + &actlen, USB_BULK_TO); + } + } + + if (result < 0) { + US_DEBUGP("Device status: %lx\n", us->pusb_dev->status); + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_FAILED; + } + + /* check bulk status */ + residue = le32_to_cpu(csw.Residue); + US_DEBUGP("Bulk Status S 0x%x T 0x%x R %u Stat 0x%x\n", + le32_to_cpu(csw.Signature), csw.Tag, residue, csw.Status); + if (csw.Signature != cpu_to_le32(US_BULK_CS_SIGN)) { + US_DEBUGP("Bad CSW signature\n"); + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_FAILED; + } else if (csw.Tag != cbw_tag) { + US_DEBUGP("Mismatching tag\n"); + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_FAILED; + } else if (csw.Status >= US_BULK_STAT_PHASE) { + US_DEBUGP("Status >= phase\n"); + usb_stor_Bulk_reset(us); + return USB_STOR_TRANSPORT_ERROR; + } else if (residue > srb->datalen) { + US_DEBUGP("residue (%uB) > req data (%luB)\n", + residue, srb->datalen); + return USB_STOR_TRANSPORT_FAILED; + } else if (csw.Status == US_BULK_STAT_FAIL) { + US_DEBUGP("FAILED\n"); + return USB_STOR_TRANSPORT_FAILED; + } + srb->trans_bytes = min(srb->datalen - residue, (ulong)data_actlen); + + return 0; +} + + +/* This issues a Bulk-only Reset to the device in question, including + * clearing the subsequent endpoint halts that may occur. + */ +int usb_stor_Bulk_reset(struct us_data *us) +{ + int result; + int result2; + unsigned int pipe; + + US_DEBUGP("%s called\n", __func__); + + /* issue the command */ + result = usb_control_msg(us->pusb_dev, + usb_sndctrlpipe(us->pusb_dev, 0), + US_BULK_RESET_REQUEST, + USB_TYPE_CLASS | USB_RECIP_INTERFACE, + 0, us->ifnum, 0, 0, USB_CNTL_TIMEOUT); + if ((result < 0) && (us->pusb_dev->status & USB_ST_STALLED)) { + US_DEBUGP("Soft reset stalled: %d\n", result); + return result; + } + wait_ms(150); + + /* clear the bulk endpoints halt */ + US_DEBUGP("Soft reset: clearing %s endpoint halt\n", "bulk-in"); + pipe = usb_rcvbulkpipe(us->pusb_dev, us->recv_bulk_ep); + result = usb_clear_halt(us->pusb_dev, pipe); + wait_ms(150); + US_DEBUGP("Soft reset: clearing %s endpoint halt\n", "bulk-out"); + pipe = usb_sndbulkpipe(us->pusb_dev, us->send_bulk_ep); + result2 = usb_clear_halt(us->pusb_dev, pipe); + wait_ms(150); + + if (result >= 0) + result = result2; + US_DEBUGP("Soft reset %s\n", ((result < 0) ? "failed" : "done")); + + return result; +} + diff --git a/drivers/usb/storage/transport.h b/drivers/usb/storage/transport.h new file mode 100644 index 0000000000..1c5c1417db --- /dev/null +++ b/drivers/usb/storage/transport.h @@ -0,0 +1,95 @@ +/* + * Most of this source has been derived from the Linux and + * U-Boot USB Mass Storage driver implementations. + * + * Adapted for barebox: + * Copyright (c) 2011, AMK Drives & Controls Ltd. + * + * 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 _TRANSPORT_H_ +#define _TRANSPORT_H_ + +#include <scsi.h> + +/* + * Bulk only data structures + */ + +/* command block wrapper */ +struct bulk_cb_wrap { + __le32 Signature; /* contains 'USBC' */ + __u32 Tag; /* unique per command id */ + __le32 DataTransferLength; /* size of data */ + __u8 Flags; /* direction in bit 7 */ + __u8 Lun; /* LUN normally 0 */ + __u8 Length; /* of of the CDB */ + __u8 CDB[16]; /* max command */ +}; + +#define US_BULK_CB_WRAP_LEN 31 +#define US_BULK_CB_SIGN 0x43425355 /*spells out USBC */ +#define US_BULK_FLAG_IN (1<<7) +#define US_BULK_FLAG_OUT (0<<7) + +/* command status wrapper */ +struct bulk_cs_wrap { + __le32 Signature; /* should = 'USBS' */ + __u32 Tag; /* same as original command */ + __le32 Residue; /* amount not transferred */ + __u8 Status; /* see below */ + __u8 Filler[18]; +}; + +#define US_BULK_CS_WRAP_LEN 13 +#define US_BULK_CS_SIGN 0x53425355 /* spells out 'USBS' */ +#define US_BULK_STAT_OK 0 +#define US_BULK_STAT_FAIL 1 +#define US_BULK_STAT_PHASE 2 + +/* bulk-only class specific requests */ +#define US_BULK_RESET_REQUEST 0xff +#define US_BULK_GET_MAX_LUN 0xfe + +/* + * usb_stor_bulk_transfer_xxx() return codes, in order of severity + */ + +#define USB_STOR_XFER_GOOD 0 /* good transfer */ +#define USB_STOR_XFER_SHORT 1 /* transferred less than expected */ +#define USB_STOR_XFER_STALLED 2 /* endpoint stalled */ +#define USB_STOR_XFER_LONG 3 /* device tried to send too much */ +#define USB_STOR_XFER_ERROR 4 /* transfer died in the middle */ + +/* + * Transport return codes + */ + +#define USB_STOR_TRANSPORT_GOOD 0 /* Transport good, command good */ +#define USB_STOR_TRANSPORT_FAILED 1 /* Transport good, command failed */ +#define USB_STOR_TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */ +#define USB_STOR_TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */ + + +struct us_data; + +extern int usb_stor_Bulk_transport(ccb *, struct us_data *); +extern int usb_stor_Bulk_max_lun(struct us_data *); +extern int usb_stor_Bulk_reset(struct us_data *); + +#endif diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c new file mode 100644 index 0000000000..d033b291c2 --- /dev/null +++ b/drivers/usb/storage/usb.c @@ -0,0 +1,619 @@ +/* + * Most of this source has been derived from the Linux and + * U-Boot USB Mass Storage driver implementations. + * + * Adapted for barebox: + * Copyright (c) 2011, AMK Drives & Controls Ltd. + * + * 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 <common.h> +#include <init.h> +#include <malloc.h> +#include <errno.h> +#include <scsi.h> +#include <usb/usb.h> +#include <usb/usb_defs.h> + +#undef USB_STOR_DEBUG + +#include "usb.h" +#include "transport.h" + + +static LIST_HEAD(us_blkdev_list); + + +/*********************************************************************** + * USB Storage routines + ***********************************************************************/ + +static int usb_stor_inquiry(ccb *srb, struct us_data *us) +{ + int retries, result; + + srb->datalen = min(128UL, srb->datalen); + if (srb->datalen < 5) { + US_DEBUGP("SCSI_INQUIRY: invalid data buffer size\n"); + return -EINVAL; + } + + retries = 3; + do { + US_DEBUGP("SCSI_INQUIRY\n"); + memset(&srb->cmd[0], 0, 6); + srb->cmdlen = 6; + srb->cmd[0] = SCSI_INQUIRY; + srb->cmd[3] = (u8)(srb->datalen >> 8); + srb->cmd[4] = (u8)(srb->datalen >> 0); + result = us->transport(srb, us); + US_DEBUGP("SCSI_INQUIRY returns %d\n", result); + } while ((result != USB_STOR_TRANSPORT_GOOD) && retries--); + + return (result != USB_STOR_TRANSPORT_GOOD) ? -EIO : 0; +} + +static int usb_stor_request_sense(ccb *srb, struct us_data *us) +{ + unsigned char *pdata = srb->pdata; + unsigned long datalen = srb->datalen; + + US_DEBUGP("SCSI_REQ_SENSE\n"); + srb->pdata = &srb->sense_buf[0]; + srb->datalen = 18; + memset(&srb->cmd[0], 0, 6); + srb->cmdlen = 6; + srb->cmd[0] = SCSI_REQ_SENSE; + srb->cmd[4] = (u8)(srb->datalen >> 0); + us->transport(srb, us); + US_DEBUGP("Request Sense returned %02X %02X %02X\n", + srb->sense_buf[2], srb->sense_buf[12], srb->sense_buf[13]); + srb->pdata = pdata; + srb->datalen = datalen; + + return 0; +} + +static int usb_stor_test_unit_ready(ccb *srb, struct us_data *us) +{ + int retries, result; + + retries = 10; + do { + US_DEBUGP("SCSI_TST_U_RDY\n"); + memset(&srb->cmd[0], 0, 6); + srb->cmdlen = 6; + srb->cmd[0] = SCSI_TST_U_RDY; + srb->datalen = 0; + result = us->transport(srb, us); + US_DEBUGP("SCSI_TST_U_RDY returns %d\n", result); + if (result == USB_STOR_TRANSPORT_GOOD) + return 0; + usb_stor_request_sense(srb, us); + wait_ms(100); + } while (retries--); + + return -1; +} + +static int usb_stor_read_capacity(ccb *srb, struct us_data *us) +{ + int retries, result; + + if (srb->datalen < 8) { + US_DEBUGP("SCSI_RD_CAPAC: invalid data buffer size\n"); + return -EINVAL; + } + + retries = 3; + do { + US_DEBUGP("SCSI_RD_CAPAC\n"); + memset(&srb->cmd[0], 0, 10); + srb->cmdlen = 10; + srb->cmd[0] = SCSI_RD_CAPAC; + srb->datalen = 8; + result = us->transport(srb, us); + US_DEBUGP("SCSI_RD_CAPAC returns %d\n", result); + } while ((result != USB_STOR_TRANSPORT_GOOD) && retries--); + + return (result != USB_STOR_TRANSPORT_GOOD) ? -EIO : 0; +} + +static int usb_stor_read_10(ccb *srb, struct us_data *us, + unsigned long start, unsigned short blocks) +{ + int retries, result; + + retries = 2; + do { + US_DEBUGP("SCSI_READ10: start %lx blocks %x\n", start, blocks); + memset(&srb->cmd[0], 0, 10); + srb->cmdlen = 10; + srb->cmd[0] = SCSI_READ10; + srb->cmd[2] = (u8)(start >> 24); + srb->cmd[3] = (u8)(start >> 16); + srb->cmd[4] = (u8)(start >> 8); + srb->cmd[5] = (u8)(start >> 0); + srb->cmd[7] = (u8)(blocks >> 8); + srb->cmd[8] = (u8)(blocks >> 0); + result = us->transport(srb, us); + US_DEBUGP("SCSI_READ10 returns %d\n", result); + if (result == USB_STOR_TRANSPORT_GOOD) + return 0; + usb_stor_request_sense(srb, us); + } while (retries--); + + return -EIO; +} + +static int usb_stor_write_10(ccb *srb, struct us_data *us, + unsigned long start, unsigned short blocks) +{ + int retries, result; + + retries = 2; + do { + US_DEBUGP("SCSI_WRITE10: start %lx blocks %x\n", start, blocks); + memset(&srb->cmd[0], 0, 10); + srb->cmdlen = 10; + srb->cmd[0] = SCSI_WRITE10; + srb->cmd[2] = (u8)(start >> 24); + srb->cmd[3] = (u8)(start >> 16); + srb->cmd[4] = (u8)(start >> 8); + srb->cmd[5] = (u8)(start >> 0); + srb->cmd[7] = (u8)(blocks >> 8); + srb->cmd[8] = (u8)(blocks >> 0); + result = us->transport(srb, us); + US_DEBUGP("SCSI_WRITE10 returns %d\n", result); + if (result == USB_STOR_TRANSPORT_GOOD) + return 0; + usb_stor_request_sense(srb, us); + } while (retries--); + + return us->transport(srb, us); +} + + +/*********************************************************************** + * Disk driver interface + ***********************************************************************/ + +#define US_MAX_IO_BLK 32U + +enum { io_rd, io_wr }; + +/* Read / write a chunk of sectors on media */ +static int usb_stor_blk_io(int io_op, struct device_d *disk_dev, + uint64_t sector_start, unsigned sector_count, + void *buffer) +{ + struct ata_interface *pata_if = disk_dev->platform_data; + struct us_blk_dev *pblk_dev = (struct us_blk_dev *)pata_if->priv; + struct us_data *us = pblk_dev->us; + ccb us_ccb; + ushort const sector_size = 512; + unsigned sectors_done; + + if (sector_count == 0) + return 0; + + /* check for unsupported block size */ + if (pblk_dev->blksz != sector_size) { + US_DEBUGP("%s: unsupported block size %lu\n", + __func__, pblk_dev->blksz); + return -EINVAL; + } + + /* check for invalid sector_start */ + if (sector_start >= pblk_dev->blknum || sector_start > (ulong)-1) { + US_DEBUGP("%s: start sector %llu too large\n", + __func__, sector_start); + return -EINVAL; + } + + us_ccb.lun = pblk_dev->lun; + usb_disable_asynch(1); + + /* ensure unit ready */ + US_DEBUGP("Testing for unit ready\n"); + if (usb_stor_test_unit_ready(&us_ccb, us)) { + US_DEBUGP("Device NOT ready\n"); + usb_disable_asynch(0); + return -EIO; + } + + /* possibly limit the amount of I/O data */ + if (sector_count > INT_MAX) { + sector_count = INT_MAX; + US_DEBUGP("Restricting I/O to %u blocks\n", sector_count); + } + if (sector_start + sector_count > pblk_dev->blknum) { + sector_count = pblk_dev->blknum - sector_start; + US_DEBUGP("Restricting I/O to %u blocks\n", sector_count); + } + + /* read / write the requested data */ + US_DEBUGP("%s %u block(s), starting from %llu\n", + ((io_op == io_rd) ? "Read" : "Write"), + sector_count, sector_start); + sectors_done = 0; + while (sector_count > 0) { + int result; + ushort n = (ushort)min(sector_count, US_MAX_IO_BLK); + us_ccb.pdata = buffer + sectors_done * sector_size; + us_ccb.datalen = n * (ulong)sector_size; + if (io_op == io_rd) + result = usb_stor_read_10(&us_ccb, us, + (ulong)sector_start, n); + else + result = usb_stor_write_10(&us_ccb, us, + (ulong)sector_start, n); + if (result != 0) { + US_DEBUGP("I/O error at sector %llu\n", sector_start); + break; + } + sector_start += n; + sector_count -= n; + sectors_done += n; + } + + usb_disable_asynch(0); + + US_DEBUGP("Successful I/O of %u blocks\n", sectors_done); + + return (sector_count != 0) ? -EIO : 0; +} + +/* Write a chunk of sectors to media */ +static int usb_stor_blk_write(struct device_d *disk_dev, uint64_t sector_start, + unsigned sector_count, const void *buffer) +{ + return usb_stor_blk_io(io_wr, disk_dev, sector_start, sector_count, + (void *)buffer); +} + +/* Read a chunk of sectors from media */ +static int usb_stor_blk_read(struct device_d *disk_dev, uint64_t sector_start, + unsigned sector_count, void *buffer) +{ + return usb_stor_blk_io(io_rd, disk_dev, sector_start, sector_count, + buffer); +} + + +/*********************************************************************** + * Block device routines + ***********************************************************************/ + +static unsigned char us_io_buf[512]; + +/* Prepare a disk device */ +static int usb_stor_init_blkdev(struct us_blk_dev *pblk_dev) +{ + struct us_data *us = pblk_dev->us; + ccb us_ccb; + unsigned long *pcap; + int result = 0; + + us_ccb.pdata = us_io_buf; + us_ccb.lun = pblk_dev->lun; + + pblk_dev->blknum = 0; + usb_disable_asynch(1); + + /* get device info */ + US_DEBUGP("Reading device info\n"); + us_ccb.datalen = 36; + if (usb_stor_inquiry(&us_ccb, us)) { + US_DEBUGP("Cannot read device info\n"); + result = -ENODEV; + goto Exit; + } + US_DEBUGP("Peripheral type: %x, removable: %x\n", + us_io_buf[0], (us_io_buf[1] >> 7)); + US_DEBUGP("ISO ver: %x, resp format: %x\n", us_io_buf[2], us_io_buf[3]); + US_DEBUGP("Vendor/product/rev: %28s\n", &us_io_buf[8]); + // TODO: process and store device info + + /* ensure unit ready */ + US_DEBUGP("Testing for unit ready\n"); + us_ccb.datalen = 0; + if (usb_stor_test_unit_ready(&us_ccb, us)) { + US_DEBUGP("Device NOT ready\n"); + result = -ENODEV; + goto Exit; + } + + /* read capacity */ + US_DEBUGP("Reading capacity\n"); + memset(us_ccb.pdata, 0, 8); + us_ccb.datalen = sizeof(us_io_buf); + if (usb_stor_read_capacity(&us_ccb, us) != 0) { + US_DEBUGP("Cannot read device capacity\n"); + result = -EIO; + goto Exit; + } + pcap = (unsigned long *)us_ccb.pdata; + US_DEBUGP("Read Capacity returns: 0x%lx, 0x%lx\n", pcap[0], pcap[1]); + pblk_dev->blknum = be32_to_cpu(pcap[0]); + pblk_dev->blksz = be32_to_cpu(pcap[1]); + pblk_dev->blknum++; + US_DEBUGP("Capacity = 0x%llx, blocksz = 0x%lx\n", + pblk_dev->blknum, pblk_dev->blksz); + +Exit: + usb_disable_asynch(0); + return result; +} + +/* Create and register a disk device for the specified LUN */ +static int usb_stor_add_blkdev(struct us_data *us, unsigned char lun) +{ + struct us_blk_dev *pblk_dev; + struct device_d *pdev; + struct ata_interface *pata_if; + int result; + + /* allocate blk dev data */ + pblk_dev = (struct us_blk_dev *)malloc(sizeof(struct us_blk_dev)); + if (!pblk_dev) + return -ENOMEM; + memset(pblk_dev, 0, sizeof(struct us_blk_dev)); + + /* initialize blk dev data */ + pblk_dev->us = us; + pblk_dev->lun = lun; + pata_if = &pblk_dev->ata_if; + pata_if->read = &usb_stor_blk_read; + pata_if->write = &usb_stor_blk_write; + pata_if->priv = pblk_dev; + pdev = &pblk_dev->dev; + strcpy(pdev->name, "disk"); + pdev->platform_data = pata_if; + + /* read some info and get the unit ready */ + result = usb_stor_init_blkdev(pblk_dev); + if (result < 0) + goto BadDevice; + + /* register disk device */ + result = register_device(pdev); + if (result < 0) + goto BadDevice; + list_add_tail(&pblk_dev->list, &us_blkdev_list); + US_DEBUGP("USB disk device successfully added\n"); + + return 0; + +BadDevice: + US_DEBUGP("%s failed with %d\n", __func__, result); + free(pblk_dev); + return result; +} + +/*********************************************************************** + * USB Mass Storage device probe and initialization + ***********************************************************************/ + +/* Get the transport settings */ +static void get_transport(struct us_data *us) +{ + switch (us->protocol) { + case US_PR_BULK: + us->transport_name = "Bulk"; + us->transport = &usb_stor_Bulk_transport; + us->transport_reset = &usb_stor_Bulk_reset; + break; + } + + US_DEBUGP("Transport: %s\n", us->transport_name); +} + +/* Get the endpoint settings */ +static int get_pipes(struct us_data *us, struct usb_interface_descriptor *intf) +{ + unsigned int i; + struct usb_endpoint_descriptor *ep; + struct usb_endpoint_descriptor *ep_in = NULL; + struct usb_endpoint_descriptor *ep_out = NULL; + struct usb_endpoint_descriptor *ep_int = NULL; + + /* + * Find the first endpoint of each type we need. + * We are expecting a minimum of 2 endpoints - in and out (bulk). + * An optional interrupt-in is OK (necessary for CBI protocol). + * We will ignore any others. + */ + for (i = 0; i < intf->bNumEndpoints; i++) { + ep = &intf->ep_desc[i]; + + if (USB_EP_IS_XFER_BULK(ep)) { + if (USB_EP_IS_DIR_IN(ep)) { + if ( !ep_in ) + ep_in = ep; + } + else { + if ( !ep_out ) + ep_out = ep; + } + } + else if (USB_EP_IS_INT_IN(ep)) { + if (!ep_int) + ep_int = ep; + } + } + if (!ep_in || !ep_out || (us->protocol == US_PR_CBI && !ep_int)) { + US_DEBUGP("Endpoint sanity check failed! Rejecting dev.\n"); + return -EIO; + } + + /* Store the pipe values */ + us->send_bulk_ep = USB_EP_NUM(ep_out); + us->recv_bulk_ep = USB_EP_NUM(ep_in); + if (ep_int) { + us->recv_intr_ep = USB_EP_NUM(ep_int); + us->ep_bInterval = ep_int->bInterval; + } + return 0; +} + +/* Scan device's LUNs, registering a disk device for each LUN */ +static int usb_stor_scan(struct usb_device *usbdev, struct us_data *us) +{ + unsigned char lun; + int num_devs = 0; + + /* obtain the max LUN */ + us->max_lun = 0; + if (us->protocol == US_PR_BULK) + us->max_lun = usb_stor_Bulk_max_lun(us); + + /* register a disk device for each active LUN */ + for (lun=0; lun<=us->max_lun; lun++) { + if (usb_stor_add_blkdev(us, lun) == 0) + num_devs++; + } + + US_DEBUGP("Found %d block devices on %s\n", num_devs, usbdev->dev.name); + + return num_devs ? 0 : -ENODEV; +} + +/* Probe routine for standard devices */ +static int usb_stor_probe(struct usb_device *usbdev, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + int ifno; + struct usb_interface_descriptor *intf; + + US_DEBUGP("Supported USB Mass Storage device detected\n"); + + /* scan usbdev interfaces again to find one that we can handle */ + for (ifno=0; ifno<usbdev->config.no_of_if; ifno++) { + intf = &usbdev->config.if_desc[ifno]; + + if (intf->bInterfaceClass == USB_CLASS_MASS_STORAGE && + intf->bInterfaceSubClass == US_SC_SCSI && + intf->bInterfaceProtocol == US_PR_BULK) + break; + } + if (ifno >= usbdev->config.no_of_if) + return -ENXIO; + + /* select the right interface */ + result = usb_set_interface(usbdev, intf->bInterfaceNumber, 0); + if (result) + return result; + + US_DEBUGP("Selected interface %d\n", (int)intf->bInterfaceNumber); + + /* allocate us_data structure */ + us = (struct us_data *)malloc(sizeof(struct us_data)); + if (!us) + return -ENOMEM; + memset(us, 0, sizeof(struct us_data)); + + /* initialize the us_data structure */ + us->pusb_dev = usbdev; + us->flags = 0; + us->ifnum = intf->bInterfaceNumber; + us->subclass = intf->bInterfaceSubClass; + us->protocol = intf->bInterfaceProtocol; + + /* get standard transport and protocol settings */ + get_transport(us); + + /* find the endpoints needed by the transport */ + result = get_pipes(us, intf); + if (result) + goto BadDevice; + + /* register a disk device for each LUN */ + usb_stor_scan(usbdev, us); + + /* associate the us_data structure with the usb_device */ + usbdev->drv_data = us; + + return 0; + +BadDevice: + US_DEBUGP("%s failed with %d\n", __func__, result); + free(us); + return result; +} + +/* Handle a USB mass-storage disconnect */ +static void usb_stor_disconnect(struct usb_device *usbdev) +{ +#if 0 + struct us_data *us = (struct us_data *)usbdev->drv_data; + struct us_blk_dev *bdev, *bdev_tmp; + + US_DEBUGP("Disconnecting USB Mass Storage device %s\n", + usbdev->dev.name); + + /* release all block devices of this mass storage device */ + list_for_each_entry_safe(bdev, bdev_tmp, &us_blkdev_list, list) { + if (bdev->us == us) { + US_DEBUGP("Releasing %s\n", bdev->dev.name); + list_del(&bdev->list); + unregister_device(&bdev->dev); + free(bdev); + } + } + + /* release device's private data */ + usbdev->drv_data = 0; + free(us); +#else + dev_err(&usbdev->dev, "Disk/partition removal not yet implemented " + "in the ATA disk driver."); +#endif +} + +#define USUAL_DEV(use_proto, use_trans, drv_info) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, use_proto, use_trans), \ + .driver_info = (drv_info) } + +/* Table with supported devices, most specific first. */ +static struct usb_device_id usb_storage_usb_ids[] = { + USUAL_DEV(US_SC_SCSI, US_PR_BULK, 0), // SCSI intf, BBB proto + { } +}; + + +/*********************************************************************** + * USB Storage driver initialization and registration + ***********************************************************************/ + +static struct usb_driver usb_storage_driver = { + .driver.name = "usb-storage", + .id_table = usb_storage_usb_ids, + .probe = usb_stor_probe, + .disconnect = usb_stor_disconnect, +}; + +static int __init usb_stor_init(void) +{ + usb_storage_driver.name = usb_storage_driver.driver.name; + return usb_driver_register(&usb_storage_driver); +} +device_initcall(usb_stor_init); + diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h new file mode 100644 index 0000000000..17a1e1263e --- /dev/null +++ b/drivers/usb/storage/usb.h @@ -0,0 +1,96 @@ +/* + * Most of this source has been derived from the Linux and + * U-Boot USB Mass Storage driver implementations. + * + * Adapted for barebox: + * Copyright (c) 2011, AMK Drives & Controls Ltd. + * + * 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 _STORAGE_USB_H_ +#define _STORAGE_USB_H_ + +#include <usb/usb.h> +#include <ata.h> +#include <scsi.h> +#include <linux/list.h> + + +#ifdef USB_STOR_DEBUG +#define US_DEBUGP(fmt, args...) printf(fmt , ##args) +#else +#define US_DEBUGP(fmt, args...) +#endif + + +/* some defines, similar to ch9.h */ +#define USB_EP_NUM(epd) \ + ((epd)->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) +#define USB_EP_IS_DIR_IN(epd) \ + (((epd)->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) +#define USB_EP_IS_XFER_BULK(epd) \ + (((epd)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == \ + USB_ENDPOINT_XFER_BULK) +#define USB_EP_IS_XFER_INT(epd) \ + (((epd)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == \ + USB_ENDPOINT_XFER_INT) +#define USB_EP_IS_INT_IN(epd) \ + (USB_EP_IS_XFER_INT(epd) && USB_EP_IS_DIR_IN(epd)) + + +struct us_data; + +typedef int (*trans_cmnd)(ccb *cb, struct us_data *data); +typedef int (*trans_reset)(struct us_data *data); + +/* one us_data object allocated per usb storage device */ +struct us_data { + struct usb_device *pusb_dev; /* this usb_device */ + unsigned int flags; /* from filter */ + unsigned char send_bulk_ep; /* used endpoints */ + unsigned char recv_bulk_ep; + unsigned char recv_intr_ep; + unsigned char ifnum; /* interface number */ + + unsigned char subclass; + unsigned char protocol; + + unsigned char max_lun; + unsigned char ep_bInterval; + + char *transport_name; + + trans_cmnd transport; /* transport function */ + trans_reset transport_reset;/* transport device reset */ + + /* SCSI interfaces */ + ccb *srb; /* current srb */ +}; + +/* one us_blk_dev object allocated per LUN */ +struct us_blk_dev { + struct us_data *us; /* LUN's enclosing dev */ + struct device_d dev; /* intf to generic driver */ + struct ata_interface ata_if; /* intf to "disk" driver */ + uint64_t blknum; /* capacity */ + unsigned long blksz; /* block size */ + unsigned char lun; /* the LUN of this blk dev */ + struct list_head list; /* siblings */ +}; + +#endif diff --git a/drivers/video/imx-ipu-fb.c b/drivers/video/imx-ipu-fb.c index 5ae8c4b389..dce2a9e47c 100644 --- a/drivers/video/imx-ipu-fb.c +++ b/drivers/video/imx-ipu-fb.c @@ -23,7 +23,7 @@ #include <common.h> #include <init.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <fb.h> #include <mach/imxfb.h> diff --git a/drivers/video/imx.c b/drivers/video/imx.c index c19e83e50f..7ffbcb550b 100644 --- a/drivers/video/imx.c +++ b/drivers/video/imx.c @@ -16,7 +16,7 @@ #include <common.h> #include <fb.h> -#include <asm/io.h> +#include <io.h> #include <mach/imxfb.h> #include <driver.h> #include <malloc.h> diff --git a/drivers/video/s3c.c b/drivers/video/s3c.c index d079fdea59..b17aeb69ff 100644 --- a/drivers/video/s3c.c +++ b/drivers/video/s3c.c @@ -29,7 +29,7 @@ #include <driver.h> #include <malloc.h> #include <errno.h> -#include <asm/io.h> +#include <io.h> #include <mach/gpio.h> #include <mach/s3c24xx-generic.h> #include <mach/fb.h> diff --git a/drivers/video/stm.c b/drivers/video/stm.c index 78acad7372..c109352565 100644 --- a/drivers/video/stm.c +++ b/drivers/video/stm.c @@ -23,7 +23,7 @@ #include <malloc.h> #include <errno.h> #include <xfuncs.h> -#include <asm/io.h> +#include <io.h> #include <mach/imx-regs.h> #include <mach/clock.h> #include <mach/fb.h> diff --git a/include/asm-generic/io.h b/include/asm-generic/io.h new file mode 100644 index 0000000000..3f0f5a2536 --- /dev/null +++ b/include/asm-generic/io.h @@ -0,0 +1,222 @@ +/* Generic I/O port emulation, based on MN10300 code + * + * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells@redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public Licence + * as published by the Free Software Foundation; either version + * 2 of the Licence, or (at your option) any later version. + */ +#ifndef __ASM_GENERIC_IO_H +#define __ASM_GENERIC_IO_H + +#include <linux/types.h> +#include <asm/byteorder.h> + +/*****************************************************************************/ +/* + * readX/writeX() are used to access memory mapped devices. On some + * architectures the memory mapped IO stuff needs to be accessed + * differently. On the simple architectures, we just read/write the + * memory location directly. + */ + +#ifndef __raw_readb +#define __raw_readb(a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a)) +#endif + +#ifndef __raw_readw +#define __raw_readw(a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a)) +#endif + +#ifndef __raw_readl +#define __raw_readl(a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a)) +#endif + +#define readb __raw_readb +#define readw(addr) __le16_to_cpu(__raw_readw(addr)) +#define readl(addr) __le32_to_cpu(__raw_readl(addr)) + +#ifndef __raw_writeb +#define __raw_writeb(v,a) (__chk_io_ptr(a), *(volatile unsigned char __force *)(a) = (v)) +#endif + +#ifndef __raw_writew +#define __raw_writew(v,a) (__chk_io_ptr(a), *(volatile unsigned short __force *)(a) = (v)) +#endif + +#ifndef __raw_writel +#define __raw_writel(v,a) (__chk_io_ptr(a), *(volatile unsigned int __force *)(a) = (v)) +#endif + +#define writeb __raw_writeb +#define writew(b,addr) __raw_writew(__cpu_to_le16(b),addr) +#define writel(b,addr) __raw_writel(__cpu_to_le32(b),addr) + +#ifdef CONFIG_64BIT +static inline u64 __raw_readq(const volatile void __iomem *addr) +{ + return *(const volatile u64 __force *) addr; +} +#define readq(addr) __le64_to_cpu(__raw_readq(addr)) + +static inline void __raw_writeq(u64 b, volatile void __iomem *addr) +{ + *(volatile u64 __force *) addr = b; +} +#define writeq(b,addr) __raw_writeq(__cpu_to_le64(b),addr) +#endif + +#ifndef PCI_IOBASE +#define PCI_IOBASE ((void __iomem *) 0) +#endif + +/*****************************************************************************/ +/* + * traditional input/output functions + */ + +static inline u8 inb(unsigned long addr) +{ + return readb(addr + PCI_IOBASE); +} + +static inline u16 inw(unsigned long addr) +{ + return readw(addr + PCI_IOBASE); +} + +static inline u32 inl(unsigned long addr) +{ + return readl(addr + PCI_IOBASE); +} + +static inline void outb(u8 b, unsigned long addr) +{ + writeb(b, addr + PCI_IOBASE); +} + +static inline void outw(u16 b, unsigned long addr) +{ + writew(b, addr + PCI_IOBASE); +} + +static inline void outl(u32 b, unsigned long addr) +{ + writel(b, addr + PCI_IOBASE); +} + +#define inb_p(addr) inb(addr) +#define inw_p(addr) inw(addr) +#define inl_p(addr) inl(addr) +#define outb_p(x, addr) outb((x), (addr)) +#define outw_p(x, addr) outw((x), (addr)) +#define outl_p(x, addr) outl((x), (addr)) + +#ifndef insb +static inline void insb(unsigned long addr, void *buffer, int count) +{ + if (count) { + u8 *buf = buffer; + do { + u8 x = inb(addr); + *buf++ = x; + } while (--count); + } +} +#endif + +#ifndef insw +static inline void insw(unsigned long addr, void *buffer, int count) +{ + if (count) { + u16 *buf = buffer; + do { + u16 x = inw(addr); + *buf++ = x; + } while (--count); + } +} +#endif + +#ifndef insl +static inline void insl(unsigned long addr, void *buffer, int count) +{ + if (count) { + u32 *buf = buffer; + do { + u32 x = inl(addr); + *buf++ = x; + } while (--count); + } +} +#endif + +#ifndef outsb +static inline void outsb(unsigned long addr, const void *buffer, int count) +{ + if (count) { + const u8 *buf = buffer; + do { + outb(*buf++, addr); + } while (--count); + } +} +#endif + +#ifndef outsw +static inline void outsw(unsigned long addr, const void *buffer, int count) +{ + if (count) { + const u16 *buf = buffer; + do { + outw(*buf++, addr); + } while (--count); + } +} +#endif + +#ifndef outsl +static inline void outsl(unsigned long addr, const void *buffer, int count) +{ + if (count) { + const u32 *buf = buffer; + do { + outl(*buf++, addr); + } while (--count); + } +} +#endif + +static inline void readsl(const void __iomem *addr, void *buf, int len) +{ + insl(addr - PCI_IOBASE, buf, len); +} + +static inline void readsw(const void __iomem *addr, void *buf, int len) +{ + insw(addr - PCI_IOBASE, buf, len); +} + +static inline void readsb(const void __iomem *addr, void *buf, int len) +{ + insb(addr - PCI_IOBASE, buf, len); +} + +static inline void writesl(const void __iomem *addr, const void *buf, int len) +{ + outsl(addr - PCI_IOBASE, buf, len); +} + +static inline void writesw(const void __iomem *addr, const void *buf, int len) +{ + outsw(addr - PCI_IOBASE, buf, len); +} + +static inline void writesb(const void __iomem *addr, const void *buf, int len) +{ + outsb(addr - PCI_IOBASE, buf, len); +} + +#endif /* __ASM_GENERIC_IO_H */ diff --git a/include/common.h b/include/common.h index 0ce4a70b56..e34bbea82f 100644 --- a/include/common.h +++ b/include/common.h @@ -94,7 +94,7 @@ void __noreturn hang (void); void __noreturn panic(const char *fmt, ...); /* */ -long int initdram (int); +void initdram (int); char *size_human_readable(ulong size); /* common/main.c */ diff --git a/include/driver.h b/include/driver.h index e9ac7279f4..80de0c8377 100644 --- a/include/driver.h +++ b/include/driver.h @@ -205,6 +205,13 @@ struct device_d *add_generic_device(const char* devname, int id, const char *res void *pdata); /* + * register a generic device + * with multiple resources + */ +struct device_d *add_generic_device_res(const char* devname, int id, + struct resource *res, int nb, void *pdata); + +/* * register a memory device */ static inline struct device_d *add_mem_device(const char *name, resource_size_t start, diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h index 2507d68a34..ccbf518c97 100644 --- a/include/i2c/i2c.h +++ b/include/i2c/i2c.h @@ -30,6 +30,7 @@ struct i2c_platform_data { #define I2C_NAME_SIZE 20 #define I2C_M_RD 0x0001 /* read data, from slave to master */ +#define I2C_M_DATA_ONLY 0x0002 /* transfer data bytes only */ #define I2C_M_TEN 0x0010 /* this is a ten bit chip address */ #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ diff --git a/include/image.h b/include/image.h index 8932947b7e..691bf2d88b 100644 --- a/include/image.h +++ b/include/image.h @@ -188,9 +188,16 @@ typedef struct image_header { uint8_t ih_name[IH_NMLEN]; /* Image Name */ } image_header_t; +struct image_handle_data { + void *data; + ulong len; +}; + struct image_handle { image_header_t header; void *data; + struct image_handle_data *data_entries; + int nb_data_entries; #define IH_MALLOC 1 int flags; }; @@ -320,13 +327,13 @@ static inline void image_set_name(image_header_t *hdr, const char *name) strncpy(image_get_name(hdr), name, IH_NMLEN); } -ulong image_multi_count(const image_header_t *hdr); -void image_multi_getimg(const image_header_t *hdr, ulong idx, - ulong *data, ulong *len); +ulong image_multi_count(void *data); +void image_multi_getimg(void *data, ulong idx, + ulong *img_data, ulong *len); void image_print_size(uint32_t size); -void image_print_contents(const void *ptr); +void image_print_contents(const image_header_t *hdr, void *data); /* commamds/bootm.c */ void print_image_hdr (image_header_t *hdr); @@ -337,6 +344,7 @@ void print_image_hdr (image_header_t *hdr); */ struct image_handle *map_image(const char *filename, int verify); void unmap_image(struct image_handle *handle); +struct image_handle_data* gen_image_handle_data(void* data, ulong len); /* * Relocate an image to load_address by uncompressing diff --git a/include/io.h b/include/io.h new file mode 100644 index 0000000000..39b5e614b7 --- /dev/null +++ b/include/io.h @@ -0,0 +1,23 @@ +#ifndef __IO_H +#define __IO_H + +#include <asm/io.h> + +/* cpu_read/cpu_write: cpu native io accessors */ +#if __BYTE_ORDER == __BIG_ENDIAN +#define cpu_readb(a) readb(a) +#define cpu_readw(a) in_be16(a) +#define cpu_readl(a) in_be32(a) +#define cpu_writeb(v, a) writeb((v), (a)) +#define cpu_writew(v, a) out_be16((a), (v)) +#define cpu_writel(v, a) out_be32((a), (v)) +#else +#define cpu_readb(a) readb(a) +#define cpu_readw(a) readw(a) +#define cpu_readl(a) readl(a) +#define cpu_writeb(v, a) writeb((v), (a)) +#define cpu_writew(v, a) writew((v), (a)) +#define cpu_writel(v, a) writel((v), (a)) +#endif + +#endif /* __IO_H */ diff --git a/include/linux/ctype.h b/include/linux/ctype.h index 728040efd3..74fb735778 100644 --- a/include/linux/ctype.h +++ b/include/linux/ctype.h @@ -2,7 +2,6 @@ #define _LINUX_CTYPE_H #include <common.h> -#include <reloc.h> /* * NOTE! This ctype does not handle EOF like the standard C @@ -20,7 +19,7 @@ extern unsigned char _ctype[]; -#define __ismask(x) (RELOC_VAR(_ctype[(int)(unsigned char)(x)])) +#define __ismask(x) (_ctype[(int)(unsigned char)(x)]) #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) diff --git a/include/mem_malloc.h b/include/mem_malloc.h deleted file mode 100644 index 67b19d7ff1..0000000000 --- a/include/mem_malloc.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __MEM_MALLOC_H -#define __MEM_MALLOC_H - -#include <linux/types.h> - -void mem_malloc_init(void *start, void *end); -ulong mem_malloc_start(void); -ulong mem_malloc_end(void); - -#endif diff --git a/include/memory.h b/include/memory.h new file mode 100644 index 0000000000..cb185afa65 --- /dev/null +++ b/include/memory.h @@ -0,0 +1,25 @@ +#ifndef __MEM_MALLOC_H +#define __MEM_MALLOC_H + +#include <linux/types.h> +#include <linux/list.h> + +void mem_malloc_init(void *start, void *end); +ulong mem_malloc_start(void); +ulong mem_malloc_end(void); + +struct memory_bank { + struct list_head list; + struct device_d *dev; + unsigned long start; + unsigned long size; +}; + +extern struct list_head memory_banks; + +void barebox_add_memory_bank(const char *name, resource_size_t start, + resource_size_t size); + +#define for_each_memory_bank(mem) list_for_each_entry(mem, &memory_banks, list) + +#endif diff --git a/include/reloc.h b/include/reloc.h deleted file mode 100644 index cc998665b5..0000000000 --- a/include/reloc.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef __RELOC_H -#define __RELOC_H - -extern unsigned long _text_base; - -#ifdef CONFIG_HAS_EARLY_INIT - -extern ulong __early_init_data_begin, __early_init_data_end; - -/* - * The difference between our link address and the address we're - * currently running at. - */ -unsigned long reloc_offset(void); - -/* - * When not running at link address, relocate a pointer by - * taking reloc_offset() into account - */ -#define RELOC(a) (typeof(*a) *)((unsigned long)a + reloc_offset()) - -/* - * dito, used for variables - */ -#define RELOC_VAR(v) *(typeof(v)* )((unsigned long)&v + reloc_offset()) - -void early_init(void); - -/* - * put a variable into early init RAM. This section will - * be relocated into SRAM during early init - */ -#define __early_initdata __attribute__ ((__section__ (".early_init_data"))) - -/* Access init data */ -#define INITDATA(var) *(typeof(var) *)((ulong)(&var) - \ - (ulong)&__early_init_data_begin + \ - (ulong)RELOC_VAR(init_data_ptr)) - -extern void *init_data_ptr; - -#else - -static inline int reloc_offset(void) -{ - return 0; -} - -static inline void early_init(void) -{ -} - -#define RELOC(a) a -#define RELOC_VAR(v) v - -#define __early_initdata - -#define INITDATA(var) var - -#endif /* CONFIG_HAS_EARLY_INIT */ - -#endif /* __RELOC_H */ diff --git a/include/scsi.h b/include/scsi.h new file mode 100644 index 0000000000..931d03da9d --- /dev/null +++ b/include/scsi.h @@ -0,0 +1,208 @@ +/* + * (C) Copyright 2001 + * Denis Peter, MPL AG Switzerland + * + * 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 _SCSI_H + #define _SCSI_H + +typedef struct SCSI_cmd_block { + unsigned char cmd[16]; /* command */ + unsigned char sense_buf[64]; /* for request sense */ + unsigned char status; /* SCSI Status */ + unsigned char target; /* Target ID */ + unsigned char lun; /* Target LUN */ + unsigned char cmdlen; /* command len */ + unsigned long datalen; /* Total data length */ + unsigned char * pdata; /* pointer to data */ + unsigned char msgout[12]; /* Messge out buffer (NOT USED) */ + unsigned char msgin[12]; /* Message in buffer */ + unsigned char sensecmdlen; /* Sense command len */ + unsigned long sensedatalen; /* Sense data len */ + unsigned char sensecmd[6]; /* Sense command */ + unsigned long contr_stat; /* Controller Status */ + unsigned long trans_bytes; /* tranfered bytes */ + + unsigned int priv; +} ccb; + +/*----------------------------------------------------------- +** +** SCSI constants. +** +**----------------------------------------------------------- +*/ + +/* +** Messages +*/ + +#define M_COMPLETE (0x00) +#define M_EXTENDED (0x01) +#define M_SAVE_DP (0x02) +#define M_RESTORE_DP (0x03) +#define M_DISCONNECT (0x04) +#define M_ID_ERROR (0x05) +#define M_ABORT (0x06) +#define M_REJECT (0x07) +#define M_NOOP (0x08) +#define M_PARITY (0x09) +#define M_LCOMPLETE (0x0a) +#define M_FCOMPLETE (0x0b) +#define M_RESET (0x0c) +#define M_ABORT_TAG (0x0d) +#define M_CLEAR_QUEUE (0x0e) +#define M_INIT_REC (0x0f) +#define M_REL_REC (0x10) +#define M_TERMINATE (0x11) +#define M_SIMPLE_TAG (0x20) +#define M_HEAD_TAG (0x21) +#define M_ORDERED_TAG (0x22) +#define M_IGN_RESIDUE (0x23) +#define M_IDENTIFY (0x80) + +#define M_X_MODIFY_DP (0x00) +#define M_X_SYNC_REQ (0x01) +#define M_X_WIDE_REQ (0x03) +#define M_X_PPR_REQ (0x04) + + +/* +** Status +*/ + +#define S_GOOD (0x00) +#define S_CHECK_COND (0x02) +#define S_COND_MET (0x04) +#define S_BUSY (0x08) +#define S_INT (0x10) +#define S_INT_COND_MET (0x14) +#define S_CONFLICT (0x18) +#define S_TERMINATED (0x20) +#define S_QUEUE_FULL (0x28) +#define S_ILLEGAL (0xff) +#define S_SENSE (0x80) + +/* + * Sense_keys + */ + +#define SENSE_NO_SENSE 0x0 +#define SENSE_RECOVERED_ERROR 0x1 +#define SENSE_NOT_READY 0x2 +#define SENSE_MEDIUM_ERROR 0x3 +#define SENSE_HARDWARE_ERROR 0x4 +#define SENSE_ILLEGAL_REQUEST 0x5 +#define SENSE_UNIT_ATTENTION 0x6 +#define SENSE_DATA_PROTECT 0x7 +#define SENSE_BLANK_CHECK 0x8 +#define SENSE_VENDOR_SPECIFIC 0x9 +#define SENSE_COPY_ABORTED 0xA +#define SENSE_ABORTED_COMMAND 0xB +#define SENSE_VOLUME_OVERFLOW 0xD +#define SENSE_MISCOMPARE 0xE + + +#define SCSI_CHANGE_DEF 0x40 /* Change Definition (Optional) */ +#define SCSI_COMPARE 0x39 /* Compare (O) */ +#define SCSI_COPY 0x18 /* Copy (O) */ +#define SCSI_COP_VERIFY 0x3A /* Copy and Verify (O) */ +#define SCSI_INQUIRY 0x12 /* Inquiry (MANDATORY) */ +#define SCSI_LOG_SELECT 0x4C /* Log Select (O) */ +#define SCSI_LOG_SENSE 0x4D /* Log Sense (O) */ +#define SCSI_MODE_SEL6 0x15 /* Mode Select 6-byte (Device Specific) */ +#define SCSI_MODE_SEL10 0x55 /* Mode Select 10-byte (Device Specific) */ +#define SCSI_MODE_SEN6 0x1A /* Mode Sense 6-byte (Device Specific) */ +#define SCSI_MODE_SEN10 0x5A /* Mode Sense 10-byte (Device Specific) */ +#define SCSI_READ_BUFF 0x3C /* Read Buffer (O) */ +#define SCSI_REQ_SENSE 0x03 /* Request Sense (MANDATORY) */ +#define SCSI_SEND_DIAG 0x1D /* Send Diagnostic (O) */ +#define SCSI_TST_U_RDY 0x00 /* Test Unit Ready (MANDATORY) */ +#define SCSI_WRITE_BUFF 0x3B /* Write Buffer (O) */ +/*************************************************************************** + * %%% Commands Unique to Direct Access Devices %%% + ***************************************************************************/ +#define SCSI_COMPARE 0x39 /* Compare (O) */ +#define SCSI_FORMAT 0x04 /* Format Unit (MANDATORY) */ +#define SCSI_LCK_UN_CAC 0x36 /* Lock Unlock Cache (O) */ +#define SCSI_PREFETCH 0x34 /* Prefetch (O) */ +#define SCSI_MED_REMOVL 0x1E /* Prevent/Allow medium Removal (O) */ +#define SCSI_READ6 0x08 /* Read 6-byte (MANDATORY) */ +#define SCSI_READ10 0x28 /* Read 10-byte (MANDATORY) */ +#define SCSI_RD_CAPAC 0x25 /* Read Capacity (MANDATORY) */ +#define SCSI_RD_DEFECT 0x37 /* Read Defect Data (O) */ +#define SCSI_READ_LONG 0x3E /* Read Long (O) */ +#define SCSI_REASS_BLK 0x07 /* Reassign Blocks (O) */ +#define SCSI_RCV_DIAG 0x1C /* Receive Diagnostic Results (O) */ +#define SCSI_RELEASE 0x17 /* Release Unit (MANDATORY) */ +#define SCSI_REZERO 0x01 /* Rezero Unit (O) */ +#define SCSI_SRCH_DAT_E 0x31 /* Search Data Equal (O) */ +#define SCSI_SRCH_DAT_H 0x30 /* Search Data High (O) */ +#define SCSI_SRCH_DAT_L 0x32 /* Search Data Low (O) */ +#define SCSI_SEEK6 0x0B /* Seek 6-Byte (O) */ +#define SCSI_SEEK10 0x2B /* Seek 10-Byte (O) */ +#define SCSI_SEND_DIAG 0x1D /* Send Diagnostics (MANDATORY) */ +#define SCSI_SET_LIMIT 0x33 /* Set Limits (O) */ +#define SCSI_START_STP 0x1B /* Start/Stop Unit (O) */ +#define SCSI_SYNC_CACHE 0x35 /* Synchronize Cache (O) */ +#define SCSI_VERIFY 0x2F /* Verify (O) */ +#define SCSI_WRITE6 0x0A /* Write 6-Byte (MANDATORY) */ +#define SCSI_WRITE10 0x2A /* Write 10-Byte (MANDATORY) */ +#define SCSI_WRT_VERIFY 0x2E /* Write and Verify (O) */ +#define SCSI_WRITE_LONG 0x3F /* Write Long (O) */ +#define SCSI_WRITE_SAME 0x41 /* Write Same (O) */ + + +/**************************************************************************** + * decleration of functions which have to reside in the LowLevel Part Driver + */ + +void scsi_print_error(ccb *pccb); +int scsi_exec(ccb *pccb); +void scsi_bus_reset(void); +void scsi_low_level_init(int busdevfunc); + + +/*************************************************************************** + * functions residing inside cmd_scsi.c + */ +void scsi_init(void); + + +#define SCSI_IDENTIFY 0xC0 /* not used */ + +/* Hardware errors */ +#define SCSI_SEL_TIME_OUT 0x00000101 /* Selection time out */ +#define SCSI_HNS_TIME_OUT 0x00000102 /* Handshake */ +#define SCSI_MA_TIME_OUT 0x00000103 /* Phase error */ +#define SCSI_UNEXP_DIS 0x00000104 /* unexpected disconnect */ + +#define SCSI_INT_STATE 0x00010000 /* unknown Interrupt number is stored in 16 LSB */ + + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#endif /* _SCSI_H */ diff --git a/include/spi/spi.h b/include/spi/spi.h index 948e0501cd..9d01d068da 100644 --- a/include/spi/spi.h +++ b/include/spi/spi.h @@ -37,7 +37,8 @@ struct spi_board_info { * powers of two bytes (e.g. 20 bit samples use 32 bits). * This may be changed by the device's driver, or left at the * default (0) indicating protocol words are eight bit bytes. - * The spi_transfer.bits_per_word can override this for each transfer. + * The spi_transfer.bits_per_word can override this for each transfer + * (FIXME: not currently implemented). * @irq: Negative, or the number passed to request_irq() to receive * interrupts from this device. * @controller_state: Controller's runtime state diff --git a/include/usb/usb.h b/include/usb/usb.h index 6ef9977497..08fd1a1185 100644 --- a/include/usb/usb.h +++ b/include/usb/usb.h @@ -205,9 +205,9 @@ struct usb_host { int (*init)(struct usb_host *); int (*exit)(struct usb_host *); int (*submit_bulk_msg)(struct usb_device *dev, unsigned long pipe, - void *buffer, int transfer_len); + void *buffer, int transfer_len, int timeout); int (*submit_control_msg)(struct usb_device *dev, unsigned long pipe, void *buffer, - int transfer_len, struct devrequest *setup); + int transfer_len, struct devrequest *setup, int timeout); int (*submit_int_msg)(struct usb_device *dev, unsigned long pipe, void *buffer, int transfer_len, int interval); void (*usb_event_poll)(void); @@ -480,6 +480,13 @@ struct usb_device_id { #define USB_DEVICE_ID_MATCH_VENDOR 0x0001 #define USB_DEVICE_ID_MATCH_DEVICE \ (USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_PRODUCT) +#define USB_DEVICE_ID_MATCH_INT_CLASS 0x0080 +#define USB_DEVICE_ID_MATCH_INT_SUBCLASS 0x0100 +#define USB_DEVICE_ID_MATCH_INT_PROTOCOL 0x0200 +#define USB_DEVICE_ID_MATCH_INT_INFO \ + (USB_DEVICE_ID_MATCH_INT_CLASS | \ + USB_DEVICE_ID_MATCH_INT_SUBCLASS | \ + USB_DEVICE_ID_MATCH_INT_PROTOCOL) /** * USB_DEVICE - macro used to describe a specific usb device @@ -494,6 +501,21 @@ struct usb_device_id { .idVendor = (vend), \ .idProduct = (prod) +/** + * USB_INTERFACE_INFO - macro used to describe a class of usb interfaces + * @cl: bInterfaceClass value + * @sc: bInterfaceSubClass value + * @pr: bInterfaceProtocol value + * + * This macro is used to create a struct usb_device_id that matches a + * specific class of interfaces. + */ +#define USB_INTERFACE_INFO(cl, sc, pr) \ + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO, \ + .bInterfaceClass = (cl), \ + .bInterfaceSubClass = (sc), \ + .bInterfaceProtocol = (pr) + #define USB_CTRL_SET_TIMEOUT 5000 #define USB_CTRL_GET_TIMEOUT 5000 diff --git a/lib/vsprintf.c b/lib/vsprintf.c index ccccc5df0d..54e162f063 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -19,7 +19,6 @@ #include <common.h> #include <led.h> -#include <reloc.h> unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) { @@ -113,8 +113,10 @@ int string_to_ip(const char *s, IPaddr_t *ip) return -EINVAL; val = simple_strtoul(s, &e, 10); - addr <<= 8; - addr |= (val & 0xFF); + if (val > 255) + return -EINVAL; + + addr = (addr << 8) | val; if (*e != '.' && i != 3) return -EINVAL; @@ -134,7 +136,8 @@ IPaddr_t getenv_ip(const char *name) if (!var) return 0; - string_to_ip(var, &ip); + if (string_to_ip(var, &ip)) + return 0; return ip; } diff --git a/scripts/mkimage.c b/scripts/mkimage.c index 40a3483138..d3a8bfb887 100644 --- a/scripts/mkimage.c +++ b/scripts/mkimage.c @@ -255,7 +255,8 @@ NXTARG: ; } /* for multi-file images we need the data part, too */ - image_print_contents((image_header_t *)ptr); + image_print_contents((image_header_t *)ptr, + (void*)image_get_data((image_header_t *)ptr)); (void) munmap((void *)ptr, sbuf.st_size); (void) close (ifd); @@ -381,7 +382,7 @@ NXTARG: ; image_set_hcrc(hdr, checksum); - image_print_contents(hdr); + image_print_contents(hdr, (void*)image_get_data(hdr)); (void) munmap((void *)ptr, sbuf.st_size); |