summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards.dox1
-rwxr-xr-xMAKEALL2
-rw-r--r--Makefile6
-rw-r--r--arch/arm/Kconfig3
-rw-r--r--arch/arm/Makefile4
-rw-r--r--arch/arm/boards/a9m2410/a9m2410.c94
-rw-r--r--arch/arm/boards/a9m2410/lowlevel_init.S6
-rw-r--r--arch/arm/boards/a9m2440/a9m2410dev.c64
-rw-r--r--arch/arm/boards/a9m2440/a9m2440.c50
-rw-r--r--arch/arm/boards/a9m2440/lowlevel_init.S11
-rw-r--r--arch/arm/boards/at91rm9200ek/env/config5
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/_update36
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/boot38
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/init19
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/init_board23
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/pcidmaloop14
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/pciloop13
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/update_kernel8
-rw-r--r--arch/arm/boards/at91sam9260ek/env/bin/update_root8
-rw-r--r--arch/arm/boards/at91sam9260ek/env/config45
-rw-r--r--arch/arm/boards/at91sam9260ek/init.c89
-rw-r--r--arch/arm/boards/at91sam9261ek/env/config5
-rw-r--r--arch/arm/boards/at91sam9261ek/init.c5
-rw-r--r--arch/arm/boards/at91sam9263ek/config.h18
-rw-r--r--arch/arm/boards/at91sam9263ek/env/config7
-rw-r--r--arch/arm/boards/at91sam9263ek/init.c1
-rw-r--r--arch/arm/boards/at91sam9m10g45ek/env/config5
-rw-r--r--arch/arm/boards/at91sam9m10g45ek/init.c1
-rw-r--r--arch/arm/boards/chumby_falconwing/env/bin/boot9
-rw-r--r--arch/arm/boards/chumby_falconwing/env/config2
-rw-r--r--arch/arm/boards/dss11/env/config5
-rw-r--r--arch/arm/boards/eukrea_cpuimx25/env/config1
-rw-r--r--arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c1
-rw-r--r--arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c1
-rw-r--r--arch/arm/boards/eukrea_cpuimx35/env/config1
-rw-r--r--arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c3
-rw-r--r--arch/arm/boards/eukrea_cpuimx51/Makefile1
-rw-r--r--arch/arm/boards/eukrea_cpuimx51/env/config1
-rw-r--r--arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c3
-rw-r--r--arch/arm/boards/eukrea_cpuimx51/lowlevel_init.S216
-rw-r--r--arch/arm/boards/freescale-mx23-evk/mx23-evk.c31
-rw-r--r--arch/arm/boards/freescale-mx28-evk/Makefile1
-rw-r--r--arch/arm/boards/freescale-mx28-evk/config.h16
-rw-r--r--arch/arm/boards/freescale-mx28-evk/env/config51
-rw-r--r--arch/arm/boards/freescale-mx28-evk/mx28-evk.c141
-rw-r--r--arch/arm/boards/freescale-mx35-3-stack/env/config5
-rw-r--r--arch/arm/boards/freescale-mx51-pdk/Makefile1
-rw-r--r--arch/arm/boards/freescale-mx51-pdk/board.c3
-rw-r--r--arch/arm/boards/freescale-mx51-pdk/env/config5
-rw-r--r--arch/arm/boards/freescale-mx51-pdk/lowlevel_init.S216
-rw-r--r--arch/arm/boards/freescale-mx53-loco/board.c4
-rw-r--r--arch/arm/boards/freescale-mx53-loco/env/config5
-rw-r--r--arch/arm/boards/freescale-mx53-smd/board.c4
-rw-r--r--arch/arm/boards/freescale-mx53-smd/env/config5
-rw-r--r--arch/arm/boards/guf-cupid/env/config5
-rw-r--r--arch/arm/boards/guf-neso/board.c1
-rw-r--r--arch/arm/boards/guf-neso/env/config5
-rw-r--r--arch/arm/boards/imx21ads/imx21ads.c1
-rw-r--r--arch/arm/boards/karo-tx25/board.c1
-rw-r--r--arch/arm/boards/karo-tx25/env/config5
-rw-r--r--arch/arm/boards/karo-tx28/env/config5
-rw-r--r--arch/arm/boards/mini2440/env/config5
-rw-r--r--arch/arm/boards/mini2440/lowlevel_init.S6
-rw-r--r--arch/arm/boards/mini2440/mini2440.c30
-rw-r--r--arch/arm/boards/mmccpu/config.h18
-rw-r--r--arch/arm/boards/nhk8815/env/config5
-rw-r--r--arch/arm/boards/panda/env/config5
-rw-r--r--arch/arm/boards/pcm037/env/config5
-rw-r--r--arch/arm/boards/pcm038/env/config5
-rw-r--r--arch/arm/boards/pcm038/pcm038.c1
-rw-r--r--arch/arm/boards/pcm043/env/config5
-rw-r--r--arch/arm/boards/pcm049/board.c11
-rw-r--r--arch/arm/boards/pcm049/env/config5
-rw-r--r--arch/arm/boards/phycard-a-l1/Makefile22
-rw-r--r--arch/arm/boards/phycard-a-l1/config.h22
-rw-r--r--arch/arm/boards/phycard-a-l1/env/config78
-rw-r--r--arch/arm/boards/phycard-a-l1/lowlevel.c39
-rw-r--r--arch/arm/boards/phycard-a-l1/pca-a-l1.c350
-rw-r--r--arch/arm/boards/phycard-a-l1/pca-a-l1.dox16
-rw-r--r--arch/arm/boards/phycard-a-l1/pca-a-l1.h35
-rw-r--r--arch/arm/boards/phycard-a-l1/platform.S65
-rw-r--r--arch/arm/boards/phycard-i.MX27/env/config5
-rw-r--r--arch/arm/boards/phycard-i.MX27/pca100.c105
-rw-r--r--arch/arm/boards/pm9261/config.h18
-rw-r--r--arch/arm/boards/pm9261/env/config5
-rw-r--r--arch/arm/boards/pm9261/init.c4
-rw-r--r--arch/arm/boards/pm9263/config.h18
-rw-r--r--arch/arm/boards/pm9g45/env/config5
-rw-r--r--arch/arm/boards/scb9328/env/config5
-rw-r--r--arch/arm/boards/usb-a926x/env/bin/init_board49
-rw-r--r--arch/arm/boards/usb-a926x/env/config5
-rw-r--r--arch/arm/boards/usb-a926x/init.c45
-rw-r--r--arch/arm/boards/versatile/env/config5
-rw-r--r--arch/arm/configs/at91sam9260ek_defconfig27
-rw-r--r--arch/arm/configs/at91sam9261ek_defconfig2
-rw-r--r--arch/arm/configs/at91sam9g10ek_defconfig2
-rw-r--r--arch/arm/configs/at91sam9g20ek_defconfig27
-rw-r--r--arch/arm/configs/cupid_defconfig19
-rw-r--r--arch/arm/configs/freescale_mx25_3stack_defconfig26
-rw-r--r--arch/arm/configs/freescale_mx35_3stack_defconfig18
-rw-r--r--arch/arm/configs/freescale_mx51_babbage_defconfig20
-rw-r--r--arch/arm/configs/freescale_mx53_loco_defconfig16
-rw-r--r--arch/arm/configs/freescale_mx53_smd_defconfig15
-rw-r--r--arch/arm/configs/imx28evk_defconfig48
-rw-r--r--arch/arm/configs/mini2440_defconfig7
-rw-r--r--arch/arm/configs/neso_defconfig13
-rw-r--r--arch/arm/configs/pca100_defconfig17
-rw-r--r--arch/arm/configs/pcm037_defconfig17
-rw-r--r--arch/arm/configs/pcm038_defconfig18
-rw-r--r--arch/arm/configs/pcm043_defconfig15
-rw-r--r--arch/arm/configs/pcm049_defconfig18
-rw-r--r--arch/arm/configs/pcm049_xload_defconfig4
-rw-r--r--arch/arm/configs/phycard_a_l1_defconfig183
-rw-r--r--arch/arm/configs/pm9261_defconfig2
-rw-r--r--arch/arm/configs/scb9328_defconfig18
-rw-r--r--arch/arm/configs/tx25stk5_defconfig19
-rw-r--r--arch/arm/configs/tx28stk5_defconfig25
-rw-r--r--arch/arm/configs/usb_a9260_defconfig24
-rw-r--r--arch/arm/configs/usb_a9263_128mib_defconfig24
-rw-r--r--arch/arm/configs/usb_a9263_defconfig24
-rw-r--r--arch/arm/configs/usb_a9g20_128mib_defconfig24
-rw-r--r--arch/arm/configs/usb_a9g20_defconfig24
-rw-r--r--arch/arm/cpu/cache-armv7.S8
-rw-r--r--arch/arm/cpu/cpu.c34
-rw-r--r--arch/arm/cpu/cpuinfo.c6
-rw-r--r--arch/arm/cpu/mmu.c12
-rw-r--r--arch/arm/include/asm/armlinux.h3
-rw-r--r--arch/arm/include/asm/io.h7
-rw-r--r--arch/arm/include/asm/mmu.h6
-rw-r--r--arch/arm/lib/Makefile1
-rw-r--r--arch/arm/lib/armlinux.c20
-rw-r--r--arch/arm/lib/bootm.c222
-rw-r--r--arch/arm/lib/bootu.c8
-rw-r--r--arch/arm/lib/bootz.c7
-rw-r--r--arch/arm/lib/copy_template.S24
-rw-r--r--arch/arm/lib/findbit.S84
-rw-r--r--arch/arm/lib/io-writesw-armv4.S11
-rw-r--r--arch/arm/lib/io.c50
-rw-r--r--arch/arm/lib/memcpy.S7
-rw-r--r--arch/arm/mach-at91/at91rm9200.c12
-rw-r--r--arch/arm/mach-at91/at91rm9200_devices.c24
-rw-r--r--arch/arm/mach-at91/at91rm9200_lowlevel_init.c6
-rw-r--r--arch/arm/mach-at91/at91sam9260.c9
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c31
-rw-r--r--arch/arm/mach-at91/at91sam9261.c9
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c26
-rw-r--r--arch/arm/mach-at91/at91sam9263.c15
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c23
-rw-r--r--arch/arm/mach-at91/at91sam926x_lowlevel_init.S278
-rw-r--r--arch/arm/mach-at91/at91sam926x_lowlevel_init.c171
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c15
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c2
-rw-r--r--arch/arm/mach-at91/gpio.c13
-rw-r--r--arch/arm/mach-at91/include/mach/at91rm9200.h9
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9260.h17
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9261.h10
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9263.h11
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9g45.h11
-rw-r--r--arch/arm/mach-at91/include/mach/board.h10
-rw-r--r--arch/arm/mach-at91/include/mach/gpio.h4
-rw-r--r--arch/arm/mach-imx/Kconfig2
-rw-r--r--arch/arm/mach-imx/Makefile4
-rw-r--r--arch/arm/mach-imx/imx27.c43
-rw-r--r--arch/arm/mach-imx/imx5.c58
-rw-r--r--arch/arm/mach-imx/imx51.c105
-rw-r--r--arch/arm/mach-imx/imx53.c61
-rw-r--r--arch/arm/mach-imx/include/mach/imx27-regs.h1
-rw-r--r--arch/arm/mach-imx/include/mach/imx5.h9
-rw-r--r--arch/arm/mach-imx/include/mach/imx53.h6
-rw-r--r--arch/arm/mach-imx/include/mach/imxfb.h1
-rw-r--r--arch/arm/mach-mxs/Kconfig7
-rw-r--r--arch/arm/mach-mxs/include/mach/iomux-imx28.h1
-rw-r--r--arch/arm/mach-omap/Kconfig10
-rw-r--r--arch/arm/mach-omap/Makefile1
-rw-r--r--arch/arm/mach-omap/include/mach/generic.h7
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-silicon.h4
-rw-r--r--arch/arm/mach-omap/include/mach/omap4_twl6030_mmc.h14
-rw-r--r--arch/arm/mach-omap/omap4_twl6030_mmc.c46
-rw-r--r--arch/arm/mach-pxa/include/mach/clock.h1
-rw-r--r--arch/arm/mach-pxa/include/mach/mci_pxa2xx.h10
-rw-r--r--arch/arm/mach-pxa/speed-pxa27x.c5
-rw-r--r--arch/arm/mach-s3c24xx/Makefile2
-rw-r--r--arch/arm/mach-s3c24xx/generic.c297
-rw-r--r--arch/arm/mach-s3c24xx/include/mach/s3c24x0-iomap.h177
-rw-r--r--arch/arm/mach-samsung/Kconfig (renamed from arch/arm/mach-s3c24xx/Kconfig)17
-rw-r--r--arch/arm/mach-samsung/Makefile3
-rw-r--r--arch/arm/mach-samsung/generic.c164
-rw-r--r--arch/arm/mach-samsung/gpio-s3c24x0.c (renamed from arch/arm/mach-s3c24xx/gpio-s3c24x0.c)33
-rw-r--r--arch/arm/mach-samsung/include/mach/gpio.h (renamed from arch/arm/mach-s3c24xx/include/mach/gpio.h)7
-rw-r--r--arch/arm/mach-samsung/include/mach/iomux-s3c24x0.h (renamed from arch/arm/mach-s3c24xx/include/mach/iomux-s3c24x0.h)0
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c-busctl.h32
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c-clocks.h31
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c-generic.h (renamed from arch/arm/mach-s3c24xx/include/mach/s3c24xx-generic.h)15
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c-iomap.h69
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c-mci.h (renamed from arch/arm/mach-s3c24xx/include/mach/mci.h)0
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c24xx-fb.h (renamed from arch/arm/mach-s3c24xx/include/mach/fb.h)0
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h77
-rw-r--r--arch/arm/mach-samsung/include/mach/s3c24xx-nand.h (renamed from arch/arm/mach-s3c24xx/include/mach/s3c24x0-nand.h)0
-rw-r--r--arch/arm/mach-samsung/lowlevel-init.S (renamed from arch/arm/mach-s3c24xx/lowlevel-init.S)10
-rw-r--r--arch/arm/mach-samsung/s3c-timer.c114
-rw-r--r--arch/arm/mach-samsung/s3c24xx-clocks.c140
-rw-r--r--arch/arm/tools/mach-types66
-rw-r--r--arch/blackfin/lib/blackfin_linux.c12
-rw-r--r--arch/nios2/boards/generic/env/config1
-rw-r--r--arch/nios2/lib/bootm.c11
-rw-r--r--arch/openrisc/Kconfig29
-rw-r--r--arch/openrisc/Makefile21
-rw-r--r--arch/openrisc/boards/generic/Makefile1
-rw-r--r--arch/openrisc/boards/generic/config.h28
-rw-r--r--arch/openrisc/boards/generic/env/config20
-rw-r--r--arch/openrisc/boards/generic/generic.c19
-rw-r--r--arch/openrisc/configs/generic_defconfig20
-rw-r--r--arch/openrisc/cpu/Makefile5
-rw-r--r--arch/openrisc/cpu/barebox.lds.S98
-rw-r--r--arch/openrisc/cpu/cache.c154
-rw-r--r--arch/openrisc/cpu/cpu.c43
-rw-r--r--arch/openrisc/cpu/exceptions.c84
-rw-r--r--arch/openrisc/cpu/start.S335
-rw-r--r--arch/openrisc/include/asm/barebox.h4
-rw-r--r--arch/openrisc/include/asm/bitops.h28
-rw-r--r--arch/openrisc/include/asm/bitops/ffs.h26
-rw-r--r--arch/openrisc/include/asm/bitops/fls.h26
-rw-r--r--arch/openrisc/include/asm/byteorder.h1
-rw-r--r--arch/openrisc/include/asm/cache.h47
-rw-r--r--arch/openrisc/include/asm/common.h4
-rw-r--r--arch/openrisc/include/asm/elf.h107
-rw-r--r--arch/openrisc/include/asm/io.h123
-rw-r--r--arch/openrisc/include/asm/openrisc_exc.h41
-rw-r--r--arch/openrisc/include/asm/posix_types.h71
-rw-r--r--arch/openrisc/include/asm/ptrace.h131
-rw-r--r--arch/openrisc/include/asm/sections.h1
-rw-r--r--arch/openrisc/include/asm/spr-defs.h567
-rw-r--r--arch/openrisc/include/asm/string.h4
-rw-r--r--arch/openrisc/include/asm/swab.h4
-rw-r--r--arch/openrisc/include/asm/system.h39
-rw-r--r--arch/openrisc/include/asm/types.h79
-rw-r--r--arch/openrisc/lib/Makefile6
-rw-r--r--arch/openrisc/lib/ashldi3.S41
-rw-r--r--arch/openrisc/lib/board.c42
-rw-r--r--arch/openrisc/lib/clock.c50
-rw-r--r--arch/openrisc/lib/cpuinfo.c156
-rw-r--r--arch/openrisc/lib/lshrdi3.S41
-rw-r--r--arch/openrisc/lib/muldi3.S58
-rw-r--r--arch/ppc/boards/pcm030/pcm030.c9
-rw-r--r--arch/ppc/lib/board.c1
-rw-r--r--arch/ppc/lib/ppclinux.c242
-rw-r--r--arch/ppc/lib/ticks.S1
-rw-r--r--arch/ppc/mach-mpc5xxx/cpu.c42
-rw-r--r--commands/Kconfig43
-rw-r--r--commands/Makefile4
-rw-r--r--commands/bootm.c451
-rw-r--r--commands/flash.c10
-rw-r--r--commands/iminfo.c71
-rw-r--r--commands/linux_exec.c60
-rw-r--r--commands/ls.c4
-rw-r--r--commands/nandtest.c364
-rw-r--r--commands/uimage.c108
-rw-r--r--commands/usbserial.c108
-rw-r--r--common/Kconfig35
-rw-r--r--common/Makefile31
-rw-r--r--common/clock.c4
-rw-r--r--common/complete.c70
-rw-r--r--common/console.c2
-rw-r--r--common/filetype.c3
-rw-r--r--common/ft_build.c620
-rw-r--r--common/image.c287
-rw-r--r--common/memory.c8
-rw-r--r--common/oftree.c22
-rw-r--r--common/startup.c29
-rw-r--r--common/tlsf.c969
-rw-r--r--common/tlsf_malloc.c99
-rw-r--r--common/tlsfbits.h55
-rw-r--r--common/uimage.c505
-rw-r--r--defaultenv/bin/_update2
-rw-r--r--defaultenv/bin/boot43
-rw-r--r--defaultenv/bin/init2
-rw-r--r--defaultenv/config5
-rw-r--r--drivers/base/resource.c2
-rw-r--r--drivers/i2c/busses/i2c-omap.c131
-rw-r--r--drivers/mci/Kconfig7
-rw-r--r--drivers/mci/Makefile2
-rw-r--r--drivers/mci/omap_hsmmc.c17
-rw-r--r--drivers/mci/pxamci.c369
-rw-r--r--drivers/mci/pxamci.h99
-rw-r--r--drivers/mci/s3c.c16
-rw-r--r--drivers/mci/twl6030.c29
-rw-r--r--drivers/mfd/Kconfig11
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/twl-core.c157
-rw-r--r--drivers/mfd/twl4030.c142
-rw-r--r--drivers/mfd/twl6030.c56
-rw-r--r--drivers/mtd/Kconfig18
-rw-r--r--drivers/mtd/Makefile8
-rw-r--r--drivers/mtd/core.c241
-rw-r--r--drivers/mtd/devices/Kconfig16
-rw-r--r--drivers/mtd/devices/Makefile5
-rw-r--r--drivers/mtd/devices/docg3.c1196
-rw-r--r--drivers/mtd/devices/docg3.h283
-rw-r--r--drivers/mtd/mtd.h42
-rw-r--r--drivers/mtd/mtdoob.c97
-rw-r--r--drivers/mtd/mtdraw.c303
-rw-r--r--drivers/mtd/nand/Kconfig15
-rw-r--r--drivers/mtd/nand/Makefile6
-rw-r--r--drivers/mtd/nand/atmel_nand.c48
-rw-r--r--drivers/mtd/nand/diskonchip.c4
-rw-r--r--drivers/mtd/nand/nand-bb.c43
-rw-r--r--drivers/mtd/nand/nand.c290
-rw-r--r--drivers/mtd/nand/nand_base.c14
-rw-r--r--drivers/mtd/nand/nand_bbt.c2
-rw-r--r--drivers/mtd/nand/nand_hwecc.c4
-rw-r--r--drivers/mtd/nand/nand_hwecc_syndrome.c6
-rw-r--r--drivers/mtd/nand/nand_imx.c2
-rw-r--r--drivers/mtd/nand/nand_omap_gpmc.c2
-rw-r--r--drivers/mtd/nand/nand_s3c24xx.c (renamed from drivers/mtd/nand/nand_s3c2410.c)10
-rw-r--r--drivers/mtd/nand/nand_swecc.c4
-rw-r--r--drivers/mtd/nand/nomadik_nand.c2
-rw-r--r--drivers/mtd/ubi/cdev.c2
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/Makefile2
-rw-r--r--drivers/net/dm9000.c564
-rw-r--r--drivers/net/dm9k.c799
-rw-r--r--drivers/serial/Kconfig10
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/serial_s3c.c (renamed from drivers/serial/serial_s3c24x0.c)72
-rw-r--r--drivers/usb/gadget/Kconfig12
-rw-r--r--drivers/usb/gadget/Makefile1
-rw-r--r--drivers/usb/gadget/at91_udc.c1538
-rw-r--r--drivers/usb/gadget/at91_udc.h168
-rw-r--r--drivers/usb/gadget/dfu.c9
-rw-r--r--drivers/usb/gadget/f_acm.c4
-rw-r--r--drivers/usb/gadget/fsl_udc.c45
-rw-r--r--drivers/usb/gadget/serial.c57
-rw-r--r--drivers/usb/gadget/u_serial.c22
-rw-r--r--drivers/usb/host/Kconfig1
-rw-r--r--drivers/usb/otg/twl4030.c6
-rw-r--r--drivers/video/Kconfig2
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/imx.c22
-rw-r--r--drivers/video/s3c24xx.c (renamed from drivers/video/s3c.c)9
-rw-r--r--fs/devfs-core.c2
-rw-r--r--fs/devfs.c2
-rw-r--r--include/boot.h62
-rw-r--r--include/common.h5
-rw-r--r--include/driver.h4
-rw-r--r--include/filetype.h1
-rw-r--r--include/ft_build.h69
-rw-r--r--include/image.h155
-rw-r--r--include/keyboard.h22
-rw-r--r--include/libbb.h3
-rw-r--r--include/linux/bch.h79
-rw-r--r--include/linux/bitrev.h16
-rw-r--r--include/linux/mtd/mtd.h3
-rw-r--r--include/mfd/twl-core.h30
-rw-r--r--include/mfd/twl4030.h35
-rw-r--r--include/mfd/twl6030.h419
-rw-r--r--include/of.h1
-rw-r--r--include/stringlist.h2
-rw-r--r--include/tlsf.h52
-rw-r--r--include/usb/usbserial.h19
-rw-r--r--include/watchdog.h92
-rw-r--r--lib/Kconfig7
-rw-r--r--lib/Makefile2
-rw-r--r--lib/bch.c1366
-rw-r--r--lib/bitrev.c68
-rw-r--r--lib/libbb.c50
-rw-r--r--lib/readline_simple.c2
-rw-r--r--lib/stringlist.c34
-rw-r--r--lib/uncompress.c8
-rw-r--r--net/net.c1
-rw-r--r--scripts/Kbuild.include143
-rw-r--r--scripts/Makefile.lib67
-rw-r--r--scripts/mkimage.c240
372 files changed, 17811 insertions, 5086 deletions
diff --git a/Documentation/boards.dox b/Documentation/boards.dox
index 140747977b..ba332a76f4 100644
--- a/Documentation/boards.dox
+++ b/Documentation/boards.dox
@@ -36,6 +36,7 @@ ARM type:
@li @subpage edb9315
@li @subpage edb9315a
@li @subpage board_cupid
+@li @subpage phycard-a-l1
Blackfin type:
diff --git a/MAKEALL b/MAKEALL
index 25b99774db..1ba4710dea 100755
--- a/MAKEALL
+++ b/MAKEALL
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
# Print statistics when we exit
trap exit 1 2 3 15
diff --git a/Makefile b/Makefile
index 2108f670c7..eb7ba8dac6 100644
--- a/Makefile
+++ b/Makefile
@@ -450,6 +450,12 @@ endif
# Force gcc to behave correct even for buggy distributions
CFLAGS += $(call cc-option, -fno-stack-protector)
+# This warning generated too much noise in a regular build.
+# Use make W=1 to enable this warning (see scripts/Makefile.build)
+CFLAGS += $(call cc-disable-warning, unused-but-set-variable)
+
+CFLAGS += $(call cc-disable-warning, trampolines)
+
# arch Makefile may override CC so keep this after arch Makefile is included
NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
CHECKFLAGS += $(NOSTDINC_FLAGS)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 40677a35ae..b6001792bc 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -68,6 +68,7 @@ config ARCH_PXA
config ARCH_S3C24xx
bool "Samsung S3C2410, S3C2412, S3C2413, S3C2440, S3C2442, S3C2443"
+ select ARCH_SAMSUNG
select CPU_ARM920T
select GENERIC_GPIO
@@ -86,7 +87,7 @@ source arch/arm/mach-netx/Kconfig
source arch/arm/mach-nomadik/Kconfig
source arch/arm/mach-omap/Kconfig
source arch/arm/mach-pxa/Kconfig
-source arch/arm/mach-s3c24xx/Kconfig
+source arch/arm/mach-samsung/Kconfig
source arch/arm/mach-versatile/Kconfig
config ARM_ASM_UNIFIED
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index a3e12e602a..9885634dde 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -52,7 +52,7 @@ machine-$(CONFIG_ARCH_NOMADIK) := nomadik
machine-$(CONFIG_ARCH_NETX) := netx
machine-$(CONFIG_ARCH_OMAP) := omap
machine-$(CONFIG_ARCH_PXA) := pxa
-machine-$(CONFIG_ARCH_S3C24xx) := s3c24xx
+machine-$(CONFIG_ARCH_SAMSUNG) := samsung
machine-$(CONFIG_ARCH_VERSATILE) := versatile
# Board directory name. This list is sorted alphanumerically
@@ -93,6 +93,7 @@ board-$(CONFIG_MACH_OMAP3EVM) := omap
board-$(CONFIG_MACH_PANDA) := panda
board-$(CONFIG_MACH_PCM049) := pcm049
board-$(CONFIG_MACH_PCA100) := phycard-i.MX27
+board-$(CONFIG_MACH_PCAAL1) := phycard-a-l1
board-$(CONFIG_MACH_PCM037) := pcm037
board-$(CONFIG_MACH_PCM038) := pcm038
board-$(CONFIG_MACH_PCM043) := pcm043
@@ -104,6 +105,7 @@ board-$(CONFIG_MACH_NESO) := guf-neso
board-$(CONFIG_MACH_MX23EVK) := freescale-mx23-evk
board-$(CONFIG_MACH_CHUMBY) := chumby_falconwing
board-$(CONFIG_MACH_TX28) := karo-tx28
+board-$(CONFIG_MACH_MX28EVK) := freescale-mx28-evk
board-$(CONFIG_MACH_FREESCALE_MX51_PDK) := freescale-mx51-pdk
board-$(CONFIG_MACH_FREESCALE_MX53_LOCO) := freescale-mx53-loco
board-$(CONFIG_MACH_FREESCALE_MX53_SMD) := freescale-mx53-smd
diff --git a/arch/arm/boards/a9m2410/a9m2410.c b/arch/arm/boards/a9m2410/a9m2410.c
index bbe16044ef..adeaaccb39 100644
--- a/arch/arm/boards/a9m2410/a9m2410.c
+++ b/arch/arm/boards/a9m2410/a9m2410.c
@@ -32,8 +32,11 @@
#include <partition.h>
#include <nand.h>
#include <io.h>
-#include <mach/s3c24x0-iomap.h>
-#include <mach/s3c24x0-nand.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c24xx-nand.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-busctl.h>
+#include <mach/s3c24xx-gpio.h>
// {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0},
static struct s3c24x0_nand_platform_data nand_info = {
@@ -42,65 +45,40 @@ static struct s3c24x0_nand_platform_data nand_info = {
static int a9m2410_mem_init(void)
{
- resource_size_t size = 0;
- uint32_t reg;
+ resource_size_t size;
/*
- * detect the current memory size
* Note: On this card the second SDRAM page is not used
*/
- reg = readl(BANKSIZE);
-
- switch (reg &= 0x7) {
- case 0:
- size = 32 * 1024 * 1024;
- break;
- case 1:
- size = 64 * 1024 * 1024;
- break;
- case 2:
- size = 128 * 1024 * 1024;
- break;
- case 4:
- size = 2 * 1024 * 1024;
- break;
- case 5:
- size = 4 * 1024 * 1024;
- break;
- case 6:
- size = 8 * 1024 * 1024;
- break;
- case 7:
- size = 16 * 1024 * 1024;
- break;
- }
+ s3c24xx_disable_second_sdram_bank();
+ size = s3c24xx_get_memory_size();
/* ---------- configure the GPIOs ------------- */
- writel(0x007FFFFF, GPACON);
- writel(0x00000000, GPCCON);
- writel(0x00000000, GPCUP);
- writel(0x00000000, GPDCON);
- writel(0x00000000, GPDUP);
- writel(0xAAAAAAAA, GPECON);
- writel(0x0000E03F, GPEUP);
- writel(0x00000000, GPBCON); /* all inputs */
- writel(0x00000007, GPBUP); /* pullup disabled for GPB0..3 */
- writel(0x00009000, GPFCON); /* GPF7 CLK_INT#, GPF6 Debug-LED */
- writel(0x000000FF, GPFUP);
- writel(readl(GPGDAT) | 0x0010, GPGDAT); /* switch off LCD backlight */
- writel(0xFF00A938, GPGCON); /* switch off USB device */
- writel(0x0000F000, GPGUP);
- writel(readl(GPHDAT) | 0x100, GPHDAT); /* switch BOOTINT/GPIO_ON# to high */
- writel(0x000007FF, GPHUP);
- writel(0x0029FAAA, GPHCON);
+ writel(0x007FFFFF, S3C_GPACON);
+ writel(0x00000000, S3C_GPCCON);
+ writel(0x00000000, S3C_GPCUP);
+ writel(0x00000000, S3C_GPDCON);
+ writel(0x00000000, S3C_GPDUP);
+ writel(0xAAAAAAAA, S3C_GPECON);
+ writel(0x0000E03F, S3C_GPEUP);
+ writel(0x00000000, S3C_GPBCON); /* all inputs */
+ writel(0x00000007, S3C_GPBUP); /* pullup disabled for GPB0..3 */
+ writel(0x00009000, S3C_GPFCON); /* GPF7 CLK_INT#, GPF6 Debug-LED */
+ writel(0x000000FF, S3C_GPFUP);
+ writel(readl(S3C_GPGDAT) | 0x0010, S3C_GPGDAT); /* switch off LCD backlight */
+ writel(0xFF00A938, S3C_GPGCON); /* switch off USB device */
+ writel(0x0000F000, S3C_GPGUP);
+ writel(readl(S3C_GPHDAT) | 0x100, S3C_GPHDAT); /* switch BOOTINT/GPIO_ON# to high */
+ writel(0x000007FF, S3C_GPHUP);
+ writel(0x0029FAAA, S3C_GPHCON);
/*
* USB port1 normal, USB port0 normal, USB1 pads for device
* PCLK output on CLKOUT0, UPLL CLK output on CLKOUT1,
* 2nd SDRAM bank off (only bank 1 is used)
*/
- writel(0x40140, MISCCR);
+ writel(0x40140, S3C_MISCCR);
- arm_add_mem_device("ram0", CS6_BASE, size);
+ arm_add_mem_device("ram0", S3C_SDRAM_BASE, size);
return 0;
}
@@ -111,24 +89,24 @@ static int a9m2410_devices_init(void)
uint32_t reg;
/* ----------- configure the access to the outer space ---------- */
- reg = readl(BWSCON);
+ reg = readl(S3C_BWSCON);
/* CS#1 to access the network controller */
reg &= ~0xf0;
reg |= 0xe0;
- writel(0x1350, BANKCON1);
+ writel(0x1350, S3C_BANKCON1);
/* CS#2 to the dual 16550 UART */
reg &= ~0xf00;
reg |= 0x400;
- writel(0x0d50, BANKCON2);
+ writel(0x0d50, S3C_BANKCON2);
- writel(reg, BWSCON);
+ writel(reg, S3C_BWSCON);
/* release the reset signal to the network and UART device */
- reg = readl(MISCCR);
+ reg = readl(S3C_MISCCR);
reg |= 0x10000;
- writel(reg, MISCCR);
+ writel(reg, S3C_MISCCR);
/* ----------- the devices the boot loader should work with -------- */
add_generic_device("s3c24x0_nand", -1, NULL, S3C24X0_NAND_BASE, 0,
@@ -138,7 +116,7 @@ static int a9m2410_devices_init(void)
* connected to CS line 1 and interrupt line
* GPIO3, data width is 32 bit
*/
- add_generic_device("smc91c111", -1, NULL, CS1_BASE + 0x300, 16,
+ add_generic_device("smc91c111", -1, NULL, S3C_CS1_BASE + 0x300, 16,
IORESOURCE_MEM, NULL);
#ifdef CONFIG_NAND
@@ -150,7 +128,7 @@ static int a9m2410_devices_init(void)
dev_add_bb_dev("env_raw", "env0");
#endif
- armlinux_set_bootparams((void*)CS6_BASE + 0x100);
+ armlinux_set_bootparams((void*)S3C_SDRAM_BASE + 0x100);
armlinux_set_architecture(MACH_TYPE_A9M2410);
return 0;
@@ -167,7 +145,7 @@ void __bare_init nand_boot(void)
static int a9m2410_console_init(void)
{
- add_generic_device("s3c24x0_serial", -1, NULL, UART1_BASE, UART1_SIZE,
+ add_generic_device("s3c_serial", -1, NULL, S3C_UART1_BASE, S3C_UART1_SIZE,
IORESOURCE_MEM, NULL);
return 0;
}
diff --git a/arch/arm/boards/a9m2410/lowlevel_init.S b/arch/arm/boards/a9m2410/lowlevel_init.S
index 461b93c3f1..a106d53a1d 100644
--- a/arch/arm/boards/a9m2410/lowlevel_init.S
+++ b/arch/arm/boards/a9m2410/lowlevel_init.S
@@ -3,7 +3,7 @@
*/
#include <config.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
.section ".text_bare_init.board_init_lowlevel","ax"
@@ -15,9 +15,9 @@ board_init_lowlevel:
bl s3c24x0_disable_wd
/* skip everything here if we are already running from SDRAM */
- cmp pc, #S3C24X0_SDRAM_BASE
+ cmp pc, #S3C_SDRAM_BASE
blo 1f
- cmp pc, #S3C24X0_SDRAM_END
+ cmp pc, #S3C_SDRAM_END
bhs 1f
mov pc, r10
diff --git a/arch/arm/boards/a9m2440/a9m2410dev.c b/arch/arm/boards/a9m2440/a9m2410dev.c
index 5f7c53b9f6..bedb0f7590 100644
--- a/arch/arm/boards/a9m2440/a9m2410dev.c
+++ b/arch/arm/boards/a9m2440/a9m2410dev.c
@@ -28,7 +28,9 @@
#include <driver.h>
#include <init.h>
#include <io.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c-busctl.h>
+#include <mach/s3c24xx-gpio.h>
/**
* Initialize the CPU to be able to work with the a9m2410dev evaluation board
@@ -38,58 +40,58 @@ int a9m2410dev_devices_init(void)
unsigned int reg;
/* ---------- configure the GPIOs ------------- */
- writel(0x007FFFFF, GPACON);
- writel(0x00000000, GPCCON);
- writel(0x00000000, GPCUP);
- writel(0x00000000, GPDCON);
- writel(0x00000000, GPDUP);
- writel(0xAAAAAAAA, GPECON);
- writel(0x0000E03F, GPEUP);
- writel(0x00000000, GPBCON); /* all inputs */
- writel(0x00000007, GPBUP); /* pullup disabled for GPB0..3 */
- writel(0x00009000, GPFCON); /* GPF7 CLK_INT#, GPF6 Debug-LED */
- writel(0x000000FF, GPFUP);
- writel(readl(GPGDAT) | 0x1010, GPGDAT); /* switch off IDLE_SW#, switch off LCD backlight */
- writel(0x0100A93A, GPGCON); /* switch on USB device */
- writel(0x0000F000, GPGUP);
- writel(0x0029FAAA, GPHCON);
+ writel(0x007FFFFF, S3C_GPACON);
+ writel(0x00000000, S3C_GPCCON);
+ writel(0x00000000, S3C_GPCUP);
+ writel(0x00000000, S3C_GPDCON);
+ writel(0x00000000, S3C_GPDUP);
+ writel(0xAAAAAAAA, S3C_GPECON);
+ writel(0x0000E03F, S3C_GPEUP);
+ writel(0x00000000, S3C_GPBCON); /* all inputs */
+ writel(0x00000007, S3C_GPBUP); /* pullup disabled for GPB0..3 */
+ writel(0x00009000, S3C_GPFCON); /* GPF7 CLK_INT#, GPF6 Debug-LED */
+ writel(0x000000FF, S3C_GPFUP);
+ writel(readl(S3C_GPGDAT) | 0x1010, S3C_GPGDAT); /* switch off IDLE_SW#, switch off LCD backlight */
+ writel(0x0100A93A, S3C_GPGCON); /* switch on USB device */
+ writel(0x0000F000, S3C_GPGUP);
+ writel(0x0029FAAA, S3C_GPHCON);
- writel((1 << 12) | (0 << 11), GPJDAT);
- writel(0x0016aaaa, GPJCON);
- writel(~((0<<12)| (1<<11)), GPJUP);
+ writel((1 << 12) | (0 << 11), S3C_GPJDAT);
+ writel(0x0016aaaa, S3C_GPJCON);
+ writel(~((0<<12)| (1<<11)), S3C_GPJUP);
- writel((0 << 12) | (0 << 11), GPJDAT);
- writel(0x0016aaaa, GPJCON);
- writel(0x00001fff, GPJUP);
+ writel((0 << 12) | (0 << 11), S3C_GPJDAT);
+ writel(0x0016aaaa, S3C_GPJCON);
+ writel(0x00001fff, S3C_GPJUP);
- writel(0x00000000, DSC0);
- writel(0x00000000, DSC1);
+ writel(0x00000000, S3C_DSC0);
+ writel(0x00000000, S3C_DSC1);
/*
* USB port1 normal, USB port0 normal, USB1 pads for device
* PCLK output on CLKOUT0, UPLL CLK output on CLKOUT1,
*/
- writel((readl(MISCCR) & ~0xFFFF) | 0x0140, MISCCR);
+ writel((readl(S3C_MISCCR) & ~0xFFFF) | 0x0140, S3C_MISCCR);
/* ----------- configure the access to the outer space ---------- */
- reg = readl(BWSCON);
+ reg = readl(S3C_BWSCON);
/* CS#1 to access the network controller */
reg &= ~0xf0;
reg |= 0xe0;
- writel(0x1350, BANKCON1);
+ writel(0x1350, S3C_BANKCON1);
/* CS#2 to the dual 16550 UART */
reg &= ~0xf00;
reg |= 0x400;
- writel(0x0d50, BANKCON2);
+ writel(0x0d50, S3C_BANKCON2);
- writel(reg, BWSCON);
+ writel(reg, S3C_BWSCON);
/* release the reset signal to the network and UART device */
- reg = readl(MISCCR);
+ reg = readl(S3C_MISCCR);
reg |= 0x10000;
- writel(reg, MISCCR);
+ writel(reg, S3C_MISCCR);
return 0;
}
diff --git a/arch/arm/boards/a9m2440/a9m2440.c b/arch/arm/boards/a9m2440/a9m2440.c
index 964d376412..6c6ccdb5f5 100644
--- a/arch/arm/boards/a9m2440/a9m2440.c
+++ b/arch/arm/boards/a9m2440/a9m2440.c
@@ -32,9 +32,11 @@
#include <partition.h>
#include <nand.h>
#include <io.h>
-#include <mach/s3c24x0-iomap.h>
-#include <mach/s3c24x0-nand.h>
-#include <mach/s3c24xx-generic.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c24xx-nand.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-busctl.h>
+#include <mach/s3c24xx-gpio.h>
#include "baseboards.h"
@@ -66,12 +68,6 @@ static int a9m2440_check_for_ram(uint32_t addr)
return rc;
}
-static void a9m2440_disable_second_sdram_bank(void)
-{
- writel(readl(BANKCON7) & ~(0x3 << 15),BANKCON7);
- writel(readl(MISCCR) | (1 << 18), MISCCR); /* disable clock */
-}
-
static int a9m2440_mem_init(void)
{
/*
@@ -80,30 +76,30 @@ static int a9m2440_mem_init(void)
* So we must check here, if the second bank is populated to get the
* correct RAM size.
*/
- switch (readl(BANKSIZE) & 0x7) {
+ switch (readl(S3C_BANKSIZE) & 0x7) {
case 0:
- if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 32 * 1024 * 1024))
- a9m2440_disable_second_sdram_bank();
+ if (a9m2440_check_for_ram(S3C_SDRAM_BASE + 32 * 1024 * 1024))
+ s3c24xx_disable_second_sdram_bank();
break;
case 1:
- if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 64 * 1024 * 1024))
- a9m2440_disable_second_sdram_bank();
+ if (a9m2440_check_for_ram(S3C_SDRAM_BASE + 64 * 1024 * 1024))
+ s3c24xx_disable_second_sdram_bank();
break;
case 2:
- if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 128 * 1024 * 1024))
- a9m2440_disable_second_sdram_bank();
+ if (a9m2440_check_for_ram(S3C_SDRAM_BASE + 128 * 1024 * 1024))
+ s3c24xx_disable_second_sdram_bank();
break;
case 4:
case 5:
case 6: /* not supported on this machine */
break;
default:
- if (a9m2440_check_for_ram(S3C24X0_SDRAM_BASE + 16 * 1024 * 1024))
- a9m2440_disable_second_sdram_bank();
+ if (a9m2440_check_for_ram(S3C_SDRAM_BASE + 16 * 1024 * 1024))
+ s3c24xx_disable_second_sdram_bank();
break;
}
- arm_add_mem_device("ram0", CS6_BASE, s3c24x0_get_memory_size());
+ arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c24xx_get_memory_size());
return 0;
}
@@ -114,23 +110,23 @@ static int a9m2440_devices_init(void)
uint32_t reg;
/* ----------- configure the access to the outer space ---------- */
- reg = readl(BWSCON);
+ reg = readl(S3C_BWSCON);
/* CS#5 to access the network controller */
reg &= ~0x00f00000;
reg |= 0x00d00000; /* 16 bit */
- writel(0x1f4c, BANKCON5);
+ writel(0x1f4c, S3C_BANKCON5);
- writel(reg, BWSCON);
+ writel(reg, S3C_BWSCON);
#ifdef CONFIG_MACH_A9M2410DEV
a9m2410dev_devices_init();
#endif
/* release the reset signal to external devices */
- reg = readl(MISCCR);
+ reg = readl(S3C_MISCCR);
reg |= 0x10000;
- writel(reg, MISCCR);
+ writel(reg, S3C_MISCCR);
/* ----------- the devices the boot loader should work with -------- */
add_generic_device("s3c24x0_nand", -1, NULL, S3C24X0_NAND_BASE, 0,
@@ -140,7 +136,7 @@ static int a9m2440_devices_init(void)
* Connected to CS line 5 + A24 and interrupt line EINT9,
* data width is 16 bit
*/
- add_generic_device("cs8900", -1, NULL, CS5_BASE + (1 << 24) + 0x300, 16,
+ add_generic_device("cs8900", -1, NULL, S3C_CS5_BASE + (1 << 24) + 0x300, 16,
IORESOURCE_MEM, NULL);
#ifdef CONFIG_NAND
@@ -151,7 +147,7 @@ static int a9m2440_devices_init(void)
devfs_add_partition("nand0", 0x40000, 0x20000, PARTITION_FIXED, "env_raw");
dev_add_bb_dev("env_raw", "env0");
#endif
- armlinux_set_bootparams((void*)CS6_BASE + 0x100);
+ armlinux_set_bootparams((void*)S3C_SDRAM_BASE + 0x100);
armlinux_set_architecture(MACH_TYPE_A9M2440);
return 0;
@@ -168,7 +164,7 @@ void __bare_init nand_boot(void)
static int a9m2440_console_init(void)
{
- add_generic_device("s3c24x0_serial", -1, NULL, UART1_BASE, UART1_SIZE,
+ add_generic_device("s3c_serial", -1, NULL, S3C_UART1_BASE, S3C_UART1_SIZE,
IORESOURCE_MEM, NULL);
return 0;
}
diff --git a/arch/arm/boards/a9m2440/lowlevel_init.S b/arch/arm/boards/a9m2440/lowlevel_init.S
index 4b5c596076..e915a1649c 100644
--- a/arch/arm/boards/a9m2440/lowlevel_init.S
+++ b/arch/arm/boards/a9m2440/lowlevel_init.S
@@ -3,7 +3,8 @@
*/
#include <config.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c24xx-gpio.h>
.section ".text_bare_init.board_init_lowlevel","ax"
@@ -33,11 +34,11 @@ sdram_init:
* configured yet, these pins show external settings, to detect
* the SDRAM size.
*/
- ldr r1, =GPBDAT
+ ldr r1, =S3C_GPBDAT
ldr r4, [r1]
and r4, r4, #0x3
- ldr r1, =S3C24X0_MEMCTL_BASE
+ ldr r1, =S3C_MEMCTL_BASE
/* configure both SDRAM areas with 32 bit data bus width */
ldr r0, =((0x2 << 24) + (0x2 << 28))
str r0, [r1], #0x1c /* post add register offset for bank6 */
@@ -218,9 +219,9 @@ board_init_lowlevel:
bl s3c24x0_disable_wd
/* skip everything here if we are already running from SDRAM */
- cmp pc, #S3C24X0_SDRAM_BASE
+ cmp pc, #S3C_SDRAM_BASE
blo 1f
- cmp pc, #S3C24X0_SDRAM_END
+ cmp pc, #S3C_SDRAM_END
bhs 1f
mov pc, r10
diff --git a/arch/arm/boards/at91rm9200ek/env/config b/arch/arm/boards/at91rm9200ek/env/config
index 1b56b25b5d..12655c2b43 100644
--- a/arch/arm/boards/at91rm9200ek/env/config
+++ b/arch/arm/boards/at91rm9200ek/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
nor_parts="256k(barebox)ro,64k(bareboxenv),1536k(kernel),-(root)"
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/_update b/arch/arm/boards/at91sam9260ek/env/bin/_update
deleted file mode 100644
index 014bce3512..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/_update
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/sh
-
-if [ -z "$part" -o -z "$image" ]; then
- echo "define \$part and \$image"
- exit 1
-fi
-
-if [ ! -e "$part" ]; then
- echo "Partition $part does not exist"
- exit 1
-fi
-
-if [ $# = 1 ]; then
- image=$1
-fi
-
-if [ x$ip = xdhcp ]; then
- dhcp
-fi
-
-ping $eth0.serverip
-if [ $? -ne 0 ] ; then
- echo "update aborted"
- exit 1
-fi
-
-unprotect $part
-
-echo
-echo "erasing partition $part"
-erase $part
-
-echo
-echo "flashing $image to $part"
-echo
-tftp $image $part
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/boot b/arch/arm/boards/at91sam9260ek/env/bin/boot
deleted file mode 100644
index ed6f11a108..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/boot
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/sh
-
-. /env/config
-
-if [ x$1 = xflash ]; then
- root=flash
- kernel=flash
-fi
-
-if [ x$1 = xnet ]; then
- root=net
- kernel=net
-fi
-
-if [ x$ip = xdhcp ]; then
- bootargs="$bootargs ip=dhcp"
-else
- bootargs="$bootargs ip=$eth0.ipaddr:$eth0.serverip:$eth0.gateway:$eth0.netmask:::"
-fi
-
-if [ x$root = xflash ]; then
- bootargs="$bootargs root=$rootpart rootfstype=jffs2"
-else
- bootargs="$bootargs root=/dev/nfs nfsroot=192.168.23.111:$nfsroot"
-fi
-
-bootargs="$bootargs mtdparts=physmap-flash.0:$mtdparts"
-
-if [ $kernel = net ]; then
- if [ x$ip = xdhcp ]; then
- dhcp
- fi
- tftp $uimage uImage
- bootm uImage
-else
- bootm /dev/nor0.kernel
-fi
-
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/init b/arch/arm/boards/at91sam9260ek/env/bin/init
deleted file mode 100644
index b8d8399842..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/init
+++ /dev/null
@@ -1,19 +0,0 @@
-#!/bin/sh
-
-PATH=/env/bin
-export PATH
-
-. /env/config
-
-echo
-echo -n "Hit any key to stop autoboot: "
-timeout -a $autoboot_timeout
-if [ $? != 0 ]; then
- echo
- echo "type update_kernel [<imagename>] to update kernel into flash"
- echo "type udate_root [<imagename>] to update rootfs into flash"
- echo
- exit
-fi
-
-boot \ No newline at end of file
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/init_board b/arch/arm/boards/at91sam9260ek/env/bin/init_board
new file mode 100644
index 0000000000..0da2781045
--- /dev/null
+++ b/arch/arm/boards/at91sam9260ek/env/bin/init_board
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+#PIOA_31
+gpio_get_value 63
+if [ $? != 0 ]
+then
+ exit
+fi
+
+echo "BP4 pressed detected wait 5s"
+timeout -s -a 5
+gpio_get_value 63
+if [ $? != 0 ]
+then
+ echo "BP4 released, normal boot"
+ exit
+fi
+
+echo ""
+echo "Start DFU Mode"
+echo ""
+
+dfu /dev/self0(barebox)sr,/dev/nand0.kernel.bb(kernel)r,/dev/nand0.root.bb(root)r -P 0x1234 -V 0x4321
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/pcidmaloop b/arch/arm/boards/at91sam9260ek/env/bin/pcidmaloop
deleted file mode 100644
index 24e76cbed7..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/pcidmaloop
+++ /dev/null
@@ -1,14 +0,0 @@
-pci stat
-pci stat -c
-while true; do
- pci readm 32 0xA1000000 32 -s
- pci readm 32 0xA2000000 256 -s
- pci dmatx 2000 a2000100 128 -s
- pci writem 32 0xa2000100 0x12345678 4 -s
- pci readm 32 0xA3000000 256 -s
- pci dmatx 2000 a3000040 128 -s
- pci writem 32 0xa3000100 0x12345678 4 -s
- pci readm 32 0xA4000000 16 -s
- pci dmatx 2000 a4000080 4 -s
- pci writem 32 0xa4000080 0x12345678 4 -s
-done
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/pciloop b/arch/arm/boards/at91sam9260ek/env/bin/pciloop
deleted file mode 100644
index 4a804f9f31..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/pciloop
+++ /dev/null
@@ -1,13 +0,0 @@
-pci stat
-pci stat -c
-while true; do
- pci readm 32 0xA1000000 32 -s
- pci readm 32 0xA2000000 256 -s
- pci writem 32 0xa2000100 0x12345678 4 -s
- pci readm 32 0xA3000000 256 -s
- pci writem 32 0xa3000100 0x12345678 4 -s
- pci readm 32 0xA4000000 16 -s
- pci writem 32 0xa4000080 0x12345678 4 -s
-
-# pci dmatx 2000 a3000040 128 -s
-done
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/update_kernel b/arch/arm/boards/at91sam9260ek/env/bin/update_kernel
deleted file mode 100644
index 1ad95fc5d6..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/update_kernel
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-. /env/config
-
-image=$uimage
-part=/dev/nor0.kernel
-
-. /env/bin/_update $1
diff --git a/arch/arm/boards/at91sam9260ek/env/bin/update_root b/arch/arm/boards/at91sam9260ek/env/bin/update_root
deleted file mode 100644
index b757a5b922..0000000000
--- a/arch/arm/boards/at91sam9260ek/env/bin/update_root
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/sh
-
-. /env/config
-
-image=$jffs2
-part=/dev/nor0.root
-
-. /env/bin/_update $1
diff --git a/arch/arm/boards/at91sam9260ek/env/config b/arch/arm/boards/at91sam9260ek/env/config
index 71d6f88cfe..ba14c2bfc5 100644
--- a/arch/arm/boards/at91sam9260ek/env/config
+++ b/arch/arm/boards/at91sam9260ek/env/config
@@ -1,20 +1,41 @@
#!/bin/sh
-# can be either 'net' or 'flash'
-kernel=net
-root=net
-
-# use 'dhcp' todo dhcp in barebox and in kernel
+# use 'dhcp' to do dhcp in barebox and in kernel
+# use 'none' if you want to skip kernel ip autoconfiguration
ip=dhcp
-#
-# setup default ethernet address
-#
-eth0.serverip=192.168.23.108
+# 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=nfs
+# can be either 'net', 'nor', 'nand' or 'initrd'
+rootfs_loc=net
+
+# can be either 'jffs2' or 'ubifs'
+rootfs_type=ubifs
+rootfsimage=root.$rootfs_type
-uimage=uImage-at91sam9260ek
+# 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
-nfsroot="/home/jbe/pengutronix/bsp/OSELAS.BSP-Phytec-phyCORE-i.MX27-trunk/root,v3"
-bootargs="console=ttyS0,115200 rw init=/bin/sh"
+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/at91sam9260ek/init.c b/arch/arm/boards/at91sam9260ek/init.c
index 958319e4ad..b10d0dc14e 100644
--- a/arch/arm/boards/at91sam9260ek/init.c
+++ b/arch/arm/boards/at91sam9260ek/init.c
@@ -31,6 +31,7 @@
#include <io.h>
#include <asm/hardware.h>
#include <nand.h>
+#include <sizes.h>
#include <linux/mtd/nand.h>
#include <mach/board.h>
#include <mach/at91sam9_smc.h>
@@ -70,9 +71,10 @@ static struct atmel_nand_data nand_pdata = {
#else
.bus_width_16 = 0,
#endif
+ .on_flash_bbt = 1,
};
-static struct sam9_smc_config ek_nand_smc_config = {
+static struct sam9_smc_config ek_9260_nand_smc_config = {
.ncs_read_setup = 0,
.nrd_setup = 1,
.ncs_write_setup = 0,
@@ -90,16 +92,41 @@ static struct sam9_smc_config ek_nand_smc_config = {
.tdf_cycles = 2,
};
+static struct sam9_smc_config ek_9g20_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 = 4,
+
+ .read_cycle = 7,
+ .write_cycle = 7,
+
+ .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
+ .tdf_cycles = 3,
+};
+
static void ek_add_device_nand(void)
{
+ struct sam9_smc_config *smc;
+
+ if (machine_is_at91sam9g20ek())
+ smc = &ek_9g20_nand_smc_config;
+ else
+ smc = &ek_9260_nand_smc_config;
+
/* setup bus-width (8 or 16) */
if (nand_pdata.bus_width_16)
- ek_nand_smc_config.mode |= AT91_SMC_DBW_16;
+ smc->mode |= AT91_SMC_DBW_16;
else
- ek_nand_smc_config.mode |= AT91_SMC_DBW_8;
+ smc->mode |= AT91_SMC_DBW_8;
/* configure chip-select 3 (NAND) */
- sam9_smc_configure(3, &ek_nand_smc_config);
+ sam9_smc_configure(3, smc);
at91_add_device_nand(&nand_pdata);
}
@@ -139,6 +166,40 @@ static void at91sam9260ek_phy_reset(void)
AT91_RSTC_URSTEN);
}
+/*
+ * MCI (SD/MMC)
+ */
+#if defined(CONFIG_MCI_ATMEL)
+static struct atmel_mci_platform_data __initdata ek_mci_data = {
+ .bus_width = 4,
+};
+
+static void ek_usb_add_device_mci(void)
+{
+ if (machine_is_at91sam9g20ek())
+ ek_mci_data.detect_pin = AT91_PIN_PC9;
+
+ at91_add_device_mci(1, &ek_mci_data);
+}
+#else
+static void ek_usb_add_device_mci(void) {}
+#endif
+
+/*
+ * USB Host port
+ */
+static struct at91_usbh_data __initdata ek_usbh_data = {
+ .ports = 2,
+};
+
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PC5,
+ .pullup_pin = -EINVAL, /* pull-up driven by UDC */
+};
+
static int at91sam9260ek_mem_init(void)
{
at91_add_device_sdram(64 * 1024 * 1024);
@@ -147,19 +208,35 @@ static int at91sam9260ek_mem_init(void)
}
mem_initcall(at91sam9260ek_mem_init);
+static void __init ek_add_device_buttons(void)
+{
+ at91_set_gpio_input(AT91_PIN_PA30, 1); /* btn3 */
+ at91_set_deglitch(AT91_PIN_PA30, 1);
+ at91_set_gpio_input(AT91_PIN_PA31, 1); /* btn4 */
+ at91_set_deglitch(AT91_PIN_PA31, 1);
+}
+
static int at91sam9260ek_devices_init(void)
{
ek_add_device_nand();
at91sam9260ek_phy_reset();
at91_add_device_eth(&macb_pdata);
+ at91_add_device_usbh_ohci(&ek_usbh_data);
+ at91_add_device_udc(&ek_udc_data);
+ ek_usb_add_device_mci();
+ ek_add_device_buttons();
armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100));
ek_set_board_type();
- devfs_add_partition("nand0", 0x00000, 0x80000, PARTITION_FIXED, "self_raw");
+ 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", 0x80000, 0x20000, PARTITION_FIXED, "env_raw");
+ 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;
}
diff --git a/arch/arm/boards/at91sam9261ek/env/config b/arch/arm/boards/at91sam9261ek/env/config
index 733326d483..d6eeea42f9 100644
--- a/arch/arm/boards/at91sam9261ek/env/config
+++ b/arch/arm/boards/at91sam9261ek/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
diff --git a/arch/arm/boards/at91sam9261ek/init.c b/arch/arm/boards/at91sam9261ek/init.c
index 0bef84d132..8b192b2cf7 100644
--- a/arch/arm/boards/at91sam9261ek/init.c
+++ b/arch/arm/boards/at91sam9261ek/init.c
@@ -50,6 +50,7 @@ static struct atmel_nand_data nand_pdata = {
#else
.bus_width_16 = 0,
#endif
+ .on_flash_bbt = 1,
};
static struct sam9_smc_config ek_nand_smc_config = {
@@ -87,7 +88,7 @@ static void ek_add_device_nand(void)
/*
* DM9000 ethernet device
*/
-#if defined(CONFIG_DRIVER_NET_DM9000)
+#if defined(CONFIG_DRIVER_NET_DM9K)
static struct dm9000_platform_data dm9000_data = {
.srom = 0,
};
@@ -130,7 +131,7 @@ static void __init ek_add_device_dm9000(void)
}
#else
static void __init ek_add_device_dm9000(void) {}
-#endif /* CONFIG_DRIVER_NET_DM9000 */
+#endif /* CONFIG_DRIVER_NET_DM9K */
static int at91sam9261ek_mem_init(void)
{
diff --git a/arch/arm/boards/at91sam9263ek/config.h b/arch/arm/boards/at91sam9263ek/config.h
index bc33227e11..8f764ebf40 100644
--- a/arch/arm/boards/at91sam9263ek/config.h
+++ b/arch/arm/boards/at91sam9263ek/config.h
@@ -40,8 +40,6 @@
AT91_MATRIX_EBI0_CS1A_SDRAMC)
/* SDRAM */
-/* SDRAMC_MR Mode register */
-#define CONFIG_SYS_SDRC_MR_VAL1 0
/* SDRAMC_TR - Refresh Timer register */
#define CONFIG_SYS_SDRC_TR_VAL1 0x13C
/* SDRAMC_CR - Configuration register*/
@@ -60,23 +58,7 @@
/* Memory Device Register -> SDRAM */
#define CONFIG_SYS_SDRC_MDR_VAL AT91_SDRAMC_MD_SDRAM
-#define CONFIG_SYS_SDRC_MR_VAL2 AT91_SDRAMC_MODE_PRECHARGE
-#define CONFIG_SYS_SDRAM_VAL1 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL3 AT91_SDRAMC_MODE_REFRESH
-#define CONFIG_SYS_SDRAM_VAL2 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL3 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL4 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL5 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL6 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL7 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL8 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL9 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL4 AT91_SDRAMC_MODE_LMR
-#define CONFIG_SYS_SDRAM_VAL10 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL5 AT91_SDRAMC_MODE_NORMAL
-#define CONFIG_SYS_SDRAM_VAL11 0 /* SDRAM_BASE */
#define CONFIG_SYS_SDRC_TR_VAL2 1200 /* SDRAM_TR */
-#define CONFIG_SYS_SDRAM_VAL12 0 /* SDRAM_BASE */
/* setup SMC0, CS0 (NOR Flash) - 16-bit, 15 WS */
#define CONFIG_SYS_SMC0_SETUP0_VAL \
diff --git a/arch/arm/boards/at91sam9263ek/env/config b/arch/arm/boards/at91sam9263ek/env/config
index 4e2923227c..e189b8e593 100644
--- a/arch/arm/boards/at91sam9263ek/env/config
+++ b/arch/arm/boards/at91sam9263ek/env/config
@@ -19,20 +19,17 @@ rootfs_loc=net
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="256k(barebox)ro,128k(bareboxenv),1536k(kernel),-(root)"
rootfs_mtdblock_nand=3
+nor_parts="256k(barebox),64k(bareboxenv),1536k(kernel),-(root)"
+
autoboot_timeout=3
bootargs="console=ttyS0,115200"
diff --git a/arch/arm/boards/at91sam9263ek/init.c b/arch/arm/boards/at91sam9263ek/init.c
index bb564d7d1b..d7b9afe5db 100644
--- a/arch/arm/boards/at91sam9263ek/init.c
+++ b/arch/arm/boards/at91sam9263ek/init.c
@@ -51,6 +51,7 @@ static struct atmel_nand_data nand_pdata = {
#else
.bus_width_16 = 0,
#endif
+ .on_flash_bbt = 1,
};
static struct sam9_smc_config ek_nand_smc_config = {
diff --git a/arch/arm/boards/at91sam9m10g45ek/env/config b/arch/arm/boards/at91sam9m10g45ek/env/config
index b8ca18dce7..3dea7247f5 100644
--- a/arch/arm/boards/at91sam9m10g45ek/env/config
+++ b/arch/arm/boards/at91sam9m10g45ek/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
diff --git a/arch/arm/boards/at91sam9m10g45ek/init.c b/arch/arm/boards/at91sam9m10g45ek/init.c
index 5fdc96037e..eff2769de5 100644
--- a/arch/arm/boards/at91sam9m10g45ek/init.c
+++ b/arch/arm/boards/at91sam9m10g45ek/init.c
@@ -72,6 +72,7 @@ static struct atmel_nand_data nand_pdata = {
#else
.bus_width_16 = 0,
#endif
+ .on_flash_bbt = 1,
};
static struct sam9_smc_config ek_nand_smc_config = {
diff --git a/arch/arm/boards/chumby_falconwing/env/bin/boot b/arch/arm/boards/chumby_falconwing/env/bin/boot
index 981a387a1d..999170cb4b 100644
--- a/arch/arm/boards/chumby_falconwing/env/bin/boot
+++ b/arch/arm/boards/chumby_falconwing/env/bin/boot
@@ -26,13 +26,6 @@ elif [ x$rootfs_loc = xinitrd ]; then
bootargs="$bootargs root=/dev/ram0 rdinit=/sbin/init"
fi
-if [ x$kernelimage_type = xuimage ]; then
- bootm /dev/$kernel_part
-elif [ x$kernelimage_type = xzimage ]; then
- bootz /dev/$kernel_part
-else
- echo "Booting failed. Correct setup of 'kernelimage_type'?"
- exit
-fi
+bootm /dev/$kernel_part
echo "Booting failed. Correct setup of 'kernel_part'?"
diff --git a/arch/arm/boards/chumby_falconwing/env/config b/arch/arm/boards/chumby_falconwing/env/config
index 1e61dce976..1419161253 100644
--- a/arch/arm/boards/chumby_falconwing/env/config
+++ b/arch/arm/boards/chumby_falconwing/env/config
@@ -25,8 +25,6 @@ rootfs_part=mmcblk0p4
# Where is the rootfs in case of 'rootfs_loc=net'
nfsroot=FIXME
-# The image type of the kernel. Can be uimage, zimage
-kernelimage_type=uimage
# Where to get the kernel image in case of 'kernel_loc=disk'
kernel_part=disk0.2
diff --git a/arch/arm/boards/dss11/env/config b/arch/arm/boards/dss11/env/config
index 5c9be7d6df..adf3af5d74 100644
--- a/arch/arm/boards/dss11/env/config
+++ b/arch/arm/boards/dss11/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
diff --git a/arch/arm/boards/eukrea_cpuimx25/env/config b/arch/arm/boards/eukrea_cpuimx25/env/config
index 5cedbf8216..bc1cfd5060 100644
--- a/arch/arm/boards/eukrea_cpuimx25/env/config
+++ b/arch/arm/boards/eukrea_cpuimx25/env/config
@@ -25,7 +25,6 @@ rootfs_type=ubifs
rootfsimage=$machine/rootfs.$rootfs_type
# kernel
-kernelimage_type=uimage
kernelimage=$machine/uImage-${machine}.bin
# barebox and it's env
diff --git a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c
index 162c1179b0..73e54f2f54 100644
--- a/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c
+++ b/arch/arm/boards/eukrea_cpuimx25/eukrea_cpuimx25.c
@@ -116,6 +116,7 @@ static struct imx_fb_videomode imxfb_mode = {
static struct imx_fb_platform_data eukrea_cpuimx25_fb_data = {
.mode = &imxfb_mode,
+ .num_modes = 1,
.pwmr = 0x00A903FF,
.lscr1 = 0x00120300,
.dmacr = 0x80040060,
diff --git a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c
index c419c7305a..e2766fb49c 100644
--- a/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c
+++ b/arch/arm/boards/eukrea_cpuimx27/eukrea_cpuimx27.c
@@ -116,6 +116,7 @@ static struct imx_fb_videomode imxfb_mode = {
static struct imx_fb_platform_data eukrea_cpuimx27_fb_data = {
.mode = &imxfb_mode,
+ .num_modes = 1,
.pwmr = 0x00A903FF,
.lscr1 = 0x00120300,
.dmacr = 0x00020010,
diff --git a/arch/arm/boards/eukrea_cpuimx35/env/config b/arch/arm/boards/eukrea_cpuimx35/env/config
index 776d19a24d..8f64ba05ca 100644
--- a/arch/arm/boards/eukrea_cpuimx35/env/config
+++ b/arch/arm/boards/eukrea_cpuimx35/env/config
@@ -25,7 +25,6 @@ rootfs_type=ubifs
rootfsimage=$machine/rootfs.$rootfs_type
# kernel
-kernelimage_type=uimage
kernelimage=$machine/uImage-${machine}.bin
# barebox and it's env
diff --git a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
index 20cfad481f..d167ab907c 100644
--- a/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
+++ b/arch/arm/boards/eukrea_cpuimx35/eukrea_cpuimx35.c
@@ -144,6 +144,9 @@ postmmu_initcall(eukrea_cpuimx35_mmu_init);
static int eukrea_cpuimx35_devices_init(void)
{
+#ifdef CONFIG_USB_GADGET
+ unsigned int tmp;
+#endif
imx35_add_nand(&nand_info);
devfs_add_partition("nand0", 0x00000, 0x40000, PARTITION_FIXED, "self_raw");
diff --git a/arch/arm/boards/eukrea_cpuimx51/Makefile b/arch/arm/boards/eukrea_cpuimx51/Makefile
index 0f506a38d0..0f781c0f34 100644
--- a/arch/arm/boards/eukrea_cpuimx51/Makefile
+++ b/arch/arm/boards/eukrea_cpuimx51/Makefile
@@ -1,3 +1,2 @@
-obj-y += lowlevel_init.o
obj-y += eukrea_cpuimx51.o
obj-y += flash_header.o
diff --git a/arch/arm/boards/eukrea_cpuimx51/env/config b/arch/arm/boards/eukrea_cpuimx51/env/config
index 91a267163a..1b57b29039 100644
--- a/arch/arm/boards/eukrea_cpuimx51/env/config
+++ b/arch/arm/boards/eukrea_cpuimx51/env/config
@@ -28,7 +28,6 @@ rootfs_type=ubifs
rootfsimage=$machine/rootfs.$rootfs_type
# kernel
-kernelimage_type=uimage
kernelimage=$machine/uImage-${machine}.bin
# barebox and it's env
diff --git a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c
index a2db6d9588..153ad2f261 100644
--- a/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c
+++ b/arch/arm/boards/eukrea_cpuimx51/eukrea_cpuimx51.c
@@ -39,6 +39,7 @@
#include <mach/imx-nand.h>
#include <mach/spi.h>
#include <mach/generic.h>
+#include <mach/imx5.h>
#include <mach/iomux-mx51.h>
#include <mach/devices-imx51.h>
@@ -139,6 +140,8 @@ static int eukrea_cpuimx51_console_init(void)
{
mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51_pads, ARRAY_SIZE(eukrea_cpuimx51_pads));
+ imx51_init_lowlevel();
+
writel(0, 0x73fa8228);
writel(0, 0x73fa822c);
writel(0, 0x73fa8230);
diff --git a/arch/arm/boards/eukrea_cpuimx51/lowlevel_init.S b/arch/arm/boards/eukrea_cpuimx51/lowlevel_init.S
deleted file mode 100644
index 0b3726f6d5..0000000000
--- a/arch/arm/boards/eukrea_cpuimx51/lowlevel_init.S
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * This code is based on the ecos babbage startup code
- *
- * 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 <config.h>
-#include <mach/imx-regs.h>
-#include <mach/clock-imx51_53.h>
-
-#define ROM_SI_REV_OFFSET 0x48
-
-.macro setup_pll pll, freq
- ldr r2, =\pll
- ldr r1, =0x00001232
- str r1, [r2, #MX5_PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */
- mov r1, #0x2
- str r1, [r2, #MX5_PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
-
- str r3, [r2, #MX5_PLL_DP_OP]
- str r3, [r2, #MX5_PLL_DP_HFS_OP]
-
- str r4, [r2, #MX5_PLL_DP_MFD]
- str r4, [r2, #MX5_PLL_DP_HFS_MFD]
-
- str r5, [r2, #MX5_PLL_DP_MFN]
- str r5, [r2, #MX5_PLL_DP_HFS_MFN]
-
- ldr r1, =0x00001232
- str r1, [r2, #MX5_PLL_DP_CTL]
-1: ldr r1, [r2, #MX5_PLL_DP_CTL]
- ands r1, r1, #0x1
- beq 1b
-.endm
-
-#define writel(val, reg) \
- ldr r0, =reg; \
- ldr r1, =val; \
- str r1, [r0];
-
-#define IMX51_TO_2
-
-.globl board_init_lowlevel
-board_init_lowlevel:
- mov r10, lr
-
- /* explicitly disable L2 cache */
- mrc 15, 0, r0, c1, c0, 1
- bic r0, r0, #0x2
- mcr 15, 0, r0, c1, c0, 1
-
- /* reconfigure L2 cache aux control reg */
- mov r0, #0xC0 /* tag RAM */
- add r0, r0, #0x4 /* data RAM */
- orr r0, r0, #(1 << 24) /* disable write allocate delay */
- orr r0, r0, #(1 << 23) /* disable write allocate combine */
- orr r0, r0, #(1 << 22) /* disable write allocate */
-
- ldr r1, =MX51_IROM_BASE_ADDR
- ldr r3, [r1, #ROM_SI_REV_OFFSET]
- cmp r3, #0x10
- orrls r0, r0, #(1 << 25) /* disable write combine for TO 2 and lower revs */
-
- mcr 15, 1, r0, c9, c0, 2
-
- ldr r0, =MX51_CCM_BASE_ADDR
-
- /* Gate of clocks to the peripherals first */
- ldr r1, =0x3FFFFFFF
- str r1, [r0, #MX5_CCM_CCGR0]
- ldr r1, =0x0
- str r1, [r0, #MX5_CCM_CCGR1]
- str r1, [r0, #MX5_CCM_CCGR2]
- str r1, [r0, #MX5_CCM_CCGR3]
-
- ldr r1, =0x00030000
- str r1, [r0, #MX5_CCM_CCGR4]
- ldr r1, =0x00FFF030
- str r1, [r0, #MX5_CCM_CCGR5]
- ldr r1, =0x00000300
- str r1, [r0, #MX5_CCM_CCGR6]
-
- /* Disable IPU and HSC dividers */
- mov r1, #0x60000
- str r1, [r0, #MX5_CCM_CCDR]
-
-#ifdef IMX51_TO_2
- /* Make sure to switch the DDR away from PLL 1 */
- ldr r1, =0x19239145
- str r1, [r0, #MX5_CCM_CBCDR]
- /* make sure divider effective */
-1: ldr r1, [r0, #MX5_CCM_CDHIPR]
- cmp r1, #0x0
- bne 1b
-#endif
-
- /* Switch ARM to step clock */
- mov r1, #0x4
- str r1, [r0, #MX5_CCM_CCSR]
-
- mov r3, #MX5_PLL_DP_OP_800
- mov r4, #MX5_PLL_DP_MFD_800
- mov r5, #MX5_PLL_DP_MFN_800
- setup_pll MX51_PLL1_BASE_ADDR
-
- mov r3, #MX5_PLL_DP_OP_665
- mov r4, #MX5_PLL_DP_MFD_665
- mov r5, #MX5_PLL_DP_MFN_665
- setup_pll MX51_PLL3_BASE_ADDR
-
- /* Switch peripheral to PLL 3 */
- ldr r1, =0x000010C0
- str r1, [r0, #MX5_CCM_CBCMR]
- ldr r1, =0x13239145
- str r1, [r0, #MX5_CCM_CBCDR]
-
- mov r3, #MX5_PLL_DP_OP_665
- mov r4, #MX5_PLL_DP_MFD_665
- mov r5, #MX5_PLL_DP_MFN_665
- setup_pll MX51_PLL2_BASE_ADDR
-
- /* Switch peripheral to PLL2 */
- ldr r1, =0x19239145
- str r1, [r0, #MX5_CCM_CBCDR]
- ldr r1, =0x000020C0
- str r1, [r0, #MX5_CCM_CBCMR]
-
- mov r3, #MX5_PLL_DP_OP_216
- mov r4, #MX5_PLL_DP_MFD_216
- mov r5, #MX5_PLL_DP_MFN_216
- setup_pll MX51_PLL3_BASE_ADDR
-
- /* Set the platform clock dividers */
- ldr r2, =MX51_ARM_BASE_ADDR
- ldr r1, =0x00000124
- str r1, [r2, #0x14]
-
- /* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */
- ldr r1, =MX51_IROM_BASE_ADDR
- ldr r3, [r1, #ROM_SI_REV_OFFSET]
- cmp r3, #0x10
- movls r1, #0x1
- movhi r1, #0
- str r1, [r0, #MX5_CCM_CACRR]
-
- /* Switch ARM back to PLL 1 */
- mov r1, #0
- str r1, [r0, #MX5_CCM_CCSR]
-
- /* setup the rest */
- /* Use lp_apm (24MHz) source for perclk */
-#ifdef IMX51_TO_2
- ldr r1, =0x000020C2
- str r1, [r0, #MX5_CCM_CBCMR]
- // ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz
- ldr r1, =0x59239100
- str r1, [r0, #MX5_CCM_CBCDR]
-#else
- ldr r1, =0x0000E3C2
- str r1, [r0, #MX5_CCM_CBCMR]
- // emi=ahb, all perclk dividers are 1 since using 24MHz
- // DDR divider=6 to have 665/6=110MHz
- ldr r1, =0x013B9100
- str r1, [r0, #MX5_CCM_CBCDR]
-#endif
-
- /* Restore the default values in the Gate registers */
- ldr r1, =0xFFFFFFFF
- str r1, [r0, #MX5_CCM_CCGR0]
- str r1, [r0, #MX5_CCM_CCGR1]
- str r1, [r0, #MX5_CCM_CCGR2]
- str r1, [r0, #MX5_CCM_CCGR3]
- str r1, [r0, #MX5_CCM_CCGR4]
- str r1, [r0, #MX5_CCM_CCGR5]
- str r1, [r0, #MX5_CCM_CCGR6]
-
- /* Use PLL 2 for UART's, get 66.5MHz from it */
- ldr r1, =0xA5A2A020
- str r1, [r0, #MX5_CCM_CSCMR1]
- ldr r1, =0x00C30321
- str r1, [r0, #MX5_CCM_CSCDR1]
-
- /* make sure divider effective */
- 1: ldr r1, [r0, #MX5_CCM_CDHIPR]
- cmp r1, #0x0
- bne 1b
-
- mov r1, #0x0
- str r1, [r0, #MX5_CCM_CCDR]
-
- writel(0x1, 0x73fa8074)
- ldr r0, =0x73f88000
- ldr r1, [r0]
- orr r1, #0x40
- str r1, [r0]
-
- ldr r0, =0x73f88004
- ldr r1, [r0]
- orr r1, #0x40
- str r1, [r0]
-
- mov pc, r10
-
diff --git a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
index 47f676919a..20d49fd691 100644
--- a/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
+++ b/arch/arm/boards/freescale-mx23-evk/mx23-evk.c
@@ -1,5 +1,6 @@
/*
* (C) Copyright 2010 Juergen Beisert - Pengutronix
+ * (C) Copyright 2011 Wolfram Sang - Pengutronix
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -21,9 +22,28 @@
#include <init.h>
#include <gpio.h>
#include <environment.h>
+#include <mci.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
#include <mach/imx-regs.h>
+#include <mach/clock.h>
+#include <mach/mci.h>
+
+static struct mxs_mci_platform_data mci_pdata = {
+ .caps = MMC_MODE_4BIT,
+ .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, /* fixed to 3.3 V */
+};
+
+static const uint32_t pad_setup[] = {
+ /* SD card interface */
+ SSP1_DATA0 | PULLUP(1),
+ SSP1_DATA1 | PULLUP(1),
+ SSP1_DATA2 | PULLUP(1),
+ SSP1_DATA3 | PULLUP(1),
+ SSP1_SCK,
+ SSP1_CMD | PULLUP(1),
+ SSP1_DETECT | PULLUP(1),
+};
static int mx23_evk_mem_init(void)
{
@@ -35,9 +55,20 @@ mem_initcall(mx23_evk_mem_init);
static int mx23_evk_devices_init(void)
{
+ int i;
+
+ /* initizalize gpios */
+ for (i = 0; i < ARRAY_SIZE(pad_setup); i++)
+ imx_gpio_mode(pad_setup[i]);
+
armlinux_set_bootparams((void*)IMX_MEMORY_BASE + 0x100);
armlinux_set_architecture(MACH_TYPE_MX23EVK);
+ imx_set_ioclk(480000000); /* enable IOCLK to run at the PLL frequency */
+ imx_set_sspclk(0, 100000000, 1);
+ add_generic_device("mxs_mci", 0, NULL, IMX_SSP1_BASE, 0,
+ IORESOURCE_MEM, &mci_pdata);
+
return 0;
}
diff --git a/arch/arm/boards/freescale-mx28-evk/Makefile b/arch/arm/boards/freescale-mx28-evk/Makefile
new file mode 100644
index 0000000000..3e1f53b06d
--- /dev/null
+++ b/arch/arm/boards/freescale-mx28-evk/Makefile
@@ -0,0 +1 @@
+obj-y += mx28-evk.o
diff --git a/arch/arm/boards/freescale-mx28-evk/config.h b/arch/arm/boards/freescale-mx28-evk/config.h
new file mode 100644
index 0000000000..8f18fda7cc
--- /dev/null
+++ b/arch/arm/boards/freescale-mx28-evk/config.h
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+#ifndef _CONFIG_H_
+# define _CONFIG_H_
+
+#endif /* _CONFIG_H_ */
diff --git a/arch/arm/boards/freescale-mx28-evk/env/config b/arch/arm/boards/freescale-mx28-evk/env/config
new file mode 100644
index 0000000000..509563388e
--- /dev/null
+++ b/arch/arm/boards/freescale-mx28-evk/env/config
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+machine=mx28-evk
+#user=
+
+# 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
+#eth0.ethaddr=de:ad:be:ef:00:00
+
+# 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=ext2
+# 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
+
+kernelimage=zImage-$machine
+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=ttyAMA0,115200"
+
+# set a fancy prompt (if support is compiled in)
+PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m "
diff --git a/arch/arm/boards/freescale-mx28-evk/mx28-evk.c b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
new file mode 100644
index 0000000000..b80b910f54
--- /dev/null
+++ b/arch/arm/boards/freescale-mx28-evk/mx28-evk.c
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2010 Juergen Beisert, Pengutronix <kernel@pengutronix.de>
+ * Copyright (C) 2011 Marc Kleine-Budde, Pengutronix <mkl@pengutronix.de>
+ * Copyright (C) 2011 Wolfram Sang, Pengutronix <w.sang@pengutronix.de>
+ *
+ * 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.
+ */
+
+#include <common.h>
+#include <environment.h>
+#include <errno.h>
+#include <fec.h>
+#include <gpio.h>
+#include <init.h>
+#include <mci.h>
+#include <io.h>
+
+#include <mach/clock.h>
+#include <mach/imx-regs.h>
+#include <mach/iomux-imx28.h>
+#include <mach/mci.h>
+
+#include <asm/armlinux.h>
+#include <asm/mmu.h>
+
+#include <generated/mach-types.h>
+
+#define MX28EVK_FEC_PHY_RESET_GPIO 141
+
+/* setup the CPU card internal signals */
+static const uint32_t mx28evk_pads[] = {
+ /* duart */
+ PWM0_DUART_RX | VE_3_3V,
+ PWM1_DUART_TX | VE_3_3V,
+
+ /* fec0 */
+ ENET_CLK | VE_3_3V | BITKEEPER(0),
+ ENET0_MDC | VE_3_3V | PULLUP(1),
+ ENET0_MDIO | VE_3_3V | PULLUP(1),
+ ENET0_TXD0 | VE_3_3V | PULLUP(1),
+ ENET0_TXD1 | VE_3_3V | PULLUP(1),
+ ENET0_TX_EN | VE_3_3V | PULLUP(1),
+ ENET0_TX_CLK | VE_3_3V | BITKEEPER(0),
+ ENET0_RXD0 | VE_3_3V | PULLUP(1),
+ ENET0_RXD1 | VE_3_3V | PULLUP(1),
+ ENET0_RX_EN | VE_3_3V | PULLUP(1),
+ /* send a "good morning" to the ext. phy 0 = reset */
+ ENET0_RX_CLK_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(0),
+ /* phy power control 1 = on */
+ SSP1_D3_GPIO | VE_3_3V | PULLUP(0) | GPIO_OUT | GPIO_VALUE(0),
+
+ /* mmc0 */
+ SSP0_D0 | VE_3_3V | PULLUP(1),
+ SSP0_D1 | VE_3_3V | PULLUP(1),
+ SSP0_D2 | VE_3_3V | PULLUP(1),
+ SSP0_D3 | VE_3_3V | PULLUP(1),
+ SSP0_D4 | VE_3_3V | PULLUP(1),
+ SSP0_D5 | VE_3_3V | PULLUP(1),
+ SSP0_D6 | VE_3_3V | PULLUP(1),
+ SSP0_D7 | VE_3_3V | PULLUP(1),
+ SSP0_CMD | VE_3_3V | PULLUP(1),
+ SSP0_CD | VE_3_3V | PULLUP(1),
+ SSP0_SCK | VE_3_3V | BITKEEPER(0),
+ /* MCI slot power control 1 = off */
+ PWM3_GPIO | VE_3_3V | GPIO_OUT | GPIO_VALUE(0),
+ /* MCI write protect 1 = not protected */
+ SSP1_SCK_GPIO | VE_3_3V | GPIO_IN,
+};
+
+static struct mxs_mci_platform_data mci_pdata = {
+ .caps = MMC_MODE_8BIT,
+ .voltages = MMC_VDD_32_33 | MMC_VDD_33_34, /* fixed to 3.3 V */
+ .f_min = 400 * 1000,
+ .f_max = 25000000,
+};
+
+/* fec */
+static void __init mx28_evk_fec_reset(void)
+{
+ mdelay(1);
+ gpio_set_value(MX28EVK_FEC_PHY_RESET_GPIO, 1);
+}
+
+/* PhyAD[0..2]=0, RMIISEL=1 */
+static struct fec_platform_data fec_info = {
+ .xcv_type = RMII,
+ .phy_addr = 0,
+};
+
+static int mx28_evk_mem_init(void)
+{
+ arm_add_mem_device("ram0", IMX_MEMORY_BASE, 128 * 1024 * 1024);
+
+ return 0;
+}
+mem_initcall(mx28_evk_mem_init);
+
+static int mx28_evk_devices_init(void)
+{
+ int i;
+
+ /* initizalize muxing */
+ for (i = 0; i < ARRAY_SIZE(mx28evk_pads); i++)
+ imx_gpio_mode(mx28evk_pads[i]);
+
+ /* enable IOCLK0 to run at the PLL frequency */
+ imx_set_ioclk(0, 480000000);
+ /* run the SSP unit clock at 100 MHz */
+ imx_set_sspclk(0, 100000000, 1);
+
+ armlinux_set_bootparams((void *)IMX_MEMORY_BASE + 0x100);
+ armlinux_set_architecture(MACH_TYPE_MX28EVK);
+
+ add_generic_device("mxs_mci", 0, NULL, IMX_SSP0_BASE, 0,
+ IORESOURCE_MEM, &mci_pdata);
+
+ imx_enable_enetclk();
+ mx28_evk_fec_reset();
+ add_generic_device("fec_imx", 0, NULL, IMX_FEC0_BASE, 0,
+ IORESOURCE_MEM, &fec_info);
+
+ return 0;
+}
+device_initcall(mx28_evk_devices_init);
+
+static int mx28_evk_console_init(void)
+{
+ add_generic_device("stm_serial", 0, NULL, IMX_DBGUART_BASE, 8192,
+ IORESOURCE_MEM, NULL);
+
+ return 0;
+}
+console_initcall(mx28_evk_console_init);
diff --git a/arch/arm/boards/freescale-mx35-3-stack/env/config b/arch/arm/boards/freescale-mx35-3-stack/env/config
index ee9bd07e28..17b1e31f07 100644
--- a/arch/arm/boards/freescale-mx35-3-stack/env/config
+++ b/arch/arm/boards/freescale-mx35-3-stack/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/freescale-mx51-pdk/Makefile b/arch/arm/boards/freescale-mx51-pdk/Makefile
index 8e0c87c96f..b56ce7f50d 100644
--- a/arch/arm/boards/freescale-mx51-pdk/Makefile
+++ b/arch/arm/boards/freescale-mx51-pdk/Makefile
@@ -1,3 +1,2 @@
-obj-y += lowlevel_init.o
obj-y += board.o
obj-y += flash_header.o
diff --git a/arch/arm/boards/freescale-mx51-pdk/board.c b/arch/arm/boards/freescale-mx51-pdk/board.c
index d56effaaf9..e6781f3a6a 100644
--- a/arch/arm/boards/freescale-mx51-pdk/board.c
+++ b/arch/arm/boards/freescale-mx51-pdk/board.c
@@ -34,6 +34,7 @@
#include <mfd/mc13892.h>
#include <io.h>
#include <asm/mmu.h>
+#include <mach/imx5.h>
#include <mach/imx-nand.h>
#include <mach/spi.h>
#include <mach/generic.h>
@@ -265,6 +266,8 @@ static int f3s_console_init(void)
{
mxc_iomux_v3_setup_multiple_pads(f3s_pads, ARRAY_SIZE(f3s_pads));
+ imx51_init_lowlevel();
+
writel(0, 0x73fa8228);
writel(0, 0x73fa822c);
writel(0, 0x73fa8230);
diff --git a/arch/arm/boards/freescale-mx51-pdk/env/config b/arch/arm/boards/freescale-mx51-pdk/env/config
index 8e6b34eec1..10690c9c50 100644
--- a/arch/arm/boards/freescale-mx51-pdk/env/config
+++ b/arch/arm/boards/freescale-mx51-pdk/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/freescale-mx51-pdk/lowlevel_init.S b/arch/arm/boards/freescale-mx51-pdk/lowlevel_init.S
deleted file mode 100644
index 0b3726f6d5..0000000000
--- a/arch/arm/boards/freescale-mx51-pdk/lowlevel_init.S
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * This code is based on the ecos babbage startup code
- *
- * 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 <config.h>
-#include <mach/imx-regs.h>
-#include <mach/clock-imx51_53.h>
-
-#define ROM_SI_REV_OFFSET 0x48
-
-.macro setup_pll pll, freq
- ldr r2, =\pll
- ldr r1, =0x00001232
- str r1, [r2, #MX5_PLL_DP_CTL] /* Set DPLL ON (set UPEN bit): BRMO=1 */
- mov r1, #0x2
- str r1, [r2, #MX5_PLL_DP_CONFIG] /* Enable auto-restart AREN bit */
-
- str r3, [r2, #MX5_PLL_DP_OP]
- str r3, [r2, #MX5_PLL_DP_HFS_OP]
-
- str r4, [r2, #MX5_PLL_DP_MFD]
- str r4, [r2, #MX5_PLL_DP_HFS_MFD]
-
- str r5, [r2, #MX5_PLL_DP_MFN]
- str r5, [r2, #MX5_PLL_DP_HFS_MFN]
-
- ldr r1, =0x00001232
- str r1, [r2, #MX5_PLL_DP_CTL]
-1: ldr r1, [r2, #MX5_PLL_DP_CTL]
- ands r1, r1, #0x1
- beq 1b
-.endm
-
-#define writel(val, reg) \
- ldr r0, =reg; \
- ldr r1, =val; \
- str r1, [r0];
-
-#define IMX51_TO_2
-
-.globl board_init_lowlevel
-board_init_lowlevel:
- mov r10, lr
-
- /* explicitly disable L2 cache */
- mrc 15, 0, r0, c1, c0, 1
- bic r0, r0, #0x2
- mcr 15, 0, r0, c1, c0, 1
-
- /* reconfigure L2 cache aux control reg */
- mov r0, #0xC0 /* tag RAM */
- add r0, r0, #0x4 /* data RAM */
- orr r0, r0, #(1 << 24) /* disable write allocate delay */
- orr r0, r0, #(1 << 23) /* disable write allocate combine */
- orr r0, r0, #(1 << 22) /* disable write allocate */
-
- ldr r1, =MX51_IROM_BASE_ADDR
- ldr r3, [r1, #ROM_SI_REV_OFFSET]
- cmp r3, #0x10
- orrls r0, r0, #(1 << 25) /* disable write combine for TO 2 and lower revs */
-
- mcr 15, 1, r0, c9, c0, 2
-
- ldr r0, =MX51_CCM_BASE_ADDR
-
- /* Gate of clocks to the peripherals first */
- ldr r1, =0x3FFFFFFF
- str r1, [r0, #MX5_CCM_CCGR0]
- ldr r1, =0x0
- str r1, [r0, #MX5_CCM_CCGR1]
- str r1, [r0, #MX5_CCM_CCGR2]
- str r1, [r0, #MX5_CCM_CCGR3]
-
- ldr r1, =0x00030000
- str r1, [r0, #MX5_CCM_CCGR4]
- ldr r1, =0x00FFF030
- str r1, [r0, #MX5_CCM_CCGR5]
- ldr r1, =0x00000300
- str r1, [r0, #MX5_CCM_CCGR6]
-
- /* Disable IPU and HSC dividers */
- mov r1, #0x60000
- str r1, [r0, #MX5_CCM_CCDR]
-
-#ifdef IMX51_TO_2
- /* Make sure to switch the DDR away from PLL 1 */
- ldr r1, =0x19239145
- str r1, [r0, #MX5_CCM_CBCDR]
- /* make sure divider effective */
-1: ldr r1, [r0, #MX5_CCM_CDHIPR]
- cmp r1, #0x0
- bne 1b
-#endif
-
- /* Switch ARM to step clock */
- mov r1, #0x4
- str r1, [r0, #MX5_CCM_CCSR]
-
- mov r3, #MX5_PLL_DP_OP_800
- mov r4, #MX5_PLL_DP_MFD_800
- mov r5, #MX5_PLL_DP_MFN_800
- setup_pll MX51_PLL1_BASE_ADDR
-
- mov r3, #MX5_PLL_DP_OP_665
- mov r4, #MX5_PLL_DP_MFD_665
- mov r5, #MX5_PLL_DP_MFN_665
- setup_pll MX51_PLL3_BASE_ADDR
-
- /* Switch peripheral to PLL 3 */
- ldr r1, =0x000010C0
- str r1, [r0, #MX5_CCM_CBCMR]
- ldr r1, =0x13239145
- str r1, [r0, #MX5_CCM_CBCDR]
-
- mov r3, #MX5_PLL_DP_OP_665
- mov r4, #MX5_PLL_DP_MFD_665
- mov r5, #MX5_PLL_DP_MFN_665
- setup_pll MX51_PLL2_BASE_ADDR
-
- /* Switch peripheral to PLL2 */
- ldr r1, =0x19239145
- str r1, [r0, #MX5_CCM_CBCDR]
- ldr r1, =0x000020C0
- str r1, [r0, #MX5_CCM_CBCMR]
-
- mov r3, #MX5_PLL_DP_OP_216
- mov r4, #MX5_PLL_DP_MFD_216
- mov r5, #MX5_PLL_DP_MFN_216
- setup_pll MX51_PLL3_BASE_ADDR
-
- /* Set the platform clock dividers */
- ldr r2, =MX51_ARM_BASE_ADDR
- ldr r1, =0x00000124
- str r1, [r2, #0x14]
-
- /* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */
- ldr r1, =MX51_IROM_BASE_ADDR
- ldr r3, [r1, #ROM_SI_REV_OFFSET]
- cmp r3, #0x10
- movls r1, #0x1
- movhi r1, #0
- str r1, [r0, #MX5_CCM_CACRR]
-
- /* Switch ARM back to PLL 1 */
- mov r1, #0
- str r1, [r0, #MX5_CCM_CCSR]
-
- /* setup the rest */
- /* Use lp_apm (24MHz) source for perclk */
-#ifdef IMX51_TO_2
- ldr r1, =0x000020C2
- str r1, [r0, #MX5_CCM_CBCMR]
- // ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz
- ldr r1, =0x59239100
- str r1, [r0, #MX5_CCM_CBCDR]
-#else
- ldr r1, =0x0000E3C2
- str r1, [r0, #MX5_CCM_CBCMR]
- // emi=ahb, all perclk dividers are 1 since using 24MHz
- // DDR divider=6 to have 665/6=110MHz
- ldr r1, =0x013B9100
- str r1, [r0, #MX5_CCM_CBCDR]
-#endif
-
- /* Restore the default values in the Gate registers */
- ldr r1, =0xFFFFFFFF
- str r1, [r0, #MX5_CCM_CCGR0]
- str r1, [r0, #MX5_CCM_CCGR1]
- str r1, [r0, #MX5_CCM_CCGR2]
- str r1, [r0, #MX5_CCM_CCGR3]
- str r1, [r0, #MX5_CCM_CCGR4]
- str r1, [r0, #MX5_CCM_CCGR5]
- str r1, [r0, #MX5_CCM_CCGR6]
-
- /* Use PLL 2 for UART's, get 66.5MHz from it */
- ldr r1, =0xA5A2A020
- str r1, [r0, #MX5_CCM_CSCMR1]
- ldr r1, =0x00C30321
- str r1, [r0, #MX5_CCM_CSCDR1]
-
- /* make sure divider effective */
- 1: ldr r1, [r0, #MX5_CCM_CDHIPR]
- cmp r1, #0x0
- bne 1b
-
- mov r1, #0x0
- str r1, [r0, #MX5_CCM_CCDR]
-
- writel(0x1, 0x73fa8074)
- ldr r0, =0x73f88000
- ldr r1, [r0]
- orr r1, #0x40
- str r1, [r0]
-
- ldr r0, =0x73f88004
- ldr r1, [r0]
- orr r1, #0x40
- str r1, [r0]
-
- mov pc, r10
-
diff --git a/arch/arm/boards/freescale-mx53-loco/board.c b/arch/arm/boards/freescale-mx53-loco/board.c
index aec2254428..fa3a40937e 100644
--- a/arch/arm/boards/freescale-mx53-loco/board.c
+++ b/arch/arm/boards/freescale-mx53-loco/board.c
@@ -34,7 +34,7 @@
#include <mach/gpio.h>
#include <mach/imx-nand.h>
#include <mach/iim.h>
-#include <mach/imx53.h>
+#include <mach/imx5.h>
#include <asm/armlinux.h>
#include <io.h>
@@ -155,7 +155,7 @@ static int loco_console_init(void)
{
mxc_iomux_v3_setup_multiple_pads(loco_pads, ARRAY_SIZE(loco_pads));
- mx53_init_lowlevel();
+ imx53_init_lowlevel();
imx53_add_uart0();
return 0;
diff --git a/arch/arm/boards/freescale-mx53-loco/env/config b/arch/arm/boards/freescale-mx53-loco/env/config
index 3659a629a9..fd238a6ac2 100644
--- a/arch/arm/boards/freescale-mx53-loco/env/config
+++ b/arch/arm/boards/freescale-mx53-loco/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/freescale-mx53-smd/board.c b/arch/arm/boards/freescale-mx53-smd/board.c
index 325458eb23..e7aa41943b 100644
--- a/arch/arm/boards/freescale-mx53-smd/board.c
+++ b/arch/arm/boards/freescale-mx53-smd/board.c
@@ -34,7 +34,7 @@
#include <mach/gpio.h>
#include <mach/imx-nand.h>
#include <mach/iim.h>
-#include <mach/imx53.h>
+#include <mach/imx5.h>
#include <asm/armlinux.h>
#include <io.h>
@@ -160,7 +160,7 @@ static int smd_console_init(void)
{
mxc_iomux_v3_setup_multiple_pads(smd_pads, ARRAY_SIZE(smd_pads));
- mx53_init_lowlevel();
+ imx53_init_lowlevel();
imx53_add_uart0();
imx53_add_uart1();
diff --git a/arch/arm/boards/freescale-mx53-smd/env/config b/arch/arm/boards/freescale-mx53-smd/env/config
index 3659a629a9..fd238a6ac2 100644
--- a/arch/arm/boards/freescale-mx53-smd/env/config
+++ b/arch/arm/boards/freescale-mx53-smd/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/guf-cupid/env/config b/arch/arm/boards/guf-cupid/env/config
index cd11eb185d..930a97d1e6 100644
--- a/arch/arm/boards/guf-cupid/env/config
+++ b/arch/arm/boards/guf-cupid/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/guf-neso/board.c b/arch/arm/boards/guf-neso/board.c
index e524b70aac..62d82f2ff9 100644
--- a/arch/arm/boards/guf-neso/board.c
+++ b/arch/arm/boards/guf-neso/board.c
@@ -105,6 +105,7 @@ static void neso_fb_enable(int enable)
static struct imx_fb_platform_data neso_fb_data = {
.mode = &imxfb_mode,
+ .num_modes = 1,
.pwmr = 0x00000000, /* doesn't matter */
.lscr1 = 0x00120300, /* doesn't matter */
/* dynamic mode -> using the reset values (as recommended in the datasheet) */
diff --git a/arch/arm/boards/guf-neso/env/config b/arch/arm/boards/guf-neso/env/config
index 162488f8b6..9b675b5920 100644
--- a/arch/arm/boards/guf-neso/env/config
+++ b/arch/arm/boards/guf-neso/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/imx21ads/imx21ads.c b/arch/arm/boards/imx21ads/imx21ads.c
index fc34709630..fde67743cd 100644
--- a/arch/arm/boards/imx21ads/imx21ads.c
+++ b/arch/arm/boards/imx21ads/imx21ads.c
@@ -70,6 +70,7 @@ static struct imx_fb_videomode imx_fb_modedata = {
static struct imx_fb_platform_data imx_fb_data = {
.mode = &imx_fb_modedata,
+ .num_modes = 1,
.cmap_greyscale = 0,
.cmap_inverse = 0,
.cmap_static = 0,
diff --git a/arch/arm/boards/karo-tx25/board.c b/arch/arm/boards/karo-tx25/board.c
index 1eece1dfed..bfccd0c09a 100644
--- a/arch/arm/boards/karo-tx25/board.c
+++ b/arch/arm/boards/karo-tx25/board.c
@@ -239,6 +239,7 @@ static void tx25_fb_enable(int enable)
static struct imx_fb_platform_data tx25_fb_data = {
.mode = &stk5_fb_mode,
+ .num_modes = 1,
.dmacr = 0x80040060,
.enable = tx25_fb_enable,
};
diff --git a/arch/arm/boards/karo-tx25/env/config b/arch/arm/boards/karo-tx25/env/config
index 9113a87bc5..69f2c26c3d 100644
--- a/arch/arm/boards/karo-tx25/env/config
+++ b/arch/arm/boards/karo-tx25/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/karo-tx28/env/config b/arch/arm/boards/karo-tx28/env/config
index fdf57ea662..ed361ebd26 100644
--- a/arch/arm/boards/karo-tx28/env/config
+++ b/arch/arm/boards/karo-tx28/env/config
@@ -24,14 +24,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/mini2440/env/config b/arch/arm/boards/mini2440/env/config
index ff6f1ea5ed..ac8c32a385 100644
--- a/arch/arm/boards/mini2440/env/config
+++ b/arch/arm/boards/mini2440/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-${machine}.${rootfs_type}
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/mini2440/lowlevel_init.S b/arch/arm/boards/mini2440/lowlevel_init.S
index 41f50cbb45..1c8860a631 100644
--- a/arch/arm/boards/mini2440/lowlevel_init.S
+++ b/arch/arm/boards/mini2440/lowlevel_init.S
@@ -3,7 +3,7 @@
*/
#include <config.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
.section ".text_bare_init.board_init_lowlevel","ax"
@@ -17,9 +17,9 @@ board_init_lowlevel:
bl s3c24x0_disable_wd
/* skip everything here if we are already running from SDRAM */
- cmp pc, #S3C24X0_SDRAM_BASE
+ cmp pc, #S3C_SDRAM_BASE
blo 1f
- cmp pc, #S3C24X0_SDRAM_END
+ cmp pc, #S3C_SDRAM_END
bhs 1f
mov pc, r10
diff --git a/arch/arm/boards/mini2440/mini2440.c b/arch/arm/boards/mini2440/mini2440.c
index b4cc0f89e8..97e56db2e6 100644
--- a/arch/arm/boards/mini2440/mini2440.c
+++ b/arch/arm/boards/mini2440/mini2440.c
@@ -38,11 +38,13 @@
#include <asm/armlinux.h>
#include <io.h>
#include <mach/gpio.h>
-#include <mach/s3c24x0-iomap.h>
-#include <mach/s3c24x0-nand.h>
-#include <mach/s3c24xx-generic.h>
-#include <mach/mci.h>
-#include <mach/fb.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c24xx-nand.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-mci.h>
+#include <mach/s3c24xx-fb.h>
+#include <mach/s3c-busctl.h>
+#include <mach/s3c24xx-gpio.h>
static struct s3c24x0_nand_platform_data nand_info = {
.nand_timing = CALC_NFCONF_TIMING(MINI2440_TACLS, MINI2440_TWRPH0,
@@ -266,7 +268,7 @@ static const unsigned pin_usage[] = {
static int mini2440_mem_init(void)
{
- arm_add_mem_device("ram0", CS6_BASE, s3c24x0_get_memory_size());
+ arm_add_mem_device("ram0", S3C_SDRAM_BASE, s3c24xx_get_memory_size());
return 0;
}
@@ -281,24 +283,24 @@ static int mini2440_devices_init(void)
for (i = 0; i < ARRAY_SIZE(pin_usage); i++)
s3c_gpio_mode(pin_usage[i]);
- reg = readl(BWSCON);
+ reg = readl(S3C_BWSCON);
/* CS#4 to access the network controller */
reg &= ~0x000f0000;
reg |= 0x000d0000; /* 16 bit */
- writel(0x1f4c, BANKCON4);
+ writel(0x1f4c, S3C_BANKCON4);
- writel(reg, BWSCON);
+ writel(reg, S3C_BWSCON);
/* release the reset signal to external devices */
- reg = readl(MISCCR);
+ reg = readl(S3C_MISCCR);
reg |= 0x10000;
- writel(reg, MISCCR);
+ writel(reg, S3C_MISCCR);
add_generic_device("s3c24x0_nand", -1, NULL, S3C24X0_NAND_BASE, 0,
IORESOURCE_MEM, &nand_info);
- add_dm9000_device(0, CS4_BASE + 0x300, CS4_BASE + 0x304,
+ add_dm9000_device(0, S3C_CS4_BASE + 0x300, S3C_CS4_BASE + 0x304,
IORESOURCE_MEM_16BIT, &dm9000_data);
#ifdef CONFIG_NAND
/* ----------- add some vital partitions -------- */
@@ -316,7 +318,7 @@ static int mini2440_devices_init(void)
IORESOURCE_MEM, &s3c24x0_fb_data);
add_generic_device("ohci", 0, NULL, S3C2410_USB_HOST_BASE, 0x100,
IORESOURCE_MEM, NULL);
- armlinux_set_bootparams((void*)CS6_BASE + 0x100);
+ armlinux_set_bootparams((void*)S3C_SDRAM_BASE + 0x100);
armlinux_set_architecture(MACH_TYPE_MINI2440);
return 0;
@@ -342,7 +344,7 @@ static int mini2440_console_init(void)
s3c_gpio_mode(GPH2_TXD0);
s3c_gpio_mode(GPH3_RXD0);
- add_generic_device("s3c24x0_serial", -1, NULL, UART1_BASE, UART1_SIZE,
+ add_generic_device("s3c_serial", -1, NULL, S3C_UART1_BASE, S3C_UART1_SIZE,
IORESOURCE_MEM, NULL);
return 0;
}
diff --git a/arch/arm/boards/mmccpu/config.h b/arch/arm/boards/mmccpu/config.h
index c37d5eb370..765b6105d9 100644
--- a/arch/arm/boards/mmccpu/config.h
+++ b/arch/arm/boards/mmccpu/config.h
@@ -41,8 +41,6 @@
AT91_MATRIX_EBI0_CS1A_SDRAMC | AT91_MATRIX_EBI0_CS3A_SMC_SMARTMEDIA)
/* SDRAM */
-/* SDRAMC_MR Mode register */
-#define CONFIG_SYS_SDRC_MR_VAL1 0
/* SDRAMC_TR - Refresh Timer register */
#define CONFIG_SYS_SDRC_TR_VAL1 0x13c
/* SDRAMC_CR - Configuration register*/
@@ -61,23 +59,7 @@
/* Memory Device Register -> SDRAM */
#define CONFIG_SYS_SDRC_MDR_VAL AT91_SDRAMC_MD_SDRAM
-#define CONFIG_SYS_SDRC_MR_VAL2 AT91_SDRAMC_MODE_PRECHARGE
-#define CONFIG_SYS_SDRAM_VAL1 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL3 AT91_SDRAMC_MODE_REFRESH
-#define CONFIG_SYS_SDRAM_VAL2 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL3 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL4 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL5 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL6 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL7 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL8 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL9 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL4 AT91_SDRAMC_MODE_LMR
-#define CONFIG_SYS_SDRAM_VAL10 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL5 AT91_SDRAMC_MODE_NORMAL
-#define CONFIG_SYS_SDRAM_VAL11 0 /* SDRAM_BASE */
#define CONFIG_SYS_SDRC_TR_VAL2 780 /* SDRAM_TR */
-#define CONFIG_SYS_SDRAM_VAL12 0 /* SDRAM_BASE */
/* setup CS0 (NOR Flash) - 16-bit */
#if 1
diff --git a/arch/arm/boards/nhk8815/env/config b/arch/arm/boards/nhk8815/env/config
index 7428c43713..c05ed2704e 100644
--- a/arch/arm/boards/nhk8815/env/config
+++ b/arch/arm/boards/nhk8815/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
# Partition Size Start
diff --git a/arch/arm/boards/panda/env/config b/arch/arm/boards/panda/env/config
index 363208e9b9..29672be9e6 100644
--- a/arch/arm/boards/panda/env/config
+++ b/arch/arm/boards/panda/env/config
@@ -18,14 +18,9 @@ kernel_loc=tftp
# can be either 'net', 'nor', 'nand' or 'initrd'
rootfs_loc=net
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/pcm037/env/config b/arch/arm/boards/pcm037/env/config
index 3748cc4c32..d67d319452 100644
--- a/arch/arm/boards/pcm037/env/config
+++ b/arch/arm/boards/pcm037/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/pcm038/env/config b/arch/arm/boards/pcm038/env/config
index 9e28f5d1f2..eb0f9c1a79 100644
--- a/arch/arm/boards/pcm038/env/config
+++ b/arch/arm/boards/pcm038/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/pcm038/pcm038.c b/arch/arm/boards/pcm038/pcm038.c
index 6b8897e00d..8dd6521383 100644
--- a/arch/arm/boards/pcm038/pcm038.c
+++ b/arch/arm/boards/pcm038/pcm038.c
@@ -104,6 +104,7 @@ static struct imx_fb_videomode imxfb_mode = {
static struct imx_fb_platform_data pcm038_fb_data = {
.mode = &imxfb_mode,
+ .num_modes = 1,
.pwmr = 0x00A903FF,
.lscr1 = 0x00120300,
.dmacr = 0x00020010,
diff --git a/arch/arm/boards/pcm043/env/config b/arch/arm/boards/pcm043/env/config
index e7f94f8dec..2a355e6704 100644
--- a/arch/arm/boards/pcm043/env/config
+++ b/arch/arm/boards/pcm043/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/pcm049/board.c b/arch/arm/boards/pcm049/board.c
index 30e24bc777..826856cb37 100644
--- a/arch/arm/boards/pcm049/board.c
+++ b/arch/arm/boards/pcm049/board.c
@@ -40,6 +40,7 @@
#include <mach/gpmc.h>
#include <mach/gpmc_nand.h>
#include <mach/xload.h>
+#include <i2c/i2c.h>
static struct NS16550_plat serial_plat = {
.clock = 48000000, /* 48MHz (APLL96/2) */
@@ -86,8 +87,18 @@ static void pcm049_network_init(void)
IORESOURCE_MEM, NULL);
}
+static struct i2c_board_info i2c_devices[] = {
+ {
+ I2C_BOARD_INFO("twl6030", 0x48),
+ },
+};
+
static int pcm049_devices_init(void)
{
+ i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
+ add_generic_device("i2c-omap", -1, NULL, 0x48070000, 0x1000,
+ IORESOURCE_MEM, NULL);
+
add_generic_device("omap-hsmmc", -1, NULL, 0x4809C100, SZ_4K,
IORESOURCE_MEM, NULL);
diff --git a/arch/arm/boards/pcm049/env/config b/arch/arm/boards/pcm049/env/config
index 54b2e3dd7d..f3487141e3 100644
--- a/arch/arm/boards/pcm049/env/config
+++ b/arch/arm/boards/pcm049/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-${machine}.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/phycard-a-l1/Makefile b/arch/arm/boards/phycard-a-l1/Makefile
new file mode 100644
index 0000000000..cb0106bb3c
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/Makefile
@@ -0,0 +1,22 @@
+# (C) Copyright 2011 Juergen Kilb <j.kilb@phytec.de>
+#
+# See file CREDITS for list of people who contributed to this
+# project.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+# MA 02111-1307 USA
+
+obj-$(CONFIG_MACH_DO_LOWLEVEL_INIT) += lowlevel.o
+obj-y += pca-a-l1.o
diff --git a/arch/arm/boards/phycard-a-l1/config.h b/arch/arm/boards/phycard-a-l1/config.h
new file mode 100644
index 0000000000..811b7ac44d
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/config.h
@@ -0,0 +1,22 @@
+/*
+ * (C) Copyright 2011 Jurgen 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 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 __CONFIG_H
+#define __CONFIG_H
+
+#endif /* __CONFIG_H */
diff --git a/arch/arm/boards/phycard-a-l1/env/config b/arch/arm/boards/phycard-a-l1/env/config
new file mode 100644
index 0000000000..4a648b92fb
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/env/config
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+machine=pcaal1
+#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' or 'disk'
+kernel_loc=nand
+# can be either 'net', 'nand', 'disk' or 'initrd'
+rootfs_loc=nand
+
+# for flash based rootfs: 'jffs2' or 'ubifs'
+# in case of disk any regular filesystem like 'ext2', 'ext3', 'reiserfs'
+rootfs_type=jffs2
+# 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=zImage-$machine
+kernelimage=uImage-$machine
+#kernelimage=Image-$machine
+#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=ttyO2,115200"
+
+# the following displays are supported
+# pd050vl1 (640 x 480)
+# pd035vl1 (640 x 480)
+# pd104slf (800 x 600)
+# pm070wl4 (800 x 480)
+#
+# omapfb.mode=<display>:<mode>,[,...]
+# omapfb.debug=<y|n>
+# - Enable debug printing. You have to have OMAPFB debug support enabled
+# in kernel config.
+#
+bootargs="$bootargs omapdss.def_disp=pd050vl1"
+#bootargs="$bootargs omapdss.def_disp=pd035vl1"
+#bootargs="$bootargs omapdss.def_disp=pd104slf"
+#bootargs="$bootargs omapdss.def_disp=pm070wl4"
+
+nand_parts="512k(x-loader)ro,1920k(barebox),128k(bareboxenv),4M(kernel),-(root)"
+nand_device=omap2-nand.0
+rootfs_mtdblock_nand=4
+
+# set a fancy prompt (if support is compiled in)
+PS1="\e[1;32mbarebox@\e[1;31m\h:\w\e[0m "
diff --git a/arch/arm/boards/phycard-a-l1/lowlevel.c b/arch/arm/boards/phycard-a-l1/lowlevel.c
new file mode 100644
index 0000000000..bffbb08fe3
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/lowlevel.c
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2011
+ * Phytec Messtechnik GmbH <www.phytec.de>
+ * Juergen Kilb <j.kilb@phytec.de>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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 <asm/barebox-arm.h>
+#include <mach/sdrc.h>
+#include <mach/omap3-silicon.h>
+
+void __naked board_init_lowlevel(void)
+{
+ uint32_t r;
+
+ /* setup a stack */
+ r = OMAP_SRAM_STACK;
+ __asm__ __volatile__("mov sp, %0" : : "r"(r));
+
+ board_init();
+
+ board_init_lowlevel_return();
+}
diff --git a/arch/arm/boards/phycard-a-l1/pca-a-l1.c b/arch/arm/boards/phycard-a-l1/pca-a-l1.c
new file mode 100644
index 0000000000..6fe27b7113
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.c
@@ -0,0 +1,350 @@
+/**
+ * @file
+ * @brief Board Initialization routines for the phyCARD-A-L1
+ *
+ * FileName: arch/arm/boards/phycard-a-l1/pca-a-l1.c
+ *
+ * This board is based on OMAP3530.
+ * More on OMAP3530 (including documentation can be found here):
+ * http://focus.ti.com/docs/prod/folders/print/omap3530.html
+ *
+ * This file provides initialization in two stages:
+ * @li Boot time initialization - just get SDRAM working.
+ * This is run from SRAM - so no case constructs and global vars can be used.
+ * @li Run time initialization - this is for the rest of the initializations
+ * such as flash, uart etc.
+ *
+ * Boot time initialization includes:
+ * @li SDRAM initialization.
+ * @li Pin Muxing relevant for the EVM.
+ *
+ * Run time initialization includes
+ * @li serial @ref serial_ns16550.c driver device definition
+ *
+ * Originally from arch/arm/boards/omap/board-beagle.c
+ */
+
+/*
+ * Copyright (C) 2011 Phytec Messtechnik GmbH - http://www.phytec.de/
+ * Juergen Kilb <j.kilb@phytec.de>
+ *
+ * based on code from Texas Instruments / board-beagle.c
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
+ * Sanjeev Premi <premi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <console.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <nand.h>
+#include <ns16550.h>
+#include <partition.h>
+#include <sizes.h>
+#include <asm/armlinux.h>
+#include <asm/io.h>
+#include <generated/mach-types.h>
+#include <linux/err.h>
+#include <mach/control.h>
+#include <mach/gpmc.h>
+#include <mach/gpmc_nand.h>
+#include <mach/omap_hsmmc.h>
+#include <mach/xload.h>
+#include <partition.h>
+#include <nand.h>
+#include <mach/omap3-mux.h>
+#include <mach/sdrc.h>
+#include <mach/silicon.h>
+#include <mach/sys_info.h>
+#include <mach/syslib.h>
+#include <mach/xload.h>
+
+#include "pca-a-l1.h"
+
+#define SMC911X_BASE 0x2c000000
+
+/*
+ * Boot-time initialization(s)
+ */
+
+/**
+ * @brief Initialize the SDRC module
+ * Initialisation for 1x256MByte but normally
+ * done by x-loader.
+ * @return void
+ */
+static void pcaal1_sdrc_init(void)
+{
+ /* SDRAM software reset */
+ /* No idle ack and RESET enable */
+ writel(0x1A, SDRC_REG(SYSCONFIG));
+ sdelay(100);
+ /* No idle ack and RESET disable */
+ writel(0x18, SDRC_REG(SYSCONFIG));
+
+ /* SDRC Sharing register */
+ /* 32-bit SDRAM on data lane [31:0] - CS0 */
+ /* pin tri-stated = 1 */
+ writel(0x00000100, SDRC_REG(SHARING));
+
+ /* ----- SDRC Registers Configuration --------- */
+ /* SDRC_MCFG0 register */
+ writel(0x03588099, SDRC_REG(MCFG_0));
+
+ /* SDRC_RFR_CTRL0 register */
+ writel(0x0004e201, SDRC_REG(RFR_CTRL_0));
+
+ /* SDRC_ACTIM_CTRLA0 register */
+ writel(0x629DB4C6, SDRC_REG(ACTIM_CTRLA_0));
+
+ /* SDRC_ACTIM_CTRLB0 register */
+ writel(0x00011113, SDRC_REG(ACTIM_CTRLB_0));
+
+ /* Disble Power Down of CKE due to 1 CKE on combo part */
+ writel(0x00000081, SDRC_REG(POWER));
+
+ /* SDRC_MANUAL command register */
+ /* NOP command */
+ writel(0x00000000, SDRC_REG(MANUAL_0));
+ /* Precharge command */
+ writel(0x00000001, SDRC_REG(MANUAL_0));
+ /* Auto-refresh command */
+ writel(0x00000002, SDRC_REG(MANUAL_0));
+ /* Auto-refresh command */
+ writel(0x00000002, SDRC_REG(MANUAL_0));
+
+ /* SDRC MR0 register Burst length=4 */
+ writel(0x00000032, SDRC_REG(MR_0));
+
+ /* SDRC DLLA control register */
+ writel(0x0000000A, SDRC_REG(DLLA_CTRL));
+}
+
+/**
+ * @brief Do the necessary pin muxing required for phyCARD-A-L1.
+ * Some pins in OMAP3 do not have alternate modes.
+ * We don't program these pins.
+ *
+ * See @ref MUX_VAL for description of the muxing mode.
+ *
+ * @return void
+ */
+static void pcaal1_mux_config(void)
+{
+ /*
+ * Serial Interface
+ */
+ MUX_VAL(CP(UART3_CTS_RCTX), (IEN | PTD | EN | M0));
+ MUX_VAL(CP(UART3_RTS_SD), (IDIS | PTD | DIS | M0));
+ MUX_VAL(CP(UART3_RX_IRRX), (IEN | PTD | EN | M0));
+ MUX_VAL(CP(UART3_TX_IRTX), (IDIS | PTD | DIS | M0));
+
+ /* GPMC */
+ MUX_VAL(CP(GPMC_A1), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A2), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A3), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A4), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A5), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A6), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A7), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A8), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A9), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_A10), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D0), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D1), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D2), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D3), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D4), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D5), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D6), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D7), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D8), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D9), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D10), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D11), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D12), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D13), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D14), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_D15), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_NCS0), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(GPMC_NADV_ALE), (IDIS | PTD | DIS | M0));
+ MUX_VAL(CP(GPMC_NOE), (IDIS | PTD | DIS | M0));
+ MUX_VAL(CP(GPMC_NWE), (IDIS | PTD | DIS | M0));
+ MUX_VAL(CP(GPMC_NBE0_CLE), (IDIS | PTD | DIS | M0));
+ MUX_VAL(CP(GPMC_NWP), (IEN | PTD | DIS | M0));
+ MUX_VAL(CP(GPMC_WAIT0), (IEN | PTU | EN | M0));
+
+ /* ETH_PME (GPIO_55) */
+ MUX_VAL(CP(GPMC_NCS4), (IDIS | PTU | EN | M4));
+ /* #CS5 (Ethernet) */
+ MUX_VAL(CP(GPMC_NCS5), (IDIS | PTU | EN | M0));
+ /* ETH_FIFO_SEL (GPIO_57) */
+ MUX_VAL(CP(GPMC_NCS6), (IDIS | PTD | EN | M4));
+ /* ETH_AMDIX_EN (GPIO_58) */
+ MUX_VAL(CP(GPMC_NCS7), (IDIS | PTU | EN | M4));
+ /* ETH_nRST (GPIO_64) */
+ MUX_VAL(CP(GPMC_WAIT2), (IDIS | PTU | EN | M4));
+
+ /* HSMMC1 */
+ MUX_VAL(CP(MMC1_CLK), (IDIS | PTU | EN | M0));
+ MUX_VAL(CP(MMC1_CMD), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(MMC1_DAT0), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(MMC1_DAT1), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(MMC1_DAT2), (IEN | PTU | EN | M0));
+ MUX_VAL(CP(MMC1_DAT3), (IEN | PTU | EN | M0));
+
+ /* USBOTG_nRST (GPIO_63) */
+ MUX_VAL(CP(GPMC_WAIT1), (IDIS | PTU | EN | M4));
+
+ /* USBH_nRST (GPIO_65) */
+ MUX_VAL(CP(GPMC_WAIT3), (IDIS | PTU | EN | M4));
+}
+
+/**
+ * @brief The basic entry point for board initialization.
+ *
+ * This is called as part of machine init (after arch init).
+ * This is again called with stack in SRAM, so not too many
+ * constructs possible here.
+ *
+ * @return void
+ */
+void board_init(void)
+{
+ int in_sdram = running_in_sdram();
+
+ pcaal1_mux_config();
+ /* Dont reconfigure SDRAM while running in SDRAM! */
+ if (!in_sdram)
+ pcaal1_sdrc_init();
+}
+
+/*
+ * Run-time initialization(s)
+ */
+static struct NS16550_plat serial_plat = {
+ .clock = 48000000, /* 48MHz (APLL96/2) */
+ .shift = 2,
+};
+
+/**
+ * @brief Initialize the serial port to be used as console.
+ *
+ * @return result of device registration
+ */
+static int pcaal1_init_console(void)
+{
+ add_ns16550_device(-1, OMAP_UART3_BASE, 1024, IORESOURCE_MEM_8BIT,
+ &serial_plat);
+
+ return 0;
+}
+console_initcall(pcaal1_init_console);
+
+#ifdef CONFIG_DRIVER_NET_SMC911X
+/** GPMC timing for our SMSC9221 device */
+static struct gpmc_config smsc_cfg = {
+ .cfg = {
+ 0x41001000, /*CONF1 */
+ 0x00040500, /*CONF2 */
+ 0x00000000, /*CONF3 */
+ 0x04000500, /*CONF4 */
+ 0x05050505, /*CONF5 */
+ 0x000002c1, /*CONF6 */
+ },
+ .base = SMC911X_BASE,
+ /* GPMC address map as small as possible */
+ .size = GPMC_SIZE_16M,
+};
+
+/*
+ * Routine: setup_net_chip
+ * Description: Setting up the configuration GPMC registers specific to the
+ * Ethernet hardware.
+ */
+static void pcaal1_setup_net_chip(void)
+{
+ gpmc_cs_config(5, &smsc_cfg);
+}
+#endif
+
+static int pcaal1_mem_init(void)
+{
+
+#ifdef CONFIG_GPMC
+ /*
+ * WP is made high and WAIT1 active Low
+ */
+ gpmc_generic_init(0x10);
+#endif
+
+ arm_add_mem_device("ram0", OMAP_SDRC_CS0, get_sdr_cs_size(SDRC_CS0_OSET));
+
+ if ((get_sdr_cs_size(SDRC_CS1_OSET) != 0) && (get_sdr_cs1_base() != OMAP_SDRC_CS0))
+ arm_add_mem_device("ram1", get_sdr_cs1_base(), get_sdr_cs_size(SDRC_CS1_OSET));
+
+ return 0;
+}
+mem_initcall(pcaal1_mem_init);
+
+#ifdef CONFIG_MCI_OMAP_HSMMC
+struct omap_hsmmc_platform_data pcaal1_hsmmc_plat = {
+ .f_max = 26000000,
+};
+#endif
+
+static int pcaal1_init_devices(void)
+{
+#ifdef CONFIG_MCI_OMAP_HSMMC
+ add_generic_device("omap-hsmmc", -1, NULL, OMAP_MMC1_BASE, SZ_4K,
+ IORESOURCE_MEM, &pcaal1_hsmmc_plat);
+#endif
+
+#ifdef CONFIG_DRIVER_NET_SMC911X
+ pcaal1_setup_net_chip();
+ add_generic_device("smc911x", -1, NULL, SMC911X_BASE, SZ_4K,
+ IORESOURCE_MEM, NULL);
+#endif
+
+ armlinux_set_bootparams((void *)0x80000100);
+ armlinux_set_architecture(MACH_TYPE_PCAAL1);
+
+ return 0;
+}
+device_initcall(pcaal1_init_devices);
+
+static int pcaal1_late_init(void)
+{
+ struct device_d *nand;
+
+ gpmc_generic_nand_devices_init(0, 16, OMAP_ECC_SOFT);
+
+ nand = get_device_by_name("nand0");
+
+ devfs_add_partition("nand0", 0x00000, 0x80000, PARTITION_FIXED, "x-loader");
+ dev_add_bb_dev("self_raw", "x_loader0");
+
+ devfs_add_partition("nand0", 0x80000, 0x1e0000, PARTITION_FIXED, "self_raw");
+ dev_add_bb_dev("self_raw", "self0");
+
+ devfs_add_partition("nand0", 0x260000, 0x20000, PARTITION_FIXED, "env_raw");
+ dev_add_bb_dev("env_raw", "env0");
+
+ return 0;
+}
+late_initcall(pcaal1_late_init);
diff --git a/arch/arm/boards/phycard-a-l1/pca-a-l1.dox b/arch/arm/boards/phycard-a-l1/pca-a-l1.dox
new file mode 100644
index 0000000000..d93c57499b
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.dox
@@ -0,0 +1,16 @@
+/** @page phycard-a-l1 Phytec's phyCARD-A-L1 (OMAP35xx)
+
+This phyCARD is based on a Texas Instruments OMAP35xx CPU.
+The card is shipped with:
+
+- 256MiB DDR-RAM
+- 256MiB NAND Flash Memory
+- SMSC9221 ethernet controller
+- USB-host interface
+- USB-OTG interface
+- LVDS camera interface
+- LVDS display interface
+- TPS65023 Power-Managmanet IC
+- 4kB I2C EEPROM
+
+*/
diff --git a/arch/arm/boards/phycard-a-l1/pca-a-l1.h b/arch/arm/boards/phycard-a-l1/pca-a-l1.h
new file mode 100644
index 0000000000..b931d8c52e
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/pca-a-l1.h
@@ -0,0 +1,35 @@
+/**
+ * @file
+ * @brief exported generic APIs which various board files implement
+ *
+ * FileName: arch/arm/boards/phycard-a-l1/board.h
+ *
+ * This file will not contain any board specific implementations.
+ */
+/*
+ * (C) Copyright 2008
+ * Texas Instruments, <www.ti.com>
+ * Raghavendra KH <r-khandenahally@ti.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
+ */
+#ifndef __BOARD_OMAP_H_
+#define __BOARD_OMAP_H_
+
+/** Generic Board initialization called from platform.S */
+void board_init(void);
+
+#endif /* __BOARD_OMAP_H_ */
diff --git a/arch/arm/boards/phycard-a-l1/platform.S b/arch/arm/boards/phycard-a-l1/platform.S
new file mode 100644
index 0000000000..596d3ab4ad
--- /dev/null
+++ b/arch/arm/boards/phycard-a-l1/platform.S
@@ -0,0 +1,65 @@
+/**
+ * @file
+ * @brief Wrapper to call board level initialization routine
+ *
+ * FileName: arch/arm/boards/phycard-a-l1/platform.S
+ *
+ * board_init_lowlevel is defined here. This calls board_init which
+ * is linked to the binary - the board_init only has a SRAM stack.
+ * so it needs to be careful about the usage of global variables
+ * and the likes. Enabled only if CONFIG_MACH_DO_LOWLEVEL_INIT is
+ * defined
+ */
+/*
+ * (C) Copyright 2006-2008
+ * Texas Instruments, <www.ti.com>
+ * Nishanth Menon <x0nishan@ti.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 <config.h>
+#include <mach/silicon.h>
+
+#ifdef CONFIG_MACH_DO_LOWLEVEL_INIT
+/**
+ * @fn void board_init_lowlevel(void)
+ *
+ * @brief This provides a assembly wrapper setting up SRAM before calling
+ * board_init
+ *
+ * @return void
+ */
+.globl board_init_lowlevel
+board_init_lowlevel:
+ /* Setup a temporary stack so that we can call C functions
+ * Yes. this might have been already done by arch code.
+ * No harm in being a bit redundant to avoid future complications
+ */
+ ldr sp, SRAM_STACK
+ str ip, [sp] /* stash old link register */
+ str lr, [sp] /* stash current link register */
+ mov ip, lr /* save link reg across call */
+ /* Do the pin muxes, sdram init etc..board-xxx.c */
+ bl board_init
+ ldr lr, [sp] /* restore current link register */
+ ldr ip, [sp] /* restore save ip */
+ /* back to arch calling code */
+ mov pc, lr
+SRAM_STACK:
+ .word OMAP_SRAM_STACK
+
+#endif /* CONFIG_MACH_DO_LOWLEVEL_INIT */
diff --git a/arch/arm/boards/phycard-i.MX27/env/config b/arch/arm/boards/phycard-i.MX27/env/config
index 0e20b48ffe..5db33d0c64 100644
--- a/arch/arm/boards/phycard-i.MX27/env/config
+++ b/arch/arm/boards/phycard-i.MX27/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/phycard-i.MX27/pca100.c b/arch/arm/boards/phycard-i.MX27/pca100.c
index 41567673a7..1b439516ba 100644
--- a/arch/arm/boards/phycard-i.MX27/pca100.c
+++ b/arch/arm/boards/phycard-i.MX27/pca100.c
@@ -35,6 +35,7 @@
#include <io.h>
#include <mach/imx-nand.h>
#include <mach/imx-pll.h>
+#include <mach/imxfb.h>
#include <gpio.h>
#include <asm/mmu.h>
#include <usb/isp1504.h>
@@ -52,6 +53,82 @@ struct imx_nand_platform_data nand_info = {
.flash_bbt = 1,
};
+static struct imx_fb_videomode imxfb_mode[] = {
+ {
+ .mode = {
+ .name = "Primeview-PD050VL1",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 40000, /* in ps (25MHz) */
+ .hsync_len = 32,
+ .left_margin = 112,
+ .right_margin = 36,
+ .vsync_len = 2,
+ .upper_margin = 33,
+ .lower_margin = 33,
+ },
+ .pcr = 0xF0C88080,
+ .bpp = 16,
+ }, {
+ .mode = {
+ .name = "Primeview-PD035VL1",
+ .refresh = 60,
+ .xres = 640,
+ .yres = 480,
+ .pixclock = 40000, /* in ps (25 MHz) */
+ .hsync_len = 30,
+ .left_margin = 98,
+ .right_margin = 36,
+ .vsync_len = 2,
+ .upper_margin = 15,
+ .lower_margin = 33,
+ },
+ .pcr = 0xF0C88080,
+ .bpp = 16,
+ }, {
+ .mode = {
+ .name = "Primeview-PD104SLF",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 600,
+ .pixclock = 25000, /* in ps (40,0 MHz) */
+ .hsync_len = 40,
+ .left_margin = 174,
+ .right_margin = 174,
+ .vsync_len = 4,
+ .upper_margin = 24,
+ .lower_margin = 23,
+ },
+ .pcr = 0xF0C88080,
+ .bpp = 16,
+ }, {
+ .mode = {
+ .name = "Primeview-PM070WL4",
+ .refresh = 60,
+ .xres = 800,
+ .yres = 480,
+ .pixclock = 31250, /* in ps (32 MHz) */
+ .hsync_len = 40,
+ .left_margin = 174,
+ .right_margin = 174,
+ .vsync_len = 2,
+ .upper_margin = 33,
+ .lower_margin = 23,
+ },
+ .pcr = 0xF0C88080,
+ .bpp = 16,
+ },
+};
+
+static struct imx_fb_platform_data pca100_fb_data = {
+ .mode = imxfb_mode,
+ .num_modes = ARRAY_SIZE(imxfb_mode),
+ .pwmr = 0x00A903FF,
+ .lscr1 = 0x00120300,
+ .dmacr = 0x00040060,
+};
+
#ifdef CONFIG_USB
static void pca100_usb_register(void)
{
@@ -176,6 +253,33 @@ static int pca100_devices_init(void)
PE2_PF_USBOTG_DIR,
PE24_PF_USBOTG_CLK,
PE25_PF_USBOTG_DATA7,
+ /* display */
+ PA5_PF_LSCLK,
+ PA6_PF_LD0,
+ PA7_PF_LD1,
+ PA8_PF_LD2,
+ PA9_PF_LD3,
+ PA10_PF_LD4,
+ PA11_PF_LD5,
+ PA12_PF_LD6,
+ PA13_PF_LD7,
+ PA14_PF_LD8,
+ PA15_PF_LD9,
+ PA16_PF_LD10,
+ PA17_PF_LD11,
+ PA18_PF_LD12,
+ PA19_PF_LD13,
+ PA20_PF_LD14,
+ PA21_PF_LD15,
+ PA22_PF_LD16,
+ PA23_PF_LD17,
+ PA26_PF_PS,
+ PA28_PF_HSYNC,
+ PA29_PF_VSYNC,
+ PA31_PF_OE_ACD,
+ /* external I2C */
+ PD17_PF_I2C_DATA,
+ PD18_PF_I2C_CLK,
};
PCCR0 |= PCCR0_SDHC2_EN;
@@ -189,6 +293,7 @@ static int pca100_devices_init(void)
imx27_add_nand(&nand_info);
imx27_add_fec(&fec_info);
imx27_add_mmc0(NULL);
+ imx27_add_fb(&pca100_fb_data);
PCCR1 |= PCCR1_PERCLK2_EN;
diff --git a/arch/arm/boards/pm9261/config.h b/arch/arm/boards/pm9261/config.h
index 97f8efc0ca..e8822a556c 100644
--- a/arch/arm/boards/pm9261/config.h
+++ b/arch/arm/boards/pm9261/config.h
@@ -40,8 +40,6 @@
(AT91_MATRIX_DBPUC | AT91_MATRIX_CS1A_SDRAMC)
/* SDRAM */
-/* SDRAMC_MR Mode register */
-#define CONFIG_SYS_SDRC_MR_VAL1 AT91_SDRAMC_MODE_NORMAL
/* SDRAMC_TR - Refresh Timer register */
#define CONFIG_SYS_SDRC_TR_VAL1 0x13C
/* SDRAMC_CR - Configuration register*/
@@ -60,23 +58,7 @@
/* Memory Device Register -> SDRAM */
#define CONFIG_SYS_SDRC_MDR_VAL AT91_SDRAMC_MD_SDRAM
-#define CONFIG_SYS_SDRC_MR_VAL2 AT91_SDRAMC_MODE_PRECHARGE
-#define CONFIG_SYS_SDRAM_VAL1 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL3 AT91_SDRAMC_MODE_REFRESH
-#define CONFIG_SYS_SDRAM_VAL2 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL3 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL4 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL5 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL6 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL7 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL8 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL9 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL4 AT91_SDRAMC_MODE_LMR
-#define CONFIG_SYS_SDRAM_VAL10 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL5 AT91_SDRAMC_MODE_NORMAL
-#define CONFIG_SYS_SDRAM_VAL11 0 /* SDRAM_BASE */
#define CONFIG_SYS_SDRC_TR_VAL2 1200 /* SDRAM_TR */
-#define CONFIG_SYS_SDRAM_VAL12 0 /* SDRAM_BASE */
/* setup SMC0, CS0 (NOR Flash) - 16-bit, 15 WS */
#define CONFIG_SYS_SMC0_SETUP0_VAL \
diff --git a/arch/arm/boards/pm9261/env/config b/arch/arm/boards/pm9261/env/config
index 7933379b65..bdc2d38d42 100644
--- a/arch/arm/boards/pm9261/env/config
+++ b/arch/arm/boards/pm9261/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
nor_parts="256k(barebox)ro,64k(bareboxenv),1536k(kernel),-(root)"
diff --git a/arch/arm/boards/pm9261/init.c b/arch/arm/boards/pm9261/init.c
index 2766f473d8..23ed44ec60 100644
--- a/arch/arm/boards/pm9261/init.c
+++ b/arch/arm/boards/pm9261/init.c
@@ -87,7 +87,7 @@ static void pm_add_device_nand(void)
/*
* DM9000 ethernet device
*/
-#if defined(CONFIG_DRIVER_NET_DM9000)
+#if defined(CONFIG_DRIVER_NET_DM9K)
static struct dm9000_platform_data dm9000_data = {
.srom = 1,
};
@@ -124,7 +124,7 @@ static void __init pm_add_device_dm9000(void)
}
#else
static void __init ek_add_device_dm9000(void) {}
-#endif /* CONFIG_DRIVER_NET_DM9000 */
+#endif /* CONFIG_DRIVER_NET_DM9K */
static int pm9261_mem_init(void)
{
diff --git a/arch/arm/boards/pm9263/config.h b/arch/arm/boards/pm9263/config.h
index 5252df288b..d5add0f4c8 100644
--- a/arch/arm/boards/pm9263/config.h
+++ b/arch/arm/boards/pm9263/config.h
@@ -55,8 +55,6 @@
AT91_MATRIX_EBI0_CS1A_SDRAMC)
/* SDRAM */
-/* SDRAMC_MR Mode register */
-#define CONFIG_SYS_SDRC_MR_VAL1 0
/* SDRAMC_TR - Refresh Timer register */
#define CONFIG_SYS_SDRC_TR_VAL1 0x3AA
/* SDRAMC_CR - Configuration register*/
@@ -75,23 +73,7 @@
/* Memory Device Register -> SDRAM */
#define CONFIG_SYS_SDRC_MDR_VAL AT91_SDRAMC_MD_SDRAM
-#define CONFIG_SYS_SDRC_MR_VAL2 AT91_SDRAMC_MODE_PRECHARGE
-#define CONFIG_SYS_SDRAM_VAL1 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL3 AT91_SDRAMC_MODE_REFRESH
-#define CONFIG_SYS_SDRAM_VAL2 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL3 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL4 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL5 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL6 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL7 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL8 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRAM_VAL9 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL4 AT91_SDRAMC_MODE_LMR
-#define CONFIG_SYS_SDRAM_VAL10 0 /* SDRAM_BASE */
-#define CONFIG_SYS_SDRC_MR_VAL5 AT91_SDRAMC_MODE_NORMAL
-#define CONFIG_SYS_SDRAM_VAL11 0 /* SDRAM_BASE */
#define CONFIG_SYS_SDRC_TR_VAL2 1200 /* SDRAM_TR */
-#define CONFIG_SYS_SDRAM_VAL12 0 /* SDRAM_BASE */
/* setup SMC0, CS0 (NOR Flash) - 16-bit, 15 WS */
#define CONFIG_SYS_SMC0_SETUP0_VAL \
diff --git a/arch/arm/boards/pm9g45/env/config b/arch/arm/boards/pm9g45/env/config
index b8ca18dce7..3dea7247f5 100644
--- a/arch/arm/boards/pm9g45/env/config
+++ b/arch/arm/boards/pm9g45/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
diff --git a/arch/arm/boards/scb9328/env/config b/arch/arm/boards/scb9328/env/config
index d0f3f25ee8..e1c5807bad 100644
--- a/arch/arm/boards/scb9328/env/config
+++ b/arch/arm/boards/scb9328/env/config
@@ -23,14 +23,9 @@ rootfs_loc=net
rootfs_type=ubifs
rootfsimage=root-$machine.$rootfs_type
-# 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
if [ -n $user ]; then
diff --git a/arch/arm/boards/usb-a926x/env/bin/init_board b/arch/arm/boards/usb-a926x/env/bin/init_board
new file mode 100644
index 0000000000..0a6baf722b
--- /dev/null
+++ b/arch/arm/boards/usb-a926x/env/bin/init_board
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+button_name="dfu_bp"
+button_wait=5
+
+product_id=0x1234
+vendor_id=0x4321
+
+dfu_config="/dev/nand0.barebox.bb(barebox)sr,/dev/nand0.kernel.bb(kernel)r,/dev/nand0.rootfs.bb(rootfs)r"
+
+if [ $at91_udc0.vbus != 1 ]
+then
+ echo "No USB Device cable plugged, normal boot"
+ exit
+fi
+
+gpio_get_value ${dfu_button}
+if [ $? != 0 ]
+then
+ autoboot_timeout=16
+ echo "enable tty over USB Device, increase the boot delay to ${autoboot_timeout}s"
+ usbserial
+ exit
+fi
+
+echo "${button_name} pressed detected wait ${button_wait}s"
+timeout -s -a ${button_wait}
+
+if [ $at91_udc0.vbus != 1 ]
+then
+ echo "No USB Device cable plugged, normal boot"
+ exit
+fi
+
+gpio_get_value ${dfu_button}
+if [ $? != 0 ]
+then
+ echo "${button_name} released, normal boot"
+ autoboot_timeout=16
+ echo "enable tty over USB Device, increase the boot delay to ${autoboot_timeout}s"
+ usbserial
+ exit
+fi
+
+echo ""
+echo "Start DFU Mode"
+echo ""
+
+dfu ${dfu_config} -P ${product_id} -V ${vendor_id}
diff --git a/arch/arm/boards/usb-a926x/env/config b/arch/arm/boards/usb-a926x/env/config
index d77f6785f5..96a4524844 100644
--- a/arch/arm/boards/usb-a926x/env/config
+++ b/arch/arm/boards/usb-a926x/env/config
@@ -19,14 +19,9 @@ rootfs_loc=net
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
diff --git a/arch/arm/boards/usb-a926x/init.c b/arch/arm/boards/usb-a926x/init.c
index 58460c1d3a..364c1ba958 100644
--- a/arch/arm/boards/usb-a926x/init.c
+++ b/arch/arm/boards/usb-a926x/init.c
@@ -37,6 +37,7 @@
#include <mach/at91sam9_smc.h>
#include <mach/sam9_smc.h>
#include <gpio.h>
+#include <led.h>
#include <mach/io.h>
#include <mach/at91_pmc.h>
#include <mach/at91_rstc.h>
@@ -57,6 +58,7 @@ static struct atmel_nand_data nand_pdata = {
/* .det_pin = ... not connected */
.rdy_pin = AT91_PIN_PC13,
.enable_pin = AT91_PIN_PC14,
+ .on_flash_bbt = 1,
};
static struct sam9_smc_config usb_a9260_nand_smc_config = {
@@ -165,6 +167,38 @@ static struct at91_usbh_data ek_usbh_data = {
.ports = 2,
};
+/*
+ * USB Device port
+ */
+static struct at91_udc_data __initdata ek_udc_data = {
+ .vbus_pin = AT91_PIN_PB11,
+ .pullup_pin = -EINVAL, /* pull-up driven by UDC */
+};
+
+static void __init ek_add_device_udc(void)
+{
+ if (machine_is_usb_a9260() || machine_is_usb_a9g20())
+ ek_udc_data.vbus_pin = AT91_PIN_PC5;
+
+ at91_add_device_udc(&ek_udc_data);
+}
+
+struct gpio_led led = {
+ .gpio = AT91_PIN_PB21,
+ .led = {
+ .name = "user_led",
+ },
+};
+
+static void __init ek_add_led(void)
+{
+ if (machine_is_usb_a9263())
+ led.active_low = 1;
+
+ at91_set_gpio_output(led.gpio, led.active_low);
+ led_gpio_register(&led);
+}
+
static int usb_a9260_mem_init(void)
{
#ifdef CONFIG_AT91_HAVE_SRAM_128M
@@ -177,6 +211,14 @@ static int usb_a9260_mem_init(void)
}
mem_initcall(usb_a9260_mem_init);
+static void __init ek_add_device_button(void)
+{
+ at91_set_GPIO_periph(AT91_PIN_PB10, 1); /* user push button, pull up enabled */
+ at91_set_deglitch(AT91_PIN_PB10, 1);
+
+ export_env_ull("dfu_button", AT91_PIN_PB10);
+}
+
static int usb_a9260_devices_init(void)
{
usb_a9260_add_device_nand();
@@ -184,6 +226,9 @@ static int usb_a9260_devices_init(void)
at91_add_device_eth(&macb_pdata);
usb_a9260_add_device_mci();
at91_add_device_usbh_ohci(&ek_usbh_data);
+ ek_add_device_udc();
+ ek_add_led();
+ ek_add_device_button();
armlinux_set_bootparams((void *)(AT91_CHIPSELECT_1 + 0x100));
usb_a9260_set_board_type();
diff --git a/arch/arm/boards/versatile/env/config b/arch/arm/boards/versatile/env/config
index 9c5ce61330..667dce3747 100644
--- a/arch/arm/boards/versatile/env/config
+++ b/arch/arm/boards/versatile/env/config
@@ -19,14 +19,9 @@ rootfs_loc=initrd
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
nfsroot="$eth0.serverip:/opt/work/busybox/arm9/rootfs_arm"
diff --git a/arch/arm/configs/at91sam9260ek_defconfig b/arch/arm/configs/at91sam9260ek_defconfig
index 2d04206cfa..3367ceec27 100644
--- a/arch/arm/configs/at91sam9260ek_defconfig
+++ b/arch/arm/configs/at91sam9260ek_defconfig
@@ -1,10 +1,14 @@
CONFIG_ARCH_AT91SAM9260=y
+CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_PROMPT="9260-EK:"
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_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/at91sam9260ek/env"
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
@@ -13,18 +17,37 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
CONFIG_CMD_MEMINFO=y
-CONFIG_CMD_CRC=y
CONFIG_CMD_MTEST=y
+CONFIG_CMD_MTEST_ALTERNATIVE=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=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_NETCONSOLE=y
CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_ATMEL=y
+CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_ATMEL=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/arm/configs/at91sam9261ek_defconfig b/arch/arm/configs/at91sam9261ek_defconfig
index a4adee93fb..b60407f058 100644
--- a/arch/arm/configs/at91sam9261ek_defconfig
+++ b/arch/arm/configs/at91sam9261ek_defconfig
@@ -41,7 +41,7 @@ CONFIG_NET_PING=y
CONFIG_NET_TFTP=y
CONFIG_NET_TFTP_PUSH=y
CONFIG_NET_RESOLV=y
-CONFIG_DRIVER_NET_DM9000=y
+CONFIG_DRIVER_NET_DM9K=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
diff --git a/arch/arm/configs/at91sam9g10ek_defconfig b/arch/arm/configs/at91sam9g10ek_defconfig
index 9271b68286..d54e42c38f 100644
--- a/arch/arm/configs/at91sam9g10ek_defconfig
+++ b/arch/arm/configs/at91sam9g10ek_defconfig
@@ -33,7 +33,7 @@ CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
CONFIG_NET_PING=y
CONFIG_NET_TFTP=y
-CONFIG_DRIVER_NET_DM9000=y
+CONFIG_DRIVER_NET_DM9K=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
diff --git a/arch/arm/configs/at91sam9g20ek_defconfig b/arch/arm/configs/at91sam9g20ek_defconfig
index bc7c242969..2492b3096a 100644
--- a/arch/arm/configs/at91sam9g20ek_defconfig
+++ b/arch/arm/configs/at91sam9g20ek_defconfig
@@ -1,14 +1,15 @@
CONFIG_ARCH_AT91SAM9G20=y
-CONFIG_MACH_AT91SAM9G20EK=y
CONFIG_AT91_HAVE_2MMC=y
+CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_PROMPT="9G20-EK:"
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_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/at91sam9260ek/env"
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
@@ -17,23 +18,37 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
CONFIG_CMD_MEMINFO=y
-CONFIG_CMD_CRC=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_MTEST_ALTERNATIVE=y
CONFIG_CMD_FLASH=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=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_NETCONSOLE=y
CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
-CONFIG_I2C=y
-CONFIG_DRIVER_CFI=y
-CONFIG_CFI_BUFFER_WRITE=y
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_ATMEL=y
+CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_ATMEL=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
diff --git a/arch/arm/configs/cupid_defconfig b/arch/arm/configs/cupid_defconfig
index 3f5038f3e6..a311e27d93 100644
--- a/arch/arm/configs/cupid_defconfig
+++ b/arch/arm/configs/cupid_defconfig
@@ -9,6 +9,7 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x87F00000
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -16,7 +17,6 @@ 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="defaultenv arch/arm/boards/guf-cupid/env"
CONFIG_CMD_EDIT=y
@@ -26,13 +26,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
@@ -56,3 +68,8 @@ CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_IMX_IPU=y
CONFIG_MCI=y
CONFIG_MCI_IMX_ESDHC=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/freescale_mx25_3stack_defconfig b/arch/arm/configs/freescale_mx25_3stack_defconfig
index e833636eef..eac343f91a 100644
--- a/arch/arm/configs/freescale_mx25_3stack_defconfig
+++ b/arch/arm/configs/freescale_mx25_3stack_defconfig
@@ -1,13 +1,22 @@
CONFIG_ARCH_IMX=y
CONFIG_ARCH_IMX25=y
CONFIG_MACH_FREESCALE_MX25_3STACK=y
+CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
+CONFIG_MMU=y
CONFIG_TEXT_BASE=0x87F00000
+CONFIG_MALLOC_SIZE=0x01000000
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
+CONFIG_LONGHELP=y
CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
# CONFIG_ERRNO_MESSAGES is not set
CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx25-3-stack/env/"
CONFIG_CMD_EDIT=y
CONFIG_CMD_SLEEP=y
@@ -16,14 +25,27 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
-CONFIG_CMD_CRC=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
@@ -32,3 +54,5 @@ CONFIG_DRIVER_NET_FEC_IMX=y
# CONFIG_SPI is not set
CONFIG_USB=y
CONFIG_USB_EHCI=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/freescale_mx35_3stack_defconfig b/arch/arm/configs/freescale_mx35_3stack_defconfig
index c8d159f442..a60658dc2f 100644
--- a/arch/arm/configs/freescale_mx35_3stack_defconfig
+++ b/arch/arm/configs/freescale_mx35_3stack_defconfig
@@ -3,8 +3,11 @@ CONFIG_ARCH_IMX35=y
CONFIG_MACH_FREESCALE_MX35_3STACK=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
CONFIG_TEXT_BASE=0x87F00000
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
@@ -20,13 +23,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
@@ -43,7 +58,8 @@ CONFIG_CFI_BUFFER_WRITE=y
CONFIG_MTD=y
CONFIG_NAND=y
CONFIG_NAND_IMX=y
-CONFIG_NAND_IMX_BOOT=y
CONFIG_UBI=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_IMX_IPU=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/freescale_mx51_babbage_defconfig b/arch/arm/configs/freescale_mx51_babbage_defconfig
index 472ed62090..dbdb76d4bf 100644
--- a/arch/arm/configs/freescale_mx51_babbage_defconfig
+++ b/arch/arm/configs/freescale_mx51_babbage_defconfig
@@ -8,13 +8,13 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x97f00000
CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
-CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="defaultenv arch/arm/boards/freescale-mx51-pdk/env/"
CONFIG_CMD_EDIT=y
@@ -24,14 +24,27 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -46,3 +59,8 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_IMX_ESDHC=y
CONFIG_I2C_MC13892=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/freescale_mx53_loco_defconfig b/arch/arm/configs/freescale_mx53_loco_defconfig
index cb07f85a47..b4e872d274 100644
--- a/arch/arm/configs/freescale_mx53_loco_defconfig
+++ b/arch/arm/configs/freescale_mx53_loco_defconfig
@@ -8,13 +8,13 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x7ff00000
CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
-CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="defaultenv arch/arm/boards/freescale-mx53-loco/env/"
CONFIG_DEBUG_INFO=y
@@ -25,13 +25,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -49,3 +61,5 @@ CONFIG_MCI_IMX_ESDHC=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/freescale_mx53_smd_defconfig b/arch/arm/configs/freescale_mx53_smd_defconfig
index 1548b0551e..f37df56912 100644
--- a/arch/arm/configs/freescale_mx53_smd_defconfig
+++ b/arch/arm/configs/freescale_mx53_smd_defconfig
@@ -9,6 +9,7 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x7ff00000
CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -25,13 +26,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -49,3 +62,5 @@ CONFIG_MCI_IMX_ESDHC=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/imx28evk_defconfig b/arch/arm/configs/imx28evk_defconfig
new file mode 100644
index 0000000000..1860aef443
--- /dev/null
+++ b/arch/arm/configs/imx28evk_defconfig
@@ -0,0 +1,48 @@
+CONFIG_ARCH_MXS=y
+CONFIG_ARCH_IMX28=y
+CONFIG_MACH_MX28EVK=y
+CONFIG_AEABI=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x43000000
+CONFIG_MALLOC_SIZE=0x800000
+CONFIG_BROKEN=y
+CONFIG_LONGHELP=y
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/freescale-mx28-evk/env"
+CONFIG_DEBUG_INFO=y
+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_ECHO_E=y
+CONFIG_CMD_MTEST=y
+CONFIG_CMD_MTEST_ALTERNATIVE=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_PING=y
+CONFIG_NET_TFTP=y
+CONFIG_NET_RESOLV=y
+CONFIG_DRIVER_NET_FEC_IMX=y
+# CONFIG_SPI is not set
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+CONFIG_MCI_MXS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_LFN=y
diff --git a/arch/arm/configs/mini2440_defconfig b/arch/arm/configs/mini2440_defconfig
index e7708717ee..9b35dd5f65 100644
--- a/arch/arm/configs/mini2440_defconfig
+++ b/arch/arm/configs/mini2440_defconfig
@@ -1,5 +1,6 @@
CONFIG_ARCH_S3C24xx=y
CONFIG_MACH_MINI2440=y
+CONFIG_MINI2440_VIDEO_N35=y
CONFIG_S3C24XX_NAND_BOOT=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
@@ -10,7 +11,6 @@ CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
-CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/mini2440/env"
CONFIG_DEBUG_INFO=y
@@ -33,7 +33,10 @@ CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
CONFIG_NET_TFTP=y
-CONFIG_DRIVER_NET_DM9000=y
+CONFIG_DRIVER_NET_DM9K=y
# CONFIG_SPI is not set
+CONFIG_USB=y
+CONFIG_USB_OHCI=y
+CONFIG_DRIVER_VIDEO_S3C24XX=y
CONFIG_MCI=y
CONFIG_MCI_S3C=y
diff --git a/arch/arm/configs/neso_defconfig b/arch/arm/configs/neso_defconfig
index dcc2f70bf4..45ffe30a70 100644
--- a/arch/arm/configs/neso_defconfig
+++ b/arch/arm/configs/neso_defconfig
@@ -8,6 +8,7 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -24,14 +25,26 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
diff --git a/arch/arm/configs/pca100_defconfig b/arch/arm/configs/pca100_defconfig
index 29e02c5327..2df7e34178 100644
--- a/arch/arm/configs/pca100_defconfig
+++ b/arch/arm/configs/pca100_defconfig
@@ -7,7 +7,8 @@ CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
-CONFIG_MALLOC_SIZE=0x500000
+CONFIG_MALLOC_SIZE=0x01000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -24,14 +25,26 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -53,3 +66,5 @@ CONFIG_UBI=y
CONFIG_USB=y
CONFIG_USB_EHCI=y
CONFIG_USB_ISP1504=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/pcm037_defconfig b/arch/arm/configs/pcm037_defconfig
index ec43317abd..7705bcf79c 100644
--- a/arch/arm/configs/pcm037_defconfig
+++ b/arch/arm/configs/pcm037_defconfig
@@ -7,6 +7,8 @@ CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
+CONFIG_MALLOC_SIZE=0x01000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -14,6 +16,7 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_PARTITION=y
+CONFIG_PARTITION_DISK=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/pcm037/env"
CONFIG_CMD_EDIT=y
@@ -23,13 +26,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -50,3 +65,5 @@ CONFIG_NAND_IMX=y
CONFIG_UBI=y
CONFIG_USB=y
CONFIG_USB_EHCI=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/pcm038_defconfig b/arch/arm/configs/pcm038_defconfig
index 2f4823a83f..b63337ec83 100644
--- a/arch/arm/configs/pcm038_defconfig
+++ b/arch/arm/configs/pcm038_defconfig
@@ -9,6 +9,7 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0xa7f00000
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -16,6 +17,7 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_PARTITION=y
+CONFIG_PARTITION_DISK=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/pcm038/env"
CONFIG_CMD_EDIT=y
@@ -25,16 +27,30 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
@@ -58,3 +74,5 @@ CONFIG_USB_ISP1504=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_IMX=y
CONFIG_IMXFB_DRIVER_VIDEO_IMX_OVERLAY=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/pcm043_defconfig b/arch/arm/configs/pcm043_defconfig
index e47bb35aa7..179d403b97 100644
--- a/arch/arm/configs/pcm043_defconfig
+++ b/arch/arm/configs/pcm043_defconfig
@@ -12,6 +12,7 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x87F00000
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -28,13 +29,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -52,3 +65,5 @@ CONFIG_MTD=y
CONFIG_NAND=y
CONFIG_NAND_IMX=y
CONFIG_UBI=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/pcm049_defconfig b/arch/arm/configs/pcm049_defconfig
index 9b4c341f53..cf1cf4812f 100644
--- a/arch/arm/configs/pcm049_defconfig
+++ b/arch/arm/configs/pcm049_defconfig
@@ -7,16 +7,15 @@ CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x8f000000
CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_PROMPT="barebox> "
CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
-CONFIG_HUSH_GETOPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
# CONFIG_TIMESTAMP is not set
-CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/pcm049/env"
CONFIG_CMD_EDIT=y
@@ -26,14 +25,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_LOADB=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
-# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
@@ -55,3 +65,5 @@ CONFIG_MCI_OMAP_HSMMC=y
CONFIG_FS_FAT=y
CONFIG_FS_FAT_WRITE=y
CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/pcm049_xload_defconfig b/arch/arm/configs/pcm049_xload_defconfig
index 7303c9a5d8..bf309414b0 100644
--- a/arch/arm/configs/pcm049_xload_defconfig
+++ b/arch/arm/configs/pcm049_xload_defconfig
@@ -22,14 +22,14 @@ CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
# CONFIG_SPI is not set
CONFIG_MTD=y
+# CONFIG_MTD_WRITE is not set
+# CONFIG_MTD_OOB_DEVICE is not set
CONFIG_NAND=y
-# CONFIG_NAND_WRITE is not set
# CONFIG_NAND_ECC_SOFT is not set
# CONFIG_NAND_ECC_HW_SYNDROME is not set
# CONFIG_NAND_ECC_HW_NONE is not set
# CONFIG_NAND_INFO is not set
# CONFIG_NAND_BBT is not set
-# CONFIG_NAND_READ_OOB is not set
CONFIG_NAND_OMAP_GPMC=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
diff --git a/arch/arm/configs/phycard_a_l1_defconfig b/arch/arm/configs/phycard_a_l1_defconfig
new file mode 100644
index 0000000000..95dffbbd56
--- /dev/null
+++ b/arch/arm/configs/phycard_a_l1_defconfig
@@ -0,0 +1,183 @@
+CONFIG_GENERIC_LINKER_SCRIPT=y
+CONFIG_ARM=y
+CONFIG_ARM_LINUX=y
+CONFIG_ARCH_OMAP=y
+CONFIG_CPU_32=y
+CONFIG_CPU_V7=y
+CONFIG_CPU_32v7=y
+CONFIG_BOARDINFO="Phytec phyCARD-A-L1"
+CONFIG_ARCH_OMAP3=y
+CONFIG_OMAP_CLOCK_ALL=y
+CONFIG_OMAP_CLOCK_SOURCE_S32K=y
+CONFIG_OMAP3_CLOCK_CONFIG=y
+CONFIG_OMAP3_COPY_CLOCK_SRAM=n
+CONFIG_OMAP_GPMC=y
+CONFIG_MACH_PCAAL1=y
+CONFIG_HAS_OMAP_NAND=y
+CONFIG_AEABI=y
+CONFIG_CMD_ARM_CPUINFO=y
+CONFIG_ARM_EXCEPTIONS=y
+CONFIG_DEFCONFIG_LIST="$ARCH_DEFCONFIG"
+CONFIG_GREGORIAN_CALENDER=y
+CONFIG_HAS_KALLSYMS=y
+CONFIG_HAS_MODULES=y
+CONFIG_CMD_MEMORY=y
+CONFIG_ENV_HANDLING=y
+CONFIG_GENERIC_GPIO=y
+CONFIG_BLOCK=y
+CONFIG_BLOCK_WRITE=y
+CONFIG_LOCALVERSION=""
+CONFIG_LOCALVERSION_AUTO=y
+CONFIG_ENVIRONMENT_VARIABLES=y
+CONFIG_HAVE_CONFIGURABLE_TEXT_BASE=y
+CONFIG_TEXT_BASE=0x85000000
+CONFIG_HAVE_CONFIGURABLE_MEMORY_LAYOUT=y
+CONFIG_MEMORY_LAYOUT_DEFAULT=y
+CONFIG_STACK_SIZE=0x8000
+CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_EXPERIMENTAL=y
+CONFIG_MALLOC_DLMALLOC=y
+CONFIG_MACH_HAS_LOWLEVEL_INIT=y
+CONFIG_MACH_DO_LOWLEVEL_INIT=y
+CONFIG_ARCH_HAS_LOWLEVEL_INIT=y
+CONFIG_PROMPT="phyCARD-A-L1 >"
+CONFIG_BAUDRATE=115200
+CONFIG_LONGHELP=y
+CONFIG_CBSIZE=1024
+CONFIG_MAXARGS=16
+CONFIG_SHELL_HUSH=y
+CONFIG_GLOB=y
+CONFIG_PROMPT_HUSH_PS2="> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_HUSH_GETOPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+CONFIG_PASSWORD=y
+CONFIG_PASSWD_SUM_MD5=y
+CONFIG_DYNAMIC_CRC_TABLE=y
+CONFIG_ERRNO_MESSAGES=y
+CONFIG_TIMESTAMP=y
+CONFIG_CONSOLE_FULL=y
+CONFIG_CONSOLE_ACTIVATE_FIRST=y
+CONFIG_PARTITION=y
+CONFIG_PARTITION_DISK=y
+CONFIG_PARTITION_DISK_DOS=y
+CONFIG_DEFAULT_ENVIRONMENT=y
+CONFIG_DEFAULT_ENVIRONMENT_PATH="defaultenv ./arch/arm/boards/phycard-a-l1/env"
+CONFIG_COMMAND_SUPPORT=y
+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_TRUE=y
+CONFIG_CMD_FALSE=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_LOGIN=y
+CONFIG_CMD_PASSWD=y
+CONFIG_PASSWD_MODE_STAR=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_LS=y
+CONFIG_CMD_RM=y
+CONFIG_CMD_CAT=y
+CONFIG_CMD_MKDIR=y
+CONFIG_CMD_RMDIR=y
+CONFIG_CMD_CP=y
+CONFIG_CMD_PWD=y
+CONFIG_CMD_CD=y
+CONFIG_CMD_MOUNT=y
+CONFIG_CMD_UMOUNT=y
+CONFIG_CMD_NAND=y
+CONFIG_CMD_CLEAR=y
+CONFIG_CMD_ECHO=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_DIGEST=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_SHA256SUM=y
+CONFIG_CMD_SHA224SUM=y
+CONFIG_CMD_MTEST=y
+CONFIG_CMD_MTEST_ALTERNATIVE=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_UBI=y
+CONFIG_CMD_BOOTM=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_IMINFO=y
+CONFIG_CMD_BOOTZ=n
+CONFIG_CMD_BOOTU=n
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_TEST=y
+CONFIG_CMD_VERSION=y
+CONFIG_CMD_HELP=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_DEVINFO=y
+CONFIG_CMD_UNCOMPRESS=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_SERIAL_NS16550=y
+CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
+CONFIG_MIIDEV=y
+CONFIG_DRIVER_NET_SMC911X=y
+CONFIG_DRIVER_NET_SMC911X_ADDRESS_SHIFT=0
+CONFIG_SPI=n
+CONFIG_MTD=y
+CONFIG_NAND=y
+CONFIG_NAND_WRITE=y
+CONFIG_NAND_ECC_SOFT=y
+CONFIG_NAND_ECC_HW=y
+CONFIG_NAND_ECC_HW_SYNDROME=y
+CONFIG_NAND_ECC_HW_NONE=y
+CONFIG_NAND_INFO=y
+CONFIG_NAND_READ_OOB=y
+CONFIG_NAND_BBT=y
+CONFIG_NAND_OOB_DEVICE=y
+CONFIG_NAND_OMAP_GPMC=y
+CONFIG_MTD_NAND_IDS=y
+CONFIG_UBI=y
+CONFIG_DISK=y
+CONFIG_DISK_WRITE=y
+CONFIG_DISK_ATA=y
+CONFIG_DISK_INTF_PLATFORM_IDE=y
+CONFIG_MCI=y
+CONFIG_MCI_INFO=y
+CONFIG_MCI_WRITE=y
+CONFIG_MCI_OMAP_HSMMC=y
+CONFIG_FS_CRAMFS=y
+CONFIG_FS_RAMFS=y
+CONFIG_FS_DEVFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_PARTITION_NEED_MTD=y
+CONFIG_ZLIB=y
+CONFIG_BZLIB=y
+CONFIG_PROCESS_ESCAPE_SEQUENCE=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_FDT=y
+CONFIG_OFTREE=y
+CONFIG_CRC32=y
+CONFIG_CRC16=y
+CONFIG_DIGEST=y
+CONFIG_MD5=y
+CONFIG_SHA1=y
+CONFIG_SHA224=y
+CONFIG_SHA256=y
diff --git a/arch/arm/configs/pm9261_defconfig b/arch/arm/configs/pm9261_defconfig
index 89aa0335e6..39f401f515 100644
--- a/arch/arm/configs/pm9261_defconfig
+++ b/arch/arm/configs/pm9261_defconfig
@@ -42,7 +42,7 @@ CONFIG_NET_PING=y
CONFIG_NET_TFTP=y
CONFIG_NET_TFTP_PUSH=y
CONFIG_NET_RESOLV=y
-CONFIG_DRIVER_NET_DM9000=y
+CONFIG_DRIVER_NET_DM9K=y
# CONFIG_SPI is not set
CONFIG_DRIVER_CFI=y
CONFIG_CFI_BUFFER_WRITE=y
diff --git a/arch/arm/configs/scb9328_defconfig b/arch/arm/configs/scb9328_defconfig
index 49556467c5..1a16999486 100644
--- a/arch/arm/configs/scb9328_defconfig
+++ b/arch/arm/configs/scb9328_defconfig
@@ -20,13 +20,25 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_UNCOMPRESS=y
CONFIG_CMD_LED=y
@@ -39,12 +51,12 @@ CONFIG_NET_TFTP=y
CONFIG_NET_TFTP_PUSH=y
CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
-CONFIG_DRIVER_NET_DM9000=y
+CONFIG_DRIVER_NET_DM9K=y
CONFIG_DRIVER_CFI=y
# CONFIG_DRIVER_CFI_BANK_WIDTH_4 is not set
CONFIG_CFI_BUFFER_WRITE=y
-CONFIG_MTD=y
-CONFIG_UBI=y
CONFIG_LED=y
CONFIG_LED_GPIO=y
CONFIG_LED_TRIGGERS=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/tx25stk5_defconfig b/arch/arm/configs/tx25stk5_defconfig
index 8127ff3597..99057c2862 100644
--- a/arch/arm/configs/tx25stk5_defconfig
+++ b/arch/arm/configs/tx25stk5_defconfig
@@ -4,8 +4,11 @@ CONFIG_MACH_TX25=y
CONFIG_IMX_IIM=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
CONFIG_MALLOC_SIZE=0x1000000
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=y
CONFIG_HUSH_FANCY_PROMPT=y
@@ -21,17 +24,30 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_MTEST_ALTERNATIVE=y
CONFIG_CMD_FLASH=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_PING=y
@@ -43,7 +59,8 @@ CONFIG_DRIVER_NET_FEC_IMX=y
CONFIG_MTD=y
CONFIG_NAND=y
CONFIG_NAND_IMX=y
-CONFIG_NAND_IMX_BOOT=y
CONFIG_UBI=y
CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_IMX=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/tx28stk5_defconfig b/arch/arm/configs/tx28stk5_defconfig
index 384c1c9f3e..b4e3747801 100644
--- a/arch/arm/configs/tx28stk5_defconfig
+++ b/arch/arm/configs/tx28stk5_defconfig
@@ -2,16 +2,18 @@ CONFIG_ARCH_MXS=y
CONFIG_ARCH_IMX28=y
CONFIG_AEABI=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
-CONFIG_MALLOC_SIZE=0x800000
+CONFIG_MALLOC_SIZE=0x01000000
CONFIG_BROKEN=y
+CONFIG_MALLOC_TLSF=y
+CONFIG_KALLSYMS=y
CONFIG_LONGHELP=y
CONFIG_GLOB=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/karo-tx28/env"
CONFIG_DEBUG_INFO=y
@@ -22,18 +24,26 @@ CONFIG_CMD_LOADENV=y
CONFIG_CMD_EXPORT=y
CONFIG_CMD_PRINTENV=y
CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIME=y
CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_IOMEM=y
CONFIG_CMD_MTEST=y
CONFIG_CMD_MTEST_ALTERNATIVE=y
-CONFIG_CMD_BOOTM_ZLIB=y
-CONFIG_CMD_BOOTM_BZLIB=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
+CONFIG_CMD_UIMAGE=y
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
CONFIG_CMD_BMP=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_UNCOMPRESS=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_TFTP=y
@@ -44,4 +54,9 @@ CONFIG_VIDEO=y
CONFIG_DRIVER_VIDEO_STM=y
CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
-CONFIG_MCI_STM378X=y
+CONFIG_MCI_MXS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
+CONFIG_ZLIB=y
+CONFIG_LZO_DECOMPRESS=y
diff --git a/arch/arm/configs/usb_a9260_defconfig b/arch/arm/configs/usb_a9260_defconfig
index adcb6036f5..9073d04194 100644
--- a/arch/arm/configs/usb_a9260_defconfig
+++ b/arch/arm/configs/usb_a9260_defconfig
@@ -1,9 +1,9 @@
CONFIG_ARCH_AT91SAM9260=y
CONFIG_MACH_USB_A9260=y
CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_MMU=y
-CONFIG_KALLSYMS=y
+CONFIG_EXPERIMENTAL=y
CONFIG_PROMPT="USB-9G20:"
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -12,6 +12,8 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env"
@@ -34,14 +36,19 @@ 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_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -54,5 +61,14 @@ CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
diff --git a/arch/arm/configs/usb_a9263_128mib_defconfig b/arch/arm/configs/usb_a9263_128mib_defconfig
index 8d5342e38c..457b25c778 100644
--- a/arch/arm/configs/usb_a9263_128mib_defconfig
+++ b/arch/arm/configs/usb_a9263_128mib_defconfig
@@ -1,10 +1,10 @@
CONFIG_ARCH_AT91SAM9263=y
CONFIG_MACH_USB_A9263=y
CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_AT91_HAVE_SRAM_128M=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_MMU=y
-CONFIG_KALLSYMS=y
+CONFIG_EXPERIMENTAL=y
CONFIG_PROMPT="USB-9G20:"
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -13,6 +13,8 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env"
@@ -35,14 +37,19 @@ 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_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -55,5 +62,14 @@ CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
diff --git a/arch/arm/configs/usb_a9263_defconfig b/arch/arm/configs/usb_a9263_defconfig
index 9f53431b93..6a7ded7c97 100644
--- a/arch/arm/configs/usb_a9263_defconfig
+++ b/arch/arm/configs/usb_a9263_defconfig
@@ -1,9 +1,9 @@
CONFIG_ARCH_AT91SAM9263=y
CONFIG_MACH_USB_A9263=y
CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_MMU=y
-CONFIG_KALLSYMS=y
+CONFIG_EXPERIMENTAL=y
CONFIG_PROMPT="USB-9G20:"
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -12,6 +12,8 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env"
@@ -34,14 +36,19 @@ 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_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -54,5 +61,14 @@ CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
diff --git a/arch/arm/configs/usb_a9g20_128mib_defconfig b/arch/arm/configs/usb_a9g20_128mib_defconfig
index 3c0e6f72a3..3d44f3948d 100644
--- a/arch/arm/configs/usb_a9g20_128mib_defconfig
+++ b/arch/arm/configs/usb_a9g20_128mib_defconfig
@@ -1,10 +1,10 @@
CONFIG_ARCH_AT91SAM9G20=y
CONFIG_MACH_USB_A9G20=y
CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_AT91_HAVE_SRAM_128M=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_MMU=y
-CONFIG_KALLSYMS=y
+CONFIG_EXPERIMENTAL=y
CONFIG_PROMPT="USB-9G20:"
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -13,6 +13,8 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env"
@@ -35,14 +37,19 @@ 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_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -55,5 +62,14 @@ CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
diff --git a/arch/arm/configs/usb_a9g20_defconfig b/arch/arm/configs/usb_a9g20_defconfig
index 2bcb8eb797..7abcd95b25 100644
--- a/arch/arm/configs/usb_a9g20_defconfig
+++ b/arch/arm/configs/usb_a9g20_defconfig
@@ -1,9 +1,9 @@
CONFIG_ARCH_AT91SAM9G20=y
CONFIG_MACH_USB_A9G20=y
CONFIG_AEABI=y
+# CONFIG_CMD_ARM_CPUINFO is not set
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
-CONFIG_MMU=y
-CONFIG_KALLSYMS=y
+CONFIG_EXPERIMENTAL=y
CONFIG_PROMPT="USB-9G20:"
CONFIG_LONGHELP=y
CONFIG_GLOB=y
@@ -12,6 +12,8 @@ CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+# CONFIG_CONSOLE_ACTIVATE_FIRST is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
CONFIG_PARTITION=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/usb-a926x/env"
@@ -34,14 +36,19 @@ 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_BOOTM_INITRD=y
+CONFIG_CMD_UIMAGE=y
+# CONFIG_CMD_BOOTZ is not set
+# CONFIG_CMD_BOOTU is not set
CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
+CONFIG_CMD_OFTREE=y
CONFIG_CMD_TIMEOUT=y
CONFIG_CMD_PARTITION=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_NET=y
CONFIG_NET_DHCP=y
CONFIG_NET_NFS=y
@@ -54,5 +61,14 @@ CONFIG_DRIVER_NET_MACB=y
# CONFIG_SPI is not set
CONFIG_MTD=y
CONFIG_NAND=y
+# CONFIG_NAND_ECC_HW is not set
+# CONFIG_NAND_ECC_HW_SYNDROME is not set
+# CONFIG_NAND_ECC_HW_NONE is not set
CONFIG_NAND_ATMEL=y
CONFIG_UBI=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_DFU=y
+CONFIG_USB_GADGET_SERIAL=y
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_TRIGGERS=y
diff --git a/arch/arm/cpu/cache-armv7.S b/arch/arm/cpu/cache-armv7.S
index 5b8491efcf..f25dcfaa57 100644
--- a/arch/arm/cpu/cache-armv7.S
+++ b/arch/arm/cpu/cache-armv7.S
@@ -84,8 +84,12 @@ loop1:
loop2:
mov r9, r4 @ create working copy of max way size
loop3:
- orr r11, r10, r9, lsl r5 @ factor way and cache number into r11
- orr r11, r11, r7, lsl r2 @ factor index number into r11
+ARM( orr r11, r10, r9, lsl r5 ) @ factor way and cache number into r11
+ARM( orr r11, r11, r7, lsl r2 ) @ factor index number into r11
+THUMB( lsl r6, r9, r5 )
+THUMB( orr r11, r10, r6 ) @ factor way and cache number into r11
+THUMB( lsl r6, r7, r2 )
+THUMB( orr r11, r11, r6 ) @ factor index number into r11
mcr p15, 0, r11, c7, c14, 2 @ clean & invalidate by set/way
subs r9, r9, #1 @ decrement the way
bge loop3
diff --git a/arch/arm/cpu/cpu.c b/arch/arm/cpu/cpu.c
index fc98844f8c..cf31e8bb2e 100644
--- a/arch/arm/cpu/cpu.c
+++ b/arch/arm/cpu/cpu.c
@@ -89,37 +89,3 @@ void arch_shutdown(void)
);
#endif
}
-
-/**
- * @page arm_boot_preparation Linux Preparation on ARM
- *
- * For ARM we never enable data cache so we do not need to disable it again.
- * Linux can be called with instruction cache enabled. As this is the
- * default setting we are running in barebox, there's no special preparation
- * required.
- */
-#ifdef CONFIG_COMMAND
-static int do_icache(struct command *cmdtp, int argc, char *argv[])
-{
- if (argc == 1) {
- printf("icache is %sabled\n", icache_status() ? "en" : "dis");
- return 0;
- }
-
- if (simple_strtoul(argv[1], NULL, 0) > 0)
- icache_enable();
- else
- icache_disable();
-
- return 0;
-}
-
-static const __maybe_unused char cmd_icache_help[] =
-"Usage: icache [0|1]\n";
-
-BAREBOX_CMD_START(icache)
- .cmd = do_icache,
- .usage = "show/change icache status",
- BAREBOX_CMD_HELP(cmd_icache_help)
-BAREBOX_CMD_END
-#endif
diff --git a/arch/arm/cpu/cpuinfo.c b/arch/arm/cpu/cpuinfo.c
index 05971b313b..7be16716fc 100644
--- a/arch/arm/cpu/cpuinfo.c
+++ b/arch/arm/cpu/cpuinfo.c
@@ -47,8 +47,8 @@ static void decode_cache(unsigned long size)
}
static char *crbits[] = {"M", "A", "C", "W", "P", "D", "L", "B", "S", "R",
- "F", "Z", "I", "V", "RR", "L4", "", "", "", "", "", "FI", "U", "XP",
- "VE", "EE", "L2"};
+ "F", "Z", "I", "V", "RR", "L4", "DT", "", "IT", "ST", "", "FI", "U", "XP",
+ "VE", "EE", "L2", "", "TRE", "AFE", "TE"};
static int do_cpuinfo(struct command *cmdtp, int argc, char *argv[])
{
@@ -170,7 +170,7 @@ static int do_cpuinfo(struct command *cmdtp, int argc, char *argv[])
}
printf("Control register: ");
- for (i = 0; i < 27; i++)
+ for (i = 0; i < ARRAY_SIZE(crbits); i++)
if (cr & (1 << i))
printf("%s ", crbits[i]);
printf("\n");
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index 29e12b7a7c..6d9b1e0231 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -111,6 +111,18 @@ static void remap_range(void *_start, size_t size, uint32_t flags)
tlb_invalidate();
}
+void *map_io_sections(unsigned long phys, void *_start, size_t size)
+{
+ unsigned long start = (unsigned long)_start, sec;
+
+ phys >>= 20;
+ for (sec = start; sec < start + size; sec += (1 << 20))
+ ttb[sec >> 20] = (phys++ << 20) | PMD_SECT_DEF_UNCACHED;
+
+ tlb_invalidate();
+ return _start;
+}
+
/*
* remap the memory bank described by mem cachable and
* bufferable
diff --git a/arch/arm/include/asm/armlinux.h b/arch/arm/include/asm/armlinux.h
index ba3a424e26..9ca1e4b6db 100644
--- a/arch/arm/include/asm/armlinux.h
+++ b/arch/arm/include/asm/armlinux.h
@@ -29,6 +29,7 @@ static inline void armlinux_set_serial(u64 serial)
struct image_data;
-void start_linux(void *adr, int swap, struct image_data *data);
+void start_linux(void *adr, int swap, unsigned long initrd_address,
+ unsigned long initrd_size, void *oftree);
#endif /* __ARCH_ARMLINUX_H */
diff --git a/arch/arm/include/asm/io.h b/arch/arm/include/asm/io.h
index ab78be3848..e0630ebb7e 100644
--- a/arch/arm/include/asm/io.h
+++ b/arch/arm/include/asm/io.h
@@ -3,4 +3,11 @@
#include <asm-generic/io.h>
+/*
+ * String version of IO memory access ops:
+ */
+extern void memcpy_fromio(void *, const volatile void __iomem *, size_t);
+extern void memcpy_toio(volatile void __iomem *, const void *, size_t);
+extern void memset_io(volatile void __iomem *, int, size_t);
+
#endif /* __ASM_ARM_IO_H */
diff --git a/arch/arm/include/asm/mmu.h b/arch/arm/include/asm/mmu.h
index 9ca5e2ab3a..f5ae7a823a 100644
--- a/arch/arm/include/asm/mmu.h
+++ b/arch/arm/include/asm/mmu.h
@@ -32,6 +32,7 @@ void dma_flush_range(unsigned long, unsigned long);
void dma_inv_range(unsigned long, unsigned long);
unsigned long virt_to_phys(void *virt);
void *phys_to_virt(unsigned long phys);
+void *map_io_sections(unsigned long physaddr, void *start, size_t size);
#else
static inline void *dma_alloc_coherent(size_t size)
@@ -66,6 +67,11 @@ static inline void dma_inv_range(unsigned long s, unsigned long e)
{
}
+static inline void *map_io_sections(unsigned long phys, void *start, size_t size)
+{
+ return (void *)phys;
+}
+
#endif
#ifdef CONFIG_CACHE_L2X0
diff --git a/arch/arm/lib/Makefile b/arch/arm/lib/Makefile
index 9383ae1472..27a4b88e3b 100644
--- a/arch/arm/lib/Makefile
+++ b/arch/arm/lib/Makefile
@@ -5,6 +5,7 @@ obj-$(CONFIG_CMD_BOOTU) += bootu.o
obj-y += div0.o
obj-y += findbit.o
obj-y += arm.o
+obj-y += io.o
obj-y += io-readsb.o
obj-y += io-readsw-armv4.o
obj-y += io-readsl.o
diff --git a/arch/arm/lib/armlinux.c b/arch/arm/lib/armlinux.c
index bd9b72a8ac..1d210d1a4c 100644
--- a/arch/arm/lib/armlinux.c
+++ b/arch/arm/lib/armlinux.c
@@ -224,7 +224,8 @@ static void setup_end_tag (void)
params->hdr.size = 0;
}
-static void setup_tags(struct image_data *data, int swap)
+static void setup_tags(unsigned long initrd_address,
+ unsigned long initrd_size, int swap)
{
const char *commandline = getenv("bootargs");
@@ -232,8 +233,8 @@ static void setup_tags(struct image_data *data, int swap)
setup_memory_tags();
setup_commandline_tag(commandline, swap);
- if (data && (data->initrd_size > 0))
- setup_initrd_tag(data->initrd_address, data->initrd_size);
+ if (initrd_size)
+ setup_initrd_tag(initrd_address, initrd_size);
setup_revision_tag();
setup_serial_tag();
@@ -249,17 +250,16 @@ void armlinux_set_bootparams(void *params)
armlinux_bootparams = params;
}
-void start_linux(void *adr, int swap, struct image_data *data)
+void start_linux(void *adr, int swap, unsigned long initrd_address,
+ unsigned long initrd_size, void *oftree)
{
void (*kernel)(int zero, int arch, void *params) = adr;
void *params = NULL;
-#ifdef CONFIG_OFTREE
- params = of_get_fixed_tree();
- if (params)
+
+ if (oftree) {
printf("booting Linux kernel with devicetree\n");
-#endif
- if (!params) {
- setup_tags(data, swap);
+ } else {
+ setup_tags(initrd_address, initrd_size, swap);
params = armlinux_bootparams;
}
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 031a2698ec..defc89b7fd 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -11,6 +11,8 @@
#include <malloc.h>
#include <fcntl.h>
#include <errno.h>
+#include <sizes.h>
+#include <libbb.h>
#include <asm/byteorder.h>
#include <asm/setup.h>
@@ -18,32 +20,224 @@
#include <asm/armlinux.h>
#include <asm/system.h>
-static int do_bootm_linux(struct image_data *data)
+static int __do_bootm_linux(struct image_data *data, int swap)
{
- void (*theKernel)(int zero, int arch, void *params);
- image_header_t *os_header = &data->os->header;
+ unsigned long kernel;
+ unsigned long initrd_start = 0, initrd_size = 0;
+ struct memory_bank *bank;
+ unsigned long load_address;
+
+ if (data->os_res) {
+ load_address = data->os_res->start;
+ } else if (data->os_address != UIMAGE_INVALID_ADDRESS) {
+ load_address = data->os_address;
+ } else {
+ bank = list_first_entry(&memory_banks,
+ struct memory_bank, list);
+ load_address = bank->start + SZ_32K;
+ if (bootm_verbose(data))
+ printf("no os load address, defaulting to 0x%08lx\n",
+ load_address);
+ }
+
+ if (!data->os_res && data->os) {
+ data->os_res = uimage_load_to_sdram(data->os,
+ data->os_num, load_address);
+ if (!data->os_res)
+ return -ENOMEM;
+ }
+
+ if (!data->os_res) {
+ data->os_res = file_to_sdram(data->os_file, load_address);
+ if (!data->os_res)
+ return -ENOMEM;
+ }
+
+ kernel = data->os_res->start + data->os_entry;
+
+ if (data->initrd_file && data->initrd_address == UIMAGE_INVALID_ADDRESS) {
+ initrd_start = data->os_res->start + SZ_8M;
- theKernel = (void *)image_get_ep(os_header);
+ if (bootm_verbose(data)) {
+ printf("no initrd load address, defaulting to 0x%08lx\n",
+ initrd_start);
+ }
+ }
- debug("## Transferring control to Linux (at address 0x%p) ...\n",
- theKernel);
+ if (data->initrd) {
+ data->initrd_res = uimage_load_to_sdram(data->initrd,
+ data->initrd_num, initrd_start);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ } else if (data->initrd_file) {
+ data->initrd_res = file_to_sdram(data->initrd_file, initrd_start);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ }
- /* we assume that the kernel is in place */
- printf("\nStarting kernel %s...\n\n", data->initrd ? "with initrd " : "");
+ if (data->initrd_res) {
+ initrd_start = data->initrd_res->start;
+ initrd_size = data->initrd_res->size;
+ }
- start_linux(theKernel, 0, data);
+ if (bootm_verbose(data)) {
+ printf("\nStarting kernel at 0x%08lx", kernel);
+ if (initrd_size)
+ printf(", initrd at 0x%08lx", initrd_start);
+ if (data->oftree)
+ printf(", oftree at 0x%p", data->oftree);
+ printf("...\n");
+ }
- return -1;
+ start_linux((void *)kernel, swap, initrd_start, initrd_size, data->oftree);
+
+ reset_cpu(0);
+
+ return -ERESTARTSYS;
+}
+
+static int do_bootm_linux(struct image_data *data)
+{
+ return __do_bootm_linux(data, 0);
}
-static struct image_handler handler = {
+static struct image_handler uimage_handler = {
+ .name = "ARM Linux uImage",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
-static int armlinux_register_image_handler(void)
+static struct image_handler rawimage_handler = {
+ .name = "ARM raw image",
+ .bootm = do_bootm_linux,
+ .filetype = filetype_unknown,
+};
+
+struct zimage_header {
+ u32 unused[9];
+ u32 magic;
+ u32 start;
+ u32 end;
+};
+
+#define ZIMAGE_MAGIC 0x016F2818
+
+static int do_bootz_linux(struct image_data *data)
+{
+ int fd, ret, swap = 0;
+ struct zimage_header __header, *header;
+ void *zimage;
+ u32 end;
+ unsigned long load_address = data->os_address;
+
+ if (load_address == UIMAGE_INVALID_ADDRESS) {
+ struct memory_bank *bank = list_first_entry(&memory_banks,
+ struct memory_bank, list);
+ data->os_address = bank->start + SZ_8M;
+ load_address = data->os_address;
+ if (bootm_verbose(data))
+ printf("no os load address, defaulting to 0x%08lx\n",
+ load_address);
+ }
+
+ fd = open(data->os_file, O_RDONLY);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+
+ header = &__header;
+ ret = read(fd, header, sizeof(*header));
+ if (ret < sizeof(*header)) {
+ printf("could not read %s\n", data->os_file);
+ goto err_out;
+ }
+
+ switch (header->magic) {
+ case swab32(ZIMAGE_MAGIC):
+ swap = 1;
+ /* fall through */
+ case ZIMAGE_MAGIC:
+ break;
+ default:
+ printf("invalid magic 0x%08x\n", header->magic);
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ end = header->end;
+
+ if (swap)
+ end = swab32(end);
+
+ data->os_res = request_sdram_region("zimage", load_address, end);
+ if (!data->os_res) {
+ ret = -ENOMEM;
+ goto err_out;
+ }
+
+ zimage = (void *)data->os_res->start;
+
+ memcpy(zimage, header, sizeof(*header));
+
+ ret = read_full(fd, zimage + sizeof(*header), end - sizeof(*header));
+ if (ret < 0)
+ goto err_out;
+ if (ret < end - sizeof(*header)) {
+ printf("premature end of image\n");
+ ret = -EIO;
+ goto err_out;
+ }
+
+ if (swap) {
+ void *ptr;
+ for (ptr = zimage; ptr < zimage + end; ptr += 4)
+ *(u32 *)ptr = swab32(*(u32 *)ptr);
+ }
+
+ return __do_bootm_linux(data, swap);
+
+err_out:
+ close(fd);
+
+ return ret;
+}
+
+static struct image_handler zimage_handler = {
+ .name = "ARM zImage",
+ .bootm = do_bootz_linux,
+ .filetype = filetype_arm_zimage,
+};
+
+static int do_bootm_barebox(struct image_data *data)
{
- return register_image_handler(&handler);
+ void (*barebox)(void);
+
+ barebox = read_file(data->os_file, NULL);
+ if (!barebox)
+ return -EINVAL;
+
+ shutdown_barebox();
+
+ barebox();
+
+ reset_cpu(0);
}
+static struct image_handler barebox_handler = {
+ .name = "ARM barebox",
+ .bootm = do_bootm_barebox,
+ .filetype = filetype_arm_barebox,
+};
+
+static int armlinux_register_image_handler(void)
+{
+ register_image_handler(&barebox_handler);
+ register_image_handler(&uimage_handler);
+ register_image_handler(&rawimage_handler);
+ register_image_handler(&zimage_handler);
+
+ return 0;
+}
late_initcall(armlinux_register_image_handler);
diff --git a/arch/arm/lib/bootu.c b/arch/arm/lib/bootu.c
index e97ded0e47..89d793af9a 100644
--- a/arch/arm/lib/bootu.c
+++ b/arch/arm/lib/bootu.c
@@ -3,12 +3,14 @@
#include <fs.h>
#include <fcntl.h>
#include <errno.h>
+#include <of.h>
#include <asm/armlinux.h>
static int do_bootu(struct command *cmdtp, int argc, char *argv[])
{
int fd;
void *kernel = NULL;
+ void *oftree = NULL;
if (argc != 2) {
barebox_cmd_usage(cmdtp);
@@ -22,7 +24,11 @@ static int do_bootu(struct command *cmdtp, int argc, char *argv[])
if (!kernel)
kernel = (void *)simple_strtoul(argv[1], NULL, 0);
- start_linux(kernel, 0, NULL);
+#ifdef CONFIG_OFTREE
+ oftree = of_get_fixed_tree();
+#endif
+
+ start_linux(kernel, 0, 0, 0, oftree);
return 1;
}
diff --git a/arch/arm/lib/bootz.c b/arch/arm/lib/bootz.c
index 956ea82862..40facf6776 100644
--- a/arch/arm/lib/bootz.c
+++ b/arch/arm/lib/bootz.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <command.h>
#include <fs.h>
+#include <of.h>
#include <fcntl.h>
#include <errno.h>
#include <malloc.h>
@@ -25,6 +26,7 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[])
int fd, ret, swap = 0;
struct zimage_header __header, *header;
void *zimage;
+ void *oftree = NULL;
u32 end;
int usemap = 0;
struct memory_bank *bank = list_first_entry(&memory_banks, struct memory_bank, list);
@@ -105,8 +107,11 @@ static int do_bootz(struct command *cmdtp, int argc, char *argv[])
}
printf("loaded zImage from %s with size %d\n", argv[1], end);
+#ifdef CONFIG_OFTREE
+ oftree = of_get_fixed_tree();
+#endif
- start_linux(zimage, swap, NULL);
+ start_linux(zimage, swap, 0, 0, oftree);
return 0;
diff --git a/arch/arm/lib/copy_template.S b/arch/arm/lib/copy_template.S
index 61b6e54e9e..d8eb06328a 100644
--- a/arch/arm/lib/copy_template.S
+++ b/arch/arm/lib/copy_template.S
@@ -57,6 +57,13 @@
*
* Restore registers with the values previously saved with the
* 'preserv' macro. Called upon code termination.
+ *
+ * LDR1W_SHIFT
+ * STR1W_SHIFT
+ *
+ * Correction to be applied to the "ip" register when branching into
+ * the ldr1w or str1w instructions (some of these macros may expand to
+ * than one 32bit instruction in Thumb-2)
*/
@@ -99,9 +106,15 @@
5: ands ip, r2, #28
rsb ip, ip, #32
+#if LDR1W_SHIFT > 0
+ lsl ip, ip, #LDR1W_SHIFT
+#endif
addne pc, pc, ip @ C is always clear here
b 7f
-6: nop
+6:
+ .rept (1 << LDR1W_SHIFT)
+ W(nop)
+ .endr
ldr1w r1, r3, abort=20f
ldr1w r1, r4, abort=20f
ldr1w r1, r5, abort=20f
@@ -110,9 +123,16 @@
ldr1w r1, r8, abort=20f
ldr1w r1, lr, abort=20f
+#if LDR1W_SHIFT < STR1W_SHIFT
+ lsl ip, ip, #STR1W_SHIFT - LDR1W_SHIFT
+#elif LDR1W_SHIFT > STR1W_SHIFT
+ lsr ip, ip, #LDR1W_SHIFT - STR1W_SHIFT
+#endif
add pc, pc, ip
nop
- nop
+ .rept (1 << STR1W_SHIFT)
+ W(nop)
+ .endr
str1w r0, r3, abort=20f
str1w r0, r4, abort=20f
str1w r0, r5, abort=20f
diff --git a/arch/arm/lib/findbit.S b/arch/arm/lib/findbit.S
index 7fa93a5d0a..ef4caff1ad 100644
--- a/arch/arm/lib/findbit.S
+++ b/arch/arm/lib/findbit.S
@@ -14,18 +14,22 @@
* also call with zero size.
* Reworked by rmk.
*/
- .section .text.basic_bit_functions
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+ .text
/*
* Purpose : Find a 'zero' bit
* Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
*/
- .globl _find_first_zero_bit_le;
-_find_first_zero_bit_le:
+ENTRY(_find_first_zero_bit_le)
teq r1, #0
beq 3f
mov r2, #0
-1: ldrb r3, [r0, r2, lsr #3]
+1:
+ ARM( ldrb r3, [r0, r2, lsr #3] )
+ THUMB( lsr r3, r2, #3 )
+ THUMB( ldrb r3, [r0, r3] )
eors r3, r3, #0xff @ invert bits
bne .L_found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
@@ -33,36 +37,40 @@ _find_first_zero_bit_le:
blo 1b
3: mov r0, r1 @ no free bits
mov pc, lr
+ENDPROC(_find_first_zero_bit_le)
/*
* Purpose : Find next 'zero' bit
- * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
- * int offset)
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
- .globl _find_next_zero_bit_le;
-_find_next_zero_bit_le:
+ENTRY(_find_next_zero_bit_le)
teq r1, #0
beq 3b
ands ip, r2, #7
beq 1b @ If new byte, goto old routine
- ldrb r3, [r0, r2, lsr #3]
+ ARM( ldrb r3, [r0, r2, lsr #3] )
+ THUMB( lsr r3, r2, #3 )
+ THUMB( ldrb r3, [r0, r3] )
eor r3, r3, #0xff @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
bne .L_found
orr r2, r2, #7 @ if zero, then no bits here
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
+ENDPROC(_find_next_zero_bit_le)
/*
* Purpose : Find a 'one' bit
- * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit)
+ * Prototype: int find_first_bit(const unsigned long *addr, unsigned int maxbit);
*/
- .globl _find_first_bit_le;
-_find_first_bit_le:
+ENTRY(_find_first_bit_le)
teq r1, #0
beq 3f
mov r2, #0
-1: ldrb r3, [r0, r2, lsr #3]
+1:
+ ARM( ldrb r3, [r0, r2, lsr #3] )
+ THUMB( lsr r3, r2, #3 )
+ THUMB( ldrb r3, [r0, r3] )
movs r3, r3
bne .L_found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
@@ -70,34 +78,37 @@ _find_first_bit_le:
blo 1b
3: mov r0, r1 @ no free bits
mov pc, lr
+ENDPROC(_find_first_bit_le)
/*
* Purpose : Find next 'one' bit
- * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit,
- * int offset)
+ * Prototype: int find_next_zero_bit(void *addr, unsigned int maxbit, int offset)
*/
- .globl _find_next_bit_le;
-_find_next_bit_le:
+ENTRY(_find_next_bit_le)
teq r1, #0
beq 3b
ands ip, r2, #7
beq 1b @ If new byte, goto old routine
- ldrb r3, [r0, r2, lsr #3]
+ ARM( ldrb r3, [r0, r2, lsr #3] )
+ THUMB( lsr r3, r2, #3 )
+ THUMB( ldrb r3, [r0, r3] )
movs r3, r3, lsr ip @ shift off unused bits
bne .L_found
orr r2, r2, #7 @ if zero, then no bits here
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
+ENDPROC(_find_next_bit_le)
#ifdef __ARMEB__
- .globl _find_first_zero_bit_be;
-_find_first_zero_bit_be:
+ENTRY(_find_first_zero_bit_be)
teq r1, #0
beq 3f
mov r2, #0
1: eor r3, r2, #0x18 @ big endian byte ordering
- ldrb r3, [r0, r3, lsr #3]
+ ARM( ldrb r3, [r0, r3, lsr #3] )
+ THUMB( lsr r3, #3 )
+ THUMB( ldrb r3, [r0, r3] )
eors r3, r3, #0xff @ invert bits
bne .L_found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
@@ -105,29 +116,33 @@ _find_first_zero_bit_be:
blo 1b
3: mov r0, r1 @ no free bits
mov pc, lr
+ENDPROC(_find_first_zero_bit_be)
- .globl _find_next_zero_bit_be;
-_find_next_zero_bit_be:
+ENTRY(_find_next_zero_bit_be)
teq r1, #0
beq 3b
ands ip, r2, #7
beq 1b @ If new byte, goto old routine
eor r3, r2, #0x18 @ big endian byte ordering
- ldrb r3, [r0, r3, lsr #3]
+ ARM( ldrb r3, [r0, r3, lsr #3] )
+ THUMB( lsr r3, #3 )
+ THUMB( ldrb r3, [r0, r3] )
eor r3, r3, #0xff @ now looking for a 1 bit
movs r3, r3, lsr ip @ shift off unused bits
bne .L_found
orr r2, r2, #7 @ if zero, then no bits here
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
+ENDPROC(_find_next_zero_bit_be)
- .globl _find_first_bit_be;
-_find_first_bit_be:
+ENTRY(_find_first_bit_be)
teq r1, #0
beq 3f
mov r2, #0
1: eor r3, r2, #0x18 @ big endian byte ordering
- ldrb r3, [r0, r3, lsr #3]
+ ARM( ldrb r3, [r0, r3, lsr #3] )
+ THUMB( lsr r3, #3 )
+ THUMB( ldrb r3, [r0, r3] )
movs r3, r3
bne .L_found @ any now set - found zero bit
add r2, r2, #8 @ next bit pointer
@@ -135,20 +150,23 @@ _find_first_bit_be:
blo 1b
3: mov r0, r1 @ no free bits
mov pc, lr
+ENDPROC(_find_first_bit_be)
- .globl _find_next_bit_be;
-_find_next_bit_be:
+ENTRY(_find_next_bit_be)
teq r1, #0
beq 3b
ands ip, r2, #7
beq 1b @ If new byte, goto old routine
eor r3, r2, #0x18 @ big endian byte ordering
- ldrb r3, [r0, r3, lsr #3]
+ ARM( ldrb r3, [r0, r3, lsr #3] )
+ THUMB( lsr r3, #3 )
+ THUMB( ldrb r3, [r0, r3] )
movs r3, r3, lsr ip @ shift off unused bits
bne .L_found
orr r2, r2, #7 @ if zero, then no bits here
add r2, r2, #1 @ align bit pointer
b 2b @ loop for next bit
+ENDPROC(_find_next_bit_be)
#endif
@@ -157,8 +175,8 @@ _find_next_bit_be:
*/
.L_found:
#if __LINUX_ARM_ARCH__ >= 5
- rsb r1, r3, #0
- and r3, r3, r1
+ rsb r0, r3, #0
+ and r3, r3, r0
clz r3, r3
rsb r3, r3, #31
add r0, r2, r3
@@ -173,5 +191,7 @@ _find_next_bit_be:
addeq r2, r2, #1
mov r0, r2
#endif
+ cmp r1, r0 @ Clamp to maxbit
+ movlo r0, r1
mov pc, lr
diff --git a/arch/arm/lib/io-writesw-armv4.S b/arch/arm/lib/io-writesw-armv4.S
index cd0aa7f2d8..ff4f71b579 100644
--- a/arch/arm/lib/io-writesw-armv4.S
+++ b/arch/arm/lib/io-writesw-armv4.S
@@ -22,8 +22,6 @@
#endif
.endm
-.section .text.writesw
-
.Loutsw_align: movs ip, r1, lsl #31
bne .Loutsw_noalign
@@ -31,7 +29,7 @@
sub r2, r2, #1
strh r3, [r0]
-ENTRY(writesw)
+ENTRY(__raw_writesw)
teq r2, #0
moveq pc, lr
ands r3, r1, #3
@@ -77,7 +75,10 @@ ENTRY(writesw)
#endif
.Loutsw_noalign:
- ldr r3, [r1, -r3]!
+ ARM( ldr r3, [r1, -r3]! )
+ THUMB( rsb r3, r3, #0 )
+ THUMB( ldr r3, [r1, r3] )
+ THUMB( sub r1, r3 )
subcs r2, r2, #1
bcs 2f
subs r2, r2, #2
@@ -96,4 +97,4 @@ ENTRY(writesw)
3: movne ip, r3, lsr #8
strneh ip, [r0]
mov pc, lr
-ENDPROC(writesw)
+ENDPROC(__raw_writesw)
diff --git a/arch/arm/lib/io.c b/arch/arm/lib/io.c
new file mode 100644
index 0000000000..abfd887aac
--- /dev/null
+++ b/arch/arm/lib/io.c
@@ -0,0 +1,50 @@
+#include <module.h>
+#include <linux/types.h>
+#include <io.h>
+
+/*
+ * Copy data from IO memory space to "real" memory space.
+ * This needs to be optimized.
+ */
+void memcpy_fromio(void *to, const volatile void __iomem *from, size_t count)
+{
+ unsigned char *t = to;
+ while (count) {
+ count--;
+ *t = readb(from);
+ t++;
+ from++;
+ }
+}
+
+/*
+ * Copy data from "real" memory space to IO memory space.
+ * This needs to be optimized.
+ */
+void memcpy_toio(volatile void __iomem *to, const void *from, size_t count)
+{
+ const unsigned char *f = from;
+ while (count) {
+ count--;
+ writeb(*f, to);
+ f++;
+ to++;
+ }
+}
+
+/*
+ * "memset" on IO memory space.
+ * This needs to be optimized.
+ */
+void memset_io(volatile void __iomem *dst, int c, size_t count)
+{
+ while (count) {
+ count--;
+ writeb(c, dst);
+ dst++;
+ }
+}
+
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memset_io);
diff --git a/arch/arm/lib/memcpy.S b/arch/arm/lib/memcpy.S
index 513ed64db0..5123691ca9 100644
--- a/arch/arm/lib/memcpy.S
+++ b/arch/arm/lib/memcpy.S
@@ -13,8 +13,11 @@
#include <linux/linkage.h>
#include <asm/assembler.h>
+#define LDR1W_SHIFT 0
+#define STR1W_SHIFT 0
+
.macro ldr1w ptr reg abort
- ldr \reg, [\ptr], #4
+ W(ldr) \reg, [\ptr], #4
.endm
.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
@@ -30,7 +33,7 @@
.endm
.macro str1w ptr reg abort
- str \reg, [\ptr], #4
+ W(str) \reg, [\ptr], #4
.endm
.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
diff --git a/arch/arm/mach-at91/at91rm9200.c b/arch/arm/mach-at91/at91rm9200.c
index b902eab59c..5e3fdeb31c 100644
--- a/arch/arm/mach-at91/at91rm9200.c
+++ b/arch/arm/mach-at91/at91rm9200.c
@@ -216,20 +216,16 @@ static void __init at91rm9200_register_clocks(void)
static struct at91_gpio_bank at91rm9200_gpio[] = {
{
- .id = AT91RM9200_ID_PIOA,
- .offset = AT91_PIOA,
+ .regbase = IOMEM(AT91_BASE_PIOA),
.clock = &pioA_clk,
}, {
- .id = AT91RM9200_ID_PIOB,
- .offset = AT91_PIOB,
+ .regbase = IOMEM(AT91_BASE_PIOB),
.clock = &pioB_clk,
}, {
- .id = AT91RM9200_ID_PIOC,
- .offset = AT91_PIOC,
+ .regbase = IOMEM(AT91_BASE_PIOC),
.clock = &pioC_clk,
}, {
- .id = AT91RM9200_ID_PIOD,
- .offset = AT91_PIOD,
+ .regbase = IOMEM(AT91_BASE_PIOD),
.clock = &pioD_clk,
}
};
diff --git a/arch/arm/mach-at91/at91rm9200_devices.c b/arch/arm/mach-at91/at91rm9200_devices.c
index bd7d3f05e4..68bcffc230 100644
--- a/arch/arm/mach-at91/at91rm9200_devices.c
+++ b/arch/arm/mach-at91/at91rm9200_devices.c
@@ -17,12 +17,15 @@
#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/io.h>
+#include <sizes.h>
#include "generic.h"
void at91_add_device_sdram(u32 size)
{
arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size);
+ add_mem_device("sram0", AT91RM9200_SRAM_BASE, AT91RM9200_SRAM_SIZE,
+ IORESOURCE_MEM_WRITEABLE);
}
/* --------------------------------------------------------------------
@@ -42,6 +45,27 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_DRIVER_AT91
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (data->vbus_pin > 0) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ if (data->pullup_pin > 0)
+ at91_set_gpio_output(data->pullup_pin, 0);
+
+ add_generic_device("at91_udc", -1, NULL, AT91RM9200_BASE_UDP, SZ_16K,
+ IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
/* --------------------------------------------------------------------
* Ethernet
diff --git a/arch/arm/mach-at91/at91rm9200_lowlevel_init.c b/arch/arm/mach-at91/at91rm9200_lowlevel_init.c
index 8d9ae08767..dc54bcfc6f 100644
--- a/arch/arm/mach-at91/at91rm9200_lowlevel_init.c
+++ b/arch/arm/mach-at91/at91rm9200_lowlevel_init.c
@@ -101,11 +101,11 @@ void __naked __bare_init board_init_lowlevel(void)
*/
/* PIOC_ASR: Configure PIOC as peripheral (D16/D31) */
- at91_sys_write(AT91_PIOC + PIO_ASR, CONFIG_SYS_PIOC_ASR_VAL);
+ __raw_writel(CONFIG_SYS_PIOC_ASR_VAL, AT91_BASE_PIOC + PIO_ASR);
/* PIOC_BSR */
- at91_sys_write(AT91_PIOC + PIO_BSR, CONFIG_SYS_PIOC_BSR_VAL);
+ __raw_writel(CONFIG_SYS_PIOC_BSR_VAL, AT91_BASE_PIOC + PIO_BSR);
/* PIOC_PDR */
- at91_sys_write(AT91_PIOC + PIO_PDR, CONFIG_SYS_PIOC_PDR_VAL);
+ __raw_writel(CONFIG_SYS_PIOC_PDR_VAL, AT91_BASE_PIOC + PIO_PDR);
/* EBI_CSA : CS1=SDRAM */
at91_sys_write(AT91_EBI_CSA, CONFIG_SYS_EBI_CSA_VAL);
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c
index 3af5747f8a..cf9e51191c 100644
--- a/arch/arm/mach-at91/at91sam9260.c
+++ b/arch/arm/mach-at91/at91sam9260.c
@@ -223,16 +223,13 @@ static void __init at91sam9260_register_clocks(void)
static struct at91_gpio_bank at91sam9260_gpio[] = {
{
- .id = AT91SAM9260_ID_PIOA,
- .offset = AT91_PIOA,
+ .regbase = IOMEM(AT91_BASE_PIOA),
.clock = &pioA_clk,
}, {
- .id = AT91SAM9260_ID_PIOB,
- .offset = AT91_PIOB,
+ .regbase = IOMEM(AT91_BASE_PIOB),
.clock = &pioB_clk,
}, {
- .id = AT91SAM9260_ID_PIOC,
- .offset = AT91_PIOC,
+ .regbase = IOMEM(AT91_BASE_PIOC),
.clock = &pioC_clk,
}
};
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index be1fdd927e..25a68caedd 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -18,12 +18,24 @@
#include <mach/at91sam9260_matrix.h>
#include <mach/gpio.h>
#include <mach/io.h>
+#include <mach/cpu.h>
#include "generic.h"
void at91_add_device_sdram(u32 size)
{
arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size);
+ if (cpu_is_at91sam9g20()) {
+ add_mem_device("sram0", AT91SAM9G20_SRAM0_BASE,
+ AT91SAM9G20_SRAM0_SIZE, IORESOURCE_MEM_WRITEABLE);
+ add_mem_device("sram1", AT91SAM9G20_SRAM1_BASE,
+ AT91SAM9G20_SRAM1_SIZE, IORESOURCE_MEM_WRITEABLE);
+ } else {
+ add_mem_device("sram0", AT91SAM9260_SRAM0_BASE,
+ AT91SAM9260_SRAM0_SIZE, IORESOURCE_MEM_WRITEABLE);
+ add_mem_device("sram1", AT91SAM9260_SRAM1_BASE,
+ AT91SAM9260_SRAM1_SIZE, IORESOURCE_MEM_WRITEABLE);
+ }
}
#if defined(CONFIG_USB_OHCI)
@@ -39,6 +51,25 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_DRIVER_AT91
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (data->vbus_pin > 0) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ add_generic_device("at91_udc", -1, NULL, AT91SAM9260_BASE_UDP, SZ_16K,
+ IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
#if defined(CONFIG_DRIVER_NET_MACB)
void at91_add_device_eth(struct at91_ether_platform_data *data)
{
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c
index b1e09ef53f..d20b2502cd 100644
--- a/arch/arm/mach-at91/at91sam9261.c
+++ b/arch/arm/mach-at91/at91sam9261.c
@@ -216,16 +216,13 @@ static void at91sam9261_register_clocks(void)
static struct at91_gpio_bank at91sam9261_gpio[] = {
{
- .id = AT91SAM9261_ID_PIOA,
- .offset = AT91_PIOA,
+ .regbase = IOMEM(AT91_BASE_PIOA),
.clock = &pioA_clk,
}, {
- .id = AT91SAM9261_ID_PIOB,
- .offset = AT91_PIOB,
+ .regbase = IOMEM(AT91_BASE_PIOB),
.clock = &pioB_clk,
}, {
- .id = AT91SAM9261_ID_PIOC,
- .offset = AT91_PIOC,
+ .regbase = IOMEM(AT91_BASE_PIOC),
.clock = &pioC_clk,
}
};
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index 3f69b1886c..ff7a938109 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -18,12 +18,19 @@
#include <mach/board.h>
#include <mach/gpio.h>
#include <mach/io.h>
+#include <mach/cpu.h>
#include "generic.h"
void at91_add_device_sdram(u32 size)
{
arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size);
+ if (cpu_is_at91sam9g10())
+ add_mem_device("sram0", AT91SAM9G10_SRAM_BASE,
+ AT91SAM9G10_SRAM_SIZE, IORESOURCE_MEM_WRITEABLE);
+ else
+ add_mem_device("sram0", AT91SAM9261_SRAM_BASE,
+ AT91SAM9261_SRAM_SIZE, IORESOURCE_MEM_WRITEABLE);
}
/* --------------------------------------------------------------------
@@ -43,6 +50,25 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_DRIVER_AT91
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (data->vbus_pin > 0) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ add_generic_device("at91_udc", -1, NULL, AT91SAM9261_BASE_UDP, SZ_16K,
+ IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_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.c b/arch/arm/mach-at91/at91sam9263.c
index eef7ad08ef..b3116d33d3 100644
--- a/arch/arm/mach-at91/at91sam9263.c
+++ b/arch/arm/mach-at91/at91sam9263.c
@@ -230,24 +230,19 @@ static void __init at91sam9263_register_clocks(void)
static struct at91_gpio_bank at91sam9263_gpio[] = {
{
- .id = AT91SAM9263_ID_PIOA,
- .offset = AT91_PIOA,
+ .regbase = IOMEM(AT91_BASE_PIOA),
.clock = &pioA_clk,
}, {
- .id = AT91SAM9263_ID_PIOB,
- .offset = AT91_PIOB,
+ .regbase = IOMEM(AT91_BASE_PIOB),
.clock = &pioB_clk,
}, {
- .id = AT91SAM9263_ID_PIOCDE,
- .offset = AT91_PIOC,
+ .regbase = IOMEM(AT91_BASE_PIOC),
.clock = &pioCDE_clk,
}, {
- .id = AT91SAM9263_ID_PIOCDE,
- .offset = AT91_PIOD,
+ .regbase = IOMEM(AT91_BASE_PIOD),
.clock = &pioCDE_clk,
}, {
- .id = AT91SAM9263_ID_PIOCDE,
- .offset = AT91_PIOE,
+ .regbase = IOMEM(AT91_BASE_PIOE),
.clock = &pioCDE_clk,
}
};
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 994a975cf9..d447e242bb 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -24,6 +24,10 @@
void at91_add_device_sdram(u32 size)
{
arm_add_mem_device("ram0", AT91_CHIPSELECT_1, size);
+ add_mem_device("sram0", AT91SAM9263_SRAM0_BASE,
+ AT91SAM9263_SRAM0_SIZE, IORESOURCE_MEM_WRITEABLE);
+ add_mem_device("sram1", AT91SAM9263_SRAM1_BASE,
+ AT91SAM9263_SRAM1_SIZE, IORESOURCE_MEM_WRITEABLE);
}
/* --------------------------------------------------------------------
@@ -51,6 +55,25 @@ void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data)
void __init at91_add_device_usbh_ohci(struct at91_usbh_data *data) {}
#endif
+/* --------------------------------------------------------------------
+ * USB Device (Gadget)
+ * -------------------------------------------------------------------- */
+
+#ifdef CONFIG_USB_GADGET_DRIVER_AT91
+void __init at91_add_device_udc(struct at91_udc_data *data)
+{
+ if (data->vbus_pin > 0) {
+ at91_set_gpio_input(data->vbus_pin, 0);
+ at91_set_deglitch(data->vbus_pin, 1);
+ }
+
+ add_generic_device("at91_udc", -1, NULL, AT91SAM9263_BASE_UDP, SZ_16K,
+ IORESOURCE_MEM, data);
+}
+#else
+void __init at91_add_device_udc(struct at91_udc_data *data) {}
+#endif
+
#if defined(CONFIG_DRIVER_NET_MACB)
void at91_add_device_eth(struct at91_ether_platform_data *data)
{
diff --git a/arch/arm/mach-at91/at91sam926x_lowlevel_init.S b/arch/arm/mach-at91/at91sam926x_lowlevel_init.S
deleted file mode 100644
index 805b201bf7..0000000000
--- a/arch/arm/mach-at91/at91sam926x_lowlevel_init.S
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Memory Setup stuff - taken from blob memsetup.S
- *
- * Copyright (C) 1999 2000 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl) and
- * Jan-Derk Bakker (J.D.Bakker@its.tudelft.nl)
- *
- * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at)
- * Copyright (C) 2009 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; 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 <config.h>
-#include <mach/hardware.h>
-#include <mach/at91_pmc.h>
-#include <mach/at91_pio.h>
-#include <mach/at91_rstc.h>
-#include <mach/at91_wdt.h>
-#include <mach/at91sam9_matrix.h>
-#include <mach/at91sam9_sdramc.h>
-#include <mach/at91sam9_smc.h>
-
-_TEXT_BASE:
- .word TEXT_BASE
-
-.globl board_init_lowlevel
-.type board_init_lowlevel,function
-board_init_lowlevel:
-
- mov r5, pc /* r5 = POS1 + 4 current */
-POS1:
- ldr r0, =POS1 /* r0 = POS1 compile */
- ldr r2, _TEXT_BASE
- sub r0, r0, r2 /* r0 = POS1-_TEXT_BASE (POS1 relative) */
- sub r5, r5, r0 /* r0 = TEXT_BASE-1 */
- sub r5, r5, #4 /* r1 = text base - current */
-
- /* memory control configuration 1 */
- ldr r0, =SMRDATA
- ldr r2, =SMRDATA1
- ldr r1, _TEXT_BASE
- sub r0, r0, r1
- sub r2, r2, r1
- add r0, r0, r5
- add r2, r2, r5
-0:
- /* the address */
- ldr r1, [r0], #4
- /* the value */
- ldr r3, [r0], #4
- str r3, [r1]
- cmp r2, r0
- bne 0b
-
-/* ----------------------------------------------------------------------------
- * PMC Init Step 1.
- * ----------------------------------------------------------------------------
- * - Check if the PLL is already initialized
- * ----------------------------------------------------------------------------
- */
- ldr r1, =(AT91_BASE_SYS + AT91_PMC_MCKR)
- ldr r0, [r1]
- and r0, r0, #3
- cmp r0, #0
- bne PLL_setup_end
-
-/* ---------------------------------------------------------------------------
- * - Enable the Main Oscillator
- * ---------------------------------------------------------------------------
- */
- ldr r1, =(AT91_BASE_SYS + AT91_CKGR_MOR)
- ldr r2, =(AT91_BASE_SYS + AT91_PMC_SR)
- /* Main oscillator Enable register PMC_MOR: */
- ldr r0, =CONFIG_SYS_MOR_VAL
- str r0, [r1]
-
- /* Reading the PMC Status to detect when the Main Oscillator is enabled */
- mov r4, #AT91_PMC_MOSCS
-MOSCS_Loop:
- ldr r3, [r2]
- and r3, r4, r3
- cmp r3, #AT91_PMC_MOSCS
- bne MOSCS_Loop
-
-/* ----------------------------------------------------------------------------
- * PMC Init Step 2.
- * ----------------------------------------------------------------------------
- * Setup PLLA
- * ----------------------------------------------------------------------------
- */
- ldr r1, =(AT91_BASE_SYS + AT91_CKGR_PLLAR)
- ldr r0, =CONFIG_SYS_PLLAR_VAL
- str r0, [r1]
-
- /* Reading the PMC Status register to detect when the PLLA is locked */
- mov r4, #AT91_PMC_LOCKA
-MOSCS_Loop1:
- ldr r3, [r2]
- and r3, r4, r3
- cmp r3, #AT91_PMC_LOCKA
- bne MOSCS_Loop1
-
-/* ----------------------------------------------------------------------------
- * PMC Init Step 3.
- * ----------------------------------------------------------------------------
- * - Switch on the Main Oscillator
- * ----------------------------------------------------------------------------
- */
- ldr r1, =(AT91_BASE_SYS + AT91_PMC_MCKR)
-
- /* -Master Clock Controller register PMC_MCKR */
- ldr r0, =CONFIG_SYS_MCKR1_VAL
- str r0, [r1]
-
- /* Reading the PMC Status to detect when the Master clock is ready */
- mov r4, #AT91_PMC_MCKRDY
-MCKRDY_Loop:
- ldr r3, [r2]
- and r3, r4, r3
- cmp r3, #AT91_PMC_MCKRDY
- bne MCKRDY_Loop
-
- ldr r0, =CONFIG_SYS_MCKR2_VAL
- str r0, [r1]
-
- /* Reading the PMC Status to detect when the Master clock is ready */
- mov r4, #AT91_PMC_MCKRDY
-MCKRDY_Loop1:
- ldr r3, [r2]
- and r3, r4, r3
- cmp r3, #AT91_PMC_MCKRDY
- bne MCKRDY_Loop1
-
-PLL_setup_end:
-
-/* ----------------------------------------------------------------------------
- * - memory control configuration 2
- * ----------------------------------------------------------------------------
- */
- ldr r0, =(AT91_BASE_SYS + AT91_SDRAMC_TR)
- ldr r1, [r0]
- cmp r1, #0
- bne SDRAM_setup_end
-
- ldr r0, =SMRDATA1
- ldr r2, =SMRDATA2
- ldr r1, _TEXT_BASE
- sub r0, r0, r1
- sub r2, r2, r1
- add r0, r0, r5
- add r2, r2, r5
-
-2:
- /* the address */
- ldr r1, [r0], #4
- /* the value */
- ldr r3, [r0], #4
- str r3, [r1]
- cmp r2, r0
- bne 2b
-
-SDRAM_setup_end:
- /* everything is fine now */
- mov pc, lr
-
- .ltorg
-
-SMRDATA:
- .word (AT91_BASE_SYS + AT91_WDT_MR)
- .word CONFIG_SYS_WDTC_WDMR_VAL
-
- /* configure PIOx as EBI0 D[16-31] */
-#if defined(CONFIG_ARCH_AT91SAM9263)
- .word (AT91_BASE_SYS + AT91_PIOD + PIO_PDR)
- .word CONFIG_SYS_PIOD_PDR_VAL1
- .word (AT91_BASE_SYS + AT91_PIOD + PIO_PUDR)
- .word CONFIG_SYS_PIOD_PPUDR_VAL
- .word (AT91_BASE_SYS + AT91_PIOD + PIO_ASR)
- .word CONFIG_SYS_PIOD_PPUDR_VAL
-#elif defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9261) \
- || defined(CONFIG_ARCH_AT91SAM9G20) || defined(CONFIG_ARCH_AT91SAM9G10)
- .word (AT91_BASE_SYS + AT91_PIOC + PIO_PDR)
- .word CONFIG_SYS_PIOC_PDR_VAL1
- .word (AT91_BASE_SYS + AT91_PIOC + PIO_PUDR)
- .word CONFIG_SYS_PIOC_PPUDR_VAL
-#endif
-
-#if defined(AT91_MATRIX_EBI0CSA)
- .word (AT91_BASE_SYS + AT91_MATRIX_EBI0CSA)
- .word CONFIG_SYS_MATRIX_EBI0CSA_VAL
-#else /* AT91_MATRIX_EBICSA */
- .word (AT91_BASE_SYS + AT91_MATRIX_EBICSA)
- .word CONFIG_SYS_MATRIX_EBICSA_VAL
-#endif
-
- /* flash */
- .word (AT91_BASE_SYS + AT91_SMC_MODE(0))
- .word CONFIG_SYS_SMC0_MODE0_VAL
-
- .word (AT91_BASE_SYS + AT91_SMC_CYCLE(0))
- .word CONFIG_SYS_SMC0_CYCLE0_VAL
-
- .word (AT91_BASE_SYS + AT91_SMC_PULSE(0))
- .word CONFIG_SYS_SMC0_PULSE0_VAL
-
- .word (AT91_BASE_SYS + AT91_SMC_SETUP(0))
- .word CONFIG_SYS_SMC0_SETUP0_VAL
-
-SMRDATA1:
- .word (AT91_BASE_SYS + AT91_SDRAMC_MR)
- .word CONFIG_SYS_SDRC_MR_VAL1
- .word (AT91_BASE_SYS + AT91_SDRAMC_TR)
- .word CONFIG_SYS_SDRC_TR_VAL1
- .word (AT91_BASE_SYS + AT91_SDRAMC_CR)
- .word CONFIG_SYS_SDRC_CR_VAL
- .word (AT91_BASE_SYS + AT91_SDRAMC_MDR)
- .word CONFIG_SYS_SDRC_MDR_VAL
- .word (AT91_BASE_SYS + AT91_SDRAMC_MR)
- .word CONFIG_SYS_SDRC_MR_VAL2
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL1
- .word (AT91_BASE_SYS + AT91_SDRAMC_MR)
- .word CONFIG_SYS_SDRC_MR_VAL3
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL2
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL3
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL4
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL5
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL6
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL7
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL8
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL9
- .word (AT91_BASE_SYS + AT91_SDRAMC_MR)
- .word CONFIG_SYS_SDRC_MR_VAL4
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL10
- .word (AT91_BASE_SYS + AT91_SDRAMC_MR)
- .word CONFIG_SYS_SDRC_MR_VAL5
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL11
- .word (AT91_BASE_SYS + AT91_SDRAMC_TR)
- .word CONFIG_SYS_SDRC_TR_VAL2
- .word AT91_SDRAM_BASE
- .word CONFIG_SYS_SDRAM_VAL12
- /* User reset enable*/
- .word (AT91_BASE_SYS + AT91_RSTC_MR)
- .word CONFIG_SYS_RSTC_RMR_VAL
-#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP
- /* MATRIX_MCFG - REMAP all masters */
- .word (AT91_BASE_SYS + AT91_MATRIX_MCFG0)
- .word 0x1FF
-#endif
-
-SMRDATA2:
- .word 0
diff --git a/arch/arm/mach-at91/at91sam926x_lowlevel_init.c b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c
new file mode 100644
index 0000000000..211074cc3f
--- /dev/null
+++ b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2008 Ronetix Ilko Iliev (www.ronetix.at)
+ * Copyright (C) 2009-2011 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2
+ */
+
+#include <common.h>
+#include <asm/system.h>
+#include <asm/barebox-arm.h>
+#include <mach/hardware.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91_pio.h>
+#include <mach/at91_rstc.h>
+#include <mach/at91_wdt.h>
+#include <mach/at91sam9_matrix.h>
+#include <mach/at91sam9_sdramc.h>
+#include <mach/at91sam9_smc.h>
+#include <mach/io.h>
+#include <init.h>
+
+static void inline access_sdram(void)
+{
+ writel(0x00000000, AT91_SDRAM_BASE);
+}
+
+static void inline pmc_check_mckrdy(void)
+{
+ u32 r;
+
+ do {
+ r = at91_sys_read(AT91_PMC_SR);
+ } while (!(r & AT91_PMC_MCKRDY));
+}
+
+void __naked __bare_init board_init_lowlevel(void)
+{
+ u32 r;
+ int i;
+
+ at91_sys_write(AT91_WDT_MR, CONFIG_SYS_WDTC_WDMR_VAL);
+
+ /* configure PIOx as EBI0 D[16-31] */
+#ifdef CONFIG_ARCH_AT91SAM9263
+ __raw_writel(CONFIG_SYS_PIOD_PDR_VAL1, AT91_BASE_PIOD + PIO_PDR);
+ __raw_writel(CONFIG_SYS_PIOD_PPUDR_VAL, AT91_BASE_PIOD + PIO_PUDR);
+ __raw_writel(CONFIG_SYS_PIOD_PPUDR_VAL, AT91_BASE_PIOD + PIO_ASR);
+#else
+ __raw_writel(CONFIG_SYS_PIOC_PDR_VAL1, AT91_BASE_PIOC + PIO_PDR);
+ __raw_writel(CONFIG_SYS_PIOC_PPUDR_VAL, AT91_BASE_PIOC + PIO_PUDR);
+#endif
+
+#if defined(AT91_MATRIX_EBI0CSA)
+ at91_sys_write(AT91_MATRIX_EBI0CSA, CONFIG_SYS_MATRIX_EBI0CSA_VAL);
+#else /* AT91_MATRIX_EBICSA */
+ at91_sys_write(AT91_MATRIX_EBICSA, CONFIG_SYS_MATRIX_EBICSA_VAL);
+#endif
+
+ /* flash */
+ at91_sys_write(AT91_SMC_MODE(0), CONFIG_SYS_SMC0_MODE0_VAL);
+
+ at91_sys_write(AT91_SMC_CYCLE(0), CONFIG_SYS_SMC0_CYCLE0_VAL);
+
+ at91_sys_write(AT91_SMC_PULSE(0), CONFIG_SYS_SMC0_PULSE0_VAL);
+
+ at91_sys_write(AT91_SMC_SETUP(0), CONFIG_SYS_SMC0_SETUP0_VAL);
+
+ /*
+ * PMC Check if the PLL is already initialized
+ */
+ r = at91_sys_read(AT91_PMC_MCKR);
+ if (r & AT91_PMC_CSS)
+ goto end;
+
+ /*
+ * Enable the Main Oscillator
+ */
+ at91_sys_write(AT91_CKGR_MOR, CONFIG_SYS_MOR_VAL);
+
+ do {
+ r = at91_sys_read(AT91_PMC_SR);
+ } while (!(r & AT91_PMC_MOSCS));
+
+ /*
+ * PLLAR: x MHz for PCK
+ */
+ at91_sys_write(AT91_CKGR_PLLAR, CONFIG_SYS_PLLAR_VAL);
+
+ do {
+ r = at91_sys_read(AT91_PMC_SR);
+ } while (!(r & AT91_PMC_LOCKA));
+
+ /*
+ * PCK/x = MCK Master Clock from SLOW
+ */
+ at91_sys_write(AT91_PMC_MCKR, CONFIG_SYS_MCKR1_VAL);
+
+ pmc_check_mckrdy();
+
+ /*
+ * PCK/x = MCK Master Clock from PLLA
+ */
+ at91_sys_write(AT91_PMC_MCKR, CONFIG_SYS_MCKR2_VAL);
+
+ pmc_check_mckrdy();
+
+ /*
+ * Init SDRAM
+ */
+
+ /*
+ * SDRAMC Check if Refresh Timer Counter is already initialized
+ */
+ r = at91_sys_read(AT91_SDRAMC_TR);
+ if (r)
+ goto end;
+
+ /* SDRAMC_MR : Normal Mode */
+ at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_NORMAL);
+
+ /* SDRAMC_TR - Refresh Timer register */
+ at91_sys_write(AT91_SDRAMC_TR, CONFIG_SYS_SDRC_TR_VAL1);
+
+ /* SDRAMC_CR - Configuration register*/
+ at91_sys_write(AT91_SDRAMC_CR, CONFIG_SYS_SDRC_CR_VAL);
+
+ /* Memory Device Type */
+ at91_sys_write(AT91_SDRAMC_MDR, CONFIG_SYS_SDRC_MDR_VAL);
+
+ /* SDRAMC_MR : Precharge All */
+ at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_PRECHARGE);
+
+ /* access SDRAM */
+ access_sdram();
+
+ /* SDRAMC_MR : refresh */
+ at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_REFRESH);
+
+ /* access SDRAM 8 times */
+ for (i = 0; i < 8; i++)
+ access_sdram();
+
+ /* SDRAMC_MR : Load Mode Register */
+ at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_LMR);
+
+ /* access SDRAM */
+ access_sdram();
+
+ /* SDRAMC_MR : Normal Mode */
+ at91_sys_write(AT91_SDRAMC_MR, AT91_SDRAMC_MODE_NORMAL);
+
+ /* access SDRAM */
+ access_sdram();
+
+ /* SDRAMC_TR : Refresh Timer Counter */
+ at91_sys_write(AT91_SDRAMC_TR, CONFIG_SYS_SDRC_TR_VAL2);
+
+ /* access SDRAM */
+ access_sdram();
+
+ /* User reset enable*/
+ at91_sys_write(AT91_RSTC_MR, CONFIG_SYS_RSTC_RMR_VAL);
+
+#ifdef CONFIG_SYS_MATRIX_MCFG_REMAP
+ /* MATRIX_MCFG - REMAP all masters */
+ at91_sys_write(AT91_MATRIX_MCFG0, 0x1FF);
+#endif
+
+end:
+ board_init_lowlevel_return();
+}
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c
index 6b9fbc5542..a6717f1968 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -242,24 +242,19 @@ static void __init at91sam9g45_register_clocks(void)
static struct at91_gpio_bank at91sam9g45_gpio[] = {
{
- .id = AT91SAM9G45_ID_PIOA,
- .offset = AT91_PIOA,
+ .regbase = IOMEM(AT91_BASE_PIOA),
.clock = &pioA_clk,
}, {
- .id = AT91SAM9G45_ID_PIOB,
- .offset = AT91_PIOB,
+ .regbase = IOMEM(AT91_BASE_PIOB),
.clock = &pioB_clk,
}, {
- .id = AT91SAM9G45_ID_PIOC,
- .offset = AT91_PIOC,
+ .regbase = IOMEM(AT91_BASE_PIOC),
.clock = &pioC_clk,
}, {
- .id = AT91SAM9G45_ID_PIODE,
- .offset = AT91_PIOD,
+ .regbase = IOMEM(AT91_BASE_PIOD),
.clock = &pioDE_clk,
}, {
- .id = AT91SAM9G45_ID_PIODE,
- .offset = AT91_PIOE,
+ .regbase = IOMEM(AT91_BASE_PIOE),
.clock = &pioDE_clk,
}
};
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 1d47dcfa10..5f1a45a16d 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -24,6 +24,8 @@
void at91_add_device_sdram(u32 size)
{
arm_add_mem_device("ram0", AT91_CHIPSELECT_6, size);
+ add_mem_device("sram0", AT91SAM9G45_SRAM_BASE,
+ AT91SAM9G45_SRAM_SIZE, IORESOURCE_MEM_WRITEABLE);
}
/* --------------------------------------------------------------------
diff --git a/arch/arm/mach-at91/gpio.c b/arch/arm/mach-at91/gpio.c
index c34df0520e..06da5af2f8 100644
--- a/arch/arm/mach-at91/gpio.c
+++ b/arch/arm/mach-at91/gpio.c
@@ -235,23 +235,14 @@ EXPORT_SYMBOL(gpio_direction_output);
int at91_gpio_init(struct at91_gpio_bank *data, int nr_banks)
{
- unsigned i;
- struct at91_gpio_bank *last;
+ unsigned i;
gpio = data;
gpio_banks = nr_banks;
- for (i = 0, last = NULL; i < nr_banks; i++, last = data, data++) {
- data->chipbase = PIN_BASE + i * 32;
- data->regbase = data->offset +
- (void __iomem *)AT91_BASE_SYS;
-
+ for (i = 0; i < nr_banks; i++, data++) {
/* enable PIO controller's clock */
clk_enable(data->clock);
-
- /* AT91SAM9263_ID_PIOCDE groups PIOC, PIOD, PIOE */
- if (last && last->id == data->id)
- last->next = data;
}
return 0;
diff --git a/arch/arm/mach-at91/include/mach/at91rm9200.h b/arch/arm/mach-at91/include/mach/at91rm9200.h
index 985977fd3f..39b1e15c44 100644
--- a/arch/arm/mach-at91/include/mach/at91rm9200.h
+++ b/arch/arm/mach-at91/include/mach/at91rm9200.h
@@ -84,15 +84,16 @@
*/
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS) /* Advanced Interrupt Controller */
#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS) /* Debug Unit */
-#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS) /* PIO Controller A */
-#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS) /* PIO Controller B */
-#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS) /* PIO Controller C */
-#define AT91_PIOD (0xfffffa00 - AT91_BASE_SYS) /* PIO Controller D */
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS) /* Power Management Controller */
#define AT91_ST (0xfffffd00 - AT91_BASE_SYS) /* System Timer */
#define AT91_RTC (0xfffffe00 - AT91_BASE_SYS) /* Real-Time Clock */
#define AT91_MC (0xffffff00 - AT91_BASE_SYS) /* Memory Controllers */
+#define AT91_BASE_PIOA 0xfffff400 /* PIO Controller A */
+#define AT91_BASE_PIOB 0xfffff600 /* PIO Controller B */
+#define AT91_BASE_PIOC 0xfffff800 /* PIO Controller C */
+#define AT91_BASE_PIOD 0xfffffa00 /* PIO Controller D */
+
#define AT91_USART0 AT91RM9200_BASE_US0
#define AT91_USART1 AT91RM9200_BASE_US1
#define AT91_USART2 AT91RM9200_BASE_US2
diff --git a/arch/arm/mach-at91/include/mach/at91sam9260.h b/arch/arm/mach-at91/include/mach/at91sam9260.h
index 7d166b7a89..72dc93199d 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9260.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9260.h
@@ -87,9 +87,6 @@
#define AT91_CCFG (0xffffef10 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
@@ -98,6 +95,10 @@
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_BASE_PIOA 0xfffff400
+#define AT91_BASE_PIOB 0xfffff600
+#define AT91_BASE_PIOC 0xfffff800
+
#define AT91_USART0 AT91SAM9260_BASE_US0
#define AT91_USART1 AT91SAM9260_BASE_US1
#define AT91_USART2 AT91SAM9260_BASE_US2
@@ -126,6 +127,16 @@
#define AT91SAM9XE_FLASH_BASE 0x00200000 /* Internal FLASH base address */
#define AT91SAM9XE_SRAM_BASE 0x00300000 /* Internal SRAM base address */
+#define AT91SAM9G20_ROM_BASE 0x00100000 /* Internal ROM base address */
+#define AT91SAM9G20_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */
+
+#define AT91SAM9G20_SRAM0_BASE 0x00200000 /* Internal SRAM 0 base address */
+#define AT91SAM9G20_SRAM0_SIZE SZ_16K /* Internal SRAM 0 size (16Kb) */
+#define AT91SAM9G20_SRAM1_BASE 0x00300000 /* Internal SRAM 1 base address */
+#define AT91SAM9G20_SRAM1_SIZE SZ_16K /* Internal SRAM 1 size (16Kb) */
+
+#define AT91SAM9G20_UHP_BASE 0x00500000 /* USB Host controller */
+
/*
* Cpu Name
*/
diff --git a/arch/arm/mach-at91/include/mach/at91sam9261.h b/arch/arm/mach-at91/include/mach/at91sam9261.h
index b303e07bbc..3be80870cf 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9261.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9261.h
@@ -73,9 +73,6 @@
#define AT91_MATRIX (0xffffee00 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
#define AT91_DBGU (0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOA (0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOB (0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOC (0xfffff800 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
@@ -84,6 +81,10 @@
#define AT91_WDT (0xfffffd40 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd50 - AT91_BASE_SYS)
+#define AT91_BASE_PIOA 0xfffff400
+#define AT91_BASE_PIOB 0xfffff600
+#define AT91_BASE_PIOC 0xfffff800
+
#define AT91_USART0 AT91SAM9261_BASE_US0
#define AT91_USART1 AT91SAM9261_BASE_US1
#define AT91_USART2 AT91SAM9261_BASE_US2
@@ -95,6 +96,9 @@
#define AT91SAM9261_SRAM_BASE 0x00300000 /* Internal SRAM base address */
#define AT91SAM9261_SRAM_SIZE 0x00028000 /* Internal SRAM size (160Kb) */
+#define AT91SAM9G10_SRAM_BASE AT91SAM9261_SRAM_BASE /* Internal SRAM base address */
+#define AT91SAM9G10_SRAM_SIZE 0x00004000 /* Internal SRAM size (16Kb) */
+
#define AT91SAM9261_ROM_BASE 0x00400000 /* Internal ROM base address */
#define AT91SAM9261_ROM_SIZE SZ_32K /* Internal ROM size (32Kb) */
diff --git a/arch/arm/mach-at91/include/mach/at91sam9263.h b/arch/arm/mach-at91/include/mach/at91sam9263.h
index 7bab1a4b10..64f4fccefe 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9263.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9263.h
@@ -87,11 +87,6 @@
#define AT91_CCFG (0xffffed10 - AT91_BASE_SYS)
#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
-#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS)
-#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
@@ -101,6 +96,12 @@
#define AT91_RTT1 (0xfffffd50 - AT91_BASE_SYS)
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
+#define AT91_BASE_PIOA 0xfffff200
+#define AT91_BASE_PIOB 0xfffff400
+#define AT91_BASE_PIOC 0xfffff600
+#define AT91_BASE_PIOD 0xfffff800
+#define AT91_BASE_PIOE 0xfffffa00
+
#define AT91_USART0 AT91SAM9263_BASE_US0
#define AT91_USART1 AT91SAM9263_BASE_US1
#define AT91_USART2 AT91SAM9263_BASE_US2
diff --git a/arch/arm/mach-at91/include/mach/at91sam9g45.h b/arch/arm/mach-at91/include/mach/at91sam9g45.h
index c5c7f497d4..18fa6c50ff 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9g45.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9g45.h
@@ -97,11 +97,6 @@
#define AT91_DMA (0xffffec00 - AT91_BASE_SYS)
#define AT91_DBGU (0xffffee00 - AT91_BASE_SYS)
#define AT91_AIC (0xfffff000 - AT91_BASE_SYS)
-#define AT91_PIOA (0xfffff200 - AT91_BASE_SYS)
-#define AT91_PIOB (0xfffff400 - AT91_BASE_SYS)
-#define AT91_PIOC (0xfffff600 - AT91_BASE_SYS)
-#define AT91_PIOD (0xfffff800 - AT91_BASE_SYS)
-#define AT91_PIOE (0xfffffa00 - AT91_BASE_SYS)
#define AT91_PMC (0xfffffc00 - AT91_BASE_SYS)
#define AT91_RSTC (0xfffffd00 - AT91_BASE_SYS)
#define AT91_SHDWC (0xfffffd10 - AT91_BASE_SYS)
@@ -111,6 +106,12 @@
#define AT91_GPBR (0xfffffd60 - AT91_BASE_SYS)
#define AT91_RTC (0xfffffdb0 - AT91_BASE_SYS)
+#define AT91_BASE_PIOA 0xfffff200
+#define AT91_BASE_PIOB 0xfffff400
+#define AT91_BASE_PIOC 0xfffff600
+#define AT91_BASE_PIOD 0xfffff800
+#define AT91_BASE_PIOE 0xfffffa00
+
#define AT91_USART0 AT91SAM9G45_BASE_US0
#define AT91_USART1 AT91SAM9G45_BASE_US1
#define AT91_USART2 AT91SAM9G45_BASE_US2
diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
index daeadbbf92..2619234196 100644
--- a/arch/arm/mach-at91/include/mach/board.h
+++ b/arch/arm/mach-at91/include/mach/board.h
@@ -34,6 +34,16 @@ 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);
+ /* USB Device */
+struct at91_udc_data {
+ int vbus_pin; /* high == host powering us */
+ u8 vbus_active_low; /* vbus polarity */
+ u8 vbus_polled; /* Use polling, not interrupt */
+ int pullup_pin; /* active == D+ pulled up */
+ u8 pullup_active_low; /* true == pullup_pin is active low */
+};
+extern void __init at91_add_device_udc(struct at91_udc_data *data);
+
/* NAND / SmartMedia */
struct atmel_nand_data {
u8 enable_pin; /* chip enable */
diff --git a/arch/arm/mach-at91/include/mach/gpio.h b/arch/arm/mach-at91/include/mach/gpio.h
index f3239f5f42..95a4bd479b 100644
--- a/arch/arm/mach-at91/include/mach/gpio.h
+++ b/arch/arm/mach-at91/include/mach/gpio.h
@@ -236,11 +236,7 @@ int at91_set_gpio_value(unsigned pin, int value);
int at91_get_gpio_value(unsigned pin);
struct at91_gpio_bank {
- unsigned chipbase; /* bank's first GPIO number */
void __iomem *regbase; /* base of register bank */
- struct at91_gpio_bank *next; /* bank sharing same IRQ/clock/... */
- unsigned short id; /* peripheral ID */
- unsigned long offset; /* offset from system peripheral base */
struct clk *clock;
};
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 27bf386fbf..7da39cbfd8 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -372,11 +372,9 @@ choice
config MACH_FREESCALE_MX51_PDK
bool "Freescale i.MX51 PDK"
- select MACH_HAS_LOWLEVEL_INIT
config MACH_EUKREA_CPUIMX51SD
bool "EUKREA CPUIMX51"
- select MACH_HAS_LOWLEVEL_INIT
help
Say Y here if you are using Eukrea's CPUIMX51 equipped
with a Freescale i.MX51 Processor
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0b3b781e8b..a9aa9e2655 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -5,8 +5,8 @@ obj-$(CONFIG_ARCH_IMX21) += speed-imx21.o imx21.o iomux-v1.o
obj-$(CONFIG_ARCH_IMX27) += speed-imx27.o imx27.o iomux-v1.o
obj-$(CONFIG_ARCH_IMX31) += speed-imx31.o imx31.o iomux-v2.o
obj-$(CONFIG_ARCH_IMX35) += speed-imx35.o imx35.o iomux-v3.o
-obj-$(CONFIG_ARCH_IMX51) += speed-imx51.o imx51.o iomux-v3.o
-obj-$(CONFIG_ARCH_IMX53) += speed-imx53.o imx53.o iomux-v3.o
+obj-$(CONFIG_ARCH_IMX51) += speed-imx51.o imx51.o iomux-v3.o imx5.o
+obj-$(CONFIG_ARCH_IMX53) += speed-imx53.o imx53.o iomux-v3.o imx5.o
obj-$(CONFIG_IMX_CLKO) += clko.o
obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_NAND_IMX) += nand.o
diff --git a/arch/arm/mach-imx/imx27.c b/arch/arm/mach-imx/imx27.c
index 86039c4dea..1af291d33a 100644
--- a/arch/arm/mach-imx/imx27.c
+++ b/arch/arm/mach-imx/imx27.c
@@ -19,6 +19,7 @@
#include <mach/imx-regs.h>
#include <sizes.h>
#include <init.h>
+#include <io.h>
#include "gpio.h"
@@ -38,11 +39,53 @@ void *imx_gpio_base[] = {
int imx_gpio_count = ARRAY_SIZE(imx_gpio_base) * 32;
+/*
+ * Initialize MAX on i.MX27. necessary to give the DMA engine
+ * higher priority to the memory than the CPU. Needed for proper
+ * audio support
+ */
+#define MAX_SLAVE_MPR_OFFSET 0x0 /* Master Priority register */
+#define MAX_SLAVE_AMPR_OFFSET 0x4 /* Alternate Master Priority register */
+#define MAX_SLAVE_PORT0_OFFSET 0x0
+#define MAX_SLAVE_PORT1_OFFSET 0x100
+#define MAX_SLAVE_PORT2_OFFSET 0x200
+#define MAX_MASTER_PRIO(master, prio) (((prio) << (master) * 4))
+
+#define MASTER_IAHB 0
+#define MASTER_DAHB 1
+#define MASTER_EMMA 2
+#define MASTER_DMA 3
+#define MASTER_SLDC 4
+#define MASTER_CODEC 5
+
+static void imx27_init_max(void)
+{
+ void __iomem *max_base = (void *)IMX_MAX_BASE;
+ u32 val;
+
+ /* 0 is the highest priority */
+ val = MAX_MASTER_PRIO(MASTER_IAHB, 5) |
+ MAX_MASTER_PRIO(MASTER_DAHB, 4) |
+ MAX_MASTER_PRIO(MASTER_EMMA, 1) |
+ MAX_MASTER_PRIO(MASTER_DMA, 2) |
+ MAX_MASTER_PRIO(MASTER_SLDC, 0) |
+ MAX_MASTER_PRIO(MASTER_CODEC, 3);
+
+ writel(val, max_base + MAX_SLAVE_PORT0_OFFSET + MAX_SLAVE_MPR_OFFSET);
+ writel(val, max_base + MAX_SLAVE_PORT1_OFFSET + MAX_SLAVE_MPR_OFFSET);
+ writel(val, max_base + MAX_SLAVE_PORT2_OFFSET + MAX_SLAVE_MPR_OFFSET);
+ writel(val, max_base + MAX_SLAVE_PORT0_OFFSET + MAX_SLAVE_AMPR_OFFSET);
+ writel(val, max_base + MAX_SLAVE_PORT1_OFFSET + MAX_SLAVE_AMPR_OFFSET);
+ writel(val, max_base + MAX_SLAVE_PORT2_OFFSET + MAX_SLAVE_AMPR_OFFSET);
+}
+
static int imx27_init(void)
{
add_generic_device("imx_iim", 0, NULL, IMX_IIM_BASE, SZ_4K,
IORESOURCE_MEM, NULL);
+ imx27_init_max();
+
return 0;
}
coredevice_initcall(imx27_init);
diff --git a/arch/arm/mach-imx/imx5.c b/arch/arm/mach-imx/imx5.c
new file mode 100644
index 0000000000..9ec78b2afd
--- /dev/null
+++ b/arch/arm/mach-imx/imx5.c
@@ -0,0 +1,58 @@
+#include <common.h>
+#include <io.h>
+#include <sizes.h>
+#include <mach/imx5.h>
+#include <mach/clock-imx51_53.h>
+
+void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn)
+{
+ u32 r;
+
+ /*
+ * If freq < 300MHz, we need to set dpdck0_2_en to 0
+ */
+ r = 0x00000232;
+ if (freq >= 300)
+ r |= 0x1000;
+
+ writel(r, base + MX5_PLL_DP_CTL);
+
+ writel(0x2, base + MX5_PLL_DP_CONFIG);
+
+ writel(op, base + MX5_PLL_DP_OP);
+ writel(op, base + MX5_PLL_DP_HFS_OP);
+
+ writel(mfd, base + MX5_PLL_DP_MFD);
+ writel(mfd, base + MX5_PLL_DP_HFS_MFD);
+
+ writel(mfn, base + MX5_PLL_DP_MFN);
+ writel(mfn, base + MX5_PLL_DP_HFS_MFN);
+
+ writel(0x00001232, base + MX5_PLL_DP_CTL);
+
+ while (!(readl(base + MX5_PLL_DP_CTL) & 1));
+}
+
+void imx5_init_lowlevel(void)
+{
+ u32 r;
+
+ /* ARM errata ID #468414 */
+ __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r));
+ r |= (1 << 5); /* enable L1NEON bit */
+ r &= ~(1 << 1); /* explicitly disable L2 cache */
+ __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r));
+
+ /* reconfigure L2 cache aux control reg */
+ r = 0xc0 | /* tag RAM */
+ 0x4 | /* data RAM */
+ (1 << 24) | /* disable write allocate delay */
+ (1 << 23) | /* disable write allocate combine */
+ (1 << 22); /* disable write allocate */
+
+ __asm__ __volatile__("mcr 15, 1, %0, c9, c0, 2" : : "r"(r));
+
+ __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r));
+ r |= 1 << 1; /* enable L2 cache */
+ __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r));
+}
diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c
index 2c1efed150..2431e61115 100644
--- a/arch/arm/mach-imx/imx51.c
+++ b/arch/arm/mach-imx/imx51.c
@@ -21,6 +21,8 @@
#include <environment.h>
#include <io.h>
#include <mach/imx51-regs.h>
+#include <mach/imx5.h>
+#include <mach/clock-imx51_53.h>
#include "gpio.h"
@@ -176,3 +178,106 @@ static int imx51_boot_save_loc(void)
}
coredevice_initcall(imx51_boot_save_loc);
+
+#define setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5)
+#define setup_pll_800(base) imx5_setup_pll((base), 800, ((8 << 4) + ((1 - 1) << 0)), (3 - 1), 1)
+#define setup_pll_665(base) imx5_setup_pll((base), 665, ((6 << 4) + ((1 - 1) << 0)), (96 - 1), 89)
+#define setup_pll_400(base) imx5_setup_pll((base), 400, ((8 << 4) + ((2 - 1) << 0)), (3 - 1), 1)
+#define setup_pll_455(base) imx5_setup_pll((base), 455, ((9 << 4) + ((2 - 1) << 0)), (48 - 1), 23)
+#define setup_pll_216(base) imx5_setup_pll((base), 216, ((6 << 4) + ((3 - 1) << 0)), (4 - 1), 3)
+
+void imx51_init_lowlevel(void)
+{
+ void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR;
+ u32 r;
+
+ imx5_init_lowlevel();
+
+ /* disable write combine for TO 2 and lower revs */
+ if (imx_silicon_revision() < MX51_CHIP_REV_3_0) {
+ __asm__ __volatile__("mrc 15, 1, %0, c9, c0, 1":"=r"(r));
+ r |= (1 << 25);
+ __asm__ __volatile__("mcr 15, 1, %0, c9, c0, 1" : : "r"(r));
+ }
+
+ /* Gate of clocks to the peripherals first */
+ writel(0x3fffffff, ccm + MX5_CCM_CCGR0);
+ writel(0x00000000, ccm + MX5_CCM_CCGR1);
+ writel(0x00000000, ccm + MX5_CCM_CCGR2);
+ writel(0x00000000, ccm + MX5_CCM_CCGR3);
+ writel(0x00030000, ccm + MX5_CCM_CCGR4);
+ writel(0x00fff030, ccm + MX5_CCM_CCGR5);
+ writel(0x00000300, ccm + MX5_CCM_CCGR6);
+
+ /* Disable IPU and HSC dividers */
+ writel(0x00060000, ccm + MX5_CCM_CCDR);
+
+ /* Make sure to switch the DDR away from PLL 1 */
+ writel(0x19239145, ccm + MX5_CCM_CBCDR);
+ /* make sure divider effective */
+ while (readl(ccm + MX5_CCM_CDHIPR));
+
+ /* Switch ARM to step clock */
+ writel(0x4, ccm + MX5_CCM_CCSR);
+
+ setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR);
+ setup_pll_665((void __iomem *)MX51_PLL3_BASE_ADDR);
+
+ /* Switch peripheral to PLL 3 */
+ writel(0x000010C0, ccm + MX5_CCM_CBCMR);
+ writel(0x13239145, ccm + MX5_CCM_CBCDR);
+
+ setup_pll_665((void __iomem *)MX51_PLL2_BASE_ADDR);
+
+ /* Switch peripheral to PLL2 */
+ writel(0x19239145, ccm + MX5_CCM_CBCDR);
+ writel(0x000020C0, ccm + MX5_CCM_CBCMR);
+
+ setup_pll_216((void __iomem *)MX51_PLL3_BASE_ADDR);
+
+ /* Set the platform clock dividers */
+ writel(0x00000124, MX51_ARM_BASE_ADDR + 0x14);
+
+ /* Run TO 3.0 at Full speed, for other TO's wait till we increase VDDGP */
+ if (imx_silicon_revision() == MX51_CHIP_REV_3_0)
+ writel(0x0, ccm + MX5_CCM_CACRR);
+ else
+ writel(0x1, ccm + MX5_CCM_CACRR);
+
+ /* Switch ARM back to PLL 1 */
+ writel(0x0, ccm + MX5_CCM_CCSR);
+
+ /* setup the rest */
+ /* Use lp_apm (24MHz) source for perclk */
+ writel(0x000020C2, ccm + MX5_CCM_CBCMR);
+ /* ddr clock from PLL 1, all perclk dividers are 1 since using 24MHz */
+ writel(0x59239100, ccm + MX5_CCM_CBCDR);
+
+ /* Restore the default values in the Gate registers */
+ writel(0xffffffff, ccm + MX5_CCM_CCGR0);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR1);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR2);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR3);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR4);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR5);
+ writel(0xffffffff, ccm + MX5_CCM_CCGR6);
+
+ /* Use PLL 2 for UART's, get 66.5MHz from it */
+ writel(0xA5A2A020, ccm + MX5_CCM_CSCMR1);
+ writel(0x00C30321, ccm + MX5_CCM_CSCDR1);
+
+ /* make sure divider effective */
+ while (readl(ccm + MX5_CCM_CDHIPR));
+
+ writel(0x0, ccm + MX5_CCM_CCDR);
+
+ writel(0x1, 0x73fa8074);
+
+ r = readl(0x73f88000);
+ r |= 0x40;
+ writel(r, 0x73f88000);
+
+ r = readl(0x73f88004);
+ r |= 0x40;
+ writel(r, 0x73f88004);
+}
diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c
index 64bec867ff..2fb18e7f13 100644
--- a/arch/arm/mach-imx/imx53.c
+++ b/arch/arm/mach-imx/imx53.c
@@ -19,6 +19,7 @@
#include <common.h>
#include <io.h>
#include <sizes.h>
+#include <mach/imx5.h>
#include <mach/imx53-regs.h>
#include <mach/clock-imx51_53.h>
@@ -45,63 +46,17 @@ static int imx53_init(void)
}
coredevice_initcall(imx53_init);
-static void setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn)
-{
- u32 r;
-
- /*
- * If freq < 300MHz, we need to set dpdck0_2_en to 0
- */
- r = 0x00000232;
- if (freq >= 300)
- r |= 0x1000;
-
- writel(r, base + MX5_PLL_DP_CTL);
-
- writel(0x2, base + MX5_PLL_DP_CONFIG);
-
- writel(op, base + MX5_PLL_DP_OP);
- writel(op, base + MX5_PLL_DP_HFS_OP);
-
- writel(mfd, base + MX5_PLL_DP_MFD);
- writel(mfd, base + MX5_PLL_DP_HFS_MFD);
-
- writel(mfn, base + MX5_PLL_DP_MFN);
- writel(mfn, base + MX5_PLL_DP_HFS_MFN);
+#define setup_pll_1000(base) imx5_setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5)
+#define setup_pll_400(base) imx5_setup_pll((base), 400, ((8 << 4) + ((2 - 1) << 0)), (3 - 1), 1)
+#define setup_pll_455(base) imx5_setup_pll((base), 455, ((9 << 4) + ((2 - 1) << 0)), (48 - 1), 23)
+#define setup_pll_216(base) imx5_setup_pll((base), 216, ((8 << 4) + ((2 - 1) << 0)), (1 - 1), 1)
- writel(0x00001232, base + MX5_PLL_DP_CTL);
-
- while (!(readl(base + MX5_PLL_DP_CTL) & 1));
-}
-
-#define setup_pll_1000(base) setup_pll((base), 1000, ((10 << 4) + ((1 - 1) << 0)), (12 - 1), 5)
-#define setup_pll_400(base) setup_pll((base), 400, ((8 << 4) + ((2 - 1) << 0)), (3 - 1), 1)
-#define setup_pll_455(base) setup_pll((base), 455, ((9 << 4) + ((2 - 1) << 0)), (48 - 1), 23)
-#define setup_pll_216(base) setup_pll((base), 216, ((8 << 4) + ((2 - 1) << 0)), (1 - 1), 1)
-
-int mx53_init_lowlevel(void)
+void imx53_init_lowlevel(void)
{
void __iomem *ccm = (void __iomem *)MX53_CCM_BASE_ADDR;
u32 r;
- /* ARM errata ID #468414 */
- __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r));
- r |= (1 << 5); /* enable L1NEON bit */
- r &= ~(1 << 1); /* explicitly disable L2 cache */
- __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r));
-
- /* reconfigure L2 cache aux control reg */
- r = 0xc0 | /* tag RAM */
- 0x4 | /* data RAM */
- (1 << 24) | /* disable write allocate delay */
- (1 << 23) | /* disable write allocate combine */
- (1 << 22); /* disable write allocate */
-
- __asm__ __volatile__("mcr 15, 1, %0, c9, c0, 2" : : "r"(r));
-
- __asm__ __volatile__("mrc 15, 0, %0, c1, c0, 1":"=r"(r));
- r |= 1 << 1; /* enable L2 cache */
- __asm__ __volatile__("mcr 15, 0, %0, c1, c0, 1" : : "r"(r));
+ imx5_init_lowlevel();
/*
* AIPS setup - Only setup MPROTx registers.
@@ -195,6 +150,4 @@ int mx53_init_lowlevel(void)
writel(0xffffffff, ccm + MX53_CCM_CCGR7);
writel(0, ccm + MX5_CCM_CCDR);
-
- return 0;
}
diff --git a/arch/arm/mach-imx/include/mach/imx27-regs.h b/arch/arm/mach-imx/include/mach/imx27-regs.h
index 6754c5a937..3a4325e3da 100644
--- a/arch/arm/mach-imx/include/mach/imx27-regs.h
+++ b/arch/arm/mach-imx/include/mach/imx27-regs.h
@@ -33,6 +33,7 @@
#define IMX_IIM_BASE (0x28000 + IMX_IO_BASE)
#define IMX_OTG_BASE (0x24000 + IMX_IO_BASE)
#define IMX_FEC_BASE (0x2b000 + IMX_IO_BASE)
+#define IMX_MAX_BASE (0x3f000 + IMX_IO_BASE)
#define IMX_NFC_BASE (0xd8000000)
#define IMX_ESD_BASE (0xd8001000)
diff --git a/arch/arm/mach-imx/include/mach/imx5.h b/arch/arm/mach-imx/include/mach/imx5.h
new file mode 100644
index 0000000000..04911797a3
--- /dev/null
+++ b/arch/arm/mach-imx/include/mach/imx5.h
@@ -0,0 +1,9 @@
+#ifndef __MACH_MX5_H
+#define __MACH_MX5_H
+
+void imx53_init_lowlevel(void);
+void imx51_init_lowlevel(void);
+void imx5_setup_pll(void __iomem *base, int freq, u32 op, u32 mfd, u32 mfn);
+void imx5_init_lowlevel(void);
+
+#endif /* __MACH_MX53_H */
diff --git a/arch/arm/mach-imx/include/mach/imx53.h b/arch/arm/mach-imx/include/mach/imx53.h
deleted file mode 100644
index b1f30d34af..0000000000
--- a/arch/arm/mach-imx/include/mach/imx53.h
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __MACH_MX53_H
-#define __MACH_MX53_H
-
-int mx53_init_lowlevel(void);
-
-#endif /* __MACH_MX53_H */
diff --git a/arch/arm/mach-imx/include/mach/imxfb.h b/arch/arm/mach-imx/include/mach/imxfb.h
index b71b7f4594..ea39e3198e 100644
--- a/arch/arm/mach-imx/include/mach/imxfb.h
+++ b/arch/arm/mach-imx/include/mach/imxfb.h
@@ -63,6 +63,7 @@ struct imx_fb_videomode {
*/
struct imx_fb_platform_data {
struct imx_fb_videomode *mode;
+ u_int num_modes;
u_int cmap_greyscale:1,
cmap_inverse:1,
diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index caef7e0225..15f7c74315 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -5,11 +5,13 @@ config ARCH_TEXT_BASE
default 0x41000000 if MACH_MX23EVK
default 0x42000000 if MACH_CHUMBY
default 0x47000000 if MACH_TX28
+ default 0x47000000 if MACH_MX28EVK
config BOARDINFO
default "Freescale i.MX23-EVK" if MACH_MX23EVK
default "Chumby Falconwing" if MACH_CHUMBY
default "Karo TX28" if MACH_TX28
+ default "Freescale i.MX28-EVK" if MACH_MX28EVK
comment "Freescale i.MX System-on-Chip"
@@ -57,6 +59,11 @@ config MACH_TX28
help
Say Y here if you are using the KARO TX28 CPU module.
+config MACH_MX28EVK
+ bool "mx28-evk"
+ help
+ Say Y here if you are using the Freescale i.MX28-EVK board
+
endchoice
endif
diff --git a/arch/arm/mach-mxs/include/mach/iomux-imx28.h b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
index 1e6d421c22..1557126592 100644
--- a/arch/arm/mach-mxs/include/mach/iomux-imx28.h
+++ b/arch/arm/mach-mxs/include/mach/iomux-imx28.h
@@ -302,6 +302,7 @@
#define PWM2 (FUNC(0) | PORTF(3, 18))
#define PWM1 (FUNC(0) | PORTF(3, 17))
+#define PWM1_DUART_TX (FUNC(2) | PORTF(3, 17))
#define PWM0 (FUNC(0) | PORTF(3, 16))
#define PWM0_I2C1_SCL (FUNC(1) | PORTF(3, 16))
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index 1174df072f..73125a79e2 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -106,7 +106,7 @@ config BOARDINFO
default "Texas Instrument's OMAP3EVM" if MACH_OMAP3EVM
default "Texas Instrument's Panda" if MACH_PANDA
default "Phytec phyCORE pcm049" if MACH_PCM049
-
+ default "Phytec phyCARD-A-L1" if MACH_PCAAL1
choice
prompt "Select OMAP board"
@@ -154,6 +154,14 @@ config MACH_PCM049
Say Y here if you are using Phytecs phyCORE pcm049 board
based on OMAP4
+config MACH_PCAAL1
+ bool "Phytec phyCARD-A-L1"
+ select MACH_HAS_LOWLEVEL_INIT
+ select OMAP_CLOCK_ALL
+ select HAS_OMAP_NAND
+ help
+ Say Y here if you are using a phyCARD-A-L1 PCA-A-L1
+
endchoice
if MACH_OMAP3EVM
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index 07bf30afab..9bd2b629a5 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -26,4 +26,5 @@ obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock_core.o omap3_clock.o
obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
obj-$(CONFIG_SHELL_NONE) += xload.o
+obj-$(CONFIG_I2C_TWL6030) += omap4_twl6030_mmc.o
obj-y += gpio.o
diff --git a/arch/arm/mach-omap/include/mach/generic.h b/arch/arm/mach-omap/include/mach/generic.h
index a2dd229c1c..c801a068e3 100644
--- a/arch/arm/mach-omap/include/mach/generic.h
+++ b/arch/arm/mach-omap/include/mach/generic.h
@@ -5,6 +5,7 @@
/* I2C controller revisions present on specific hardware */
#define OMAP_I2C_REV_ON_2430 0x36
#define OMAP_I2C_REV_ON_3430 0x3C
+#define OMAP_I2C_REV_ON_4430 0x40
#ifdef CONFIG_ARCH_OMAP
#define cpu_is_omap2430() (1)
@@ -17,3 +18,9 @@
#else
#define cpu_is_omap34xx() (0)
#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+#define cpu_is_omap4xxx() (1)
+#else
+#define cpu_is_omap4xxx() (0)
+#endif
diff --git a/arch/arm/mach-omap/include/mach/omap3-silicon.h b/arch/arm/mach-omap/include/mach/omap3-silicon.h
index 67f77476a9..361d25e999 100644
--- a/arch/arm/mach-omap/include/mach/omap3-silicon.h
+++ b/arch/arm/mach-omap/include/mach/omap3-silicon.h
@@ -115,6 +115,10 @@
/** Gives the silicon revision */
#define OMAP_TAP_BASE (OMAP_L4_WKUP_BASE + 0xA000)
#define IDCODE_REG (OMAP_TAP_BASE + 0x204)
+#define DIE_ID_0 (OMAP_TAP_BASE + 0x218)
+#define DIE_ID_1 (OMAP_TAP_BASE + 0x21c)
+#define DIE_ID_2 (OMAP_TAP_BASE + 0x220)
+#define DIE_ID_3 (OMAP_TAP_BASE + 0x224)
/** Masks to extract information from ID code register */
#define IDCODE_HAWKEYE_MASK 0x0FFFF000
diff --git a/arch/arm/mach-omap/include/mach/omap4_twl6030_mmc.h b/arch/arm/mach-omap/include/mach/omap4_twl6030_mmc.h
new file mode 100644
index 0000000000..e5e2d9c229
--- /dev/null
+++ b/arch/arm/mach-omap/include/mach/omap4_twl6030_mmc.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ */
+
+#ifndef __OMAP4_TWL6030_MMC_H__
+#define __OMAP4_TWL6030_MMC_H__
+
+/*
+ * Sets up voltage for mmc slot.
+ */
+void set_up_mmc_voltage_omap4(void);
+
+/* __OMAP4_TWL6030_MMC_H__ */
+#endif
diff --git a/arch/arm/mach-omap/omap4_twl6030_mmc.c b/arch/arm/mach-omap/omap4_twl6030_mmc.c
new file mode 100644
index 0000000000..5d87935404
--- /dev/null
+++ b/arch/arm/mach-omap/omap4_twl6030_mmc.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de
+ *
+ * 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 <io.h>
+
+#include <mci/twl6030.h>
+
+/* MMC voltage */
+#define OMAP4_CONTROL_PBIASLITE 0x4A100600
+#define OMAP4_MMC1_PBIASLITE_VMODE (1<<21)
+#define OMAP4_MMC1_PBIASLITE_PWRDNZ (1<<22)
+#define OMAP4_MMC1_PWRDNZ (1<<26)
+
+void set_up_mmc_voltage_omap4(void)
+{
+ u32 value;
+
+ value = readl(OMAP4_CONTROL_PBIASLITE);
+ value &= ~(OMAP4_MMC1_PBIASLITE_PWRDNZ | OMAP4_MMC1_PWRDNZ);
+ writel(value, OMAP4_CONTROL_PBIASLITE);
+
+ twl6030_mci_power_init();
+
+ value = readl(OMAP4_CONTROL_PBIASLITE);
+ value |= (OMAP4_MMC1_PBIASLITE_VMODE | OMAP4_MMC1_PBIASLITE_PWRDNZ |
+ OMAP4_MMC1_PWRDNZ);
+ writel(value, OMAP4_CONTROL_PBIASLITE);
+}
+EXPORT_SYMBOL(set_up_mmc_voltage_omap4);
diff --git a/arch/arm/mach-pxa/include/mach/clock.h b/arch/arm/mach-pxa/include/mach/clock.h
index 4326fcaf76..c53432f015 100644
--- a/arch/arm/mach-pxa/include/mach/clock.h
+++ b/arch/arm/mach-pxa/include/mach/clock.h
@@ -12,6 +12,7 @@
#define __MACH_CLOCK_H
unsigned long pxa_get_uartclk(void);
+unsigned long pxa_get_mmcclk(void);
unsigned long pxa_get_lcdclk(void);
#endif /* !__MACH_CLOCK_H */
diff --git a/arch/arm/mach-pxa/include/mach/mci_pxa2xx.h b/arch/arm/mach-pxa/include/mach/mci_pxa2xx.h
new file mode 100644
index 0000000000..b24bc58afe
--- /dev/null
+++ b/arch/arm/mach-pxa/include/mach/mci_pxa2xx.h
@@ -0,0 +1,10 @@
+
+struct mci_host;
+struct device_d;
+
+struct pxamci_platform_data {
+ int gpio_power;
+ int gpio_power_invert;
+ int (*init)(struct mci_host*, struct device_d*);
+ int (*setpower)(struct mci_host*, int on);
+};
diff --git a/arch/arm/mach-pxa/speed-pxa27x.c b/arch/arm/mach-pxa/speed-pxa27x.c
index 0317d539a1..534eb1dcc7 100644
--- a/arch/arm/mach-pxa/speed-pxa27x.c
+++ b/arch/arm/mach-pxa/speed-pxa27x.c
@@ -19,6 +19,11 @@ unsigned long pxa_get_uartclk(void)
return 14857000;
}
+unsigned long pxa_get_mmcclk(void)
+{
+ return 19500000;
+}
+
/*
* Return the current LCD clock frequency in units of 10kHz as
*/
diff --git a/arch/arm/mach-s3c24xx/Makefile b/arch/arm/mach-s3c24xx/Makefile
deleted file mode 100644
index 88d45fe370..0000000000
--- a/arch/arm/mach-s3c24xx/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-y += generic.o gpio-s3c24x0.o
-obj-$(CONFIG_S3C24XX_LOW_LEVEL_INIT) += lowlevel-init.o
diff --git a/arch/arm/mach-s3c24xx/generic.c b/arch/arm/mach-s3c24xx/generic.c
deleted file mode 100644
index d2f2ac7ac0..0000000000
--- a/arch/arm/mach-s3c24xx/generic.c
+++ /dev/null
@@ -1,297 +0,0 @@
-/*
- * 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
- */
-/**
- * @file
- * @brief Basic clock, sdram and timer handling for S3C24xx CPUs
- */
-
-#include <config.h>
-#include <common.h>
-#include <init.h>
-#include <clock.h>
-#include <io.h>
-#include <mach/s3c24x0-iomap.h>
-
-/**
- * Calculate the current M-PLL clock.
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_mpllclk(void)
-{
- uint32_t m, p, s, reg_val;
-
- reg_val = readl(MPLLCON);
- m = ((reg_val & 0xFF000) >> 12) + 8;
- p = ((reg_val & 0x003F0) >> 4) + 2;
- s = reg_val & 0x3;
-#ifdef CONFIG_CPU_S3C2410
- return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
-#endif
-#ifdef CONFIG_CPU_S3C2440
- return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s));
-#endif
-}
-
-/**
- * Calculate the current U-PLL clock
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_upllclk(void)
-{
- uint32_t m, p, s, reg_val;
-
- reg_val = readl(UPLLCON);
- m = ((reg_val & 0xFF000) >> 12) + 8;
- p = ((reg_val & 0x003F0) >> 4) + 2;
- s = reg_val & 0x3;
-
- return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
-}
-
-/**
- * Calculate the FCLK frequency used for the ARM CPU core
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_fclk(void)
-{
- return s3c24xx_get_mpllclk();
-}
-
-/**
- * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_hclk(void)
-{
- uint32_t f_clk;
-
- f_clk = s3c24xx_get_fclk();
-#ifdef CONFIG_CPU_S3C2410
- if (readl(CLKDIVN) & 0x02)
- return f_clk >> 1;
-#endif
-#ifdef CONFIG_CPU_S3C2440
- switch(readl(CLKDIVN) & 0x06) {
- case 2:
- return f_clk >> 1;
- case 4:
- return f_clk >> 2; /* TODO consider CAMDIVN */
- case 6:
- return f_clk / 3; /* TODO consider CAMDIVN */
- }
-#endif
- return f_clk;
-}
-
-/**
- * Calculate the PCLK frequency used for the slower peripherals
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_pclk(void)
-{
- uint32_t p_clk;
-
- p_clk = s3c24xx_get_hclk();
- if (readl(CLKDIVN) & 0x01)
- return p_clk >> 1;
- return p_clk;
-}
-
-/**
- * Calculate the UCLK frequency used by the USB host device
- * @return Current frequency in Hz
- */
-uint32_t s3c24xx_get_uclk(void)
-{
- return s3c24xx_get_upllclk();
-}
-
-/**
- * Calculate the amount of connected and available memory
- * @return Memory size in bytes
- */
-uint32_t s3c24x0_get_memory_size(void)
-{
- uint32_t reg, size;
-
- /*
- * detect the current memory size
- */
- reg = readl(BANKSIZE);
-
- switch (reg & 0x7) {
- case 0:
- size = 32 * 1024 * 1024;
- break;
- case 1:
- size = 64 * 1024 * 1024;
- break;
- case 2:
- size = 128 * 1024 * 1024;
- break;
- case 4:
- size = 2 * 1024 * 1024;
- break;
- case 5:
- size = 4 * 1024 * 1024;
- break;
- case 6:
- size = 8 * 1024 * 1024;
- break;
- default:
- size = 16 * 1024 * 1024;
- break;
- }
-
- /*
- * Is bank7 also configured for SDRAM usage?
- */
- if ((readl(BANKCON7) & (0x3 << 15)) == (0x3 << 15))
- size <<= 1; /* also count this bank */
-
- return size;
-}
-
-/**
- * Show the user the current clock settings
- */
-int s3c24xx_dump_clocks(void)
-{
- printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000);
- printf("mpll: %7d kHz\n", s3c24xx_get_mpllclk() / 1000);
- printf("upll: %7d kHz\n", s3c24xx_get_upllclk() / 1000);
- printf("fclk: %7d kHz\n", s3c24xx_get_fclk() / 1000);
- printf("hclk: %7d kHz\n", s3c24xx_get_hclk() / 1000);
- printf("pclk: %7d kHz\n", s3c24xx_get_pclk() / 1000);
- printf("SDRAM1: CL%d@%dMHz\n", ((readl(BANKCON6) & 0xc) >> 2) + 2, s3c24xx_get_hclk() / 1000000);
- if ((readl(BANKCON7) & (0x3 << 15)) == (0x3 << 15))
- printf("SDRAM2: CL%d@%dMHz\n", ((readl(BANKCON7) & 0xc) >> 2) + 2,
- s3c24xx_get_hclk() / 1000000);
- return 0;
-}
-
-late_initcall(s3c24xx_dump_clocks);
-
-static uint64_t s3c24xx_clocksource_read(void)
-{
- /* note: its a down counter */
- return 0xFFFF - readw(TCNTO4);
-}
-
-static struct clocksource cs = {
- .read = s3c24xx_clocksource_read,
- .mask = CLOCKSOURCE_MASK(16),
- .shift = 10,
-};
-
-static int clocksource_init (void)
-{
- uint32_t p_clk = s3c24xx_get_pclk();
-
- writel(0x00000000, TCON); /* stop all timers */
- writel(0x00ffffff, TCFG0); /* PCLK / (255 + 1) for timer 4 */
- writel(0x00030000, TCFG1); /* /16 */
-
- writew(0xffff, TCNTB4); /* reload value is TOP */
-
- writel(0x00600000, TCON); /* force a first reload */
- writel(0x00400000, TCON);
- writel(0x00500000, TCON); /* enable timer 4 with auto reload */
-
- cs.mult = clocksource_hz2mult(p_clk / ((255 + 1) * 16), cs.shift);
- init_clock(&cs);
-
- return 0;
-}
-core_initcall(clocksource_init);
-
-void __noreturn reset_cpu(unsigned long addr)
-{
- /* Disable watchdog */
- writew(0x0000, WTCON);
-
- /* Initialize watchdog timer count register */
- writew(0x0001, WTCNT);
-
- /* Enable watchdog timer; assert reset at timer timeout */
- writew(0x0021, WTCON);
-
- /* loop forever and wait for reset to happen */
- while(1)
- ;
-}
-EXPORT_SYMBOL(reset_cpu);
-
-/**
-
-@page dev_s3c24xx_arch Samsung's S3C24xx Platforms in barebox
-
-@section s3c24xx_boards Boards using S3C24xx Processors
-
-@li @subpage arch/arm/boards/a9m2410/a9m2410.c
-@li @subpage arch/arm/boards/a9m2440/a9m2440.c
-
-@section s3c24xx_arch Documentation for S3C24xx Architectures Files
-
-@li @subpage arch/arm/mach-s3c24xx/generic.c
-
-@section s3c24xx_mem_map SDRAM Memory Map
-
-SDRAM starts at address 0x3000.0000 up to the available amount of connected
-SDRAM memory. Physically this CPU can handle up to 256MiB (two areas with
-up to 128MiB each).
-
-@subsection s3c24xx_mem_generic_map Generic Map
-- 0x0000.0000 Start of the internal SRAM when booting from NAND flash memory or CS signal to a NOR flash memory.
-- 0x0800.0000 Start of I/O space.
-- 0x3000.0000 Start of SDRAM area.
- - 0x3000.0100 Start of the TAG list area.
- - 0x3000.8000 Start of the linux kernel (physical address).
-- 0x4000.0000 Start of internal SRAM, when booting from NOR flash memory
-- 0x4800.0000 Start of the internal I/O area
-
-@section s3c24xx_asm_arm include/asm-arm/arch-s3c24xx directory guidelines
-All S3C24xx common headers are located here.
-
-@note Do not add board specific header files/information here.
-*/
-
-/** @page dev_s3c24xx_mach Samsung's S3C24xx based platforms
-
-@par barebox Map
-
-The location of the @a barebox itself depends on the available amount of
-installed SDRAM memory:
-
-- 0x30fc.0000 Start of @a barebox when 16MiB SDRAM is available
-- 0x31fc.0000 Start of @a barebox when 32MiB SDRAM is available
-- 0x33fc.0000 Start of @a barebox when 64MiB SDRAM is available
-
-Adjust the @p CONFIG_TEXT_BASE/CONFIG_ARCH_TEXT_BASE symbol in accordance to
-the available memory.
-
-@note The RAM based filesystem and the stack resides always below the
-@a barebox start address.
-
-@li @subpage dev_s3c24xx_wd_handling
-@li @subpage dev_s3c24xx_pll_handling
-@li @subpage dev_s3c24xx_sdram_handling
-@li @subpage dev_s3c24xx_nandboot_handling
-*/
diff --git a/arch/arm/mach-s3c24xx/include/mach/s3c24x0-iomap.h b/arch/arm/mach-s3c24xx/include/mach/s3c24x0-iomap.h
deleted file mode 100644
index a990d80c4a..0000000000
--- a/arch/arm/mach-s3c24xx/include/mach/s3c24x0-iomap.h
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2009 Juergen Beisert, Pengutronix
- *
- * 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
- *
- */
-
-/* S3C2410 device base addresses */
-#define S3C24X0_SDRAM_BASE 0x30000000
-#define S3C24X0_SDRAM_END 0x40000000
-#define S3C24X0_MEMCTL_BASE 0x48000000
-#define S3C2410_USB_HOST_BASE 0x49000000
-#define S3C2410_INTERRUPT_BASE 0x4A000000
-#define S3C2410_DMA_BASE 0x4B000000
-#define S3C24X0_CLOCK_POWER_BASE 0x4C000000
-#define S3C2410_LCD_BASE 0x4D000000
-#define S3C24X0_NAND_BASE 0x4E000000
-#define S3C24X0_UART_BASE 0x50000000
-#define S3C24X0_TIMER_BASE 0x51000000
-#define S3C2410_USB_DEVICE_BASE 0x52000140
-#define S3C24X0_WATCHDOG_BASE 0x53000000
-#define S3C2410_I2C_BASE 0x54000000
-#define S3C2410_I2S_BASE 0x55000000
-#define S3C24X0_GPIO_BASE 0x56000000
-#define S3C2410_RTC_BASE 0x57000000
-#define S3C2410_ADC_BASE 0x58000000
-#define S3C2410_SPI_BASE 0x59000000
-#define S3C2410_SDI_BASE 0x5A000000
-
-/* Clock control (direct access) */
-
-#define LOCKTIME (S3C24X0_CLOCK_POWER_BASE)
-#define MPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x4)
-#define UPLLCON (S3C24X0_CLOCK_POWER_BASE + 0x8)
-#define CLKCON (S3C24X0_CLOCK_POWER_BASE + 0xc)
-#define CLKSLOW (S3C24X0_CLOCK_POWER_BASE + 0x10)
-#define CLKDIVN (S3C24X0_CLOCK_POWER_BASE + 0x14)
-
-/* Timer (direct access) */
-#define TCFG0 (S3C24X0_TIMER_BASE + 0x00)
-#define TCFG1 (S3C24X0_TIMER_BASE + 0x04)
-#define TCON (S3C24X0_TIMER_BASE + 0x08)
-#define TCNTB0 (S3C24X0_TIMER_BASE + 0x0c)
-#define TCMPB0 (S3C24X0_TIMER_BASE + 0x10)
-#define TCNTO0 (S3C24X0_TIMER_BASE + 0x14)
-#define TCNTB1 (S3C24X0_TIMER_BASE + 0x18)
-#define TCMPB1 (S3C24X0_TIMER_BASE + 0x1c)
-#define TCNTO1 (S3C24X0_TIMER_BASE + 0x20)
-#define TCNTB2 (S3C24X0_TIMER_BASE + 0x24)
-#define TCMPB2 (S3C24X0_TIMER_BASE + 0x28)
-#define TCNTO2 (S3C24X0_TIMER_BASE + 0x2c)
-#define TCNTB3 (S3C24X0_TIMER_BASE + 0x30)
-#define TCMPB3 (S3C24X0_TIMER_BASE + 0x34)
-#define TCNTO3 (S3C24X0_TIMER_BASE + 0x38)
-#define TCNTB4 (S3C24X0_TIMER_BASE + 0x3c)
-#define TCNTO4 (S3C24X0_TIMER_BASE + 0x40)
-
-/* Watchdog (direct access) */
-#define WTCON (S3C24X0_WATCHDOG_BASE)
-#define WTDAT (S3C24X0_WATCHDOG_BASE + 0x04)
-#define WTCNT (S3C24X0_WATCHDOG_BASE + 0x08)
-
-/*
- * if we are booting from NAND, its internal SRAM occures at
- * a different address than without this feature
- */
-#ifdef CONFIG_S3C24XX_NAND_BOOT
-# define NFC_RAM_AREA 0x00000000
-#else
-# define NFC_RAM_AREA 0x40000000
-#endif
-#define NFC_RAM_SIZE 4096
-
-/* internal UARTs (driver based) */
-#define UART1_BASE (S3C24X0_UART_BASE)
-#define UART1_SIZE 0x4000
-#define UART2_BASE (S3C24X0_UART_BASE + 0x4000)
-#define UART2_SIZE 0x4000
-#define UART3_BASE (S3C24X0_UART_BASE + 0x8000)
-#define UART3_SIZE 0x4000
-
-/* CS configuration (direct access) */
-#define BWSCON (S3C24X0_MEMCTL_BASE)
-#define BANKCON0 (S3C24X0_MEMCTL_BASE + 0x04)
-#define BANKCON1 (S3C24X0_MEMCTL_BASE + 0x08)
-#define BANKCON2 (S3C24X0_MEMCTL_BASE + 0x0c)
-#define BANKCON3 (S3C24X0_MEMCTL_BASE + 0x10)
-#define BANKCON4 (S3C24X0_MEMCTL_BASE + 0x14)
-#define BANKCON5 (S3C24X0_MEMCTL_BASE + 0x18)
-#define BANKCON6 (S3C24X0_MEMCTL_BASE + 0x1c)
-#define BANKCON7 (S3C24X0_MEMCTL_BASE + 0x20)
-#define REFRESH (S3C24X0_MEMCTL_BASE + 0x24)
-#define BANKSIZE (S3C24X0_MEMCTL_BASE + 0x28)
-#define MRSRB6 (S3C24X0_MEMCTL_BASE + 0x2c)
-#define MRSRB7 (S3C24X0_MEMCTL_BASE + 0x30)
-
-/* GPIO registers (direct access) */
-#define GPACON (S3C24X0_GPIO_BASE)
-#define GPADAT (S3C24X0_GPIO_BASE + 0x04)
-
-#define GPBCON (S3C24X0_GPIO_BASE + 0x10)
-#define GPBDAT (S3C24X0_GPIO_BASE + 0x14)
-#define GPBUP (S3C24X0_GPIO_BASE + 0x18)
-
-#define GPCCON (S3C24X0_GPIO_BASE + 0x20)
-#define GPCDAT (S3C24X0_GPIO_BASE + 0x24)
-#define GPCUP (S3C24X0_GPIO_BASE + 0x28)
-
-#define GPDCON (S3C24X0_GPIO_BASE + 0x30)
-#define GPDDAT (S3C24X0_GPIO_BASE + 0x34)
-#define GPDUP (S3C24X0_GPIO_BASE + 0x38)
-
-#define GPECON (S3C24X0_GPIO_BASE + 0x40)
-#define GPEDAT (S3C24X0_GPIO_BASE + 0x44)
-#define GPEUP (S3C24X0_GPIO_BASE + 0x48)
-
-#define GPFCON (S3C24X0_GPIO_BASE + 0x50)
-#define GPFDAT (S3C24X0_GPIO_BASE + 0x54)
-#define GPFUP (S3C24X0_GPIO_BASE + 0x58)
-
-#define GPGCON (S3C24X0_GPIO_BASE + 0x60)
-#define GPGDAT (S3C24X0_GPIO_BASE + 0x64)
-#define GPGUP (S3C24X0_GPIO_BASE + 0x68)
-
-#define GPHCON (S3C24X0_GPIO_BASE + 0x70)
-#define GPHDAT (S3C24X0_GPIO_BASE + 0x74)
-#define GPHUP (S3C24X0_GPIO_BASE + 0x78)
-
-#ifdef CONFIG_CPU_S3C2440
-# define GPJCON (S3C24X0_GPIO_BASE + 0xd0)
-# define GPJDAT (S3C24X0_GPIO_BASE + 0xd4)
-# define GPJUP (S3C24X0_GPIO_BASE + 0xd8)
-#endif
-
-#define MISCCR (S3C24X0_GPIO_BASE + 0x80)
-#define DCLKCON (S3C24X0_GPIO_BASE + 0x84)
-#define EXTINT0 (S3C24X0_GPIO_BASE + 0x88)
-#define EXTINT1 (S3C24X0_GPIO_BASE + 0x8c)
-#define EXTINT2 (S3C24X0_GPIO_BASE + 0x90)
-#define EINTFLT0 (S3C24X0_GPIO_BASE + 0x94)
-#define EINTFLT1 (S3C24X0_GPIO_BASE + 0x98)
-#define EINTFLT2 (S3C24X0_GPIO_BASE + 0x9c)
-#define EINTFLT3 (S3C24X0_GPIO_BASE + 0xa0)
-#define EINTMASK (S3C24X0_GPIO_BASE + 0xa4)
-#define EINTPEND (S3C24X0_GPIO_BASE + 0xa8)
-#define GSTATUS0 (S3C24X0_GPIO_BASE + 0xac)
-#define GSTATUS1 (S3C24X0_GPIO_BASE + 0xb0)
-#define GSTATUS2 (S3C24X0_GPIO_BASE + 0xb4)
-#define GSTATUS3 (S3C24X0_GPIO_BASE + 0xb8)
-#define GSTATUS4 (S3C24X0_GPIO_BASE + 0xbc)
-
-#ifdef CONFIG_CPU_S3C2440
-# define DSC0 (S3C24X0_GPIO_BASE + 0xc4)
-# define DSC1 (S3C24X0_GPIO_BASE + 0xc8)
-#endif
-
-/* external IO space */
-#define CS0_BASE 0x00000000
-#define CS1_BASE 0x08000000
-#define CS2_BASE 0x10000000
-#define CS3_BASE 0x18000000
-#define CS4_BASE 0x20000000
-#define CS5_BASE 0x28000000
-#define CS6_BASE 0x30000000
diff --git a/arch/arm/mach-s3c24xx/Kconfig b/arch/arm/mach-samsung/Kconfig
index 80b65fb4ca..bc283dc947 100644
--- a/arch/arm/mach-s3c24xx/Kconfig
+++ b/arch/arm/mach-samsung/Kconfig
@@ -1,14 +1,21 @@
-if ARCH_S3C24xx
+config ARCH_SAMSUNG
+ bool
+
+if ARCH_SAMSUNG
config ARCH_TEXT_BASE
hex
- default 0x31fc0000
+ default 0x31fc0000 if MACH_MINI2440
+ default 0x31fc0000 if MACH_A9M2440
+ default 0x31fc0000 if MACH_A9M2410
config BOARDINFO
default "Mini 2440" if MACH_MINI2440
default "Digi A9M2440" if MACH_A9M2440
default "Digi A9M2410" if MACH_A9M2410
+if ARCH_S3C24xx
+
config CPU_S3C2410
bool
@@ -67,7 +74,7 @@ config MACH_A9M2410DEV
endchoice
-source arch/arm/boards/mini2440/Kconfig
+source arch/arm/boards/mini2440/Kconfig
endmenu
@@ -98,7 +105,7 @@ config S3C24XX_NAND_BOOT
prompt "Booting from NAND"
select MTD
select NAND
- select NAND_S3C24X0
+ select NAND_S3C24XX
help
Add generic support to boot from NAND flash. Image loading will be
skipped if the code is running from NOR or already from SDRAM.
@@ -106,3 +113,5 @@ config S3C24XX_NAND_BOOT
endmenu
endif
+
+endif
diff --git a/arch/arm/mach-samsung/Makefile b/arch/arm/mach-samsung/Makefile
new file mode 100644
index 0000000000..2ba5c3f1e2
--- /dev/null
+++ b/arch/arm/mach-samsung/Makefile
@@ -0,0 +1,3 @@
+obj-y += s3c-timer.o generic.o
+obj-$(CONFIG_ARCH_S3C24xx) += gpio-s3c24x0.o s3c24xx-clocks.o
+obj-$(CONFIG_S3C24XX_LOW_LEVEL_INIT) += lowlevel-init.o
diff --git a/arch/arm/mach-samsung/generic.c b/arch/arm/mach-samsung/generic.c
new file mode 100644
index 0000000000..7706be2628
--- /dev/null
+++ b/arch/arm/mach-samsung/generic.c
@@ -0,0 +1,164 @@
+/*
+ * 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
+ */
+/**
+ * @file
+ * @brief Basic clock, sdram and timer handling for S3C24xx CPUs
+ */
+
+#include <config.h>
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <io.h>
+#include <sizes.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-busctl.h>
+#include <mach/s3c24xx-gpio.h>
+
+/**
+ * Calculate the amount of connected and available memory
+ * @return Memory size in bytes
+ */
+uint32_t s3c24xx_get_memory_size(void)
+{
+ uint32_t reg, size;
+
+ /*
+ * detect the current memory size
+ */
+ reg = readl(S3C_BANKSIZE);
+
+ switch (reg & 0x7) {
+ case 0:
+ size = SZ_32M;
+ break;
+ case 1:
+ size = SZ_64M;
+ break;
+ case 2:
+ size = SZ_128M;
+ break;
+ case 4:
+ size = SZ_2M;
+ break;
+ case 5:
+ size = SZ_4M;
+ break;
+ case 6:
+ size = SZ_8M;
+ break;
+ default:
+ size = SZ_16M;
+ break;
+ }
+
+ /*
+ * Is bank7 also configured for SDRAM usage?
+ */
+ if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15))
+ size <<= 1; /* also count this bank */
+
+ return size;
+}
+
+void s3c24xx_disable_second_sdram_bank(void)
+{
+ writel(readl(S3C_BANKCON7) & ~(0x3 << 15), S3C_BANKCON7);
+ writel(readl(S3C_MISCCR) | (1 << 18), S3C_MISCCR); /* disable its clock */
+}
+
+#define S3C_WTCON (S3C_WATCHDOG_BASE)
+#define S3C_WTDAT (S3C_WATCHDOG_BASE + 0x04)
+#define S3C_WTCNT (S3C_WATCHDOG_BASE + 0x08)
+
+void __noreturn reset_cpu(unsigned long addr)
+{
+ /* Disable watchdog */
+ writew(0x0000, S3C_WTCON);
+
+ /* Initialize watchdog timer count register */
+ writew(0x0001, S3C_WTCNT);
+
+ /* Enable watchdog timer; assert reset at timer timeout */
+ writew(0x0021, S3C_WTCON);
+
+ /* loop forever and wait for reset to happen */
+ while(1)
+ ;
+}
+EXPORT_SYMBOL(reset_cpu);
+
+/**
+
+@page dev_s3c24xx_arch Samsung's S3C24xx Platforms in barebox
+
+@section s3c24xx_boards Boards using S3C24xx Processors
+
+@li @subpage arch/arm/boards/a9m2410/a9m2410.c
+@li @subpage arch/arm/boards/a9m2440/a9m2440.c
+
+@section s3c24xx_arch Documentation for S3C24xx Architectures Files
+
+@li @subpage arch/arm/mach-s3c24xx/generic.c
+
+@section s3c24xx_mem_map SDRAM Memory Map
+
+SDRAM starts at address 0x3000.0000 up to the available amount of connected
+SDRAM memory. Physically this CPU can handle up to 256MiB (two areas with
+up to 128MiB each).
+
+@subsection s3c24xx_mem_generic_map Generic Map
+- 0x0000.0000 Start of the internal SRAM when booting from NAND flash memory or CS signal to a NOR flash memory.
+- 0x0800.0000 Start of I/O space.
+- 0x3000.0000 Start of SDRAM area.
+ - 0x3000.0100 Start of the TAG list area.
+ - 0x3000.8000 Start of the linux kernel (physical address).
+- 0x4000.0000 Start of internal SRAM, when booting from NOR flash memory
+- 0x4800.0000 Start of the internal I/O area
+
+@section s3c24xx_asm_arm include/asm-arm/arch-s3c24xx directory guidelines
+All S3C24xx common headers are located here.
+
+@note Do not add board specific header files/information here.
+*/
+
+/** @page dev_s3c24xx_mach Samsung's S3C24xx based platforms
+
+@par barebox Map
+
+The location of the @a barebox itself depends on the available amount of
+installed SDRAM memory:
+
+- 0x30fc.0000 Start of @a barebox when 16MiB SDRAM is available
+- 0x31fc.0000 Start of @a barebox when 32MiB SDRAM is available
+- 0x33fc.0000 Start of @a barebox when 64MiB SDRAM is available
+
+Adjust the @p CONFIG_TEXT_BASE/CONFIG_ARCH_TEXT_BASE symbol in accordance to
+the available memory.
+
+@note The RAM based filesystem and the stack resides always below the
+@a barebox start address.
+
+@li @subpage dev_s3c24xx_wd_handling
+@li @subpage dev_s3c24xx_pll_handling
+@li @subpage dev_s3c24xx_sdram_handling
+@li @subpage dev_s3c24xx_nandboot_handling
+*/
diff --git a/arch/arm/mach-s3c24xx/gpio-s3c24x0.c b/arch/arm/mach-samsung/gpio-s3c24x0.c
index 946ec3396e..4f1c5cca85 100644
--- a/arch/arm/mach-s3c24xx/gpio-s3c24x0.c
+++ b/arch/arm/mach-samsung/gpio-s3c24x0.c
@@ -18,8 +18,9 @@
#include <common.h>
#include <errno.h>
#include <io.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
#include <mach/gpio.h>
+#include <mach/s3c24xx-gpio.h>
static const unsigned char group_offset[] =
{
@@ -45,10 +46,10 @@ void gpio_set_value(unsigned gpio, int value)
offset = group_offset[group];
- reg = readl(GPADAT + offset);
+ reg = readl(S3C_GPADAT + offset);
reg &= ~(1 << bit);
reg |= (!!value) << bit;
- writel(reg, GPADAT + offset);
+ writel(reg, S3C_GPADAT + offset);
}
int gpio_direction_input(unsigned gpio)
@@ -60,9 +61,9 @@ int gpio_direction_input(unsigned gpio)
offset = group_offset[group];
- reg = readl(GPACON + offset);
+ reg = readl(S3C_GPACON + offset);
reg &= ~(0x3 << (bit << 1));
- writel(reg, GPACON + offset);
+ writel(reg, S3C_GPACON + offset);
return 0;
}
@@ -81,14 +82,14 @@ int gpio_direction_output(unsigned gpio, int value)
gpio_set_value(gpio,value);
/* direction */
if (group == 0) { /* GPA is special */
- reg = readl(GPACON);
+ reg = readl(S3C_GPACON);
reg &= ~(1 << bit);
- writel(reg, GPACON);
+ writel(reg, S3C_GPACON);
} else {
- reg = readl(GPACON + offset);
+ reg = readl(S3C_GPACON + offset);
reg &= ~(0x3 << (bit << 1));
reg |= 0x1 << (bit << 1);
- writel(reg, GPACON + offset);
+ writel(reg, S3C_GPACON + offset);
}
return 0;
@@ -107,7 +108,7 @@ int gpio_get_value(unsigned gpio)
offset = group_offset[group];
/* value */
- reg = readl(GPADAT + offset);
+ reg = readl(S3C_GPADAT + offset);
return !!(reg & (1 << bit));
}
@@ -132,9 +133,9 @@ void s3c_gpio_mode(unsigned gpio_mode)
gpio_direction_output(bit, GET_GPIOVAL(gpio_mode));
break;
default:
- reg = readl(GPACON);
+ reg = readl(S3C_GPACON);
reg |= 1 << bit;
- writel(reg, GPACON);
+ writel(reg, S3C_GPACON);
break;
}
return;
@@ -143,12 +144,12 @@ void s3c_gpio_mode(unsigned gpio_mode)
offset = group_offset[group];
if (PU_PRESENT(gpio_mode)) {
- reg = readl(GPACON + offset + 8);
+ reg = readl(S3C_GPACON + offset + 8);
if (GET_PU(gpio_mode))
reg |= (1 << bit); /* set means _disabled_ */
else
reg &= ~(1 << bit);
- writel(reg, GPACON + offset + 8);
+ writel(reg, S3C_GPACON + offset + 8);
}
switch (func) {
@@ -160,10 +161,10 @@ void s3c_gpio_mode(unsigned gpio_mode)
break;
case 2: /* function one */
case 3: /* function two */
- reg = readl(GPACON + offset);
+ reg = readl(S3C_GPACON + offset);
reg &= ~(0x3 << (bit << 1));
reg |= func << (bit << 1);
- writel(reg, GPACON + offset);
+ writel(reg, S3C_GPACON + offset);
break;
}
}
diff --git a/arch/arm/mach-s3c24xx/include/mach/gpio.h b/arch/arm/mach-samsung/include/mach/gpio.h
index 37db4f55fc..372339490c 100644
--- a/arch/arm/mach-s3c24xx/include/mach/gpio.h
+++ b/arch/arm/mach-samsung/include/mach/gpio.h
@@ -8,17 +8,12 @@
* 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 __ASM_MACH_GPIO_H
#define __ASM_MACH_GPIO_H
-#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2410)
+#ifdef CONFIG_ARCH_S3C24xx
# include <mach/iomux-s3c24x0.h>
#endif
diff --git a/arch/arm/mach-s3c24xx/include/mach/iomux-s3c24x0.h b/arch/arm/mach-samsung/include/mach/iomux-s3c24x0.h
index 2c64a979df..2c64a979df 100644
--- a/arch/arm/mach-s3c24xx/include/mach/iomux-s3c24x0.h
+++ b/arch/arm/mach-samsung/include/mach/iomux-s3c24x0.h
diff --git a/arch/arm/mach-samsung/include/mach/s3c-busctl.h b/arch/arm/mach-samsung/include/mach/s3c-busctl.h
new file mode 100644
index 0000000000..4bcf0a7013
--- /dev/null
+++ b/arch/arm/mach-samsung/include/mach/s3c-busctl.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2011 Juergen Beisert, Pengutronix
+ *
+ * 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.
+ */
+
+#ifndef __MACH_S3C_BUSCTL_H
+# define __MACH_S3C_BUSCTL_H
+
+#define S3C_BWSCON (S3C_MEMCTL_BASE)
+#define S3C_BANKCON0 (S3C_MEMCTL_BASE + 0x04)
+#define S3C_BANKCON1 (S3C_MEMCTL_BASE + 0x08)
+#define S3C_BANKCON2 (S3C_MEMCTL_BASE + 0x0c)
+#define S3C_BANKCON3 (S3C_MEMCTL_BASE + 0x10)
+#define S3C_BANKCON4 (S3C_MEMCTL_BASE + 0x14)
+#define S3C_BANKCON5 (S3C_MEMCTL_BASE + 0x18)
+#define S3C_BANKCON6 (S3C_MEMCTL_BASE + 0x1c)
+#define S3C_BANKCON7 (S3C_MEMCTL_BASE + 0x20)
+#define S3C_REFRESH (S3C_MEMCTL_BASE + 0x24)
+#define S3C_BANKSIZE (S3C_MEMCTL_BASE + 0x28)
+#define S3C_MRSRB6 (S3C_MEMCTL_BASE + 0x2c)
+#define S3C_MRSRB7 (S3C_MEMCTL_BASE + 0x30)
+
+#endif /* __MACH_S3C_BUSCTL_H */
diff --git a/arch/arm/mach-samsung/include/mach/s3c-clocks.h b/arch/arm/mach-samsung/include/mach/s3c-clocks.h
new file mode 100644
index 0000000000..44b2a6c8ee
--- /dev/null
+++ b/arch/arm/mach-samsung/include/mach/s3c-clocks.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2011 Juergen Beisert, Pengutronix
+ *
+ * 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.
+ */
+
+#ifndef __MACH_S3C_CLOCKS_H
+# define __MACH_S3C_CLOCKS_H
+
+#ifdef CONFIG_ARCH_S3C24xx
+# define S3C_LOCKTIME (S3C_CLOCK_POWER_BASE)
+# define S3C_MPLLCON (S3C_CLOCK_POWER_BASE + 0x4)
+# define S3C_UPLLCON (S3C_CLOCK_POWER_BASE + 0x8)
+# define S3C_CLKCON (S3C_CLOCK_POWER_BASE + 0xc)
+# define S3C_CLKSLOW (S3C_CLOCK_POWER_BASE + 0x10)
+# define S3C_CLKDIVN (S3C_CLOCK_POWER_BASE + 0x14)
+
+# define S3C_MPLLCON_GET_MDIV(x) ((((x) >> 12) & 0xff) + 8)
+# define S3C_MPLLCON_GET_PDIV(x) ((((x) >> 4) & 0x3f) + 2)
+# define S3C_MPLLCON_GET_SDIV(x) ((x) & 0x3)
+#endif
+
+#endif /* __MACH_S3C_CLOCKS_H */
diff --git a/arch/arm/mach-s3c24xx/include/mach/s3c24xx-generic.h b/arch/arm/mach-samsung/include/mach/s3c-generic.h
index b8abcf1d9c..4ea3dd7ea4 100644
--- a/arch/arm/mach-s3c24xx/include/mach/s3c24xx-generic.h
+++ b/arch/arm/mach-samsung/include/mach/s3c-generic.h
@@ -24,10 +24,11 @@
* MA 02111-1307 USA
*/
-uint32_t s3c24xx_get_mpllclk(void);
-uint32_t s3c24xx_get_upllclk(void);
-uint32_t s3c24xx_get_fclk(void);
-uint32_t s3c24xx_get_hclk(void);
-uint32_t s3c24xx_get_pclk(void);
-uint32_t s3c24xx_get_uclk(void);
-uint32_t s3c24x0_get_memory_size(void);
+uint32_t s3c_get_mpllclk(void);
+uint32_t s3c_get_upllclk(void);
+uint32_t s3c_get_fclk(void);
+uint32_t s3c_get_hclk(void);
+uint32_t s3c_get_pclk(void);
+uint32_t s3c_get_uclk(void);
+uint32_t s3c24xx_get_memory_size(void);
+void s3c24xx_disable_second_sdram_bank(void);
diff --git a/arch/arm/mach-samsung/include/mach/s3c-iomap.h b/arch/arm/mach-samsung/include/mach/s3c-iomap.h
new file mode 100644
index 0000000000..9e867f8a34
--- /dev/null
+++ b/arch/arm/mach-samsung/include/mach/s3c-iomap.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 Juergen Beisert, Pengutronix
+ *
+ * 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
+ *
+ */
+
+/* S3C2410 device base addresses */
+#define S3C_MEMCTL_BASE 0x48000000
+#define S3C2410_USB_HOST_BASE 0x49000000
+#define S3C2410_INTERRUPT_BASE 0x4A000000
+#define S3C2410_DMA_BASE 0x4B000000
+#define S3C_CLOCK_POWER_BASE 0x4C000000
+#define S3C2410_LCD_BASE 0x4D000000
+#define S3C24X0_NAND_BASE 0x4E000000
+#define S3C_UART_BASE 0x50000000
+#define S3C_TIMER_BASE 0x51000000
+#define S3C2410_USB_DEVICE_BASE 0x52000140
+#define S3C_WATCHDOG_BASE 0x53000000
+#define S3C2410_I2C_BASE 0x54000000
+#define S3C2410_I2S_BASE 0x55000000
+#define S3C_GPIO_BASE 0x56000000
+#define S3C2410_RTC_BASE 0x57000000
+#define S3C2410_ADC_BASE 0x58000000
+#define S3C2410_SPI_BASE 0x59000000
+#define S3C2410_SDI_BASE 0x5A000000
+
+/* external IO space */
+#define S3C_CS0_BASE 0x00000000
+#define S3C_CS1_BASE 0x08000000
+#define S3C_CS2_BASE 0x10000000
+#define S3C_CS3_BASE 0x18000000
+#define S3C_CS4_BASE 0x20000000
+#define S3C_CS5_BASE 0x28000000
+#define S3C_CS6_BASE 0x30000000
+
+#define S3C_SDRAM_BASE S3C_CS6_BASE
+#define S3C_SDRAM_END (S3C_SDRAM_BASE + 0x10000000)
+
+/*
+ * if we are booting from NAND, its internal SRAM occures at
+ * a different address than without this feature
+ */
+#ifdef CONFIG_S3C24XX_NAND_BOOT
+# define NFC_RAM_AREA 0x00000000
+#else
+# define NFC_RAM_AREA 0x40000000
+#endif
+#define NFC_RAM_SIZE 4096
+
+#define S3C_UART1_BASE (S3C_UART_BASE)
+#define S3C_UART1_SIZE 0x4000
+#define S3C_UART2_BASE (S3C_UART_BASE + 0x4000)
+#define S3C_UART2_SIZE 0x4000
+#define S3C_UART3_BASE (S3C_UART_BASE + 0x8000)
+#define S3C_UART3_SIZE 0x4000
diff --git a/arch/arm/mach-s3c24xx/include/mach/mci.h b/arch/arm/mach-samsung/include/mach/s3c-mci.h
index 6ba8961693..6ba8961693 100644
--- a/arch/arm/mach-s3c24xx/include/mach/mci.h
+++ b/arch/arm/mach-samsung/include/mach/s3c-mci.h
diff --git a/arch/arm/mach-s3c24xx/include/mach/fb.h b/arch/arm/mach-samsung/include/mach/s3c24xx-fb.h
index 05e013aadb..05e013aadb 100644
--- a/arch/arm/mach-s3c24xx/include/mach/fb.h
+++ b/arch/arm/mach-samsung/include/mach/s3c24xx-fb.h
diff --git a/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h b/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h
new file mode 100644
index 0000000000..c83597410c
--- /dev/null
+++ b/arch/arm/mach-samsung/include/mach/s3c24xx-gpio.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2011 Juergen Beisert, Pengutronix
+ *
+ * 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.
+ */
+
+#ifndef __MACH_S3C24XX_GPIO_H
+# define __MACH_S3C24XX_GPIO_H
+
+#define S3C_GPACON (S3C_GPIO_BASE)
+#define S3C_GPADAT (S3C_GPIO_BASE + 0x04)
+
+#define S3C_GPBCON (S3C_GPIO_BASE + 0x10)
+#define S3C_GPBDAT (S3C_GPIO_BASE + 0x14)
+#define S3C_GPBUP (S3C_GPIO_BASE + 0x18)
+
+#define S3C_GPCCON (S3C_GPIO_BASE + 0x20)
+#define S3C_GPCDAT (S3C_GPIO_BASE + 0x24)
+#define S3C_GPCUP (S3C_GPIO_BASE + 0x28)
+
+#define S3C_GPDCON (S3C_GPIO_BASE + 0x30)
+#define S3C_GPDDAT (S3C_GPIO_BASE + 0x34)
+#define S3C_GPDUP (S3C_GPIO_BASE + 0x38)
+
+#define S3C_GPECON (S3C_GPIO_BASE + 0x40)
+#define S3C_GPEDAT (S3C_GPIO_BASE + 0x44)
+#define S3C_GPEUP (S3C_GPIO_BASE + 0x48)
+
+#define S3C_GPFCON (S3C_GPIO_BASE + 0x50)
+#define S3C_GPFDAT (S3C_GPIO_BASE + 0x54)
+#define S3C_GPFUP (S3C_GPIO_BASE + 0x58)
+
+#define S3C_GPGCON (S3C_GPIO_BASE + 0x60)
+#define S3C_GPGDAT (S3C_GPIO_BASE + 0x64)
+#define S3C_GPGUP (S3C_GPIO_BASE + 0x68)
+
+#define S3C_GPHCON (S3C_GPIO_BASE + 0x70)
+#define S3C_GPHDAT (S3C_GPIO_BASE + 0x74)
+#define S3C_GPHUP (S3C_GPIO_BASE + 0x78)
+
+#ifdef CONFIG_CPU_S3C2440
+# define S3C_GPJCON (S3C_GPIO_BASE + 0xd0)
+# define S3C_GPJDAT (S3C_GPIO_BASE + 0xd4)
+# define S3C_GPJUP (S3C_GPIO_BASE + 0xd8)
+#endif
+
+#define S3C_MISCCR (S3C_GPIO_BASE + 0x80)
+#define S3C_DCLKCON (S3C_GPIO_BASE + 0x84)
+#define S3C_EXTINT0 (S3C_GPIO_BASE + 0x88)
+#define S3C_EXTINT1 (S3C_GPIO_BASE + 0x8c)
+#define S3C_EXTINT2 (S3C_GPIO_BASE + 0x90)
+#define S3C_EINTFLT0 (S3C_GPIO_BASE + 0x94)
+#define S3C_EINTFLT1 (S3C_GPIO_BASE + 0x98)
+#define S3C_EINTFLT2 (S3C_GPIO_BASE + 0x9c)
+#define S3C_EINTFLT3 (S3C_GPIO_BASE + 0xa0)
+#define S3C_EINTMASK (S3C_GPIO_BASE + 0xa4)
+#define S3C_EINTPEND (S3C_GPIO_BASE + 0xa8)
+#define S3C_GSTATUS0 (S3C_GPIO_BASE + 0xac)
+#define S3C_GSTATUS1 (S3C_GPIO_BASE + 0xb0)
+#define S3C_GSTATUS2 (S3C_GPIO_BASE + 0xb4)
+#define S3C_GSTATUS3 (S3C_GPIO_BASE + 0xb8)
+#define S3C_GSTATUS4 (S3C_GPIO_BASE + 0xbc)
+
+#ifdef CONFIG_CPU_S3C2440
+# define S3C_DSC0 (S3C_GPIO_BASE + 0xc4)
+# define S3C_DSC1 (S3C_GPIO_BASE + 0xc8)
+#endif
+
+#endif /* __MACH_S3C24XX_GPIO_H */
diff --git a/arch/arm/mach-s3c24xx/include/mach/s3c24x0-nand.h b/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h
index 7610b4e29d..7610b4e29d 100644
--- a/arch/arm/mach-s3c24xx/include/mach/s3c24x0-nand.h
+++ b/arch/arm/mach-samsung/include/mach/s3c24xx-nand.h
diff --git a/arch/arm/mach-s3c24xx/lowlevel-init.S b/arch/arm/mach-samsung/lowlevel-init.S
index e8004e588c..31c619609f 100644
--- a/arch/arm/mach-s3c24xx/lowlevel-init.S
+++ b/arch/arm/mach-samsung/lowlevel-init.S
@@ -19,7 +19,7 @@
*/
#include <config.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-iomap.h>
.section ".text_bare_init.s3c24x0_disable_wd","ax"
@@ -29,7 +29,7 @@
.globl s3c24x0_disable_wd
s3c24x0_disable_wd:
- ldr r0, =S3C24X0_WATCHDOG_BASE
+ ldr r0, =S3C_WATCHDOG_BASE
mov r1, #0x0
str r1, [r0]
mov pc, lr
@@ -77,7 +77,7 @@ routine very early in your board_init_lowlevel routine.
.globl s3c24x0_pll_init
s3c24x0_pll_init:
- mov r0, #S3C24X0_CLOCK_POWER_BASE
+ mov r0, #S3C_CLOCK_POWER_BASE
/* configure internal clock ratio */
mov r1, #BOARD_SPECIFIC_CLKDIVN
@@ -192,7 +192,7 @@ With m = MDIV + 8, p = PDIV + 2 and s = SDIV.
s3c24x0_sdram_init:
adr r0, SDRAMDATA /* get the current relative address of the table */
- mov r1, #S3C24X0_MEMCTL_BASE
+ mov r1, #S3C_MEMCTL_BASE
mov r2, #6 /* we *know* it contains 6 entries */
ldr r3, [r0], #4 /* write BSWCON first */
@@ -255,7 +255,7 @@ s3c24x0_nand_boot:
* In the case of NOR boot we are running from the same address space.
* Detect this case to handle it correctly.
*/
- mov r1, #S3C24X0_MEMCTL_BASE
+ mov r1, #S3C_MEMCTL_BASE
ldr r3, [r1]
and r3, r3, #0x6
cmp r3, #0x0 /* check for NAND case */
diff --git a/arch/arm/mach-samsung/s3c-timer.c b/arch/arm/mach-samsung/s3c-timer.c
new file mode 100644
index 0000000000..6665c8c3d5
--- /dev/null
+++ b/arch/arm/mach-samsung/s3c-timer.c
@@ -0,0 +1,114 @@
+/*
+ * 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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <io.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c-generic.h>
+
+#define S3C_TCFG0 (S3C_TIMER_BASE + 0x00)
+# define S3C_TCFG0_T4MASK 0xff00
+# define S3C_TCFG0_SET_PSCL234(x) ((x) << 8)
+# define S3C_TCFG0_GET_PSCL234(x) (((x) >> 8) & 0xff)
+#define S3C_TCFG1 (S3C_TIMER_BASE + 0x04)
+# define S3C_TCFG1_T4MASK 0xf0000
+# define S3C_TCFG1_SET_T4MUX(x) ((x) << 16)
+# define S3C_TCFG1_GET_T4MUX(x) (((x) >> 16) & 0xf)
+#define S3C_TCON (S3C_TIMER_BASE + 0x08)
+# define S3C_TCON_T4MASK (7 << 20)
+# define S3C_TCON_T4START (1 << 20)
+# define S3C_TCON_T4MANUALUPD (1 << 21)
+# define S3C_TCON_T4RELOAD (1 <<22)
+#define S3C_TCNTB4 (S3C_TIMER_BASE + 0x3c)
+#define S3C_TCNTO4 (S3C_TIMER_BASE + 0x40)
+
+#define TIMER_WIDTH 16
+#define TIMER_SHIFT 10
+#define PRE_MUX 3
+#define PRE_MUX_ADD 1
+static const uint32_t max = 0x0000ffff;
+
+static void s3c_init_t4_clk_source(void)
+{
+ unsigned reg;
+
+ reg = readl(S3C_TCON) & ~S3C_TCON_T4MASK; /* stop timer 4 */
+ writel(reg, S3C_TCON);
+ reg = readl(S3C_TCFG0) & ~S3C_TCFG0_T4MASK;
+ reg |= S3C_TCFG0_SET_PSCL234(0); /* 0 means pre scaler is '256' */
+ writel(reg, S3C_TCFG0);
+ reg = readl(S3C_TCFG1) & ~S3C_TCFG1_T4MASK;
+ reg |= S3C_TCFG1_SET_T4MUX(PRE_MUX); /* / 16 */
+ writel(reg, S3C_TCFG1);
+}
+
+static unsigned s3c_get_t4_clk(void)
+{
+ unsigned clk = s3c_get_pclk();
+ unsigned pre = S3C_TCFG0_GET_PSCL234(readl(S3C_TCFG0)) + 1;
+ unsigned div = S3C_TCFG1_GET_T4MUX(readl(S3C_TCFG1)) + PRE_MUX_ADD;
+
+ return clk / pre / (1 << div);
+}
+
+static void s3c_timer_init(void)
+{
+ unsigned tcon;
+
+ tcon = readl(S3C_TCON) & ~S3C_TCON_T4MASK;
+
+ writel(max, S3C_TCNTB4); /* reload value */
+ /* force a manual counter update */
+ writel(tcon | S3C_TCON_T4MANUALUPD, S3C_TCON);
+}
+
+static void s3c_timer_start(void)
+{
+ unsigned tcon;
+
+ tcon = readl(S3C_TCON) & ~S3C_TCON_T4MANUALUPD;
+ tcon |= S3C_TCON_T4START | S3C_TCON_T4RELOAD;
+ writel(tcon, S3C_TCON);
+}
+
+static uint64_t s3c_clocksource_read(void)
+{
+ /* note: its a down counter */
+ return max - readl(S3C_TCNTO4);
+}
+
+static struct clocksource cs = {
+ .read = s3c_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(TIMER_WIDTH),
+ .shift = TIMER_SHIFT,
+};
+
+static int s3c_clk_src_init(void)
+{
+ /* select its clock source first */
+ s3c_init_t4_clk_source();
+
+ s3c_timer_init();
+ s3c_timer_start();
+
+ cs.mult = clocksource_hz2mult(s3c_get_t4_clk(), cs.shift);
+ init_clock(&cs);
+
+ return 0;
+}
+core_initcall(s3c_clk_src_init);
diff --git a/arch/arm/mach-samsung/s3c24xx-clocks.c b/arch/arm/mach-samsung/s3c24xx-clocks.c
new file mode 100644
index 0000000000..a99d1b9d18
--- /dev/null
+++ b/arch/arm/mach-samsung/s3c24xx-clocks.c
@@ -0,0 +1,140 @@
+/*
+ * 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.
+ */
+
+#include <config.h>
+#include <common.h>
+#include <init.h>
+#include <clock.h>
+#include <io.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-clocks.h>
+#include <mach/s3c-busctl.h>
+
+/**
+ * Calculate the current M-PLL clock.
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_mpllclk(void)
+{
+ uint32_t m, p, s, reg_val;
+
+ reg_val = readl(S3C_MPLLCON);
+ m = ((reg_val & 0xFF000) >> 12) + 8;
+ p = ((reg_val & 0x003F0) >> 4) + 2;
+ s = reg_val & 0x3;
+#ifdef CONFIG_CPU_S3C2410
+ return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
+#endif
+#ifdef CONFIG_CPU_S3C2440
+ return 2 * m * (S3C24XX_CLOCK_REFERENCE / (p << s));
+#endif
+}
+
+/**
+ * Calculate the current U-PLL clock
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_upllclk(void)
+{
+ uint32_t m, p, s, reg_val;
+
+ reg_val = readl(S3C_UPLLCON);
+ m = ((reg_val & 0xFF000) >> 12) + 8;
+ p = ((reg_val & 0x003F0) >> 4) + 2;
+ s = reg_val & 0x3;
+
+ return (S3C24XX_CLOCK_REFERENCE * m) / (p << s);
+}
+
+/**
+ * Calculate the FCLK frequency used for the ARM CPU core
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_fclk(void)
+{
+ return s3c_get_mpllclk();
+}
+
+/**
+ * Calculate the HCLK frequency used for the AHB bus (CPU to main peripheral)
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_hclk(void)
+{
+ uint32_t f_clk;
+
+ f_clk = s3c_get_fclk();
+#ifdef CONFIG_CPU_S3C2410
+ if (readl(S3C_CLKDIVN) & 0x02)
+ return f_clk >> 1;
+#endif
+#ifdef CONFIG_CPU_S3C2440
+ switch(readl(S3C_CLKDIVN) & 0x06) {
+ case 2:
+ return f_clk >> 1;
+ case 4:
+ return f_clk >> 2; /* TODO consider CAMDIVN */
+ case 6:
+ return f_clk / 3; /* TODO consider CAMDIVN */
+ }
+#endif
+ return f_clk;
+}
+
+/**
+ * Calculate the PCLK frequency used for the slower peripherals
+ * @return Current frequency in Hz
+ */
+uint32_t s3c_get_pclk(void)
+{
+ uint32_t p_clk;
+
+ p_clk = s3c_get_hclk();
+ if (readl(S3C_CLKDIVN) & 0x01)
+ return p_clk >> 1;
+ return p_clk;
+}
+
+/**
+ * Calculate the UCLK frequency used by the USB host device
+ * @return Current frequency in Hz
+ */
+uint32_t s3c24_get_uclk(void)
+{
+ return s3c_get_upllclk();
+}
+
+/**
+ * Show the user the current clock settings
+ */
+int s3c24xx_dump_clocks(void)
+{
+ printf("refclk: %7d kHz\n", S3C24XX_CLOCK_REFERENCE / 1000);
+ printf("mpll: %7d kHz\n", s3c_get_mpllclk() / 1000);
+ printf("upll: %7d kHz\n", s3c_get_upllclk() / 1000);
+ printf("fclk: %7d kHz\n", s3c_get_fclk() / 1000);
+ printf("hclk: %7d kHz\n", s3c_get_hclk() / 1000);
+ printf("pclk: %7d kHz\n", s3c_get_pclk() / 1000);
+ printf("SDRAM1: CL%d@%dMHz\n", ((readl(S3C_BANKCON6) & 0xc) >> 2) + 2,
+ s3c_get_hclk() / 1000000);
+ if ((readl(S3C_BANKCON7) & (0x3 << 15)) == (0x3 << 15))
+ printf("SDRAM2: CL%d@%dMHz\n",
+ ((readl(S3C_BANKCON7) & 0xc) >> 2) + 2,
+ s3c_get_hclk() / 1000000);
+ return 0;
+}
+
+late_initcall(s3c24xx_dump_clocks);
diff --git a/arch/arm/tools/mach-types b/arch/arm/tools/mach-types
index d5930268c8..38e901dacb 100644
--- a/arch/arm/tools/mach-types
+++ b/arch/arm/tools/mach-types
@@ -12,7 +12,7 @@
#
# http://www.arm.linux.org.uk/developer/machines/?action=new
#
-# Last update: Tue Dec 6 15:54:16 2011
+# Last update: Thu Jan 5 07:57:22 2012
#
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
#
@@ -2814,7 +2814,7 @@ omap3_braillo MACH_OMAP3_BRAILLO OMAP3_BRAILLO 2839
spyplug MACH_SPYPLUG SPYPLUG 2840
ginger MACH_GINGER GINGER 2841
tny_t3530 MACH_TNY_T3530 TNY_T3530 2842
-pca102 MACH_PCA102 PCA102 2843
+pcaal1 MACH_PCAAL1 PCAAL1 2843
spade MACH_SPADE SPADE 2844
mxc25_topaz MACH_MXC25_TOPAZ MXC25_TOPAZ 2845
t5325 MACH_T5325 T5325 2846
@@ -3664,7 +3664,7 @@ promwad_jade MACH_PROMWAD_JADE PROMWAD_JADE 3708
amp MACH_AMP AMP 3709
gnet_amp MACH_GNET_AMP GNET_AMP 3710
toques MACH_TOQUES TOQUES 3711
-apx4devkit MACH_APX4 APX4 3712
+apx4devkit MACH_APX4DEVKIT APX4DEVKIT 3712
dct_storm MACH_DCT_STORM DCT_STORM 3713
dm8168z3 MACH_Z3 Z3 3714
owl MACH_OWL OWL 3715
@@ -3843,3 +3843,63 @@ elite_ulk MACH_ELITE_ULK ELITE_ULK 3888
pov2 MACH_POV2 POV2 3889
ipod_touch_2g MACH_IPOD_TOUCH_2G IPOD_TOUCH_2G 3890
da850_pqab MACH_DA850_PQAB DA850_PQAB 3891
+fermi MACH_FERMI FERMI 3892
+ccardwmx28 MACH_CCARDWMX28 CCARDWMX28 3893
+ccardmx28 MACH_CCARDMX28 CCARDMX28 3894
+fs20_fcm2050 MACH_FS20_FCM2050 FS20_FCM2050 3895
+kinetis MACH_KINETIS KINETIS 3896
+kai MACH_KAI KAI 3897
+bcthb2 MACH_BCTHB2 BCTHB2 3898
+inels3_cu MACH_INELS3_CU INELS3_CU 3899
+da850_juniper MACH_JUNIPER JUNIPER 3900
+da850_apollo MACH_DA850_APOLLO DA850_APOLLO 3901
+tracnas MACH_TRACNAS TRACNAS 3902
+mityarm335x MACH_MITYARM335X MITYARM335X 3903
+xcgz7x MACH_XCGZ7X XCGZ7X 3904
+cubox MACH_CUBOX CUBOX 3905
+terminator MACH_TERMINATOR TERMINATOR 3906
+eye03 MACH_EYE03 EYE03 3907
+kota3 MACH_KOTA3 KOTA3 3908
+mx53_nitrogen_k MACH_MX5 MX5 3909
+pscpe MACH_PSCPE PSCPE 3910
+akt1100 MACH_AKT1100 AKT1100 3911
+pcaaxl2 MACH_PCAAXL2 PCAAXL2 3912
+primodd_ct MACH_PRIMODD_CT PRIMODD_CT 3913
+nsbc MACH_NSBC NSBC 3914
+meson2_skt MACH_MESON2_SKT MESON2_SKT 3915
+meson2_ref MACH_MESON2_REF MESON2_REF 3916
+ccardwmx28js MACH_CCARDWMX28JS CCARDWMX28JS 3917
+ccardmx28js MACH_CCARDMX28JS CCARDMX28JS 3918
+indico MACH_INDICO INDICO 3919
+msm8960dt MACH_MSM8960DT MSM8960DT 3920
+primods MACH_PRIMODS PRIMODS 3921
+beluga_m1388 MACH_BELUGA_M1388 BELUGA_M1388 3922
+primotd MACH_PRIMOTD PRIMOTD 3923
+varan_master MACH_VARAN_MASTER VARAN_MASTER 3924
+primodd MACH_PRIMODD PRIMODD 3925
+jetduo MACH_JETDUO JETDUO 3926
+mx53_umobo MACH_MX53_UMOBO MX53_UMOBO 3927
+trats MACH_TRATS TRATS 3928
+starcraft MACH_STARCRAFT STARCRAFT 3929
+qseven_tegra2 MACH_QSEVEN_TEGRA2 QSEVEN_TEGRA2 3930
+lichee_sun4i_devbd MACH_LICHEE_SUN4I_DEVBD LICHEE_SUN4I_DEVBD 3931
+movenow MACH_MOVENOW MOVENOW 3932
+golf_u MACH_GOLF_U GOLF_U 3933
+msm7627a_evb MACH_MSM7627A_EVB MSM7627A_EVB 3934
+rambo MACH_RAMBO RAMBO 3935
+golfu MACH_GOLFU GOLFU 3936
+mango310 MACH_MANGO310 MANGO310 3937
+dns343 MACH_DNS343 DNS343 3938
+var_som_om44 MACH_VAR_SOM_OM44 VAR_SOM_OM44 3939
+naon MACH_NAON NAON 3940
+vp4000 MACH_VP4000 VP4000 3941
+impcard MACH_IMPCARD IMPCARD 3942
+smoovcam MACH_SMOOVCAM SMOOVCAM 3943
+cobham3725 MACH_COBHAM3725 COBHAM3725 3944
+cobham3730 MACH_COBHAM3730 COBHAM3730 3945
+cobham3703 MACH_COBHAM3703 COBHAM3703 3946
+quetzal MACH_QUETZAL QUETZAL 3947
+apq8064_cdp MACH_APQ8064_CDP APQ8064_CDP 3948
+apq8064_mtp MACH_APQ8064_MTP APQ8064_MTP 3949
+apq8064_fluid MACH_APQ8064_FLUID APQ8064_FLUID 3950
+apq8064_liquid MACH_APQ8064_LIQUID APQ8064_LIQUID 3951
diff --git a/arch/blackfin/lib/blackfin_linux.c b/arch/blackfin/lib/blackfin_linux.c
index 9da9ec4e58..458d1b180b 100644
--- a/arch/blackfin/lib/blackfin_linux.c
+++ b/arch/blackfin/lib/blackfin_linux.c
@@ -34,6 +34,7 @@
#include <asm/byteorder.h>
#include <asm/cpu.h>
#include <asm/blackfin.h>
+#include <errno.h>
#include <init.h>
#include <boot.h>
@@ -44,10 +45,11 @@ static int do_bootm_linux(struct image_data *idata)
int (*appl)(char *cmdline);
const char *cmdline = getenv("bootargs");
char *cmdlinedest = (char *) CMD_LINE_ADDR;
- struct image_handle *os_handle = idata->os;
- image_header_t *os_header = &os_handle->header;
- appl = (int (*)(char *))image_get_ep(os_header);
+ if (!idata->os_res)
+ return -EINVAL;
+
+ appl = (void *)(idata->os_address + idata->os_entry);
printf("Starting Kernel at 0x%p\n", appl);
icache_disable();
@@ -63,8 +65,10 @@ static int do_bootm_linux(struct image_data *idata)
}
static struct image_handler handler = {
+ .name = "Blackfin Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
static int bfinlinux_register_image_handler(void)
diff --git a/arch/nios2/boards/generic/env/config b/arch/nios2/boards/generic/env/config
index 5d23098390..16adc49f1c 100644
--- a/arch/nios2/boards/generic/env/config
+++ b/arch/nios2/boards/generic/env/config
@@ -5,7 +5,6 @@ kernel=flash
root=flash
kernel_loc=nor
-kernelimage_type=uimage
# use 'dhcp' todo dhcp in barebox and in kernel
ip=none
diff --git a/arch/nios2/lib/bootm.c b/arch/nios2/lib/bootm.c
index b5b344f499..1cd43c81af 100644
--- a/arch/nios2/lib/bootm.c
+++ b/arch/nios2/lib/bootm.c
@@ -31,17 +31,20 @@
#include <environment.h>
#include <init.h>
#include <boot.h>
+#include <errno.h>
#include <asm/cache.h>
#define NIOS_MAGIC 0x534f494e /* enable command line and initrd passing */
static int do_bootm_linux(struct image_data *idata)
{
- image_header_t *os_header = &idata->os->header;
void (*kernel)(int, int, int, const char *);
const char *commandline = getenv ("bootargs");
- kernel = (void (*)(int, int, int, const char *))ntohl(os_header->ih_ep);
+ if (!idata->os_res)
+ return -EINVAL;
+
+ kernel = (void *)(idata->os_address + idata->os_entry);
/* kernel parameters passing
* r4 : NIOS magic
@@ -63,8 +66,10 @@ static int do_bootm_linux(struct image_data *idata)
}
static struct image_handler handler = {
+ .name = "NIOS2 Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
int nios2_register_image_handler(void)
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig
new file mode 100644
index 0000000000..a3cb33765d
--- /dev/null
+++ b/arch/openrisc/Kconfig
@@ -0,0 +1,29 @@
+config OPENRISC
+ bool
+ select HAVE_CONFIGURABLE_MEMORY_LAYOUT
+ default y
+
+# not used
+config ARCH_TEXT_BASE
+ hex
+ default 0x00000000
+
+config BOARDINFO
+ default "Openrisc simulator" if GENERIC
+
+choice
+ prompt "Select your board"
+
+config GENERIC
+ bool "Generic "
+ select OPENRISC
+
+endchoice
+
+source common/Kconfig
+source commands/Kconfig
+source net/Kconfig
+source drivers/Kconfig
+source fs/Kconfig
+source lib/Kconfig
+source crypto/Kconfig
diff --git a/arch/openrisc/Makefile b/arch/openrisc/Makefile
new file mode 100644
index 0000000000..fd8bbbf4d7
--- /dev/null
+++ b/arch/openrisc/Makefile
@@ -0,0 +1,21 @@
+CPPFLAGS += -D__OR1K__ -ffixed-r10 -mhard-mul -mhard-div
+
+board-$(CONFIG_GENERIC) := generic
+
+KALLSYMS += --symbol-prefix=_
+
+archprepare: maketools
+
+PHONY += maketools
+
+ifneq ($(board-y),)
+BOARD := arch/openrisc/boards/$(board-y)/
+else
+BOARD :=
+endif
+
+common-y += $(BOARD)
+common-y += arch/openrisc/lib/
+common-y += arch/openrisc/cpu/
+
+lds-y += arch/openrisc/cpu/barebox.lds
diff --git a/arch/openrisc/boards/generic/Makefile b/arch/openrisc/boards/generic/Makefile
new file mode 100644
index 0000000000..d8a3d7f2cc
--- /dev/null
+++ b/arch/openrisc/boards/generic/Makefile
@@ -0,0 +1 @@
+obj-y += generic.o
diff --git a/arch/openrisc/boards/generic/config.h b/arch/openrisc/boards/generic/config.h
new file mode 100644
index 0000000000..88d2929af5
--- /dev/null
+++ b/arch/openrisc/boards/generic/config.h
@@ -0,0 +1,28 @@
+#ifndef _GENERIC_NAMES_H_
+#define _GENERIC_NAMES_H_
+
+#define CONFIG_SYS_CLK_FREQ 20000000
+
+#define OPENRISC_TIMER_FREQ 20000000
+
+#define OPENRISC_SOPC_MEMORY_BASE 0x00000000
+#define OPENRISC_SOPC_MEMORY_SIZE 0x02000000
+
+#define OPENRISC_SOPC_UART_BASE 0x90000000
+#define CONFIG_SYS_UART_FREQ CONFIG_SYS_CLK_FREQ
+#define CONFIG_SYS_UART_BAUD 115200
+
+/* We reserve 256K for barebox */
+#define BAREBOX_RESERVED_SIZE 0x40000
+
+/* Barebox will be at top of main memory */
+#define OPENRISC_SOPC_TEXT_BASE (OPENRISC_SOPC_MEMORY_BASE + OPENRISC_SOPC_MEMORY_SIZE - BAREBOX_RESERVED_SIZE)
+
+/*
+* TEXT_BASE is defined here because STACK_BASE definition
+* in include/asm-generic/memory_layout.h uses this name
+*/
+
+#define TEXT_BASE OPENRISC_SOPC_TEXT_BASE
+
+#endif
diff --git a/arch/openrisc/boards/generic/env/config b/arch/openrisc/boards/generic/env/config
new file mode 100644
index 0000000000..9dee8d98b4
--- /dev/null
+++ b/arch/openrisc/boards/generic/env/config
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+# can be either 'net' or 'flash'
+kernel=flash
+root=flash
+
+kernel_loc=nor
+kernelimage_type=uimage
+
+# use 'dhcp' todo dhcp in barebox and in kernel
+ip=none
+
+autoboot_timeout=3
+
+nor_parts="256k(barebox),128k(env),4M(kernel),-(rootfs)"
+
+bootargs="console=ttyS0,9600"
+
+# set a fancy prompt (if support is compiled in)
+PS1="\e[1;33mbarebox@\e[1;32mor32:\w\e[0m "
diff --git a/arch/openrisc/boards/generic/generic.c b/arch/openrisc/boards/generic/generic.c
new file mode 100644
index 0000000000..6a9ce5b864
--- /dev/null
+++ b/arch/openrisc/boards/generic/generic.c
@@ -0,0 +1,19 @@
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <partition.h>
+#include <ns16550.h>
+
+static struct NS16550_plat serial_plat = {
+ .clock = 50000000, /* 48MHz (APLL96/2) */
+ .shift = 0,
+};
+
+static int openrisc_console_init(void)
+{
+ /* Register the serial port */
+ add_ns16550_device(-1, OPENRISC_SOPC_UART_BASE, 1024, IORESOURCE_MEM_8BIT, &serial_plat);
+ return 0;
+}
+
+console_initcall(openrisc_console_init);
diff --git a/arch/openrisc/configs/generic_defconfig b/arch/openrisc/configs/generic_defconfig
new file mode 100644
index 0000000000..68e037119f
--- /dev/null
+++ b/arch/openrisc/configs/generic_defconfig
@@ -0,0 +1,20 @@
+CONFIG_LONGHELP=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_PARTITION=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_TIME=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_FLASH=y
+# CONFIG_CMD_BOOTM is not set
+CONFIG_CMD_RESET=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_PARTITION=y
+CONFIG_DRIVER_SERIAL_NS16550=y
diff --git a/arch/openrisc/cpu/Makefile b/arch/openrisc/cpu/Makefile
new file mode 100644
index 0000000000..1cd7506003
--- /dev/null
+++ b/arch/openrisc/cpu/Makefile
@@ -0,0 +1,5 @@
+obj-y += start.o
+obj-y += cpu.o
+obj-y += exceptions.o
+obj-y += cache.o
+extra-y += barebox.lds
diff --git a/arch/openrisc/cpu/barebox.lds.S b/arch/openrisc/cpu/barebox.lds.S
new file mode 100644
index 0000000000..d3e02a6ac0
--- /dev/null
+++ b/arch/openrisc/cpu/barebox.lds.S
@@ -0,0 +1,98 @@
+/*
+ * barebox - barebox.lds.S
+ *
+ * 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 <config.h>
+#include <asm-generic/barebox.lds.h>
+
+OUTPUT_FORMAT("elf32-or32", "elf32-or32", "elf32-or32")
+__DYNAMIC = 0;
+
+MEMORY
+{
+ vectors : ORIGIN = 0, LENGTH = 0x2000
+ ram : ORIGIN = TEXT_BASE,
+ LENGTH = BAREBOX_RESERVED_SIZE
+}
+
+SECTIONS
+{
+ .vectors :
+ {
+ *(.vectors)
+ } > vectors
+
+ . = ALIGN(4);
+ __start = .;
+ .text : AT (__start) {
+ _stext = .;
+ *(.text)
+ _etext = .;
+ *(.lit)
+ *(.shdata)
+ _endtext = .;
+ } > ram
+
+ . = ALIGN(4);
+ .rodata : {
+ *(.rodata);
+ *(.rodata.*)
+ } > ram
+
+ . = ALIGN(4);
+ . = .;
+ __barebox_cmd_start = .;
+ .barebox_cmd : { BAREBOX_CMDS } > ram
+ __barebox_cmd_end = .;
+
+ __barebox_magicvar_start = .;
+ .barebox_magicvar : { BAREBOX_MAGICVARS } > ram
+ __barebox_magicvar_end = .;
+
+ __barebox_initcalls_start = .;
+ .barebox_initcalls : { INITCALLS } > ram
+ __barebox_initcalls_end = .;
+
+ ___usymtab_start = .;
+ __usymtab : { BAREBOX_SYMS } > ram
+ ___usymtab_end = .;
+
+ __etext = .; /* End of text and rodata section */
+
+ . = ALIGN(4);
+ .data : {
+ sdata = .;
+ _sdata = .;
+ *(.data)
+ edata = .;
+ _edata = .;
+ } > ram
+
+ . = ALIGN(4);
+ .bss :
+ {
+ __bss_start = .;
+ _bss_start = .;
+ *(.shbss)
+ *(.bss)
+ *(COMMON)
+ _bss_end = .;
+ __bss_stop = .;
+ } > ram
+ __end = .;
+}
diff --git a/arch/openrisc/cpu/cache.c b/arch/openrisc/cpu/cache.c
new file mode 100644
index 0000000000..81a0d13938
--- /dev/null
+++ b/arch/openrisc/cpu/cache.c
@@ -0,0 +1,154 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 <asm/system.h>
+
+void flush_dcache_range(unsigned long addr, unsigned long stop)
+{
+ ulong block_size = (mfspr(SPR_DCCFGR) & SPR_DCCFGR_CBS) ? 32 : 16;
+
+ while (addr < stop) {
+ mtspr(SPR_DCBFR, addr);
+ addr += block_size;
+ }
+}
+
+void invalidate_dcache_range(unsigned long addr, unsigned long stop)
+{
+ ulong block_size = (mfspr(SPR_DCCFGR) & SPR_DCCFGR_CBS) ? 32 : 16;
+
+ while (addr < stop) {
+ mtspr(SPR_DCBIR, addr);
+ addr += block_size;
+ }
+}
+
+static void invalidate_icache_range(unsigned long addr, unsigned long stop)
+{
+ ulong block_size = (mfspr(SPR_ICCFGR) & SPR_ICCFGR_CBS) ? 32 : 16;
+
+ while (addr < stop) {
+ mtspr(SPR_ICBIR, addr);
+ addr += block_size;
+ }
+}
+
+void flush_cache(unsigned long addr, unsigned long size)
+{
+ flush_dcache_range(addr, addr + size);
+ invalidate_icache_range(addr, addr + size);
+}
+
+int icache_status(void)
+{
+ return mfspr(SPR_SR) & SPR_SR_ICE;
+}
+
+int checkicache(void)
+{
+ unsigned long iccfgr;
+ unsigned long cache_set_size;
+ unsigned long cache_ways;
+ unsigned long cache_block_size;
+
+ iccfgr = mfspr(SPR_ICCFGR);
+ cache_ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
+ cache_set_size = 1 << ((iccfgr & SPR_ICCFGR_NCS) >> 3);
+ cache_block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16;
+
+ return cache_set_size * cache_ways * cache_block_size;
+}
+
+int dcache_status(void)
+{
+ return mfspr(SPR_SR) & SPR_SR_DCE;
+}
+
+int checkdcache(void)
+{
+ unsigned long dccfgr;
+ unsigned long cache_set_size;
+ unsigned long cache_ways;
+ unsigned long cache_block_size;
+
+ dccfgr = mfspr(SPR_DCCFGR);
+ cache_ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
+ cache_set_size = 1 << ((dccfgr & SPR_DCCFGR_NCS) >> 3);
+ cache_block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16;
+
+ return cache_set_size * cache_ways * cache_block_size;
+}
+
+void dcache_enable(void)
+{
+ mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_DCE);
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+}
+
+void dcache_disable(void)
+{
+ mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_DCE);
+}
+
+void icache_enable(void)
+{
+ mtspr(SPR_SR, mfspr(SPR_SR) | SPR_SR_ICE);
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+ asm volatile("l.nop");
+}
+
+void icache_disable(void)
+{
+ mtspr(SPR_SR, mfspr(SPR_SR) & ~SPR_SR_ICE);
+}
+
+int cache_init(void)
+{
+ if (mfspr(SPR_UPR) & SPR_UPR_ICP) {
+ icache_disable();
+ invalidate_icache_range(0, checkicache());
+ icache_enable();
+ }
+
+ if (mfspr(SPR_UPR) & SPR_UPR_DCP) {
+ dcache_disable();
+ invalidate_dcache_range(0, checkdcache());
+ dcache_enable();
+ }
+
+ return 0;
+}
+
+core_initcall(cache_init);
diff --git a/arch/openrisc/cpu/cpu.c b/arch/openrisc/cpu/cpu.c
new file mode 100644
index 0000000000..48f5d032a5
--- /dev/null
+++ b/arch/openrisc/cpu/cpu.c
@@ -0,0 +1,43 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <init.h>
+#include <asm/system.h>
+#include <asm/openrisc_exc.h>
+
+int cleanup_before_linux(void)
+{
+ return 0;
+}
+
+extern void __reset(void);
+
+void __noreturn reset_cpu(ulong ignored)
+{
+ __reset();
+ /* not reached, __reset does not return */
+
+ /* Not reached */
+ while (1);
+}
diff --git a/arch/openrisc/cpu/exceptions.c b/arch/openrisc/cpu/exceptions.c
new file mode 100644
index 0000000000..a979258f80
--- /dev/null
+++ b/arch/openrisc/cpu/exceptions.c
@@ -0,0 +1,84 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 <asm/system.h>
+
+static const char * const excp_table[] = {
+ "Unknown exception",
+ "Reset",
+ "Bus Error",
+ "Data Page Fault",
+ "Instruction Page Fault",
+ "Tick Timer",
+ "Alignment",
+ "Illegal Instruction",
+ "External Interrupt",
+ "D-TLB Miss",
+ "I-TLB Miss",
+ "Range",
+ "System Call",
+ "Floating Point",
+ "Trap",
+};
+
+static void (*handlers[32])(void);
+
+void exception_install_handler(int exception, void (*handler)(void))
+{
+ if (exception < 0 || exception > 31)
+ return;
+
+ handlers[exception] = handler;
+}
+
+void exception_free_handler(int exception)
+{
+ if (exception < 0 || exception > 31)
+ return;
+
+ handlers[exception] = 0;
+}
+
+static void exception_hang(int vect)
+{
+ printf("Unhandled exception at 0x%x ", vect & 0xff00);
+
+ vect = ((vect >> 8) & 0xff);
+ if (vect < ARRAY_SIZE(excp_table))
+ printf("(%s)\n", excp_table[vect]);
+ else
+ printf("(%s)\n", excp_table[0]);
+
+ printf("EPCR: 0x%08lx\n", mfspr(SPR_EPCR_BASE));
+ printf("EEAR: 0x%08lx\n", mfspr(SPR_EEAR_BASE));
+ printf("ESR: 0x%08lx\n", mfspr(SPR_ESR_BASE));
+ hang();
+}
+
+void exception_handler(int vect)
+{
+ int exception = vect >> 8;
+
+ if (handlers[exception])
+ handlers[exception]();
+ else
+ exception_hang(vect);
+}
diff --git a/arch/openrisc/cpu/start.S b/arch/openrisc/cpu/start.S
new file mode 100644
index 0000000000..056f116b06
--- /dev/null
+++ b/arch/openrisc/cpu/start.S
@@ -0,0 +1,335 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 <config.h>
+#include <asm-generic/memory_layout.h>
+#include <asm/spr-defs.h>
+
+#define EXCEPTION_STACK_SIZE (128+128)
+
+#define HANDLE_EXCEPTION \
+ l.addi r1, r1, -EXCEPTION_STACK_SIZE ;\
+ l.sw 0x1c(r1), r9 ;\
+ l.jal _exception_handler ;\
+ l.nop ;\
+ l.lwz r9, 0x1c(r1) ;\
+ l.addi r1, r1, EXCEPTION_STACK_SIZE ;\
+ l.rfe ;\
+ l.nop
+
+ .section .vectors, "ax"
+ .global __reset
+
+ /* reset */
+ .org 0x100
+__reset:
+ /* there is no guarantee r0 is hardwired to zero, clear it here */
+ l.andi r0, r0, 0
+ /* reset stack and frame pointers */
+ l.andi r1, r0, 0
+ l.andi r2, r0, 0
+
+ /* set supervisor mode */
+ l.ori r3,r0,SPR_SR_SM
+ l.mtspr r0,r3,SPR_SR
+
+ /* Relocate barebox */
+ l.movhi r3,hi(__start) /* source start address */
+ l.ori r3,r3,lo(__start)
+ l.movhi r4,hi(_stext) /* dest start address */
+ l.ori r4,r4,lo(_stext)
+ l.movhi r5,hi(__end) /* dest end address */
+ l.ori r5,r5,lo(__end)
+
+.L_reloc:
+ l.lwz r6,0(r3)
+ l.sw 0(r4),r6
+ l.addi r3,r3,4
+ l.sfltu r4,r5
+ l.bf .L_reloc
+ l.addi r4,r4,4 /*delay slot */
+
+#ifdef CONFIG_SYS_RELOCATE_VECTORS
+ /* Relocate vectors from 0xf0000000 to 0x00000000 */
+ l.movhi r4, 0xf000 /* source */
+ l.movhi r5, 0 /* destination */
+ l.addi r6, r5, CONFIG_SYS_VECTORS_LEN /* length */
+.L_relocvectors:
+ l.lwz r7, 0(r4)
+ l.sw 0(r5), r7
+ l.addi r5, r5, 4
+ l.sfeq r5,r6
+ l.bnf .L_relocvectors
+ l.addi r4,r4, 4
+#endif
+
+ l.j _start
+ l.nop
+
+ /* bus error */
+ .org 0x200
+ HANDLE_EXCEPTION
+
+ /* data page fault */
+ .org 0x300
+ HANDLE_EXCEPTION
+
+ /* instruction page fault */
+ .org 0x400
+ HANDLE_EXCEPTION
+
+ /* tick timer */
+ .org 0x500
+ HANDLE_EXCEPTION
+
+ /* alignment */
+ .org 0x600
+ HANDLE_EXCEPTION
+
+ /* illegal instruction */
+ .org 0x700
+ HANDLE_EXCEPTION
+
+ /* external interrupt */
+ .org 0x800
+ HANDLE_EXCEPTION
+
+ /* D-TLB miss */
+ .org 0x900
+ HANDLE_EXCEPTION
+
+ /* I-TLB miss */
+ .org 0xa00
+ HANDLE_EXCEPTION
+
+ /* range */
+ .org 0xb00
+ HANDLE_EXCEPTION
+
+ /* system call */
+ .org 0xc00
+ HANDLE_EXCEPTION
+
+ /* floating point */
+ .org 0xd00
+ HANDLE_EXCEPTION
+
+ /* trap */
+ .org 0xe00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0xf00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1100
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1200
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1300
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1400
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1500
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1600
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1700
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1800
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1900
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1a00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1b00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1c00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1d00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1e00
+ HANDLE_EXCEPTION
+
+ /* reserved */
+ .org 0x1f00
+ HANDLE_EXCEPTION
+
+ /* Startup routine */
+ .text
+ .global _start
+_start:
+ /* Init stack and frame pointers */
+ l.movhi r1, hi(STACK_BASE)
+ l.ori r1, r1, lo(STACK_BASE)
+ l.or r2, r0, r1
+
+ /* clear BSS segments */
+ l.movhi r4, hi(_bss_start)
+ l.ori r4, r4, lo(_bss_start)
+ l.movhi r5, hi(_bss_end)
+ l.ori r5, r5, lo(_bss_end)
+.L_clear_bss:
+ l.sw 0(r4), r0
+ l.sfltu r4,r5
+ l.bf .L_clear_bss
+ l.addi r4,r4,4
+
+ /* Reset registers before jumping to board_init */
+ l.andi r3, r0, 0
+ l.andi r4, r0, 0
+ l.andi r5, r0, 0
+ l.andi r6, r0, 0
+ l.andi r7, r0, 0
+ l.andi r8, r0, 0
+ l.andi r9, r0, 0
+ l.andi r10, r0, 0
+ l.andi r11, r0, 0
+ l.andi r12, r0, 0
+ l.andi r13, r0, 0
+ l.andi r14, r0, 0
+ l.andi r15, r0, 0
+ l.andi r17, r0, 0
+ l.andi r18, r0, 0
+ l.andi r19, r0, 0
+ l.andi r20, r0, 0
+ l.andi r21, r0, 0
+ l.andi r22, r0, 0
+ l.andi r23, r0, 0
+ l.andi r24, r0, 0
+ l.andi r25, r0, 0
+ l.andi r26, r0, 0
+ l.andi r27, r0, 0
+ l.andi r28, r0, 0
+ l.andi r29, r0, 0
+ l.andi r30, r0, 0
+ l.andi r31, r0, 0
+
+ l.j start_barebox
+ l.nop
+
+ .size _start, .-_start
+
+/*
+ * Store state onto stack and call the real exception handler
+ */
+ .section .text
+ .extern exception_handler
+ .type _exception_handler,@function
+
+_exception_handler:
+ /* Store state (r9 already saved)*/
+ l.sw 0x00(r1), r2
+ l.sw 0x04(r1), r3
+ l.sw 0x08(r1), r4
+ l.sw 0x0c(r1), r5
+ l.sw 0x10(r1), r6
+ l.sw 0x14(r1), r7
+ l.sw 0x18(r1), r8
+ l.sw 0x20(r1), r10
+ l.sw 0x24(r1), r11
+ l.sw 0x28(r1), r12
+ l.sw 0x2c(r1), r13
+ l.sw 0x30(r1), r14
+ l.sw 0x34(r1), r15
+ l.sw 0x38(r1), r16
+ l.sw 0x3c(r1), r17
+ l.sw 0x40(r1), r18
+ l.sw 0x44(r1), r19
+ l.sw 0x48(r1), r20
+ l.sw 0x4c(r1), r21
+ l.sw 0x50(r1), r22
+ l.sw 0x54(r1), r23
+ l.sw 0x58(r1), r24
+ l.sw 0x5c(r1), r25
+ l.sw 0x60(r1), r26
+ l.sw 0x64(r1), r27
+ l.sw 0x68(r1), r28
+ l.sw 0x6c(r1), r29
+ l.sw 0x70(r1), r30
+ l.sw 0x74(r1), r31
+
+ /* Save return address */
+ l.or r14, r0, r9
+ /* Call exception handler with the link address as argument */
+ l.jal exception_handler
+ l.or r3, r0, r14
+ /* Load return address */
+ l.or r9, r0, r14
+
+ /* Restore state */
+ l.lwz r2, 0x00(r1)
+ l.lwz r3, 0x04(r1)
+ l.lwz r4, 0x08(r1)
+ l.lwz r5, 0x0c(r1)
+ l.lwz r6, 0x10(r1)
+ l.lwz r7, 0x14(r1)
+ l.lwz r8, 0x18(r1)
+ l.lwz r10, 0x20(r1)
+ l.lwz r11, 0x24(r1)
+ l.lwz r12, 0x28(r1)
+ l.lwz r13, 0x2c(r1)
+ l.lwz r14, 0x30(r1)
+ l.lwz r15, 0x34(r1)
+ l.lwz r16, 0x38(r1)
+ l.lwz r17, 0x3c(r1)
+ l.lwz r18, 0x40(r1)
+ l.lwz r19, 0x44(r1)
+ l.lwz r20, 0x48(r1)
+ l.lwz r21, 0x4c(r1)
+ l.lwz r22, 0x50(r1)
+ l.lwz r23, 0x54(r1)
+ l.lwz r24, 0x58(r1)
+ l.lwz r25, 0x5c(r1)
+ l.lwz r26, 0x60(r1)
+ l.lwz r27, 0x64(r1)
+ l.lwz r28, 0x68(r1)
+ l.lwz r29, 0x6c(r1)
+ l.lwz r30, 0x70(r1)
+ l.lwz r31, 0x74(r1)
+ l.jr r9
+ l.nop
diff --git a/arch/openrisc/include/asm/barebox.h b/arch/openrisc/include/asm/barebox.h
new file mode 100644
index 0000000000..9dd1df8e32
--- /dev/null
+++ b/arch/openrisc/include/asm/barebox.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_BAREBOX_H_
+#define _ASM_BAREBOX_H_
+
+#endif /* _ASM_BAREBOX_H_ */
diff --git a/arch/openrisc/include/asm/bitops.h b/arch/openrisc/include/asm/bitops.h
new file mode 100644
index 0000000000..c001a5d1f6
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops.h
@@ -0,0 +1,28 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ *
+ * 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 __ASM_OPENRISC_BITOPS_H
+#define __ASM_OPENRISC_BITOPS_H
+
+#define PLATFORM_FLS
+#include <asm/bitops/fls.h>
+#define PLATFORM_FFS
+#include <asm/bitops/ffs.h>
+
+#endif /* __ASM_GENERIC_BITOPS_H */
diff --git a/arch/openrisc/include/asm/bitops/ffs.h b/arch/openrisc/include/asm/bitops/ffs.h
new file mode 100644
index 0000000000..1de5295816
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/ffs.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_OPENRISC_FFS_H
+#define __ASM_OPENRISC_FFS_H
+
+static inline int ffs(int x)
+{
+ int ret;
+
+ __asm__ ("l.ff1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret;
+}
+
+#endif /* __ASM_OPENRISC_FFS_H */
diff --git a/arch/openrisc/include/asm/bitops/fls.h b/arch/openrisc/include/asm/bitops/fls.h
new file mode 100644
index 0000000000..8c77c13776
--- /dev/null
+++ b/arch/openrisc/include/asm/bitops/fls.h
@@ -0,0 +1,26 @@
+/*
+ * OpenRISC Linux
+ *
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ *
+ * 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.
+ */
+
+#ifndef __ASM_OPENRISC_FLS_H
+#define __ASM_OPENRISC_FLS_H
+
+static inline int fls(int x)
+{
+ int ret;
+
+ __asm__ ("l.fl1 %0,%1"
+ : "=r" (ret)
+ : "r" (x));
+
+ return ret;
+}
+
+#endif /* __ASM_OPENRISC_FLS_H */
diff --git a/arch/openrisc/include/asm/byteorder.h b/arch/openrisc/include/asm/byteorder.h
new file mode 100644
index 0000000000..60d14f7e14
--- /dev/null
+++ b/arch/openrisc/include/asm/byteorder.h
@@ -0,0 +1 @@
+#include <linux/byteorder/big_endian.h>
diff --git a/arch/openrisc/include/asm/cache.h b/arch/openrisc/include/asm/cache.h
new file mode 100644
index 0000000000..05cf998b30
--- /dev/null
+++ b/arch/openrisc/include/asm/cache.h
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ *
+ * 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 __ASM_OPENRISC_CACHE_H_
+#define __ASM_OPENRISC_CACHE_H_
+
+void flush_dcache_range(unsigned long addr, unsigned long stop);
+void invalidate_dcache_range(unsigned long addr, unsigned long stop);
+void flush_cache(unsigned long addr, unsigned long size);
+int icache_status(void);
+int checkicache(void);
+int dcache_status(void);
+int checkdcache(void);
+void dcache_enable(void);
+void dcache_disable(void);
+void icache_enable(void);
+void icache_disable(void);
+
+/*
+ * Valid L1 data cache line sizes for the OpenRISC architecture are
+ * 16 and 32 bytes.
+ * If the board configuration has not specified one we default to the
+ * largest of these values for alignment of DMA buffers.
+ */
+#ifdef CONFIG_SYS_CACHELINE_SIZE
+#define ARCH_DMA_MINALIGN CONFIG_SYS_CACHELINE_SIZE
+#else
+#define ARCH_DMA_MINALIGN 32
+#endif
+
+#endif /* __ASM_OPENRISC_CACHE_H_ */
diff --git a/arch/openrisc/include/asm/common.h b/arch/openrisc/include/asm/common.h
new file mode 100644
index 0000000000..027dca2d56
--- /dev/null
+++ b/arch/openrisc/include/asm/common.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_COMMON_H
+#define __ASM_COMMON_H
+
+#endif /* _ASM_COMMON_H */
diff --git a/arch/openrisc/include/asm/elf.h b/arch/openrisc/include/asm/elf.h
new file mode 100644
index 0000000000..6a134a5723
--- /dev/null
+++ b/arch/openrisc/include/asm/elf.h
@@ -0,0 +1,107 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_OPENRISC_ELF_H
+#define __ASM_OPENRISC_ELF_H
+
+/*
+ * ELF register definitions..
+ */
+#include <linux/types.h>
+#include <asm/ptrace.h>
+
+/* The OR1K relocation types... not all relevant for module loader */
+#define R_OR32_NONE 0
+#define R_OR32_32 1
+#define R_OR32_16 2
+#define R_OR32_8 3
+#define R_OR32_CONST 4
+#define R_OR32_CONSTH 5
+#define R_OR32_JUMPTARG 6
+#define R_OR32_VTINHERIT 7
+#define R_OR32_VTENTRY 8
+
+typedef unsigned long elf_greg_t;
+
+/*
+ * Note that NGREG is defined to ELF_NGREG in include/linux/elfcore.h, and is
+ * thus exposed to user-space.
+ */
+#define ELF_NGREG (sizeof(struct user_regs_struct) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+/* A placeholder; OR32 does not have fp support yes, so no fp regs for now. */
+typedef unsigned long elf_fpregset_t;
+
+/* This should be moved to include/linux/elf.h */
+#define EM_OR32 0x8472
+#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_ARCH EM_OR32
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+
+#ifdef __KERNEL__
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+
+#define elf_check_arch(x) \
+ (((x)->e_machine == EM_OR32) || ((x)->e_machine == EM_OPENRISC))
+
+/* This is the location that an ET_DYN program is loaded if exec'ed. Typical
+ use of this is to invoke "./ld.so someprog" to test out a new version of
+ the loader. We need to make sure that it is out of the way of the program
+ that it will "exec", and that there is sufficient room for the brk. */
+
+#define ELF_ET_DYN_BASE (0x08000000)
+
+/*
+ * Enable dump using regset.
+ * This covers all of general/DSP/FPU regs.
+ */
+#define CORE_DUMP_USE_REGSET
+
+#define ELF_EXEC_PAGESIZE 8192
+
+extern void dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt);
+#define ELF_CORE_COPY_REGS(dest, regs) dump_elf_thread(dest, regs);
+
+/* This yields a mask that user programs can use to figure out what
+ instruction set this cpu supports. This could be done in userspace,
+ but it's not easy, and we've already done it here. */
+
+#define ELF_HWCAP (0)
+
+/* This yields a string that ld.so will use to load implementation
+ specific libraries for optimization. This is more specific in
+ intent than poking at uname or /proc/cpuinfo.
+
+ For the moment, we have only optimizations for the Intel generations,
+ but that could change... */
+
+#define ELF_PLATFORM (NULL)
+
+#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+
+#endif /* __KERNEL__ */
+#endif
diff --git a/arch/openrisc/include/asm/io.h b/arch/openrisc/include/asm/io.h
new file mode 100644
index 0000000000..19b260a175
--- /dev/null
+++ b/arch/openrisc/include/asm/io.h
@@ -0,0 +1,123 @@
+/*
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 __ASM_OPENRISC_IO_H
+#define __ASM_OPENRISC_IO_H
+
+#include <asm/byteorder.h>
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
+ */
+#define MAP_NOCACHE (0)
+#define MAP_WRCOMBINE (0)
+#define MAP_WRBACK (0)
+#define MAP_WRTHROUGH (0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+ return (void *)paddr;
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+/*
+ * Change virtual addresses to physical addresses
+ */
+static inline phys_addr_t virt_to_phys(void *vaddr)
+{
+ return (phys_addr_t)(vaddr);
+}
+
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the openrisc architecture, we just read/write the
+ * memory location directly.
+ */
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define writeb(b, addr) ((*(volatile unsigned char *) (addr)) = (b))
+#define writew(b, addr) ((*(volatile unsigned short *) (addr)) = (b))
+#define writel(b, addr) ((*(volatile unsigned int *) (addr)) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define memset_io(a, b, c) memset((void *)(a), (b), (c))
+#define memcpy_fromio(a, b, c) memcpy((a), (void *)(b), (c))
+#define memcpy_toio(a, b, c) memcpy((void *)(a), (b), (c))
+
+#define out_be32(a, v) __raw_writel((v), (void __iomem __force *)(a))
+#define out_be16(a, v) __raw_writew((v), (a))
+
+#define in_be32(a) __raw_readl((const void __iomem __force *)(a))
+#define in_be16(a) __raw_readw(a)
+
+#define writel_be(v, a) out_be32((__force unsigned *)a, v)
+#define readl_be(a) in_be32((__force unsigned *)a)
+
+/*
+ * Again, OpenRISC does not require mem IO specific function.
+ */
+
+
+#define IO_BASE 0x0
+#define IO_SPACE_LIMIT 0xffffffff
+
+#define inb(port) readb((port + IO_BASE))
+#define outb(value, port) writeb((value), (port + IO_BASE))
+#define inb_p(port) inb((port))
+#define outb_p(value, port) outb((value), (port))
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#define xlate_dev_mem_ptr(p) __va(p)
+
+/*
+ * Convert a virtual cached pointer to an uncached pointer
+ */
+#define xlate_dev_kmem_ptr(p) p
+
+#define ioread8(addr) readb(addr)
+#define ioread16(addr) readw(addr)
+#define ioread32(addr) readl(addr)
+
+#define iowrite8(v, addr) writeb((v), (addr))
+#define iowrite16(v, addr) writew((v), (addr))
+#define iowrite32(v, addr) writel((v), (addr))
+
+#endif
diff --git a/arch/openrisc/include/asm/openrisc_exc.h b/arch/openrisc/include/asm/openrisc_exc.h
new file mode 100644
index 0000000000..33f64538f8
--- /dev/null
+++ b/arch/openrisc/include/asm/openrisc_exc.h
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ *
+ * 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 _OPENRISC_EXC_H_
+#define _OPENRISC_EXC_H_
+
+#define EXC_RESET 0x01
+#define EXC_BUS_ERROR 0x02
+#define EXC_DATA_PAGE_FAULT 0x03
+#define EXC_INSTR_PAGE_FAULT 0x04
+#define EXC_TIMER 0x05
+#define EXC_ALIGNMENT 0x06
+#define EXC_ILLEGAL_INSTR 0x07
+#define EXC_EXT_IRQ 0x08
+#define EXC_DTLB_MISS 0x09
+#define EXC_ITLB_MISS 0x0a
+#define EXC_RANGE 0x0b
+#define EXC_SYSCALL 0x0c
+#define EXC_FLOAT_POINT 0x0d
+#define EXC_TRAP 0x0e
+
+void exception_install_handler(int exception, void (*handler)(void));
+void exception_free_handler(int exception);
+
+#endif
diff --git a/arch/openrisc/include/asm/posix_types.h b/arch/openrisc/include/asm/posix_types.h
new file mode 100644
index 0000000000..7f4c9423ca
--- /dev/null
+++ b/arch/openrisc/include/asm/posix_types.h
@@ -0,0 +1,71 @@
+/*
+ * Based on microblaze implementation:
+ * Copyright (C) 2003 John Williams <jwilliams@itee.uq.edu.au>
+ * Copyright (C) 2001,2002 NEC Corporation
+ * Copyright (C) 2001,2002 Miles Bader <miles@gnu.org>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of this
+ * archive for more details.
+ *
+ * Written by Miles Bader <miles@gnu.org>
+ * Microblaze port by John Williams
+ */
+
+#ifndef __ASM_OPENRISC_POSIX_TYPES_H
+#define __ASM_OPENRISC_POSIX_TYPES_H
+
+typedef unsigned long __kernel_ino_t;
+typedef unsigned long long __kernel_ino64_t;
+typedef unsigned int __kernel_mode_t;
+typedef unsigned int __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef long long __kernel_loff_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char *__kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(fd, fd_set) \
+ __set_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
+#undef __FD_CLR
+#define __FD_CLR(fd, fd_set) \
+ __clear_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
+#undef __FD_ISSET
+#define __FD_ISSET(fd, fd_set) \
+ __test_bit(fd, (void *)&((__kernel_fd_set *)fd_set)->fds_bits)
+#undef __FD_ZERO
+#define __FD_ZERO(fd_set) \
+ memset(fd_set, 0, sizeof(*(fd_set *)fd_set))
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif /* __ASM_OPENRISC_POSIX_TYPES_H */
diff --git a/arch/openrisc/include/asm/ptrace.h b/arch/openrisc/include/asm/ptrace.h
new file mode 100644
index 0000000000..ffdea52925
--- /dev/null
+++ b/arch/openrisc/include/asm/ptrace.h
@@ -0,0 +1,131 @@
+/*
+ * OpenRISC Linux
+ *
+ * Linux architectural port borrowing liberally from similar works of
+ * others. All original copyrights apply as per the original source
+ * declaration.
+ *
+ * OpenRISC implementation:
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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.
+ */
+
+#ifndef __ASM_OPENRISC_PTRACE_H
+#define __ASM_OPENRISC_PTRACE_H
+
+#include <asm/spr-defs.h>
+
+#ifndef __ASSEMBLY__
+/*
+ * This is the layout of the regset returned by the GETREGSET ptrace call
+ */
+struct user_regs_struct {
+ /* GPR R0-R31... */
+ unsigned long gpr[32];
+ unsigned long pc;
+ unsigned long sr;
+ unsigned long pad1;
+ unsigned long pad2;
+};
+#endif
+
+#ifdef __KERNEL__
+
+/*
+ * Make kernel PTrace/register structures opaque to userspace... userspace can
+ * access thread state via the regset mechanism. This allows us a bit of
+ * flexibility in how we order the registers on the stack, permitting some
+ * optimizations like packing call-clobbered registers together so that
+ * they share a cacheline (not done yet, though... future optimization).
+ */
+
+#ifndef __ASSEMBLY__
+/*
+ * This struct describes how the registers are laid out on the kernel stack
+ * during a syscall or other kernel entry.
+ *
+ * This structure should always be cacheline aligned on the stack.
+ * FIXME: I don't think that's the case right now. The alignment is
+ * taken care of elsewhere... head.S, process.c, etc.
+ */
+
+struct pt_regs {
+ union {
+ struct {
+ /* Named registers */
+ long sr; /* Stored in place of r0 */
+ long sp; /* r1 */
+ };
+ struct {
+ /* Old style */
+ long offset[2];
+ long gprs[30];
+ };
+ struct {
+ /* New style */
+ long gpr[32];
+ };
+ };
+ long pc;
+ long orig_gpr11; /* For restarting system calls */
+ long syscallno; /* Syscall number (used by strace) */
+ long dummy; /* Cheap alignment fix */
+};
+#endif /* __ASSEMBLY__ */
+
+/* TODO: Rename this to REDZONE because that's what it is */
+#define STACK_FRAME_OVERHEAD 128 /* size of minimum stack frame */
+
+#define instruction_pointer(regs) ((regs)->pc)
+#define user_mode(regs) (((regs)->sr & SPR_SR_SM) == 0)
+#define user_stack_pointer(regs) ((unsigned long)(regs)->sp)
+#define profile_pc(regs) instruction_pointer(regs)
+
+/*
+ * Offsets used by 'ptrace' system call interface.
+ */
+#define PT_SR 0
+#define PT_SP 4
+#define PT_GPR2 8
+#define PT_GPR3 12
+#define PT_GPR4 16
+#define PT_GPR5 20
+#define PT_GPR6 24
+#define PT_GPR7 28
+#define PT_GPR8 32
+#define PT_GPR9 36
+#define PT_GPR10 40
+#define PT_GPR11 44
+#define PT_GPR12 48
+#define PT_GPR13 52
+#define PT_GPR14 56
+#define PT_GPR15 60
+#define PT_GPR16 64
+#define PT_GPR17 68
+#define PT_GPR18 72
+#define PT_GPR19 76
+#define PT_GPR20 80
+#define PT_GPR21 84
+#define PT_GPR22 88
+#define PT_GPR23 92
+#define PT_GPR24 96
+#define PT_GPR25 100
+#define PT_GPR26 104
+#define PT_GPR27 108
+#define PT_GPR28 112
+#define PT_GPR29 116
+#define PT_GPR30 120
+#define PT_GPR31 124
+#define PT_PC 128
+#define PT_ORIG_GPR11 132
+#define PT_SYSCALLNO 136
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASM_OPENRISC_PTRACE_H */
diff --git a/arch/openrisc/include/asm/sections.h b/arch/openrisc/include/asm/sections.h
new file mode 100644
index 0000000000..2b8c516038
--- /dev/null
+++ b/arch/openrisc/include/asm/sections.h
@@ -0,0 +1 @@
+#include <asm-generic/sections.h>
diff --git a/arch/openrisc/include/asm/spr-defs.h b/arch/openrisc/include/asm/spr-defs.h
new file mode 100644
index 0000000000..cb0cdfa7fe
--- /dev/null
+++ b/arch/openrisc/include/asm/spr-defs.h
@@ -0,0 +1,567 @@
+/*
+ * SPR Definitions
+ *
+ * Copyright (C) 2000 Damjan Lampret
+ * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com>
+ * Copyright (C) 2008, 2010 Embecosm Limited
+ * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se>
+ * et al.
+ *
+ * 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 file is part of OpenRISC 1000 Architectural Simulator.
+ */
+
+#ifndef SPR_DEFS__H
+#define SPR_DEFS__H
+
+/* Definition of special-purpose registers (SPRs) */
+
+#define MAX_GRPS (32)
+#define MAX_SPRS_PER_GRP_BITS (11)
+#define MAX_SPRS_PER_GRP (1 << MAX_SPRS_PER_GRP_BITS)
+#define MAX_SPRS (0x10000)
+
+/* Base addresses for the groups */
+#define SPRGROUP_SYS (0 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DMMU (1 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IMMU (2 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_DC (3 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_IC (4 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_MAC (5 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_D (6 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PC (7 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PM (8 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_PIC (9 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_TT (10 << MAX_SPRS_PER_GRP_BITS)
+#define SPRGROUP_FP (11 << MAX_SPRS_PER_GRP_BITS)
+
+/* System control and status group */
+#define SPR_VR (SPRGROUP_SYS + 0)
+#define SPR_UPR (SPRGROUP_SYS + 1)
+#define SPR_CPUCFGR (SPRGROUP_SYS + 2)
+#define SPR_DMMUCFGR (SPRGROUP_SYS + 3)
+#define SPR_IMMUCFGR (SPRGROUP_SYS + 4)
+#define SPR_DCCFGR (SPRGROUP_SYS + 5)
+#define SPR_ICCFGR (SPRGROUP_SYS + 6)
+#define SPR_DCFGR (SPRGROUP_SYS + 7)
+#define SPR_PCCFGR (SPRGROUP_SYS + 8)
+#define SPR_NPC (SPRGROUP_SYS + 16)
+#define SPR_SR (SPRGROUP_SYS + 17)
+#define SPR_PPC (SPRGROUP_SYS + 18)
+#define SPR_FPCSR (SPRGROUP_SYS + 20)
+#define SPR_EPCR_BASE (SPRGROUP_SYS + 32)
+#define SPR_EPCR_LAST (SPRGROUP_SYS + 47)
+#define SPR_EEAR_BASE (SPRGROUP_SYS + 48)
+#define SPR_EEAR_LAST (SPRGROUP_SYS + 63)
+#define SPR_ESR_BASE (SPRGROUP_SYS + 64)
+#define SPR_ESR_LAST (SPRGROUP_SYS + 79)
+#define SPR_GPR_BASE (SPRGROUP_SYS + 1024)
+
+/* Data MMU group */
+#define SPR_DMMUCR (SPRGROUP_DMMU + 0)
+#define SPR_DTLBEIR (SPRGROUP_DMMU + 2)
+#define SPR_DTLBMR_BASE(WAY) (SPRGROUP_DMMU + 0x200 + (WAY) * 0x100)
+#define SPR_DTLBMR_LAST(WAY) (SPRGROUP_DMMU + 0x27f + (WAY) * 0x100)
+#define SPR_DTLBTR_BASE(WAY) (SPRGROUP_DMMU + 0x280 + (WAY) * 0x100)
+#define SPR_DTLBTR_LAST(WAY) (SPRGROUP_DMMU + 0x2ff + (WAY) * 0x100)
+
+/* Instruction MMU group */
+#define SPR_IMMUCR (SPRGROUP_IMMU + 0)
+#define SPR_ITLBEIR (SPRGROUP_IMMU + 2)
+#define SPR_ITLBMR_BASE(WAY) (SPRGROUP_IMMU + 0x200 + (WAY) * 0x100)
+#define SPR_ITLBMR_LAST(WAY) (SPRGROUP_IMMU + 0x27f + (WAY) * 0x100)
+#define SPR_ITLBTR_BASE(WAY) (SPRGROUP_IMMU + 0x280 + (WAY) * 0x100)
+#define SPR_ITLBTR_LAST(WAY) (SPRGROUP_IMMU + 0x2ff + (WAY) * 0x100)
+
+/* Data cache group */
+#define SPR_DCCR (SPRGROUP_DC + 0)
+#define SPR_DCBPR (SPRGROUP_DC + 1)
+#define SPR_DCBFR (SPRGROUP_DC + 2)
+#define SPR_DCBIR (SPRGROUP_DC + 3)
+#define SPR_DCBWR (SPRGROUP_DC + 4)
+#define SPR_DCBLR (SPRGROUP_DC + 5)
+#define SPR_DCR_BASE(WAY) (SPRGROUP_DC + 0x200 + (WAY) * 0x200)
+#define SPR_DCR_LAST(WAY) (SPRGROUP_DC + 0x3ff + (WAY) * 0x200)
+
+/* Instruction cache group */
+#define SPR_ICCR (SPRGROUP_IC + 0)
+#define SPR_ICBPR (SPRGROUP_IC + 1)
+#define SPR_ICBIR (SPRGROUP_IC + 2)
+#define SPR_ICBLR (SPRGROUP_IC + 3)
+#define SPR_ICR_BASE(WAY) (SPRGROUP_IC + 0x200 + (WAY) * 0x200)
+#define SPR_ICR_LAST(WAY) (SPRGROUP_IC + 0x3ff + (WAY) * 0x200)
+
+/* MAC group */
+#define SPR_MACLO (SPRGROUP_MAC + 1)
+#define SPR_MACHI (SPRGROUP_MAC + 2)
+
+/* Debug group */
+#define SPR_DVR(N) (SPRGROUP_D + (N))
+#define SPR_DCR(N) (SPRGROUP_D + 8 + (N))
+#define SPR_DMR1 (SPRGROUP_D + 16)
+#define SPR_DMR2 (SPRGROUP_D + 17)
+#define SPR_DWCR0 (SPRGROUP_D + 18)
+#define SPR_DWCR1 (SPRGROUP_D + 19)
+#define SPR_DSR (SPRGROUP_D + 20)
+#define SPR_DRR (SPRGROUP_D + 21)
+
+/* Performance counters group */
+#define SPR_PCCR(N) (SPRGROUP_PC + (N))
+#define SPR_PCMR(N) (SPRGROUP_PC + 8 + (N))
+
+/* Power management group */
+#define SPR_PMR (SPRGROUP_PM + 0)
+
+/* PIC group */
+#define SPR_PICMR (SPRGROUP_PIC + 0)
+#define SPR_PICPR (SPRGROUP_PIC + 1)
+#define SPR_PICSR (SPRGROUP_PIC + 2)
+
+/* Tick Timer group */
+#define SPR_TTMR (SPRGROUP_TT + 0)
+#define SPR_TTCR (SPRGROUP_TT + 1)
+
+/*
+ * Bit definitions for the Version Register
+ */
+#define SPR_VR_VER 0xff000000 /* Processor version */
+#define SPR_VR_CFG 0x00ff0000 /* Processor configuration */
+#define SPR_VR_RES 0x0000ffc0 /* Reserved */
+#define SPR_VR_REV 0x0000003f /* Processor revision */
+
+#define SPR_VR_VER_OFF 24
+#define SPR_VR_CFG_OFF 16
+#define SPR_VR_REV_OFF 0
+
+/*
+ * Bit definitions for the Unit Present Register
+ */
+#define SPR_UPR_UP 0x00000001 /* UPR present */
+#define SPR_UPR_DCP 0x00000002 /* Data cache present */
+#define SPR_UPR_ICP 0x00000004 /* Instruction cache present */
+#define SPR_UPR_DMP 0x00000008 /* Data MMU present */
+#define SPR_UPR_IMP 0x00000010 /* Instruction MMU present */
+#define SPR_UPR_MP 0x00000020 /* MAC present */
+#define SPR_UPR_DUP 0x00000040 /* Debug unit present */
+#define SPR_UPR_PCUP 0x00000080 /* Performance counters unit present */
+#define SPR_UPR_PMP 0x00000100 /* Power management present */
+#define SPR_UPR_PICP 0x00000200 /* PIC present */
+#define SPR_UPR_TTP 0x00000400 /* Tick timer present */
+#define SPR_UPR_RES 0x00fe0000 /* Reserved */
+#define SPR_UPR_CUP 0xff000000 /* Context units present */
+
+/*
+ * Bit definitions for the CPU configuration register
+ */
+#define SPR_CPUCFGR_NSGF 0x0000000f /* Number of shadow GPR files */
+#define SPR_CPUCFGR_CGF 0x00000010 /* Custom GPR file */
+#define SPR_CPUCFGR_OB32S 0x00000020 /* ORBIS32 supported */
+#define SPR_CPUCFGR_OB64S 0x00000040 /* ORBIS64 supported */
+#define SPR_CPUCFGR_OF32S 0x00000080 /* ORFPX32 supported */
+#define SPR_CPUCFGR_OF64S 0x00000100 /* ORFPX64 supported */
+#define SPR_CPUCFGR_OV64S 0x00000200 /* ORVDX64 supported */
+#define SPR_CPUCFGR_RES 0xfffffc00 /* Reserved */
+
+/*
+ * Bit definitions for the Debug configuration register and other
+ * constants.
+ */
+
+#define SPR_DCFGR_NDP 0x00000007 /* Number of matchpoints mask */
+#define SPR_DCFGR_NDP1 0x00000000 /* One matchpoint supported */
+#define SPR_DCFGR_NDP2 0x00000001 /* Two matchpoints supported */
+#define SPR_DCFGR_NDP3 0x00000002 /* Three matchpoints supported */
+#define SPR_DCFGR_NDP4 0x00000003 /* Four matchpoints supported */
+#define SPR_DCFGR_NDP5 0x00000004 /* Five matchpoints supported */
+#define SPR_DCFGR_NDP6 0x00000005 /* Six matchpoints supported */
+#define SPR_DCFGR_NDP7 0x00000006 /* Seven matchpoints supported */
+#define SPR_DCFGR_NDP8 0x00000007 /* Eight matchpoints supported */
+#define SPR_DCFGR_WPCI 0x00000008 /* Watchpoint counters implemented */
+
+#define MATCHPOINTS_TO_NDP(n) (1 == n ? SPR_DCFGR_NDP1 : \
+ 2 == n ? SPR_DCFGR_NDP2 : \
+ 3 == n ? SPR_DCFGR_NDP3 : \
+ 4 == n ? SPR_DCFGR_NDP4 : \
+ 5 == n ? SPR_DCFGR_NDP5 : \
+ 6 == n ? SPR_DCFGR_NDP6 : \
+ 7 == n ? SPR_DCFGR_NDP7 : SPR_DCFGR_NDP8)
+#define MAX_MATCHPOINTS 8
+#define MAX_WATCHPOINTS (MAX_MATCHPOINTS + 2)
+
+/*
+ * Bit definitions for the Supervision Register
+ */
+#define SPR_SR_SM 0x00000001 /* Supervisor Mode */
+#define SPR_SR_TEE 0x00000002 /* Tick timer Exception Enable */
+#define SPR_SR_IEE 0x00000004 /* Interrupt Exception Enable */
+#define SPR_SR_DCE 0x00000008 /* Data Cache Enable */
+#define SPR_SR_ICE 0x00000010 /* Instruction Cache Enable */
+#define SPR_SR_DME 0x00000020 /* Data MMU Enable */
+#define SPR_SR_IME 0x00000040 /* Instruction MMU Enable */
+#define SPR_SR_LEE 0x00000080 /* Little Endian Enable */
+#define SPR_SR_CE 0x00000100 /* CID Enable */
+#define SPR_SR_F 0x00000200 /* Condition Flag */
+#define SPR_SR_CY 0x00000400 /* Carry flag */
+#define SPR_SR_OV 0x00000800 /* Overflow flag */
+#define SPR_SR_OVE 0x00001000 /* Overflow flag Exception */
+#define SPR_SR_DSX 0x00002000 /* Delay Slot Exception */
+#define SPR_SR_EPH 0x00004000 /* Exception Prefix High */
+#define SPR_SR_FO 0x00008000 /* Fixed one */
+#define SPR_SR_SUMRA 0x00010000 /* Supervisor SPR read access */
+#define SPR_SR_RES 0x0ffe0000 /* Reserved */
+#define SPR_SR_CID 0xf0000000 /* Context ID */
+
+/*
+ * Bit definitions for the Data MMU Control Register
+ */
+#define SPR_DMMUCR_P2S 0x0000003e /* Level 2 Page Size */
+#define SPR_DMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
+#define SPR_DMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
+#define SPR_DMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Instruction MMU Control Register
+ */
+#define SPR_IMMUCR_P2S 0x0000003e /* Level 2 Page Size */
+#define SPR_IMMUCR_P1S 0x000007c0 /* Level 1 Page Size */
+#define SPR_IMMUCR_VADDR_WIDTH 0x0000f800 /* Virtual ADDR Width */
+#define SPR_IMMUCR_PADDR_WIDTH 0x000f0000 /* Physical ADDR Width */
+
+/*
+ * Bit definitions for the Data TLB Match Register
+ */
+#define SPR_DTLBMR_V 0x00000001 /* Valid */
+#define SPR_DTLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
+#define SPR_DTLBMR_CID 0x0000003c /* Context ID */
+#define SPR_DTLBMR_LRU 0x000000c0 /* Least Recently Used */
+#define SPR_DTLBMR_VPN 0xfffff000 /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Data TLB Translate Register
+ */
+#define SPR_DTLBTR_CC 0x00000001 /* Cache Coherency */
+#define SPR_DTLBTR_CI 0x00000002 /* Cache Inhibit */
+#define SPR_DTLBTR_WBC 0x00000004 /* Write-Back Cache */
+#define SPR_DTLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
+#define SPR_DTLBTR_A 0x00000010 /* Accessed */
+#define SPR_DTLBTR_D 0x00000020 /* Dirty */
+#define SPR_DTLBTR_URE 0x00000040 /* User Read Enable */
+#define SPR_DTLBTR_UWE 0x00000080 /* User Write Enable */
+#define SPR_DTLBTR_SRE 0x00000100 /* Supervisor Read Enable */
+#define SPR_DTLBTR_SWE 0x00000200 /* Supervisor Write Enable */
+#define SPR_DTLBTR_PPN 0xfffff000 /* Physical Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Match Register
+ */
+#define SPR_ITLBMR_V 0x00000001 /* Valid */
+#define SPR_ITLBMR_PL1 0x00000002 /* Page Level 1 (if 0 then PL2) */
+#define SPR_ITLBMR_CID 0x0000003c /* Context ID */
+#define SPR_ITLBMR_LRU 0x000000c0 /* Least Recently Used */
+#define SPR_ITLBMR_VPN 0xfffff000 /* Virtual Page Number */
+
+/*
+ * Bit definitions for the Instruction TLB Translate Register
+ */
+#define SPR_ITLBTR_CC 0x00000001 /* Cache Coherency */
+#define SPR_ITLBTR_CI 0x00000002 /* Cache Inhibit */
+#define SPR_ITLBTR_WBC 0x00000004 /* Write-Back Cache */
+#define SPR_ITLBTR_WOM 0x00000008 /* Weakly-Ordered Memory */
+#define SPR_ITLBTR_A 0x00000010 /* Accessed */
+#define SPR_ITLBTR_D 0x00000020 /* Dirty */
+#define SPR_ITLBTR_SXE 0x00000040 /* User Read Enable */
+#define SPR_ITLBTR_UXE 0x00000080 /* User Write Enable */
+#define SPR_ITLBTR_PPN 0xfffff000 /* Physical Page Number */
+
+/*
+ * Bit definitions for Data Cache Control register
+ */
+#define SPR_DCCR_EW 0x000000ff /* Enable ways */
+
+/*
+ * Bit definitions for Insn Cache Control register
+ */
+#define SPR_ICCR_EW 0x000000ff /* Enable ways */
+
+/*
+ * Bit definitions for Data Cache Configuration Register
+ */
+
+#define SPR_DCCFGR_NCW 0x00000007
+#define SPR_DCCFGR_NCS 0x00000078
+#define SPR_DCCFGR_CBS 0x00000080
+#define SPR_DCCFGR_CWS 0x00000100
+#define SPR_DCCFGR_CCRI 0x00000200
+#define SPR_DCCFGR_CBIRI 0x00000400
+#define SPR_DCCFGR_CBPRI 0x00000800
+#define SPR_DCCFGR_CBLRI 0x00001000
+#define SPR_DCCFGR_CBFRI 0x00002000
+#define SPR_DCCFGR_CBWBRI 0x00004000
+
+#define SPR_DCCFGR_NCW_OFF 0
+#define SPR_DCCFGR_NCS_OFF 3
+#define SPR_DCCFGR_CBS_OFF 7
+
+/*
+ * Bit definitions for Instruction Cache Configuration Register
+ */
+#define SPR_ICCFGR_NCW 0x00000007
+#define SPR_ICCFGR_NCS 0x00000078
+#define SPR_ICCFGR_CBS 0x00000080
+#define SPR_ICCFGR_CCRI 0x00000200
+#define SPR_ICCFGR_CBIRI 0x00000400
+#define SPR_ICCFGR_CBPRI 0x00000800
+#define SPR_ICCFGR_CBLRI 0x00001000
+
+#define SPR_ICCFGR_NCW_OFF 0
+#define SPR_ICCFGR_NCS_OFF 3
+#define SPR_ICCFGR_CBS_OFF 7
+
+/*
+ * Bit definitions for Data MMU Configuration Register
+ */
+#define SPR_DMMUCFGR_NTW 0x00000003
+#define SPR_DMMUCFGR_NTS 0x0000001C
+#define SPR_DMMUCFGR_NAE 0x000000E0
+#define SPR_DMMUCFGR_CRI 0x00000100
+#define SPR_DMMUCFGR_PRI 0x00000200
+#define SPR_DMMUCFGR_TEIRI 0x00000400
+#define SPR_DMMUCFGR_HTR 0x00000800
+
+#define SPR_DMMUCFGR_NTW_OFF 0
+#define SPR_DMMUCFGR_NTS_OFF 2
+
+/*
+ * Bit definitions for Instruction MMU Configuration Register
+ */
+#define SPR_IMMUCFGR_NTW 0x00000003
+#define SPR_IMMUCFGR_NTS 0x0000001C
+#define SPR_IMMUCFGR_NAE 0x000000E0
+#define SPR_IMMUCFGR_CRI 0x00000100
+#define SPR_IMMUCFGR_PRI 0x00000200
+#define SPR_IMMUCFGR_TEIRI 0x00000400
+#define SPR_IMMUCFGR_HTR 0x00000800
+
+#define SPR_IMMUCFGR_NTW_OFF 0
+#define SPR_IMMUCFGR_NTS_OFF 2
+
+/*
+ * Bit definitions for Debug Control registers
+ */
+#define SPR_DCR_DP 0x00000001 /* DVR/DCR present */
+#define SPR_DCR_CC 0x0000000e /* Compare condition */
+#define SPR_DCR_SC 0x00000010 /* Signed compare */
+#define SPR_DCR_CT 0x000000e0 /* Compare to */
+
+/* Bit results with SPR_DCR_CC mask */
+#define SPR_DCR_CC_MASKED 0x00000000
+#define SPR_DCR_CC_EQUAL 0x00000002
+#define SPR_DCR_CC_LESS 0x00000004
+#define SPR_DCR_CC_LESSE 0x00000006
+#define SPR_DCR_CC_GREAT 0x00000008
+#define SPR_DCR_CC_GREATE 0x0000000a
+#define SPR_DCR_CC_NEQUAL 0x0000000c
+
+/* Bit results with SPR_DCR_CT mask */
+#define SPR_DCR_CT_DISABLED 0x00000000
+#define SPR_DCR_CT_IFEA 0x00000020
+#define SPR_DCR_CT_LEA 0x00000040
+#define SPR_DCR_CT_SEA 0x00000060
+#define SPR_DCR_CT_LD 0x00000080
+#define SPR_DCR_CT_SD 0x000000a0
+#define SPR_DCR_CT_LSEA 0x000000c0
+#define SPR_DCR_CT_LSD 0x000000e0
+
+/*
+ * Bit definitions for Debug Mode 1 register
+ */
+#define SPR_DMR1_CW 0x000fffff /* Chain register pair data */
+#define SPR_DMR1_CW0_AND 0x00000001
+#define SPR_DMR1_CW0_OR 0x00000002
+#define SPR_DMR1_CW0 (SPR_DMR1_CW0_AND | SPR_DMR1_CW0_OR)
+#define SPR_DMR1_CW1_AND 0x00000004
+#define SPR_DMR1_CW1_OR 0x00000008
+#define SPR_DMR1_CW1 (SPR_DMR1_CW1_AND | SPR_DMR1_CW1_OR)
+#define SPR_DMR1_CW2_AND 0x00000010
+#define SPR_DMR1_CW2_OR 0x00000020
+#define SPR_DMR1_CW2 (SPR_DMR1_CW2_AND | SPR_DMR1_CW2_OR)
+#define SPR_DMR1_CW3_AND 0x00000040
+#define SPR_DMR1_CW3_OR 0x00000080
+#define SPR_DMR1_CW3 (SPR_DMR1_CW3_AND | SPR_DMR1_CW3_OR)
+#define SPR_DMR1_CW4_AND 0x00000100
+#define SPR_DMR1_CW4_OR 0x00000200
+#define SPR_DMR1_CW4 (SPR_DMR1_CW4_AND | SPR_DMR1_CW4_OR)
+#define SPR_DMR1_CW5_AND 0x00000400
+#define SPR_DMR1_CW5_OR 0x00000800
+#define SPR_DMR1_CW5 (SPR_DMR1_CW5_AND | SPR_DMR1_CW5_OR)
+#define SPR_DMR1_CW6_AND 0x00001000
+#define SPR_DMR1_CW6_OR 0x00002000
+#define SPR_DMR1_CW6 (SPR_DMR1_CW6_AND | SPR_DMR1_CW6_OR)
+#define SPR_DMR1_CW7_AND 0x00004000
+#define SPR_DMR1_CW7_OR 0x00008000
+#define SPR_DMR1_CW7 (SPR_DMR1_CW7_AND | SPR_DMR1_CW7_OR)
+#define SPR_DMR1_CW8_AND 0x00010000
+#define SPR_DMR1_CW8_OR 0x00020000
+#define SPR_DMR1_CW8 (SPR_DMR1_CW8_AND | SPR_DMR1_CW8_OR)
+#define SPR_DMR1_CW9_AND 0x00040000
+#define SPR_DMR1_CW9_OR 0x00080000
+#define SPR_DMR1_CW9 (SPR_DMR1_CW9_AND | SPR_DMR1_CW9_OR)
+#define SPR_DMR1_RES1 0x00300000 /* Reserved */
+#define SPR_DMR1_ST 0x00400000 /* Single-step trace*/
+#define SPR_DMR1_BT 0x00800000 /* Branch trace */
+#define SPR_DMR1_RES2 0xff000000 /* Reserved */
+
+/*
+ * Bit definitions for Debug Mode 2 register. AWTC and WGB corrected by JPB
+ */
+#define SPR_DMR2_WCE0 0x00000001 /* Watchpoint counter 0 enable */
+#define SPR_DMR2_WCE1 0x00000002 /* Watchpoint counter 0 enable */
+#define SPR_DMR2_AWTC 0x00000ffc /* Assign watchpoints to counters */
+#define SPR_DMR2_AWTC_OFF 2 /* Bit offset to AWTC field */
+#define SPR_DMR2_WGB 0x003ff000 /* Watch generating breakpoint */
+#define SPR_DMR2_WGB_OFF 12 /* Bit offset to WGB field */
+#define SPR_DMR2_WBS 0xffc00000 /* Watchpoint status */
+#define SPR_DMR2_WBS_OFF 22 /* Bit offset to WBS field */
+
+/*
+ * Bit definitions for Debug watchpoint counter registers
+ */
+#define SPR_DWCR_COUNT 0x0000ffff /* Count */
+#define SPR_DWCR_MATCH 0xffff0000 /* Match */
+#define SPR_DWCR_MATCH_OFF 16 /* Match bit offset */
+
+/*
+ * Bit definitions for Debug stop register
+ *
+ */
+#define SPR_DSR_RSTE 0x00000001 /* Reset exception */
+#define SPR_DSR_BUSEE 0x00000002 /* Bus error exception */
+#define SPR_DSR_DPFE 0x00000004 /* Data Page Fault exception */
+#define SPR_DSR_IPFE 0x00000008 /* Insn Page Fault exception */
+#define SPR_DSR_TTE 0x00000010 /* Tick Timer exception */
+#define SPR_DSR_AE 0x00000020 /* Alignment exception */
+#define SPR_DSR_IIE 0x00000040 /* Illegal Instruction exception */
+#define SPR_DSR_IE 0x00000080 /* Interrupt exception */
+#define SPR_DSR_DME 0x00000100 /* DTLB miss exception */
+#define SPR_DSR_IME 0x00000200 /* ITLB miss exception */
+#define SPR_DSR_RE 0x00000400 /* Range exception */
+#define SPR_DSR_SCE 0x00000800 /* System call exception */
+#define SPR_DSR_FPE 0x00001000 /* Floating Point Exception */
+#define SPR_DSR_TE 0x00002000 /* Trap exception */
+
+/*
+ * Bit definitions for Debug reason register
+ */
+#define SPR_DRR_RSTE 0x00000001 /* Reset exception */
+#define SPR_DRR_BUSEE 0x00000002 /* Bus error exception */
+#define SPR_DRR_DPFE 0x00000004 /* Data Page Fault exception */
+#define SPR_DRR_IPFE 0x00000008 /* Insn Page Fault exception */
+#define SPR_DRR_TTE 0x00000010 /* Tick Timer exception */
+#define SPR_DRR_AE 0x00000020 /* Alignment exception */
+#define SPR_DRR_IIE 0x00000040 /* Illegal Instruction exception */
+#define SPR_DRR_IE 0x00000080 /* Interrupt exception */
+#define SPR_DRR_DME 0x00000100 /* DTLB miss exception */
+#define SPR_DRR_IME 0x00000200 /* ITLB miss exception */
+#define SPR_DRR_RE 0x00000400 /* Range exception */
+#define SPR_DRR_SCE 0x00000800 /* System call exception */
+#define SPR_DRR_FPE 0x00001000 /* Floating Point Exception */
+#define SPR_DRR_TE 0x00002000 /* Trap exception */
+
+/*
+ * Bit definitions for Performance counters mode registers
+ */
+#define SPR_PCMR_CP 0x00000001 /* Counter present */
+#define SPR_PCMR_UMRA 0x00000002 /* User mode read access */
+#define SPR_PCMR_CISM 0x00000004 /* Count in supervisor mode */
+#define SPR_PCMR_CIUM 0x00000008 /* Count in user mode */
+#define SPR_PCMR_LA 0x00000010 /* Load access event */
+#define SPR_PCMR_SA 0x00000020 /* Store access event */
+#define SPR_PCMR_IF 0x00000040 /* Instruction fetch event*/
+#define SPR_PCMR_DCM 0x00000080 /* Data cache miss event */
+#define SPR_PCMR_ICM 0x00000100 /* Insn cache miss event */
+#define SPR_PCMR_IFS 0x00000200 /* Insn fetch stall event */
+#define SPR_PCMR_LSUS 0x00000400 /* LSU stall event */
+#define SPR_PCMR_BS 0x00000800 /* Branch stall event */
+#define SPR_PCMR_DTLBM 0x00001000 /* DTLB miss event */
+#define SPR_PCMR_ITLBM 0x00002000 /* ITLB miss event */
+#define SPR_PCMR_DDS 0x00004000 /* Data dependency stall event */
+#define SPR_PCMR_WPE 0x03ff8000 /* Watchpoint events */
+
+/*
+ * Bit definitions for the Power management register
+ */
+#define SPR_PMR_SDF 0x0000000f /* Slow down factor */
+#define SPR_PMR_DME 0x00000010 /* Doze mode enable */
+#define SPR_PMR_SME 0x00000020 /* Sleep mode enable */
+#define SPR_PMR_DCGE 0x00000040 /* Dynamic clock gating enable */
+#define SPR_PMR_SUME 0x00000080 /* Suspend mode enable */
+
+/*
+ * Bit definitions for PICMR
+ */
+#define SPR_PICMR_IUM 0xfffffffc /* Interrupt unmask */
+
+/*
+ * Bit definitions for PICPR
+ */
+#define SPR_PICPR_IPRIO 0xfffffffc /* Interrupt priority */
+
+/*
+ * Bit definitions for PICSR
+ */
+#define SPR_PICSR_IS 0xffffffff /* Interrupt status */
+
+/*
+ * Bit definitions for Tick Timer Control Register
+ */
+#define SPR_TTCR_CNT 0xffffffff /* Count, time period */
+#define SPR_TTMR_TP 0x0fffffff /* Time period */
+#define SPR_TTMR_IP 0x10000000 /* Interrupt Pending */
+#define SPR_TTMR_IE 0x20000000 /* Interrupt Enable */
+#define SPR_TTMR_DI 0x00000000 /* Disabled */
+#define SPR_TTMR_RT 0x40000000 /* Restart tick */
+#define SPR_TTMR_SR 0x80000000 /* Single run */
+#define SPR_TTMR_CR 0xc0000000 /* Continuous run */
+#define SPR_TTMR_M 0xc0000000 /* Tick mode */
+
+/*
+ * Bit definitions for the FP Control Status Register
+ */
+#define SPR_FPCSR_FPEE 0x00000001 /* Floating Point Exception Enable */
+#define SPR_FPCSR_RM 0x00000006 /* Rounding Mode */
+#define SPR_FPCSR_OVF 0x00000008 /* Overflow Flag */
+#define SPR_FPCSR_UNF 0x00000010 /* Underflow Flag */
+#define SPR_FPCSR_SNF 0x00000020 /* SNAN Flag */
+#define SPR_FPCSR_QNF 0x00000040 /* QNAN Flag */
+#define SPR_FPCSR_ZF 0x00000080 /* Zero Flag */
+#define SPR_FPCSR_IXF 0x00000100 /* Inexact Flag */
+#define SPR_FPCSR_IVF 0x00000200 /* Invalid Flag */
+#define SPR_FPCSR_INF 0x00000400 /* Infinity Flag */
+#define SPR_FPCSR_DZF 0x00000800 /* Divide By Zero Flag */
+#define SPR_FPCSR_ALLF (SPR_FPCSR_OVF | SPR_FPCSR_UNF | SPR_FPCSR_SNF | \
+ SPR_FPCSR_QNF | SPR_FPCSR_ZF | SPR_FPCSR_IXF | \
+ SPR_FPCSR_IVF | SPR_FPCSR_INF | SPR_FPCSR_DZF)
+
+#define FPCSR_RM_RN (0<<1)
+#define FPCSR_RM_RZ (1<<1)
+#define FPCSR_RM_RIP (2<<1)
+#define FPCSR_RM_RIN (3<<1)
+
+/*
+ * l.nop constants
+ */
+#define NOP_NOP 0x0000 /* Normal nop instruction */
+#define NOP_EXIT 0x0001 /* End of simulation */
+#define NOP_REPORT 0x0002 /* Simple report */
+#define NOP_PUTC 0x0004 /* Simputc instruction */
+#define NOP_CNT_RESET 0x0005 /* Reset statistics counters */
+#define NOP_GET_TICKS 0x0006 /* Get # ticks running */
+#define NOP_GET_PS 0x0007 /* Get picosecs/cycle */
+#define NOP_REPORT_FIRST 0x0400 /* Report with number */
+#define NOP_REPORT_LAST 0x03ff /* Report with number */
+
+#endif /* SPR_DEFS__H */
diff --git a/arch/openrisc/include/asm/string.h b/arch/openrisc/include/asm/string.h
new file mode 100644
index 0000000000..73e265564a
--- /dev/null
+++ b/arch/openrisc/include/asm/string.h
@@ -0,0 +1,4 @@
+#ifndef __ASM_OPENRISC_STRING_H
+#define __ASM_OPENRISC_STRING_H
+
+#endif
diff --git a/arch/openrisc/include/asm/swab.h b/arch/openrisc/include/asm/swab.h
new file mode 100644
index 0000000000..b07e1d51f1
--- /dev/null
+++ b/arch/openrisc/include/asm/swab.h
@@ -0,0 +1,4 @@
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+#endif /* _ASM_SWAB_H */
diff --git a/arch/openrisc/include/asm/system.h b/arch/openrisc/include/asm/system.h
new file mode 100644
index 0000000000..d68036325a
--- /dev/null
+++ b/arch/openrisc/include/asm/system.h
@@ -0,0 +1,39 @@
+/*
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 __ASM_OPENRISC_SYSTEM_H
+#define __ASM_OPENRISC_SYSTEM_H
+
+#include <asm/spr-defs.h>
+
+static inline unsigned long mfspr(unsigned long add)
+{
+ unsigned long ret;
+
+ __asm__ __volatile__ ("l.mfspr %0,r0,%1" : "=r" (ret) : "K" (add));
+
+ return ret;
+}
+
+static inline void mtspr(unsigned long add, unsigned long val)
+{
+ __asm__ __volatile__ ("l.mtspr r0,%1,%0" : : "K" (add), "r" (val));
+}
+
+#endif /* __ASM_OPENRISC_SYSTEM_H */
diff --git a/arch/openrisc/include/asm/types.h b/arch/openrisc/include/asm/types.h
new file mode 100644
index 0000000000..55efa36c2b
--- /dev/null
+++ b/arch/openrisc/include/asm/types.h
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * 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 _ASM_TYPES_H
+#define _ASM_TYPES_H
+
+/*
+ * This file is never included by application software unless
+ * explicitly requested (e.g., via linux/types.h) in which case the
+ * application is Linux specific so (user-) name space pollution is
+ * not a major issue. However, for interoperability, libraries still
+ * need to be careful to avoid a name clashes.
+ */
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+/*typedef unsigned long phys_addr_t;*/
+typedef unsigned long phys_size_t;
+#endif /* __KERNEL__ */
+
+#endif /* _ASM_TYPES_H */
diff --git a/arch/openrisc/lib/Makefile b/arch/openrisc/lib/Makefile
new file mode 100644
index 0000000000..aaf93cbd20
--- /dev/null
+++ b/arch/openrisc/lib/Makefile
@@ -0,0 +1,6 @@
+obj-y += clock.o
+obj-y += board.o
+obj-y += cpuinfo.o
+obj-y += muldi3.o
+obj-y += lshrdi3.o
+obj-y += ashldi3.o
diff --git a/arch/openrisc/lib/ashldi3.S b/arch/openrisc/lib/ashldi3.S
new file mode 100644
index 0000000000..3e422fadc4
--- /dev/null
+++ b/arch/openrisc/lib/ashldi3.S
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * Extracted from gcc generated assembly.
+ *
+ * Extended precision shifts.
+ *
+ * R3/R4 (MSW, LSW) has 64 bit value
+ * R5 has shift count
+ * result in R11/R12
+ *
+ */
+
+.globl __ashldi3
+
+__ashldi3:
+ l.sfeqi r5,0x0
+ l.bf out /* if count = 0, go out */
+
+ l.addi r6,r0,0x20 /* r6 = 32 */
+ l.sub r6,r6,r5 /* r6 = 32 - count */
+ l.sfgtsi r6,0x0 /* if count >= 32 */
+ l.bnf more_than_32 /* branch to more_than_32 */
+ l.nop 0x0
+
+less_than_32:
+ l.srl r6,r4,r6 /* r6 gets the bits moved from LSW to MSW */
+ l.sll r3,r3,r5 /* shift MSW */
+ l.sll r4,r4,r5 /* shift LSW */
+ l.or r3,r6,r3 /* MSW gets bits shifted from LSW */
+
+out:
+ l.ori r11,r3,0x0
+ l.jr r9
+ l.ori r12,r4,0x0
+
+more_than_32:
+ l.sub r3,r0,r6 /* r3 = -r6, the number of bits above 32 */
+ l.sll r3,r4,r3 /* MSW = LSW << r3 */
+ l.j out /* go out */
+ l.addi r4,r0,0x0 /* LSW = 0 */
diff --git a/arch/openrisc/lib/board.c b/arch/openrisc/lib/board.c
new file mode 100644
index 0000000000..a2158cb0c0
--- /dev/null
+++ b/arch/openrisc/lib/board.c
@@ -0,0 +1,42 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <init.h>
+#include <memory.h>
+#include <asm-generic/memory_layout.h>
+
+int openrisc_mem_malloc_init(void)
+{
+
+ mem_malloc_init((void *)(OPENRISC_SOPC_TEXT_BASE - MALLOC_SIZE),
+ (void *)(OPENRISC_SOPC_TEXT_BASE - 1));
+
+ return 0;
+}
+
+core_initcall(openrisc_mem_malloc_init);
+
+void arch_shutdown(void)
+{
+}
diff --git a/arch/openrisc/lib/clock.c b/arch/openrisc/lib/clock.c
new file mode 100644
index 0000000000..ab0a90d4dc
--- /dev/null
+++ b/arch/openrisc/lib/clock.c
@@ -0,0 +1,50 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <init.h>
+#include <asm/system.h>
+#include <asm/openrisc_exc.h>
+
+static uint64_t openrisc_clocksource_read(void)
+{
+ return (uint64_t)(mfspr(SPR_TTCR));
+}
+
+static struct clocksource cs = {
+ .read = openrisc_clocksource_read,
+ .mask = 0xffffffff,
+ .shift = 12,
+};
+
+static int clocksource_init(void)
+{
+ mtspr(SPR_TTMR, SPR_TTMR_CR | 0xFFFFFF);
+ cs.mult = clocksource_hz2mult(OPENRISC_TIMER_FREQ, cs.shift);
+
+ init_clock(&cs);
+
+ return 0;
+}
+
+core_initcall(clocksource_init);
diff --git a/arch/openrisc/lib/cpuinfo.c b/arch/openrisc/lib/cpuinfo.c
new file mode 100644
index 0000000000..3ec44c1b9b
--- /dev/null
+++ b/arch/openrisc/lib/cpuinfo.c
@@ -0,0 +1,156 @@
+/*
+ * (C) Copyright 2011, Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
+ * (C) Copyright 2011, Julius Baxter <julius@opencores.org>
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/system.h>
+#include <asm/cache.h>
+#include <asm/openrisc_exc.h>
+
+static volatile int illegal_instruction;
+
+static void illegal_instruction_handler(void)
+{
+ ulong *epcr = (ulong *)mfspr(SPR_EPCR_BASE);
+
+ /* skip over the illegal instruction */
+ mtspr(SPR_EPCR_BASE, (ulong)(++epcr));
+ illegal_instruction = 1;
+}
+
+static int checkinstructions(void)
+{
+ ulong ra = 1, rb = 1, rc;
+
+ exception_install_handler(EXC_ILLEGAL_INSTR,
+ illegal_instruction_handler);
+
+ illegal_instruction = 0;
+ asm volatile("l.mul %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
+ printf(" Hardware multiplier: %s\n",
+ illegal_instruction ? "no" : "yes");
+
+ illegal_instruction = 0;
+ asm volatile("l.div %0,%1,%2" : "=r" (rc) : "r" (ra), "r" (rb));
+ printf(" Hardware divider: %s\n",
+ illegal_instruction ? "no" : "yes");
+
+ exception_free_handler(EXC_ILLEGAL_INSTR);
+
+ return 0;
+}
+
+int checkcpu(void)
+{
+ ulong upr = mfspr(SPR_UPR);
+ ulong vr = mfspr(SPR_VR);
+ ulong iccfgr = mfspr(SPR_ICCFGR);
+ ulong dccfgr = mfspr(SPR_DCCFGR);
+ ulong immucfgr = mfspr(SPR_IMMUCFGR);
+ ulong dmmucfgr = mfspr(SPR_DMMUCFGR);
+ ulong cpucfgr = mfspr(SPR_CPUCFGR);
+ uint ver = (vr & SPR_VR_VER) >> 24;
+ uint rev = vr & SPR_VR_REV;
+ uint block_size;
+ uint ways;
+ uint sets;
+
+ printf("CPU: OpenRISC-%x00 (rev %d) @ %d MHz\n",
+ ver, rev, (CONFIG_SYS_CLK_FREQ / 1000000));
+
+ if (upr & SPR_UPR_DCP) {
+ block_size = (dccfgr & SPR_DCCFGR_CBS) ? 32 : 16;
+ ways = 1 << (dccfgr & SPR_DCCFGR_NCW);
+ printf(" D-Cache: %d bytes, %d bytes/line, %d way(s)\n",
+ checkdcache(), block_size, ways);
+ } else {
+ printf(" D-Cache: no\n");
+ }
+
+ if (upr & SPR_UPR_ICP) {
+ block_size = (iccfgr & SPR_ICCFGR_CBS) ? 32 : 16;
+ ways = 1 << (iccfgr & SPR_ICCFGR_NCW);
+ printf(" I-Cache: %d bytes, %d bytes/line, %d way(s)\n",
+ checkicache(), block_size, ways);
+ } else {
+ printf(" I-Cache: no\n");
+ }
+
+ if (upr & SPR_UPR_DMP) {
+ sets = 1 << ((dmmucfgr & SPR_DMMUCFGR_NTS) >> 2);
+ ways = (dmmucfgr & SPR_DMMUCFGR_NTW) + 1;
+ printf(" DMMU: %d sets, %d way(s)\n",
+ sets, ways);
+ } else {
+ printf(" DMMU: no\n");
+ }
+
+ if (upr & SPR_UPR_IMP) {
+ sets = 1 << ((immucfgr & SPR_IMMUCFGR_NTS) >> 2);
+ ways = (immucfgr & SPR_IMMUCFGR_NTW) + 1;
+ printf(" IMMU: %d sets, %d way(s)\n",
+ sets, ways);
+ } else {
+ printf(" IMMU: no\n");
+ }
+
+ printf(" MAC unit: %s\n",
+ (upr & SPR_UPR_MP) ? "yes" : "no");
+ printf(" Debug unit: %s\n",
+ (upr & SPR_UPR_DUP) ? "yes" : "no");
+ printf(" Performance counters: %s\n",
+ (upr & SPR_UPR_PCUP) ? "yes" : "no");
+ printf(" Power management: %s\n",
+ (upr & SPR_UPR_PMP) ? "yes" : "no");
+ printf(" Interrupt controller: %s\n",
+ (upr & SPR_UPR_PICP) ? "yes" : "no");
+ printf(" Timer: %s\n",
+ (upr & SPR_UPR_TTP) ? "yes" : "no");
+ printf(" Custom unit(s): %s\n",
+ (upr & SPR_UPR_CUP) ? "yes" : "no");
+
+ printf(" Supported instructions:\n");
+ printf(" ORBIS32: %s\n",
+ (cpucfgr & SPR_CPUCFGR_OB32S) ? "yes" : "no");
+ printf(" ORBIS64: %s\n",
+ (cpucfgr & SPR_CPUCFGR_OB64S) ? "yes" : "no");
+ printf(" ORFPX32: %s\n",
+ (cpucfgr & SPR_CPUCFGR_OF32S) ? "yes" : "no");
+ printf(" ORFPX64: %s\n",
+ (cpucfgr & SPR_CPUCFGR_OF64S) ? "yes" : "no");
+
+ checkinstructions();
+
+ return 0;
+}
+
+static int do_cpuinfo(struct command *cmdtp, int argc, char *argv[])
+{
+ checkcpu();
+ return 0;
+}
+
+BAREBOX_CMD_START(cpuinfo)
+ .cmd = do_cpuinfo,
+ .usage = "Show info about CPU",
+BAREBOX_CMD_END
diff --git a/arch/openrisc/lib/lshrdi3.S b/arch/openrisc/lib/lshrdi3.S
new file mode 100644
index 0000000000..de30445f4e
--- /dev/null
+++ b/arch/openrisc/lib/lshrdi3.S
@@ -0,0 +1,41 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * Extracted from gcc generated assembly.
+ *
+ * Extended precision shifts.
+ *
+ * R3/R4 (MSW, LSW) has 64 bit value
+ * R5 has shift count
+ * result in R11/R12
+ *
+ */
+
+.globl __lshrdi3
+
+__lshrdi3:
+ l.sfeqi r5,0x0
+ l.bf out /* if count = 0, go out */
+
+ l.addi r6,r0,0x20 /* r6 = 32 */
+ l.sub r6,r6,r5 /* r6 = 32 - count */
+ l.sfgtsi r6,0x0 /* if count >= 32 */
+ l.bnf more_than_32 /* branch to more_than_32 */
+ l.nop 0x0
+
+less_than_32:
+ l.sll r6,r3,r6 /* r6 gets the bits moved from MSW to LSW */
+ l.srl r4,r4,r5 /* shift LSW */
+ l.srl r3,r3,r5 /* shift MSW */
+ l.or r4,r6,r4 /* LSW gets bits shifted from MSW */
+
+ out:
+ l.ori r11,r3,0x0
+ l.jr r9
+ l.ori r12,r4,0x0
+
+more_than_32:
+ l.sub r4,r0,r6 /* r4 = -r6, the number of bits above 32 */
+ l.srl r4,r3,r4 /* LSW = MSW >> r4 */
+ l.j out /* go out */
+ l.addi r3,r0,0x0 /* MSW = 0 */
diff --git a/arch/openrisc/lib/muldi3.S b/arch/openrisc/lib/muldi3.S
new file mode 100644
index 0000000000..902338a242
--- /dev/null
+++ b/arch/openrisc/lib/muldi3.S
@@ -0,0 +1,58 @@
+/*
+ * (C) Copyright 2011 - Franck JULLIEN <elec4fun@gmail.com>
+ *
+ * Extracted from gcc generated assembly.
+ *
+ * Multiply two quads. Hereafter, the illustration of what is going on :
+ *
+ * | r3 | r4 |
+ * | r5 | r6 |
+ * --------------------
+ * | r4 * r6 |
+ * | r3 * r6 | | +
+ * | r5 * r4 | | +
+ * | r3 * r5 | | | +
+ * ------------------------------------------- =
+ * | 64 bits result |
+ *
+ */
+
+.globl __muldi3
+
+__muldi3:
+ /* starts with the full 64 bits mul (r4 * r6) */
+ l.andi r7,r4,0xffff
+ l.srli r8,r4,0x10
+
+ l.andi r11,r6,0xffff
+ l.srli r12,r6,0x10
+
+ l.mul r13,r11,r7
+ l.mul r11,r11,r8
+ l.mul r7,r12,r7
+
+ l.srli r15,r13,0x10
+ l.add r7,r7,r15
+ l.add r7,r11,r7
+ l.sfleu r11,r7
+ l.bf no_carry
+ l.mul r8,r12,r8
+
+ l.movhi r15,0x1
+ l.add r8,r8,r15
+
+no_carry:
+ /* Now compute r3 * r6 */
+ l.mul r6,r6,r3
+ /* and r4 * r5 */
+ l.mul r4,r4,r5
+ /* finaly previous results and put the result in r11:r12 */
+ l.srli r3,r7,0x10
+ l.slli r7,r7,0x10
+ l.andi r13,r13,0xffff
+ l.add r8,r8,r3
+ l.add r11,r4,r6
+ l.add r12,r7,r13
+ l.add r11,r11,r8
+ l.jr r9
+ l.nop
diff --git a/arch/ppc/boards/pcm030/pcm030.c b/arch/ppc/boards/pcm030/pcm030.c
index 9c6ccb7bc8..80f1cbe7fa 100644
--- a/arch/ppc/boards/pcm030/pcm030.c
+++ b/arch/ppc/boards/pcm030/pcm030.c
@@ -191,12 +191,3 @@ void initdram (int board_type)
}
}
}
-
-#if defined(CONFIG_OF_FLAT_TREE) && defined(CONFIG_OF_BOARD_SETUP)
-void
-ft_board_setup(void *blob, bd_t *bd)
-{
- ft_cpu_setup(blob, bd);
-}
-#endif
-
diff --git a/arch/ppc/lib/board.c b/arch/ppc/lib/board.c
index 0e839eb053..a840c75204 100644
--- a/arch/ppc/lib/board.c
+++ b/arch/ppc/lib/board.c
@@ -23,7 +23,6 @@
#include <debug_ll.h>
#include <common.h>
-#include <watchdog.h>
#include <command.h>
#include <malloc.h>
#include <memory.h>
diff --git a/arch/ppc/lib/ppclinux.c b/arch/ppc/lib/ppclinux.c
index 471b3037fe..95dc83bfe5 100644
--- a/arch/ppc/lib/ppclinux.c
+++ b/arch/ppc/lib/ppclinux.c
@@ -2,7 +2,6 @@
#include <common.h>
#include <command.h>
-#include <watchdog.h>
#include <image.h>
#include <init.h>
#include <environment.h>
@@ -11,236 +10,17 @@
#include <errno.h>
#include <fs.h>
-#ifdef CONFIG_OF_FLAT_TREE
-#include <ft_build.h>
-#endif
-extern bd_t *bd;
-
-static int do_bootm_linux(struct image_data *idata)
+static int do_bootm_linux(struct image_data *data)
{
- ulong sp;
- ulong initrd_end = 0;
- ulong cmd_start, cmd_end;
- ulong initrd_high;
- int initrd_copy_to_ram = 1;
- char *cmdline;
- const char *c;
- bd_t *kbd;
- void (*kernel)(bd_t *, ulong, ulong, ulong, ulong);
-#ifdef CONFIG_OF_FLAT_TREE
- char *of_flat_tree = NULL;
-#endif
- image_header_t *os_header = &idata->os->header;
- image_header_t *initrd_header = NULL;
- void *os_data = NULL;
- void *initrd_data = NULL;
- void *of_data = NULL;
- struct image_handle *oftree_handle;
- unsigned long os_len, initrd_len;
-
- if (idata->initrd)
- initrd_header = &idata->initrd->header;
-
- printf("entering %s: os_header: %p initrd_header: %p oftree: %s\n",
- __FUNCTION__, os_header, initrd_header, idata->oftree);
-
- if (image_get_type(os_header) == IH_TYPE_MULTI) {
- unsigned long *data = (unsigned long *)(idata->os->data);
- unsigned long len1 = 0, len2 = 0;
-
- if (!*data) {
- printf("multifile image with 0 entries???\n");
- return -1;
- }
- os_len = ntohl(*data); /* first one is the kernel */
- data++;
-
- if (*data) {
- len1 = ntohl(*data); /* could be initrd or oftree */
- data++;
- }
-
- if (*data) {
- len2 = ntohl(*data); /* could be oftree */
- data++;
- }
-
- while (*data) /* skip all remaining files */
- data++;
-
- data++; /* skip terminating zero */
-
- os_data = (void *)ntohl(data);
+ void (*kernel)(void *, void *, unsigned long,
+ unsigned long, unsigned long);
- if (len2) {
- initrd_data = (void *)
- ((unsigned long)data + ((os_len + 3) & ~3));
- initrd_len = len1;
- of_data = (void *)
- ((unsigned long)initrd_data + ((initrd_len + 3) & ~3));
- } else if (len1) {
- /* We could check here if this is a multifile image
- * with only a kernel and an oftree. Original barebox
- * did not do this, so leave it out for now.
- */
- initrd_data = (void *)((unsigned long)data + ((os_len + 3) & ~3));
- initrd_len = len1;
- }
- } else {
- os_data = idata->os->data;
- printf("set os_data to %p\n", os_data);
- }
+ if (!data->os_res)
+ return -EINVAL;
- if (idata->initrd)
- initrd_data = idata->initrd->data;
-
-#ifdef CONFIG_OF_FLAT_TREE
- if (idata->oftree) {
- /* The oftree can be given either as an barebox image or as a
- * binary blob. First try to read it as an image.
- */
- oftree_handle = map_image(idata->oftree, 1);
- if (oftree_handle) {
- of_data = oftree_handle->data;
- } else {
- of_data = read_file(idata->oftree, 0);
- if (!of_data) {
- printf("could not read %s: %s\n", idata->oftree, errno_str());
- return -1;
- }
- }
- /* FIXME: check if this is really an oftree */
- }
-#endif
- printf("loading kernel.\n");
-
- if ((c = getenv ("initrd_high")) != NULL) {
- /* a value of "no" or a similar string will act like 0,
- * turning the "load high" feature off. This is intentional.
- */
- initrd_high = simple_strtoul(c, NULL, 16);
- if (initrd_high == ~0)
- initrd_copy_to_ram = 0;
- } else { /* not set, no restrictions to load high */
- initrd_high = ~0;
- }
-
-#ifdef CONFIG_LOGBUFFER
- kbd=gd->bd;
- /* Prevent initrd from overwriting logbuffer */
- if (initrd_high < (kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD))
- initrd_high = kbd->bi_memsize-LOGBUFF_LEN-LOGBUFF_OVERHEAD;
- debug ("## Logbuffer at 0x%08lX ", kbd->bi_memsize-LOGBUFF_LEN);
-#endif
+ kernel = (void *)(data->os_address + data->os_entry);
/*
- * Booting a (Linux) kernel image
- *
- * Allocate space for command line and board info - the
- * address should be as high as possible within the reach of
- * the kernel (see CFG_BOOTMAPSZ settings), but in unused
- * memory, which means far enough below the current stack
- * pointer.
- */
-
- asm( "mr %0,1": "=r"(sp) : );
-
- debug ("## Current stack ends at 0x%08lX ", sp);
-
- sp -= 2048; /* just to be sure */
- if (sp > CFG_BOOTMAPSZ)
- sp = CFG_BOOTMAPSZ;
- sp &= ~0xF;
-
- debug ("=> set upper limit to 0x%08lX\n", sp);
-
- cmdline = (char *)((sp - CONFIG_CBSIZE) & ~0xF);
- kbd = (bd_t *)(((ulong)cmdline - sizeof(bd_t)) & ~0xF);
-
- printf("cmdline: %p kbd: %p\n", cmdline, kbd);
-
- if ((c = getenv("bootargs")) == NULL)
- c = "";
-
- strcpy (cmdline, c);
-
- cmd_start = (ulong)cmdline;
- cmd_end = cmd_start + strlen(cmdline);
-
- init_board_data(kbd);
-
-#ifdef DEBUG
- printf ("## cmdline at 0x%08lX ... 0x%08lX\n", cmd_start, cmd_end);
-
-// do_bdinfo (NULL, 0, 0, NULL);
-#endif
-
- if ((c = getenv ("clocks_in_mhz")) != NULL) {
- /* convert all clock information to MHz */
- kbd->bi_intfreq /= 1000000L;
- kbd->bi_busfreq /= 1000000L;
-#if defined(CONFIG_MPC8220)
- kbd->bi_inpfreq /= 1000000L;
- kbd->bi_pcifreq /= 1000000L;
- kbd->bi_pevfreq /= 1000000L;
- kbd->bi_flbfreq /= 1000000L;
- kbd->bi_vcofreq /= 1000000L;
-#endif
-#if defined(CONFIG_CPM2)
- kbd->bi_cpmfreq /= 1000000L;
- kbd->bi_brgfreq /= 1000000L;
- kbd->bi_sccfreq /= 1000000L;
- kbd->bi_vco /= 1000000L;
-#endif
-#if defined(CONFIG_MPC5xxx)
- kbd->bi_ipbfreq /= 1000000L;
- kbd->bi_pcifreq /= 1000000L;
-#endif /* CONFIG_MPC5xxx */
- }
-
- kernel = (void (*)(bd_t *, ulong, ulong, ulong, ulong))image_get_ep(os_header); /* FIXME */
-
-#if defined(CFG_INIT_RAM_LOCK) && !defined(CONFIG_E500)
- unlock_ram_in_cache();
-#endif
-
-#ifdef CONFIG_OF_FLAT_TREE
- /* move of_flat_tree if needed */
- if (of_data) {
- ulong of_start, of_len;
- of_len = ((struct boot_param_header *)of_data)->totalsize;
- /* provide extra 8k pad */
- if (initrd_data)
- of_start = (unsigned long)initrd_data - of_len - 8192;
- else
- of_start = (ulong)kbd - of_len - 8192;
- of_start &= ~(4096 - 1); /* align on page */
- debug ("## device tree at 0x%p ... 0x%p (len=%ld=0x%lX)\n",
- of_data, of_data + of_len - 1, of_len, of_len);
-
- of_flat_tree = (char *)of_start;
- printf (" Loading Device Tree to %08lx, end %08lx ... ",
- of_start, of_start + of_len - 1);
- memmove ((void *)of_start, (void *)of_data, of_len);
- }
-#endif
-
- /*
- * Linux Kernel Parameters (passing board info data):
- * r3: ptr to board info data
- * r4: initrd_start or 0 if no initrd
- * r5: initrd_end - unused if r4 is 0
- * r6: Start of command line string
- * r7: End of command line string
- */
-#ifdef CONFIG_OF_FLAT_TREE
- if (!of_flat_tree) /* no device tree; boot old style */
-#endif
- (*kernel) (kbd, (ulong)initrd_data, initrd_end, cmd_start, cmd_end);
- /* does not return */
-
-#ifdef CONFIG_OF_FLAT_TREE
- /*
* Linux Kernel Parameters (passing device tree):
* r3: ptr to OF flat tree, followed by the board info data
* r4: physical pointer to the kernel itself
@@ -248,11 +28,8 @@ static int do_bootm_linux(struct image_data *idata)
* r6: NULL
* r7: NULL
*/
- ft_setup(of_flat_tree, kbd, (long)initrd_data, initrd_end);
- ft_cpu_setup(of_flat_tree, kbd);
+ kernel(data->oftree, kernel, 0, 0, 0);
- (*kernel) ((bd_t *)of_flat_tree, (ulong)kernel, 0, 0, 0);
-#endif
reset_cpu(0);
/* not reached */
@@ -260,8 +37,10 @@ static int do_bootm_linux(struct image_data *idata)
}
static struct image_handler handler = {
+ .name = "PowerPC Linux",
.bootm = do_bootm_linux,
- .image_type = IH_OS_LINUX,
+ .filetype = filetype_uimage,
+ .ih_os = IH_OS_LINUX,
};
static int ppclinux_register_image_handler(void)
@@ -270,4 +49,3 @@ static int ppclinux_register_image_handler(void)
}
late_initcall(ppclinux_register_image_handler);
-
diff --git a/arch/ppc/lib/ticks.S b/arch/ppc/lib/ticks.S
index 5d6c4277af..453d889213 100644
--- a/arch/ppc/lib/ticks.S
+++ b/arch/ppc/lib/ticks.S
@@ -26,7 +26,6 @@
#include <asm/ppc_asm.tmpl>
#include <asm/ppc_defs.h>
#include <config.h>
-#include <watchdog.h>
/*
* unsigned long long get_ticks(void);
diff --git a/arch/ppc/mach-mpc5xxx/cpu.c b/arch/ppc/mach-mpc5xxx/cpu.c
index d695b9b545..62ddb1fbe2 100644
--- a/arch/ppc/mach-mpc5xxx/cpu.c
+++ b/arch/ppc/mach-mpc5xxx/cpu.c
@@ -34,12 +34,9 @@
#include <init.h>
#include <types.h>
#include <errno.h>
+#include <of.h>
#include <mach/clocks.h>
-#if defined(CONFIG_OF_FLAT_TREE)
-#include <ft_build.h>
-#endif
-
int checkcpu (void)
{
ulong clock = get_cpu_clock();
@@ -83,27 +80,26 @@ void __noreturn reset_cpu (unsigned long addr)
/* ------------------------------------------------------------------------- */
-#ifdef CONFIG_OF_FLAT_TREE
-void
-ft_cpu_setup(void *blob, bd_t *bd)
+#ifdef CONFIG_OFTREE
+static int of_mpc5200_fixup(struct fdt_header *fdt)
+{
+ char *cpu_path = "/cpus/PowerPC,5200@0";
+ int div = in_8((void*)CFG_MBAR + 0x204) & 0x0020 ? 8 : 4;
+
+ do_fixup_by_path_u32(fdt, cpu_path, "timebase-frequency", get_timebase_clock(), 1);
+ do_fixup_by_path_u32(fdt, cpu_path, "bus-frequency", get_bus_clock(), 1);
+ do_fixup_by_path_u32(fdt, cpu_path, "clock-frequency", get_cpu_clock(), 1);
+ do_fixup_by_path_u32(fdt, "/soc5200@f0000000", "bus-frequency", get_ipb_clock(), 1);
+ do_fixup_by_path_u32(fdt, "/soc5200@f0000000", "system-frequency",
+ get_bus_clock() * div, 1);
+ return 0;
+}
+
+static int of_register_mpc5200_fixup(void)
{
- u32 *p;
- int len;
-
- /* Core XLB bus frequency */
- p = ft_get_prop(blob, "/cpus/" OF_CPU "/bus-frequency", &len);
- if (p != NULL)
- *p = cpu_to_be32(get_bus_clock());
-
- /* SOC peripherals use the IPB bus frequency */
- p = ft_get_prop(blob, "/" OF_SOC "/bus-frequency", &len);
- if (p != NULL)
- *p = cpu_to_be32(get_ipb_clock());
-
- p = ft_get_prop(blob, "/" OF_SOC "/ethernet@3000/mac-address", &len);
- if (p != NULL)
- memcpy(p, bd->bi_enetaddr, 6);
+ return of_register_fixup(of_mpc5200_fixup);
}
+late_initcall(of_register_mpc5200_fixup);
#endif
int cpu_init_board_data(bd_t *bd)
diff --git a/commands/Kconfig b/commands/Kconfig
index ebc9c7f2d0..6f9ccb82c9 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -173,6 +173,13 @@ config CMD_NAND
depends on NAND
prompt "nand"
+config CMD_NANDTEST
+ tristate
+ depends on NAND
+ depends on PARTITION
+ depends on NAND_ECC_HW || NAND_ECC_SOFT
+ prompt "nandtest"
+
endmenu
menu "console "
@@ -310,11 +317,41 @@ config CMD_BOOTM_SHOW_TYPE
depends on CMD_BOOTM
prompt "show image information"
-config CMD_IMINFO
+config CMD_BOOTM_VERBOSE
+ bool
+ prompt "bootm verbose support"
+ depends on CMD_BOOTM
+ help
+ support verbose bootm (-v switch)
+
+config CMD_BOOTM_INITRD
bool
- prompt "iminfo"
+ prompt "bootm initrd support"
+ depends on CMD_BOOTM
+ help
+ support initrds in bootm
+
+config CMD_BOOTM_OFTREE
+ bool
+ depends on CMD_BOOTM
+ select OFTREE
+ prompt "bootm oftree support"
+ help
+ say yes here to support passing a flat device tree to the kernel
+
+config CMD_BOOTM_OFTREE_UIMAGE
+ bool
+ prompt "support passing oftree uImages"
+ depends on CMD_BOOTM_OFTREE
+ help
+ Support using oftree uImages. Without this only raw oftree
+ blobs can be used.
+
+config CMD_UIMAGE
+ tristate
+ prompt "uimage"
help
- Show information about uImages
+ Show information about uImage and also extract and verify uImages.
config CMD_BOOTZ
tristate
diff --git a/commands/Makefile b/commands/Makefile
index aa013de107..31442b5ad4 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_CMD_BOOTM) += bootm.o
-obj-$(CONFIG_CMD_IMINFO) += iminfo.o
+obj-$(CONFIG_CMD_UIMAGE) += uimage.o
obj-$(CONFIG_CMD_LINUX16) += linux16.o
obj-$(CONFIG_CMD_LOADB) += loadb.o xyzModem.o
obj-$(CONFIG_CMD_LOADY) += loadb.o xyzModem.o
@@ -39,6 +39,7 @@ obj-$(CONFIG_CMD_PRINTENV) += printenv.o
obj-$(CONFIG_CMD_SAVEENV) += saveenv.o
obj-$(CONFIG_CMD_LOADENV) += loadenv.o
obj-$(CONFIG_CMD_NAND) += nand.o
+obj-$(CONFIG_CMD_NANDTEST) += nandtest.o
obj-$(CONFIG_CMD_TRUE) += true.o
obj-$(CONFIG_CMD_FALSE) += false.o
obj-$(CONFIG_CMD_VERSION) += version.o
@@ -47,6 +48,7 @@ obj-$(CONFIG_CMD_LSMOD) += lsmod.o
obj-$(CONFIG_CMD_INSMOD) += insmod.o
obj-$(CONFIG_CMD_BMP) += bmp.o
obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
+obj-$(CONFIG_USB_GADGET_SERIAL) += usbserial.o
obj-$(CONFIG_CMD_GPIO) += gpio.o
obj-$(CONFIG_CMD_UNCOMPRESS) += uncompress.o
obj-$(CONFIG_CMD_I2C) += i2c.o
diff --git a/commands/bootm.c b/commands/bootm.c
index f97a842232..c23f4f3996 100644
--- a/commands/bootm.c
+++ b/commands/bootm.c
@@ -25,7 +25,6 @@
* Boot support
*/
#include <common.h>
-#include <watchdog.h>
#include <driver.h>
#include <command.h>
#include <image.h>
@@ -38,198 +37,411 @@
#include <fs.h>
#include <errno.h>
#include <boot.h>
+#include <of.h>
+#include <libfdt.h>
#include <rtc.h>
#include <init.h>
+#include <of.h>
#include <magicvar.h>
#include <uncompress.h>
+#include <memory.h>
+#include <filetype.h>
#include <asm-generic/memory_layout.h>
-struct image_handle_data* image_handle_data_get_by_num(struct image_handle* handle, int num)
+static LIST_HEAD(handler_list);
+
+#ifdef CONFIG_CMD_BOOTM_INITRD
+static inline int bootm_initrd(struct image_data *data)
+{
+ return data->initrd ? 1 : 0;
+}
+#else
+static inline int bootm_initrd(struct image_data *data)
{
- if (!handle || num < 0 || num >= handle->nb_data_entries)
- return NULL;
+ return 0;
+}
+#endif
- return &handle->data_entries[num];
+int register_image_handler(struct image_handler *handler)
+{
+ list_add_tail(&handler->list, &handler_list);
+ return 0;
}
-int relocate_image(struct image_handle *handle, void *load_address)
+#define UIMAGE_SOME_ADDRESS (UIMAGE_INVALID_ADDRESS - 1)
+
+static int bootm_open_os_uimage(struct image_data *data)
{
- image_header_t *hdr = &handle->header;
- unsigned long len = image_get_size(hdr);
- struct image_handle_data *iha;
- void *data;
int ret;
- iha = image_handle_data_get_by_num(handle, 0);
- data = iha->data;
+ data->os = uimage_open(data->os_file);
+ if (!data->os)
+ return -EINVAL;
- switch (image_get_comp(hdr)) {
- case IH_COMP_NONE:
- if (load_address == data) {
- printf (" XIP ... ");
- } else {
- memmove(load_address, data, len);
- }
- break;
- default:
- printf (" Uncompressing ... ");
- ret = uncompress(data, len, NULL, NULL, load_address, NULL,
- uncompress_err_stdout);
- if (ret)
+ if (data->verify) {
+ ret = uimage_verify(data->os);
+ if (ret) {
+ printf("Checking data crc failed with %s\n",
+ strerror(-ret));
return ret;
- break;
+ }
+ }
+
+ uimage_print_contents(data->os);
+
+ if (data->os->header.ih_arch != IH_ARCH) {
+ printf("Unsupported Architecture 0x%x\n",
+ data->os->header.ih_arch);
+ return -EINVAL;
+ }
+
+ if (data->os_address == UIMAGE_SOME_ADDRESS)
+ data->os_address = data->os->header.ih_load;
+
+ if (data->os_address != UIMAGE_INVALID_ADDRESS) {
+ data->os_res = uimage_load_to_sdram(data->os, 0,
+ data->os_address);
+ if (!data->os_res)
+ return -ENOMEM;
}
return 0;
}
-EXPORT_SYMBOL(relocate_image);
-
-static LIST_HEAD(handler_list);
-int register_image_handler(struct image_handler *handler)
+static int bootm_open_initrd_uimage(struct image_data *data)
{
- list_add_tail(&handler->list, &handler_list);
+ int ret;
+
+ if (!data->initrd_file)
+ return 0;
+
+ if (strcmp(data->os_file, data->initrd_file)) {
+ data->initrd = uimage_open(data->initrd_file);
+ if (!data->initrd)
+ return -EINVAL;
+
+ if (data->verify) {
+ ret = uimage_verify(data->initrd);
+ if (ret) {
+ printf("Checking data crc failed with %s\n",
+ strerror(-ret));
+ }
+ }
+ uimage_print_contents(data->initrd);
+ } else {
+ data->initrd = data->os;
+ }
+
+ if (data->initrd_address == UIMAGE_SOME_ADDRESS)
+ data->initrd_address = data->initrd->header.ih_load;
+
+ if (data->initrd_address != UIMAGE_INVALID_ADDRESS) {
+ data->initrd_res = uimage_load_to_sdram(data->initrd,
+ data->initrd_num,
+ data->initrd_address);
+ if (!data->initrd_res)
+ return -ENOMEM;
+ }
+
return 0;
}
-/*
- * generate a image_handle from a multi_image
- * this image_handle can be freed by unmap_image
- */
-static struct image_handle *get_fake_image_handle(struct image_data *data, int num)
+#ifdef CONFIG_OFTREE
+static int bootm_open_oftree(struct image_data *data, char *oftree, int num)
{
- struct image_handle *handle;
- struct image_handle_data* iha;
- image_header_t *header;
+ enum filetype ft;
+ struct fdt_header *fdt;
+ int ret;
+ size_t size;
+
+ ft = file_name_detect_type(oftree);
+ if ((int)ft < 0)
+ return ft;
- iha = image_handle_data_get_by_num(data->os, num);
+ if (ft == filetype_uimage) {
+#ifdef CONFIG_CMD_BOOTM_OFTREE_UIMAGE
+ struct uimage_handle *of_handle;
+ int release = 0;
- handle = xzalloc(sizeof(struct image_handle));
- header = &handle->header;
- handle->data_entries = gen_image_handle_data(iha->data, iha->len);
- handle->nb_data_entries = 1;
- header->ih_size = cpu_to_uimage(iha->len);
- handle->data = handle->data_entries[0].data;
+ if (!strcmp(data->os_file, oftree)) {
+ of_handle = data->os;
+ } else if (!strcmp(data->initrd_file, oftree)) {
+ of_handle = data->initrd;
+ } else {
+ of_handle = uimage_open(oftree);
+ if (!of_handle)
+ return -ENODEV;
+ uimage_print_contents(of_handle);
+ release = 1;
+ }
+
+ fdt = uimage_load_to_buf(of_handle, num, &size);
+
+ if (release)
+ uimage_close(of_handle);
+#else
+ return -EINVAL;
+#endif
+ } else {
+ fdt = read_file(oftree, &size);
+ if (!fdt) {
+ perror("open");
+ return -ENODEV;
+ }
+ }
+
+ ft = file_detect_type(fdt);
+ if (ft != filetype_oftree) {
+ printf("%s is not a oftree but %s\n", oftree,
+ file_type_to_string(ft));
+ }
+
+ if (bootm_verbose(data))
+ printf("Loading oftree from '%s'\n", oftree);
+
+ fdt = xrealloc(fdt, size + 0x8000);
+ fdt_open_into(fdt, fdt, size + 0x8000);
+
+ if (!fdt) {
+ printf("unable to read %s\n", oftree);
+ return -ENODEV;
+ }
+
+ ret = of_fix_tree(fdt);
+ if (ret)
+ return ret;
- return handle;
+ if (bootm_verbose(data) > 1)
+ fdt_print(fdt, "/");
+
+ data->oftree = fdt;
+
+ return ret;
+}
+#endif
+
+static struct image_handler *bootm_find_handler(enum filetype filetype,
+ struct image_data *data)
+{
+ struct image_handler *handler;
+
+ list_for_each_entry(handler, &handler_list, list) {
+ if (filetype != filetype_uimage &&
+ handler->filetype == filetype)
+ return handler;
+ if (filetype == filetype_uimage &&
+ handler->ih_os == data->os->header.ih_os)
+ return handler;
+ }
+
+ return NULL;
+}
+
+static void bootm_image_name_and_no(char *name, int *no)
+{
+ char *at;
+
+ *no = 0;
+
+ at = strchr(name, '@');
+ if (!at)
+ return;
+
+ *at++ = 0;
+
+ *no = simple_strtoul(at, NULL, 10);
}
static int do_bootm(struct command *cmdtp, int argc, char *argv[])
{
- int opt;
- image_header_t *os_header;
- struct image_handle *os_handle = NULL;
+ int opt;
struct image_handler *handler;
struct image_data data;
- const char *initrdname = NULL;
int ret = 1;
+ enum filetype os_type, initrd_type = filetype_unknown;
+ char *oftree = NULL;
+ int fallback = 0;
memset(&data, 0, sizeof(struct image_data));
- data.verify = 1;
- data.initrd_address = ~0;
- while ((opt = getopt(argc, argv, "nr:L:")) > 0) {
+ data.initrd_address = UIMAGE_SOME_ADDRESS;
+ data.os_address = UIMAGE_SOME_ADDRESS;
+ data.verify = 0;
+ data.verbose = 0;
+
+ while ((opt = getopt(argc, argv, "cL:r:a:e:vo:f")) > 0) {
switch(opt) {
- case 'n':
- data.verify = 0;
+ case 'c':
+ data.verify = 1;
break;
+#ifdef CONFIG_CMD_BOOTM_INITRD
case 'L':
data.initrd_address = simple_strtoul(optarg, NULL, 0);
break;
case 'r':
- initrdname = optarg;
+ data.initrd_file = optarg;
+ break;
+#endif
+ case 'a':
+ data.os_address = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'e':
+ data.os_entry = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ data.verbose++;
+ break;
+ case 'o':
+ oftree = optarg;
+ break;
+ case 'f':
+ fallback = 1;
break;
default:
break;
}
}
- if (optind == argc) {
- ret = COMMAND_ERROR_USAGE;
- goto err_out;
- }
+ if (optind == argc)
+ return COMMAND_ERROR_USAGE;
- os_handle = map_image(argv[optind], data.verify);
- if (!os_handle)
- goto err_out;
- data.os = os_handle;
+ data.os_file = argv[optind];
- os_header = &os_handle->header;
+ bootm_image_name_and_no(data.os_file, &data.os_num);
- if (image_get_arch(os_header) != IH_ARCH) {
- printf("Unsupported Architecture 0x%x\n",
- image_get_arch(os_header));
+ os_type = file_name_detect_type(data.os_file);
+ if ((int)os_type < 0) {
+ printf("could not open %s: %s\n", data.os_file,
+ strerror(-os_type));
goto err_out;
}
- if (initrdname) {
- /* check for multi image @<num> */
- if (initrdname[0] == '@') {
- int num = simple_strtol(optarg + 1, NULL, 0);
+ if (!fallback && os_type == filetype_unknown) {
+ printf("Unknown OS filetype (try -f)\n");
+ goto err_out;
+ }
- data.initrd = get_fake_image_handle(&data, num);
- } else {
- data.initrd = map_image(optarg, data.verify);
+ if (os_type == filetype_uimage) {
+ ret = bootm_open_os_uimage(&data);
+ if (ret) {
+ printf("loading initrd failed with %s\n",
+ strerror(-ret));
+ goto err_out;
}
- if (!data.initrd)
+ }
+
+ if (bootm_initrd(&data)) {
+ bootm_image_name_and_no(data.initrd_file, &data.initrd_num);
+
+ initrd_type = file_name_detect_type(data.initrd_file);
+ if ((int)initrd_type < 0) {
+ printf("could not open %s: %s\n", data.initrd_file,
+ strerror(-initrd_type));
goto err_out;
+ }
+ if (initrd_type == filetype_uimage) {
+ ret = bootm_open_initrd_uimage(&data);
+ if (ret) {
+ printf("loading initrd failed with %s\n",
+ strerror(-ret));
+ goto err_out;
+ }
+ }
}
- /*
- * We have reached the point of no return: we are going to
- * overwrite all exception vector code, so we cannot easily
- * recover from any failures any more...
- */
-
- puts ("OK\n");
-
- /*
- * FIXME: we do not check at all whether
- * - we will write the image to sdram
- * - we overwrite ourselves
- * - kernel and initrd overlap
- */
- ret = relocate_image(data.os, (void *)image_get_load(os_header));
- if (ret)
- goto err_out;
+ if (bootm_verbose(&data)) {
+ printf("\nLoading OS %s '%s'", file_type_to_string(os_type),
+ data.os_file);
+ if (os_type == filetype_uimage &&
+ data.os->header.ih_type == IH_TYPE_MULTI)
+ printf(", multifile image %d", data.os_num);
+ printf("\n");
+ if (data.os_res)
+ printf("OS image is at 0x%08x-0x%08x\n",
+ data.os_res->start,
+ data.os_res->start +
+ data.os_res->size - 1);
+ else
+ printf("OS image not yet relocated\n");
+
+ if (data.initrd_file) {
+ printf("Loading initrd %s '%s'",
+ file_type_to_string(initrd_type),
+ data.initrd_file);
+ if (initrd_type == filetype_uimage &&
+ data.initrd->header.ih_type == IH_TYPE_MULTI)
+ printf(", multifile image %d", data.initrd_num);
+ printf("\n");
+ if (data.initrd_res)
+ printf("initrd is at 0x%08x-0x%08x\n",
+ data.initrd_res->start,
+ data.initrd_res->start +
+ data.initrd_res->size - 1);
+ else
+ printf("initrd image not yet relocated\n");
+ }
+ }
- if (data.initrd) {
- if (data.initrd && data.initrd_address == ~0)
- data.initrd_address = uimage_to_cpu(data.initrd->header.ih_load);
+#ifdef CONFIG_OFTREE
+ if (oftree) {
+ int oftree_num;
- data.initrd_size = image_get_data_size(&data.initrd->header);
+ bootm_image_name_and_no(oftree, &oftree_num);
- ret = relocate_image(data.initrd, (void *)data.initrd_address);
+ ret = bootm_open_oftree(&data, oftree, oftree_num);
if (ret)
goto err_out;
}
-
- /* loop through the registered handlers */
- list_for_each_entry(handler, &handler_list, list) {
- if (image_get_os(os_header) == handler->image_type) {
- handler->bootm(&data);
- printf("handler returned!\n");
- goto err_out;
- }
+#endif
+ if (data.os_address == UIMAGE_SOME_ADDRESS)
+ data.os_address = UIMAGE_INVALID_ADDRESS;
+ if (data.initrd_address == UIMAGE_SOME_ADDRESS)
+ data.initrd_address = UIMAGE_INVALID_ADDRESS;
+
+ handler = bootm_find_handler(os_type, &data);
+ if (!handler) {
+ printf("no image handler found for image type %s\n",
+ file_type_to_string(os_type));
+ if (os_type == filetype_uimage)
+ printf("and os type: %d\n", data.os->header.ih_os);
+ goto err_out;
}
- printf("no image handler found for image type %d\n",
- image_get_os(os_header));
+ if (bootm_verbose(&data))
+ printf("Passing control to %s handler\n", handler->name);
+
+ ret = handler->bootm(&data);
+
+ printf("handler failed with %s\n", strerror(-ret));
err_out:
- if (os_handle)
- unmap_image(os_handle);
- if (data.initrd)
- unmap_image(data.initrd);
- return ret;
+ if (data.os_res)
+ release_sdram_region(data.os_res);
+ if (data.initrd_res)
+ release_sdram_region(data.initrd_res);
+ if (data.initrd && data.initrd != data.os)
+ uimage_close(data.initrd);
+ if (data.os)
+ uimage_close(data.os);
+ return 1;
}
BAREBOX_CMD_HELP_START(bootm)
BAREBOX_CMD_HELP_USAGE("bootm [OPTIONS] image\n")
BAREBOX_CMD_HELP_SHORT("Boot an application image.\n")
-BAREBOX_CMD_HELP_OPT ("-n", "Do not verify the image (speeds up boot process)\n")
+BAREBOX_CMD_HELP_OPT ("-c", "crc check uImage data\n")
+#ifdef CONFIG_CMD_BOOTM_INITRD
BAREBOX_CMD_HELP_OPT ("-r <initrd>","specify an initrd image\n")
-BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address")
+BAREBOX_CMD_HELP_OPT ("-L <load addr>","specify initrd load address\n")
+#endif
+BAREBOX_CMD_HELP_OPT ("-a <load addr>","specify os load address\n")
+BAREBOX_CMD_HELP_OPT ("-e <ofs>","entry point to the image relative to start (0)\n")
+#ifdef CONFIG_OFTREE
+BAREBOX_CMD_HELP_OPT ("-o <oftree>","specify oftree\n")
+#endif
+#ifdef CONFIG_CMD_BOOTM_VERBOSE
+BAREBOX_CMD_HELP_OPT ("-v","verbose\n")
+#endif
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(bootm)
@@ -240,13 +452,6 @@ BAREBOX_CMD_END
BAREBOX_MAGICVAR(bootargs, "Linux Kernel parameters");
-#ifdef CONFIG_BZLIB
-void bz_internal_error(int errcode)
-{
- printf ("BZIP2 internal error %d\n", errcode);
-}
-#endif /* CONFIG_BZLIB */
-
/**
* @file
* @brief Boot support for Linux
diff --git a/commands/flash.c b/commands/flash.c
index a3f3508f2f..85efd06e43 100644
--- a/commands/flash.c
+++ b/commands/flash.c
@@ -56,11 +56,6 @@ static int do_flerase(struct command *cmdtp, int argc, char *argv[])
size = s.st_size;
- if (!filename) {
- printf("missing filename\n");
- return 1;
- }
-
fd = open(filename, O_WRONLY);
if (fd < 0) {
printf("open %s: %s", filename, errno_str());
@@ -132,11 +127,6 @@ static int do_protect(struct command *cmdtp, int argc, char *argv[])
size = s.st_size;
- if (!filename) {
- printf("missing filename\n");
- return 1;
- }
-
fd = open(filename, O_WRONLY);
if (fd < 0) {
printf("open %s: %s", filename, errno_str());
diff --git a/commands/iminfo.c b/commands/iminfo.c
deleted file mode 100644
index 2fde9bc09c..0000000000
--- a/commands/iminfo.c
+++ /dev/null
@@ -1,71 +0,0 @@
-#include <common.h>
-#include <command.h>
-#include <image.h>
-#include <fs.h>
-#include <malloc.h>
-#include <fcntl.h>
-#include <errno.h>
-
-static int image_info(image_header_t *hdr)
-{
- u32 len, checksum;
-
- if (image_get_magic(hdr) != IH_MAGIC) {
- puts (" Bad Magic Number\n");
- return 1;
- }
-
- len = image_get_header_size();
-
- checksum = image_get_hcrc(hdr);
- hdr->ih_hcrc = 0;
-
- if (crc32 (0, hdr, len) != checksum) {
- puts (" Bad Header Checksum\n");
- return 1;
- }
-
- image_print_contents(hdr, NULL);
-
- return 0;
-}
-
-static int do_iminfo(struct command *cmdtp, int argc, char *argv[])
-{
- int rcode = 1;
- int fd;
- int ret;
- image_header_t hdr;
-
- if (argc != 2)
- return COMMAND_ERROR_USAGE;
-
- fd = open(argv[1], O_RDONLY);
- if (fd < 0) {
- perror("open");
- return 1;
- }
-
- ret = read(fd, &hdr, sizeof(image_header_t));
- if (ret != sizeof(image_header_t))
- goto err_out;
-
- printf("Image at %s:\n", argv[1]);
- image_info(&hdr);
-
-err_out:
- close(fd);
-
- return rcode;
-}
-
-BAREBOX_CMD_HELP_START(iminfo)
-BAREBOX_CMD_HELP_USAGE("iminfo\n")
-BAREBOX_CMD_HELP_SHORT("Print header information for an application image.\n")
-BAREBOX_CMD_HELP_END
-
-BAREBOX_CMD_START(iminfo)
- .cmd = do_iminfo,
- .usage = "print header information for an application image",
- BAREBOX_CMD_HELP(cmd_iminfo_help)
-BAREBOX_CMD_END
diff --git a/commands/linux_exec.c b/commands/linux_exec.c
new file mode 100644
index 0000000000..00c7e8007a
--- /dev/null
+++ b/commands/linux_exec.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2011 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <command.h>
+#include <mach/linux.h>
+
+static int do_linux_exec(struct command *cmdtp, int argc, char *argv[])
+{
+ int ret;
+ char **newargv;
+ char *newenv[] = { NULL };
+ int i, j;
+
+ if (argc < 2)
+ return 1;
+
+ newargv = xzalloc(sizeof(char*) * argc);
+
+ for (j = 0, i = 1; i < argc; i++, j++)
+ newargv[j] = argv[i];
+
+ newargv[j] = NULL;
+ ret = linux_execve(argv[1], newargv, newenv);
+
+ free(newargv);
+
+ if (ret)
+ return 1;
+
+ return 0;
+}
+
+BAREBOX_CMD_HELP_START(linux_exec)
+BAREBOX_CMD_HELP_USAGE("linux_exec ...\n")
+BAREBOX_CMD_HELP_SHORT("Execute a command on the host\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(linux_exec)
+ .cmd = do_linux_exec,
+ .usage = "Execute a command on the host",
+ BAREBOX_CMD_HELP(cmd_linux_exec_help)
+BAREBOX_CMD_END
diff --git a/commands/ls.c b/commands/ls.c
index 278a8bcad2..070aa9002b 100644
--- a/commands/ls.c
+++ b/commands/ls.c
@@ -68,7 +68,7 @@ int ls(const char *path, ulong flags)
if (stat(tmp, &s))
goto out;
if (flags & LS_COLUMN)
- string_list_add(&sl, d->d_name);
+ string_list_add_sorted(&sl, d->d_name);
else
ls_one(d->d_name, &s);
}
@@ -156,7 +156,7 @@ static int do_ls(struct command *cmdtp, int argc, char *argv[])
if (!(s.st_mode & S_IFDIR)) {
if (flags & LS_COLUMN)
- string_list_add(&sl, argv[o]);
+ string_list_add_sorted(&sl, argv[o]);
else
ls_one(argv[o], &s);
}
diff --git a/commands/nandtest.c b/commands/nandtest.c
new file mode 100644
index 0000000000..3a955e93fc
--- /dev/null
+++ b/commands/nandtest.c
@@ -0,0 +1,364 @@
+/*
+ * Based on nandtest.c source in mtd-utils package.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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 <command.h>
+#include <fs.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <ioctl.h>
+#include <linux/mtd/mtd-abi.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+/* Max ECC Bits that can be corrected */
+#define MAX_ECC_BITS 8
+
+/*
+ * Structures for flash memory information.
+ */
+static struct region_info_user memregion;
+static struct mtd_info_user meminfo;
+static struct mtd_ecc_stats oldstats, newstats;
+
+static int fd, seed;
+/* Markbad option flag */
+static int markbad;
+
+/* ECC-Calculation stats */
+static unsigned int ecc_stats[MAX_ECC_BITS];
+static unsigned int ecc_stats_over;
+static unsigned int ecc_failed_cnt;
+
+/*
+ * Implementation of pread with lseek and read.
+ */
+static ssize_t pread(int fd, void *buf, size_t count, off_t offset)
+{
+ int ret;
+
+ /* Seek to offset */
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0)
+ perror("lseek");
+
+ /* Read from flash and put it into buf */
+ ret = read(fd, buf, count);
+ if (ret < 0)
+ perror("read");
+
+ return 0;
+}
+
+/*
+ * Implementation of pwrite with lseek and write.
+ */
+static ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset)
+{
+ int ret;
+
+ ret = lseek(fd, offset, SEEK_SET);
+ if (ret < 0)
+ perror("lseek");
+
+ /* Write buf to flash */
+ ret = write(fd, buf, count);
+ if (ret < 0) {
+ perror("write");
+ if (markbad) {
+ printf("Mark block bad at 0x%08x\n",
+ (unsigned)(offset + memregion.offset));
+ ioctl(fd, MEMSETBADBLOCK, &offset);
+ }
+ }
+
+ flush(fd);
+ return 0;
+}
+
+/*
+ * Erase and write function.
+ * Param ofs: offset on flash_device.
+ * Param data: data to write on flash.
+ * Param rbuf: pointer to allocated buffer to copy readed data.
+ */
+static int erase_and_write(off_t ofs, unsigned char *data, unsigned char *rbuf)
+{
+ struct erase_info_user er;
+ int i, ret;
+
+ printf("\r0x%08x: erasing... ", (unsigned)(ofs + memregion.offset));
+
+ er.start = ofs;
+ er.length = meminfo.erasesize;
+
+ ret = erase(fd, er.length, er.start);
+ if (ret < 0) {
+ perror("erase");
+ printf("Could't not erase flash at 0x%08x length 0x%08x.\n",
+ er.start, er.length);
+ return ret;
+ }
+
+ printf("\r0x%08x: writing...", (unsigned)(ofs + memregion.offset));
+
+ /* Write data to given offset */
+ pwrite(fd, data, meminfo.erasesize, ofs);
+
+ printf("\r0x%08x: reading...", (unsigned)(ofs + memregion.offset));
+
+ /* Read data from offset */
+ pread(fd, rbuf, meminfo.erasesize, ofs);
+
+ ret = ioctl(fd, ECCGETSTATS, &newstats);
+ if (ret < 0) {
+ perror("ECCGETSTATS");
+ return ret;
+ }
+
+ if (newstats.corrected > oldstats.corrected) {
+ printf("\n %d bit(s) ECC corrected at 0x%08x\n",
+ newstats.corrected - oldstats.corrected,
+ (unsigned)(ofs + memregion.offset));
+ if ((newstats.corrected-oldstats.corrected) >= MAX_ECC_BITS) {
+ /* Increment ECC stats that are over MAX_ECC_BITS */
+ ecc_stats_over++;
+ } else {
+ /* Increment ECC stat value */
+ ecc_stats[(newstats.corrected-oldstats.corrected)-1]++;
+ }
+ /* Set oldstats to newstats */
+ oldstats.corrected = newstats.corrected;
+ }
+ if (newstats.failed > oldstats.failed) {
+ printf("\nECC failed at 0x%08x\n",
+ (unsigned)(ofs + memregion.offset));
+ oldstats.failed = newstats.failed;
+ ecc_failed_cnt++;
+ }
+
+ printf("\r0x%08x: checking...", (unsigned)(ofs + memregion.offset));
+
+ /* Compared written data with read data.
+ * If data is not identical, display a detailed
+ * debugging information. */
+ ret = memcmp(data, rbuf, meminfo.erasesize);
+ if (ret < 0) {
+ printf("\ncompare failed. seed %d\n", seed);
+ for (i = 0; i < meminfo.erasesize; i++) {
+ if (data[i] != rbuf[i])
+ printf("Byte 0x%x is %02x should be %02x\n",
+ i, rbuf[i], data[i]);
+ }
+ return ret;
+ }
+ return 0;
+}
+
+/* Print stats of nandtest. */
+static void print_stats(int nr_passes, int length)
+{
+ int i;
+ printf("-------- Summary --------\n");
+ printf("Tested blocks : %d\n", (length/meminfo.erasesize)
+ * nr_passes);
+
+ for (i = 0; i < MAX_ECC_BITS; i++)
+ printf("ECC %d bit error(s) : %d\n", i+1, ecc_stats[i]);
+
+ printf("ECC >%d bit error(s) : %d\n", MAX_ECC_BITS, ecc_stats_over);
+ printf("ECC corrections failed : %d\n", ecc_failed_cnt);
+ printf("-------------------------\n");
+}
+
+/* Main program. */
+static int do_nandtest(struct command *cmdtp, int argc, char *argv[])
+{
+ int opt, length = -1, do_nandtest_dev = -1;
+ off_t flash_offset = 0;
+ off_t test_ofs;
+ unsigned int nr_passes = 1, pass;
+ int i;
+ int ret = -1;
+ unsigned char *wbuf, *rbuf;
+
+ ecc_failed_cnt = 0;
+ ecc_stats_over = 0;
+ markbad = 0;
+ fd = -1;
+
+ memset(ecc_stats, 0, MAX_ECC_BITS);
+
+ while ((opt = getopt(argc, argv, "ms:p:o:l:t")) > 0) {
+ switch (opt) {
+ case 'm':
+ markbad = 1;
+ break;
+ case 's':
+ seed = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ nr_passes = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'o':
+ flash_offset = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'l':
+ length = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 't':
+ do_nandtest_dev = 1;
+ break;
+ default:
+ return COMMAND_ERROR_USAGE;
+ }
+ }
+
+ /* Check if no device is given */
+ if (optind >= argc)
+ return COMMAND_ERROR_USAGE;
+
+ if (do_nandtest_dev == -1) {
+ printf("Please add -t parameter to start nandtest.\n");
+ return 0;
+ }
+
+ printf("Open device %s\n", argv[optind]);
+
+ fd = open(argv[optind], O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return COMMAND_ERROR_USAGE;
+ }
+
+ /* Getting flash information. */
+
+ ret = ioctl(fd, MEMGETINFO, &meminfo);
+ if (ret < 0) {
+ perror("MEMGETINFO");
+ goto err;
+ }
+
+ ret = ioctl(fd, MEMGETREGIONINFO, &memregion);
+ if (ret < 0) {
+ perror("MEMGETREGIONINFO");
+ goto err;
+ }
+
+ ret = ioctl(fd, ECCGETSTATS, &oldstats);
+ if (ret < 0) {
+ perror("ECCGETSTATS");
+ goto err;
+ }
+
+ if (length == -1) {
+ length = meminfo.size;
+ length -= flash_offset;
+ }
+
+ printf("Flash offset: 0x%08x\n",
+ (unsigned)(flash_offset+memregion.offset));
+ printf("Length: 0x%08x\n", (unsigned)length);
+ printf("End address: 0x%08x\n",
+ (unsigned)(flash_offset+length+memregion.offset));
+ printf("Erasesize: 0x%08x\n", (unsigned)(meminfo.erasesize));
+ printf("Starting nandtest...\n");
+
+ if (flash_offset % meminfo.erasesize) {
+ printf("Offset 0x%08x not multiple of erase size 0x%08x\n",
+ (unsigned)flash_offset, meminfo.erasesize);
+ goto err;
+ }
+ if (length % meminfo.erasesize) {
+ printf("Length 0x%08x not multiple of erase size 0x%08x\n",
+ length, meminfo.erasesize);
+ goto err;
+ }
+ if (length + flash_offset > meminfo.size) {
+ printf("Length 0x%08x + offset 0x%08x exceeds "
+ "device size 0x%08x\n",
+ length, (unsigned)flash_offset, meminfo.size);
+ goto err;
+ }
+
+ wbuf = malloc(meminfo.erasesize * 2);
+ if (!wbuf) {
+ printf("Could not allocate %d bytes for buffer\n",
+ meminfo.erasesize * 2);
+ goto err;
+ }
+ rbuf = wbuf + meminfo.erasesize;
+
+ for (pass = 0; pass < nr_passes; pass++) {
+ for (test_ofs = flash_offset;
+ test_ofs < flash_offset+length;
+ test_ofs += meminfo.erasesize) {
+
+ srand(seed);
+ seed = rand();
+
+ if (ioctl(fd, MEMGETBADBLOCK, (void *)test_ofs)) {
+ printf("\rBad block at 0x%08x\n",
+ (unsigned)(test_ofs +
+ memregion.offset));
+ continue;
+ }
+
+ for (i = 0; i < meminfo.erasesize; i++)
+ wbuf[i] = rand();
+
+ ret = erase_and_write(test_ofs, wbuf, rbuf);
+ if (ret < 0)
+ goto err2;
+ }
+ printf("\nFinished pass %d successfully\n", pass+1);
+ }
+
+ print_stats(nr_passes, length);
+
+ ret = close(fd);
+ if (ret < 0) {
+ perror("close");
+ goto err2;
+ }
+
+ free(wbuf);
+
+ return 0;
+err2:
+ free(wbuf);
+err:
+ printf("Error occurred.\n");
+ close(fd);
+ return 1;
+}
+
+/* String for usage of nandtest */
+static const __maybe_unused char cmd_nandtest_help[] =
+"Usage: nand [OPTION] <device>\n"
+ " -t, Really do a nandtest on device.\n"
+ " -m, Mark blocks bad if they appear so.\n"
+ " -s <seed>, Supply random seed.\n"
+ " -p <passes>, Number of passes.\n"
+ " -o <offset>, Start offset on flash.\n"
+ " -l <length>, Length of flash to test.\n";
+
+BAREBOX_CMD_START(nandtest)
+ .cmd = do_nandtest,
+ .usage = "NAND Test",
+ BAREBOX_CMD_HELP(cmd_nandtest_help)
+BAREBOX_CMD_END
diff --git a/commands/uimage.c b/commands/uimage.c
new file mode 100644
index 0000000000..82efd78349
--- /dev/null
+++ b/commands/uimage.c
@@ -0,0 +1,108 @@
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <libbb.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <malloc.h>
+#include <errno.h>
+#include <getopt.h>
+
+static int uimage_fd;
+
+static int uimage_flush(void *buf, unsigned int len)
+{
+ int ret;
+
+ ret = write_full(uimage_fd, buf, len);
+
+ return ret;
+}
+
+static int do_uimage(struct command *cmdtp, int argc, char *argv[])
+{
+ struct uimage_handle *handle;
+ int ret;
+ int verify = 0;
+ int fd;
+ int opt;
+ char *extract = NULL;
+ int info = 0;
+ int image_no = 0;
+
+ while ((opt = getopt(argc, argv, "ve:in:")) > 0) {
+ switch (opt) {
+ case 'v':
+ verify = 1;
+ break;
+ case 'i':
+ info = 1;
+ break;
+ case 'e':
+ extract = optarg;
+ break;
+ case 'n':
+ image_no = simple_strtoul(optarg, NULL, 0);
+ break;
+ }
+ }
+
+ if (optind == argc)
+ return COMMAND_ERROR_USAGE;
+
+ handle = uimage_open(argv[optind]);
+ if (!handle)
+ return 1;
+
+ if (info) {
+ printf("Image at %s:\n", argv[optind]);
+ uimage_print_contents(handle);
+ }
+
+ if (verify) {
+ printf("verifying data crc... ");
+ ret = uimage_verify(handle);
+ if (ret) {
+ goto err;
+ printf("Bad Data CRC\n");
+ } else {
+ printf("ok\n");
+ }
+ }
+
+ if (extract) {
+ fd = open(extract, O_WRONLY | O_CREAT | O_TRUNC);
+ if (fd < 0) {
+ perror("open");
+ ret = fd;
+ goto err;
+ }
+ uimage_fd = fd;
+ ret = uimage_load(handle, image_no, uimage_flush);
+ if (ret) {
+ printf("loading uImage failed with %d\n", ret);
+ close(fd);
+ goto err;
+ }
+
+ close(fd);
+ }
+err:
+ uimage_close(handle);
+
+ return ret ? 1 : 0;
+}
+
+BAREBOX_CMD_HELP_START(uimage)
+BAREBOX_CMD_HELP_USAGE("uimage [OPTIONS] <file>\n")
+BAREBOX_CMD_HELP_OPT ("-i", "show information about image\n")
+BAREBOX_CMD_HELP_OPT ("-v", "verify image\n")
+BAREBOX_CMD_HELP_OPT ("-e <outfile>", "extract image to <outfile>\n")
+BAREBOX_CMD_HELP_OPT ("-n <no>", "use image number <no> in multifile images\n")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(uimage)
+ .cmd = do_uimage,
+ .usage = "extract/verify uImage",
+ BAREBOX_CMD_HELP(cmd_uimage_help)
+BAREBOX_CMD_END
diff --git a/commands/usbserial.c b/commands/usbserial.c
new file mode 100644
index 0000000000..eb31934d76
--- /dev/null
+++ b/commands/usbserial.c
@@ -0,0 +1,108 @@
+/*
+ * usbserial.c - usb serial gadget command
+ *
+ * Copyright (c) 2011 Eric Bénard <eric@eukrea.com>, Eukréa Electromatique
+ * based on dfu.c which is :
+ * Copyright (c) 2009 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <command.h>
+#include <errno.h>
+#include <malloc.h>
+#include <getopt.h>
+#include <fs.h>
+#include <xfuncs.h>
+#include <usb/usbserial.h>
+
+static int do_usbserial(struct command *cmdtp, int argc, char *argv[])
+{
+ int opt;
+ struct usb_serial_pdata pdata;
+ char *argstr;
+ char *manufacturer = "barebox";
+ char *productname = CONFIG_BOARDINFO;
+ u16 idVendor = 0, idProduct = 0;
+ int mode = 0;
+
+ while ((opt = getopt(argc, argv, "m:p:V:P:asd")) > 0) {
+ switch (opt) {
+ case 'm':
+ manufacturer = optarg;
+ break;
+ case 'p':
+ productname = optarg;
+ break;
+ case 'V':
+ idVendor = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'P':
+ idProduct = simple_strtoul(optarg, NULL, 0);
+ break;
+ case 'a':
+ mode = 0;
+ break;
+#ifdef HAVE_OBEX
+ case 'o':
+ mode = 1;
+ break;
+#endif
+ case 's':
+ mode = 2;
+ break;
+ case 'd':
+ usb_serial_unregister();
+ return 0;
+ }
+ }
+
+ argstr = argv[optind];
+
+ pdata.manufacturer = manufacturer;
+ pdata.productname = productname;
+ pdata.idVendor = idVendor;
+ pdata.idProduct = idProduct;
+ pdata.mode = mode;
+
+ return usb_serial_register(&pdata);
+}
+
+BAREBOX_CMD_HELP_START(usbserial)
+BAREBOX_CMD_HELP_USAGE("usbserial [OPTIONS] <description>\n")
+BAREBOX_CMD_HELP_SHORT("Enable/disable a serial gadget on the USB device interface.\n")
+BAREBOX_CMD_HELP_OPT ("-m <str>", "Manufacturer string (barebox)\n")
+BAREBOX_CMD_HELP_OPT ("-p <str>", "product string (" CONFIG_BOARDINFO ")\n")
+BAREBOX_CMD_HELP_OPT ("-V <id>", "vendor id\n")
+BAREBOX_CMD_HELP_OPT ("-P <id>", "product id\n")
+BAREBOX_CMD_HELP_OPT ("-a", "CDC ACM (default)\n")
+#ifdef HAVE_OBEX
+BAREBOX_CMD_HELP_OPT ("-o", "CDC OBEX\n")
+#endif
+BAREBOX_CMD_HELP_OPT ("-s", "Generic Serial\n")
+BAREBOX_CMD_HELP_OPT ("-d", "Disable the serial gadget\n")
+BAREBOX_CMD_HELP_END
+
+/**
+ * @page usbserial_command
+ */
+
+BAREBOX_CMD_START(usbserial)
+ .cmd = do_usbserial,
+ .usage = "Serial gadget enable/disable",
+ BAREBOX_CMD_HELP(cmd_usbserial_help)
+BAREBOX_CMD_END
diff --git a/common/Kconfig b/common/Kconfig
index 27464d15e4..ca4f09922c 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -159,6 +159,9 @@ choice
config MALLOC_DLMALLOC
bool "dlmalloc"
+config MALLOC_TLSF
+ bool "tlsf"
+
config MALLOC_DUMMY
bool "dummy malloc"
depends on SHELL_NONE
@@ -398,10 +401,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 OF_FLAT_TREE
- bool
- prompt "Open Firmware flat device tree support"
-
config PARTITION
bool
prompt "Enable Partitions"
@@ -428,6 +427,34 @@ config DEFAULT_ENVIRONMENT
Enabling this option will give you a default environment when
the environment found in the environment sector is invalid
+config DEFAULT_ENVIRONMENT_COMPRESSED
+ bool
+ depends on DEFAULT_ENVIRONMENT
+ default y if ZLIB
+ default y if BZLIB
+ default y if LZO_DECOMPRESS
+
+if DEFAULT_ENVIRONMENT_COMPRESSED
+
+choice
+ prompt "compression"
+
+config DEFAULT_ENVIRONMENT_COMPRESSED_GZIP
+ bool "gzip"
+ depends on ZLIB
+
+config DEFAULT_ENVIRONMENT_COMPRESSED_BZIP2
+ bool "bzip2"
+ depends on BZLIB
+
+config DEFAULT_ENVIRONMENT_COMPRESSED_LZO
+ bool "lzo"
+ depends on LZO_DECOMPRESS
+
+endchoice
+
+endif
+
config DEFAULT_ENVIRONMENT_GENERIC
bool
depends on DEFAULT_ENVIRONMENT
diff --git a/common/Makefile b/common/Makefile
index 9bce47943c..d1132c3e52 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -1,7 +1,6 @@
obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_GREGORIAN_CALENDER) += date.o
-obj-$(CONFIG_OF_FLAT_TREE) += ft_build.o
obj-$(CONFIG_KALLSYMS) += kallsyms.o
obj-$(CONFIG_ENV_HANDLING) += environment.o
obj-$(CONFIG_AUTO_COMPLETE) += complete.o
@@ -14,6 +13,8 @@ obj-$(CONFIG_OFTREE) += oftree.o
obj-y += memory.o
obj-$(CONFIG_MALLOC_DLMALLOC) += dlmalloc.o
+obj-$(CONFIG_MALLOC_TLSF) += tlsf_malloc.o
+obj-$(CONFIG_MALLOC_TLSF) += tlsf.o
obj-$(CONFIG_MALLOC_DUMMY) += dummy_malloc.o
obj-y += clock.o
obj-y += version.o
@@ -23,6 +24,7 @@ obj-$(CONFIG_CONSOLE_SIMPLE) += console_simple.o
obj-$(CONFIG_DIGEST) += digest.o
obj-$(CONFIG_ENVIRONMENT_VARIABLES) += env.o
obj-$(CONFIG_CMD_BOOTM) += image.o
+obj-$(CONFIG_CMD_BOOTM) += uimage.o
obj-y += startup.o
obj-y += misc.o
obj-y += memsize.o
@@ -52,5 +54,30 @@ endif # ifdef CONFIG_DEFAULT_ENVIRONMENT
barebox_default_env: $(ENV_FILES)
$(Q)$(srctree)/scripts/genenv $(srctree) $(objtree) $(DEFAULT_ENVIRONMENT_PATH)
-include/generated/barebox_default_env.h: barebox_default_env
+barebox_default_env_comp =
+ifeq ($(CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED_GZIP),y)
+barebox_default_env_comp = .gz
+endif
+ifeq ($(CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED_BZIP2),y)
+barebox_default_env_comp = .bz2
+endif
+ifeq ($(CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED_LZO),y)
+barebox_default_env_comp = .lzo
+endif
+
+barebox_default_env.gz: barebox_default_env
+ $(call if_changed,gzip)
+
+barebox_default_env.bz2: barebox_default_env
+ $(call if_changed,bzip2)
+
+barebox_default_env.lzo: barebox_default_env
+ $(call if_changed,lzo)
+
+include/generated/barebox_default_env.h: barebox_default_env$(barebox_default_env_comp)
$(Q)cat $< | $(objtree)/scripts/bin2c default_environment > $@
+ $(Q)echo "const int default_environment_uncompress_size=`stat -c%s barebox_default_env`;" >> $@
+
+CLEAN_FILES += include/generated/barebox_default_env.h barebox_default_env
+CLEAN_FILES += barebox_default_env.gz barebox_default_env.bz2
+CLEAN_FILES += barebox_default_env.lzo
diff --git a/common/clock.c b/common/clock.c
index 79c06c8ddc..f322db8152 100644
--- a/common/clock.c
+++ b/common/clock.c
@@ -27,6 +27,7 @@
#include <common.h>
#include <asm-generic/div64.h>
#include <clock.h>
+#include <poller.h>
static struct clocksource *current_clock;
static uint64_t time_ns;
@@ -139,6 +140,9 @@ uint32_t clocksource_hz2mult(uint32_t hz, uint32_t shift_constant)
int is_timeout(uint64_t start_ns, uint64_t time_offset_ns)
{
+ if (time_offset_ns >= 100 * USECOND)
+ poller_call();
+
if ((int64_t)(start_ns + time_offset_ns - get_time_ns()) < 0)
return 1;
else
diff --git a/common/complete.c b/common/complete.c
index 46ba871a98..6d5349b509 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -27,6 +27,7 @@
#include <libgen.h>
#include <command.h>
#include <stringlist.h>
+#include <environment.h>
static int file_complete(struct string_list *sl, char *instr)
{
@@ -55,7 +56,7 @@ static int file_complete(struct string_list *sl, char *instr)
strcat(tmp, "/");
else
strcat(tmp, " ");
- string_list_add(sl, tmp);
+ string_list_add_sorted(sl, tmp);
}
}
@@ -67,6 +68,69 @@ out:
return 0;
}
+static int path_command_complete(struct string_list *sl, char *instr)
+{
+ struct stat s;
+ DIR *dir;
+ struct dirent *d;
+ char tmp[PATH_MAX];
+ char *path, *p, *n;
+
+ p = path = strdup(getenv("PATH"));
+
+ if (!path)
+ return -1;
+
+ while (p) {
+ n = strchr(p, ':');
+ if (n)
+ *n++ = '\0';
+ if (*p == '\0') {
+ p = n;
+ continue;
+ }
+ dir = opendir(p);
+
+ /* We need to check all PATH dirs, so if one failed,
+ * try next */
+ if (!dir) {
+ p = n;
+ continue;
+ }
+
+ while ((d = readdir(dir))) {
+ if (!strcmp(d->d_name, ".") ||
+ !strcmp(d->d_name, ".."))
+ continue;
+
+ if (!strncmp(instr, d->d_name, strlen(instr))) {
+ strcpy(tmp, d->d_name);
+ if (!stat(tmp, &s) &&
+ S_ISDIR(s.st_mode))
+ continue;
+ else
+ strcat(tmp, " ");
+
+ /* This function is called
+ * after command_complete,
+ * so we check if a double
+ * entry exist */
+ if (string_list_contains
+ (sl, tmp) == 0) {
+ string_list_add_sorted(sl, tmp);
+ }
+ }
+ }
+
+ closedir(dir);
+ p = n;
+ }
+
+ free(path);
+
+ return 0;
+}
+
static int command_complete(struct string_list *sl, char *instr)
{
struct command *cmdtp;
@@ -121,8 +185,10 @@ int complete(char *instr, char **outstr)
t++;
file_complete(&sl, t);
instr = t;
- } else
+ } else {
command_complete(&sl, instr);
+ path_command_complete(&sl, instr);
+ }
pos = strlen(instr);
diff --git a/common/console.c b/common/console.c
index cab8689252..88c40101a6 100644
--- a/common/console.c
+++ b/common/console.c
@@ -225,8 +225,6 @@ int getc(void)
*/
start = get_time_ns();
while (1) {
- poller_call();
-
if (tstc_raw()) {
kfifo_putc(console_input_buffer, getc_raw());
diff --git a/common/filetype.c b/common/filetype.c
index 5635d40af0..40faff3ada 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -36,6 +36,7 @@ static const char *filetype_str[] = {
[filetype_jffs2] = "JFFS2 image",
[filetype_gzip] = "gzip compressed",
[filetype_bzip2] = "bzip2 compressed",
+ [filetype_oftree] = "open firmware flat device tree",
};
const char *file_type_to_string(enum filetype f)
@@ -69,6 +70,8 @@ enum filetype file_detect_type(void *_buf)
if (buf8[0] == 'B' && buf8[1] == 'Z' && buf8[2] == 'h' &&
buf8[3] > '0' && buf8[3] <= '9')
return filetype_bzip2;
+ if (buf[0] == be32_to_cpu(0xd00dfeed))
+ return filetype_oftree;
return filetype_unknown;
}
diff --git a/common/ft_build.c b/common/ft_build.c
deleted file mode 100644
index 9042f1337b..0000000000
--- a/common/ft_build.c
+++ /dev/null
@@ -1,620 +0,0 @@
-/*
- * OF flat tree builder
- * Written by: Pantelis Antoniou <pantelis.antoniou@gmail.com>
- * Updated by: Matthew McClintock <msm@freescale.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 <boot.h>
-#include <init.h>
-#include <malloc.h>
-#include <environment.h>
-#include <asm/byteorder.h>
-#include <stdio.h>
-
-#include <errno.h>
-#include <stddef.h>
-
-#include <ft_build.h>
-
-#undef DEBUG
-
-/* align addr on a size boundary - adjust address up if needed -- Cort */
-#define _ALIGN(addr,size) (((addr)+(size)-1)&(~((size)-1)))
-#ifndef CONFIG_OF_BOOT_CPU
-#define CONFIG_OF_BOOT_CPU 0
-#endif
-#define SIZE_OF_RSVMAP_ENTRY (2*sizeof(u64))
-
-static void ft_put_word(struct ft_cxt *cxt, u32 v)
-{
- memmove(cxt->p + sizeof(u32), cxt->p, cxt->p_end - cxt->p);
-
- *(u32 *) cxt->p = cpu_to_be32(v);
- cxt->p += sizeof(u32);
- cxt->p_end += sizeof(u32);
-}
-
-static inline void ft_put_bin(struct ft_cxt *cxt, const void *data, int sz)
-{
- int aligned_size = ((u8 *)_ALIGN((unsigned long)cxt->p + sz,
- sizeof(u32))) - cxt->p;
-
- memmove(cxt->p + aligned_size, cxt->p, cxt->p_end - cxt->p);
-
- /* make sure the last bytes are zeroed */
- memset(cxt->p + aligned_size - (aligned_size % sizeof(u32)), 0,
- (aligned_size % sizeof(u32)));
-
- memcpy(cxt->p, data, sz);
-
- cxt->p += aligned_size;
- cxt->p_end += aligned_size;
-}
-
-void ft_begin_node(struct ft_cxt *cxt, const char *name)
-{
- ft_put_word(cxt, OF_DT_BEGIN_NODE);
- ft_put_bin(cxt, name, strlen(name) + 1);
-}
-
-void ft_end_node(struct ft_cxt *cxt)
-{
- ft_put_word(cxt, OF_DT_END_NODE);
-}
-
-void ft_nop(struct ft_cxt *cxt)
-{
- ft_put_word(cxt, OF_DT_NOP);
-}
-
-static int lookup_string(struct ft_cxt *cxt, const char *name)
-{
- u8 *p;
-
- p = cxt->p;
- while (p < cxt->p_end) {
- if (strcmp((char *)p, name) == 0)
- return p - cxt->p;
- p += strlen((char *)p) + 1;
- }
-
- return -1;
-}
-
-void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz)
-{
- int off = 0;
-
- off = lookup_string(cxt, name);
- if (off == -1) {
- memcpy(cxt->p_end, name, strlen(name) + 1);
- off = cxt->p_end - cxt->p;
- cxt->p_end += strlen(name) + 1;
- }
-
- /* now put offset from beginning of *STRUCTURE* */
- /* will be fixed up at the end */
- ft_put_word(cxt, OF_DT_PROP);
- ft_put_word(cxt, sz);
- ft_put_word(cxt, off);
- ft_put_bin(cxt, data, sz);
-}
-
-void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str)
-{
- ft_prop(cxt, name, str, strlen(str) + 1);
-}
-
-void ft_prop_int(struct ft_cxt *cxt, const char *name, int val)
-{
- u32 v = cpu_to_be32((u32) val);
-
- ft_prop(cxt, name, &v, sizeof(u32));
-}
-
-/* pick up and start working on a tree in place */
-void ft_init_cxt(struct ft_cxt *cxt, void *blob)
-{
- struct boot_param_header *bph = blob;
-
- memset(cxt, 0, sizeof(*cxt));
-
- cxt->bph = bph;
- bph->boot_cpuid_phys = CONFIG_OF_BOOT_CPU;
-
- /* find beginning and end of reserve map table (zeros in last entry) */
- cxt->p_rsvmap = (u8 *)bph + bph->off_mem_rsvmap;
- while ( ((uint64_t *)cxt->p_rsvmap)[0] != 0 &&
- ((uint64_t *)cxt->p_rsvmap)[1] != 0 ) {
- cxt->p_rsvmap += SIZE_OF_RSVMAP_ENTRY;
- }
-
- cxt->p_start = (u8 *)bph + bph->off_dt_struct;
- cxt->p_end = (u8 *)bph + bph->totalsize;
- cxt->p = (u8 *)bph + bph->off_dt_strings;
-}
-
-/* add a reserver physical area to the rsvmap */
-void ft_add_rsvmap(struct ft_cxt *cxt, u64 physstart, u64 physend)
-{
- memmove(cxt->p_rsvmap + SIZE_OF_RSVMAP_ENTRY, cxt->p_rsvmap,
- cxt->p_end - cxt->p_rsvmap);
-
- ((u64 *)cxt->p_rsvmap)[0] = cpu_to_be64(physstart);
- ((u64 *)cxt->p_rsvmap)[1] = cpu_to_be64(physend);
- ((u64 *)cxt->p_rsvmap)[2] = 0;
- ((u64 *)cxt->p_rsvmap)[3] = 0;
-
- cxt->p_rsvmap += SIZE_OF_RSVMAP_ENTRY;
- cxt->p_start += SIZE_OF_RSVMAP_ENTRY;
- cxt->p += SIZE_OF_RSVMAP_ENTRY;
- cxt->p_end += SIZE_OF_RSVMAP_ENTRY;
-}
-
-void ft_end_tree(struct ft_cxt *cxt)
-{
- ft_put_word(cxt, OF_DT_END);
-}
-
-/* update the boot param header with correct values */
-void ft_finalize_tree(struct ft_cxt *cxt) {
- struct boot_param_header *bph = cxt->bph;
-
- bph->totalsize = cxt->p_end - (u8 *)bph;
- bph->off_dt_struct = cxt->p_start - (u8 *)bph;
- bph->off_dt_strings = cxt->p - (u8 *)bph;
- bph->dt_strings_size = cxt->p_end - cxt->p;
-}
-
-static inline int isprint(int c)
-{
- return c >= 0x20 && c <= 0x7e;
-}
-
-static int is_printable_string(const void *data, int len)
-{
- const char *s = data;
- const char *ss;
-
- /* zero length is not */
- if (len == 0)
- return 0;
-
- /* must terminate with zero */
- if (s[len - 1] != '\0')
- return 0;
-
- ss = s;
- while (*s && isprint(*s))
- s++;
-
- /* not zero, or not done yet */
- if (*s != '\0' || (s + 1 - ss) < len)
- return 0;
-
- return 1;
-}
-
-static void print_data(const void *data, int len)
-{
- int i;
- const u8 *s;
-
- /* no data, don't print */
- if (len == 0)
- return;
-
- if (is_printable_string(data, len)) {
- puts(" = \"");
- puts(data);
- puts("\"");
- return;
- }
-
- switch (len) {
- case 1: /* byte */
- printf(" = <%02x>", (*(u8 *) data) & 0xff);
- break;
- case 2: /* half-word */
- printf(" = <%04x>", be16_to_cpu(*(u16 *) data) & 0xffff);
- break;
- case 4: /* word */
- printf(" = <%x>", be32_to_cpu(*(u32 *) data) & 0xffffffffU);
- break;
- case 8: /* double-word */
- printf(" = <%qx>", be64_to_cpu(*(uint64_t *) data));
- break;
- default: /* anything else... hexdump */
- printf(" = [");
- for (i = 0, s = data; i < len; i++)
- printf("%02x%s", s[i], i < len - 1 ? " " : "");
- printf("]");
-
- break;
- }
-}
-
-void ft_dump_blob(const void *bphp)
-{
- const struct boot_param_header *bph = bphp;
- const uint64_t *p_rsvmap = (const uint64_t *)
- ((const char *)bph + be32_to_cpu(bph->off_mem_rsvmap));
- const u32 *p_struct = (const u32 *)
- ((const char *)bph + be32_to_cpu(bph->off_dt_struct));
- const u32 *p_strings = (const u32 *)
- ((const char *)bph + be32_to_cpu(bph->off_dt_strings));
- u32 tag;
- const u32 *p;
- const char *s, *t;
- int depth, sz, shift;
- int i;
- uint64_t addr, size;
-
- if (be32_to_cpu(bph->magic) != OF_DT_HEADER) {
- /* not valid tree */
- return;
- }
-
- depth = 0;
- shift = 4;
-
- for (i = 0;; i++) {
- addr = be64_to_cpu(p_rsvmap[i * 2]);
- size = be64_to_cpu(p_rsvmap[i * 2 + 1]);
- if (addr == 0 && size == 0)
- break;
-
- printf("/memreserve/ %qx %qx;\n", addr, size);
- }
-
- p = p_struct;
- while ((tag = be32_to_cpu(*p++)) != OF_DT_END) {
-
- /* printf("tag: 0x%08x (%d)\n", tag, p - p_struct); */
-
- if (tag == OF_DT_BEGIN_NODE) {
- s = (const char *)p;
- p = (u32 *) _ALIGN((unsigned long)p + strlen(s) + 1, 4);
-
- printf("%*s%s {\n", depth * shift, "", s);
-
- depth++;
- continue;
- }
-
- if (tag == OF_DT_END_NODE) {
- depth--;
-
- printf("%*s};\n", depth * shift, "");
- continue;
- }
-
- if (tag == OF_DT_NOP) {
- printf("%*s[NOP]\n", depth * shift, "");
- continue;
- }
-
- if (tag != OF_DT_PROP) {
- fprintf(stderr, "%*s ** Unknown tag 0x%08x at 0x%p\n",
- depth * shift, "", tag, --p);
- break;
- }
- sz = be32_to_cpu(*p++);
- s = (const char *)p_strings + be32_to_cpu(*p++);
- t = (const char *)p;
- p = (const u32 *)_ALIGN((unsigned long)p + sz, 4);
- printf("%*s%s", depth * shift, "", s);
- print_data(t, sz);
- printf(";\n");
- }
-}
-
-void ft_backtrack_node(struct ft_cxt *cxt)
-{
- int i = 4;
-
- while (be32_to_cpu(*(u32 *) (cxt->p - i)) != OF_DT_END_NODE)
- i += 4;
-
- memmove (cxt->p - i, cxt->p, cxt->p_end - cxt->p);
-
- cxt->p_end -= i;
- cxt->p -= i;
-}
-
-void *ft_get_prop(void *bphp, const char *propname, int *szp)
-{
- struct boot_param_header *bph = bphp;
- uint32_t *p_struct =
- (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_struct));
- uint32_t *p_strings =
- (uint32_t *) ((char *)bph + be32_to_cpu(bph->off_dt_strings));
- uint32_t version = be32_to_cpu(bph->version);
- uint32_t tag;
- uint32_t *p;
- char *s, *t;
- char *ss;
- int sz;
- static char path[256], prop[256];
-
- path[0] = '\0';
-
- p = p_struct;
- while ((tag = be32_to_cpu(*p++)) != OF_DT_END) {
-
- if (tag == OF_DT_BEGIN_NODE) {
- s = (char *)p;
- p = (uint32_t *) _ALIGN((unsigned long)p + strlen(s) +
- 1, 4);
- strcat(path, s);
- strcat(path, "/");
- continue;
- }
-
- if (tag == OF_DT_END_NODE) {
- path[strlen(path) - 1] = '\0';
- ss = strrchr(path, '/');
- if (ss != NULL)
- ss[1] = '\0';
- continue;
- }
-
- if (tag == OF_DT_NOP)
- continue;
-
- if (tag != OF_DT_PROP)
- break;
-
- sz = be32_to_cpu(*p++);
- s = (char *)p_strings + be32_to_cpu(*p++);
- if (version < 0x10 && sz >= 8)
- p = (uint32_t *) _ALIGN((unsigned long)p, 8);
- t = (char *)p;
- p = (uint32_t *) _ALIGN((unsigned long)p + sz, 4);
-
- strcpy(prop, path);
- strcat(prop, s);
-
- if (strcmp(prop, propname) == 0) {
- *szp = sz;
- return t;
- }
- }
-
- return NULL;
-}
-
-/********************************************************************/
-
-/* Function that returns a character from the environment */
-extern uchar(*env_get_char) (int);
-
-#define BDM(x) { .name = #x, .offset = offsetof(bd_t, bi_ ##x ) }
-
-#ifdef CONFIG_OF_HAS_BD_T
-static const struct {
- const char *name;
- int offset;
-} bd_map[] = {
- BDM(memstart),
- BDM(memsize),
- BDM(flashstart),
- BDM(flashsize),
- BDM(flashoffset),
- BDM(sramstart),
- BDM(sramsize),
-#if defined(CONFIG_5xx) || defined(CONFIG_8xx) || defined(CONFIG_8260) \
- || defined(CONFIG_E500)
- BDM(immr_base),
-#endif
-#if defined(CONFIG_MPC5xxx)
- BDM(mbar_base),
-#endif
-#if defined(CONFIG_MPC83XX)
- BDM(immrbar),
-#endif
-#if defined(CONFIG_MPC8220)
- BDM(mbar_base),
- BDM(inpfreq),
- BDM(pcifreq),
- BDM(pevfreq),
- BDM(flbfreq),
- BDM(vcofreq),
-#endif
- BDM(bootflags),
- BDM(ip_addr),
- BDM(intfreq),
- BDM(busfreq),
-#ifdef CONFIG_CPM2
- BDM(cpmfreq),
- BDM(brgfreq),
- BDM(sccfreq),
- BDM(vco),
-#endif
-#if defined(CONFIG_MPC5xxx)
- BDM(ipbfreq),
- BDM(pcifreq),
-#endif
- BDM(baudrate),
-};
-#endif
-
-void ft_setup(void *blob, bd_t * bd, ulong initrd_start, ulong initrd_end)
-{
- u32 *p;
- int len;
- struct ft_cxt cxt;
- ulong clock;
-#if defined(CONFIG_OF_HAS_BAREBOX_ENV)
- int k, nxt;
-#endif
-#if defined(CONFIG_OF_HAS_BD_T)
- u8 *end;
-#endif
-#if defined(CONFIG_OF_HAS_BAREBOX_ENV) || defined(CONFIG_OF_HAS_BD_T)
- int i;
- static char tmpenv[256];
-#endif
-
- /* disable OF tree; booting old kernel */
- if (getenv("disable_of") != NULL) {
- memcpy(blob, bd, sizeof(*bd));
- return;
- }
-
-#ifdef DEBUG
- printf ("recieved oftree\n");
- ft_dump_blob(blob);
-#endif
-
- ft_init_cxt(&cxt, blob);
-
- if (initrd_start && initrd_end)
- ft_add_rsvmap(&cxt, initrd_start, initrd_end - initrd_start + 1);
-
- /* back into root */
- ft_backtrack_node(&cxt);
-
-#ifdef CONFIG_OF_HAS_BAREBOX_ENV
- ft_begin_node(&cxt, "barebox-env");
-
- for (i = 0; env_get_char(i) != '\0'; i = nxt + 1) {
- char *s, *lval, *rval;
-
- for (nxt = i; env_get_char(nxt) != '\0'; ++nxt) ;
- s = tmpenv;
- for (k = i; k < nxt && s < &tmpenv[sizeof(tmpenv) - 1]; ++k)
- *s++ = env_get_char(k);
- *s++ = '\0';
- lval = tmpenv;
- s = strchr(tmpenv, '=');
- if (s != NULL) {
- *s++ = '\0';
- rval = s;
- } else
- continue;
- ft_prop_str(&cxt, lval, rval);
- }
-
- ft_end_node(&cxt);
-#endif
-
- ft_begin_node(&cxt, "chosen");
- ft_prop_str(&cxt, "name", "chosen");
-
- ft_prop_str(&cxt, "bootargs", getenv("bootargs"));
- ft_prop_int(&cxt, "linux,platform", 0x600); /* what is this? */
- if (initrd_start && initrd_end) {
- ft_prop_int(&cxt, "linux,initrd-start", initrd_start);
- ft_prop_int(&cxt, "linux,initrd-end", initrd_end);
- }
-#ifdef OF_STDOUT_PATH
- ft_prop_str(&cxt, "linux,stdout-path", OF_STDOUT_PATH);
-#endif
-
- ft_end_node(&cxt);
-
- ft_end_node(&cxt); /* end root */
-
- ft_end_tree(&cxt);
- ft_finalize_tree(&cxt);
-
-#ifdef CONFIG_OF_HAS_BD_T
- /* paste the bd_t at the end of the flat tree */
- end = (char *)blob +
- be32_to_cpu(((struct boot_param_header *)blob)->totalsize);
- memcpy(end, bd, sizeof(*bd));
-#endif
-
-#ifdef CONFIG_PPC
-
-#ifdef CONFIG_OF_HAS_BD_T
- for (i = 0; i < sizeof(bd_map)/sizeof(bd_map[0]); i++) {
- uint32_t v;
-
- sprintf(tmpenv, "/bd_t/%s", bd_map[i].name);
- v = *(uint32_t *)((char *)bd + bd_map[i].offset);
-
- p = ft_get_prop(blob, tmpenv, &len);
- if (p != NULL)
- *p = cpu_to_be32(v);
- }
-
- p = ft_get_prop(blob, "/bd_t/enetaddr", &len);
- if (p != NULL)
- memcpy(p, bd->bi_enetaddr, 6);
-
- p = ft_get_prop(blob, "/bd_t/ethspeed", &len);
- if (p != NULL)
- *p = cpu_to_be32((uint32_t) bd->bi_ethspeed);
-#endif
-
- clock = bd->bi_intfreq;
- p = ft_get_prop(blob, "/cpus/" OF_CPU "/clock-frequency", &len);
- if (p != NULL)
- *p = cpu_to_be32(clock);
-
-#ifdef OF_TBCLK
- clock = OF_TBCLK;
- p = ft_get_prop(blob, "/cpus/" OF_CPU "/timebase-frequency", &len);
- if (p != NULL)
- *p = cpu_to_be32(clock);
-#endif
-#endif /* __powerpc__ */
-
-#ifdef CONFIG_OF_BOARD_SETUP
- ft_board_setup(blob, bd);
-#endif
-
- /* in case the size changed in the platform code */
- ft_finalize_tree(&cxt);
-
-#ifdef DEBUG
- printf("final OF-tree\n");
- ft_dump_blob(blob);
-#endif
-}
-
-#if 0
-static int oftree_handler_cmdline_parse(struct image_data *data, int opt,
- char *optarg)
-{
- switch(opt) {
- case 'o':
- printf("using oftree %s\n", optarg);
- data->oftree = optarg;
- return 0;
- default:
- return 1;
- }
-}
-
-static struct image_handler of_handler = {
- .cmdline_options = "o:",
- .cmdline_parse = oftree_handler_cmdline_parse,
- .help_string = " -o <oftree> use oftree",
-};
-
-static int oftree_register_image_handler(void)
-{
- return register_image_handler(&of_handler);
-}
-
-late_initcall(oftree_register_image_handler);
-#endif
diff --git a/common/image.c b/common/image.c
index d68889bc0f..e7d2242e78 100644
--- a/common/image.c
+++ b/common/image.c
@@ -144,290 +144,3 @@ const char *image_get_comp_name(uint8_t comp)
return get_table_entry_name(comp_name, "Unknown Compression", comp);
}
#endif
-
-/**
- * image_multi_count - get component (sub-image) count
- * @hdr: pointer to the header of the multi component image
- *
- * image_multi_count() returns number of components in a multi
- * component image.
- *
- * Note: no checking of the image type is done, caller must pass
- * a valid multi component image.
- *
- * returns:
- * number of components
- */
-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 *)data;
-
- /* count non empty slots */
- for (i = 0; size[i]; ++i)
- count++;
-
- return count;
-}
-
-/**
- * image_multi_getimg - get component data address and size
- * @hdr: pointer to the header of the multi component image
- * @idx: index of the requested component
- * @data: pointer to a ulong variable, will hold component data address
- * @len: pointer to a ulong variable, will hold component size
- *
- * image_multi_getimg() returns size and data address for the requested
- * component in a multi component image.
- *
- * Note: no checking of the image type is done, caller must pass
- * a valid multi component image.
- *
- * returns:
- * 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(void *data, ulong idx,
- ulong *img_data, ulong *len)
-{
- int i;
- uint32_t *size;
- ulong offset, count, tmp_img_data;
-
- /* get number of component */
- 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 *)data;
-
- /* get address of the proper component data start, which means
- * skipping sizes table (add 1 for last, null entry) */
- tmp_img_data = (ulong)data + (count + 1) * sizeof (uint32_t);
-
- if (idx < count) {
- *len = uimage_to_cpu(size[idx]);
- offset = 0;
-
- /* go over all indices preceding requested component idx */
- for (i = 0; i < idx; i++) {
- /* add up i-th component size, rounding up to 4 bytes */
- offset += (uimage_to_cpu(size[i]) + 3) & ~3 ;
- }
-
- /* calculate idx-th component data address */
- *img_data = tmp_img_data + offset;
- } else {
- *len = 0;
- *img_data = 0;
- }
-}
-
-static void image_print_type(const image_header_t *hdr)
-{
- const char *os, *arch, *type, *comp;
-
- os = image_get_os_name(image_get_os(hdr));
- arch = image_get_arch_name(image_get_arch(hdr));
- type = image_get_type_name(image_get_type(hdr));
- comp = image_get_comp_name(image_get_comp(hdr));
-
- printf ("%s %s %s (%s)\n", arch, os, type, comp);
-}
-
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || !defined(__BAREBOX__)
-static void image_print_time(time_t timestamp)
-{
-#if defined(__BAREBOX__)
- struct rtc_time tm;
-
- to_tm(timestamp, &tm);
- printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n",
- tm.tm_year, tm.tm_mon, tm.tm_mday,
- tm.tm_hour, tm.tm_min, tm.tm_sec);
-#else
- printf("%s", ctime(&timestamp));
-#endif
-}
-#endif /* CONFIG_TIMESTAMP || CONFIG_CMD_DATE || !__BAREBOX__ */
-
-void image_print_size(uint32_t size)
-{
-#ifdef __BAREBOX__
- printf("%d Bytes = %s\n", size, size_human_readable(size));
-#else
- printf("%d Bytes = %.2f kB = %.2f MB\n",
- size, (double)size / 1.024e3,
- (double)size / 1.048576e6);
-#endif
-}
-
-void image_print_contents(const image_header_t *hdr, void *data)
-{
- const char *p;
- int type;
-
-#ifdef __BAREBOX__
- p = " ";
-#else
- p = "";
-#endif
-
- printf("%sImage Name: %.*s\n", p, IH_NMLEN, image_get_name(hdr));
-#if defined(CONFIG_TIMESTAMP) || defined(CONFIG_CMD_DATE) || !defined(__BAREBOX__)
- printf("%sCreated: ", p);
- image_print_time((time_t)image_get_time(hdr));
-#endif
- printf ("%sImage Type: ", p);
- image_print_type(hdr);
- printf ("%sData Size: ", p);
- image_print_size(image_get_data_size(hdr));
- printf ("%sLoad Address: %08x\n", p, image_get_load(hdr));
- printf ("%sEntry Point: %08x\n", p, image_get_ep(hdr));
-
- type = image_get_type(hdr);
- if (data && (type == IH_TYPE_MULTI || type == IH_TYPE_SCRIPT)) {
- int i;
- ulong img_data, len;
- ulong count = image_multi_count(data);
-
- printf ("%sContents:\n", p);
- for (i = 0; i < count; i++) {
- image_multi_getimg(data, i, &img_data, &len);
-
- printf("%s Image %d: ", p, i);
- image_print_size(len);
-
- if (image_get_type(hdr) != IH_TYPE_SCRIPT && i > 0) {
- /*
- * the user may need to know offsets
- * if planning to do something with
- * multiple files
- */
- 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->data_entries);
- 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 f0ae1ccbaf..faff33b419 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -47,11 +47,19 @@ unsigned long mem_malloc_end(void)
return malloc_end;
}
+#ifdef CONFIG_MALLOC_TLSF
+#include <tlsf.h>
+tlsf_pool tlsf_mem_pool;
+#endif
+
void mem_malloc_init(void *start, void *end)
{
malloc_start = (unsigned long)start;
malloc_end = (unsigned long)end;
malloc_brk = malloc_start;
+#ifdef CONFIG_MALLOC_TLSF
+ tlsf_mem_pool = tlsf_create(start, (char *)end - (char *)start);
+#endif
}
#ifndef __SANDBOX__
diff --git a/common/oftree.c b/common/oftree.c
index 2a2f464204..a657d31664 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -293,20 +293,28 @@ int of_register_fixup(int (*fixup)(struct fdt_header *))
return 0;
}
-struct fdt_header *of_get_fixed_tree(void)
+int of_fix_tree(struct fdt_header *fdt)
{
struct of_fixup *of_fixup;
int ret;
- if (!barebox_fdt)
- return NULL;
-
list_for_each_entry(of_fixup, &of_fixup_list, list) {
- ret = of_fixup->fixup(barebox_fdt);
+ ret = of_fixup->fixup(fdt);
if (ret)
- return NULL;
+ return ret;
}
- return barebox_fdt;
+ return 0;
}
+struct fdt_header *of_get_fixed_tree(void)
+{
+ int ret;
+
+ if (!barebox_fdt)
+ return NULL;
+ ret = of_fix_tree(barebox_fdt);
+ if (ret)
+ return NULL;
+ return barebox_fdt;
+}
diff --git a/common/startup.c b/common/startup.c
index 13783fb27a..180fdc3599 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -64,10 +64,35 @@ static void display_meminfo(void)
#ifdef CONFIG_DEFAULT_ENVIRONMENT
#include <generated/barebox_default_env.h>
+#ifdef CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED
+#include <uncompress.h>
+void *defaultenv;
+#else
+#define defaultenv default_environment
+#endif
+
static int register_default_env(void)
{
- add_mem_device("defaultenv", (unsigned long)default_environment,
- sizeof(default_environment),
+#ifdef CONFIG_DEFAULT_ENVIRONMENT_COMPRESSED
+ int ret;
+ void *tmp;
+
+ tmp = xzalloc(default_environment_size);
+ memcpy(tmp, default_environment, default_environment_size);
+
+ defaultenv = xzalloc(default_environment_uncompress_size);
+
+ ret = uncompress(tmp, default_environment_size, NULL, NULL,
+ defaultenv, NULL, uncompress_err_stdout);
+
+ free(tmp);
+
+ if (ret)
+ return ret;
+#endif
+
+ add_mem_device("defaultenv", (unsigned long)defaultenv,
+ default_environment_uncompress_size,
IORESOURCE_MEM_WRITEABLE);
return 0;
}
diff --git a/common/tlsf.c b/common/tlsf.c
new file mode 100644
index 0000000000..c810e8dafe
--- /dev/null
+++ b/common/tlsf.c
@@ -0,0 +1,969 @@
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <linux/stringify.h>
+
+#include "tlsf.h"
+#include "tlsfbits.h"
+
+#ifdef DEBUG
+#define tlsf_assert(expr) \
+ ((expr) ? (void)(0) : printf("%s\n", __stringify(expr)))
+#else
+#define tlsf_assert(expr) (void)(0)
+#endif
+
+/*
+** Constants.
+*/
+
+/* Public constants: may be modified. */
+enum tlsf_public
+{
+ /* log2 of number of linear subdivisions of block sizes. */
+ SL_INDEX_COUNT_LOG2 = 5,
+};
+
+/* Private constants: do not modify. */
+enum tlsf_private
+{
+#if defined (TLSF_64BIT)
+ /* All allocation sizes and addresses are aligned to 8 bytes. */
+ ALIGN_SIZE_LOG2 = 3,
+#else
+ /* All allocation sizes and addresses are aligned to 4 bytes. */
+ ALIGN_SIZE_LOG2 = 2,
+#endif
+ ALIGN_SIZE = (1 << ALIGN_SIZE_LOG2),
+
+ /*
+ ** We support allocations of sizes up to (1 << FL_INDEX_MAX) bits.
+ ** However, because we linearly subdivide the second-level lists, and
+ ** our minimum size granularity is 4 bytes, it doesn't make sense to
+ ** create first-level lists for sizes smaller than SL_INDEX_COUNT * 4,
+ ** or (1 << (SL_INDEX_COUNT_LOG2 + 2)) bytes, as there we will be
+ ** trying to split size ranges into more slots than we have available.
+ ** Instead, we calculate the minimum threshold size, and place all
+ ** blocks below that size into the 0th first-level list.
+ */
+
+#if defined (TLSF_64BIT)
+ /*
+ ** TODO: We can increase this to support larger sizes, at the expense
+ ** of more overhead in the TLSF structure.
+ */
+ FL_INDEX_MAX = 32,
+#else
+ FL_INDEX_MAX = 30,
+#endif
+ SL_INDEX_COUNT = (1 << SL_INDEX_COUNT_LOG2),
+ FL_INDEX_SHIFT = (SL_INDEX_COUNT_LOG2 + ALIGN_SIZE_LOG2),
+ FL_INDEX_COUNT = (FL_INDEX_MAX - FL_INDEX_SHIFT + 1),
+
+ SMALL_BLOCK_SIZE = (1 << FL_INDEX_SHIFT),
+};
+
+/*
+** Cast and min/max macros.
+*/
+
+#define tlsf_cast(t, exp) ((t) (exp))
+#define tlsf_min(a, b) ((a) < (b) ? (a) : (b))
+#define tlsf_max(a, b) ((a) > (b) ? (a) : (b))
+
+/*
+** Set assert macro, if it has not been provided by the user.
+*/
+#if !defined (tlsf_assert)
+#define tlsf_assert assert
+#endif
+
+/*
+** Static assertion mechanism.
+*/
+
+#define _tlsf_glue2(x, y) x ## y
+#define _tlsf_glue(x, y) _tlsf_glue2(x, y)
+#define tlsf_static_assert(exp) \
+ typedef char _tlsf_glue(static_assert, __LINE__) [(exp) ? 1 : -1]
+
+#ifndef __BAREBOX__
+/* This code has been tested on 32- and 64-bit (LP/LLP) architectures. */
+tlsf_static_assert(sizeof(int) * CHAR_BIT == 32);
+tlsf_static_assert(sizeof(size_t) * CHAR_BIT >= 32);
+tlsf_static_assert(sizeof(size_t) * CHAR_BIT <= 64);
+
+/* SL_INDEX_COUNT must be <= number of bits in sl_bitmap's storage type. */
+tlsf_static_assert(sizeof(unsigned int) * CHAR_BIT >= SL_INDEX_COUNT);
+
+/* Ensure we've properly tuned our sizes. */
+tlsf_static_assert(ALIGN_SIZE == SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
+#endif
+
+/*
+** Data structures and associated constants.
+*/
+
+/*
+** Block header structure.
+**
+** There are several implementation subtleties involved:
+** - The prev_phys_block field is only valid if the previous block is free.
+** - The prev_phys_block field is actually stored at the end of the
+** previous block. It appears at the beginning of this structure only to
+** simplify the implementation.
+** - The next_free / prev_free fields are only valid if the block is free.
+*/
+typedef struct block_header_t
+{
+ /* Points to the previous physical block. */
+ struct block_header_t* prev_phys_block;
+
+ /* The size of this block, excluding the block header. */
+ size_t size;
+
+ /* Next and previous free blocks. */
+ struct block_header_t* next_free;
+ struct block_header_t* prev_free;
+} block_header_t;
+
+/*
+** Since block sizes are always at least a multiple of 4, the two least
+** significant bits of the size field are used to store the block status:
+** - bit 0: whether block is busy or free
+** - bit 1: whether previous block is busy or free
+*/
+static const size_t block_header_free_bit = 1 << 0;
+static const size_t block_header_prev_free_bit = 1 << 1;
+
+/*
+** The size of the block header exposed to used blocks is the size field.
+** The prev_phys_block field is stored *inside* the previous free block.
+*/
+static const size_t block_header_overhead = sizeof(size_t);
+
+/* User data starts directly after the size field in a used block. */
+static const size_t block_start_offset =
+ offsetof(block_header_t, size) + sizeof(size_t);
+
+/*
+** A free block must be large enough to store its header minus the size of
+** the prev_phys_block field, and no larger than the number of addressable
+** bits for FL_INDEX.
+*/
+static const size_t block_size_min =
+ sizeof(block_header_t) - sizeof(block_header_t*);
+static const size_t block_size_max = tlsf_cast(size_t, 1) << FL_INDEX_MAX;
+
+
+/* The TLSF pool structure. */
+typedef struct pool_t
+{
+ /* Empty lists point at this block to indicate they are free. */
+ block_header_t block_null;
+
+ /* Bitmaps for free lists. */
+ unsigned int fl_bitmap;
+ unsigned int sl_bitmap[FL_INDEX_COUNT];
+
+ /* Head of free lists. */
+ block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
+} pool_t;
+
+/* A type used for casting when doing pointer arithmetic. */
+typedef ptrdiff_t tlsfptr_t;
+
+/*
+** block_header_t member functions.
+*/
+
+static size_t block_size(const block_header_t* block)
+{
+ return block->size & ~(block_header_free_bit | block_header_prev_free_bit);
+}
+
+static void block_set_size(block_header_t* block, size_t size)
+{
+ const size_t oldsize = block->size;
+ block->size = size | (oldsize & (block_header_free_bit | block_header_prev_free_bit));
+}
+
+static int block_is_last(const block_header_t* block)
+{
+ return 0 == block_size(block);
+}
+
+static int block_is_free(const block_header_t* block)
+{
+ return tlsf_cast(int, block->size & block_header_free_bit);
+}
+
+static void block_set_free(block_header_t* block)
+{
+ block->size |= block_header_free_bit;
+}
+
+static void block_set_used(block_header_t* block)
+{
+ block->size &= ~block_header_free_bit;
+}
+
+static int block_is_prev_free(const block_header_t* block)
+{
+ return tlsf_cast(int, block->size & block_header_prev_free_bit);
+}
+
+static void block_set_prev_free(block_header_t* block)
+{
+ block->size |= block_header_prev_free_bit;
+}
+
+static void block_set_prev_used(block_header_t* block)
+{
+ block->size &= ~block_header_prev_free_bit;
+}
+
+static block_header_t* block_from_ptr(const void* ptr)
+{
+ return tlsf_cast(block_header_t*,
+ tlsf_cast(unsigned char*, ptr) - block_start_offset);
+}
+
+static void* block_to_ptr(const block_header_t* block)
+{
+ return tlsf_cast(void*,
+ tlsf_cast(unsigned char*, block) + block_start_offset);
+}
+
+/* Return location of next block after block of given size. */
+static block_header_t* offset_to_block(const void* ptr, size_t size)
+{
+ return tlsf_cast(block_header_t*, tlsf_cast(tlsfptr_t, ptr) + size);
+}
+
+/* Return location of previous block. */
+static block_header_t* block_prev(const block_header_t* block)
+{
+ return block->prev_phys_block;
+}
+
+/* Return location of next existing block. */
+static block_header_t* block_next(const block_header_t* block)
+{
+ block_header_t* next = offset_to_block(block_to_ptr(block),
+ block_size(block) - block_header_overhead);
+ tlsf_assert(!block_is_last(block));
+ return next;
+}
+
+/* Link a new block with its physical neighbor, return the neighbor. */
+static block_header_t* block_link_next(block_header_t* block)
+{
+ block_header_t* next = block_next(block);
+ next->prev_phys_block = block;
+ return next;
+}
+
+static void block_mark_as_free(block_header_t* block)
+{
+ /* Link the block to the next block, first. */
+ block_header_t* next = block_link_next(block);
+ block_set_prev_free(next);
+ block_set_free(block);
+}
+
+static void block_mark_as_used(block_header_t* block)
+{
+ block_header_t* next = block_next(block);
+ block_set_prev_used(next);
+ block_set_used(block);
+}
+
+static size_t align_up(size_t x, size_t align)
+{
+ tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+ return (x + (align - 1)) & ~(align - 1);
+}
+
+static size_t align_down(size_t x, size_t align)
+{
+ tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+ return x - (x & (align - 1));
+}
+
+static void* align_ptr(const void* ptr, size_t align)
+{
+ const tlsfptr_t aligned =
+ (tlsf_cast(tlsfptr_t, ptr) + (align - 1)) & ~(align - 1);
+ tlsf_assert(0 == (align & (align - 1)) && "must align to a power of two");
+ return tlsf_cast(void*, aligned);
+}
+
+/*
+** Adjust an allocation size to be aligned to word size, and no smaller
+** than internal minimum.
+*/
+static size_t adjust_request_size(size_t size, size_t align)
+{
+ size_t adjust = 0;
+ if (size && size < block_size_max)
+ {
+ const size_t aligned = align_up(size, align);
+ adjust = tlsf_max(aligned, block_size_min);
+ }
+ return adjust;
+}
+
+/*
+** TLSF utility functions. In most cases, these are direct translations of
+** the documentation found in the white paper.
+*/
+
+static void mapping_insert(size_t size, int* fli, int* sli)
+{
+ int fl, sl;
+ if (size < SMALL_BLOCK_SIZE)
+ {
+ /* Store small blocks in first list. */
+ fl = 0;
+ sl = tlsf_cast(int, size) / (SMALL_BLOCK_SIZE / SL_INDEX_COUNT);
+ }
+ else
+ {
+ fl = tlsf_fls_sizet(size);
+ sl = tlsf_cast(int, size >> (fl - SL_INDEX_COUNT_LOG2)) ^ (1 << SL_INDEX_COUNT_LOG2);
+ fl -= (FL_INDEX_SHIFT - 1);
+ }
+ *fli = fl;
+ *sli = sl;
+}
+
+/* This version rounds up to the next block size (for allocations) */
+static void mapping_search(size_t size, int* fli, int* sli)
+{
+ if (size >= (1 << SL_INDEX_COUNT_LOG2))
+ {
+ const size_t round = (1 << (tlsf_fls_sizet(size) - SL_INDEX_COUNT_LOG2)) - 1;
+ size += round;
+ }
+ mapping_insert(size, fli, sli);
+}
+
+static block_header_t* search_suitable_block(pool_t* pool, int* fli, int* sli)
+{
+ int fl = *fli;
+ int sl = *sli;
+
+ /*
+ ** First, search for a block in the list associated with the given
+ ** fl/sl index.
+ */
+ unsigned int sl_map = pool->sl_bitmap[fl] & (~0 << sl);
+ if (!sl_map)
+ {
+ /* No block exists. Search in the next largest first-level list. */
+ const unsigned int fl_map = pool->fl_bitmap & (~0 << (fl + 1));
+ if (!fl_map)
+ {
+ /* No free blocks available, memory has been exhausted. */
+ return 0;
+ }
+
+ fl = tlsf_ffs(fl_map);
+ *fli = fl;
+ sl_map = pool->sl_bitmap[fl];
+ }
+ tlsf_assert(sl_map && "internal error - second level bitmap is null");
+ sl = tlsf_ffs(sl_map);
+ *sli = sl;
+
+ /* Return the first block in the free list. */
+ return pool->blocks[fl][sl];
+}
+
+/* Remove a free block from the free list.*/
+static void remove_free_block(pool_t* pool, block_header_t* block, int fl, int sl)
+{
+ block_header_t* prev = block->prev_free;
+ block_header_t* next = block->next_free;
+ tlsf_assert(prev && "prev_free field can not be null");
+ tlsf_assert(next && "next_free field can not be null");
+ next->prev_free = prev;
+ prev->next_free = next;
+
+ /* If this block is the head of the free list, set new head. */
+ if (pool->blocks[fl][sl] == block)
+ {
+ pool->blocks[fl][sl] = next;
+
+ /* If the new head is null, clear the bitmap. */
+ if (next == &pool->block_null)
+ {
+ pool->sl_bitmap[fl] &= ~(1 << sl);
+
+ /* If the second bitmap is now empty, clear the fl bitmap. */
+ if (!pool->sl_bitmap[fl])
+ {
+ pool->fl_bitmap &= ~(1 << fl);
+ }
+ }
+ }
+}
+
+/* Insert a free block into the free block list. */
+static void insert_free_block(pool_t* pool, block_header_t* block, int fl, int sl)
+{
+ block_header_t* current = pool->blocks[fl][sl];
+ tlsf_assert(current && "free list cannot have a null entry");
+ tlsf_assert(block && "cannot insert a null entry into the free list");
+ block->next_free = current;
+ block->prev_free = &pool->block_null;
+ current->prev_free = block;
+
+ tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE)
+ && "block not aligned properly");
+ /*
+ ** Insert the new block at the head of the list, and mark the first-
+ ** and second-level bitmaps appropriately.
+ */
+ pool->blocks[fl][sl] = block;
+ pool->fl_bitmap |= (1 << fl);
+ pool->sl_bitmap[fl] |= (1 << sl);
+}
+
+/* Remove a given block from the free list. */
+static void block_remove(pool_t* pool, block_header_t* block)
+{
+ int fl, sl;
+ mapping_insert(block_size(block), &fl, &sl);
+ remove_free_block(pool, block, fl, sl);
+}
+
+/* Insert a given block into the free list. */
+static void block_insert(pool_t* pool, block_header_t* block)
+{
+ int fl, sl;
+ mapping_insert(block_size(block), &fl, &sl);
+ insert_free_block(pool, block, fl, sl);
+}
+
+static int block_can_split(block_header_t* block, size_t size)
+{
+ return block_size(block) >= sizeof(block_header_t) + size;
+}
+
+/* Split a block into two, the second of which is free. */
+static block_header_t* block_split(block_header_t* block, size_t size)
+{
+ /* Calculate the amount of space left in the remaining block. */
+ block_header_t* remaining =
+ offset_to_block(block_to_ptr(block), size - block_header_overhead);
+
+ const size_t remain_size = block_size(block) - (size + block_header_overhead);
+
+ tlsf_assert(block_to_ptr(remaining) == align_ptr(block_to_ptr(remaining), ALIGN_SIZE)
+ && "remaining block not aligned properly");
+
+ tlsf_assert(block_size(block) == remain_size + size + block_header_overhead);
+ block_set_size(remaining, remain_size);
+ tlsf_assert(block_size(remaining) >= block_size_min && "block split with invalid size");
+
+ block_set_size(block, size);
+ block_mark_as_free(remaining);
+
+ return remaining;
+}
+
+/* Absorb a free block's storage into an adjacent previous free block. */
+static block_header_t* block_absorb(block_header_t* prev, block_header_t* block)
+{
+ tlsf_assert(!block_is_last(prev) && "previous block can't be last!");
+ /* Note: Leaves flags untouched. */
+ prev->size += block_size(block) + block_header_overhead;
+ block_link_next(prev);
+ return prev;
+}
+
+/* Merge a just-freed block with an adjacent previous free block. */
+static block_header_t* block_merge_prev(pool_t* pool, block_header_t* block)
+{
+ if (block_is_prev_free(block))
+ {
+ block_header_t* prev = block_prev(block);
+ tlsf_assert(prev && "prev physical block can't be null");
+ tlsf_assert(block_is_free(prev) && "prev block is not free though marked as such");
+ block_remove(pool, prev);
+ block = block_absorb(prev, block);
+ }
+
+ return block;
+}
+
+/* Merge a just-freed block with an adjacent free block. */
+static block_header_t* block_merge_next(pool_t* pool, block_header_t* block)
+{
+ block_header_t* next = block_next(block);
+ tlsf_assert(next && "next physical block can't be null");
+
+ if (block_is_free(next))
+ {
+ tlsf_assert(!block_is_last(block) && "previous block can't be last!");
+ block_remove(pool, next);
+ block = block_absorb(block, next);
+ }
+
+ return block;
+}
+
+/* Trim any trailing block space off the end of a block, return to pool. */
+static void block_trim_free(pool_t* pool, block_header_t* block, size_t size)
+{
+ tlsf_assert(block_is_free(block) && "block must be free");
+ if (block_can_split(block, size))
+ {
+ block_header_t* remaining_block = block_split(block, size);
+ block_link_next(block);
+ block_set_prev_free(remaining_block);
+ block_insert(pool, remaining_block);
+ }
+}
+
+/* Trim any trailing block space off the end of a used block, return to pool. */
+static void block_trim_used(pool_t* pool, block_header_t* block, size_t size)
+{
+ tlsf_assert(!block_is_free(block) && "block must be used");
+ if (block_can_split(block, size))
+ {
+ /* If the next block is free, we must coalesce. */
+ block_header_t* remaining_block = block_split(block, size);
+ block_set_prev_used(remaining_block);
+
+ remaining_block = block_merge_next(pool, remaining_block);
+ block_insert(pool, remaining_block);
+ }
+}
+
+static block_header_t* block_trim_free_leading(pool_t* pool, block_header_t* block, size_t size)
+{
+ block_header_t* remaining_block = block;
+ if (block_can_split(block, size))
+ {
+ /* We want the 2nd block. */
+ remaining_block = block_split(block, size - block_header_overhead);
+ block_set_prev_free(remaining_block);
+
+ block_link_next(block);
+ block_insert(pool, block);
+ }
+
+ return remaining_block;
+}
+
+static block_header_t* block_locate_free(pool_t* pool, size_t size)
+{
+ int fl = 0, sl = 0;
+ block_header_t* block = 0;
+
+ if (size)
+ {
+ mapping_search(size, &fl, &sl);
+ block = search_suitable_block(pool, &fl, &sl);
+ }
+
+ if (block)
+ {
+ tlsf_assert(block_size(block) >= size);
+ remove_free_block(pool, block, fl, sl);
+ }
+
+ return block;
+}
+
+static void* block_prepare_used(pool_t* pool, block_header_t* block, size_t size)
+{
+ void* p = 0;
+ if (block)
+ {
+ block_trim_free(pool, block, size);
+ block_mark_as_used(block);
+ p = block_to_ptr(block);
+ }
+ return p;
+}
+
+/* Clear structure and point all empty lists at the null block. */
+static void pool_construct(pool_t* pool)
+{
+ int i, j;
+
+ pool->block_null.next_free = &pool->block_null;
+ pool->block_null.prev_free = &pool->block_null;
+
+ pool->fl_bitmap = 0;
+ for (i = 0; i < FL_INDEX_COUNT; ++i)
+ {
+ pool->sl_bitmap[i] = 0;
+ for (j = 0; j < SL_INDEX_COUNT; ++j)
+ {
+ pool->blocks[i][j] = &pool->block_null;
+ }
+ }
+}
+
+/*
+** Debugging utilities.
+*/
+
+typedef struct integrity_t
+{
+ int prev_status;
+ int status;
+} integrity_t;
+
+#define tlsf_insist(x) { tlsf_assert(x); if (!(x)) { status--; } }
+
+static void integrity_walker(void* ptr, size_t size, int used, void* user)
+{
+ block_header_t* block = block_from_ptr(ptr);
+ integrity_t* integ = tlsf_cast(integrity_t*, user);
+ const int this_prev_status = block_is_prev_free(block) ? 1 : 0;
+ const int this_status = block_is_free(block) ? 1 : 0;
+ const size_t this_block_size = block_size(block);
+
+ int status = 0;
+ tlsf_insist(integ->prev_status == this_prev_status && "prev status incorrect");
+ tlsf_insist(size == this_block_size && "block size incorrect");
+
+ integ->prev_status = this_status;
+ integ->status += status;
+}
+
+int tlsf_check_heap(tlsf_pool tlsf)
+{
+ int i, j;
+
+ pool_t* pool = tlsf_cast(pool_t*, tlsf);
+ int status = 0;
+
+ /* Check that the blocks are physically correct. */
+ integrity_t integ = { 0, 0 };
+ tlsf_walk_heap(tlsf, integrity_walker, &integ);
+ status = integ.status;
+
+ /* Check that the free lists and bitmaps are accurate. */
+ for (i = 0; i < FL_INDEX_COUNT; ++i)
+ {
+ for (j = 0; j < SL_INDEX_COUNT; ++j)
+ {
+ const int fl_map = pool->fl_bitmap & (1 << i);
+ const int sl_list = pool->sl_bitmap[i];
+ const int sl_map = sl_list & (1 << j);
+ const block_header_t* block = pool->blocks[i][j];
+
+ /* Check that first- and second-level lists agree. */
+ if (!fl_map)
+ {
+ tlsf_insist(!sl_map && "second-level map must be null");
+ }
+
+ if (!sl_map)
+ {
+ tlsf_insist(block == &pool->block_null && "block list must be null");
+ continue;
+ }
+
+ /* Check that there is at least one free block. */
+ tlsf_insist(sl_list && "no free blocks in second-level map");
+ tlsf_insist(block != &pool->block_null && "block should not be null");
+
+ while (block != &pool->block_null)
+ {
+ int fli, sli;
+ tlsf_insist(block_is_free(block) && "block should be free");
+ tlsf_insist(!block_is_prev_free(block) && "blocks should have coalesced");
+ tlsf_insist(!block_is_free(block_next(block)) && "blocks should have coalesced");
+ tlsf_insist(block_is_prev_free(block_next(block)) && "block should be free");
+ tlsf_insist(block_size(block) >= block_size_min && "block not minimum size");
+
+ mapping_insert(block_size(block), &fli, &sli);
+ tlsf_insist(fli == i && sli == j && "block size indexed in wrong list");
+ block = block->next_free;
+ }
+ }
+ }
+
+ return status;
+}
+
+#undef tlsf_insist
+
+static void default_walker(void* ptr, size_t size, int used, void* user)
+{
+ (void)user;
+ printf("\t%p %s size: %x (%p)\n", ptr, used ? "used" : "free", (unsigned int)size, block_from_ptr(ptr));
+}
+
+void tlsf_walk_heap(tlsf_pool pool, tlsf_walker walker, void* user)
+{
+ tlsf_walker heap_walker = walker ? walker : default_walker;
+ block_header_t* block =
+ offset_to_block(pool, sizeof(pool_t) - block_header_overhead);
+
+ while (block && !block_is_last(block))
+ {
+ heap_walker(
+ block_to_ptr(block),
+ block_size(block),
+ !block_is_free(block),
+ user);
+ block = block_next(block);
+ }
+}
+
+size_t tlsf_block_size(void* ptr)
+{
+ size_t size = 0;
+ if (ptr)
+ {
+ const block_header_t* block = block_from_ptr(ptr);
+ size = block_size(block);
+ }
+ return size;
+}
+
+/*
+** Overhead of the TLSF structures in a given memory block passed to
+** tlsf_create, equal to the size of a pool_t plus overhead of the initial
+** free block and the sentinel block.
+*/
+size_t tlsf_overhead()
+{
+ const size_t pool_overhead = sizeof(pool_t) + 2 * block_header_overhead;
+ return pool_overhead;
+}
+
+/*
+** TLSF main interface. Right out of the white paper.
+*/
+
+tlsf_pool tlsf_create(void* mem, size_t bytes)
+{
+ block_header_t* block;
+ block_header_t* next;
+
+ const size_t pool_overhead = tlsf_overhead();
+ const size_t pool_bytes = align_down(bytes - pool_overhead, ALIGN_SIZE);
+ pool_t* pool = tlsf_cast(pool_t*, mem);
+
+#ifdef DEBUG
+ /* Verify ffs/fls work properly. */
+ int rv = 0;
+ rv += (tlsf_ffs(0) == -1) ? 0 : 0x1;
+ rv += (tlsf_fls(0) == -1) ? 0 : 0x2;
+ rv += (tlsf_ffs(1) == 0) ? 0 : 0x4;
+ rv += (tlsf_fls(1) == 0) ? 0 : 0x8;
+ rv += (tlsf_ffs(0x80000000) == 31) ? 0 : 0x10;
+ rv += (tlsf_ffs(0x80008000) == 15) ? 0 : 0x20;
+ rv += (tlsf_fls(0x80000008) == 31) ? 0 : 0x40;
+ rv += (tlsf_fls(0x7FFFFFFF) == 30) ? 0 : 0x80;
+
+#if defined (TLSF_64BIT)
+ rv += (tlsf_fls_sizet(0x80000000) == 31) ? 0 : 0x100;
+ rv += (tlsf_fls_sizet(0x100000000) == 32) ? 0 : 0x200;
+ rv += (tlsf_fls_sizet(0xffffffffffffffff) == 63) ? 0 : 0x400;
+ if (rv)
+ {
+ printf("tlsf_create: %x ffs/fls tests failed!\n", rv);
+ return 0;
+ }
+#endif
+#endif
+
+ if (pool_bytes < block_size_min || pool_bytes > block_size_max)
+ {
+#if defined (TLSF_64BIT)
+ printf("tlsf_create: Pool size must be at least %d bytes.\n",
+ (unsigned int)(pool_overhead + block_size_min));
+#else
+ printf("tlsf_create: Pool size must be between %u and %u bytes.\n",
+ (unsigned int)(pool_overhead + block_size_min),
+ (unsigned int)(pool_overhead + block_size_max));
+#endif
+ return 0;
+ }
+
+ /* Construct a valid pool object. */
+ pool_construct(pool);
+
+ /*
+ ** Create the main free block. Offset the start of the block slightly
+ ** so that the prev_phys_block field falls inside of the pool
+ ** structure - it will never be used.
+ */
+ block = offset_to_block(
+ tlsf_cast(void*, pool), sizeof(pool_t) - block_header_overhead);
+ block_set_size(block, pool_bytes);
+ block_set_free(block);
+ block_set_prev_used(block);
+ block_insert(pool, block);
+
+ /* Split the block to create a zero-size pool sentinel block. */
+ next = block_link_next(block);
+ block_set_size(next, 0);
+ block_set_used(next);
+ block_set_prev_free(next);
+
+ return tlsf_cast(tlsf_pool, pool);
+}
+
+void tlsf_destroy(tlsf_pool pool)
+{
+ /* Nothing to do. */
+ pool = pool;
+}
+
+void* tlsf_malloc(tlsf_pool tlsf, size_t size)
+{
+ pool_t* pool = tlsf_cast(pool_t*, tlsf);
+ const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
+ block_header_t* block = block_locate_free(pool, adjust);
+ return block_prepare_used(pool, block, adjust);
+}
+
+void* tlsf_memalign(tlsf_pool tlsf, size_t align, size_t size)
+{
+ pool_t* pool = tlsf_cast(pool_t*, tlsf);
+ const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
+
+ /*
+ ** We must allocate an additional minimum block size bytes so that if
+ ** our free block will leave an alignment gap which is smaller, we can
+ ** trim a leading free block and release it back to the heap. We must
+ ** do this because the previous physical block is in use, therefore
+ ** the prev_phys_block field is not valid, and we can't simply adjust
+ ** the size of that block.
+ */
+ const size_t gap_minimum = sizeof(block_header_t);
+ const size_t size_with_gap = adjust_request_size(adjust + align + gap_minimum, align);
+
+ /* If alignment is less than or equals base alignment, we're done. */
+ const size_t aligned_size = (align <= ALIGN_SIZE) ? adjust : size_with_gap;
+
+ block_header_t* block = block_locate_free(pool, aligned_size);
+
+ /* This can't be a static assert. */
+ tlsf_assert(sizeof(block_header_t) == block_size_min + block_header_overhead);
+
+ if (block)
+ {
+ void* ptr = block_to_ptr(block);
+ void* aligned = align_ptr(ptr, align);
+ size_t gap = tlsf_cast(size_t,
+ tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
+
+ /* If gap size is too small, offset to next aligned boundary. */
+ if (gap && gap < gap_minimum)
+ {
+ const size_t gap_remain = gap_minimum - gap;
+ const size_t offset = tlsf_max(gap_remain, align);
+ const void* next_aligned = tlsf_cast(void*,
+ tlsf_cast(tlsfptr_t, aligned) + offset);
+
+ aligned = align_ptr(next_aligned, align);
+ gap = tlsf_cast(size_t,
+ tlsf_cast(tlsfptr_t, aligned) - tlsf_cast(tlsfptr_t, ptr));
+ }
+
+ if (gap)
+ {
+ tlsf_assert(gap >= gap_minimum && "gap size too small");
+ block = block_trim_free_leading(pool, block, gap);
+ }
+ }
+
+ return block_prepare_used(pool, block, adjust);
+}
+
+void tlsf_free(tlsf_pool tlsf, void* ptr)
+{
+ /* Don't attempt to free a NULL pointer. */
+ if (ptr)
+ {
+ pool_t* pool = tlsf_cast(pool_t*, tlsf);
+ block_header_t* block = block_from_ptr(ptr);
+ block_mark_as_free(block);
+ block = block_merge_prev(pool, block);
+ block = block_merge_next(pool, block);
+ block_insert(pool, block);
+ }
+}
+
+/*
+** The TLSF block information provides us with enough information to
+** provide a reasonably intelligent implementation of realloc, growing or
+** shrinking the currently allocated block as required.
+**
+** This routine handles the somewhat esoteric edge cases of realloc:
+** - a non-zero size with a null pointer will behave like malloc
+** - a zero size with a non-null pointer will behave like free
+** - a request that cannot be satisfied will leave the original buffer
+** untouched
+** - an extended buffer size will leave the newly-allocated area with
+** contents undefined
+*/
+void* tlsf_realloc(tlsf_pool tlsf, void* ptr, size_t size)
+{
+ pool_t* pool = tlsf_cast(pool_t*, tlsf);
+ void* p = 0;
+
+ /* Zero-size requests are treated as free. */
+ if (ptr && size == 0)
+ {
+ tlsf_free(tlsf, ptr);
+ }
+ /* Requests with NULL pointers are treated as malloc. */
+ else if (!ptr)
+ {
+ p = tlsf_malloc(tlsf, size);
+ }
+ else
+ {
+ block_header_t* block = block_from_ptr(ptr);
+ block_header_t* next = block_next(block);
+
+ const size_t cursize = block_size(block);
+ const size_t combined = cursize + block_size(next) + block_header_overhead;
+ const size_t adjust = adjust_request_size(size, ALIGN_SIZE);
+
+ /*
+ ** If the next block is used, or when combined with the current
+ ** block, does not offer enough space, we must reallocate and copy.
+ */
+ if (adjust > cursize && (!block_is_free(next) || adjust > combined))
+ {
+ p = tlsf_malloc(tlsf, size);
+ if (p)
+ {
+ const size_t minsize = tlsf_min(cursize, size);
+ memcpy(p, ptr, minsize);
+ tlsf_free(tlsf, ptr);
+ }
+ }
+ else
+ {
+ /* Do we need to expand to the next block? */
+ if (adjust > cursize)
+ {
+ block_merge_next(pool, block);
+ block_mark_as_used(block);
+ }
+
+ /* Trim the resulting block and return the original pointer. */
+ block_trim_used(pool, block, adjust);
+ p = ptr;
+ }
+ }
+
+ return p;
+}
diff --git a/common/tlsf_malloc.c b/common/tlsf_malloc.c
new file mode 100644
index 0000000000..2fe443bf2b
--- /dev/null
+++ b/common/tlsf_malloc.c
@@ -0,0 +1,99 @@
+/*
+ * tlsf wrapper for barebox
+ *
+ * Copyright (C) 2011 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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 <config.h>
+#include <malloc.h>
+#include <string.h>
+#include <malloc.h>
+
+#include <stdio.h>
+#include <module.h>
+#include <tlsf.h>
+
+extern tlsf_pool tlsf_mem_pool;
+
+void *malloc(size_t bytes)
+{
+ return tlsf_malloc(tlsf_mem_pool, bytes);
+}
+EXPORT_SYMBOL(malloc);
+
+/*
+ * calloc calls malloc, then zeroes out the allocated chunk.
+ */
+void *calloc(size_t n, size_t elem_size)
+{
+ void *mem;
+ size_t sz;
+
+ sz = n * elem_size;
+ mem = malloc(sz);
+ memset(mem, 0, sz);
+
+ return mem;
+}
+EXPORT_SYMBOL(calloc);
+
+void free(void *mem)
+{
+ tlsf_free(tlsf_mem_pool, mem);
+}
+EXPORT_SYMBOL(free);
+
+void *realloc(void *oldmem, size_t bytes)
+{
+ return tlsf_realloc(tlsf_mem_pool, oldmem, bytes);
+}
+EXPORT_SYMBOL(realloc);
+
+void *memalign(size_t alignment, size_t bytes)
+{
+ return tlsf_memalign(tlsf_mem_pool, alignment, bytes);
+}
+EXPORT_SYMBOL(memalign);
+
+struct malloc_stats {
+ size_t free;
+ size_t used;
+};
+
+static void malloc_walker(void* ptr, size_t size, int used, void *user)
+{
+ struct malloc_stats *s = user;
+
+ if (used)
+ s->used += size;
+ else
+ s->free += size;
+}
+
+void malloc_stats(void)
+{
+ struct malloc_stats s;
+
+ s.used = 0;
+ s.free = 0;
+
+ tlsf_walk_heap(tlsf_mem_pool, malloc_walker, &s);
+
+ printf("used: %10d\nfree: %10d\n", s.used, s.free);
+}
diff --git a/common/tlsfbits.h b/common/tlsfbits.h
new file mode 100644
index 0000000000..93466e46a8
--- /dev/null
+++ b/common/tlsfbits.h
@@ -0,0 +1,55 @@
+#ifndef INCLUDED_tlsfbits
+#define INCLUDED_tlsfbits
+
+#include <linux/bitops.h>
+
+/*
+** Architecture-specific bit manipulation routines.
+**
+** TLSF achieves O(1) cost for malloc and free operations by limiting
+** the search for a free block to a free list of guaranteed size
+** adequate to fulfill the request, combined with efficient free list
+** queries using bitmasks and architecture-specific bit-manipulation
+** routines.
+**
+** Most modern processors provide instructions to count leading zeroes
+** in a word, find the lowest and highest set bit, etc. These
+** specific implementations will be used when available, falling back
+** to a reasonably efficient generic implementation.
+**
+** NOTE: TLSF spec relies on ffs/fls returning value 0..31.
+** ffs/fls return 1-32 by default, returning 0 for error.
+*/
+
+static int tlsf_ffs(unsigned int word)
+{
+ return ffs(word) - 1;
+}
+
+static int tlsf_fls(unsigned int word)
+{
+ return fls(word) - 1;
+}
+
+/* Possibly 64-bit version of tlsf_fls. */
+#if defined (TLSF_64BIT)
+tlsf_decl int tlsf_fls_sizet(size_t size)
+{
+ int high = (int)(size >> 32);
+ int bits = 0;
+ if (high)
+ {
+ bits = 32 + tlsf_fls(high);
+ }
+ else
+ {
+ bits = tlsf_fls((int)size & 0xffffffff);
+
+ }
+ return bits;
+}
+#else
+#define tlsf_fls_sizet tlsf_fls
+#endif
+
+#endif
diff --git a/common/uimage.c b/common/uimage.c
new file mode 100644
index 0000000000..28791b5413
--- /dev/null
+++ b/common/uimage.c
@@ -0,0 +1,505 @@
+/*
+ * uimage.c - uimage handling code
+ *
+ * Copyright (c) 2011 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * partly based on U-Boot uImage code
+ *
+ * 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 version 2
+ * as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#include <common.h>
+#include <image.h>
+#include <malloc.h>
+#include <errno.h>
+#include <libbb.h>
+#include <uncompress.h>
+#include <fcntl.h>
+#include <fs.h>
+#include <rtc.h>
+#include <filetype.h>
+#include <memory.h>
+
+#ifdef CONFIG_UIMAGE_MULTI
+static inline int uimage_is_multi_image(struct uimage_handle *handle)
+{
+ return (handle->header.ih_type == IH_TYPE_MULTI) ? 1 : 0;
+}
+#else
+static inline int uimage_is_multi_image(struct uimage_handle *handle)
+{
+ return 0;
+}
+#endif
+
+void uimage_print_contents(struct uimage_handle *handle)
+{
+ struct image_header *hdr = &handle->header;
+#if defined(CONFIG_TIMESTAMP)
+ struct rtc_time tm;
+#endif
+ printf(" Image Name: %.*s\n", IH_NMLEN, hdr->ih_name);
+#if defined(CONFIG_TIMESTAMP)
+ printf(" Created: ");
+ to_tm(hdr->ih_time, &tm);
+ printf("%4d-%02d-%02d %2d:%02d:%02d UTC\n",
+ tm.tm_year, tm.tm_mon, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+#endif
+#if defined(CONFIG_CMD_BOOTM_SHOW_TYPE)
+ printf(" OS: %s\n", image_get_os_name(hdr->ih_os));
+ printf(" Architecture: %s\n", image_get_arch_name(hdr->ih_arch));
+ printf(" Type: %s\n", image_get_type_name(hdr->ih_type));
+ printf(" Compression: %s\n", image_get_comp_name(hdr->ih_comp));
+#endif
+ printf(" Data Size: %d Bytes = %s\n", hdr->ih_size,
+ size_human_readable(hdr->ih_size));
+ printf(" Load Address: %08x\n", hdr->ih_load);
+ printf(" Entry Point: %08x\n", hdr->ih_ep);
+
+ if (uimage_is_multi_image(handle)) {
+ int i;
+
+ printf(" Contents:\n");
+
+ for (i = 0; i < handle->nb_data_entries; i++) {
+ struct uimage_handle_data *data = &handle->ihd[i];
+
+ printf(" Image %d: %ld (%s)\n", i,
+ data->len, size_human_readable(data->len));
+ }
+ }
+}
+EXPORT_SYMBOL(uimage_print_contents);
+
+size_t uimage_get_size(struct uimage_handle *handle, unsigned int image_no)
+{
+ if (image_no >= handle->nb_data_entries)
+ return -EINVAL;
+
+ return handle->ihd[image_no].len;
+}
+EXPORT_SYMBOL(uimage_get_size);
+
+/*
+ * open a uimage. This will check the header contents and
+ * return a handle to the uImage
+ */
+struct uimage_handle *uimage_open(const char *filename)
+{
+ int fd;
+ uint32_t checksum;
+ struct uimage_handle *handle;
+ struct image_header *header;
+ int i;
+ int ret;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ printf("could not open: %s\n", errno_str());
+ return NULL;
+ }
+
+ handle = xzalloc(sizeof(struct uimage_handle));
+ header = &handle->header;
+
+ if (read(fd, header, sizeof(*header)) < 0) {
+ printf("could not read: %s\n", errno_str());
+ goto err_out;
+ }
+
+ if (uimage_to_cpu(header->ih_magic) != IH_MAGIC) {
+ printf("Bad Magic Number\n");
+ goto err_out;
+ }
+
+ checksum = uimage_to_cpu(header->ih_hcrc);
+ header->ih_hcrc = 0;
+
+ if (crc32(0, header, sizeof(*header)) != checksum) {
+ printf("Bad Header Checksum\n");
+ goto err_out;
+ }
+
+ /* convert header to cpu native endianess */
+ header->ih_magic = uimage_to_cpu(header->ih_magic);
+ header->ih_hcrc = uimage_to_cpu(header->ih_hcrc);
+ header->ih_time = uimage_to_cpu(header->ih_time);
+ header->ih_size = uimage_to_cpu(header->ih_size);
+ header->ih_load = uimage_to_cpu(header->ih_load);
+ header->ih_ep = uimage_to_cpu(header->ih_ep);
+ header->ih_dcrc = uimage_to_cpu(header->ih_dcrc);
+
+ if (header->ih_name[0]) {
+ handle->name = xzalloc(IH_NMLEN + 1);
+ strncpy(handle->name, header->ih_name, IH_NMLEN);
+ } else {
+ handle->name = xstrdup(filename);
+ }
+
+ if (uimage_is_multi_image(handle)) {
+ size_t offset;
+
+ for (i = 0; i < MAX_MULTI_IMAGE_COUNT; i++) {
+ u32 size;
+
+ ret = read(fd, &size, sizeof(size));
+ if (ret < 0)
+ goto err_out;
+
+ if (!size)
+ break;
+
+ handle->ihd[i].len = uimage_to_cpu(size);
+ }
+
+ handle->nb_data_entries = i;
+
+ /* offset of the first image in a multifile image */
+ offset = 0;
+
+ for (i = 0; i < handle->nb_data_entries; i++) {
+ handle->ihd[i].offset = offset;
+ offset += (handle->ihd[i].len + 3) & ~3;
+ }
+
+ handle->data_offset = sizeof(struct image_header) +
+ sizeof(u32) * (handle->nb_data_entries + 1);
+ } else {
+ handle->ihd[0].offset = 0;
+ handle->ihd[0].len = header->ih_size;
+ handle->nb_data_entries = 1;
+ handle->data_offset = sizeof(struct image_header);
+ }
+
+ /*
+ * fd is now at the first data word
+ */
+ handle->fd = fd;
+
+ return handle;
+err_out:
+ close(fd);
+ free(handle);
+ return NULL;
+}
+EXPORT_SYMBOL(uimage_open);
+
+/*
+ * close a uImage previously opened with uimage_open
+ */
+void uimage_close(struct uimage_handle *handle)
+{
+ close(handle->fd);
+ free(handle->name);
+ free(handle);
+}
+EXPORT_SYMBOL(uimage_close);
+
+static int uimage_fd;
+
+static int uimage_fill(void *buf, unsigned int len)
+{
+ return read_full(uimage_fd, buf, len);
+}
+
+static int uncompress_copy(unsigned char *inbuf_unused, int len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *outbuf_unused,
+ int *pos,
+ void(*error_fn)(char *x))
+{
+ int ret;
+ void *buf = xmalloc(PAGE_SIZE);
+
+ while (len) {
+ int now = min(len, PAGE_SIZE);
+ ret = fill(buf, now);
+ if (ret < 0)
+ goto err;
+ ret = flush(buf, now);
+ if (ret < 0)
+ goto err;
+ len -= now;
+ }
+
+ ret = 0;
+err:
+ free(buf);
+ return ret;
+}
+
+/*
+ * Verify the data crc of an uImage
+ */
+int uimage_verify(struct uimage_handle *handle)
+{
+ u32 crc = 0;
+ int len, ret;
+ void *buf;
+
+ ret = lseek(handle->fd, sizeof(struct image_header), SEEK_SET);
+ if (ret < 0)
+ return ret;
+
+ buf = xmalloc(PAGE_SIZE);
+
+ len = handle->header.ih_size;
+ while (len) {
+ int now = min(len, PAGE_SIZE);
+ ret = read(handle->fd, buf, now);
+ if (ret < 0)
+ goto err;
+ crc = crc32(crc, buf, now);
+ len -= ret;
+ }
+
+ if (crc != handle->header.ih_dcrc) {
+ printf("Bad Data CRC: 0x%08x != 0x%08x\n",
+ crc, handle->header.ih_dcrc);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = 0;
+err:
+ free(buf);
+
+ return ret;
+}
+EXPORT_SYMBOL(uimage_verify);
+
+/*
+ * Load a uimage, flushing output to flush function
+ */
+int uimage_load(struct uimage_handle *handle, unsigned int image_no,
+ int(*flush)(void*, unsigned int))
+{
+ image_header_t *hdr = &handle->header;
+ struct uimage_handle_data *iha;
+ int ret;
+ int (*uncompress_fn)(unsigned char *inbuf, int len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *output,
+ int *pos,
+ void(*error)(char *x));
+
+ if (image_no >= handle->nb_data_entries)
+ return -EINVAL;
+
+ iha = &handle->ihd[image_no];
+
+ ret = lseek(handle->fd, iha->offset + handle->data_offset,
+ SEEK_SET);
+ if (ret < 0)
+ return ret;
+
+ if (hdr->ih_comp == IH_COMP_NONE)
+ uncompress_fn = uncompress_copy;
+ else
+ uncompress_fn = uncompress;
+
+ uimage_fd = handle->fd;
+
+ ret = uncompress_fn(NULL, iha->len, uimage_fill, flush,
+ NULL, NULL,
+ uncompress_err_stdout);
+ return ret;
+}
+EXPORT_SYMBOL(uimage_load);
+
+static void *uimage_buf;
+static size_t uimage_size;
+static struct resource *uimage_resource;
+
+static int uimage_sdram_flush(void *buf, unsigned int len)
+{
+ if (uimage_size + len > uimage_resource->size) {
+ resource_size_t start = uimage_resource->start;
+ resource_size_t size = uimage_resource->size + len;
+ release_sdram_region(uimage_resource);
+
+ uimage_resource = request_sdram_region("uimage",
+ start, size);
+ if (!uimage_resource) {
+ printf("unable to request SDRAM 0x%08x-0x%08x\n",
+ start, start + size - 1);
+ return -ENOMEM;
+ }
+ }
+
+ memcpy(uimage_buf + uimage_size, buf, len);
+
+ uimage_size += len;
+
+ return len;
+}
+
+#define BUFSIZ (PAGE_SIZE * 2)
+
+struct resource *file_to_sdram(const char *filename, unsigned long adr)
+{
+ struct resource *res;
+ size_t size = BUFSIZ;
+ size_t ofs = 0;
+ int fd;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ return NULL;
+
+ while (1) {
+ size_t now;
+
+ res = request_sdram_region("image", adr, size);
+ if (!res) {
+ printf("unable to request SDRAM 0x%08lx-0x%08lx\n",
+ adr, adr + size - 1);
+ goto out;
+ }
+
+ now = read_full(fd, (void *)(res->start + ofs), BUFSIZ);
+ if (now < 0) {
+ release_sdram_region(res);
+ res = NULL;
+ goto out;
+ }
+ if (now < BUFSIZ)
+ goto out;
+
+ release_sdram_region(res);
+
+ ofs += BUFSIZ;
+ size += BUFSIZ;
+ }
+out:
+ close(fd);
+
+ return res;
+}
+
+/*
+ * Load an uImage to a dynamically allocated sdram resource.
+ * the resource must be freed afterwards with release_sdram_region
+ */
+struct resource *uimage_load_to_sdram(struct uimage_handle *handle,
+ int image_no, unsigned long load_address)
+{
+ int ret;
+ size_t size;
+ resource_size_t start = (resource_size_t)load_address;
+
+ uimage_buf = (void *)load_address;
+ uimage_size = 0;
+
+ size = uimage_get_size(handle, image_no);
+ if (size < 0)
+ return NULL;
+
+ uimage_resource = request_sdram_region("uimage",
+ start, size);
+ if (!uimage_resource) {
+ printf("unable to request SDRAM 0x%08x-0x%08x\n",
+ start, start + size - 1);
+ return NULL;
+ }
+
+ ret = uimage_load(handle, image_no, uimage_sdram_flush);
+ if (ret) {
+ release_sdram_region(uimage_resource);
+ return NULL;
+ }
+
+ return uimage_resource;
+}
+EXPORT_SYMBOL(uimage_load_to_sdram);
+
+void *uimage_load_to_buf(struct uimage_handle *handle, int image_no,
+ size_t *outsize)
+{
+ u32 size;
+ int ret;
+ struct uimage_handle_data *ihd;
+ char ftbuf[128];
+ enum filetype ft;
+ void *buf;
+
+ if (image_no >= handle->nb_data_entries)
+ return NULL;
+
+ ihd = &handle->ihd[image_no];
+
+ ret = lseek(handle->fd, ihd->offset + handle->data_offset,
+ SEEK_SET);
+ if (ret < 0)
+ return NULL;
+
+ if (handle->header.ih_comp == IH_COMP_NONE) {
+ buf = malloc(ihd->len);
+ if (!buf)
+ return NULL;
+
+ ret = read_full(handle->fd, buf, ihd->len);
+ if (ret < ihd->len) {
+ free(buf);
+ return NULL;
+ }
+ goto out;
+ }
+
+ ret = read(handle->fd, ftbuf, 128);
+ if (ret < 0)
+ return NULL;
+
+ ft = file_detect_type(ftbuf);
+ if ((int)ft < 0)
+ return NULL;
+
+ if (ft != filetype_gzip)
+ return NULL;
+
+ ret = lseek(handle->fd, ihd->offset + handle->data_offset +
+ ihd->len - 4,
+ SEEK_SET);
+ if (ret < 0)
+ return NULL;
+
+ ret = read(handle->fd, &size, 4);
+ if (ret < 0)
+ return NULL;
+
+ size = le32_to_cpu(size);
+
+ ret = lseek(handle->fd, ihd->offset + handle->data_offset,
+ SEEK_SET);
+ if (ret < 0)
+ return NULL;
+
+ buf = malloc(size);
+ ret = uncompress_fd_to_buf(handle->fd, buf, uncompress_err_stdout);
+ if (ret) {
+ free(buf);
+ return NULL;
+ }
+
+out:
+ if (outsize)
+ *outsize = size;
+
+ return buf;
+}
diff --git a/defaultenv/bin/_update b/defaultenv/bin/_update
index 1bcb71c9b2..9e88dea6dc 100644
--- a/defaultenv/bin/_update
+++ b/defaultenv/bin/_update
@@ -44,7 +44,7 @@ echo
if [ x$mode = xtftp ]; then
tftp $image $part || exit 1
else
- cp $image $part || exit 1
+ cp -v $image $part || exit 1
fi
protect $part
diff --git a/defaultenv/bin/boot b/defaultenv/bin/boot
index 90ebf9a3da..11207573c6 100644
--- a/defaultenv/bin/boot
+++ b/defaultenv/bin/boot
@@ -72,35 +72,12 @@ if [ -n $mtdparts ]; then
bootargs="${bootargs} mtdparts=${mtdparts}"
fi
-if [ ! -e /dev/ram0.kernelraw ]; then
- # arm raw kernel images are usually located at sdram start + 0x8000
- addpart /dev/ram0 8M@0x8000(kernelraw)
-fi
-
-if [ ! -e /dev/ram0.kernel ]; then
- # Here we can safely put the kernel without risking of overwriting it
- # while extracting
- addpart /dev/ram0 8M@8M(kernel)
-fi
-
if [ x$kernel_loc = xnfs -o x$kernel_loc = xtftp ]; then
if [ x$ip = xdhcp ]; then
dhcp
fi
- if [ $kernelimage_type = uimage ]; then
- netload="/dev/ram0.kernel"
- elif [ $kernelimage_type = zimage ]; then
- netload="/dev/ram0.kernel"
- elif [ $kernelimage_type = raw ]; then
- netload="/dev/ram0.kernelraw"
- elif [ $kernelimage_type = raw_lzo ]; then
- netload="/dev/ram0.kernel"
- else
- echo "error: set kernelimage_type to one of 'uimage', 'zimage', 'raw' or 'raw_lzo'"
- exit 1
- fi
- $kernel_loc $kernelimage $netload || exit 1
- kdev="$netload"
+ kdev=/image
+ $kernel_loc $kernelimage $kdev || exit 1
elif [ x$kernel_loc = xnor ]; then
kdev="/dev/nor0.kernel"
elif [ x$kernel_loc = xnand ]; then
@@ -112,18 +89,6 @@ else
exit 1
fi
-echo "booting kernel of type $kernelimage_type from $kdev"
+echo "booting kernel from $kdev"
-if [ x$kernelimage_type = xuimage ]; then
- bootm $bootm_opt $kdev
-elif [ x$kernelimage_type = xzimage ]; then
- bootz $kdev
-elif [ x$kernelimage_type = xraw ]; then
- if [ $kernel_loc != net ]; then
- cp $kdev /dev/ram0.kernelraw
- fi
- bootu /dev/ram0.kernelraw
-elif [ x$kernelimage_type = xraw_lzo ]; then
- uncompress $kdev /dev/ram0.kernelraw
- bootu /dev/ram0.kernelraw
-fi
+bootm $bootm_opt $kdev
diff --git a/defaultenv/bin/init b/defaultenv/bin/init
index b66f7d988c..b371c423a9 100644
--- a/defaultenv/bin/init
+++ b/defaultenv/bin/init
@@ -21,7 +21,7 @@ if [ -e /dev/nand0 -a -n "$nand_parts" ]; then
fi
if [ -f /env/bin/init_board ]; then
- /env/bin/init_board
+ . /env/bin/init_board
fi
echo
diff --git a/defaultenv/config b/defaultenv/config
index 0aaead5ccb..98662735e1 100644
--- a/defaultenv/config
+++ b/defaultenv/config
@@ -31,14 +31,9 @@ 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
diff --git a/drivers/base/resource.c b/drivers/base/resource.c
index 5c9c16c591..d2f7a07763 100644
--- a/drivers/base/resource.c
+++ b/drivers/base/resource.c
@@ -69,7 +69,7 @@ struct device_d *add_generic_device_res(const char* devname, int id,
}
EXPORT_SYMBOL(add_generic_device_res);
-#ifdef CONFIG_DRIVER_NET_DM9000
+#ifdef CONFIG_DRIVER_NET_DM9K
struct device_d *add_dm9000_device(int id, resource_size_t base,
resource_size_t data, int flags, void *pdata)
{
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 2a1ae7af75..cbc3a84440 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -57,26 +57,6 @@
/* This will be the driver name */
#define DRIVER_NAME "i2c-omap"
-#define OMAP_I2C_REV_REG 0x00
-#define OMAP_I2C_IE_REG 0x04
-#define OMAP_I2C_STAT_REG 0x08
-#define OMAP_I2C_IV_REG 0x0c
-/* For OMAP3 I2C_IV has changed to I2C_WE (wakeup enable) */
-#define OMAP_I2C_WE_REG 0x0c
-#define OMAP_I2C_SYSS_REG 0x10
-#define OMAP_I2C_BUF_REG 0x14
-#define OMAP_I2C_CNT_REG 0x18
-#define OMAP_I2C_DATA_REG 0x1c
-#define OMAP_I2C_SYSC_REG 0x20
-#define OMAP_I2C_CON_REG 0x24
-#define OMAP_I2C_OA_REG 0x28
-#define OMAP_I2C_SA_REG 0x2c
-#define OMAP_I2C_PSC_REG 0x30
-#define OMAP_I2C_SCLL_REG 0x34
-#define OMAP_I2C_SCLH_REG 0x38
-#define OMAP_I2C_SYSTEST_REG 0x3c
-#define OMAP_I2C_BUFSTAT_REG 0x40
-
/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
#define OMAP_I2C_IE_XDR (1 << 14) /* TX Buffer drain int enable */
#define OMAP_I2C_IE_RDR (1 << 13) /* RX Buffer drain int enable */
@@ -168,6 +148,8 @@
struct omap_i2c_struct {
void *base;
+ u8 *regs;
+ u8 reg_shift;
struct resource *ioarea;
u32 speed; /* Speed of bus in Khz */
u16 cmd_err;
@@ -190,16 +172,90 @@ struct omap_i2c_struct {
};
#define to_omap_i2c_struct(a) container_of(a, struct omap_i2c_struct, adapter)
+enum {
+ OMAP_I2C_REV_REG = 0,
+ OMAP_I2C_IE_REG,
+ OMAP_I2C_STAT_REG,
+ OMAP_I2C_IV_REG,
+ OMAP_I2C_WE_REG,
+ OMAP_I2C_SYSS_REG,
+ OMAP_I2C_BUF_REG,
+ OMAP_I2C_CNT_REG,
+ OMAP_I2C_DATA_REG,
+ OMAP_I2C_SYSC_REG,
+ OMAP_I2C_CON_REG,
+ OMAP_I2C_OA_REG,
+ OMAP_I2C_SA_REG,
+ OMAP_I2C_PSC_REG,
+ OMAP_I2C_SCLL_REG,
+ OMAP_I2C_SCLH_REG,
+ OMAP_I2C_SYSTEST_REG,
+ OMAP_I2C_BUFSTAT_REG,
+ OMAP_I2C_REVNB_LO,
+ OMAP_I2C_REVNB_HI,
+ OMAP_I2C_IRQSTATUS_RAW,
+ OMAP_I2C_IRQENABLE_SET,
+ OMAP_I2C_IRQENABLE_CLR,
+};
+
+static const u8 reg_map[] = {
+ [OMAP_I2C_REV_REG] = 0x00,
+ [OMAP_I2C_IE_REG] = 0x01,
+ [OMAP_I2C_STAT_REG] = 0x02,
+ [OMAP_I2C_IV_REG] = 0x03,
+ [OMAP_I2C_WE_REG] = 0x03,
+ [OMAP_I2C_SYSS_REG] = 0x04,
+ [OMAP_I2C_BUF_REG] = 0x05,
+ [OMAP_I2C_CNT_REG] = 0x06,
+ [OMAP_I2C_DATA_REG] = 0x07,
+ [OMAP_I2C_SYSC_REG] = 0x08,
+ [OMAP_I2C_CON_REG] = 0x09,
+ [OMAP_I2C_OA_REG] = 0x0a,
+ [OMAP_I2C_SA_REG] = 0x0b,
+ [OMAP_I2C_PSC_REG] = 0x0c,
+ [OMAP_I2C_SCLL_REG] = 0x0d,
+ [OMAP_I2C_SCLH_REG] = 0x0e,
+ [OMAP_I2C_SYSTEST_REG] = 0x0f,
+ [OMAP_I2C_BUFSTAT_REG] = 0x10,
+};
+
+static const u8 omap4_reg_map[] = {
+ [OMAP_I2C_REV_REG] = 0x04,
+ [OMAP_I2C_IE_REG] = 0x2c,
+ [OMAP_I2C_STAT_REG] = 0x28,
+ [OMAP_I2C_IV_REG] = 0x34,
+ [OMAP_I2C_WE_REG] = 0x34,
+ [OMAP_I2C_SYSS_REG] = 0x90,
+ [OMAP_I2C_BUF_REG] = 0x94,
+ [OMAP_I2C_CNT_REG] = 0x98,
+ [OMAP_I2C_DATA_REG] = 0x9c,
+ [OMAP_I2C_SYSC_REG] = 0x10,
+ [OMAP_I2C_CON_REG] = 0xa4,
+ [OMAP_I2C_OA_REG] = 0xa8,
+ [OMAP_I2C_SA_REG] = 0xac,
+ [OMAP_I2C_PSC_REG] = 0xb0,
+ [OMAP_I2C_SCLL_REG] = 0xb4,
+ [OMAP_I2C_SCLH_REG] = 0xb8,
+ [OMAP_I2C_SYSTEST_REG] = 0xbc,
+ [OMAP_I2C_BUFSTAT_REG] = 0xc0,
+ [OMAP_I2C_REVNB_LO] = 0x00,
+ [OMAP_I2C_REVNB_HI] = 0x04,
+ [OMAP_I2C_IRQSTATUS_RAW] = 0x24,
+ [OMAP_I2C_IRQENABLE_SET] = 0x2c,
+ [OMAP_I2C_IRQENABLE_CLR] = 0x30,
+};
static inline void omap_i2c_write_reg(struct omap_i2c_struct *i2c_omap,
int reg, u16 val)
{
- __raw_writew(val, i2c_omap->base + reg);
+ __raw_writew(val, i2c_omap->base +
+ (i2c_omap->regs[reg] << i2c_omap->reg_shift));
}
static inline u16 omap_i2c_read_reg(struct omap_i2c_struct *i2c_omap, int reg)
{
- return __raw_readw(i2c_omap->base + reg);
+ return __raw_readw(i2c_omap->base +
+ (i2c_omap->regs[reg] << i2c_omap->reg_shift));
}
static void omap_i2c_unidle(struct omap_i2c_struct *i2c_omap)
@@ -228,6 +284,9 @@ static void omap_i2c_idle(struct omap_i2c_struct *i2c_omap)
u16 iv;
i2c_omap->iestate = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IE_REG);
+
+ /* Barebox driver don't need to clear interrupts here */
+
/* omap_i2c_write_reg(i2c_omap, OMAP_I2C_IE_REG, 0); */
if (i2c_omap->rev < OMAP_I2C_REV_2) {
iv = omap_i2c_read_reg(i2c_omap, OMAP_I2C_IV_REG); /* Read clears */
@@ -299,7 +358,7 @@ static int omap_i2c_init(struct omap_i2c_struct *i2c_omap)
/* omap1 handling is missing here */
- if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap4xxx()) {
/*
* HSI2C controller internal clk rate should be 19.2 Mhz for
@@ -472,7 +531,8 @@ complete:
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
- !cpu_is_omap34xx()) {
+ !cpu_is_omap34xx() &&
+ !cpu_is_omap4xxx()) {
if (dev->buf_len) {
*dev->buf++ = w >> 8;
dev->buf_len--;
@@ -512,7 +572,8 @@ complete:
dev->buf_len--;
/* Data reg from 2430 is 8 bit wide */
if (!cpu_is_omap2430() &&
- !cpu_is_omap34xx()) {
+ !cpu_is_omap34xx() &&
+ !cpu_is_omap4xxx()) {
if (dev->buf_len) {
w |= *dev->buf++ << 8;
dev->buf_len--;
@@ -650,7 +711,8 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adapter,
while (ret){
ret = omap_i2c_isr(i2c_omap);
if (is_timeout(start, MSECOND)) {
- dev_err(adapter->dev, "timed out on polling for"
+ dev_err(adapter->dev,
+ "timed out on polling for "
"open i2c message handling\n");
return -ETIMEDOUT;
}
@@ -725,6 +787,14 @@ i2c_omap_probe(struct device_d *pdev)
goto err_free_mem;
}
+ if (cpu_is_omap4xxx()) {
+ i2c_omap->regs = (u8 *)omap4_reg_map;
+ i2c_omap->reg_shift = 0;
+ } else {
+ i2c_omap->regs = (u8 *)reg_map;
+ i2c_omap->reg_shift = 2;
+ }
+
if (pdev->platform_data != NULL)
speed = *(u32 *)pdev->platform_data;
else
@@ -738,7 +808,7 @@ i2c_omap_probe(struct device_d *pdev)
i2c_omap->rev = omap_i2c_read_reg(i2c_omap, OMAP_I2C_REV_REG) & 0xff;
/* i2c_omap->base = OMAP2_I2C_BASE3; */
- if (cpu_is_omap2430() || cpu_is_omap34xx()) {
+ if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap4xxx()) {
u16 s;
/* Set up the fifo size - Get total size */
@@ -750,8 +820,13 @@ i2c_omap_probe(struct device_d *pdev)
* size. This is to ensure that we can handle the status on int
* call back latencies.
*/
+
i2c_omap->fifo_size = (i2c_omap->fifo_size / 2);
- i2c_omap->b_hw = 1; /* Enable hardware fixes */
+
+ if (i2c_omap->rev >= OMAP_I2C_REV_ON_4430)
+ i2c_omap->b_hw = 0; /* Disable hardware fixes */
+ else
+ i2c_omap->b_hw = 1; /* Enable hardware fixes */
}
/* reset ASAP, clearing any IRQs */
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 6ed21cd2a4..8279e5d7ce 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -72,6 +72,13 @@ config MCI_OMAP_HSMMC
Enable this entry to add support to read and write SD cards on a
OMAP4 based system.
+config MCI_PXA
+ bool "PXA"
+ depends on ARCH_PXA
+ help
+ Enable this entry to add support to read and write SD cards on a
+ XScale PXA25x / PXA27x based system.
+
config MCI_ATMEL
bool "ATMEL (AT91)"
depends on ARCH_AT91
diff --git a/drivers/mci/Makefile b/drivers/mci/Makefile
index d7482dc8a2..b7bb846291 100644
--- a/drivers/mci/Makefile
+++ b/drivers/mci/Makefile
@@ -4,5 +4,7 @@ obj-$(CONFIG_MCI_S3C) += s3c.o
obj-$(CONFIG_MCI_IMX) += imx.o
obj-$(CONFIG_MCI_IMX_ESDHC) += imx-esdhc.o
obj-$(CONFIG_MCI_OMAP_HSMMC) += omap_hsmmc.o
+obj-$(CONFIG_I2C_TWL6030) += twl6030.o
+obj-$(CONFIG_MCI_PXA) += pxamci.o
obj-$(CONFIG_MCI_ATMEL) += atmel_mci.o
obj-$(CONFIG_MCI_SPI) += mci_spi.o
diff --git a/drivers/mci/omap_hsmmc.c b/drivers/mci/omap_hsmmc.c
index d171c1dcf7..e671bbea73 100644
--- a/drivers/mci/omap_hsmmc.c
+++ b/drivers/mci/omap_hsmmc.c
@@ -33,6 +33,12 @@
#include <mach/omap_hsmmc.h>
+#if defined(CONFIG_I2C_TWL6030) && \
+ defined(CONFIG_MCI_OMAP_HSMMC) && \
+ defined(CONFIG_ARCH_OMAP4)
+#include <mach/omap4_twl6030_mmc.h>
+#endif
+
struct hsmmc {
unsigned char res1[0x10];
unsigned int sysconfig; /* 0x10 */
@@ -215,6 +221,17 @@ static int mmc_init_setup(struct mci_host *mci, struct device_d *dev)
unsigned int dsor;
uint64_t start;
+/*
+ * Fix voltage for mmc, if booting from nand.
+ * It's necessary to do this here, because
+ * you need to set up this at probetime.
+ */
+#if defined(CONFIG_I2C_TWL6030) && \
+ defined(CONFIG_MCI_OMAP_HSMMC) && \
+ defined(CONFIG_ARCH_OMAP4)
+ set_up_mmc_voltage_omap4();
+#endif
+
writel(readl(&mmc_base->sysconfig) | MMC_SOFTRESET,
&mmc_base->sysconfig);
diff --git a/drivers/mci/pxamci.c b/drivers/mci/pxamci.c
new file mode 100644
index 0000000000..75b61f07b8
--- /dev/null
+++ b/drivers/mci/pxamci.c
@@ -0,0 +1,369 @@
+/*
+ * PXA MCI driver
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Insprired by linux kernel driver
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <clock.h>
+#include <init.h>
+#include <mci.h>
+
+#include <mach/clock.h>
+#include <mach/mci_pxa2xx.h>
+#include <mach/pxa-regs.h>
+#include "pxamci.h"
+
+#define DRIVER_NAME "pxa-mmc"
+
+static void clk_enable(void)
+{
+ CKEN |= CKEN_MMC;
+}
+
+static int pxamci_set_power(struct pxamci_host *host, int on)
+{
+ mci_dbg("on=%d\n", on);
+ if (host->pdata && host->pdata->gpio_power > 0)
+ gpio_set_value(host->pdata->gpio_power,
+ !!on ^ host->pdata->gpio_power_invert);
+ else if (host->pdata && host->pdata->setpower)
+ host->pdata->setpower(&host->mci, on);
+ return 0;
+}
+
+static void pxamci_start_clock(struct pxamci_host *host)
+{
+ mmc_writel(START_CLOCK, MMC_STRPCL);
+}
+
+static void pxamci_stop_clock(struct pxamci_host *host)
+{
+ uint64_t start = get_time_ns();
+ unsigned stat;
+
+ stat = mmc_readl(MMC_STAT);
+ if (stat & STAT_CLK_EN)
+ writel(STOP_CLOCK, host->base + MMC_STRPCL);
+ while (!is_timeout(start, 10 * MSECOND) && stat & STAT_CLK_EN)
+ stat = mmc_readl(MMC_STAT);
+
+ if (stat & STAT_CLK_EN)
+ mci_err("unable to stop clock\n");
+}
+
+static void pxamci_setup_data(struct pxamci_host *host, struct mci_data *data)
+{
+ static const unsigned int timeout = 100000000; /* 10ms */
+
+ mci_dbg("nbblocks=%d, blocksize=%d\n", data->blocks, data->blocksize);
+ mmc_writel(data->blocks, MMC_NOB);
+ mmc_writel(data->blocksize, MMC_BLKLEN);
+ mmc_writel((timeout + 255) / 256, MMC_RDTO);
+}
+
+static int pxamci_read_data(struct pxamci_host *host, unsigned char *dst,
+ unsigned len)
+{
+ int trf_len, trf_len1, trf_len4, ret = 0;
+ uint64_t start;
+ u32 *dst4;
+
+ mci_dbg("dst=%p, len=%u\n", dst, len);
+ while (!ret && len > 0) {
+ trf_len = min_t(int, len, MMC_FIFO_LENGTH);
+
+ for (start = get_time_ns(), ret = -ETIMEDOUT;
+ ret && !is_timeout(start, 10 * MSECOND);)
+ if (mmc_readl(MMC_I_REG) & RXFIFO_RD_REQ)
+ ret = 0;
+ trf_len1 = trf_len % 4;
+ trf_len4 = trf_len / 4;
+ for (dst4 = (u32 *)dst; !ret && trf_len4 > 0; trf_len4--)
+ *dst4++ = mmc_readl(MMC_RXFIFO);
+ for (dst = (u8 *)dst4; !ret && trf_len1 > 0; trf_len1--)
+ *dst++ = mmc_readb(MMC_RXFIFO);
+ len -= trf_len;
+ }
+
+ if (!ret)
+ for (start = get_time_ns(), ret = -ETIMEDOUT;
+ ret && !is_timeout(start, 10 * MSECOND);)
+ if (mmc_readl(MMC_STAT) & STAT_DATA_TRAN_DONE)
+ ret = 0;
+ mci_dbg("ret=%d, remain=%d, stat=%x, mmc_i_reg=%x\n",
+ ret, len, mmc_readl(MMC_STAT), mmc_readl(MMC_I_REG));
+ return ret;
+}
+
+static int pxamci_write_data(struct pxamci_host *host, const unsigned char *src,
+ unsigned len)
+{
+ uint64_t start;
+ int trf_len, partial = 0, ret = 0;
+ unsigned stat;
+
+ mci_dbg("src=%p, len=%u\n", src, len);
+ while (!ret && len > 0) {
+ trf_len = min_t(int, len, MMC_FIFO_LENGTH);
+ partial = trf_len < MMC_FIFO_LENGTH;
+
+ for (start = get_time_ns(), ret = -ETIMEDOUT;
+ ret && !is_timeout(start, 10 * MSECOND);)
+ if (mmc_readl(MMC_I_REG) & TXFIFO_WR_REQ)
+ ret = 0;
+ for (; !ret && trf_len > 0; trf_len--, len--)
+ mmc_writeb(*src++, MMC_TXFIFO);
+ if (partial)
+ mmc_writeb(BUF_PART_FULL, MMC_PRTBUF);
+ }
+
+ if (!ret)
+ for (start = get_time_ns(), ret = -ETIMEDOUT;
+ ret && !is_timeout(start, 100 * MSECOND);) {
+ stat = mmc_readl(MMC_STAT);
+ stat &= STAT_DATA_TRAN_DONE | STAT_PRG_DONE;
+ if (stat == (STAT_DATA_TRAN_DONE | STAT_PRG_DONE))
+ ret = 0;
+ }
+ mci_dbg("ret=%d, remain=%d, stat=%x, mmc_i_reg=%x\n",
+ ret, len, mmc_readl(MMC_STAT), mmc_readl(MMC_I_REG));
+ return ret;
+}
+
+static int pxamci_transfer_data(struct pxamci_host *host,
+ struct mci_data *data)
+{
+ int nbbytes = data->blocks * data->blocksize;
+ int ret;
+ unsigned err_mask = STAT_CRC_READ_ERROR | STAT_CRC_WRITE_ERROR |
+ STAT_READ_TIME_OUT;
+
+ if (data->flags & MMC_DATA_WRITE)
+ ret = pxamci_write_data(host, data->src, nbbytes);
+ else
+ ret = pxamci_read_data(host, data->dest, nbbytes);
+
+ if (!ret && (mmc_readl(MMC_STAT) & err_mask))
+ ret = -EILSEQ;
+ return ret;
+}
+
+static void pxamci_start_cmd(struct pxamci_host *host, struct mci_cmd *cmd,
+ unsigned int cmdat)
+{
+ mci_dbg("cmd=(idx=%d,type=%d,clkrt=%d)\n", cmd->cmdidx, cmd->resp_type,
+ host->clkrt);
+ if (cmd->resp_type & MMC_RSP_BUSY)
+ cmdat |= CMDAT_BUSY;
+
+ switch (cmd->resp_type) {
+ /* r1, r1b, r6, r7 */
+ case MMC_RSP_R1:
+ case MMC_RSP_R1b:
+ cmdat |= CMDAT_RESP_SHORT;
+ break;
+ case MMC_RSP_R2:
+ cmdat |= CMDAT_RESP_R2;
+ break;
+ case MMC_RSP_R3:
+ cmdat |= CMDAT_RESP_R3;
+ break;
+ default:
+ break;
+ }
+
+ mmc_writel(cmd->cmdidx, MMC_CMD);
+ mmc_writel(cmd->cmdarg >> 16, MMC_ARGH);
+ mmc_writel(cmd->cmdarg & 0xffff, MMC_ARGL);
+ mmc_writel(host->clkrt, MMC_CLKRT);
+ pxamci_start_clock(host);
+ mmc_writel(cmdat, MMC_CMDAT);
+}
+
+static int pxamci_cmd_response(struct pxamci_host *host, struct mci_cmd *cmd)
+{
+ unsigned v, stat;
+ int i;
+
+ /*
+ * Did I mention this is Sick. We always need to
+ * discard the upper 8 bits of the first 16-bit word.
+ */
+ v = mmc_readl(MMC_RES) & 0xffff;
+ for (i = 0; i < 4; i++) {
+ u32 w1 = mmc_readl(MMC_RES) & 0xffff;
+ u32 w2 = mmc_readl(MMC_RES) & 0xffff;
+ cmd->response[i] = v << 24 | w1 << 8 | w2 >> 8;
+ v = w2;
+ }
+
+ stat = mmc_readl(MMC_STAT);
+ if (stat & STAT_TIME_OUT_RESPONSE)
+ return -ETIMEDOUT;
+ if (stat & STAT_RES_CRC_ERR && cmd->resp_type & MMC_RSP_CRC) {
+ /*
+ * workaround for erratum #42:
+ * Intel PXA27x Family Processor Specification Update Rev 001
+ * A bogus CRC error can appear if the msb of a 136 bit
+ * response is a one.
+ */
+ if (cpu_is_pxa27x() && cmd->resp_type & MMC_RSP_136 &&
+ cmd->response[0] & 0x80000000)
+ pr_debug("ignoring CRC from command %d - *risky*\n",
+ cmd->cmdidx);
+ else
+ return -EILSEQ;
+ }
+
+ return 0;
+}
+
+static int pxamci_mmccmd(struct pxamci_host *host, struct mci_cmd *cmd,
+ struct mci_data *data, unsigned int cmddat)
+{
+ int ret = 0;
+ uint64_t start;
+
+ pxamci_start_cmd(host, cmd, cmddat);
+ for (start = get_time_ns(), ret = -ETIMEDOUT;
+ ret && !is_timeout(start, 10 * MSECOND);)
+ if (mmc_readl(MMC_STAT) & STAT_END_CMD_RES)
+ ret = 0;
+
+ if (!ret && data)
+ ret = pxamci_transfer_data(host, data);
+
+ if (!ret)
+ ret = pxamci_cmd_response(host, cmd);
+ return ret;
+}
+
+static int pxamci_request(struct mci_host *mci, struct mci_cmd *cmd,
+ struct mci_data *data)
+{
+ struct pxamci_host *host = to_pxamci(mci);
+ unsigned int cmdat;
+ int ret;
+
+ pxamci_stop_clock(host);
+
+ cmdat = host->cmdat;
+ host->cmdat &= ~CMDAT_INIT;
+
+ if (data) {
+ pxamci_setup_data(host, data);
+
+ cmdat &= ~CMDAT_BUSY;
+ cmdat |= CMDAT_DATAEN;
+ if (data->flags & MMC_DATA_WRITE)
+ cmdat |= CMDAT_WRITE;
+ }
+
+ ret = pxamci_mmccmd(host, cmd, data, cmdat);
+ return ret;
+}
+
+static void pxamci_set_ios(struct mci_host *mci, struct device_d *dev,
+ unsigned bus_width, unsigned clock)
+{
+ struct pxamci_host *host = to_pxamci(mci);
+ unsigned int clk_in = pxa_get_mmcclk();
+ int fact;
+
+ mci_dbg("bus_width=%d, clock=%u\n", bus_width, clock);
+ if (clock)
+ fact = min_t(int, clk_in / clock, 1 << 6);
+ else
+ fact = 1 << 6;
+ fact = max_t(int, fact, 1);
+
+ /*
+ * We calculate clkrt here, and will write it on the next command
+ * MMC card clock = mmcclk / (2 ^ clkrt)
+ */
+ /* to handle (19.5MHz, 26MHz) */
+ host->clkrt = fls(fact) - 1;
+
+ if (bus_width == 4)
+ host->cmdat |= CMDAT_SD_4DAT;
+ else
+ host->cmdat &= ~CMDAT_SD_4DAT;
+ host->cmdat |= CMDAT_INIT;
+
+ clk_enable();
+ pxamci_set_power(host, 1);
+}
+
+static int pxamci_init(struct mci_host *mci, struct device_d *dev)
+{
+ struct pxamci_host *host = to_pxamci(mci);
+
+ if (host->pdata && host->pdata->init)
+ return host->pdata->init(mci, dev);
+ return 0;
+}
+
+static int pxamci_probe(struct device_d *dev)
+{
+ struct pxamci_host *host;
+ int gpio_power = -1;
+
+ host = xzalloc(sizeof(*host));
+ host->base = dev_request_mem_region(dev, 0);
+
+ host->mci.init = pxamci_init;
+ host->mci.send_cmd = pxamci_request;
+ host->mci.set_ios = pxamci_set_ios;
+ host->mci.host_caps = MMC_MODE_4BIT;
+ host->mci.hw_dev = dev;
+ host->mci.voltages = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+ /*
+ * Calculate minimum clock rate, rounding up.
+ */
+ host->mci.f_min = pxa_get_mmcclk() >> 6;
+ host->mci.f_max = pxa_get_mmcclk();
+
+ /*
+ * Ensure that the host controller is shut down, and setup
+ * with our defaults.
+ */
+ pxamci_stop_clock(host);
+ mmc_writel(0, MMC_SPI);
+ mmc_writel(64, MMC_RESTO);
+ mmc_writel(0, MMC_I_MASK);
+
+ host->pdata = dev->platform_data;
+ if (host->pdata)
+ gpio_power = host->pdata->gpio_power;
+
+ if (gpio_power > 0)
+ gpio_direction_output(gpio_power,
+ host->pdata->gpio_power_invert);
+
+ mci_register(&host->mci);
+ return 0;
+}
+
+static struct driver_d pxamci_driver = {
+ .name = DRIVER_NAME,
+ .probe = pxamci_probe,
+};
+
+static int __init pxamci_init_driver(void)
+{
+ register_driver(&pxamci_driver);
+ return 0;
+}
+
+device_initcall(pxamci_init_driver);
diff --git a/drivers/mci/pxamci.h b/drivers/mci/pxamci.h
new file mode 100644
index 0000000000..18d12a3038
--- /dev/null
+++ b/drivers/mci/pxamci.h
@@ -0,0 +1,99 @@
+/*
+ * PXA MCI driver
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Insprired by linux kernel driver
+ */
+
+#define MMC_FIFO_LENGTH 32
+
+#define MMC_STRPCL 0x0000
+#define STOP_CLOCK (1 << 0)
+#define START_CLOCK (2 << 0)
+
+#define MMC_STAT 0x0004
+#define STAT_END_CMD_RES (1 << 13)
+#define STAT_PRG_DONE (1 << 12)
+#define STAT_DATA_TRAN_DONE (1 << 11)
+#define STAT_CLK_EN (1 << 8)
+#define STAT_RECV_FIFO_FULL (1 << 7)
+#define STAT_XMIT_FIFO_EMPTY (1 << 6)
+#define STAT_RES_CRC_ERR (1 << 5)
+#define STAT_SPI_READ_ERROR_TOKEN (1 << 4)
+#define STAT_CRC_READ_ERROR (1 << 3)
+#define STAT_CRC_WRITE_ERROR (1 << 2)
+#define STAT_TIME_OUT_RESPONSE (1 << 1)
+#define STAT_READ_TIME_OUT (1 << 0)
+
+#define MMC_CLKRT 0x0008 /* 3 bit */
+
+#define MMC_SPI 0x000c
+#define SPI_CS_ADDRESS (1 << 3)
+#define SPI_CS_EN (1 << 2)
+#define CRC_ON (1 << 1)
+#define SPI_EN (1 << 0)
+
+#define MMC_CMDAT 0x0010
+#define CMDAT_SDIO_INT_EN (1 << 11)
+#define CMDAT_SD_4DAT (1 << 8)
+#define CMDAT_DMAEN (1 << 7)
+#define CMDAT_INIT (1 << 6)
+#define CMDAT_BUSY (1 << 5)
+#define CMDAT_STREAM (1 << 4) /* 1 = stream */
+#define CMDAT_WRITE (1 << 3) /* 1 = write */
+#define CMDAT_DATAEN (1 << 2)
+#define CMDAT_RESP_NONE (0 << 0)
+#define CMDAT_RESP_SHORT (1 << 0)
+#define CMDAT_RESP_R2 (2 << 0)
+#define CMDAT_RESP_R3 (3 << 0)
+
+#define MMC_RESTO 0x0014 /* 7 bit */
+#define MMC_RDTO 0x0018 /* 16 bit */
+#define MMC_BLKLEN 0x001c /* 10 bit */
+#define MMC_NOB 0x0020 /* 16 bit */
+
+#define MMC_PRTBUF 0x0024
+#define BUF_PART_FULL (1 << 0)
+
+#define MMC_I_REG 0x002c
+#define TXFIFO_WR_REQ (1 << 6)
+#define RXFIFO_RD_REQ (1 << 5)
+#define CLK_IS_OFF (1 << 4)
+#define STOP_CMD (1 << 3)
+#define END_CMD_RES (1 << 2)
+#define PRG_DONE (1 << 1)
+#define DATA_TRAN_DONE (1 << 0)
+
+#define MMC_I_MASK 0x0028
+#define MMC_CMD 0x0030
+#define MMC_ARGH 0x0034 /* 16 bit */
+#define MMC_ARGL 0x0038 /* 16 bit */
+#define MMC_RES 0x003c /* 16 bit */
+#define MMC_RXFIFO 0x0040 /* 8 bit */
+#define MMC_TXFIFO 0x0044 /* 8 bit */
+
+struct pxamci_host {
+ struct mci_host mci;
+ void __iomem *base;
+ struct pxamci_platform_data *pdata;
+
+ unsigned int cmdat;
+ int clkrt;
+};
+
+#define to_pxamci(mci) container_of(mci, struct pxamci_host, mci)
+
+#define mmc_readb(reg) readb(host->base + (reg))
+#define mmc_readl(reg) readl(host->base + (reg))
+#define mmc_writeb(val, reg) writeb((val), host->base + (reg))
+#define mmc_writel(val, reg) writel((val), host->base + (reg))
+
+#define mci_dbg(fmt, arg...) \
+ dev_dbg(host->mci.hw_dev, "%s: " fmt, __func__, ## arg)
+#define mci_err(fmt, arg...) \
+ dev_err(host->mci.hw_dev, "%s: " fmt, __func__, ## arg)
diff --git a/drivers/mci/s3c.c b/drivers/mci/s3c.c
index 89c8168fd6..7babab45f1 100644
--- a/drivers/mci/s3c.c
+++ b/drivers/mci/s3c.c
@@ -40,9 +40,9 @@
#include <errno.h>
#include <clock.h>
#include <io.h>
-#include <mach/mci.h>
-#include <mach/s3c24xx-generic.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-mci.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-iomap.h>
#define SDICON 0x0
# define SDICON_SDRESET (1 << 8)
@@ -191,7 +191,7 @@ static unsigned s3c_setup_clock_speed(struct device_d *hw_dev, unsigned nc)
if (nc == 0)
return 0;
- clock = s3c24xx_get_pclk();
+ clock = s3c_get_pclk();
/* Calculate the required prescaler value to get the requested frequency */
mci_psc = (clock + (nc >> 2)) / nc;
@@ -760,8 +760,8 @@ static int s3c_mci_probe(struct device_d *hw_dev)
struct s3c_mci_platform_data *pd = hw_dev->platform_data;
/* TODO replace by the global func: enable the SDI unit clock */
- writel(readl(S3C24X0_CLOCK_POWER_BASE + 0x0c) | 0x200,
- S3C24X0_CLOCK_POWER_BASE + 0x0c);
+ writel(readl(S3C_CLOCK_POWER_BASE + 0x0c) | 0x200,
+ S3C_CLOCK_POWER_BASE + 0x0c);
if (pd == NULL) {
pr_err("Missing platform data\n");
@@ -775,8 +775,8 @@ static int s3c_mci_probe(struct device_d *hw_dev)
/* feed forward the platform specific values */
mci_pdata.voltages = pd->voltages;
mci_pdata.host_caps = pd->caps;
- mci_pdata.f_min = pd->f_min == 0 ? s3c24xx_get_pclk() / 256 : pd->f_min;
- mci_pdata.f_max = pd->f_max == 0 ? s3c24xx_get_pclk() / 2 : pd->f_max;
+ mci_pdata.f_min = pd->f_min == 0 ? s3c_get_pclk() / 256 : pd->f_min;
+ mci_pdata.f_max = pd->f_max == 0 ? s3c_get_pclk() / 2 : pd->f_max;
/*
* Start the clock to let the engine and the card finishes its startup
diff --git a/drivers/mci/twl6030.c b/drivers/mci/twl6030.c
new file mode 100644
index 0000000000..4a875bd62b
--- /dev/null
+++ b/drivers/mci/twl6030.c
@@ -0,0 +1,29 @@
+/*
+ * MCI pmic power.
+ */
+
+#include <mfd/twl6030.h>
+#include <mci/twl6030.h>
+#include <asm/io.h>
+
+static int twl6030_mci_write(u8 address, u8 data)
+{
+ int ret;
+ struct twl6030 *twl6030 = twl6030_get();
+
+ ret = twl6030_reg_write(twl6030, address, data);
+ if (ret != 0)
+ printf("TWL6030:MCI:Write[0x%x] Error %d\n", address, ret);
+
+ return ret;
+}
+
+void twl6030_mci_power_init(void)
+{
+ twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_VOLTAGE,
+ TWL6030_VMMC_VSEL_0 | TWL6030_VMMC_VSEL_2 |
+ TWL6030_VMMC_VSEL_4);
+ twl6030_mci_write(TWL6030_PMCS_VMMC_CFG_STATE,
+ TWL6030_VMMC_STATE0 | TWL6030_VMMC_GRP_APP);
+}
+
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 96440d852f..87797de323 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -16,10 +16,19 @@ config I2C_LP3972
depends on I2C
bool "LP3972 driver"
+config I2C_TWLCORE
+ bool
+
config I2C_TWL4030
depends on I2C
+ depends on USB_TWL4030
+ select I2C_TWLCORE
bool "TWL4030 driver"
- select GPIO
+
+config I2C_TWL6030
+ depends on I2C
+ select I2C_TWLCORE
+ bool "TWL6030 driver"
config DRIVER_SPI_MC13783
depends on SPI
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d411f23b69..1171335b28 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -2,5 +2,7 @@ obj-$(CONFIG_I2C_MC13892) += mc13892.o
obj-$(CONFIG_I2C_MC34704) += mc34704.o
obj-$(CONFIG_I2C_MC9SDZ60) += mc9sdz60.o
obj-$(CONFIG_I2C_LP3972) += lp3972.o
+obj-$(CONFIG_I2C_TWLCORE) += twl-core.o
obj-$(CONFIG_I2C_TWL4030) += twl4030.o
+obj-$(CONFIG_I2C_TWL6030) += twl6030.o
obj-$(CONFIG_DRIVER_SPI_MC13783) += mc13783.o
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
new file mode 100644
index 0000000000..cb2c03dfca
--- /dev/null
+++ b/drivers/mfd/twl-core.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ *
+ * Based on:
+ * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+
+#include <i2c/i2c.h>
+#include <mfd/twl-core.h>
+
+#define to_twlcore(a) container_of(a, struct twlcore, cdev)
+
+static struct twlcore *twl_dev;
+
+struct twlcore *twlcore_get(void)
+{
+ return twl_dev;
+}
+EXPORT_SYMBOL(twlcore_get);
+
+int twlcore_reg_read(struct twlcore *twlcore, u16 reg, u8 *val)
+{
+ int ret;
+ struct i2c_msg xfer_msg[2];
+ struct i2c_msg *msg;
+ int i2c_addr;
+ unsigned char buf = reg & 0xff;
+
+ i2c_addr = twlcore->client->addr + (reg / 0x100);
+
+ /* [MSG1] fill the register address data */
+ msg = &xfer_msg[0];
+ msg->addr = i2c_addr;
+ msg->len = 1;
+ msg->flags = 0;
+ msg->buf = &buf;
+ /* [MSG2] fill the data rx buffer */
+ msg = &xfer_msg[1];
+ msg->addr = i2c_addr;
+ msg->flags = I2C_M_RD;
+ msg->len = 1; /* only n bytes */
+ msg->buf = val;
+ ret = i2c_transfer(twlcore->client->adapter, xfer_msg, 2);
+
+ /* i2c_transfer returns number of messages transferred */
+ if (ret < 0) {
+ pr_err("%s: failed to transfer all messages: %s\n",
+ __func__, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(twlcore_reg_read);
+
+int twlcore_reg_write(struct twlcore *twlcore, u16 reg, u8 val)
+{
+ int ret;
+ struct i2c_msg xfer_msg[1];
+ struct i2c_msg *msg;
+ int i2c_addr;
+ u8 buf[2];
+
+ buf[0] = reg & 0xff;
+ buf[1] = val;
+
+ i2c_addr = twlcore->client->addr + (reg / 0x100);
+
+ /*
+ * [MSG1]: fill the register address data
+ * fill the data Tx buffer
+ */
+ msg = xfer_msg;
+ msg->addr = i2c_addr;
+ msg->len = 2;
+ msg->flags = 0;
+ msg->buf = buf;
+ /* over write the first byte of buffer with the register address */
+ ret = i2c_transfer(twlcore->client->adapter, xfer_msg, 1);
+
+ /* i2c_transfer returns number of messages transferred */
+ if (ret < 0) {
+ pr_err("%s: failed to transfer all messages: %s\n",
+ __func__, strerror(-ret));
+ return ret;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(twlcore_reg_write);
+
+int twlcore_set_bits(struct twlcore *twlcore, u16 reg, u8 mask, u8 val)
+{
+ u8 tmp;
+ int ret;
+
+ ret = twlcore_reg_read(twlcore, reg, &tmp);
+ tmp = (tmp & ~mask) | val;
+
+ if (ret)
+ ret = twlcore_reg_write(twlcore, reg, tmp);
+
+ return ret;
+}
+EXPORT_SYMBOL(twlcore_set_bits);
+
+static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct twlcore *priv = to_twlcore(cdev);
+ u8 *buf = _buf;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ ret = twlcore_reg_read(priv, offset, buf);
+ if (ret)
+ return (ssize_t)ret;
+ buf++;
+ offset++;
+ }
+
+ return count;
+}
+
+static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct twlcore *twlcore = to_twlcore(cdev);
+ const u8 *buf = _buf;
+ size_t i;
+ int ret;
+
+ for (i = 0; i < count; i++) {
+ ret = twlcore_reg_write(twlcore, offset, *buf);
+ if (ret)
+ return (ssize_t)ret;
+ buf++;
+ offset++;
+ }
+
+ return count;
+}
+
+struct file_operations twl_fops = {
+ .lseek = dev_lseek_default,
+ .read = twl_read,
+ .write = twl_write,
+};
+EXPORT_SYMBOL(twl_fops);
diff --git a/drivers/mfd/twl4030.c b/drivers/mfd/twl4030.c
index 6a06bd44bb..191c91f36a 100644
--- a/drivers/mfd/twl4030.c
+++ b/drivers/mfd/twl4030.c
@@ -29,145 +29,19 @@ struct twl4030 *twl4030_get(void)
}
EXPORT_SYMBOL(twl4030_get);
-int twl4030_reg_read(struct twl4030 *twl4030, u16 reg, u8 *val)
-{
- int ret;
- struct i2c_msg xfer_msg[2];
- struct i2c_msg *msg;
- int i2c_addr;
- unsigned char buf = reg & 0xff;
-
- i2c_addr = twl4030->client->addr + (reg / 0x100);
-
- /* [MSG1] fill the register address data */
- msg = &xfer_msg[0];
- msg->addr = i2c_addr;
- msg->len = 1;
- msg->flags = 0; /* Read the register value */
- msg->buf = &buf;
- /* [MSG2] fill the data rx buffer */
- msg = &xfer_msg[1];
- msg->addr = i2c_addr;
- msg->flags = I2C_M_RD; /* Read the register value */
- msg->len = 1; /* only n bytes */
- msg->buf = val;
- ret = i2c_transfer(twl4030->client->adapter, xfer_msg, 2);
-
- /* i2c_transfer returns number of messages transferred */
- if (ret < 0) {
- pr_err("%s: failed to transfer all messages: %s\n", __func__, strerror(-ret));
- return ret;
- }
- return 0;
-}
-EXPORT_SYMBOL(twl4030_reg_read);
-
-int twl4030_reg_write(struct twl4030 *twl4030, u16 reg, u8 val)
-{
- int ret;
- struct i2c_msg xfer_msg[1];
- struct i2c_msg *msg;
- int i2c_addr;
- u8 buf[2];
-
- buf[0] = reg & 0xff;
- buf[1] = val;
-
- i2c_addr = twl4030->client->addr + (reg / 0x100);
-
- /*
- * [MSG1]: fill the register address data
- * fill the data Tx buffer
- */
- msg = xfer_msg;
- msg->addr = i2c_addr;
- msg->len = 2;
- msg->flags = 0;
- msg->buf = buf;
- /* over write the first byte of buffer with the register address */
- ret = i2c_transfer(twl4030->client->adapter, xfer_msg, 1);
-
- /* i2c_transfer returns number of messages transferred */
- if (ret < 0) {
- pr_err("%s: failed to transfer all messages: %s\n", __func__, strerror(-ret));
- return ret;
- }
- return 0;
-}
-EXPORT_SYMBOL(twl4030_reg_write);
-
-int twl4030_set_bits(struct twl4030 *twl4030, enum twl4030_reg reg, u8 mask, u8 val)
-{
- u8 tmp;
- int err;
-
- err = twl4030_reg_read(twl4030, reg, &tmp);
- tmp = (tmp & ~mask) | val;
-
- if (!err)
- err = twl4030_reg_write(twl4030, reg, tmp);
-
- return err;
-}
-EXPORT_SYMBOL(twl4030_set_bits);
-
-static ssize_t twl_read(struct cdev *cdev, void *_buf, size_t count, ulong offset, ulong flags)
-{
- struct twl4030 *priv = to_twl4030(cdev);
- u8 *buf = _buf;
- size_t i = count;
- int err;
-
- while (i) {
- err = twl4030_reg_read(priv, offset, buf);
- if (err)
- return (ssize_t)err;
- buf++;
- i--;
- offset++;
- }
-
- return count;
-}
-
-static ssize_t twl_write(struct cdev *cdev, const void *_buf, size_t count, ulong offset, ulong flags)
-{
- struct twl4030 *twl4030 = to_twl4030(cdev);
- const u8 *buf = _buf;
- size_t i = count;
- int err;
-
- while (i) {
- err = twl4030_reg_write(twl4030, offset, *buf);
- if (err)
- return (ssize_t)err;
- buf++;
- i--;
- offset++;
- }
-
- return count;
-}
-
-static struct file_operations twl_fops = {
- .lseek = dev_lseek_default,
- .read = twl_read,
- .write = twl_write,
-};
-
static int twl_probe(struct device_d *dev)
{
if (twl_dev)
return -EBUSY;
twl_dev = xzalloc(sizeof(struct twl4030));
- twl_dev->cdev.name = DRIVERNAME;
- twl_dev->client = to_i2c_client(dev);
- twl_dev->cdev.size = 1024;
- twl_dev->cdev.dev = dev;
- twl_dev->cdev.ops = &twl_fops;
+ twl_dev->core.cdev.name = DRIVERNAME;
+ twl_dev->core.client = to_i2c_client(dev);
+ twl_dev->core.cdev.size = 1024;
+ twl_dev->core.cdev.dev = dev;
+ twl_dev->core.cdev.ops = &twl_fops;
- devfs_create(&twl_dev->cdev);
+ devfs_create(&(twl_dev->core.cdev));
return 0;
}
@@ -179,8 +53,8 @@ static struct driver_d twl_driver = {
static int twl_init(void)
{
- register_driver(&twl_driver);
- return 0;
+ register_driver(&twl_driver);
+ return 0;
}
device_initcall(twl_init);
diff --git a/drivers/mfd/twl6030.c b/drivers/mfd/twl6030.c
new file mode 100644
index 0000000000..7ecfed8062
--- /dev/null
+++ b/drivers/mfd/twl6030.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ *
+ * This file is released under the GPLv2
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+
+#include <i2c/i2c.h>
+#include <mfd/twl6030.h>
+
+#define DRIVERNAME "twl6030"
+
+#define to_twl6030(a) container_of(a, struct twl6030, cdev)
+
+static struct twl6030 *twl_dev;
+
+struct twl6030 *twl6030_get(void)
+{
+ return twl_dev;
+}
+EXPORT_SYMBOL(twl6030_get);
+
+static int twl_probe(struct device_d *dev)
+{
+ if (twl_dev)
+ return -EBUSY;
+
+ twl_dev = xzalloc(sizeof(struct twl6030));
+ twl_dev->core.cdev.name = DRIVERNAME;
+ twl_dev->core.client = to_i2c_client(dev);
+ twl_dev->core.cdev.size = 1024;
+ twl_dev->core.cdev.dev = dev;
+ twl_dev->core.cdev.ops = &twl_fops;
+
+ devfs_create(&(twl_dev->core.cdev));
+
+ return 0;
+}
+
+static struct driver_d twl_driver = {
+ .name = DRIVERNAME,
+ .probe = twl_probe,
+};
+
+static int twl_init(void)
+{
+ register_driver(&twl_driver);
+ return 0;
+}
+
+device_initcall(twl_init);
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 562f0cd8cd..0a4ca31bda 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -3,6 +3,24 @@ menuconfig MTD
if MTD
+config MTD_WRITE
+ bool
+ default y
+ prompt "Support writing to MTD devices"
+
+config MTD_OOB_DEVICE
+ bool
+ select NAND_READ_OOB if NAND
+ default y
+ prompt "Create a device for reading the OOB data"
+
+config MTD_RAW_DEVICE
+ bool
+ select NAND_READ_OOB if NAND
+ default n
+ prompt "mtdraw device to read/write both data+oob"
+
+source "drivers/mtd/devices/Kconfig"
source "drivers/mtd/nand/Kconfig"
source "drivers/mtd/ubi/Kconfig"
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 85bed11745..4f97d9a6f3 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,3 +1,7 @@
-obj-$(CONFIG_NAND) += nand/
-obj-$(CONFIG_UBI) += ubi/
+obj-$(CONFIG_NAND) += nand/
+obj-$(CONFIG_UBI) += ubi/
+obj-y += devices/
obj-$(CONFIG_PARTITION_NEED_MTD) += partition.o
+obj-$(CONFIG_MTD) += core.o
+obj-$(CONFIG_MTD_OOB_DEVICE) += mtdoob.o
+obj-$(CONFIG_MTD_RAW_DEVICE) += mtdraw.o
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
new file mode 100644
index 0000000000..f25863dade
--- /dev/null
+++ b/drivers/mtd/core.c
@@ -0,0 +1,241 @@
+/*
+ * (C) Copyright 2005
+ * 2N Telekomunikace, a.s. <www.2n.cz>
+ * Ladislav Michl <michl@2n.cz>
+ *
+ * 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
+ * version 2 as published by the Free Software Foundation.
+ *
+ * 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.
+ */
+#include <common.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/mtd.h>
+#include <init.h>
+#include <xfuncs.h>
+#include <driver.h>
+#include <malloc.h>
+#include <ioctl.h>
+#include <nand.h>
+#include <errno.h>
+
+#include "mtd.h"
+
+static LIST_HEAD(mtd_register_hooks);
+
+static ssize_t mtd_read(struct cdev *cdev, void* buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct mtd_info *mtd = cdev->priv;
+ size_t retlen;
+ int ret;
+
+ debug("mtd_read: 0x%08lx 0x%08x\n", offset, count);
+
+ ret = mtd->read(mtd, offset, count, &retlen, buf);
+
+ if(ret) {
+ printf("err %d\n", ret);
+ return ret;
+ }
+ return retlen;
+}
+
+#define NOTALIGNED(x) (x & (mtd->writesize - 1)) != 0
+#define MTDPGALG(x) ((x) & ~(mtd->writesize - 1))
+
+#ifdef CONFIG_MTD_WRITE
+static int all_ff(const void *buf, int len)
+{
+ int i;
+ const uint8_t *p = buf;
+
+ for (i = 0; i < len; i++)
+ if (p[i] != 0xFF)
+ return 0;
+ return 1;
+}
+
+static ssize_t mtd_write(struct cdev* cdev, const void *buf, size_t _count,
+ ulong offset, ulong flags)
+{
+ struct mtd_info *mtd = cdev->priv;
+ size_t retlen, now;
+ int ret = 0;
+ void *wrbuf = NULL;
+ size_t count = _count;
+
+ if (NOTALIGNED(offset)) {
+ printf("offset 0x%0lx not page aligned\n", offset);
+ return -EINVAL;
+ }
+
+ dev_dbg(cdev->dev, "write: 0x%08lx 0x%08x\n", offset, count);
+ while (count) {
+ now = count > mtd->writesize ? mtd->writesize : count;
+
+ if (NOTALIGNED(now)) {
+ dev_dbg(cdev->dev, "not aligned: %d %ld\n",
+ mtd->writesize,
+ (offset % mtd->writesize));
+ wrbuf = xmalloc(mtd->writesize);
+ memset(wrbuf, 0xff, mtd->writesize);
+ memcpy(wrbuf + (offset % mtd->writesize), buf, now);
+ if (!all_ff(wrbuf, mtd->writesize))
+ ret = mtd->write(mtd, MTDPGALG(offset),
+ mtd->writesize, &retlen,
+ wrbuf);
+ free(wrbuf);
+ } else {
+ if (!all_ff(buf, mtd->writesize))
+ ret = mtd->write(mtd, offset, now, &retlen,
+ buf);
+ dev_dbg(cdev->dev,
+ "offset: 0x%08lx now: 0x%08x retlen: 0x%08x\n",
+ offset, now, retlen);
+ }
+ if (ret)
+ goto out;
+
+ offset += now;
+ count -= now;
+ buf += now;
+ }
+
+out:
+ return ret ? ret : _count;
+}
+#endif
+
+int mtd_ioctl(struct cdev *cdev, int request, void *buf)
+{
+ struct mtd_info *mtd = cdev->priv;
+ struct mtd_info_user *user = buf;
+
+ switch (request) {
+ case MEMGETBADBLOCK:
+ dev_dbg(cdev->dev, "MEMGETBADBLOCK: 0x%08lx\n", (off_t)buf);
+ return mtd->block_isbad(mtd, (off_t)buf);
+#ifdef CONFIG_MTD_WRITE
+ case MEMSETBADBLOCK:
+ dev_dbg(cdev->dev, "MEMSETBADBLOCK: 0x%08lx\n", (off_t)buf);
+ return mtd->block_markbad(mtd, (off_t)buf);
+#endif
+ case MEMGETINFO:
+ user->type = mtd->type;
+ user->flags = mtd->flags;
+ user->size = mtd->size;
+ user->erasesize = mtd->erasesize;
+ user->oobsize = mtd->oobsize;
+ user->mtd = mtd;
+ /* The below fields are obsolete */
+ user->ecctype = -1;
+ user->eccsize = 0;
+ return 0;
+ }
+
+ return 0;
+}
+
+#ifdef CONFIG_MTD_WRITE
+static ssize_t mtd_erase(struct cdev *cdev, size_t count, unsigned long offset)
+{
+ struct mtd_info *mtd = cdev->priv;
+ struct erase_info erase;
+ int ret;
+
+ memset(&erase, 0, sizeof(erase));
+ erase.mtd = mtd;
+ erase.addr = offset;
+ erase.len = mtd->erasesize;
+
+ while (count > 0) {
+ dev_dbg(cdev->dev, "erase %d %d\n", erase.addr, erase.len);
+
+ ret = mtd->block_isbad(mtd, erase.addr);
+ if (ret > 0) {
+ printf("Skipping bad block at 0x%08x\n", erase.addr);
+ } else {
+ ret = mtd->erase(mtd, &erase);
+ if (ret)
+ return ret;
+ }
+
+ erase.addr += mtd->erasesize;
+ count -= count > mtd->erasesize ? mtd->erasesize : count;
+ }
+
+ return 0;
+}
+#endif
+
+static struct file_operations mtd_ops = {
+ .read = mtd_read,
+#ifdef CONFIG_MTD_WRITE
+ .write = mtd_write,
+ .erase = mtd_erase,
+#endif
+ .ioctl = mtd_ioctl,
+ .lseek = dev_lseek_default,
+};
+
+int add_mtd_device(struct mtd_info *mtd, char *devname)
+{
+ char str[16];
+ struct mtddev_hook *hook;
+
+ if (!devname)
+ devname = "mtd";
+ strcpy(mtd->class_dev.name, devname);
+ mtd->class_dev.id = -1;
+ register_device(&mtd->class_dev);
+
+ mtd->cdev.ops = &mtd_ops;
+ mtd->cdev.size = mtd->size;
+ mtd->cdev.name = asprintf("%s%d", devname, mtd->class_dev.id);
+ mtd->cdev.priv = mtd;
+ mtd->cdev.dev = &mtd->class_dev;
+ mtd->cdev.mtd = mtd;
+
+ sprintf(str, "%u", mtd->size);
+ dev_add_param_fixed(&mtd->class_dev, "size", str);
+ sprintf(str, "%u", mtd->erasesize);
+ dev_add_param_fixed(&mtd->class_dev, "erasesize", str);
+ sprintf(str, "%u", mtd->writesize);
+ dev_add_param_fixed(&mtd->class_dev, "writesize", str);
+ sprintf(str, "%u", mtd->oobsize);
+ dev_add_param_fixed(&mtd->class_dev, "oobsize", str);
+
+ devfs_create(&mtd->cdev);
+
+ list_for_each_entry(hook, &mtd_register_hooks, hook)
+ if (hook->add_mtd_device)
+ hook->add_mtd_device(mtd, devname);
+
+ return 0;
+}
+
+int del_mtd_device (struct mtd_info *mtd)
+{
+ struct mtddev_hook *hook;
+
+ list_for_each_entry(hook, &mtd_register_hooks, hook)
+ if (hook->del_mtd_device)
+ hook->del_mtd_device(mtd);
+ unregister_device(&mtd->class_dev);
+ free(mtd->param_size.value);
+ free(mtd->cdev.name);
+ return 0;
+}
+
+void mtdcore_add_hook(struct mtddev_hook *hook)
+{
+ list_add(&hook->hook, &mtd_register_hooks);
+}
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
new file mode 100644
index 0000000000..e6d747c46d
--- /dev/null
+++ b/drivers/mtd/devices/Kconfig
@@ -0,0 +1,16 @@
+menu "Self contained MTD devices"
+ depends on MTD!=n
+
+config MTD_DOCG3
+ bool "M-Systems Disk-On-Chip G3"
+ select BCH
+ select BITREV
+ ---help---
+ This provides an MTD device driver for the M-Systems DiskOnChip
+ G3 devices.
+
+ The driver provides access to G3 DiskOnChip, distributed by
+ M-Systems and now Sandisk. The support is very experimental,
+ and doesn't give access to any write operations.
+
+endmenu
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
new file mode 100644
index 0000000000..164a72e188
--- /dev/null
+++ b/drivers/mtd/devices/Makefile
@@ -0,0 +1,5 @@
+#
+# Makefile for the self containted memory technology device drivers.
+#
+
+obj-$(CONFIG_MTD_DOCG3) += docg3.o
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
new file mode 100644
index 0000000000..f7e33dc457
--- /dev/null
+++ b/drivers/mtd/devices/docg3.c
@@ -0,0 +1,1196 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * 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.
+ *
+ * Taken from linux kernel.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <driver.h>
+#include <errno.h>
+#include <malloc.h>
+#include <io.h>
+#include <linux/kernel.h>
+#include <linux/mtd/mtd.h>
+#include <linux/err.h>
+#include <linux/bitrev.h>
+#include <linux/bch.h>
+
+#include "docg3.h"
+
+static unsigned reliable_mode;
+
+/**
+ * struct docg3_bch - BCH engine
+ */
+static struct bch_control *docg3_bch;
+struct mtd_info *docg3_floors[DOC_MAX_NBFLOORS];
+
+static inline u8 doc_readb(struct docg3 *docg3, u16 reg)
+{
+ u8 val = readb(docg3->base + reg);
+
+ doc_dbg("readb(%04x) -> %02x\n", reg, val);
+ return val;
+}
+
+static inline u16 doc_readw(struct docg3 *docg3, u16 reg)
+{
+ u16 val = readw(docg3->base + reg);
+
+ doc_dbg("readb(%04x) -> %04x\n", reg, val);
+ return val;
+}
+
+static inline void doc_writeb(struct docg3 *docg3, u8 val, u16 reg)
+{
+ doc_dbg("writeb(%02x into %04x)\n", val, reg);
+ writeb(val, docg3->base + reg);
+}
+
+static inline void doc_writew(struct docg3 *docg3, u16 val, u16 reg)
+{
+ doc_dbg("writew(%04x into %04x)\n", val, reg);
+ writew(val, docg3->base + reg);
+}
+
+static inline void doc_flash_command(struct docg3 *docg3, u8 cmd)
+{
+ doc_writeb(docg3, cmd, DOC_FLASHCOMMAND);
+}
+
+static inline void doc_flash_sequence(struct docg3 *docg3, u8 seq)
+{
+ doc_writeb(docg3, seq, DOC_FLASHSEQUENCE);
+}
+
+static inline void doc_flash_address(struct docg3 *docg3, u8 addr)
+{
+ doc_writeb(docg3, addr, DOC_FLASHADDRESS);
+}
+
+static int doc_register_readb(struct docg3 *docg3, int reg)
+{
+ u8 val;
+
+ doc_writew(docg3, reg, DOC_READADDRESS);
+ val = doc_readb(docg3, reg);
+ doc_vdbg("Read register %04x : %02x\n", reg, val);
+ return val;
+}
+
+static int doc_register_readw(struct docg3 *docg3, int reg)
+{
+ u16 val;
+
+ doc_writew(docg3, reg, DOC_READADDRESS);
+ val = doc_readw(docg3, reg);
+ doc_vdbg("Read register %04x : %04x\n", reg, val);
+ return val;
+}
+
+static void doc_delay(struct docg3 *docg3, int nbNOPs)
+{
+ int i;
+
+ doc_vdbg("NOP x %d\n", nbNOPs);
+ for (i = 0; i < nbNOPs; i++)
+ doc_writeb(docg3, 0, DOC_NOP);
+}
+
+static int is_prot_seq_error(struct docg3 *docg3)
+{
+ int ctrl;
+
+ ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+ return ctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR);
+}
+
+static int doc_is_ready(struct docg3 *docg3)
+{
+ int ctrl;
+
+ ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+ return ctrl & DOC_CTRL_FLASHREADY;
+}
+
+static int doc_wait_ready(struct docg3 *docg3)
+{
+ int maxWaitCycles = 100;
+
+ do {
+ doc_delay(docg3, 4);
+ } while (!doc_is_ready(docg3) && maxWaitCycles--);
+ doc_delay(docg3, 2);
+ if (maxWaitCycles > 0)
+ return 0;
+ else
+ return -EIO;
+}
+
+static int doc_reset_seq(struct docg3 *docg3)
+{
+ int ret;
+
+ doc_writeb(docg3, 0x10, DOC_FLASHCONTROL);
+ doc_flash_sequence(docg3, DOC_SEQ_RESET);
+ doc_flash_command(docg3, DOC_CMD_RESET);
+ doc_delay(docg3, 2);
+ ret = doc_wait_ready(docg3);
+
+ doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true");
+ return ret;
+}
+
+static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
+ int first)
+{
+ int i, cdr, len4;
+ u16 data16, *dst16;
+ u8 data8, *dst8;
+
+ doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
+ cdr = len & 0x3;
+ len4 = len - cdr;
+
+ if (first)
+ doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
+ dst16 = buf;
+ for (i = 0; i < len4; i += 2) {
+ data16 = doc_readw(docg3, DOC_IOSPACE_DATA);
+ if (dst16) {
+ *dst16 = data16;
+ dst16++;
+ }
+ }
+
+ if (cdr) {
+ doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
+ DOC_READADDRESS);
+ doc_delay(docg3, 1);
+ dst8 = (u8 *)dst16;
+ for (i = 0; i < cdr; i++) {
+ data8 = doc_readb(docg3, DOC_IOSPACE_DATA);
+ if (dst8) {
+ *dst8 = data8;
+ dst8++;
+ }
+ }
+ }
+}
+
+static void doc_set_reliable_mode(struct docg3 *docg3)
+{
+ static char *strmode[] = { "normal", "fast", "reliable", "invalid" };
+
+ doc_dbg("doc_set_reliable_mode(%s)\n", strmode[docg3->reliable]);
+ switch (docg3->reliable) {
+ case 0:
+ break;
+ case 1:
+ doc_flash_sequence(docg3, DOC_SEQ_SET_FASTMODE);
+ doc_flash_command(docg3, DOC_CMD_FAST_MODE);
+ break;
+ case 2:
+ doc_flash_sequence(docg3, DOC_SEQ_SET_RELIABLEMODE);
+ doc_flash_command(docg3, DOC_CMD_FAST_MODE);
+ doc_flash_command(docg3, DOC_CMD_RELIABLE_MODE);
+ break;
+ default:
+ doc_err("doc_set_reliable_mode(): invalid mode\n");
+ break;
+ }
+ doc_delay(docg3, 2);
+}
+
+static void doc_set_asic_mode(struct docg3 *docg3, u8 mode)
+{
+ int i;
+
+ for (i = 0; i < 12; i++)
+ doc_readb(docg3, DOC_IOSPACE_IPL);
+
+ mode |= DOC_ASICMODE_MDWREN;
+ doc_dbg("doc_set_asic_mode(%02x)\n", mode);
+ doc_writeb(docg3, mode, DOC_ASICMODE);
+ doc_writeb(docg3, ~mode, DOC_ASICMODECONFIRM);
+ doc_delay(docg3, 1);
+}
+
+static void doc_set_device_id(struct docg3 *docg3, int id)
+{
+ u8 ctrl;
+
+ doc_dbg("doc_set_device_id(%d)\n", id);
+ doc_writeb(docg3, id, DOC_DEVICESELECT);
+ ctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+
+ ctrl &= ~DOC_CTRL_VIOLATION;
+ ctrl |= DOC_CTRL_CE;
+ doc_writeb(docg3, ctrl, DOC_FLASHCONTROL);
+}
+
+static int doc_set_extra_page_mode(struct docg3 *docg3)
+{
+ int fctrl;
+
+ doc_dbg("doc_set_extra_page_mode()\n");
+ doc_flash_sequence(docg3, DOC_SEQ_PAGE_SIZE_532);
+ doc_flash_command(docg3, DOC_CMD_PAGE_SIZE_532);
+ doc_delay(docg3, 2);
+
+ fctrl = doc_register_readb(docg3, DOC_FLASHCONTROL);
+ if (fctrl & (DOC_CTRL_PROTECTION_ERROR | DOC_CTRL_SEQUENCE_ERROR))
+ return -EIO;
+ else
+ return 0;
+}
+
+static void doc_setup_addr_sector(struct docg3 *docg3, int sector)
+{
+ doc_delay(docg3, 1);
+ doc_flash_address(docg3, sector & 0xff);
+ doc_flash_address(docg3, (sector >> 8) & 0xff);
+ doc_flash_address(docg3, (sector >> 16) & 0xff);
+ doc_delay(docg3, 1);
+}
+
+static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
+ int wear, int ofs)
+{
+ int sector, ret = 0;
+
+ doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n",
+ block0, block1, page, ofs, wear);
+
+ if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) {
+ doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
+ doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
+ doc_delay(docg3, 2);
+ } else {
+ doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
+ doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
+ doc_delay(docg3, 2);
+ }
+
+ doc_set_reliable_mode(docg3);
+ if (wear)
+ ret = doc_set_extra_page_mode(docg3);
+ if (ret)
+ goto out;
+
+ doc_flash_sequence(docg3, DOC_SEQ_READ);
+ sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+ doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+ doc_setup_addr_sector(docg3, sector);
+
+ sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+ doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+ doc_setup_addr_sector(docg3, sector);
+ doc_delay(docg3, 1);
+
+out:
+ return ret;
+}
+
+static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
+{
+ doc_writew(docg3, DOC_ECCCONF0_READ_MODE
+ | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
+ | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
+ DOC_ECCCONF0);
+ doc_delay(docg3, 4);
+ doc_register_readb(docg3, DOC_FLASHCONTROL);
+ return doc_wait_ready(docg3);
+}
+
+static void doc_hamming_ecc_init(struct docg3 *docg3, int nb_bytes)
+{
+ u8 ecc_conf1;
+
+ ecc_conf1 = doc_register_readb(docg3, DOC_ECCCONF1);
+ ecc_conf1 &= ~DOC_ECCCONF1_HAMMING_BITS_MASK;
+ ecc_conf1 |= (nb_bytes & DOC_ECCCONF1_HAMMING_BITS_MASK);
+ doc_writeb(docg3, ecc_conf1, DOC_ECCCONF1);
+}
+
+static int doc_ecc_bch_fix_data(struct docg3 *docg3, void *buf, u8 *hwecc)
+{
+ u8 ecc[DOC_ECC_BCH_SIZE];
+ int errorpos[DOC_ECC_BCH_T], i, numerrs;
+
+ for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+ ecc[i] = bitrev8(hwecc[i]);
+ numerrs = decode_bch(docg3_bch, NULL, DOC_ECC_BCH_COVERED_BYTES,
+ NULL, ecc, NULL, errorpos);
+ BUG_ON(numerrs == -EINVAL);
+ if (numerrs < 0)
+ goto out;
+
+ for (i = 0; i < numerrs; i++)
+ errorpos[i] = (errorpos[i] & ~7) | (7 - (errorpos[i] & 7));
+ for (i = 0; i < numerrs; i++)
+ if (errorpos[i] < DOC_ECC_BCH_COVERED_BYTES*8)
+ /* error is located in data, correct it */
+ change_bit(errorpos[i], buf);
+out:
+ doc_dbg("doc_ecc_bch_fix_data: flipped %d bits\n", numerrs);
+ return numerrs;
+}
+
+static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
+ int page, int offset)
+{
+ int wear_area = 0, ret = 0;
+
+ doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n",
+ block0, block1, page, offset);
+ if (offset >= DOC_LAYOUT_WEAR_OFFSET)
+ wear_area = 1;
+ if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2))
+ return -EINVAL;
+
+ doc_set_device_id(docg3, docg3->device_id);
+ ret = doc_reset_seq(docg3);
+ if (ret)
+ goto err;
+
+ /* Program the flash address block and page */
+ ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset);
+ if (ret)
+ goto err;
+
+ doc_flash_command(docg3, DOC_CMD_READ_ALL_PLANES);
+ doc_delay(docg3, 2);
+ doc_wait_ready(docg3);
+
+ doc_flash_command(docg3, DOC_CMD_SET_ADDR_READ);
+ doc_delay(docg3, 1);
+ if (offset >= DOC_LAYOUT_PAGE_SIZE * 2)
+ offset -= 2 * DOC_LAYOUT_PAGE_SIZE;
+ doc_flash_address(docg3, offset >> 2);
+ doc_delay(docg3, 1);
+ doc_wait_ready(docg3);
+
+ doc_flash_command(docg3, DOC_CMD_READ_FLASH);
+
+ return 0;
+err:
+ doc_writeb(docg3, 0, DOC_DATAEND);
+ doc_delay(docg3, 2);
+ return -EIO;
+}
+
+static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
+ int first)
+{
+ doc_read_data_area(docg3, buf, len, first);
+ doc_delay(docg3, 2);
+ return len;
+}
+
+static void doc_get_bch_hw_ecc(struct docg3 *docg3, u8 *hwecc)
+{
+ int i;
+
+ for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+ hwecc[i] = doc_register_readb(docg3, DOC_BCH_HW_ECC(i));
+}
+
+static void doc_page_finish(struct docg3 *docg3)
+{
+ doc_writeb(docg3, 0, DOC_DATAEND);
+ doc_delay(docg3, 2);
+}
+
+static void doc_read_page_finish(struct docg3 *docg3)
+{
+ doc_page_finish(docg3);
+ doc_set_device_id(docg3, 0);
+}
+
+static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
+ int *ofs, int reliable)
+{
+ uint sector, pages_biblock;
+
+ pages_biblock = DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES;
+ if (reliable == 1 || reliable == 2)
+ pages_biblock /= 2;
+
+ sector = from / DOC_LAYOUT_PAGE_SIZE;
+ *block0 = sector / pages_biblock * DOC_LAYOUT_NBPLANES;
+ *block1 = *block0 + 1;
+ *page = sector % pages_biblock;
+ *page /= DOC_LAYOUT_NBPLANES;
+ if (reliable == 1 || reliable == 2)
+ *page *= 2;
+ if (sector % 2)
+ *ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
+ else
+ *ofs = 0;
+}
+
+static int doc_read_oob(struct mtd_info *mtd, loff_t from,
+ struct mtd_oob_ops *ops)
+{
+ struct docg3 *docg3 = mtd->priv;
+ int block0, block1, page, ret, ofs = 0;
+ u8 *oobbuf = ops->oobbuf;
+ u8 *buf = ops->datbuf;
+ size_t len, ooblen, nbdata, nboob;
+ u8 hwecc[DOC_ECC_BCH_SIZE], eccconf1;
+
+ if (buf)
+ len = ops->len;
+ else
+ len = 0;
+ if (oobbuf)
+ ooblen = ops->ooblen;
+ else
+ ooblen = 0;
+
+ if (oobbuf && ops->mode == MTD_OOB_PLACE)
+ oobbuf += ops->ooboffs;
+
+ doc_dbg("doc_read_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n",
+ from, ops->mode, buf, len, oobbuf, ooblen);
+ if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % DOC_LAYOUT_OOB_SIZE) ||
+ (from % DOC_LAYOUT_PAGE_SIZE))
+ return -EINVAL;
+
+ ret = -EINVAL;
+ calc_block_sector(from + len, &block0, &block1, &page, &ofs,
+ docg3->reliable);
+ if (block1 > docg3->max_block)
+ goto err;
+
+ ops->oobretlen = 0;
+ ops->retlen = 0;
+ ret = 0;
+ while (!ret && (len > 0 || ooblen > 0)) {
+ calc_block_sector(from, &block0, &block1, &page, &ofs,
+ docg3->reliable);
+ nbdata = min_t(size_t, len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+ nboob = min_t(size_t, ooblen, (size_t)DOC_LAYOUT_OOB_SIZE);
+ ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
+ if (ret < 0)
+ goto err;
+ ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES);
+ if (ret < 0)
+ goto err_in_read;
+ ret = doc_read_page_getbytes(docg3, nbdata, buf, 1);
+ if (ret < nbdata)
+ goto err_in_read;
+ doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE - nbdata,
+ NULL, 0);
+ ret = doc_read_page_getbytes(docg3, nboob, oobbuf, 0);
+ if (ret < nboob)
+ goto err_in_read;
+ doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE - nboob,
+ NULL, 0);
+
+ doc_get_bch_hw_ecc(docg3, hwecc);
+ eccconf1 = doc_register_readb(docg3, DOC_ECCCONF1);
+
+ if (nboob >= DOC_LAYOUT_OOB_SIZE) {
+ doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ oobbuf[0], oobbuf[1], oobbuf[2], oobbuf[3],
+ oobbuf[4], oobbuf[5], oobbuf[6]);
+ doc_dbg("OOB - HAMMING: %02x\n", oobbuf[7]);
+ doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ oobbuf[8], oobbuf[9], oobbuf[10], oobbuf[11],
+ oobbuf[12], oobbuf[13], oobbuf[14]);
+ doc_dbg("OOB - UNUSED: %02x\n", oobbuf[15]);
+ }
+ doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
+ doc_dbg("ECC HW_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+ hwecc[0], hwecc[1], hwecc[2], hwecc[3], hwecc[4],
+ hwecc[5], hwecc[6]);
+
+ ret = -EIO;
+ if (is_prot_seq_error(docg3))
+ goto err_in_read;
+ ret = 0;
+ if ((block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) &&
+ (eccconf1 & DOC_ECCCONF1_BCH_SYNDROM_ERR) &&
+ (eccconf1 & DOC_ECCCONF1_PAGE_IS_WRITTEN) &&
+ (ops->mode != MTD_OOB_RAW) &&
+ (nbdata == DOC_LAYOUT_PAGE_SIZE)) {
+ ret = doc_ecc_bch_fix_data(docg3, buf, hwecc);
+ if (ret < 0) {
+ mtd->ecc_stats.failed++;
+ ret = -EBADMSG;
+ }
+ if (ret > 0) {
+ mtd->ecc_stats.corrected += ret;
+ ret = -EUCLEAN;
+ }
+ }
+
+ doc_read_page_finish(docg3);
+ ops->retlen += nbdata;
+ ops->oobretlen += nboob;
+ buf += nbdata;
+ oobbuf += nboob;
+ len -= nbdata;
+ ooblen -= nboob;
+ from += DOC_LAYOUT_PAGE_SIZE;
+ }
+
+ return ret;
+err_in_read:
+ doc_read_page_finish(docg3);
+err:
+ return ret;
+}
+
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct mtd_oob_ops ops;
+ size_t ret;
+
+ memset(&ops, 0, sizeof(ops));
+ ops.datbuf = buf;
+ ops.len = len;
+ ops.mode = MTD_OOB_AUTO;
+
+ ret = doc_read_oob(mtd, from, &ops);
+ *retlen = ops.retlen;
+ return ret;
+}
+
+static int doc_reload_bbt(struct docg3 *docg3)
+{
+ int block = DOC_LAYOUT_BLOCK_BBT;
+ int ret = 0, nbpages, page;
+ u_char *buf = docg3->bbt;
+
+ nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE);
+ for (page = 0; !ret && (page < nbpages); page++) {
+ ret = doc_read_page_prepare(docg3, block, block + 1,
+ page + DOC_LAYOUT_PAGE_BBT, 0);
+ if (!ret)
+ ret = doc_read_page_ecc_init(docg3,
+ DOC_LAYOUT_PAGE_SIZE);
+ if (!ret)
+ doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
+ buf, 1);
+ buf += DOC_LAYOUT_PAGE_SIZE;
+ }
+ doc_read_page_finish(docg3);
+ return ret;
+}
+
+static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
+{
+ struct docg3 *docg3 = mtd->priv;
+ int block0, block1, page, ofs, is_good;
+
+ calc_block_sector(from, &block0, &block1, &page, &ofs,
+ docg3->reliable);
+ doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
+ from, block0, block1, page, ofs);
+
+ if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA)
+ return 0;
+ if (block1 > docg3->max_block)
+ return -EINVAL;
+
+ is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7));
+ return !is_good;
+}
+
+#ifdef MTD_WRITE
+static int doc_guess_autoecc(struct mtd_oob_ops *ops)
+{
+ int autoecc;
+
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_AUTO:
+ autoecc = 1;
+ break;
+ case MTD_OOB_RAW:
+ autoecc = 0;
+ break;
+ default:
+ autoecc = -EINVAL;
+ }
+ return autoecc;
+}
+
+static void doc_fill_autooob(u8 *dst, u8 *oobsrc)
+{
+ memcpy(dst, oobsrc, DOC_LAYOUT_OOB_PAGEINFO_SZ);
+ dst[DOC_LAYOUT_OOB_UNUSED_OFS] = oobsrc[DOC_LAYOUT_OOB_PAGEINFO_SZ];
+}
+
+static int doc_backup_oob(struct docg3 *docg3, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ int ooblen = ops->ooblen, autoecc;
+
+ if (ooblen != DOC_LAYOUT_OOB_SIZE)
+ return -EINVAL;
+ autoecc = doc_guess_autoecc(ops);
+ if (autoecc < 0)
+ return autoecc;
+
+ docg3->oob_write_ofs = to;
+ docg3->oob_autoecc = autoecc;
+ if (ops->mode == MTD_OOB_AUTO) {
+ doc_fill_autooob(docg3->oob_write_buf, ops->oobbuf);
+ ops->oobretlen = 8;
+ } else {
+ memcpy(docg3->oob_write_buf, ops->oobbuf, DOC_LAYOUT_OOB_SIZE);
+ ops->oobretlen = DOC_LAYOUT_OOB_SIZE;
+ }
+ return 0;
+}
+
+static void doc_write_data_area(struct docg3 *docg3, const void *buf, int len)
+{
+ int i, cdr, len4;
+ u16 *src16;
+ u8 *src8;
+
+ doc_dbg("doc_write_data_area(buf=%p, len=%d)\n", buf, len);
+ cdr = len & 0x3;
+ len4 = len - cdr;
+
+ doc_writew(docg3, DOC_IOSPACE_DATA, DOC_READADDRESS);
+ src16 = (u16 *)buf;
+ for (i = 0; i < len4; i += 2) {
+ doc_writew(docg3, *src16, DOC_IOSPACE_DATA);
+ src16++;
+ }
+
+ src8 = (u8 *)src16;
+ for (i = 0; i < cdr; i++) {
+ doc_writew(docg3, DOC_IOSPACE_DATA | DOC_READADDR_ONE_BYTE,
+ DOC_READADDRESS);
+ doc_writeb(docg3, *src8, DOC_IOSPACE_DATA);
+ src8++;
+ }
+}
+
+static void doc_setup_writeaddr_sector(struct docg3 *docg3, int sector, int ofs)
+{
+ ofs = ofs >> 2;
+ doc_delay(docg3, 1);
+ doc_flash_address(docg3, ofs & 0xff);
+ doc_flash_address(docg3, sector & 0xff);
+ doc_flash_address(docg3, (sector >> 8) & 0xff);
+ doc_flash_address(docg3, (sector >> 16) & 0xff);
+ doc_delay(docg3, 1);
+}
+
+static int doc_write_seek(struct docg3 *docg3, int block0, int block1, int page,
+ int ofs)
+{
+ int ret = 0, sector;
+
+ doc_dbg("doc_write_seek(blocks=(%d,%d), page=%d, ofs=%d)\n",
+ block0, block1, page, ofs);
+
+ doc_set_reliable_mode(docg3);
+
+ if (ofs < 2 * DOC_LAYOUT_PAGE_SIZE) {
+ doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE1);
+ doc_flash_command(docg3, DOC_CMD_READ_PLANE1);
+ doc_delay(docg3, 2);
+ } else {
+ doc_flash_sequence(docg3, DOC_SEQ_SET_PLANE2);
+ doc_flash_command(docg3, DOC_CMD_READ_PLANE2);
+ doc_delay(docg3, 2);
+ }
+
+ doc_flash_sequence(docg3, DOC_SEQ_PAGE_SETUP);
+ doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1);
+
+ sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+ doc_setup_writeaddr_sector(docg3, sector, ofs);
+
+ doc_flash_command(docg3, DOC_CMD_PROG_CYCLE3);
+ doc_delay(docg3, 2);
+ ret = doc_wait_ready(docg3);
+ if (ret)
+ goto out;
+
+ doc_flash_command(docg3, DOC_CMD_PROG_CYCLE1);
+ sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+ doc_setup_writeaddr_sector(docg3, sector, ofs);
+ doc_delay(docg3, 1);
+
+out:
+ return ret;
+}
+
+static int doc_write_page_ecc_init(struct docg3 *docg3, int len)
+{
+ doc_writew(docg3, DOC_ECCCONF0_WRITE_MODE
+ | DOC_ECCCONF0_BCH_ENABLE | DOC_ECCCONF0_HAMMING_ENABLE
+ | (len & DOC_ECCCONF0_DATA_BYTES_MASK),
+ DOC_ECCCONF0);
+ doc_delay(docg3, 4);
+ doc_register_readb(docg3, DOC_FLASHCONTROL);
+ return doc_wait_ready(docg3);
+}
+
+static void doc_write_page_putbytes(struct docg3 *docg3, int len,
+ const u_char *buf)
+{
+ doc_write_data_area(docg3, buf, len);
+ doc_delay(docg3, 2);
+}
+
+static void doc_ecc_disable(struct docg3 *docg3)
+{
+ doc_writew(docg3, DOC_ECCCONF0_READ_MODE, DOC_ECCCONF0);
+ doc_delay(docg3, 4);
+}
+
+static int doc_get_op_status(struct docg3 *docg3)
+{
+ u8 status;
+
+ doc_flash_sequence(docg3, DOC_SEQ_PLANES_STATUS);
+ doc_flash_command(docg3, DOC_CMD_PLANES_STATUS);
+ doc_delay(docg3, 5);
+
+ doc_ecc_disable(docg3);
+ doc_read_data_area(docg3, &status, 1, 1);
+ return status;
+}
+
+static int doc_write_erase_wait_status(struct docg3 *docg3)
+{
+ int status, ret = 0;
+
+ if (!doc_is_ready(docg3))
+ mdelay(3000);
+ if (!doc_is_ready(docg3)) {
+ doc_dbg("Timeout reached and the chip is still not ready\n");
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ status = doc_get_op_status(docg3);
+ if (status & DOC_PLANES_STATUS_FAIL) {
+ doc_dbg("Erase/Write failed on (a) plane(s), status = %x\n",
+ status);
+ ret = -EIO;
+ }
+
+out:
+ doc_page_finish(docg3);
+ return ret;
+}
+
+static int doc_erase_block(struct docg3 *docg3, int block0, int block1)
+{
+ int ret, sector;
+
+ doc_dbg("doc_erase_block(blocks=(%d,%d))\n", block0, block1);
+ ret = doc_reset_seq(docg3);
+ if (ret)
+ return -EIO;
+
+ doc_set_reliable_mode(docg3);
+ doc_flash_sequence(docg3, DOC_SEQ_ERASE);
+
+ sector = block0 << DOC_ADDR_BLOCK_SHIFT;
+ doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+ doc_setup_addr_sector(docg3, sector);
+ sector = block1 << DOC_ADDR_BLOCK_SHIFT;
+ doc_flash_command(docg3, DOC_CMD_PROG_BLOCK_ADDR);
+ doc_setup_addr_sector(docg3, sector);
+ doc_delay(docg3, 1);
+
+ doc_flash_command(docg3, DOC_CMD_ERASECYCLE2);
+ doc_delay(docg3, 2);
+
+ if (is_prot_seq_error(docg3)) {
+ doc_err("Erase blocks %d,%d error\n", block0, block1);
+ return -EIO;
+ }
+
+ return doc_write_erase_wait_status(docg3);
+}
+
+static int doc_erase(struct mtd_info *mtd, struct erase_info *info)
+{
+ struct docg3 *docg3 = mtd->priv;
+ uint64_t len;
+ int block0, block1, page, ret, ofs = 0;
+
+ doc_dbg("doc_erase(from=%d, len=%d\n", info->addr, info->len);
+ doc_set_device_id(docg3, docg3->device_id);
+
+ info->state = MTD_ERASE_PENDING;
+ calc_block_sector(info->addr + info->len, &block0, &block1, &page,
+ &ofs, docg3->reliable);
+ ret = -EINVAL;
+ if (block1 > docg3->max_block || page || ofs)
+ goto reset_err;
+
+ ret = 0;
+ calc_block_sector(info->addr, &block0, &block1, &page, &ofs,
+ docg3->reliable);
+ doc_set_reliable_mode(docg3);
+ for (len = info->len; !ret && len > 0; len -= mtd->erasesize) {
+ info->state = MTD_ERASING;
+ ret = doc_erase_block(docg3, block0, block1);
+ block0 += 2;
+ block1 += 2;
+ }
+
+ if (ret)
+ goto reset_err;
+
+ info->state = MTD_ERASE_DONE;
+ return 0;
+
+reset_err:
+ info->state = MTD_ERASE_FAILED;
+ return ret;
+}
+
+static int doc_write_page(struct docg3 *docg3, loff_t to, const u_char *buf,
+ const u_char *oob, int autoecc)
+{
+ int block0, block1, page, ret, ofs = 0;
+ u8 hwecc[DOC_ECC_BCH_SIZE], hamming;
+
+ doc_dbg("doc_write_page(to=%lld)\n", to);
+ calc_block_sector(to, &block0, &block1, &page, &ofs, docg3->reliable);
+
+ doc_set_device_id(docg3, docg3->device_id);
+ ret = doc_reset_seq(docg3);
+ if (ret)
+ goto err;
+
+ /* Program the flash address block and page */
+ ret = doc_write_seek(docg3, block0, block1, page, ofs);
+ if (ret)
+ goto err;
+
+ doc_write_page_ecc_init(docg3, DOC_ECC_BCH_TOTAL_BYTES);
+ doc_delay(docg3, 2);
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_PAGE_SIZE, buf);
+
+ if (oob && autoecc) {
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ, oob);
+ doc_delay(docg3, 2);
+ oob += DOC_LAYOUT_OOB_UNUSED_OFS;
+
+ hamming = doc_register_readb(docg3, DOC_HAMMINGPARITY);
+ doc_delay(docg3, 2);
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_HAMMING_SZ,
+ &hamming);
+ doc_delay(docg3, 2);
+
+ doc_get_bch_hw_ecc(docg3, hwecc);
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_BCH_SZ, hwecc);
+ doc_delay(docg3, 2);
+
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_UNUSED_SZ, oob);
+ }
+ if (oob && !autoecc)
+ doc_write_page_putbytes(docg3, DOC_LAYOUT_OOB_SIZE, oob);
+
+ doc_delay(docg3, 2);
+ doc_page_finish(docg3);
+ doc_delay(docg3, 2);
+ doc_flash_command(docg3, DOC_CMD_PROG_CYCLE2);
+ doc_delay(docg3, 2);
+
+ /*
+ * The wait status will perform another doc_page_finish() call, but that
+ * seems to please the docg3, so leave it.
+ */
+ ret = doc_write_erase_wait_status(docg3);
+ return ret;
+err:
+ doc_read_page_finish(docg3);
+ return ret;
+}
+
+static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
+ struct mtd_oob_ops *ops)
+{
+ struct docg3 *docg3 = mtd->priv;
+ int block0, block1, page, ret, pofs = 0, autoecc, oobdelta;
+ u8 *oobbuf = ops->oobbuf;
+ u8 *buf = ops->datbuf;
+ size_t len, ooblen;
+ u8 oob[DOC_LAYOUT_OOB_SIZE] __aligned(4);
+
+ if (buf)
+ len = ops->len;
+ else
+ len = 0;
+ if (oobbuf)
+ ooblen = ops->ooblen;
+ else
+ ooblen = 0;
+
+ if (oobbuf && ops->mode == MTD_OOB_PLACE)
+ oobbuf += ops->ooboffs;
+
+ doc_dbg("doc_write_oob(from=%lld, mode=%d, data=(%p:%zu), oob=(%p:%zu))\n",
+ ofs, ops->mode, buf, len, oobbuf, ooblen);
+ switch (ops->mode) {
+ case MTD_OOB_PLACE:
+ case MTD_OOB_RAW:
+ oobdelta = mtd->oobsize;
+ break;
+ case MTD_OOB_AUTO:
+ oobdelta = mtd->ecclayout->oobavail;
+ break;
+ default:
+ oobdelta = 0;
+ }
+ if ((len % DOC_LAYOUT_PAGE_SIZE) || (ooblen % oobdelta) ||
+ (ofs % DOC_LAYOUT_PAGE_SIZE))
+ return -EINVAL;
+ if (len && ooblen &&
+ (len / DOC_LAYOUT_PAGE_SIZE) != (ooblen / oobdelta))
+ return -EINVAL;
+
+ ret = -EINVAL;
+ calc_block_sector(ofs + len, &block0, &block1, &page, &pofs,
+ docg3->reliable);
+ if (block1 > docg3->max_block)
+ goto err;
+
+ ops->oobretlen = 0;
+ ops->retlen = 0;
+ ret = 0;
+ if (len == 0 && ooblen == 0)
+ return -EINVAL;
+ if (len == 0 && ooblen > 0)
+ return doc_backup_oob(docg3, ofs, ops);
+
+ autoecc = doc_guess_autoecc(ops);
+ if (autoecc < 0)
+ return autoecc;
+
+ while (!ret && len > 0) {
+ memset(oob, 0, sizeof(oob));
+ if (ofs == docg3->oob_write_ofs)
+ memcpy(oob, docg3->oob_write_buf, DOC_LAYOUT_OOB_SIZE);
+ else if (ooblen > 0 && ops->mode == MTD_OOB_AUTO)
+ doc_fill_autooob(oob, oobbuf);
+ else if (ooblen > 0)
+ memcpy(oob, oobbuf, DOC_LAYOUT_OOB_SIZE);
+ ret = doc_write_page(docg3, ofs, buf, oob, autoecc);
+
+ ofs += DOC_LAYOUT_PAGE_SIZE;
+ len -= DOC_LAYOUT_PAGE_SIZE;
+ buf += DOC_LAYOUT_PAGE_SIZE;
+ if (ooblen) {
+ oobbuf += oobdelta;
+ ooblen -= oobdelta;
+ ops->oobretlen += oobdelta;
+ }
+ ops->retlen += DOC_LAYOUT_PAGE_SIZE;
+ }
+err:
+ doc_set_device_id(docg3, 0);
+ return ret;
+}
+
+static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct docg3 *docg3 = mtd->priv;
+ int ret;
+ struct mtd_oob_ops ops;
+
+ doc_dbg("doc_write(to=%lld, len=%zu)\n", to, len);
+ ops.datbuf = (char *)buf;
+ ops.len = len;
+ ops.mode = MTD_OOB_PLACE;
+ ops.oobbuf = NULL;
+ ops.ooblen = 0;
+ ops.ooboffs = 0;
+
+ ret = doc_write_oob(mtd, to, &ops);
+ *retlen = ops.retlen;
+ return ret;
+}
+#endif
+
+static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
+{
+ struct docg3 *docg3 = mtd->priv;
+ int cfg;
+
+ cfg = doc_register_readb(docg3, DOC_CONFIGURATION);
+ docg3->if_cfg = (cfg & DOC_CONF_IF_CFG ? 1 : 0);
+ docg3->reliable = reliable_mode;
+
+ switch (chip_id) {
+ case DOC_CHIPID_G3:
+ mtd->name = asprintf("DiskOnChip G3 floor %d",
+ docg3->device_id);
+ docg3->max_block = 2047;
+ break;
+ }
+ mtd->type = MTD_NANDFLASH;
+ mtd->flags = MTD_CAP_NANDFLASH;
+ mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
+ if (docg3->reliable == 2)
+ mtd->size /= 2;
+ mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
+ if (docg3->reliable == 2)
+ mtd->erasesize /= 2;
+ mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+ mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
+ mtd->read = doc_read;
+ mtd->read_oob = doc_read_oob;
+ mtd->block_isbad = doc_block_isbad;
+#ifdef MTD_WRITE
+ mtd->erase = doc_erase;
+ mtd->write = doc_write;
+ mtd->write_oob = doc_write_oob;
+#endif
+}
+
+static struct mtd_info *doc_probe_device(void __iomem *base, int floor,
+ struct device_d *dev)
+{
+ int ret, bbt_nbpages;
+ u16 chip_id, chip_id_inv;
+ struct docg3 *docg3;
+ struct mtd_info *mtd;
+
+ ret = -ENOMEM;
+ docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
+ if (!docg3)
+ goto nomem1;
+ mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+ if (!mtd)
+ goto nomem2;
+ mtd->priv = docg3;
+ bbt_nbpages = DIV_ROUND_UP(docg3->max_block + 1,
+ 8 * DOC_LAYOUT_PAGE_SIZE);
+ docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+ if (!docg3->bbt)
+ goto nomem3;
+
+ docg3->dev = dev;
+ docg3->device_id = floor;
+ docg3->base = base;
+ doc_set_device_id(docg3, docg3->device_id);
+ if (!floor)
+ doc_set_asic_mode(docg3, DOC_ASICMODE_RESET);
+ doc_set_asic_mode(docg3, DOC_ASICMODE_NORMAL);
+
+ chip_id = doc_register_readw(docg3, DOC_CHIPID);
+ chip_id_inv = doc_register_readw(docg3, DOC_CHIPID_INV);
+
+ ret = 0;
+ if (chip_id != (u16)(~chip_id_inv))
+ goto nomem3;
+
+ switch (chip_id) {
+ case DOC_CHIPID_G3:
+ doc_info("Found a G3 DiskOnChip at addr %p, floor %d\n",
+ base, floor);
+ break;
+ default:
+ doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
+ goto nomem3;
+ }
+
+ doc_set_driver_info(chip_id, mtd);
+
+ doc_hamming_ecc_init(docg3, DOC_LAYOUT_OOB_PAGEINFO_SZ);
+ doc_reload_bbt(docg3);
+ return mtd;
+
+nomem3:
+ kfree(mtd);
+nomem2:
+ kfree(docg3);
+nomem1:
+ return ERR_PTR(ret);
+}
+
+static int __init docg3_probe(struct device_d *dev)
+{
+ struct mtd_info *mtd;
+ void __iomem *base;
+ int ret, floor, found = 0;
+
+ base = dev_request_mem_region(dev, 0);
+
+ ret = -ENOMEM;
+ docg3_bch = init_bch(DOC_ECC_BCH_M, DOC_ECC_BCH_T,
+ DOC_ECC_BCH_PRIMPOLY);
+ if (!docg3_bch)
+ goto nomem2;
+
+ /* for (floor = 0; floor < DOC_MAX_NBFLOORS; floor++) { */
+ for (floor = 0; floor < 2; floor++) {
+ mtd = doc_probe_device(base, floor, dev);
+ if (IS_ERR(mtd)) {
+ ret = PTR_ERR(mtd);
+ goto err_probe;
+ }
+ if (!mtd) {
+ if (floor == 0)
+ goto notfound;
+ else
+ continue;
+ }
+ docg3_floors[floor] = mtd;
+ ret = add_mtd_device(mtd, NULL);
+ if (ret)
+ goto err_probe;
+ found++;
+ }
+
+ if (ret)
+ goto err_probe;
+ if (!found)
+ goto notfound;
+
+ return 0;
+
+notfound:
+ ret = -ENODEV;
+ dev_info(dev, "No supported DiskOnChip found\n");
+err_probe:
+ free_bch(docg3_bch);
+nomem2:
+ return ret;
+}
+
+static struct driver_d g3_driver = {
+ .name = "docg3",
+ .probe = docg3_probe,
+};
+
+static int __init docg3_init(void)
+{
+ return register_driver(&g3_driver);
+}
+
+device_initcall(docg3_init);
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
new file mode 100644
index 0000000000..97eafe3520
--- /dev/null
+++ b/drivers/mtd/devices/docg3.h
@@ -0,0 +1,283 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * 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.
+ *
+ */
+
+#ifndef _MTD_DOCG3_H
+#define _MTD_DOCG3_H
+
+/*
+ * Flash memory areas :
+ * - 0x0000 .. 0x07ff : IPL
+ * - 0x0800 .. 0x0fff : Data area
+ * - 0x1000 .. 0x17ff : Registers
+ * - 0x1800 .. 0x1fff : Unknown
+ */
+#define DOC_IOSPACE_IPL 0x0000
+#define DOC_IOSPACE_DATA 0x0800
+#define DOC_IOSPACE_SIZE 0x2000
+
+/*
+ * DOC G3 layout and adressing scheme
+ * A page address for the block "b", plane "P" and page "p":
+ * address = [bbbb bPpp pppp]
+ */
+
+#define DOC_ADDR_PAGE_MASK 0x3f
+#define DOC_ADDR_BLOCK_SHIFT 6
+#define DOC_LAYOUT_NBPLANES 2
+#define DOC_LAYOUT_PAGES_PER_BLOCK 64
+#define DOC_LAYOUT_PAGE_SIZE 512
+#define DOC_LAYOUT_OOB_SIZE 16
+#define DOC_LAYOUT_WEAR_SIZE 8
+#define DOC_LAYOUT_PAGE_OOB_SIZE \
+ (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE)
+#define DOC_LAYOUT_WEAR_OFFSET (DOC_LAYOUT_PAGE_OOB_SIZE * 2)
+#define DOC_LAYOUT_BLOCK_SIZE \
+ (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
+
+/*
+ * ECC related constants
+ */
+#define DOC_ECC_BCH_M 14
+#define DOC_ECC_BCH_T 4
+#define DOC_ECC_BCH_PRIMPOLY 0x4443
+#define DOC_ECC_BCH_SIZE 7
+#define DOC_ECC_BCH_COVERED_BYTES \
+ (DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ + \
+ DOC_LAYOUT_OOB_HAMMING_SZ)
+#define DOC_ECC_BCH_TOTAL_BYTES \
+ (DOC_ECC_BCH_COVERED_BYTES + DOC_LAYOUT_OOB_BCH_SZ)
+
+/*
+ * Blocks distribution
+ */
+#define DOC_LAYOUT_BLOCK_BBT 0
+#define DOC_LAYOUT_BLOCK_OTP 0
+#define DOC_LAYOUT_BLOCK_FIRST_DATA 6
+
+#define DOC_LAYOUT_PAGE_BBT 4
+
+/*
+ * Extra page OOB (16 bytes wide) layout
+ */
+#define DOC_LAYOUT_OOB_PAGEINFO_OFS 0
+#define DOC_LAYOUT_OOB_HAMMING_OFS 7
+#define DOC_LAYOUT_OOB_BCH_OFS 8
+#define DOC_LAYOUT_OOB_UNUSED_OFS 15
+#define DOC_LAYOUT_OOB_PAGEINFO_SZ 7
+#define DOC_LAYOUT_OOB_HAMMING_SZ 1
+#define DOC_LAYOUT_OOB_BCH_SZ 7
+#define DOC_LAYOUT_OOB_UNUSED_SZ 1
+
+
+#define DOC_CHIPID_G3 0x200
+#define DOC_ERASE_MARK 0xaa
+#define DOC_MAX_NBFLOORS 4
+/*
+ * Flash registers
+ */
+#define DOC_CHIPID 0x1000
+#define DOC_TEST 0x1004
+#define DOC_BUSLOCK 0x1006
+#define DOC_ENDIANCONTROL 0x1008
+#define DOC_DEVICESELECT 0x100a
+#define DOC_ASICMODE 0x100c
+#define DOC_CONFIGURATION 0x100e
+#define DOC_INTERRUPTCONTROL 0x1010
+#define DOC_READADDRESS 0x101a
+#define DOC_DATAEND 0x101e
+#define DOC_INTERRUPTSTATUS 0x1020
+
+#define DOC_FLASHSEQUENCE 0x1032
+#define DOC_FLASHCOMMAND 0x1034
+#define DOC_FLASHADDRESS 0x1036
+#define DOC_FLASHCONTROL 0x1038
+#define DOC_NOP 0x103e
+
+#define DOC_ECCCONF0 0x1040
+#define DOC_ECCCONF1 0x1042
+#define DOC_ECCPRESET 0x1044
+#define DOC_HAMMINGPARITY 0x1046
+#define DOC_BCH_HW_ECC(idx) (0x1048 + idx)
+
+#define DOC_PROTECTION 0x1056
+#define DOC_DPS0_KEY 0x105c
+#define DOC_DPS1_KEY 0x105e
+#define DOC_DPS0_ADDRLOW 0x1060
+#define DOC_DPS0_ADDRHIGH 0x1062
+#define DOC_DPS1_ADDRLOW 0x1064
+#define DOC_DPS1_ADDRHIGH 0x1066
+#define DOC_DPS0_STATUS 0x106c
+#define DOC_DPS1_STATUS 0x106e
+
+#define DOC_ASICMODECONFIRM 0x1072
+#define DOC_CHIPID_INV 0x1074
+#define DOC_POWERMODE 0x107c
+
+/*
+ * Flash sequences
+ * A sequence is preset before one or more commands are input to the chip.
+ */
+#define DOC_SEQ_RESET 0x00
+#define DOC_SEQ_PAGE_SIZE_532 0x03
+#define DOC_SEQ_SET_FASTMODE 0x05
+#define DOC_SEQ_SET_RELIABLEMODE 0x09
+#define DOC_SEQ_READ 0x12
+#define DOC_SEQ_SET_PLANE1 0x0e
+#define DOC_SEQ_SET_PLANE2 0x10
+#define DOC_SEQ_PAGE_SETUP 0x1d
+#define DOC_SEQ_ERASE 0x27
+#define DOC_SEQ_PLANES_STATUS 0x31
+
+/*
+ * Flash commands
+ */
+#define DOC_CMD_READ_PLANE1 0x00
+#define DOC_CMD_SET_ADDR_READ 0x05
+#define DOC_CMD_READ_ALL_PLANES 0x30
+#define DOC_CMD_READ_PLANE2 0x50
+#define DOC_CMD_READ_FLASH 0xe0
+#define DOC_CMD_PAGE_SIZE_532 0x3c
+
+#define DOC_CMD_PROG_BLOCK_ADDR 0x60
+#define DOC_CMD_PROG_CYCLE1 0x80
+#define DOC_CMD_PROG_CYCLE2 0x10
+#define DOC_CMD_PROG_CYCLE3 0x11
+#define DOC_CMD_ERASECYCLE2 0xd0
+#define DOC_CMD_READ_STATUS 0x70
+#define DOC_CMD_PLANES_STATUS 0x71
+
+#define DOC_CMD_RELIABLE_MODE 0x22
+#define DOC_CMD_FAST_MODE 0xa2
+
+#define DOC_CMD_RESET 0xff
+
+/*
+ * Flash register : DOC_FLASHCONTROL
+ */
+#define DOC_CTRL_VIOLATION 0x20
+#define DOC_CTRL_CE 0x10
+#define DOC_CTRL_UNKNOWN_BITS 0x08
+#define DOC_CTRL_PROTECTION_ERROR 0x04
+#define DOC_CTRL_SEQUENCE_ERROR 0x02
+#define DOC_CTRL_FLASHREADY 0x01
+
+/*
+ * Flash register : DOC_ASICMODE
+ */
+#define DOC_ASICMODE_RESET 0x00
+#define DOC_ASICMODE_NORMAL 0x01
+#define DOC_ASICMODE_POWERDOWN 0x02
+#define DOC_ASICMODE_MDWREN 0x04
+#define DOC_ASICMODE_BDETCT_RESET 0x08
+#define DOC_ASICMODE_RSTIN_RESET 0x10
+#define DOC_ASICMODE_RAM_WE 0x20
+
+/*
+ * Flash register : DOC_ECCCONF0
+ */
+#define DOC_ECCCONF0_WRITE_MODE 0x0000
+#define DOC_ECCCONF0_READ_MODE 0x8000
+#define DOC_ECCCONF0_AUTO_ECC_ENABLE 0x4000
+#define DOC_ECCCONF0_HAMMING_ENABLE 0x1000
+#define DOC_ECCCONF0_BCH_ENABLE 0x0800
+#define DOC_ECCCONF0_DATA_BYTES_MASK 0x07ff
+
+/*
+ * Flash register : DOC_ECCCONF1
+ */
+#define DOC_ECCCONF1_BCH_SYNDROM_ERR 0x80
+#define DOC_ECCCONF1_UNKOWN1 0x40
+#define DOC_ECCCONF1_PAGE_IS_WRITTEN 0x20
+#define DOC_ECCCONF1_UNKOWN3 0x10
+#define DOC_ECCCONF1_HAMMING_BITS_MASK 0x0f
+
+/*
+ * Flash register : DOC_PROTECTION
+ */
+#define DOC_PROTECT_FOUNDRY_OTP_LOCK 0x01
+#define DOC_PROTECT_CUSTOMER_OTP_LOCK 0x02
+#define DOC_PROTECT_LOCK_INPUT 0x04
+#define DOC_PROTECT_STICKY_LOCK 0x08
+#define DOC_PROTECT_PROTECTION_ENABLED 0x10
+#define DOC_PROTECT_IPL_DOWNLOAD_LOCK 0x20
+#define DOC_PROTECT_PROTECTION_ERROR 0x80
+
+/*
+ * Flash register : DOC_DPS0_STATUS and DOC_DPS1_STATUS
+ */
+#define DOC_DPS_OTP_PROTECTED 0x01
+#define DOC_DPS_READ_PROTECTED 0x02
+#define DOC_DPS_WRITE_PROTECTED 0x04
+#define DOC_DPS_HW_LOCK_ENABLED 0x08
+#define DOC_DPS_KEY_OK 0x80
+
+/*
+ * Flash register : DOC_CONFIGURATION
+ */
+#define DOC_CONF_IF_CFG 0x80
+#define DOC_CONF_MAX_ID_MASK 0x30
+#define DOC_CONF_VCCQ_3V 0x01
+
+/*
+ * Flash register : DOC_READADDRESS
+ */
+#define DOC_READADDR_INC 0x8000
+#define DOC_READADDR_ONE_BYTE 0x4000
+#define DOC_READADDR_ADDR_MASK 0x1fff
+
+/*
+ * Flash register : DOC_POWERMODE
+ */
+#define DOC_POWERDOWN_READY 0x80
+
+/*
+ * Status of erase and write operation
+ */
+#define DOC_PLANES_STATUS_FAIL 0x01
+#define DOC_PLANES_STATUS_PLANE0_KO 0x02
+#define DOC_PLANES_STATUS_PLANE1_KO 0x04
+
+/*
+ * DPS key management
+ *
+ * Each floor of docg3 has 2 protection areas: DPS0 and DPS1. These areas span
+ * across block boundaries, and define whether these blocks can be read or
+ * written.
+ * The definition is dynamically stored in page 0 of blocks (2,3) for DPS0, and
+ * page 0 of blocks (4,5) for DPS1.
+ */
+#define DOC_LAYOUT_DPS_KEY_LENGTH 8
+
+struct docg3 {
+ struct device_d *dev;
+ void __iomem *base;
+ unsigned int device_id:4;
+ unsigned int if_cfg:1;
+ unsigned int reliable:2;
+ int max_block;
+ u8 *bbt;
+ loff_t oob_write_ofs;
+ int oob_autoecc;
+ u8 oob_write_buf[DOC_LAYOUT_OOB_SIZE];
+};
+
+#define doc_err(fmt, arg...) dev_err(docg3->dev, fmt, ## arg)
+#define doc_info(fmt, arg...) dev_info(docg3->dev, fmt, ## arg)
+#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, fmt, ## arg)
+#define doc_vdbg(fmt, arg...) dev_dbg(docg3->dev, fmt, ## arg)
+
+#endif
diff --git a/drivers/mtd/mtd.h b/drivers/mtd/mtd.h
new file mode 100644
index 0000000000..c8af6e3c9d
--- /dev/null
+++ b/drivers/mtd/mtd.h
@@ -0,0 +1,42 @@
+/*
+ * MTD devices registration
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * 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.
+ *
+ */
+
+/**
+ * mtddev_hook - hook to register additional mtd devices
+ * @add_mtd_device: called when a MTD driver calls add_mtd_device()
+ * @del_mtd_device: called when a MTD driver calls del_mtd_device()
+ *
+ * Provide a hook to be called whenether a add_mtd_device() is called.
+ * Additionnal devices like mtdoob and mtdraw subscribe to the service.
+ */
+struct mtddev_hook {
+ struct list_head hook;
+ int (*add_mtd_device)(struct mtd_info *mtd, char *devname);
+ int (*del_mtd_device)(struct mtd_info *mtd);
+};
+struct cdev;
+
+/**
+ * mtdcore_add_hook - add a hook to MTD registration/unregistration
+ * @hook: the hook
+ *
+ * Normally called in a coredevice_initcall() to add another MTD layout (such as
+ * mtdraw, ...)
+ */
+void mtdcore_add_hook(struct mtddev_hook *hook);
+
+int mtd_ioctl(struct cdev *cdev, int request, void *buf);
diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c
new file mode 100644
index 0000000000..be656a4d33
--- /dev/null
+++ b/drivers/mtd/mtdoob.c
@@ -0,0 +1,97 @@
+/*
+ * MTD oob device
+ *
+ * Copyright (C) 2011 Sascha Hauer
+ *
+ * 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.
+ *
+ * Adds a character devices :
+ * - mtdoob<N>
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <ioctl.h>
+#include <errno.h>
+#include <linux/mtd/mtd.h>
+
+#include "mtd.h"
+
+struct mtdoob {
+ struct cdev cdev;
+ struct mtd_info *mtd;
+};
+
+static struct mtd_info *to_mtd(struct cdev *cdev)
+{
+ struct mtdoob *mtdoob = cdev->priv;
+ return mtdoob->mtd;
+}
+
+static ssize_t mtd_read_oob(struct cdev *cdev, void *buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct mtd_info *mtd = to_mtd(cdev);
+ struct mtd_oob_ops ops;
+ int ret;
+
+ if (count < mtd->oobsize)
+ return -EINVAL;
+
+ ops.mode = MTD_OOB_RAW;
+ ops.ooboffs = 0;
+ ops.ooblen = mtd->oobsize;
+ ops.oobbuf = buf;
+ ops.datbuf = NULL;
+ ops.len = mtd->oobsize;
+
+ offset /= mtd->oobsize;
+ ret = mtd->read_oob(mtd, offset * mtd->writesize, &ops);
+ if (ret)
+ return ret;
+
+ return mtd->oobsize;
+}
+
+static struct file_operations mtd_ops_oob = {
+ .read = mtd_read_oob,
+ .ioctl = mtd_ioctl,
+ .lseek = dev_lseek_default,
+};
+
+static int add_mtdoob_device(struct mtd_info *mtd, char *devname)
+{
+ struct mtdoob *mtdoob;
+
+ mtdoob = xzalloc(sizeof(*mtdoob));
+ mtdoob->cdev.ops = &mtd_ops_oob;
+ mtdoob->cdev.size = (mtd->size / mtd->writesize) * mtd->oobsize;
+ mtdoob->cdev.name = asprintf("%s_oob%d", devname, mtd->class_dev.id);
+ mtdoob->cdev.priv = mtdoob;
+ mtdoob->cdev.dev = &mtd->class_dev;
+ mtdoob->mtd = mtd;
+ devfs_create(&mtdoob->cdev);
+
+ return 0;
+}
+
+static struct mtddev_hook mtdoob_hook = {
+ .add_mtd_device = add_mtdoob_device,
+};
+
+static int __init register_mtdoob(void)
+{
+ mtdcore_add_hook(&mtdoob_hook);
+ return 0;
+}
+
+coredevice_initcall(register_mtdoob);
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
new file mode 100644
index 0000000000..b1cce3d836
--- /dev/null
+++ b/drivers/mtd/mtdraw.c
@@ -0,0 +1,303 @@
+/*
+ * MTD raw device
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * 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.
+ *
+ * Adds a character devices :
+ * - mtdraw<N>
+ *
+ * Device mtd_raw<N> provides acces to the MTD "pages+OOB". For example if a MTD
+ * has pages of 512 bytes and OOB of 16 bytes, mtd_oob<N> will be made of blocks
+ * of 528 bytes, with page data being followed by OOB.
+ * The layout will be: <page0> <oob0> <page1> <oob1> ... <pageN> <oobN>.
+ * This means that a read at offset 516 of 20 bytes will give the 12 last bytes
+ * of the OOB of page0, and the 8 first bytes of page1.
+ * Same thing applies for writes, which have to be page+oob aligned (ie. offset
+ * and size should be multiples of (mtd->writesize + mtd->oobsize)).
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <ioctl.h>
+#include <errno.h>
+#include <linux/mtd/mtd.h>
+
+#include "mtd.h"
+
+/* Must be a multiple of the largest NAND page size */
+#define RAW_WRITEBUF_SIZE 4096
+
+/**
+ * mtdraw - mtdraw device private data
+ * @cdev: character device "mtdraw<N>"
+ * @mtd: MTD device to handle read/writes/erases
+ *
+ * @writebuf: buffer to handle unaligned writes (ie. writes of sizes which are
+ * not multiples of MTD (writesize+oobsize)
+ * @write_fill: number of bytes in writebuf
+ * @write_ofs: offset in character device (mtdraw) where last write(s) stored
+ * bytes because of unaligned writes (ie. remain of writesize+oobsize write)
+ *
+ * The mtdraw device must allow unaligned writes. This is enabled by a write buffer which gathers data to issue mtd->write_oob() with full page+oob data.
+ * Suppose writesize=512, oobsize=16.
+ * A first write of 512 bytes triggers:
+ * - write_ofs = offset of write()
+ * - write_fill = 512
+ * - copy of the 512 provided bytes into writebuf
+ * - no actual mtd->write if done
+ * A second write of 512 bytes triggers:
+ * - copy of the 16 first bytes into writebuf
+ * - a mtd->write_oob() from writebuf
+ * - empty writebuf
+ * - copy the remaining 496 bytes into writebuf
+ * => write_fill = 496, write_ofs = offset + 528
+ * Etc ...
+ */
+struct mtdraw {
+ struct cdev cdev;
+ struct mtd_info *mtd;
+ void *writebuf;
+ int write_fill;
+ int write_ofs;
+};
+
+static struct mtdraw *to_mtdraw(struct cdev *cdev)
+{
+ return cdev->priv;
+}
+
+static struct mtd_info *to_mtd(struct cdev *cdev)
+{
+ struct mtdraw *mtdraw = to_mtdraw(cdev);
+ return mtdraw->mtd;
+}
+
+static ssize_t mtdraw_read_unaligned(struct mtd_info *mtd, void *dst,
+ size_t count, int skip, ulong offset)
+{
+ struct mtd_oob_ops ops;
+ ssize_t ret;
+ int partial = 0;
+ void *tmp = dst;
+
+ if (skip || count < mtd->writesize + mtd->oobsize)
+ partial = 1;
+ if (partial)
+ tmp = malloc(mtd->writesize + mtd->oobsize);
+ if (!tmp)
+ return -ENOMEM;
+ ops.mode = MTD_OOB_RAW;
+ ops.datbuf = tmp;
+ ops.len = mtd->writesize;
+ ops.oobbuf = tmp + mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ret = mtd->read_oob(mtd, offset, &ops);
+ if (ret)
+ goto err;
+ if (partial)
+ memcpy(dst, tmp + skip, count);
+ ret = count;
+err:
+ if (partial)
+ free(tmp);
+
+ return ret;
+}
+
+static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct mtd_info *mtd = to_mtd(cdev);
+ ssize_t retlen = 0, ret = 1, toread;
+ ulong numpage;
+ int skip;
+
+ numpage = offset / (mtd->writesize + mtd->oobsize);
+ skip = offset % (mtd->writesize + mtd->oobsize);
+
+ while (ret > 0 && count > 0) {
+ toread = min_t(int, count, mtd->writesize + mtd->oobsize);
+ ret = mtdraw_read_unaligned(mtd, buf, toread,
+ skip, numpage++ * mtd->writesize);
+ buf += ret;
+ skip = 0;
+ count -= ret;
+ retlen += ret;
+ }
+ if (ret < 0)
+ printf("err %d\n", ret);
+ else
+ ret = retlen;
+ return ret;
+}
+
+#ifdef CONFIG_MTD_WRITE
+static ssize_t mtdraw_blkwrite(struct mtd_info *mtd, const void *buf,
+ ulong offset)
+{
+ struct mtd_oob_ops ops;
+ int ret;
+
+ ops.mode = MTD_OOB_RAW;
+ ops.datbuf = (void *)buf;
+ ops.len = mtd->writesize;
+ ops.oobbuf = (void *)buf + mtd->writesize;
+ ops.ooblen = mtd->oobsize;
+ ret = mtd->write_oob(mtd, offset, &ops);
+ if (!ret)
+ ret = ops.retlen + ops.oobretlen;
+ return ret;
+}
+
+static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes)
+{
+ memcpy(mtdraw->writebuf + mtdraw->write_fill, src, nbbytes);
+ mtdraw->write_fill += nbbytes;
+}
+
+static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count,
+ ulong offset, ulong flags)
+{
+ struct mtdraw *mtdraw = to_mtdraw(cdev);
+ struct mtd_info *mtd = to_mtd(cdev);
+ int bsz = mtd->writesize + mtd->oobsize;
+ ulong numpage;
+ size_t retlen = 0, tofill;
+ int ret = 0;
+
+ if (mtdraw->write_fill &&
+ mtdraw->write_ofs + mtdraw->write_fill != offset)
+ return -EINVAL;
+ if (mtdraw->write_fill == 0 && offset % bsz)
+ return -EINVAL;
+
+ if (mtdraw->write_fill) {
+ tofill = min_t(size_t, count, bsz - mtdraw->write_fill);
+ mtdraw_fillbuf(mtdraw, buf, tofill);
+ offset += tofill;
+ count -= tofill;
+ retlen += tofill;
+ }
+
+ if (mtdraw->write_fill == bsz) {
+ ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, mtdraw->write_ofs);
+ retlen += ret;
+ mtdraw->write_fill = 0;
+ }
+
+ numpage = offset / (mtd->writesize + mtd->oobsize);
+ while (ret >= 0 && count >= bsz) {
+ ret = mtdraw_blkwrite(mtd, buf + retlen,
+ mtd->writesize * numpage++);
+ count -= ret;
+ retlen += ret;
+ offset += ret;
+ }
+
+ if (ret >= 0 && count) {
+ mtdraw->write_ofs = offset - mtdraw->write_fill;
+ mtdraw_fillbuf(mtdraw, buf + retlen, count);
+ }
+
+ if (ret < 0) {
+ printf("err %d\n", ret);
+ return ret;
+ } else {
+ return retlen;
+ }
+}
+
+static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, ulong offset)
+{
+ struct mtd_info *mtd = to_mtd(cdev);
+ struct erase_info erase;
+ int ret;
+
+ offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize;
+ count = count / (mtd->writesize + mtd->oobsize) * mtd->writesize;
+
+ memset(&erase, 0, sizeof(erase));
+ erase.mtd = mtd;
+ erase.addr = offset;
+ erase.len = mtd->erasesize;
+
+ while (count > 0) {
+ debug("erase %d %d\n", erase.addr, erase.len);
+
+ ret = mtd->block_isbad(mtd, erase.addr);
+ if (ret > 0) {
+ printf("Skipping bad block at 0x%08x\n", erase.addr);
+ } else {
+ ret = mtd->erase(mtd, &erase);
+ if (ret)
+ return ret;
+ }
+
+ erase.addr += mtd->erasesize;
+ count -= count > mtd->erasesize ? mtd->erasesize : count;
+ }
+
+ return 0;
+}
+#else
+static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count,
+ ulong offset, ulong flags)
+{
+ return 0;
+}
+static ssize_t mtdraw_erase(struct cdev *cdev, size_t count, ulong offset)
+{
+ return 0;
+}
+#endif
+
+static const struct file_operations mtd_raw_fops = {
+ .read = mtdraw_read,
+ .write = mtdraw_write,
+ .erase = mtdraw_erase,
+ .ioctl = mtd_ioctl,
+ .lseek = dev_lseek_default,
+};
+
+static int add_mtdraw_device(struct mtd_info *mtd, char *devname)
+{
+ struct mtdraw *mtdraw;
+
+ mtdraw = xzalloc(sizeof(*mtdraw));
+ mtdraw->writebuf = xmalloc(RAW_WRITEBUF_SIZE);
+ mtdraw->mtd = mtd;
+
+ mtdraw->cdev.ops = (struct file_operations *)&mtd_raw_fops;
+ mtdraw->cdev.size = mtd->size / mtd->writesize *
+ (mtd->writesize + mtd->oobsize);
+ mtdraw->cdev.name = asprintf("%sraw%d", devname, mtd->class_dev.id);
+ mtdraw->cdev.priv = mtdraw;
+ mtdraw->cdev.dev = &mtd->class_dev;
+ mtdraw->cdev.mtd = mtd;
+ devfs_create(&mtdraw->cdev);
+
+ return 0;
+}
+
+static struct mtddev_hook mtdraw_hook = {
+ .add_mtd_device = add_mtdraw_device,
+};
+
+static int __init register_mtdraw(void)
+{
+ mtdcore_add_hook(&mtdraw_hook);
+ return 0;
+}
+
+coredevice_initcall(register_mtdraw);
diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 1cc29a8eca..926a64bf96 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -8,11 +8,6 @@ menuconfig NAND
if NAND
-config NAND_WRITE
- bool
- default y
- prompt "Support writing to Nand"
-
config NAND_ECC_SOFT
bool
default y
@@ -53,12 +48,6 @@ config NAND_BBT
Say y here to include support for bad block tables. This speeds
up the process of checking for bad blocks
-config NAND_OOB_DEVICE
- bool
- select NAND_READ_OOB
- default y
- prompt "create a device for reading the OOB data"
-
config NAND_IMX
bool
prompt "i.MX NAND driver"
@@ -76,9 +65,9 @@ config NAND_ATMEL
prompt "Atmel (AT91SAM9xxx) NAND driver"
depends on ARCH_AT91
-config NAND_S3C24X0
+config NAND_S3C24XX
bool
- prompt "Samsung S3C24X0 NAND driver"
+ prompt "Samsung S3C24XX NAND driver"
depends on ARCH_S3C24xx
help
Add support for processor's NAND device controller.
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 149cbbfa22..5c6d8b3cca 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -1,7 +1,7 @@
# Generic NAND options
-obj-$(CONFIG_NAND) += nand.o nand_ecc.o
-obj-$(CONFIG_NAND_WRITE) += nand_write.o
+obj-$(CONFIG_NAND) += nand_ecc.o
+obj-$(CONFIG_MTD_WRITE) += nand_write.o
obj-$(CONFIG_NAND_ECC_SOFT) += nand_ecc.o nand_swecc.o
obj-$(CONFIG_NAND_ECC_HW) += nand_hwecc.o
obj-$(CONFIG_NAND_ECC_HW_SYNDROME) += nand_hwecc_syndrome.o
@@ -14,4 +14,4 @@ obj-$(CONFIG_MTD_NAND_NOMADIK) += nomadik_nand.o
obj-$(CONFIG_NAND_IMX) += nand_imx.o
obj-$(CONFIG_NAND_OMAP_GPMC) += nand_omap_gpmc.o nand_omap_bch_decoder.o
obj-$(CONFIG_NAND_ATMEL) += atmel_nand.o
-obj-$(CONFIG_NAND_S3C24X0) += nand_s3c2410.o
+obj-$(CONFIG_NAND_S3C24XX) += nand_s3c24xx.o
diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 8cc1b51f7f..3213de2967 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -36,18 +36,6 @@
#include <errno.h>
-#ifdef CONFIG_MTD_NAND_ATMEL_ECC_HW
-#define hard_ecc 1
-#else
-#define hard_ecc 0
-#endif
-
-#ifdef CONFIG_MTD_NAND_ATMEL_ECC_NONE
-#define no_ecc 1
-#else
-#define no_ecc 0
-#endif
-
/* Register access macros */
#define ecc_readl(add, reg) \
readl(add + ATMEL_ECC_##reg)
@@ -148,30 +136,16 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
*/
static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd->priv;
-
- readsb(nand_chip->IO_ADDR_R, buf, len);
-}
-
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
-{
- struct nand_chip *nand_chip = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
- readsw(nand_chip->IO_ADDR_R, buf, len / 2);
+ memcpy_fromio(buf, chip->IO_ADDR_R, len);
}
static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
{
- struct nand_chip *nand_chip = mtd->priv;
+ struct nand_chip *chip = mtd->priv;
- writesb(nand_chip->IO_ADDR_W, buf, len);
-}
-
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
-{
- struct nand_chip *nand_chip = mtd->priv;
-
- writesw(nand_chip->IO_ADDR_W, buf, len / 2);
+ memcpy_toio(chip->IO_ADDR_W, buf, len);
}
/*
@@ -188,7 +162,6 @@ static int atmel_nand_calculate(struct mtd_info *mtd,
{
struct nand_chip *nand_chip = mtd->priv;
struct atmel_nand_host *host = nand_chip->priv;
-/* uint32_t *eccpos = nand_chip->ecc.layout->eccpos; */
unsigned int ecc_value;
/* get the first 2 ECC bytes */
@@ -417,14 +390,11 @@ static int __init atmel_nand_probe(struct device_d *dev)
nand_chip->chip_delay = 20; /* 20us command delay time */
- if (host->board->bus_width_16) { /* 16-bit bus width */
+ if (host->board->bus_width_16) /* 16-bit bus width */
nand_chip->options |= NAND_BUSWIDTH_16;
- nand_chip->read_buf = atmel_read_buf16;
- nand_chip->write_buf = atmel_write_buf16;
- } else {
- nand_chip->read_buf = atmel_read_buf;
- nand_chip->write_buf = atmel_write_buf;
- }
+
+ nand_chip->read_buf = atmel_read_buf;
+ nand_chip->write_buf = atmel_write_buf;
atmel_nand_enable(host);
@@ -485,7 +455,7 @@ static int __init atmel_nand_probe(struct device_d *dev)
goto err_scan_tail;
}
- add_mtd_device(mtd);
+ add_mtd_device(mtd, "nand");
if (!res)
return res;
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index 2433945571..6da68dcb17 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -1358,7 +1358,7 @@ static int __init nftl_scan_bbt(struct mtd_info *mtd)
At least as nand_bbt.c is currently written. */
if ((ret = nand_scan_bbt(mtd, NULL)))
return ret;
- add_mtd_device(mtd);
+ add_mtd_device(mtd, "nand");
#ifdef CONFIG_MTD_PARTITIONS
if (!no_autopart)
add_mtd_partitions(mtd, parts, numparts);
@@ -1418,7 +1418,7 @@ static int __init inftl_scan_bbt(struct mtd_info *mtd)
do without it for non-INFTL use, since all it gives us is
autopartitioning, but I want to give it more thought. */
if (!numparts) return -EIO;
- add_mtd_device(mtd);
+ add_mtd_device(mtd, "nand");
#ifdef CONFIG_MTD_PARTITIONS
if (!no_autopart)
add_mtd_partitions(mtd, parts, numparts);
diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c
index dbfb8e38b3..bd30438958 100644
--- a/drivers/mtd/nand/nand-bb.c
+++ b/drivers/mtd/nand/nand-bb.c
@@ -45,6 +45,7 @@ struct nand_bb {
size_t raw_size;
size_t size;
off_t offset;
+ unsigned long flags;
void *writebuf;
struct cdev cdev;
@@ -89,7 +90,7 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count,
/* Must be a multiple of the largest NAND page size */
#define BB_WRITEBUF_SIZE 4096
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static int nand_bb_write_buf(struct nand_bb *bb, size_t count)
{
int ret, now;
@@ -164,13 +165,14 @@ static int nand_bb_erase(struct cdev *cdev, size_t count, unsigned long offset)
}
#endif
-static int nand_bb_open(struct cdev *cdev)
+static int nand_bb_open(struct cdev *cdev, unsigned long flags)
{
struct nand_bb *bb = cdev->priv;
if (bb->open)
return -EBUSY;
+ bb->flags = flags;
bb->open = 1;
bb->offset = 0;
bb->needs_write = 0;
@@ -183,7 +185,7 @@ static int nand_bb_close(struct cdev *cdev)
{
struct nand_bb *bb = cdev->priv;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (bb->needs_write)
nand_bb_write_buf(bb, bb->offset % BB_WRITEBUF_SIZE);
#endif
@@ -211,11 +213,44 @@ static int nand_bb_calc_size(struct nand_bb *bb)
return 0;
}
+static off_t nand_bb_lseek(struct cdev *cdev, off_t __offset)
+{
+ struct nand_bb *bb = cdev->priv;
+ unsigned long raw_pos = 0;
+ uint32_t offset = __offset;
+ int ret;
+
+ /* lseek only in readonly mode */
+ if (bb->flags & O_ACCMODE)
+ return -ENOSYS;
+ while (raw_pos < bb->raw_size) {
+ off_t now = min(offset, bb->info.erasesize);
+
+ ret = cdev_ioctl(bb->cdev_parent, MEMGETBADBLOCK, (void *)raw_pos);
+ if (ret < 0)
+ return ret;
+ if (!ret) {
+ offset -= now;
+ raw_pos += now;
+ } else {
+ raw_pos += bb->info.erasesize;
+ }
+
+ if (!offset) {
+ bb->offset = raw_pos;
+ return __offset;
+ }
+ }
+
+ return -EINVAL;
+}
+
static struct file_operations nand_bb_ops = {
.open = nand_bb_open,
.close = nand_bb_close,
.read = nand_bb_read,
-#ifdef CONFIG_NAND_WRITE
+ .lseek = nand_bb_lseek,
+#ifdef CONFIG_MTD_WRITE
.write = nand_bb_write,
.erase = nand_bb_erase,
#endif
diff --git a/drivers/mtd/nand/nand.c b/drivers/mtd/nand/nand.c
deleted file mode 100644
index 130e2af3be..0000000000
--- a/drivers/mtd/nand/nand.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/*
- * (C) Copyright 2005
- * 2N Telekomunikace, a.s. <www.2n.cz>
- * Ladislav Michl <michl@2n.cz>
- *
- * 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
- * version 2 as published by the Free Software Foundation.
- *
- * 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/mtd/nand.h>
-#include <linux/mtd/mtd.h>
-#include <init.h>
-#include <xfuncs.h>
-#include <driver.h>
-#include <malloc.h>
-#include <ioctl.h>
-#include <nand.h>
-#include <errno.h>
-
-static ssize_t nand_read(struct cdev *cdev, void* buf, size_t count, ulong offset, ulong flags)
-{
- struct mtd_info *info = cdev->priv;
- size_t retlen;
- int ret;
-
- debug("nand_read: 0x%08lx 0x%08x\n", offset, count);
-
- ret = info->read(info, offset, count, &retlen, buf);
-
- if(ret) {
- printf("err %d\n", ret);
- return ret;
- }
- return retlen;
-}
-
-#define NOTALIGNED(x) (x & (info->writesize - 1)) != 0
-
-#ifdef CONFIG_NAND_WRITE
-static int all_ff(const void *buf, int len)
-{
- int i;
- const uint8_t *p = buf;
-
- for (i = 0; i < len; i++)
- if (p[i] != 0xFF)
- return 0;
- return 1;
-}
-
-static ssize_t nand_write(struct cdev* cdev, const void *buf, size_t _count, ulong offset, ulong flags)
-{
- struct mtd_info *info = cdev->priv;
- size_t retlen, now;
- int ret = 0;
- void *wrbuf = NULL;
- size_t count = _count;
-
- if (NOTALIGNED(offset)) {
- printf("offset 0x%0lx not page aligned\n", offset);
- return -EINVAL;
- }
-
- debug("write: 0x%08lx 0x%08x\n", offset, count);
-
- while (count) {
- now = count > info->writesize ? info->writesize : count;
-
- if (NOTALIGNED(now)) {
- debug("not aligned: %d %ld\n", info->writesize, (offset % info->writesize));
- wrbuf = xmalloc(info->writesize);
- memset(wrbuf, 0xff, info->writesize);
- memcpy(wrbuf + (offset % info->writesize), buf, now);
- if (!all_ff(wrbuf, info->writesize))
- ret = info->write(info, offset & ~(info->writesize - 1),
- info->writesize, &retlen, wrbuf);
- free(wrbuf);
- } else {
- if (!all_ff(buf, info->writesize))
- ret = info->write(info, offset, now, &retlen, buf);
- debug("offset: 0x%08lx now: 0x%08x retlen: 0x%08x\n", offset, now, retlen);
- }
- if (ret)
- goto out;
-
- offset += now;
- count -= now;
- buf += now;
- }
-
-out:
- return ret ? ret : _count;
-}
-#endif
-
-static int nand_ioctl(struct cdev *cdev, int request, void *buf)
-{
- struct mtd_info *info = cdev->priv;
- struct mtd_info_user *user = buf;
-
- switch (request) {
- case MEMGETBADBLOCK:
- debug("MEMGETBADBLOCK: 0x%08lx\n", (off_t)buf);
- return info->block_isbad(info, (off_t)buf);
-#ifdef CONFIG_NAND_WRITE
- case MEMSETBADBLOCK:
- debug("MEMSETBADBLOCK: 0x%08lx\n", (off_t)buf);
- return info->block_markbad(info, (off_t)buf);
-#endif
- case MEMGETINFO:
- user->type = info->type;
- user->flags = info->flags;
- user->size = info->size;
- user->erasesize = info->erasesize;
- user->oobsize = info->oobsize;
- user->mtd = info;
- /* The below fields are obsolete */
- user->ecctype = -1;
- user->eccsize = 0;
- return 0;
- }
-
- return 0;
-}
-
-#ifdef CONFIG_NAND_WRITE
-static ssize_t nand_erase(struct cdev *cdev, size_t count, unsigned long offset)
-{
- struct mtd_info *info = cdev->priv;
- struct erase_info erase;
- int ret;
-
- memset(&erase, 0, sizeof(erase));
- erase.mtd = info;
- erase.addr = offset;
- erase.len = info->erasesize;
-
- while (count > 0) {
- debug("erase %d %d\n", erase.addr, erase.len);
-
- ret = info->block_isbad(info, erase.addr);
- if (ret > 0) {
- printf("Skipping bad block at 0x%08x\n", erase.addr);
- } else {
- ret = info->erase(info, &erase);
- if (ret)
- return ret;
- }
-
- erase.addr += info->erasesize;
- count -= count > info->erasesize ? info->erasesize : count;
- }
-
- return 0;
-}
-#endif
-
-#if 0
-static char* mtd_get_size(struct device_d *, struct param_d *param)
-{
- static char
-}
-#endif
-
-static struct file_operations nand_ops = {
- .read = nand_read,
-#ifdef CONFIG_NAND_WRITE
- .write = nand_write,
- .erase = nand_erase,
-#endif
- .ioctl = nand_ioctl,
- .lseek = dev_lseek_default,
-};
-
-#ifdef CONFIG_NAND_OOB_DEVICE
-static ssize_t nand_read_oob(struct cdev *cdev, void *buf, size_t count, ulong offset, ulong flags)
-{
- struct mtd_info *info = cdev->priv;
- struct nand_chip *chip = info->priv;
- struct mtd_oob_ops ops;
- int ret;
-
- if (count < info->oobsize)
- return -EINVAL;
-
- ops.mode = MTD_OOB_RAW;
- ops.ooboffs = 0;
- ops.ooblen = info->oobsize;
- ops.oobbuf = buf;
- ops.datbuf = NULL;
- ops.len = info->oobsize;
-
- offset /= info->oobsize;
- ret = info->read_oob(info, offset << chip->page_shift, &ops);
- if (ret)
- return ret;
-
- return info->oobsize;
-}
-
-static struct file_operations nand_ops_oob = {
- .read = nand_read_oob,
- .ioctl = nand_ioctl,
- .lseek = dev_lseek_default,
-};
-
-static int nand_init_oob_cdev(struct mtd_info *mtd)
-{
- struct nand_chip *chip = mtd->priv;
-
- mtd->cdev_oob.ops = &nand_ops_oob;
- mtd->cdev_oob.size = (mtd->size >> chip->page_shift) * mtd->oobsize;
- mtd->cdev_oob.name = asprintf("nand_oob%d", mtd->class_dev.id);
- mtd->cdev_oob.priv = mtd;
- mtd->cdev_oob.dev = &mtd->class_dev;
- devfs_create(&mtd->cdev_oob);
-
- return 0;
-}
-
-static void nand_exit_oob_cdev(struct mtd_info *mtd)
-{
- free(mtd->cdev_oob.name);
-}
-#else
-
-static int nand_init_oob_cdev(struct mtd_info *mtd)
-{
- return 0;
-}
-
-static void nand_exit_oob_cdev(struct mtd_info *mtd)
-{
- return;
-}
-#endif
-
-int add_mtd_device(struct mtd_info *mtd)
-{
- char str[16];
-
- strcpy(mtd->class_dev.name, "nand");
- register_device(&mtd->class_dev);
-
- mtd->cdev.ops = &nand_ops;
- mtd->cdev.size = mtd->size;
- mtd->cdev.name = asprintf("nand%d", mtd->class_dev.id);
- mtd->cdev.priv = mtd;
- mtd->cdev.dev = &mtd->class_dev;
- mtd->cdev.mtd = mtd;
-
- sprintf(str, "%u", mtd->size);
- dev_add_param_fixed(&mtd->class_dev, "size", str);
- sprintf(str, "%u", mtd->erasesize);
- dev_add_param_fixed(&mtd->class_dev, "erasesize", str);
- sprintf(str, "%u", mtd->writesize);
- dev_add_param_fixed(&mtd->class_dev, "writesize", str);
- sprintf(str, "%u", mtd->oobsize);
- dev_add_param_fixed(&mtd->class_dev, "oobsize", str);
-
- devfs_create(&mtd->cdev);
-
- nand_init_oob_cdev(mtd);
-
- return 0;
-}
-
-int del_mtd_device (struct mtd_info *mtd)
-{
- unregister_device(&mtd->class_dev);
- nand_exit_oob_cdev(mtd);
- free(mtd->param_size.value);
- free(mtd->cdev.name);
- return 0;
-}
-
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ec0f4a3e11..c4eca0d2a3 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1006,7 +1006,7 @@ static void nand_set_defaults(struct nand_chip *chip, int busw)
chip->read_word = nand_read_word;
if (!chip->block_bad)
chip->block_bad = nand_block_bad;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (!chip->block_markbad)
chip->block_markbad = nand_default_block_markbad;
if (!chip->write_buf)
@@ -1168,7 +1168,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)
chip->options &= ~NAND_SAMSUNG_LP_OPTIONS;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
/* Check for AND chips with 4 page planes */
if (chip->options & NAND_4PAGE_ARRAY)
chip->erase_cmd = multi_erase_cmd;
@@ -1297,7 +1297,7 @@ int nand_scan_tail(struct mtd_info *mtd)
}
}
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (!chip->write_page)
chip->write_page = nand_write_page;
#endif
@@ -1308,7 +1308,7 @@ int nand_scan_tail(struct mtd_info *mtd)
*/
if (!chip->ecc.read_page_raw)
chip->ecc.read_page_raw = nand_read_page_raw;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (!chip->ecc.write_page_raw)
chip->ecc.write_page_raw = nand_write_page_raw;
#endif
@@ -1335,7 +1335,7 @@ int nand_scan_tail(struct mtd_info *mtd)
printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
"This is not recommended !!\n");
chip->ecc.read_page = nand_read_page_raw;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
chip->ecc.write_page = nand_write_page_raw;
chip->ecc.write_oob = nand_write_oob_std;
#endif
@@ -1401,7 +1401,7 @@ int nand_scan_tail(struct mtd_info *mtd)
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
mtd->erase = nand_erase;
mtd->write = nand_write;
mtd->write_oob = nand_write_oob;
@@ -1413,7 +1413,7 @@ int nand_scan_tail(struct mtd_info *mtd)
mtd->lock = NULL;
mtd->unlock = NULL;
mtd->block_isbad = nand_block_isbad;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
mtd->block_markbad = nand_block_markbad;
#endif
/* propagate ecc.layout to mtd_info */
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index bf3a7dbc74..c1696eead0 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -557,7 +557,7 @@ static int search_read_bbts(struct mtd_info *mtd, uint8_t * buf, struct nand_bbt
* (Re)write the bad block table
*
*/
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
struct nand_bbt_descr *td, struct nand_bbt_descr *md,
int chipsel)
diff --git a/drivers/mtd/nand/nand_hwecc.c b/drivers/mtd/nand/nand_hwecc.c
index 5ead49c60c..a48efa1074 100644
--- a/drivers/mtd/nand/nand_hwecc.c
+++ b/drivers/mtd/nand/nand_hwecc.c
@@ -61,7 +61,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
*/
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
{
@@ -94,7 +94,7 @@ void nand_init_ecc_hw(struct nand_chip *chip)
if (!chip->ecc.read_oob)
chip->ecc.read_oob = nand_read_oob_std;
#endif
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (!chip->ecc.write_oob)
chip->ecc.write_oob = nand_write_oob_std;
if (!chip->ecc.write_page)
diff --git a/drivers/mtd/nand/nand_hwecc_syndrome.c b/drivers/mtd/nand/nand_hwecc_syndrome.c
index dd067c9970..1493b88439 100644
--- a/drivers/mtd/nand/nand_hwecc_syndrome.c
+++ b/drivers/mtd/nand/nand_hwecc_syndrome.c
@@ -72,7 +72,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
* The hw generator calculates the error syndrome automatically. Therefor
* we need a special oob layout and handling.
*/
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static void nand_write_page_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, const uint8_t *buf)
{
@@ -155,7 +155,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @page: page number to write
*/
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static int nand_write_oob_syndrome(struct mtd_info *mtd,
struct nand_chip *chip, int page)
{
@@ -216,7 +216,7 @@ void nand_init_ecc_hw_syndrome(struct nand_chip *chip)
chip->ecc.read_page = nand_read_page_syndrome;
if (!chip->ecc.read_oob)
chip->ecc.read_oob = nand_read_oob_syndrome;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
if (!chip->ecc.write_page)
chip->ecc.write_page = nand_write_page_syndrome;
if (!chip->ecc.write_oob)
diff --git a/drivers/mtd/nand/nand_imx.c b/drivers/mtd/nand/nand_imx.c
index c8c69d602e..85cfbeda95 100644
--- a/drivers/mtd/nand/nand_imx.c
+++ b/drivers/mtd/nand/nand_imx.c
@@ -1176,7 +1176,7 @@ static int __init imxnd_probe(struct device_d *dev)
goto escan;
}
- add_mtd_device(mtd);
+ add_mtd_device(mtd, "nand");
dev->priv = host;
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index d5e642aefe..9fb11323f7 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -956,7 +956,7 @@ static int gpmc_nand_probe(struct device_d *pdev)
dev_set_param(pdev, "eccmode", ecc_mode_strings[pdata->ecc_mode]);
/* We are all set to register with the system now! */
- err = add_mtd_device(minfo);
+ err = add_mtd_device(minfo, "nand");
if (err) {
dev_dbg(pdev, "device registration failed\n");
goto out_release_mem;
diff --git a/drivers/mtd/nand/nand_s3c2410.c b/drivers/mtd/nand/nand_s3c24xx.c
index c5f5d97db3..e55aef0335 100644
--- a/drivers/mtd/nand/nand_s3c2410.c
+++ b/drivers/mtd/nand/nand_s3c24xx.c
@@ -30,9 +30,9 @@
#include <init.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
-#include <mach/s3c24xx-generic.h>
-#include <mach/s3c24x0-iomap.h>
-#include <mach/s3c24x0-nand.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-iomap.h>
+#include <mach/s3c24xx-nand.h>
#include <io.h>
#include <asm-generic/errno.h>
@@ -485,8 +485,8 @@ static int s3c24x0_nand_probe(struct device_d *dev)
goto on_error;
}
- return add_mtd_device(mtd);
-
+ return add_mtd_device(mtd, "nand");
+
on_error:
free(host);
return ret;
diff --git a/drivers/mtd/nand/nand_swecc.c b/drivers/mtd/nand/nand_swecc.c
index a5edffaece..95dfbd8083 100644
--- a/drivers/mtd/nand/nand_swecc.c
+++ b/drivers/mtd/nand/nand_swecc.c
@@ -57,7 +57,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
* @chip: nand chip info structure
* @buf: data buffer
*/
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
const uint8_t *buf)
{
@@ -85,7 +85,7 @@ void nand_init_ecc_soft(struct nand_chip *chip)
chip->ecc.correct = nand_correct_data;
chip->ecc.read_page = nand_read_page_swecc;
chip->ecc.read_oob = nand_read_oob_std;
-#ifdef CONFIG_NAND_WRITE
+#ifdef CONFIG_MTD_WRITE
chip->ecc.write_page = nand_write_page_swecc;
chip->ecc.write_oob = nand_write_oob_std;
#endif
diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index c1e93ad076..05d61c2bf4 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -220,7 +220,7 @@ static int nomadik_nand_probe(struct device_d *dev)
}
pr_info("Registering %s as whole device\n", mtd->name);
- add_mtd_device(mtd);
+ add_mtd_device(mtd, "nand");
return 0;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 96ae16e0c2..95bef1f9e0 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -81,7 +81,7 @@ static ssize_t ubi_volume_cdev_write(struct cdev* cdev, const void *buf,
return err;
}
-static int ubi_volume_cdev_open(struct cdev *cdev)
+static int ubi_volume_cdev_open(struct cdev *cdev, unsigned long flags)
{
struct ubi_volume_cdev_priv *priv = cdev->priv;
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index 19e35dbbab..b236d17e2e 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -46,8 +46,8 @@ config DRIVER_NET_SMC91111
This option enables support for the SMSC LAN91C111
ethernet chip.
-config DRIVER_NET_DM9000
- bool "Davicom dm9000 ethernet driver"
+config DRIVER_NET_DM9K
+ bool "Davicom dm9k[E|A|B] ethernet driver"
depends on HAS_DM9000
select MIIDEV
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index f02618bd23..a84d3dc8d5 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -1,7 +1,7 @@
obj-$(CONFIG_DRIVER_NET_CS8900) += cs8900.o
obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
-obj-$(CONFIG_DRIVER_NET_DM9000) += dm9000.o
+obj-$(CONFIG_DRIVER_NET_DM9K) += dm9k.o
obj-$(CONFIG_DRIVER_NET_NETX) += netx_eth.o
obj-$(CONFIG_DRIVER_NET_AT91_ETHER) += at91_ether.o
obj-$(CONFIG_DRIVER_NET_MPC5200) += fec_mpc5200.o
diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c
deleted file mode 100644
index f32778135d..0000000000
--- a/drivers/net/dm9000.c
+++ /dev/null
@@ -1,564 +0,0 @@
-/*
- * dm9000.c
- *
- * A Davicom DM9000 ISA NIC fast Ethernet driver for Linux.
- * Copyright (C) 1997 Sten Wang
- *
- * 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.
- *
- * (C)Copyright 1997-1998 DAVICOM Semiconductor,Inc. All Rights Reserved.
- *
- * V0.11 06/20/2001 REG_0A bit3=1, default enable BP with DA match
- * 06/22/2001 Support DM9801 progrmming
- * E3: R25 = ((R24 + NF) & 0x00ff) | 0xf000
- * E4: R25 = ((R24 + NF) & 0x00ff) | 0xc200
- * R17 = (R17 & 0xfff0) | NF + 3
- * E5: R25 = ((R24 + NF - 3) & 0x00ff) | 0xc200
- * R17 = (R17 & 0xfff0) | NF
- *
- * v1.00 modify by simon 2001.9.5
- * change for kernel 2.4.x
- *
- * v1.1 11/09/2001 fix force mode bug
- *
- * v1.2 03/18/2003 Weilun Huang <weilun_huang@davicom.com.tw>:
- * Fixed phy reset.
- * Added tx/rx 32 bit mode.
- * Cleaned up for kernel merge.
- *
- *
- *
- * 12/15/2003 Initial port to barebox by Sascha Hauer
- * <saschahauer@web.de>
- *
- * ... see commit logs
- */
-
-#include <common.h>
-#include <command.h>
-#include <driver.h>
-#include <clock.h>
-#include <miidev.h>
-#include <malloc.h>
-#include <net.h>
-#include <init.h>
-#include <io.h>
-#include <xfuncs.h>
-#include <dm9000.h>
-#include <errno.h>
-
-#define DM9000_ID 0x90000A46
-#define DM9000_PKT_MAX 1536 /* Received packet max size */
-#define DM9000_PKT_RDY 0x01 /* Packet ready to receive */
-
-#define DM9000_NCR 0x00
-#define DM9000_NSR 0x01
-#define DM9000_TCR 0x02
-#define DM9000_TSR1 0x03
-#define DM9000_TSR2 0x04
-#define DM9000_RCR 0x05
-#define DM9000_RSR 0x06
-#define DM9000_ROCR 0x07
-#define DM9000_BPTR 0x08
-#define DM9000_FCTR 0x09
-#define DM9000_FCR 0x0A
-#define DM9000_EPCR 0x0B
-#define DM9000_EPAR 0x0C
-#define DM9000_EPDRL 0x0D
-#define DM9000_EPDRH 0x0E
-#define DM9000_WCR 0x0F
-
-#define DM9000_PAR 0x10
-#define DM9000_MAR 0x16
-
-#define DM9000_GPCR 0x1e
-#define DM9000_GPR 0x1f
-#define DM9000_TRPAL 0x22
-#define DM9000_TRPAH 0x23
-#define DM9000_RWPAL 0x24
-#define DM9000_RWPAH 0x25
-
-#define DM9000_VIDL 0x28
-#define DM9000_VIDH 0x29
-#define DM9000_PIDL 0x2A
-#define DM9000_PIDH 0x2B
-
-#define DM9000_CHIPR 0x2C
-#define DM9000_SMCR 0x2F
-
-#define DM9000_PHY 0x40 /* PHY address 0x01 */
-
-#define DM9000_MRCMDX 0xF0
-#define DM9000_MRCMD 0xF2
-#define DM9000_MRRL 0xF4
-#define DM9000_MRRH 0xF5
-#define DM9000_MWCMDX 0xF6
-#define DM9000_MWCMD 0xF8
-#define DM9000_MWRL 0xFA
-#define DM9000_MWRH 0xFB
-#define DM9000_TXPLL 0xFC
-#define DM9000_TXPLH 0xFD
-#define DM9000_ISR 0xFE
-#define DM9000_IMR 0xFF
-
-#define NCR_EXT_PHY (1<<7)
-#define NCR_WAKEEN (1<<6)
-#define NCR_FCOL (1<<4)
-#define NCR_FDX (1<<3)
-#define NCR_LBK (3<<1)
-#define NCR_RST (1<<0)
-
-#define NSR_SPEED (1<<7)
-#define NSR_LINKST (1<<6)
-#define NSR_WAKEST (1<<5)
-#define NSR_TX2END (1<<3)
-#define NSR_TX1END (1<<2)
-#define NSR_RXOV (1<<1)
-
-#define TCR_TJDIS (1<<6)
-#define TCR_EXCECM (1<<5)
-#define TCR_PAD_DIS2 (1<<4)
-#define TCR_CRC_DIS2 (1<<3)
-#define TCR_PAD_DIS1 (1<<2)
-#define TCR_CRC_DIS1 (1<<1)
-#define TCR_TXREQ (1<<0)
-
-#define TSR_TJTO (1<<7)
-#define TSR_LC (1<<6)
-#define TSR_NC (1<<5)
-#define TSR_LCOL (1<<4)
-#define TSR_COL (1<<3)
-#define TSR_EC (1<<2)
-
-#define RCR_WTDIS (1<<6)
-#define RCR_DIS_LONG (1<<5)
-#define RCR_DIS_CRC (1<<4)
-#define RCR_ALL (1<<3)
-#define RCR_RUNT (1<<2)
-#define RCR_PRMSC (1<<1)
-#define RCR_RXEN (1<<0)
-
-#define RSR_RF (1<<7)
-#define RSR_MF (1<<6)
-#define RSR_LCS (1<<5)
-#define RSR_RWTO (1<<4)
-#define RSR_PLE (1<<3)
-#define RSR_AE (1<<2)
-#define RSR_CE (1<<1)
-#define RSR_FOE (1<<0)
-
-#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 )
-#define FCTR_LWOT(ot) ( ot & 0xf )
-
-#define IMR_PAR (1<<7)
-#define IMR_ROOM (1<<3)
-#define IMR_ROM (1<<2)
-#define IMR_PTM (1<<1)
-#define IMR_PRM (1<<0)
-
-struct dm9000_priv {
- void __iomem *iobase;
- void __iomem *iodata;
- struct mii_device miidev;
- int buswidth;
- int srom;
-};
-
-#ifdef CONFIG_DM9000_DEBUG
-static void
-dump_regs(void)
-{
- debug("\n");
- debug("NCR (0x00): %02x\n", DM9000_ior(0));
- debug("NSR (0x01): %02x\n", DM9000_ior(1));
- debug("TCR (0x02): %02x\n", DM9000_ior(2));
- debug("TSRI (0x03): %02x\n", DM9000_ior(3));
- debug("TSRII (0x04): %02x\n", DM9000_ior(4));
- debug("RCR (0x05): %02x\n", DM9000_ior(5));
- debug("RSR (0x06): %02x\n", DM9000_ior(6));
- debug("ISR (0xFE): %02x\n", DM9000_ior(ISR));
- debug("\n");
-}
-#endif
-
-static u8 DM9000_ior(struct dm9000_priv *priv, int reg)
-{
- writeb(reg, priv->iobase);
- return readb(priv->iodata);
-}
-
-static void DM9000_iow(struct dm9000_priv *priv, int reg, u8 value)
-{
- writeb(reg, priv->iobase);
- writeb(value, priv->iodata);
-}
-
-static int dm9000_phy_read(struct mii_device *mdev, int addr, int reg)
-{
- int val;
- struct eth_device *edev = mdev->edev;
- struct dm9000_priv *priv = edev->priv;
-
- /* Fill the phyxcer register into REG_0C */
- DM9000_iow(priv, DM9000_EPAR, DM9000_PHY | reg);
- DM9000_iow(priv, DM9000_EPCR, 0xc); /* Issue phyxcer read command */
- udelay(100); /* Wait read complete */
- DM9000_iow(priv, DM9000_EPCR, 0x0); /* Clear phyxcer read command */
- val = (DM9000_ior(priv, DM9000_EPDRH) << 8) | DM9000_ior(priv, DM9000_EPDRL);
-
- /* The read data keeps on REG_0D & REG_0E */
- debug("phy_read(%d): %d\n", reg, val);
- return val;
-}
-
-static int dm9000_phy_write(struct mii_device *mdev, int addr, int reg, int val)
-{
- struct eth_device *edev = mdev->edev;
- struct dm9000_priv *priv = edev->priv;
-
- /* Fill the phyxcer register into REG_0C */
- DM9000_iow(priv, DM9000_EPAR, DM9000_PHY | reg);
-
- /* Fill the written data into REG_0D & REG_0E */
- DM9000_iow(priv, DM9000_EPDRL, (val & 0xff));
- DM9000_iow(priv, DM9000_EPDRH, ((val >> 8) & 0xff));
- DM9000_iow(priv, DM9000_EPCR, 0xa); /* Issue phyxcer write command */
- udelay(500); /* Wait write complete */
- DM9000_iow(priv, DM9000_EPCR, 0x0); /* Clear phyxcer write command */
-
- debug("phy_write(reg:%d, value:%d)\n", reg, value);
-
- return 0;
-}
-
-static int dm9000_check_id(struct dm9000_priv *priv)
-{
- u32 id_val;
- id_val = DM9000_ior(priv, DM9000_VIDL);
- id_val |= DM9000_ior(priv, DM9000_VIDH) << 8;
- id_val |= DM9000_ior(priv, DM9000_PIDL) << 16;
- id_val |= DM9000_ior(priv, DM9000_PIDH) << 24;
- if (id_val == DM9000_ID) {
- printf("dm9000 i/o: 0x%p, id: 0x%x \n", priv->iobase,
- id_val);
- return 0;
- } else {
- printf("dm9000 not found at 0x%p id: 0x%08x\n",
- priv->iobase, id_val);
- return -1;
- }
-}
-
-static void dm9000_reset(struct dm9000_priv *priv)
-{
- debug("resetting\n");
- DM9000_iow(priv, DM9000_NCR, NCR_RST);
- udelay(1000); /* delay 1ms */
-}
-
-static int dm9000_eth_open(struct eth_device *edev)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
-
- miidev_wait_aneg(&priv->miidev);
- miidev_print_status(&priv->miidev);
- return 0;
-}
-
-static int dm9000_eth_send (struct eth_device *edev,
- void *packet, int length)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
- char *data_ptr;
- u32 tmplen, i;
- uint64_t tmo;
-
- debug("eth_send: length: %d\n", length);
-
- for (i = 0; i < length; i++) {
- if (i % 8 == 0)
- debug("\nSend: 02x: ", i);
- debug("%02x ", ((unsigned char *) packet)[i]);
- } debug("\n");
-
- /* Move data to DM9000 TX RAM */
- data_ptr = (char *) packet;
- writeb(DM9000_MWCMD, priv->iobase);
-
- switch (priv->buswidth) {
- case IORESOURCE_MEM_8BIT:
- for (i = 0; i < length; i++)
- writeb(data_ptr[i] & 0xff, priv->iodata);
- break;
- case IORESOURCE_MEM_16BIT:
- tmplen = (length + 1) / 2;
- for (i = 0; i < tmplen; i++)
- writew(((u16 *)data_ptr)[i], priv->iodata);
- break;
- case IORESOURCE_MEM_32BIT:
- tmplen = (length + 3) / 4;
- for (i = 0; i < tmplen; i++)
- writel(((u32 *) data_ptr)[i], priv->iodata);
- break;
- default:
- /* dm9000_probe makes sure this cannot happen */
- return -EINVAL;
- }
-
- /* Set TX length to DM9000 */
- DM9000_iow(priv, DM9000_TXPLL, length & 0xff);
- DM9000_iow(priv, DM9000_TXPLH, (length >> 8) & 0xff);
-
- /* Issue TX polling command */
- DM9000_iow(priv, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */
-
- /* wait for end of transmission */
- tmo = get_time_ns();
- while (DM9000_ior(priv, DM9000_TCR) & TCR_TXREQ) {
- if (is_timeout(tmo, 5 * SECOND)) {
- printf("transmission timeout\n");
- break;
- }
- }
- debug("transmit done\n\n");
- return 0;
-}
-
-static void dm9000_eth_halt (struct eth_device *edev)
-{
- debug("eth_halt\n");
-#if 0
- phy_write(0, 0x8000); /* PHY RESET */
- DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
- DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
- DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
-#endif
-}
-
-static int dm9000_eth_rx (struct eth_device *edev)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
- u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];
- u16 RxStatus, RxLen = 0;
- u32 tmplen, i;
- u32 tmpdata;
-
- /* Check packet ready or not */
- DM9000_ior(priv, DM9000_MRCMDX); /* Dummy read */
- rxbyte = readb(priv->iodata); /* Got most updated data */
- if (rxbyte == 0)
- return 0;
-
- /* Status check: this byte must be 0 or 1 */
- if (rxbyte > 1) {
- DM9000_iow(priv, DM9000_RCR, 0x00); /* Stop Device */
- DM9000_iow(priv, DM9000_ISR, 0x80); /* Stop INT request */
- debug("rx status check: %d\n", rxbyte);
- }
- debug("receiving packet\n");
-
- /* A packet ready now & Get status/length */
- writeb(DM9000_MRCMD, priv->iobase);
-
- /* Move data from DM9000 */
- /* Read received packet from RX SRAM */
- switch (priv->buswidth) {
- case IORESOURCE_MEM_8BIT:
- RxStatus = readb(priv->iodata) + (readb(priv->iodata) << 8);
- RxLen = readb(priv->iodata) + (readb(priv->iodata) << 8);
- for (i = 0; i < RxLen; i++)
- rdptr[i] = readb(priv->iodata);
- break;
- case IORESOURCE_MEM_16BIT:
- RxStatus = readw(priv->iodata);
- RxLen = readw(priv->iodata);
- tmplen = (RxLen + 1) / 2;
- for (i = 0; i < tmplen; i++)
- ((u16 *) rdptr)[i] = readw(priv->iodata);
- break;
- case IORESOURCE_MEM_32BIT:
- tmpdata = readl(priv->iodata);
- RxStatus = tmpdata;
- RxLen = tmpdata >> 16;
- tmplen = (RxLen + 3) / 4;
- for (i = 0; i < tmplen; i++)
- ((u32 *) rdptr)[i] = readl(priv->iodata);
- break;
- default:
- /* dm9000_probe makes sure this cannot happen */
- return -EINVAL;
- }
-
- if ((RxStatus & 0xbf00) || (RxLen < 0x40)
- || (RxLen > DM9000_PKT_MAX)) {
- if (RxStatus & 0x100) {
- printf("rx fifo error\n");
- }
- if (RxStatus & 0x200) {
- printf("rx crc error\n");
- }
- if (RxStatus & 0x8000) {
- printf("rx length error\n");
- }
- if (RxLen > DM9000_PKT_MAX) {
- printf("rx length too big\n");
- dm9000_reset(priv);
- }
- } else {
-
- /* Pass to upper layer */
- debug("passing packet to upper layer\n");
- net_receive(NetRxPackets[0], RxLen);
- return RxLen;
- }
- return 0;
-}
-
-static u16 read_srom_word(struct dm9000_priv *priv, int offset)
-{
- DM9000_iow(priv, DM9000_EPAR, offset);
- DM9000_iow(priv, DM9000_EPCR, 0x4);
- udelay(200);
- DM9000_iow(priv, DM9000_EPCR, 0x0);
- return (DM9000_ior(priv, DM9000_EPDRL) + (DM9000_ior(priv, DM9000_EPDRH) << 8));
-}
-
-static int dm9000_get_ethaddr(struct eth_device *edev, unsigned char *adr)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
- int i, oft;
-
- if (priv->srom) {
- for (i = 0; i < 3; i++)
- ((u16 *) adr)[i] = read_srom_word(priv, i);
- } else {
- for (i = 0, oft = 0x10; i < 6; i++, oft++)
- adr[i] = DM9000_ior(priv, oft);
- }
-
- return 0;
-}
-
-static int dm9000_set_ethaddr(struct eth_device *edev, unsigned char *adr)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
- int i, oft;
-
- debug("%s\n", __FUNCTION__);
-
- for (i = 0, oft = 0x10; i < 6; i++, oft++)
- DM9000_iow(priv, oft, adr[i]);
- for (i = 0, oft = 0x16; i < 8; i++, oft++)
- DM9000_iow(priv, oft, 0xff);
-
-#if 0
- for (i = 0; i < 5; i++)
- printf ("%02x:", adr[i]);
- printf ("%02x\n", adr[5]);
-#endif
- return 0;
-}
-
-static int dm9000_init_dev(struct eth_device *edev)
-{
- struct dm9000_priv *priv = (struct dm9000_priv *)edev->priv;
-
- miidev_restart_aneg(&priv->miidev);
- return 0;
-}
-
-static int dm9000_probe(struct device_d *dev)
-{
- struct eth_device *edev;
- struct dm9000_priv *priv;
- struct dm9000_platform_data *pdata;
-
- debug("dm9000_eth_init()\n");
-
- edev = xzalloc(sizeof(struct eth_device) + sizeof(struct dm9000_priv));
- dev->type_data = edev;
- edev->priv = (struct dm9000_priv *)(edev + 1);
-
- if (!dev->platform_data) {
- printf("dm9000: no platform_data\n");
- return -ENODEV;
- }
-
- if (dev->num_resources < 2) {
- printf("dm9000: need 2 resources base and data");
- return -ENODEV;
- }
-
- pdata = dev->platform_data;
-
- priv = edev->priv;
-
- priv->buswidth = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
- priv->iodata = dev_request_mem_region(dev, 1);
- priv->iobase = dev_request_mem_region(dev, 0);
- priv->srom = pdata->srom;
-
- edev->init = dm9000_init_dev;
- edev->open = dm9000_eth_open;
- edev->send = dm9000_eth_send;
- edev->recv = dm9000_eth_rx;
- edev->halt = dm9000_eth_halt;
- edev->set_ethaddr = dm9000_set_ethaddr;
- edev->get_ethaddr = dm9000_get_ethaddr;
- edev->parent = dev;
-
- /* RESET device */
- dm9000_reset(priv);
- if(dm9000_check_id(priv))
- return -1;
-
- /* Program operating register */
- DM9000_iow(priv, DM9000_NCR, 0x0); /* only intern phy supported by now */
- DM9000_iow(priv, DM9000_TCR, 0); /* TX Polling clear */
- DM9000_iow(priv, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */
- DM9000_iow(priv, DM9000_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8)); /* Flow Control : High/Low Water */
- DM9000_iow(priv, DM9000_FCR, 0x0); /* SH FIXME: This looks strange! Flow Control */
- DM9000_iow(priv, DM9000_SMCR, 0); /* Special Mode */
- DM9000_iow(priv, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); /* clear TX status */
- DM9000_iow(priv, DM9000_ISR, 0x0f); /* Clear interrupt status */
-
- /* Activate DM9000 */
- DM9000_iow(priv, DM9000_GPCR, 0x01); /* Let GPIO0 output */
- DM9000_iow(priv, DM9000_GPR, 0x00); /* Enable PHY */
- DM9000_iow(priv, DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN); /* RX enable */
- DM9000_iow(priv, DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask */
-
- priv->miidev.read = dm9000_phy_read;
- priv->miidev.write = dm9000_phy_write;
- priv->miidev.address = 0;
- priv->miidev.flags = 0;
- priv->miidev.edev = edev;
- priv->miidev.parent = dev;
-
- mii_register(&priv->miidev);
- eth_register(edev);
-
- return 0;
-}
-
-static struct driver_d dm9000_driver = {
- .name = "dm9000",
- .probe = dm9000_probe,
-};
-
-static int dm9000_init(void)
-{
- register_driver(&dm9000_driver);
- return 0;
-}
-
-device_initcall(dm9000_init);
-
diff --git a/drivers/net/dm9k.c b/drivers/net/dm9k.c
new file mode 100644
index 0000000000..983edd4d74
--- /dev/null
+++ b/drivers/net/dm9k.c
@@ -0,0 +1,799 @@
+/*
+ * Copyright (C) 2011 Juergen Beisert, Pengutronix
+ *
+ * Davicom DM9000(E/A/B) NIC fast Ethernet driver for Barebox
+ *
+ * In some ways inspired by code
+ *
+ * Copyright (C) 1997 Sten Wang
+ * 1997-1998 DAVICOM Semiconductor,Inc.
+ * 2003 Weilun Huang <weilun_huang@davicom.com.tw>
+ * 2003 <saschahauer@web.de>
+ *
+ * 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.
+ */
+
+#undef DEBUG
+
+#include <init.h>
+#include <common.h>
+#include <driver.h>
+#include <miidev.h>
+#include <net.h>
+#include <io.h>
+#include <xfuncs.h>
+#include <dm9000.h>
+#include <errno.h>
+
+#define DM9K_ID 0x90000A46
+#define CHIPR_DM9000A 0x19
+#define CHIPR_DM9000B 0x1A
+
+#define DM9K_PKT_NONE 0x00 /* no packet received (end marker) */
+#define DM9K_PKT_RDY 0x01 /* packet ready to read */
+#define DM9K_PKT_ERR 0x02 /* chip error */
+#define DM9K_PKT_MAX 1536 /* packet max size */
+
+#define DM9K_NCR 0x00
+# define NCR_EXT_PHY (1 << 7)
+# define NCR_WAKEEN (1 << 6)
+# define NCR_FCOL (1 << 4)
+# define NCR_FDX (1 << 3)
+# define NCR_LBK (3 << 1)
+# define NCR_RST (1 << 0)
+
+#define DM9K_NSR 0x01
+# define NSR_SPEED (1 << 7)
+# define NSR_LINKST (1 << 6)
+# define NSR_WAKEST (1 << 5)
+# define NSR_TX2END (1 << 3)
+# define NSR_TX1END (1 << 2)
+# define NSR_RXOV (1 << 1)
+
+#define DM9K_TCR 0x02
+# define TCR_TJDIS (1 << 6)
+# define TCR_EXCECM (1 << 5)
+# define TCR_PAD_DIS2 (1 << 4)
+# define TCR_CRC_DIS2 (1 << 3)
+# define TCR_PAD_DIS1 (1 << 2)
+# define TCR_CRC_DIS1 (1 << 1)
+# define TCR_TXREQ (1 << 0)
+
+#define DM9K_TSR1 0x03
+#define DM9K_TSR2 0x04
+# define TSR_TJTO (1 << 7)
+# define TSR_LC (1 << 6)
+# define TSR_NC (1 << 5)
+# define TSR_LCOL (1 << 4)
+# define TSR_COL (1 << 3)
+# define TSR_EC (1 << 2)
+
+#define DM9K_RCR 0x05
+# define RCR_WTDIS (1 << 6)
+# define RCR_DIS_LONG (1 << 5)
+# define RCR_DIS_CRC (1 << 4)
+# define RCR_ALL (1 << 3)
+# define RCR_RUNT (1 << 2)
+# define RCR_PRMSC (1 << 1)
+# define RCR_RXEN (1 << 0)
+
+#define DM9K_RSR 0x06
+# define RSR_RF (1 << 7)
+# define RSR_MF (1 << 6)
+# define RSR_LCS (1 << 5)
+# define RSR_RWTO (1 << 4)
+# define RSR_PLE (1 << 3)
+# define RSR_AE (1 << 2)
+# define RSR_CE (1 << 1)
+# define RSR_FOE (1 << 0)
+# define RSR_ERR_MASK (RSR_FOE | RSR_CE | RSR_AE | RSR_PLE | RSR_RWTO | RSR_LCS | RSR_RF)
+
+#define DM9K_ROCR 0x07
+#define DM9K_BPTR 0x08
+#define DM9K_FCTR 0x09
+#define DM9K_FCR 0x0A
+#define DM9K_EPCR 0x0B
+#define DM9K_EPAR 0x0C
+#define DM9K_EPDRL 0x0D
+#define DM9K_EPDRH 0x0E
+#define DM9K_WCR 0x0F
+
+#define DM9K_PAR 0x10
+#define DM9K_MAR 0x16
+
+#define DM9K_GPCR 0x1e
+#define DM9K_GPR 0x1f
+#define DM9K_TRPAL 0x22
+#define DM9K_TRPAH 0x23
+#define DM9K_RWPAL 0x24
+#define DM9K_RWPAH 0x25
+
+#define DM9K_VIDL 0x28
+#define DM9K_VIDH 0x29
+#define DM9K_PIDL 0x2A
+#define DM9K_PIDH 0x2B
+
+#define DM9K_CHIPR 0x2C
+#define DM9K_SMCR 0x2F
+
+#define DM9K_PHY 0x40 /* PHY address 0x01 */
+
+#define DM9K_MRCMDX 0xF0
+#define DM9K_MRCMD 0xF2
+#define DM9K_MRRL 0xF4
+#define DM9K_MRRH 0xF5
+#define DM9K_MWCMDX 0xF6
+#define DM9K_MWCMD 0xF8
+#define DM9K_MWRL 0xFA
+#define DM9K_MWRH 0xFB
+#define DM9K_TXPLL 0xFC
+#define DM9K_TXPLH 0xFD
+
+#define DM9K_ISR 0xFE
+# define ISR_IOM0 (1 << 7) /* 0: 16 bit, 1: 8 bit*/
+# define ISR_LNKCHG (1 << 5) /* link status change */
+# define ISR_UDRUN (1 << 4) /* transmit underrun */
+# define ISR_ROO (1 << 3) /* receive overflow counter overflow */
+# define ISR_ROS (1 << 2) /* receive overflow */
+# define ISR_PT (1 << 1) /* packet transmitted */
+# define ISR_PR (1 << 0) /* packet received */
+# define ISR_CLEAR_MASK (ISR_PR | ISR_PT | ISR_ROS | ISR_ROO | ISR_UDRUN | ISR_LNKCHG)
+
+#define DM9K_IMR 0xFF
+# define IMR_PAR (1 << 7)
+# define IMR_ROOM (1 << 3)
+# define IMR_ROM (1 << 2)
+# define IMR_PTM (1 << 1)
+# define IMR_PRM (1 << 0)
+
+#define FCTR_HWOT(ot) (( ot & 0xf ) << 4 )
+#define FCTR_LWOT(ot) ( ot & 0xf )
+
+struct dm9k {
+ void __iomem *iobase;
+ void __iomem *iodata;
+ struct mii_device miidev;
+ int buswidth;
+ int srom;
+ uint8_t pckt[2048];
+};
+
+/* ------------------ register access functions -------------------------- */
+
+static uint8_t dm9k_ior(struct dm9k *priv, int reg)
+{
+ writeb(reg, priv->iobase);
+ return readb(priv->iodata);
+}
+
+static void dm9k_iow(struct dm9k *priv, int reg, uint8_t value)
+{
+ writeb(reg, priv->iobase);
+ writeb(value, priv->iodata);
+}
+
+/* ------------------- data move functions ---------------------------- */
+
+static void dm9k_wd_8(void __iomem *port, const void *src, int length)
+{
+ const uint8_t *from = (const uint8_t *)src;
+
+ while (length--)
+ writeb(*from++, port);
+}
+
+static void dm9k_rd_8(void __iomem *port, void *dst, unsigned length)
+{
+ uint8_t *to = (uint8_t *)dst;
+
+ while (length--)
+ *to++ = readb(port);
+}
+
+static void dm9k_dump_8(void __iomem *port, unsigned length)
+{
+ while (length--)
+ readb(port);
+}
+
+static unsigned dm9k_read_packet_status_8(void __iomem *port, unsigned *status)
+{
+ uint16_t st, le;
+
+ dm9k_rd_8(port, &st, sizeof(st));
+ dm9k_rd_8(port, &le, sizeof(le));
+
+ *status = st >> 8;
+ return le;
+}
+
+static void dm9k_wd_16(void __iomem *port, const void *src, int length)
+{
+ const uint16_t *from = (const uint16_t *)src;
+
+ length += 1;
+ length /= 2;
+ while (length--)
+ writew(*from++, port);
+}
+
+static void dm9k_rd_16(void __iomem *port, void *dst, unsigned length)
+{
+ uint16_t *to = (uint16_t *)dst;
+
+ length += 1;
+ length >>= 1;
+ while (length--)
+ *to++ = readw(port);
+}
+
+static void dm9k_dump_16(void __iomem *port, unsigned length)
+{
+ length += 1;
+ length >>= 1;
+ while (length--)
+ readw(port);
+}
+
+static unsigned dm9k_read_packet_status_16(void __iomem *port, unsigned *status)
+{
+ *status = readw(port) >> 8;
+ return le16_to_cpu(readw(port));
+}
+
+static void dm9k_wd_32(void __iomem *port, const void *src, int length)
+{
+ const uint32_t *from = (const uint32_t *)src;
+
+ length += 3;
+ length /= 4;
+ while (length--)
+ writel(*from++, port);
+}
+
+static void dm9k_rd_32(void __iomem *port, void *dst, unsigned length)
+{
+ uint32_t *to = (uint32_t *)dst;
+
+ length += 3;
+ length >>= 2;
+ while (length--)
+ *to++ = readl(port);
+}
+
+static void dm9k_dump_32(void __iomem *port, unsigned length)
+{
+ length += 3;
+ length >>= 2;
+ while (length--)
+ readl(port);
+}
+
+static unsigned dm9k_read_packet_status_32(void __iomem *port, unsigned *status)
+{
+ uint32_t tmp = readl(port);
+
+ *status = (tmp >> 8) & 0xff;
+ return tmp >> 16;
+}
+
+static unsigned dm9k_read_packet_status(int b_width, void __iomem *port, unsigned *status)
+{
+ unsigned rc;
+
+ switch (b_width) {
+ case IORESOURCE_MEM_8BIT:
+ rc = dm9k_read_packet_status_8(port, status);
+ break;
+ case IORESOURCE_MEM_16BIT:
+ rc = dm9k_read_packet_status_16(port, status);
+ break;
+ case IORESOURCE_MEM_32BIT:
+ rc = dm9k_read_packet_status_32(port, status);
+ break;
+ default:
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+static void dm9k_dump(int b_width, void __iomem *port, unsigned length)
+{
+ switch (b_width) {
+ case IORESOURCE_MEM_8BIT:
+ dm9k_dump_8(port, length);
+ break;
+ case IORESOURCE_MEM_16BIT:
+ dm9k_dump_16(port, length);
+ break;
+ case IORESOURCE_MEM_32BIT:
+ dm9k_dump_32(port, length);
+ break;
+ }
+}
+
+static void dm9k_rd(int b_width, void __iomem *port, void *dst, unsigned length)
+{
+ switch (b_width) {
+ case IORESOURCE_MEM_8BIT:
+ dm9k_rd_8(port, dst, length);
+ break;
+ case IORESOURCE_MEM_16BIT:
+ dm9k_rd_16(port, dst, length);
+ break;
+ case IORESOURCE_MEM_32BIT:
+ dm9k_rd_32(port, dst, length);
+ break;
+ }
+}
+
+static void dm9k_wd(int b_width, void __iomem *port, const void *src, int length)
+{
+ switch (b_width) {
+ case IORESOURCE_MEM_8BIT:
+ dm9k_wd_8(port, src, length);
+ break;
+ case IORESOURCE_MEM_16BIT:
+ dm9k_wd_16(port, src, length);
+ break;
+ case IORESOURCE_MEM_32BIT:
+ dm9k_wd_32(port, src, length);
+ break;
+ }
+}
+
+/* ----------------- end of data move functions -------------------------- */
+
+static int dm9k_phy_read(struct mii_device *mdev, int addr, int reg)
+{
+ unsigned val;
+ struct eth_device *edev = mdev->edev;
+ struct device_d *dev = edev->parent;
+ struct dm9k *priv = edev->priv;
+
+ /* Fill the phyxcer register into REG_0C */
+ dm9k_iow(priv, DM9K_EPAR, DM9K_PHY | reg);
+ dm9k_iow(priv, DM9K_EPCR, 0xc); /* Issue phyxcer read command */
+ udelay(100); /* Wait read complete */
+ dm9k_iow(priv, DM9K_EPCR, 0x0); /* Clear phyxcer read command */
+ val = dm9k_ior(priv, DM9K_EPDRH);
+ val <<= 8;
+ val |= dm9k_ior(priv, DM9K_EPDRL);
+
+ /* The read data keeps on REG_0D & REG_0E */
+ dev_dbg(dev, "phy_read(%d): %d\n", reg, val);
+ return val;
+}
+
+static int dm9k_phy_write(struct mii_device *mdev, int addr, int reg, int val)
+{
+ struct eth_device *edev = mdev->edev;
+ struct device_d *dev = edev->parent;
+ struct dm9k *priv = edev->priv;
+
+ /* Fill the phyxcer register into REG_0C */
+ dm9k_iow(priv, DM9K_EPAR, DM9K_PHY | reg);
+
+ /* Fill the written data into REG_0D & REG_0E */
+ dm9k_iow(priv, DM9K_EPDRL, val);
+ dm9k_iow(priv, DM9K_EPDRH, val >> 8);
+ dm9k_iow(priv, DM9K_EPCR, 0xa); /* Issue phyxcer write command */
+ udelay(500); /* Wait write complete */
+ dm9k_iow(priv, DM9K_EPCR, 0x0); /* Clear phyxcer write command */
+
+ dev_dbg(dev, "phy_write(reg:%d, value:%d)\n", reg, val);
+
+ return 0;
+}
+
+static int dm9k_check_id(struct dm9k *priv)
+{
+ struct device_d *dev = priv->miidev.parent;
+ u32 id;
+ char c;
+
+ id = dm9k_ior(priv, DM9K_VIDL);
+ id |= dm9k_ior(priv, DM9K_VIDH) << 8;
+ id |= dm9k_ior(priv, DM9K_PIDL) << 16;
+ id |= dm9k_ior(priv, DM9K_PIDH) << 24;
+
+ if (id != DM9K_ID) {
+ dev_err(dev, "dm9000 not found at 0x%p id: 0x%08x\n",
+ priv->iobase, id);
+ return -ENODEV;
+ }
+
+ id = dm9k_ior(priv, DM9K_CHIPR);
+ dev_dbg(dev, "dm9000 revision 0x%02x\n", id);
+
+ switch (id) {
+ case CHIPR_DM9000A:
+ c = 'A';
+ break;
+ case CHIPR_DM9000B:
+ c = 'B';
+ break;
+ default:
+ c = 'E';
+ }
+ dev_info(dev, "Found DM9000%c at i/o: 0x%p\n", c, priv->iobase);
+
+ return 0;
+}
+
+static void dm9k_enable(struct dm9k *priv)
+{
+ /* only intern phy supported by now */
+ dm9k_iow(priv, DM9K_NCR, 0x00);
+ /* TX Polling clear */
+ dm9k_iow(priv, DM9K_TCR, 0x00);
+ /* Less 3Kb, 200us */
+ dm9k_iow(priv, DM9K_BPTR, 0x3f);
+ /* Flow Control : High/Low Water */
+ dm9k_iow(priv, DM9K_FCTR, FCTR_HWOT(3) | FCTR_LWOT(8));
+ /* SH FIXME: This looks strange! Flow Control */
+ dm9k_iow(priv, DM9K_FCR, 0x00);
+ /* Special Mode */
+ dm9k_iow(priv, DM9K_SMCR, 0x00);
+ /* clear TX status */
+ dm9k_iow(priv, DM9K_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END);
+ /* Clear interrupt status */
+ dm9k_iow(priv, DM9K_IMR, IMR_PAR);
+ dm9k_iow(priv, DM9K_ISR, ISR_CLEAR_MASK);
+
+ /* Activate DM9000 */
+ dm9k_iow(priv, DM9K_GPCR, 0x01); /* Let GPIO0 output */
+ dm9k_iow(priv, DM9K_GPR, 0x00); /* Enable PHY */
+ /* RX enable */
+ dm9k_iow(priv, DM9K_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
+ /* Enable TX/RX interrupt mask */
+ dm9k_iow(priv, DM9K_IMR, IMR_PAR | IMR_PRM | IMR_PTM);
+}
+
+static void dm9k_reset(struct dm9k *priv)
+{
+ struct device_d *dev = priv->miidev.parent;
+
+ dev_dbg(dev, "%s\n", __func__);
+ dm9k_iow(priv, DM9K_NCR, NCR_RST);
+ udelay(1000); /* delay 1ms */
+}
+
+static int dm9k_eth_open(struct eth_device *edev)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+
+ miidev_wait_aneg(&priv->miidev);
+ miidev_print_status(&priv->miidev);
+ return 0;
+}
+
+static void dm9k_write_length(struct dm9k *priv, unsigned length)
+{
+ dm9k_iow(priv, DM9K_TXPLL, length);
+ dm9k_iow(priv, DM9K_TXPLH, length >> 8);
+}
+
+static int dm9k_wait_for_trans_end(struct dm9k *priv)
+{
+ struct device_d *dev = priv->miidev.parent;
+ static const uint64_t toffs = 1 * SECOND;
+ uint8_t status;
+ uint64_t start = get_time_ns();
+
+ do {
+ status = dm9k_ior(priv, DM9K_NSR);
+ if (status & (NSR_TX1END | NSR_TX2END)) {
+ dev_dbg(dev, "transmit done\n");
+ return 0;
+ }
+ status = dm9k_ior(priv, DM9K_ISR);
+ if (status & IMR_PTM) {
+ /* Clear Tx bit in ISR */
+ dm9k_iow(priv, DM9K_ISR, IMR_PTM);
+ dev_dbg(dev, "transmit done\n");
+ return 0;
+ }
+ } while (!is_timeout(start, toffs));
+
+ return -ETIMEDOUT;
+}
+
+static int dm9k_eth_send(struct eth_device *edev, void *packet, int length)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+ struct device_d *dev = priv->miidev.parent;
+
+ dev_dbg(dev, "%s: %d bytes\n", __func__, length);
+
+ /* arm the Tx bit */
+ dm9k_iow(priv, DM9K_ISR, IMR_PTM);
+
+ /* Prepare for TX-data */
+ writeb(DM9K_MWCMD, priv->iobase);
+
+ /* Move the packet into the DM9k's TX RAM */
+ dm9k_wd(priv->buswidth, priv->iodata, packet, length);
+
+ /* Set TX length of the packet */
+ dm9k_write_length(priv, length);
+
+ /* Issue TX polling command */
+ dm9k_iow(priv, DM9K_TCR, TCR_TXREQ); /* Cleared after TX complete */
+
+ /* wait for end of transmission */
+ return dm9k_wait_for_trans_end(priv);
+}
+
+static int dm9k_check_for_rx_packet(struct dm9k *priv)
+{
+ uint8_t status;
+ struct device_d *dev = priv->miidev.parent;
+
+ status = dm9k_ior(priv, DM9K_ISR);
+ if (!(status & ISR_PR))
+ return 0; /* no packet */
+
+ dev_dbg(dev, "Packet present\n");
+ dm9k_iow(priv, DM9K_ISR, ISR_PR); /* clear PR status latched in bit 0 */
+ return 1; /* packet present */
+}
+
+static int dm9k_validate_entry(struct dm9k *priv)
+{
+ struct device_d *dev = priv->miidev.parent;
+
+ uint8_t p_stat;
+ /*
+ * setup read pointer to current packet
+ * but without address increment
+ */
+ dm9k_ior(priv, DM9K_MRCMDX);
+
+ /* read the entry's status according to the app note */
+ p_stat = readb(priv->iodata) & 0x03;
+ dev_dbg(dev, "%s packet status %02X\n", __func__, p_stat);
+
+ switch (p_stat) {
+ case DM9K_PKT_NONE: /* there is no packet (or the last in the chain) */
+ return 0;
+
+ case DM9K_PKT_ERR: /* chip in invalid state. Needs a software reset */
+ dev_dbg(dev, "Confused chip.\n");
+ dm9k_iow(priv, DM9K_RCR, 0x00); /* Stop Device */
+ dm9k_iow(priv, DM9K_ISR, 0x80); /* Stop INT request */
+ dm9k_reset(priv);
+ dm9k_enable(priv);
+ return 0;
+ }
+
+ return 1; /* entry is valid */
+}
+
+static int dm9k_eth_rx(struct eth_device *edev)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+ struct device_d *dev = edev->parent;
+ unsigned rx_stat = 0, rx_len = 0;
+ bool p_valid;
+
+ if (dm9k_check_for_rx_packet(priv) == 0)
+ return 0; /* no data present */
+
+ do {
+ if (!dm9k_validate_entry(priv))
+ return 0;
+
+ /* assume this packet is valid */
+ p_valid = true;
+
+ /* read with automatic address increment now */
+ writeb(DM9K_MRCMD, priv->iobase);
+ rx_len = dm9k_read_packet_status(priv->buswidth, priv->iodata, &rx_stat);
+ if (rx_len < 0x40) {
+ dev_dbg(dev, "Packet too short (%u bytes)\n", rx_len);
+ p_valid = false;
+ }
+
+ /* validate packet */
+ if (rx_stat & RSR_ERR_MASK) {
+ if (rx_stat & RSR_FOE)
+ dev_warn(dev, "rx fifo overflow error\n");
+ if (rx_stat & RSR_CE)
+ dev_warn(dev, "rx crc error\n");
+ if (rx_stat & RSR_AE)
+ dev_warn(dev, "rx Alignment Error error\n");
+ if (rx_stat & RSR_PLE)
+ dev_warn(dev, "rx Physical Layer Error error\n");
+ if (rx_stat & RSR_RWTO)
+ dev_warn(dev, "rx Receive Watchdog Time Out error\n");
+ if (rx_stat & RSR_LCS)
+ dev_warn(dev, "rx Late Collision Seen error\n");
+ if (rx_stat & RSR_RF)
+ dev_warn(dev, "rx length error (runt frame)\n");
+ p_valid = false;
+ }
+
+ if (rx_len > DM9K_PKT_MAX) {
+ dev_warn(dev, "rx length too big\n");
+ /* discard packet */
+ dm9k_dump(priv->buswidth, priv->iodata, rx_len);
+ dm9k_reset(priv);
+ dm9k_enable(priv);
+ return 0;
+ }
+
+ if (p_valid == true) {
+ dev_dbg(dev, "Receiving packet\n");
+ dm9k_rd(priv->buswidth, priv->iodata, priv->pckt, rx_len);
+ dev_dbg(dev, "passing %u bytes packet to upper layer\n", rx_len);
+ net_receive(priv->pckt, rx_len);
+ } else {
+ dev_dbg(dev, "Discarding packet\n");
+ dm9k_dump(priv->buswidth, priv->iodata, rx_len); /* discard packet */
+ }
+ } while (1);
+
+ return 0;
+}
+
+
+static void dm9k_eth_halt(struct eth_device *edev)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+
+ dm9k_iow(priv, DM9K_GPR, 0x01); /* Power-Down PHY */
+ dm9k_iow(priv, DM9K_IMR, 0x80); /* Disable all interrupt */
+ dm9k_iow(priv, DM9K_RCR, 0x00); /* Disable RX */
+}
+
+static u16 read_srom_word(struct dm9k *priv, int offset)
+{
+ dm9k_iow(priv, DM9K_EPAR, offset);
+ dm9k_iow(priv, DM9K_EPCR, 0x4);
+ udelay(200);
+ dm9k_iow(priv, DM9K_EPCR, 0x0);
+ return (dm9k_ior(priv, DM9K_EPDRL) + (dm9k_ior(priv, DM9K_EPDRH) << 8));
+}
+
+static int dm9k_get_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+ int i, oft;
+
+ if (priv->srom) {
+ for (i = 0; i < 3; i++)
+ ((u16 *) adr)[i] = read_srom_word(priv, i);
+ } else {
+ for (i = 0, oft = DM9K_PAR; i < 6; i++, oft++)
+ adr[i] = dm9k_ior(priv, oft);
+ }
+
+ return 0;
+}
+
+static int dm9k_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+ int i, oft;
+
+ for (i = 0, oft = DM9K_PAR; i < 6; i++, oft++)
+ dm9k_iow(priv, oft, adr[i]);
+ for (i = 0, oft = DM9K_MAR; i < 8; i++, oft++)
+ dm9k_iow(priv, oft, 0xff);
+
+ return 0;
+}
+
+static int dm9k_init_dev(struct eth_device *edev)
+{
+ struct dm9k *priv = (struct dm9k *)edev->priv;
+
+ miidev_restart_aneg(&priv->miidev);
+ return 0;
+}
+
+static int dm9k_probe(struct device_d *dev)
+{
+ unsigned io_mode;
+ struct eth_device *edev;
+ struct dm9k *priv;
+ struct dm9000_platform_data *pdata;
+
+ if (!dev->platform_data) {
+ dev_err(dev, "No platform_data\n");
+ return -ENODEV;
+ }
+
+ if (dev->num_resources < 2) {
+ dev_err(dev, "Need 2 resources base and data");
+ return -ENODEV;
+ }
+
+ edev = xzalloc(sizeof(struct eth_device) + sizeof(struct dm9k));
+ dev->type_data = edev;
+ edev->priv = (struct dm9k *)(edev + 1);
+
+ pdata = dev->platform_data;
+
+ priv = edev->priv;
+
+ priv->buswidth = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
+ priv->iodata = dev_request_mem_region(dev, 1);
+ priv->iobase = dev_request_mem_region(dev, 0);
+ priv->srom = pdata->srom;
+
+ edev->init = dm9k_init_dev;
+ edev->open = dm9k_eth_open;
+ edev->send = dm9k_eth_send;
+ edev->recv = dm9k_eth_rx;
+ edev->halt = dm9k_eth_halt;
+ edev->set_ethaddr = dm9k_set_ethaddr;
+ edev->get_ethaddr = dm9k_get_ethaddr;
+ edev->parent = dev;
+
+ priv->miidev.read = dm9k_phy_read;
+ priv->miidev.write = dm9k_phy_write;
+ priv->miidev.address = 0;
+ priv->miidev.flags = 0;
+ priv->miidev.edev = edev;
+ priv->miidev.parent = dev;
+
+ /* RESET device */
+ dm9k_reset(priv);
+ if(dm9k_check_id(priv))
+ return -ENODEV;
+
+ io_mode = dm9k_ior(priv, DM9K_ISR) >> 6;
+ switch (io_mode) {
+ case 0:
+ dev_dbg(dev, "16 bit data bus\n");
+ if (priv->buswidth != IORESOURCE_MEM_16BIT)
+ dev_err(dev,
+ "Wrong databus width defined at compile time\n");
+ break;
+ case 1:
+ dev_dbg(dev, "32 bit data bus\n");
+ if (priv->buswidth != IORESOURCE_MEM_32BIT)
+ dev_err(dev,
+ "Wrong databus width defined at compile time\n");
+ break;
+ case 2:
+ dev_dbg(dev, "8 bit data bus\n");
+ if (priv->buswidth != IORESOURCE_MEM_32BIT)
+ dev_err(dev,
+ "Wrong databus width defined at compile time\n");
+ break;
+ default:
+ dev_warn(dev, "Unknown data width\n");
+ }
+
+ dm9k_enable(priv);
+
+ mii_register(&priv->miidev);
+ eth_register(edev);
+
+ return 0;
+}
+
+static struct driver_d dm9k_driver = {
+ .name = "dm9000",
+ .probe = dm9k_probe,
+};
+
+static int dm9k_init(void)
+{
+ register_driver(&dm9k_driver);
+ return 0;
+}
+
+device_initcall(dm9k_init);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index 592d543508..186b59638f 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -78,16 +78,16 @@ config DRIVER_SERIAL_PL010
help
Enable this to get support for AMBA PL010 based serial devices
-config DRIVER_SERIAL_S3C24X0
- bool "Samsung S3C24X0 serial driver"
+config DRIVER_SERIAL_S3C
+ bool "Samsung S3C serial driver"
depends on ARCH_S3C24xx
default y
help
- Say Y here if you want to use the CONS on a S3C24X0 CPU
+ Say Y here if you want to use the CONS on a Samsung S3C CPU
-config DRIVER_SERIAL_S3C24X0_AUTOSYNC
+config DRIVER_SERIAL_S3C_AUTOSYNC
bool "Enable auto flow"
- depends on DRIVER_SERIAL_S3C24X0
+ depends on DRIVER_SERIAL_S3C
help
Say Y here if you want to use the auto flow feature of this
UART. RTS and CTS will be handled by the hardware when enabled.
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index a7021252f7..e2d56b96b7 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -15,7 +15,7 @@ obj-$(CONFIG_DRIVER_SERIAL_MPC5XXX) += serial_mpc5xxx.o
obj-$(CONFIG_DRIVER_SERIAL_BLACKFIN) += serial_blackfin.o
obj-$(CONFIG_DRIVER_SERIAL_NS16550) += serial_ns16550.o
obj-$(CONFIG_DRIVER_SERIAL_PL010) += serial_pl010.o
-obj-$(CONFIG_DRIVER_SERIAL_S3C24X0) += serial_s3c24x0.o
+obj-$(CONFIG_DRIVER_SERIAL_S3C) += serial_s3c.o
obj-$(CONFIG_DRIVER_SERIAL_ALTERA) += serial_altera.o
obj-$(CONFIG_DRIVER_SERIAL_ALTERA_JTAG) += serial_altera_jtag.o
obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o
diff --git a/drivers/serial/serial_s3c24x0.c b/drivers/serial/serial_s3c.c
index 1e27d48bfd..b7e09879bd 100644
--- a/drivers/serial/serial_s3c24x0.c
+++ b/drivers/serial/serial_s3c.c
@@ -1,5 +1,5 @@
/*
- * (c) 2009 Juergen Beisert <j.beisert@saschahauer.de>
+ * (c) 2009...2011 Juergen Beisert <j.beisert@pengutronix.de>
*
* Based on code from:
* (c) 2004 Sascha Hauer <sascha@saschahauer.de>
@@ -25,8 +25,8 @@
#include <init.h>
#include <malloc.h>
#include <io.h>
-#include <mach/s3c24xx-generic.h>
-#include <mach/s3c24x0-iomap.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c-iomap.h>
/* Note: Offsets are for little endian access */
#define ULCON 0x00 /* line control */
@@ -41,20 +41,36 @@
#define URXH 0x24 /* receive */
#define UBRDIV 0x28 /* baudrate generator */
-static int s3c24x0_serial_setbaudrate(struct console_device *cdev, int baudrate)
+static unsigned s3c_get_arch_uart_input_clock(void __iomem *base)
+{
+ unsigned reg = readw(base + UCON);
+
+ switch (reg & 0xc00) {
+ case 0x000:
+ case 0x800:
+ return s3c_get_pclk();
+ case 0x400:
+ break; /* TODO UEXTCLK */
+ case 0xc00:
+ break; /* TODO FCLK/n */
+ }
+
+ return 0; /* not nice, but we can't emit an error message! */
+}
+
+static int s3c_serial_setbaudrate(struct console_device *cdev, int baudrate)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
unsigned val;
- /* value is calculated so : PCLK / (16 * baudrate) -1 */
- val = s3c24xx_get_pclk() / (16 * baudrate) - 1;
+ val = s3c_get_arch_uart_input_clock(base) / (16 * baudrate) - 1;
writew(val, base + UBRDIV);
return 0;
}
-static int s3c24x0_serial_init_port(struct console_device *cdev)
+static int s3c_serial_init_port(struct console_device *cdev)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
@@ -71,7 +87,7 @@ static int s3c24x0_serial_init_port(struct console_device *cdev)
*/
writew(0x0245, base + UCON);
-#ifdef CONFIG_DRIVER_SERIAL_S3C24X0_AUTOSYNC
+#ifdef CONFIG_DRIVER_SERIAL_S3C_AUTOSYNC
writeb(0x10, base + UMCON); /* enable auto flow control */
#else
writeb(0x01, base + UMCON); /* RTS up */
@@ -80,7 +96,7 @@ static int s3c24x0_serial_init_port(struct console_device *cdev)
return 0;
}
-static void s3c24x0_serial_putc(struct console_device *cdev, char c)
+static void s3c_serial_putc(struct console_device *cdev, char c)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
@@ -92,7 +108,7 @@ static void s3c24x0_serial_putc(struct console_device *cdev, char c)
writeb(c, base + UTXH);
}
-static int s3c24x0_serial_tstc(struct console_device *cdev)
+static int s3c_serial_tstc(struct console_device *cdev)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
@@ -104,7 +120,7 @@ static int s3c24x0_serial_tstc(struct console_device *cdev)
return 0;
}
-static int s3c24x0_serial_getc(struct console_device *cdev)
+static int s3c_serial_getc(struct console_device *cdev)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
@@ -116,7 +132,7 @@ static int s3c24x0_serial_getc(struct console_device *cdev)
return readb(base + URXH);
}
-static void s3c24x0_serial_flush(struct console_device *cdev)
+static void s3c_serial_flush(struct console_device *cdev)
{
struct device_d *dev = cdev->dev;
void __iomem *base = dev->priv;
@@ -125,7 +141,7 @@ static void s3c24x0_serial_flush(struct console_device *cdev)
;
}
-static int s3c24x0_serial_probe(struct device_d *dev)
+static int s3c_serial_probe(struct device_d *dev)
{
struct console_device *cdev;
@@ -134,13 +150,13 @@ static int s3c24x0_serial_probe(struct device_d *dev)
dev->priv = dev_request_mem_region(dev, 0);
cdev->dev = dev;
cdev->f_caps = CONSOLE_STDIN | CONSOLE_STDOUT | CONSOLE_STDERR;
- cdev->tstc = s3c24x0_serial_tstc;
- cdev->putc = s3c24x0_serial_putc;
- cdev->getc = s3c24x0_serial_getc;
- cdev->flush = s3c24x0_serial_flush;
- cdev->setbrg = s3c24x0_serial_setbaudrate;
+ cdev->tstc = s3c_serial_tstc;
+ cdev->putc = s3c_serial_putc;
+ cdev->getc = s3c_serial_getc;
+ cdev->flush = s3c_serial_flush;
+ cdev->setbrg = s3c_serial_setbaudrate;
- s3c24x0_serial_init_port(cdev);
+ s3c_serial_init_port(cdev);
/* Enable UART */
console_register(cdev);
@@ -148,25 +164,25 @@ static int s3c24x0_serial_probe(struct device_d *dev)
return 0;
}
-static void s3c24x0_serial_remove(struct device_d *dev)
+static void s3c_serial_remove(struct device_d *dev)
{
struct console_device *cdev = dev->type_data;
- s3c24x0_serial_flush(cdev);
+ s3c_serial_flush(cdev);
free(cdev);
dev->type_data = NULL;
}
-static struct driver_d s3c24x0_serial_driver = {
- .name = "s3c24x0_serial",
- .probe = s3c24x0_serial_probe,
- .remove = s3c24x0_serial_remove,
+static struct driver_d s3c_serial_driver = {
+ .name = "s3c_serial",
+ .probe = s3c_serial_probe,
+ .remove = s3c_serial_remove,
};
-static int s3c24x0_serial_init(void)
+static int s3c_serial_init(void)
{
- register_driver(&s3c24x0_serial_driver);
+ register_driver(&s3c_serial_driver);
return 0;
}
-console_initcall(s3c24x0_serial_init);
+console_initcall(s3c_serial_init);
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 472c591c35..797d19fe5f 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -15,6 +15,13 @@ config USB_GADGET_DRIVER_ARC
depends on ARCH_IMX
select USB_GADGET_DUALSPEED
+config USB_GADGET_DRIVER_AT91
+ bool
+ prompt "at91 gadget driver"
+ depends on ARCH_AT91
+ select USB_GADGET_DUALSPEED
+ select POLLER
+
config USB_GADGET_DRIVER_PXA27X
bool
prompt "PXA27x gadget driver"
@@ -23,8 +30,7 @@ config USB_GADGET_DRIVER_PXA27X
select POLLER
endchoice
-choice
- prompt "USB Gadget drivers"
+comment "USB Gadget drivers"
config USB_GADGET_DFU
bool
@@ -35,7 +41,5 @@ config USB_GADGET_SERIAL
depends on EXPERIMENTAL
prompt "Serial Gadget"
-endchoice
-
endif
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index e034786dc8..367d7ceaba 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -3,4 +3,5 @@ obj-$(CONFIG_USB_GADGET) += composite.o config.o usbstring.o epautoconf.o
obj-$(CONFIG_USB_GADGET_SERIAL) += u_serial.o serial.o f_serial.o f_acm.o
obj-$(CONFIG_USB_GADGET_DFU) += dfu.o
obj-$(CONFIG_USB_GADGET_DRIVER_ARC) += fsl_udc.o
+obj-$(CONFIG_USB_GADGET_DRIVER_AT91) += at91_udc.o
obj-$(CONFIG_USB_GADGET_DRIVER_PXA27X) += pxa27x_udc.o
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c
new file mode 100644
index 0000000000..bb0d6143f1
--- /dev/null
+++ b/drivers/usb/gadget/at91_udc.c
@@ -0,0 +1,1538 @@
+/*
+ * at91_udc -- driver for at91-series USB peripheral controller
+ *
+ * Copyright (C) 2004 by Thomas Rathbone
+ * Copyright (C) 2005 by HP Labs
+ * Copyright (C) 2005 by David Brownell
+ *
+ * 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.
+ */
+
+#undef VERBOSE_DEBUG
+#undef PACKET_TRACE
+
+#include <common.h>
+#include <errno.h>
+#include <init.h>
+#include <clock.h>
+#include <usb/ch9.h>
+#include <usb/gadget.h>
+#include <poller.h>
+
+#include <linux/list.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <asm/byteorder.h>
+
+#include <mach/hardware.h>
+#include <mach/io.h>
+#include <mach/board.h>
+#include <mach/cpu.h>
+#include <mach/gpio.h>
+#include <mach/at91sam9261_matrix.h>
+
+#include "at91_udc.h"
+
+
+/*
+ * This controller is simple and PIO-only. It's used in many AT91-series
+ * full speed USB controllers, including the at91rm9200 (arm920T, with MMU),
+ * at91sam926x (arm926ejs, with MMU), and several no-mmu versions.
+ *
+ * This driver expects the board has been wired with two GPIOs suppporting
+ * a VBUS sensing IRQ, and a D+ pullup. (They may be omitted, but the
+ * testing hasn't covered such cases.)
+ *
+ * The pullup is most important (so it's integrated on sam926x parts). It
+ * provides software control over whether the host enumerates the device.
+ *
+ * The VBUS sensing helps during enumeration, and allows both USB clocks
+ * (and the transceiver) to stay gated off until they're necessary, saving
+ * power. During USB suspend, the 48 MHz clock is gated off in hardware;
+ * it may also be gated off by software during some Linux sleep states.
+ */
+
+#define DRIVER_VERSION "3 May 2006"
+
+#define driver_name "at91_udc"
+static const char ep0name[] = "ep0";
+
+#define at91_udp_read(udc, reg) \
+ __raw_readl((udc)->udp_baseaddr + (reg))
+#define at91_udp_write(udc, reg, val) \
+ __raw_writel((val), (udc)->udp_baseaddr + (reg))
+
+/*-------------------------------------------------------------------------*/
+
+static void done(struct at91_ep *ep, struct at91_request *req, int status)
+{
+ unsigned stopped = ep->stopped;
+ struct at91_udc *udc = ep->udc;
+
+ list_del_init(&req->queue);
+ if (req->req.status == -EINPROGRESS)
+ req->req.status = status;
+ else
+ status = req->req.status;
+ if (status && status != -ESHUTDOWN)
+ VDBG(udc, "%s done %p, status %d\n", ep->ep.name, req, status);
+
+ ep->stopped = 1;
+ req->req.complete(&ep->ep, &req->req);
+ ep->stopped = stopped;
+
+ /* ep0 is always ready; other endpoints need a non-empty queue */
+ if (list_empty(&ep->queue) && ep->int_mask != (1 << 0))
+ at91_udp_write(udc, AT91_UDP_IDR, ep->int_mask);
+}
+
+/*-------------------------------------------------------------------------*/
+
+/* bits indicating OUT fifo has data ready */
+#define RX_DATA_READY (AT91_UDP_RX_DATA_BK0 | AT91_UDP_RX_DATA_BK1)
+
+/*
+ * Endpoint FIFO CSR bits have a mix of bits, making it unsafe to just write
+ * back most of the value you just read (because of side effects, including
+ * bits that may change after reading and before writing).
+ *
+ * Except when changing a specific bit, always write values which:
+ * - clear SET_FX bits (setting them could change something)
+ * - set CLR_FX bits (clearing them could change something)
+ *
+ * There are also state bits like FORCESTALL, EPEDS, DIR, and EPTYPE
+ * that shouldn't normally be changed.
+ *
+ * NOTE at91sam9260 docs mention synch between UDPCK and MCK clock domains,
+ * implying a need to wait for one write to complete (test relevant bits)
+ * before starting the next write. This shouldn't be an issue given how
+ * infrequently we write, except maybe for write-then-read idioms.
+ */
+#define SET_FX (AT91_UDP_TXPKTRDY)
+#define CLR_FX (RX_DATA_READY | AT91_UDP_RXSETUP \
+ | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)
+
+/* pull OUT packet data from the endpoint's fifo */
+static int read_fifo (struct at91_ep *ep, struct at91_request *req)
+{
+ u32 __iomem *creg = ep->creg;
+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+ u32 csr;
+ u8 *buf;
+ unsigned int count, bufferspace, is_done;
+
+ buf = req->req.buf + req->req.actual;
+ bufferspace = req->req.length - req->req.actual;
+
+ /*
+ * there might be nothing to read if ep_queue() calls us,
+ * or if we already emptied both pingpong buffers
+ */
+rescan:
+ csr = __raw_readl(creg);
+ if ((csr & RX_DATA_READY) == 0)
+ return 0;
+
+ count = (csr & AT91_UDP_RXBYTECNT) >> 16;
+ if (count > ep->ep.maxpacket)
+ count = ep->ep.maxpacket;
+ if (count > bufferspace) {
+ DBG(ep->udc, "%s buffer overflow\n", ep->ep.name);
+ req->req.status = -EOVERFLOW;
+ count = bufferspace;
+ }
+ readsb(dreg, buf, count);
+
+ /* release and swap pingpong mem bank */
+ csr |= CLR_FX;
+ if (ep->is_pingpong) {
+ if (ep->fifo_bank == 0) {
+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+ ep->fifo_bank = 1;
+ } else {
+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK1);
+ ep->fifo_bank = 0;
+ }
+ } else
+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+ __raw_writel(csr, creg);
+
+ req->req.actual += count;
+ is_done = (count < ep->ep.maxpacket);
+ if (count == bufferspace)
+ is_done = 1;
+
+ PACKET("%s %p out/%d%s\n", ep->ep.name, &req->req, count,
+ is_done ? " (done)" : "");
+
+ /*
+ * avoid extra trips through IRQ logic for packets already in
+ * the fifo ... maybe preventing an extra (expensive) OUT-NAK
+ */
+ if (is_done)
+ done(ep, req, 0);
+ else if (ep->is_pingpong) {
+ /*
+ * One dummy read to delay the code because of a HW glitch:
+ * CSR returns bad RXCOUNT when read too soon after updating
+ * RX_DATA_BK flags.
+ */
+ csr = __raw_readl(creg);
+
+ bufferspace -= count;
+ buf += count;
+ goto rescan;
+ }
+
+ return is_done;
+}
+
+/* load fifo for an IN packet */
+static int write_fifo(struct at91_ep *ep, struct at91_request *req)
+{
+ u32 __iomem *creg = ep->creg;
+ u32 csr = __raw_readl(creg);
+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+ unsigned total, count, is_last;
+ u8 *buf;
+
+ /*
+ * TODO: allow for writing two packets to the fifo ... that'll
+ * reduce the amount of IN-NAKing, but probably won't affect
+ * throughput much. (Unlike preventing OUT-NAKing!)
+ */
+
+ /*
+ * If ep_queue() calls us, the queue is empty and possibly in
+ * odd states like TXCOMP not yet cleared (we do it, saving at
+ * least one IRQ) or the fifo not yet being free. Those aren't
+ * issues normally (IRQ handler fast path).
+ */
+ if (unlikely(csr & (AT91_UDP_TXCOMP | AT91_UDP_TXPKTRDY))) {
+ if (csr & AT91_UDP_TXCOMP) {
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+ __raw_writel(csr, creg);
+ csr = __raw_readl(creg);
+ }
+ if (csr & AT91_UDP_TXPKTRDY)
+ return 0;
+ }
+
+ buf = req->req.buf + req->req.actual;
+ total = req->req.length - req->req.actual;
+ if (ep->ep.maxpacket < total) {
+ count = ep->ep.maxpacket;
+ is_last = 0;
+ } else {
+ count = total;
+ is_last = (count < ep->ep.maxpacket) || !req->req.zero;
+ }
+
+ /*
+ * Write the packet, maybe it's a ZLP.
+ *
+ * NOTE: incrementing req->actual before we receive the ACK means
+ * gadget driver IN bytecounts can be wrong in fault cases. That's
+ * fixable with PIO drivers like this one (save "count" here, and
+ * do the increment later on TX irq), but not for most DMA hardware.
+ *
+ * So all gadget drivers must accept that potential error. Some
+ * hardware supports precise fifo status reporting, letting them
+ * recover when the actual bytecount matters (e.g. for USB Test
+ * and Measurement Class devices).
+ */
+ writesb(dreg, buf, count);
+ csr &= ~SET_FX;
+ csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+ writel(csr, creg);
+ req->req.actual += count;
+
+ PACKET("%s %p in/%d%s\n", ep->ep.name, &req->req, count,
+ is_last ? " (done)" : "");
+ if (is_last)
+ done(ep, req, 0);
+ return is_last;
+}
+
+static void nuke(struct at91_ep *ep, int status)
+{
+ struct at91_request *req;
+
+ /* terminate any request in the queue */
+ ep->stopped = 1;
+ if (list_empty(&ep->queue))
+ return;
+
+ VDBG(udc, "%s %s\n", __func__, ep->ep.name);
+ while (!list_empty(&ep->queue)) {
+ req = list_entry(ep->queue.next, struct at91_request, queue);
+ done(ep, req, status);
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_ep_enable(struct usb_ep *_ep,
+ const struct usb_endpoint_descriptor *desc)
+{
+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
+ u16 maxpacket;
+ u32 tmp;
+
+ if (!_ep || !ep
+ || !desc || ep->desc
+ || _ep->name == ep0name
+ || desc->bDescriptorType != USB_DT_ENDPOINT
+ || (maxpacket = le16_to_cpu(desc->wMaxPacketSize)) == 0
+ || maxpacket > ep->maxpacket) {
+ DBG(udc, "bad ep or descriptor\n");
+ return -EINVAL;
+ }
+
+ if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+ DBG(udc, "bogus device state\n");
+ return -ESHUTDOWN;
+ }
+
+ tmp = usb_endpoint_type(desc);
+ switch (tmp) {
+ case USB_ENDPOINT_XFER_CONTROL:
+ DBG(udc, "only one control endpoint\n");
+ return -EINVAL;
+ case USB_ENDPOINT_XFER_INT:
+ if (maxpacket > 64)
+ goto bogus_max;
+ break;
+ case USB_ENDPOINT_XFER_BULK:
+ switch (maxpacket) {
+ case 8:
+ case 16:
+ case 32:
+ case 64:
+ goto ok;
+ }
+bogus_max:
+ DBG(udc, "bogus maxpacket %d\n", maxpacket);
+ return -EINVAL;
+ case USB_ENDPOINT_XFER_ISOC:
+ if (!ep->is_pingpong) {
+ DBG(udc, "iso requires double buffering\n");
+ return -EINVAL;
+ }
+ break;
+ }
+
+ok:
+
+ /* initialize endpoint to match this descriptor */
+ ep->is_in = usb_endpoint_dir_in(desc);
+ ep->is_iso = (tmp == USB_ENDPOINT_XFER_ISOC);
+ ep->stopped = 0;
+ if (ep->is_in)
+ tmp |= 0x04;
+ tmp <<= 8;
+ tmp |= AT91_UDP_EPEDS;
+ __raw_writel(tmp, ep->creg);
+
+ ep->desc = desc;
+ ep->ep.maxpacket = maxpacket;
+
+ /*
+ * reset/init endpoint fifo. NOTE: leaves fifo_bank alone,
+ * since endpoint resets don't reset hw pingpong state.
+ */
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+
+ return 0;
+}
+
+static int at91_ep_disable (struct usb_ep * _ep)
+{
+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
+
+ if (ep == &ep->udc->ep[0])
+ return -EINVAL;
+
+ nuke(ep, -ESHUTDOWN);
+
+ /* restore the endpoint's pristine config */
+ ep->desc = NULL;
+ ep->ep.maxpacket = ep->maxpacket;
+
+ /* reset fifos and endpoint */
+ if (ep->udc->clocked) {
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+ __raw_writel(0, ep->creg);
+ }
+
+ return 0;
+}
+
+/*
+ * this is a PIO-only driver, so there's nothing
+ * interesting for request or buffer allocation.
+ */
+
+static struct usb_request *
+at91_ep_alloc_request(struct usb_ep *_ep)
+{
+ struct at91_request *req;
+
+ req = xzalloc(sizeof *req);
+
+ INIT_LIST_HEAD(&req->queue);
+ return &req->req;
+}
+
+static void at91_ep_free_request(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct at91_request *req;
+
+ req = container_of(_req, struct at91_request, req);
+ BUG_ON(!list_empty(&req->queue));
+ kfree(req);
+}
+
+static int at91_ep_queue(struct usb_ep *_ep,
+ struct usb_request *_req)
+{
+ struct at91_request *req;
+ struct at91_ep *ep;
+ struct at91_udc *udc;
+ int status;
+
+ req = container_of(_req, struct at91_request, req);
+ ep = container_of(_ep, struct at91_ep, ep);
+
+ if (!_req || !_req->complete
+ || !_req->buf || !list_empty(&req->queue)) {
+ DBG(udc, "invalid request\n");
+ return -EINVAL;
+ }
+
+ if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
+ DBG(udc, "invalid ep\n");
+ return -EINVAL;
+ }
+
+ udc = ep->udc;
+
+ if (!udc || !udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+ DBG(udc, "invalid device\n");
+ return -EINVAL;
+ }
+
+ _req->status = -EINPROGRESS;
+ _req->actual = 0;
+
+ /* try to kickstart any empty and idle queue */
+ if (list_empty(&ep->queue) && !ep->stopped) {
+ int is_ep0;
+
+ /*
+ * If this control request has a non-empty DATA stage, this
+ * will start that stage. It works just like a non-control
+ * request (until the status stage starts, maybe early).
+ *
+ * If the data stage is empty, then this starts a successful
+ * IN/STATUS stage. (Unsuccessful ones use set_halt.)
+ */
+ is_ep0 = (ep->ep.name == ep0name);
+ if (is_ep0) {
+ u32 tmp;
+
+ if (!udc->req_pending) {
+ status = -EINVAL;
+ goto done;
+ }
+
+ /*
+ * defer changing CONFG until after the gadget driver
+ * reconfigures the endpoints.
+ */
+ if (udc->wait_for_config_ack) {
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+ tmp ^= AT91_UDP_CONFG;
+ VDBG(udc, "toggle config\n");
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+ }
+ if (req->req.length == 0) {
+ep0_in_status:
+ PACKET("ep0 in/status\n");
+ status = 0;
+ tmp = __raw_readl(ep->creg);
+ tmp &= ~SET_FX;
+ tmp |= CLR_FX | AT91_UDP_TXPKTRDY;
+ __raw_writel(tmp, ep->creg);
+ udc->req_pending = 0;
+ goto done;
+ }
+ }
+
+ if (ep->is_in)
+ status = write_fifo(ep, req);
+ else {
+ status = read_fifo(ep, req);
+
+ /* IN/STATUS stage is otherwise triggered by irq */
+ if (status && is_ep0)
+ goto ep0_in_status;
+ }
+ } else
+ status = 0;
+
+ if (req && !status) {
+ list_add_tail (&req->queue, &ep->queue);
+ }
+done:
+ return (status < 0) ? status : 0;
+}
+
+static int at91_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req)
+{
+ struct at91_ep *ep;
+ struct at91_request *req;
+
+ ep = container_of(_ep, struct at91_ep, ep);
+ if (!_ep || ep->ep.name == ep0name)
+ return -EINVAL;
+
+ /* make sure it's actually queued on this endpoint */
+ list_for_each_entry (req, &ep->queue, queue) {
+ if (&req->req == _req)
+ break;
+ }
+ if (&req->req != _req) {
+ return -EINVAL;
+ }
+
+ done(ep, req, -ECONNRESET);
+ return 0;
+}
+
+static int at91_ep_set_halt(struct usb_ep *_ep, int value)
+{
+ struct at91_ep *ep = container_of(_ep, struct at91_ep, ep);
+ struct at91_udc *udc = ep->udc;
+ u32 __iomem *creg;
+ u32 csr;
+ int status = 0;
+
+ if (!_ep || ep->is_iso || !ep->udc->clocked)
+ return -EINVAL;
+
+ creg = ep->creg;
+
+ csr = __raw_readl(creg);
+
+ /*
+ * fail with still-busy IN endpoints, ensuring correct sequencing
+ * of data tx then stall. note that the fifo rx bytecount isn't
+ * completely accurate as a tx bytecount.
+ */
+ if (ep->is_in && (!list_empty(&ep->queue) || (csr >> 16) != 0))
+ status = -EAGAIN;
+ else {
+ csr |= CLR_FX;
+ csr &= ~SET_FX;
+ if (value) {
+ csr |= AT91_UDP_FORCESTALL;
+ VDBG(udc, "halt %s\n", ep->ep.name);
+ } else {
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+ csr &= ~AT91_UDP_FORCESTALL;
+ }
+ __raw_writel(csr, creg);
+ }
+
+ return status;
+}
+
+static const struct usb_ep_ops at91_ep_ops = {
+ .enable = at91_ep_enable,
+ .disable = at91_ep_disable,
+ .alloc_request = at91_ep_alloc_request,
+ .free_request = at91_ep_free_request,
+ .queue = at91_ep_queue,
+ .dequeue = at91_ep_dequeue,
+ .set_halt = at91_ep_set_halt,
+ /* there's only imprecise fifo status reporting */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int at91_get_frame(struct usb_gadget *gadget)
+{
+ struct at91_udc *udc = to_udc(gadget);
+
+ if (!to_udc(gadget)->clocked)
+ return -EINVAL;
+ return at91_udp_read(udc, AT91_UDP_FRM_NUM) & AT91_UDP_NUM;
+}
+
+static int at91_wakeup(struct usb_gadget *gadget)
+{
+ struct at91_udc *udc = to_udc(gadget);
+ u32 glbstate;
+ int status = -EINVAL;
+
+ DBG(udc, "%s\n", __func__ );
+
+ if (!udc->clocked || !udc->suspended)
+ goto done;
+
+ /* NOTE: some "early versions" handle ESR differently ... */
+
+ glbstate = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+ if (!(glbstate & AT91_UDP_ESR))
+ goto done;
+ glbstate |= AT91_UDP_ESR;
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, glbstate);
+
+done:
+ return status;
+}
+
+/* reinit == restore initial software state */
+static void udc_reinit(struct at91_udc *udc)
+{
+ u32 i;
+
+ INIT_LIST_HEAD(&udc->gadget.ep_list);
+ INIT_LIST_HEAD(&udc->gadget.ep0->ep_list);
+
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ struct at91_ep *ep = &udc->ep[i];
+
+ if (i != 0)
+ list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list);
+ ep->desc = NULL;
+ ep->stopped = 0;
+ ep->fifo_bank = 0;
+ ep->ep.maxpacket = ep->maxpacket;
+ ep->creg = (void __iomem *) udc->udp_baseaddr + AT91_UDP_CSR(i);
+ /* initialize one queue per endpoint */
+ INIT_LIST_HEAD(&ep->queue);
+ }
+}
+
+static void stop_activity(struct at91_udc *udc)
+{
+ struct usb_gadget_driver *driver = udc->driver;
+ int i;
+
+ if (udc->gadget.speed == USB_SPEED_UNKNOWN)
+ driver = NULL;
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ udc->suspended = 0;
+
+ for (i = 0; i < NUM_ENDPOINTS; i++) {
+ struct at91_ep *ep = &udc->ep[i];
+ ep->stopped = 1;
+ nuke(ep, -ESHUTDOWN);
+ }
+ if (driver) {
+ driver->disconnect(&udc->gadget);
+ }
+
+ udc_reinit(udc);
+}
+
+static void clk_on(struct at91_udc *udc)
+{
+ if (udc->clocked)
+ return;
+ udc->clocked = 1;
+ clk_enable(udc->iclk);
+ clk_enable(udc->fclk);
+}
+
+static void clk_off(struct at91_udc *udc)
+{
+ if (!udc->clocked)
+ return;
+ udc->clocked = 0;
+ udc->gadget.speed = USB_SPEED_UNKNOWN;
+ clk_disable(udc->fclk);
+ clk_disable(udc->iclk);
+}
+
+/*
+ * activate/deactivate link with host; minimize power usage for
+ * inactive links by cutting clocks and transceiver power.
+ */
+static void pullup(struct at91_udc *udc, int is_on)
+{
+ int active = !udc->board.pullup_active_low;
+
+ if (!udc->enabled || !udc->vbus)
+ is_on = 0;
+ DBG(udc, "%sactive\n", is_on ? "" : "in");
+
+ if (is_on) {
+ clk_on(udc);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_TXVC, 0);
+ if (cpu_is_at91rm9200())
+ gpio_set_value(udc->board.pullup_pin, active);
+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc |= AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+ u32 usbpucr;
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr |= AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
+ } else {
+ stop_activity(udc);
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ if (cpu_is_at91rm9200())
+ gpio_set_value(udc->board.pullup_pin, !active);
+ else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
+ u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
+
+ txvc &= ~AT91_UDP_TXVC_PUON;
+ at91_udp_write(udc, AT91_UDP_TXVC, txvc);
+ } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+ u32 usbpucr;
+ usbpucr = at91_sys_read(AT91_MATRIX_USBPUCR);
+ usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
+ at91_sys_write(AT91_MATRIX_USBPUCR, usbpucr);
+ }
+ clk_off(udc);
+ }
+}
+
+/* vbus is here! turn everything on that's ready */
+static int at91_vbus_session(struct usb_gadget *gadget, int is_active)
+{
+ struct at91_udc *udc = to_udc(gadget);
+
+ /* VDBG(udc, "vbus %s\n", is_active ? "on" : "off"); */
+ udc->vbus = (is_active != 0);
+ if (udc->driver)
+ pullup(udc, is_active);
+ else
+ pullup(udc, 0);
+ return 0;
+}
+
+static int at91_pullup(struct usb_gadget *gadget, int is_on)
+{
+ struct at91_udc *udc = to_udc(gadget);
+
+ udc->enabled = is_on = !!is_on;
+ pullup(udc, is_on);
+ return 0;
+}
+
+static int at91_set_selfpowered(struct usb_gadget *gadget, int is_on)
+{
+ struct at91_udc *udc = to_udc(gadget);
+
+ udc->selfpowered = (is_on != 0);
+ return 0;
+}
+
+static const struct usb_gadget_ops at91_udc_ops = {
+ .get_frame = at91_get_frame,
+ .wakeup = at91_wakeup,
+ .set_selfpowered = at91_set_selfpowered,
+ .vbus_session = at91_vbus_session,
+ .pullup = at91_pullup,
+
+ /*
+ * VBUS-powered devices may also also want to support bigger
+ * power budgets after an appropriate SET_CONFIGURATION.
+ */
+ /* .vbus_power = at91_vbus_power, */
+};
+
+/*-------------------------------------------------------------------------*/
+
+static int handle_ep(struct at91_ep *ep)
+{
+ struct at91_request *req;
+ u32 __iomem *creg = ep->creg;
+ u32 csr = __raw_readl(creg);
+
+ if (!list_empty(&ep->queue))
+ req = list_entry(ep->queue.next,
+ struct at91_request, queue);
+ else
+ req = NULL;
+
+ if (ep->is_in) {
+ if (csr & (AT91_UDP_STALLSENT | AT91_UDP_TXCOMP)) {
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_TXCOMP);
+ __raw_writel(csr, creg);
+ }
+ if (req)
+ return write_fifo(ep, req);
+
+ } else {
+ if (csr & AT91_UDP_STALLSENT) {
+ /* STALLSENT bit == ISOERR */
+ if (ep->is_iso && req)
+ req->req.status = -EILSEQ;
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_STALLSENT);
+ __raw_writel(csr, creg);
+ csr = __raw_readl(creg);
+ }
+ if (req && (csr & RX_DATA_READY))
+ return read_fifo(ep, req);
+ }
+ return 0;
+}
+
+union setup {
+ u8 raw[8];
+ struct usb_ctrlrequest r;
+};
+
+static void handle_setup(struct at91_udc *udc, struct at91_ep *ep, u32 csr)
+{
+ u32 __iomem *creg = ep->creg;
+ u8 __iomem *dreg = ep->creg + (AT91_UDP_FDR(0) - AT91_UDP_CSR(0));
+ unsigned rxcount, i = 0;
+ u32 tmp;
+ union setup pkt;
+ int status = 0;
+
+ /* read and ack SETUP; hard-fail for bogus packets */
+ rxcount = (csr & AT91_UDP_RXBYTECNT) >> 16;
+ if (likely(rxcount == 8)) {
+ while (rxcount--)
+ pkt.raw[i++] = __raw_readb(dreg);
+ if (pkt.r.bRequestType & USB_DIR_IN) {
+ csr |= AT91_UDP_DIR;
+ ep->is_in = 1;
+ } else {
+ csr &= ~AT91_UDP_DIR;
+ ep->is_in = 0;
+ }
+ } else {
+ /* REVISIT this happens sometimes under load; why?? */
+ ERR(udc, "SETUP len %d, csr %08x\n", rxcount, csr);
+ status = -EINVAL;
+ }
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_RXSETUP);
+ __raw_writel(csr, creg);
+ udc->wait_for_addr_ack = 0;
+ udc->wait_for_config_ack = 0;
+ ep->stopped = 0;
+ if (unlikely(status != 0))
+ goto stall;
+
+#define w_index le16_to_cpu(pkt.r.wIndex)
+#define w_value le16_to_cpu(pkt.r.wValue)
+#define w_length le16_to_cpu(pkt.r.wLength)
+
+ VDBG(udc, "SETUP %02x.%02x v%04x i%04x l%04x\n",
+ pkt.r.bRequestType, pkt.r.bRequest,
+ w_value, w_index, w_length);
+
+ /*
+ * A few standard requests get handled here, ones that touch
+ * hardware ... notably for device and endpoint features.
+ */
+ udc->req_pending = 1;
+ csr = __raw_readl(creg);
+ csr |= CLR_FX;
+ csr &= ~SET_FX;
+ switch ((pkt.r.bRequestType << 8) | pkt.r.bRequest) {
+
+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+ | USB_REQ_SET_ADDRESS:
+ __raw_writel(csr | AT91_UDP_TXPKTRDY, creg);
+ udc->addr = w_value;
+ udc->wait_for_addr_ack = 1;
+ udc->req_pending = 0;
+ /* FADDR is set later, when we ack host STATUS */
+ return;
+
+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+ | USB_REQ_SET_CONFIGURATION:
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_CONFG;
+ if (pkt.r.wValue)
+ udc->wait_for_config_ack = (tmp == 0);
+ else
+ udc->wait_for_config_ack = (tmp != 0);
+ if (udc->wait_for_config_ack)
+ VDBG(udc, "wait for config\n");
+ /* CONFG is toggled later, if gadget driver succeeds */
+ break;
+
+ /*
+ * Hosts may set or clear remote wakeup status, and
+ * devices may report they're VBUS powered.
+ */
+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+ | USB_REQ_GET_STATUS:
+ tmp = (udc->selfpowered << USB_DEVICE_SELF_POWERED);
+ if (at91_udp_read(udc, AT91_UDP_GLB_STAT) & AT91_UDP_ESR)
+ tmp |= (1 << USB_DEVICE_REMOTE_WAKEUP);
+ PACKET("get device status\n");
+ __raw_writeb(tmp, dreg);
+ __raw_writeb(0, dreg);
+ goto write_in;
+ /* then STATUS starts later, automatically */
+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+ | USB_REQ_SET_FEATURE:
+ if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+ goto stall;
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+ tmp |= AT91_UDP_ESR;
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+ goto succeed;
+ case ((USB_TYPE_STANDARD|USB_RECIP_DEVICE) << 8)
+ | USB_REQ_CLEAR_FEATURE:
+ if (w_value != USB_DEVICE_REMOTE_WAKEUP)
+ goto stall;
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+ tmp &= ~AT91_UDP_ESR;
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+ goto succeed;
+
+ /*
+ * Interfaces have no feature settings; this is pretty useless.
+ * we won't even insist the interface exists...
+ */
+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+ | USB_REQ_GET_STATUS:
+ PACKET("get interface status\n");
+ __raw_writeb(0, dreg);
+ __raw_writeb(0, dreg);
+ goto write_in;
+ /* then STATUS starts later, automatically */
+ case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+ | USB_REQ_SET_FEATURE:
+ case ((USB_TYPE_STANDARD|USB_RECIP_INTERFACE) << 8)
+ | USB_REQ_CLEAR_FEATURE:
+ goto stall;
+
+ /*
+ * Hosts may clear bulk/intr endpoint halt after the gadget
+ * driver sets it (not widely used); or set it (for testing)
+ */
+ case ((USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+ | USB_REQ_GET_STATUS:
+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+ ep = &udc->ep[tmp];
+ if (tmp >= NUM_ENDPOINTS || (tmp && !ep->desc))
+ goto stall;
+
+ if (tmp) {
+ if ((w_index & USB_DIR_IN)) {
+ if (!ep->is_in)
+ goto stall;
+ } else if (ep->is_in)
+ goto stall;
+ }
+ PACKET("get %s status\n", ep->ep.name);
+ if (__raw_readl(ep->creg) & AT91_UDP_FORCESTALL)
+ tmp = (1 << USB_ENDPOINT_HALT);
+ else
+ tmp = 0;
+ __raw_writeb(tmp, dreg);
+ __raw_writeb(0, dreg);
+ goto write_in;
+ /* then STATUS starts later, automatically */
+ case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+ | USB_REQ_SET_FEATURE:
+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+ ep = &udc->ep[tmp];
+ if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+ goto stall;
+ if (!ep->desc || ep->is_iso)
+ goto stall;
+ if ((w_index & USB_DIR_IN)) {
+ if (!ep->is_in)
+ goto stall;
+ } else if (ep->is_in)
+ goto stall;
+
+ tmp = __raw_readl(ep->creg);
+ tmp &= ~SET_FX;
+ tmp |= CLR_FX | AT91_UDP_FORCESTALL;
+ __raw_writel(tmp, ep->creg);
+ goto succeed;
+ case ((USB_TYPE_STANDARD|USB_RECIP_ENDPOINT) << 8)
+ | USB_REQ_CLEAR_FEATURE:
+ tmp = w_index & USB_ENDPOINT_NUMBER_MASK;
+ ep = &udc->ep[tmp];
+ if (w_value != USB_ENDPOINT_HALT || tmp >= NUM_ENDPOINTS)
+ goto stall;
+ if (tmp == 0)
+ goto succeed;
+ if (!ep->desc || ep->is_iso)
+ goto stall;
+ if ((w_index & USB_DIR_IN)) {
+ if (!ep->is_in)
+ goto stall;
+ } else if (ep->is_in)
+ goto stall;
+
+ at91_udp_write(udc, AT91_UDP_RST_EP, ep->int_mask);
+ at91_udp_write(udc, AT91_UDP_RST_EP, 0);
+ tmp = __raw_readl(ep->creg);
+ tmp |= CLR_FX;
+ tmp &= ~(SET_FX | AT91_UDP_FORCESTALL);
+ __raw_writel(tmp, ep->creg);
+ if (!list_empty(&ep->queue))
+ handle_ep(ep);
+ goto succeed;
+ }
+
+#undef w_value
+#undef w_index
+#undef w_length
+
+ /* pass request up to the gadget driver */
+ if (udc->driver) {
+ status = udc->driver->setup(&udc->gadget, &pkt.r);
+ }
+ else
+ status = -ENODEV;
+ if (status < 0) {
+stall:
+ VDBG(udc, "req %02x.%02x protocol STALL; stat %d\n",
+ pkt.r.bRequestType, pkt.r.bRequest, status);
+ csr |= AT91_UDP_FORCESTALL;
+ __raw_writel(csr, creg);
+ udc->req_pending = 0;
+ }
+ return;
+
+succeed:
+ /* immediate successful (IN) STATUS after zero length DATA */
+ PACKET("ep0 in/status\n");
+write_in:
+ csr |= AT91_UDP_TXPKTRDY;
+ __raw_writel(csr, creg);
+ udc->req_pending = 0;
+}
+
+static void handle_ep0(struct at91_udc *udc)
+{
+ struct at91_ep *ep0 = &udc->ep[0];
+ u32 __iomem *creg = ep0->creg;
+ u32 csr = __raw_readl(creg);
+ struct at91_request *req;
+
+ if (unlikely(csr & AT91_UDP_STALLSENT)) {
+ nuke(ep0, -EPROTO);
+ udc->req_pending = 0;
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_STALLSENT | AT91_UDP_FORCESTALL);
+ __raw_writel(csr, creg);
+ VDBG(udc, "ep0 stalled\n");
+ csr = __raw_readl(creg);
+ }
+ if (csr & AT91_UDP_RXSETUP) {
+ nuke(ep0, 0);
+ udc->req_pending = 0;
+ handle_setup(udc, ep0, csr);
+ return;
+ }
+
+ if (list_empty(&ep0->queue))
+ req = NULL;
+ else
+ req = list_entry(ep0->queue.next, struct at91_request, queue);
+
+ /* host ACKed an IN packet that we sent */
+ if (csr & AT91_UDP_TXCOMP) {
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_TXCOMP);
+
+ /* write more IN DATA? */
+ if (req && ep0->is_in) {
+ if (handle_ep(ep0))
+ udc->req_pending = 0;
+
+ /*
+ * Ack after:
+ * - last IN DATA packet (including GET_STATUS)
+ * - IN/STATUS for OUT DATA
+ * - IN/STATUS for any zero-length DATA stage
+ * except for the IN DATA case, the host should send
+ * an OUT status later, which we'll ack.
+ */
+ } else {
+ udc->req_pending = 0;
+ __raw_writel(csr, creg);
+
+ /*
+ * SET_ADDRESS takes effect only after the STATUS
+ * (to the original address) gets acked.
+ */
+ if (udc->wait_for_addr_ack) {
+ u32 tmp;
+
+ at91_udp_write(udc, AT91_UDP_FADDR,
+ AT91_UDP_FEN | udc->addr);
+ tmp = at91_udp_read(udc, AT91_UDP_GLB_STAT);
+ tmp &= ~AT91_UDP_FADDEN;
+ if (udc->addr)
+ tmp |= AT91_UDP_FADDEN;
+ at91_udp_write(udc, AT91_UDP_GLB_STAT, tmp);
+
+ udc->wait_for_addr_ack = 0;
+ VDBG(udc, "address %d\n", udc->addr);
+ }
+ }
+ }
+
+ /* OUT packet arrived ... */
+ else if (csr & AT91_UDP_RX_DATA_BK0) {
+ csr |= CLR_FX;
+ csr &= ~(SET_FX | AT91_UDP_RX_DATA_BK0);
+
+ /* OUT DATA stage */
+ if (!ep0->is_in) {
+ if (req) {
+ if (handle_ep(ep0)) {
+ /* send IN/STATUS */
+ PACKET("ep0 in/status\n");
+ csr = __raw_readl(creg);
+ csr &= ~SET_FX;
+ csr |= CLR_FX | AT91_UDP_TXPKTRDY;
+ __raw_writel(csr, creg);
+ udc->req_pending = 0;
+ }
+ } else if (udc->req_pending) {
+ /*
+ * AT91 hardware has a hard time with this
+ * "deferred response" mode for control-OUT
+ * transfers. (For control-IN it's fine.)
+ *
+ * The normal solution leaves OUT data in the
+ * fifo until the gadget driver is ready.
+ * We couldn't do that here without disabling
+ * the IRQ that tells about SETUP packets,
+ * e.g. when the host gets impatient...
+ *
+ * Working around it by copying into a buffer
+ * would almost be a non-deferred response,
+ * except that it wouldn't permit reliable
+ * stalling of the request. Instead, demand
+ * that gadget drivers not use this mode.
+ */
+ DBG(udc, "no control-OUT deferred responses!\n");
+ __raw_writel(csr | AT91_UDP_FORCESTALL, creg);
+ udc->req_pending = 0;
+ }
+
+ /* STATUS stage for control-IN; ack. */
+ } else {
+ PACKET("ep0 out/status ACK\n");
+ __raw_writel(csr, creg);
+
+ /* "early" status stage */
+ if (req)
+ done(ep0, req, 0);
+ }
+ }
+}
+
+static void at91_udc_irq (void *_udc)
+{
+ struct at91_udc *udc = _udc;
+ u32 rescans = 5;
+
+ while (rescans--) {
+ u32 status;
+
+ status = at91_udp_read(udc, AT91_UDP_ISR);
+ if (!status)
+ break;
+
+ /* USB reset irq: not maskable */
+ if (status & AT91_UDP_ENDBUSRES) {
+ at91_udp_write(udc, AT91_UDP_IDR, ~MINIMUS_INTERRUPTUS);
+ /* Atmel code clears this irq twice */
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_ENDBUSRES);
+ VDBG(udc, "end bus reset\n");
+ udc->addr = 0;
+ stop_activity(udc);
+
+ /* enable ep0 */
+ at91_udp_write(udc, AT91_UDP_CSR(0),
+ AT91_UDP_EPEDS | AT91_UDP_EPTYPE_CTRL);
+ udc->gadget.speed = USB_SPEED_FULL;
+ udc->suspended = 0;
+
+ /*
+ * NOTE: this driver keeps clocks off unless the
+ * USB host is present. That saves power, but for
+ * boards that don't support VBUS detection, both
+ * clocks need to be active most of the time.
+ */
+
+ /* host initiated suspend (3+ms bus idle) */
+ } else if (status & AT91_UDP_RXSUSP) {
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXSUSP);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXSUSP);
+ /* VDBG(udc, "bus suspend\n"); */
+ if (udc->suspended)
+ continue;
+ udc->suspended = 1;
+
+ /*
+ * NOTE: when suspending a VBUS-powered device, the
+ * gadget driver should switch into slow clock mode
+ * and then into standby to avoid drawing more than
+ * 500uA power (2500uA for some high-power configs).
+ */
+ if (udc->driver && udc->driver->suspend) {
+ udc->driver->suspend(&udc->gadget);
+ }
+
+ /* host initiated resume */
+ } else if (status & AT91_UDP_RXRSM) {
+ at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
+ at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
+ /* VDBG(udc, "bus resume\n"); */
+ if (!udc->suspended)
+ continue;
+ udc->suspended = 0;
+
+ /*
+ * NOTE: for a VBUS-powered device, the gadget driver
+ * would normally want to switch out of slow clock
+ * mode into normal mode.
+ */
+ if (udc->driver && udc->driver->resume) {
+ udc->driver->resume(&udc->gadget);
+ }
+
+ /* endpoint IRQs are cleared by handling them */
+ } else {
+ int i;
+ unsigned mask = 1;
+ struct at91_ep *ep = &udc->ep[1];
+
+ if (status & mask)
+ handle_ep0(udc);
+ for (i = 1; i < NUM_ENDPOINTS; i++) {
+ mask <<= 1;
+ if (status & mask)
+ handle_ep(ep);
+ ep++;
+ }
+ }
+ }
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct at91_udc controller = {
+ .gadget = {
+ .ops = &at91_udc_ops,
+ .ep0 = &controller.ep[0].ep,
+ .name = driver_name,
+ },
+ .ep[0] = {
+ .ep = {
+ .name = ep0name,
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 8,
+ .int_mask = 1 << 0,
+ },
+ .ep[1] = {
+ .ep = {
+ .name = "ep1",
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .is_pingpong = 1,
+ .maxpacket = 64,
+ .int_mask = 1 << 1,
+ },
+ .ep[2] = {
+ .ep = {
+ .name = "ep2",
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .is_pingpong = 1,
+ .maxpacket = 64,
+ .int_mask = 1 << 2,
+ },
+ .ep[3] = {
+ .ep = {
+ /* could actually do bulk too */
+ .name = "ep3-int",
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .maxpacket = 8,
+ .int_mask = 1 << 3,
+ },
+ .ep[4] = {
+ .ep = {
+ .name = "ep4",
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .is_pingpong = 1,
+ .maxpacket = 256,
+ .int_mask = 1 << 4,
+ },
+ .ep[5] = {
+ .ep = {
+ .name = "ep5",
+ .ops = &at91_ep_ops,
+ },
+ .udc = &controller,
+ .is_pingpong = 1,
+ .maxpacket = 256,
+ .int_mask = 1 << 5,
+ },
+ /* ep6 and ep7 are also reserved (custom silicon might use them) */
+};
+
+static void at91_udc_irq (void *_udc);
+
+static void at91_update_vbus(struct at91_udc *udc, u32 value)
+{
+ if (value == udc->gpio_vbus_val)
+ return;
+
+ if (value)
+ dev_set_param(udc->dev, "vbus", "1");
+ else
+ dev_set_param(udc->dev, "vbus", "0");
+
+ udc->gpio_vbus_val = value;
+}
+
+int usb_gadget_poll(void)
+{
+ struct at91_udc *udc = &controller;
+ u32 value;
+
+ if (!udc->udp_baseaddr)
+ return 0;
+
+ value = gpio_get_value(udc->board.vbus_pin);
+ value ^= udc->board.vbus_active_low;
+
+ if (!value) {
+ at91_update_vbus(udc, value);
+ return 0;
+ }
+ at91_update_vbus(udc, value);
+
+ value = at91_udp_read(udc, AT91_UDP_ISR) & (~(AT91_UDP_SOFINT));
+ if (value)
+ at91_udc_irq(udc);
+
+ return value;
+}
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+ struct at91_udc *udc = &controller;
+ int retval;
+
+ if (!udc->iclk)
+ return -ENODEV;
+
+ if (!driver
+ || driver->speed < USB_SPEED_FULL
+ || !driver->bind
+ || !driver->setup) {
+ DBG(udc, "bad parameter.\n");
+ return -EINVAL;
+ }
+
+ if (udc->driver) {
+ DBG(udc, "UDC already has a gadget driver\n");
+ return -EBUSY;
+ }
+
+ udc->driver = driver;
+ udc->enabled = 1;
+ udc->selfpowered = 1;
+
+ retval = driver->bind(&udc->gadget);
+ if (retval) {
+ DBG(udc, "bind() returned %d\n", retval);
+ udc->driver = NULL;
+ udc->enabled = 0;
+ udc->selfpowered = 0;
+ return retval;
+ }
+
+ pullup(udc, 1);
+
+ DBG(udc, "bound to %s\n", driver->function);
+ return 0;
+}
+EXPORT_SYMBOL (usb_gadget_register_driver);
+
+int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
+{
+ struct at91_udc *udc = &controller;
+
+ if (!driver || driver != udc->driver || !driver->unbind)
+ return -EINVAL;
+
+ udc->enabled = 0;
+ at91_udp_write(udc, AT91_UDP_IDR, ~0);
+ pullup(udc, 0);
+
+ driver->unbind(&udc->gadget);
+ udc->driver = NULL;
+
+ DBG(udc, "unbound from %s\n", driver->function);
+ return 0;
+}
+EXPORT_SYMBOL (usb_gadget_unregister_driver);
+
+/*-------------------------------------------------------------------------*/
+
+static void at91_udc_poller(struct poller_struct *poller)
+{
+ usb_gadget_poll();
+}
+
+static struct poller_struct poller = {
+ .func = at91_udc_poller
+};
+
+static int __init at91udc_probe(struct device_d *dev)
+{
+ struct at91_udc *udc;
+ int retval;
+
+ if (!dev->platform_data) {
+ /* small (so we copy it) but critical! */
+ DBG(udc, "missing platform_data\n");
+ return -ENODEV;
+ }
+
+ /* init software state */
+ udc = &controller;
+ udc->dev = dev;
+ udc->board = *(struct at91_udc_data *) dev->platform_data;
+ udc->enabled = 0;
+
+ /* rm9200 needs manual D+ pullup; off by default */
+ if (cpu_is_at91rm9200()) {
+ if (udc->board.pullup_pin <= 0) {
+ DBG(udc, "no D+ pullup?\n");
+ retval = -ENODEV;
+ goto fail0;
+ }
+ retval = gpio_request(udc->board.pullup_pin, "udc_pullup");
+ if (retval) {
+ DBG(udc, "D+ pullup is busy\n");
+ goto fail0;
+ }
+ gpio_direction_output(udc->board.pullup_pin,
+ udc->board.pullup_active_low);
+ }
+
+ /* newer chips have more FIFO memory than rm9200 */
+ if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) {
+ udc->ep[0].maxpacket = 64;
+ udc->ep[3].maxpacket = 64;
+ udc->ep[4].maxpacket = 512;
+ udc->ep[5].maxpacket = 512;
+ } else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
+ udc->ep[3].maxpacket = 64;
+ } else if (cpu_is_at91sam9263()) {
+ udc->ep[0].maxpacket = 64;
+ udc->ep[3].maxpacket = 64;
+ }
+
+ udc->udp_baseaddr = dev_request_mem_region(dev, 0);
+ if (!udc->udp_baseaddr) {
+ retval = -ENOMEM;
+ goto fail0a;
+ }
+
+ udc_reinit(udc);
+
+ /* get interface and function clocks */
+ udc->iclk = clk_get(dev, "udc_clk");
+ udc->fclk = clk_get(dev, "udpck");
+ if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk)) {
+ DBG(udc, "clocks missing\n");
+ retval = -ENODEV;
+ /* NOTE: we "know" here that refcounts on these are NOPs */
+ goto fail0a;
+ }
+
+ /* don't do anything until we have both gadget driver and VBUS */
+ clk_enable(udc->iclk);
+ at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
+ at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
+ /* Clear all pending interrupts - UDP may be used by bootloader. */
+ at91_udp_write(udc, AT91_UDP_ICR, 0xffffffff);
+ clk_disable(udc->iclk);
+
+ if (udc->board.vbus_pin > 0) {
+ /*
+ * Get the initial state of VBUS - we cannot expect
+ * a pending interrupt.
+ */
+ udc->vbus = at91_get_gpio_value(udc->board.vbus_pin);
+ DBG(udc, "VBUS detection: host:%s \n",
+ udc->vbus ? "present":"absent");
+ } else {
+ DBG(udc, "no VBUS detection, assuming always-on\n");
+ udc->vbus = 1;
+ }
+
+ dev_add_param(dev, "vbus", NULL, NULL, 0);
+ dev_set_param(dev, "vbus", "0");
+
+ poller_register(&poller);
+
+ INFO(udc, "%s version %s\n", driver_name, DRIVER_VERSION);
+ return 0;
+
+fail0a:
+ if (cpu_is_at91rm9200())
+ gpio_free(udc->board.pullup_pin);
+fail0:
+ DBG(udc, "%s probe failed, %d\n", driver_name, retval);
+ return retval;
+}
+
+
+static struct driver_d at91_udc_driver = {
+ .name = driver_name,
+ .probe = at91udc_probe,
+};
+
+static int at91_udc_init(void)
+{
+ register_driver(&at91_udc_driver);
+ return 0;
+}
+device_initcall(at91_udc_init);
diff --git a/drivers/usb/gadget/at91_udc.h b/drivers/usb/gadget/at91_udc.h
new file mode 100644
index 0000000000..e592cc54ff
--- /dev/null
+++ b/drivers/usb/gadget/at91_udc.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004 by Thomas Rathbone, HP Labs
+ * Copyright (C) 2005 by Ivan Kokshaysky
+ * Copyright (C) 2006 by SAN People
+ *
+ * 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.
+ */
+
+#ifndef AT91_UDC_H
+#define AT91_UDC_H
+
+/*
+ * USB Device Port (UDP) registers.
+ * Based on AT91RM9200 datasheet revision E.
+ */
+
+#define AT91_UDP_FRM_NUM 0x00 /* Frame Number Register */
+#define AT91_UDP_NUM (0x7ff << 0) /* Frame Number */
+#define AT91_UDP_FRM_ERR (1 << 16) /* Frame Error */
+#define AT91_UDP_FRM_OK (1 << 17) /* Frame OK */
+
+#define AT91_UDP_GLB_STAT 0x04 /* Global State Register */
+#define AT91_UDP_FADDEN (1 << 0) /* Function Address Enable */
+#define AT91_UDP_CONFG (1 << 1) /* Configured */
+#define AT91_UDP_ESR (1 << 2) /* Enable Send Resume */
+#define AT91_UDP_RSMINPR (1 << 3) /* Resume has been sent */
+#define AT91_UDP_RMWUPE (1 << 4) /* Remote Wake Up Enable */
+
+#define AT91_UDP_FADDR 0x08 /* Function Address Register */
+#define AT91_UDP_FADD (0x7f << 0) /* Function Address Value */
+#define AT91_UDP_FEN (1 << 8) /* Function Enable */
+
+#define AT91_UDP_IER 0x10 /* Interrupt Enable Register */
+#define AT91_UDP_IDR 0x14 /* Interrupt Disable Register */
+#define AT91_UDP_IMR 0x18 /* Interrupt Mask Register */
+
+#define AT91_UDP_ISR 0x1c /* Interrupt Status Register */
+#define AT91_UDP_EP(n) (1 << (n)) /* Endpoint Interrupt Status */
+#define AT91_UDP_RXSUSP (1 << 8) /* USB Suspend Interrupt Status */
+#define AT91_UDP_RXRSM (1 << 9) /* USB Resume Interrupt Status */
+#define AT91_UDP_EXTRSM (1 << 10) /* External Resume Interrupt Status [AT91RM9200 only] */
+#define AT91_UDP_SOFINT (1 << 11) /* Start of Frame Interrupt Status */
+#define AT91_UDP_ENDBUSRES (1 << 12) /* End of Bus Reset Interrupt Status */
+#define AT91_UDP_WAKEUP (1 << 13) /* USB Wakeup Interrupt Status [AT91RM9200 only] */
+
+#define AT91_UDP_ICR 0x20 /* Interrupt Clear Register */
+#define AT91_UDP_RST_EP 0x28 /* Reset Endpoint Register */
+
+#define AT91_UDP_CSR(n) (0x30+((n)*4)) /* Endpoint Control/Status Registers 0-7 */
+#define AT91_UDP_TXCOMP (1 << 0) /* Generates IN packet with data previously written in DPR */
+#define AT91_UDP_RX_DATA_BK0 (1 << 1) /* Receive Data Bank 0 */
+#define AT91_UDP_RXSETUP (1 << 2) /* Send STALL to the host */
+#define AT91_UDP_STALLSENT (1 << 3) /* Stall Sent / Isochronous error (Isochronous endpoints) */
+#define AT91_UDP_TXPKTRDY (1 << 4) /* Transmit Packet Ready */
+#define AT91_UDP_FORCESTALL (1 << 5) /* Force Stall */
+#define AT91_UDP_RX_DATA_BK1 (1 << 6) /* Receive Data Bank 1 */
+#define AT91_UDP_DIR (1 << 7) /* Transfer Direction */
+#define AT91_UDP_EPTYPE (7 << 8) /* Endpoint Type */
+#define AT91_UDP_EPTYPE_CTRL (0 << 8)
+#define AT91_UDP_EPTYPE_ISO_OUT (1 << 8)
+#define AT91_UDP_EPTYPE_BULK_OUT (2 << 8)
+#define AT91_UDP_EPTYPE_INT_OUT (3 << 8)
+#define AT91_UDP_EPTYPE_ISO_IN (5 << 8)
+#define AT91_UDP_EPTYPE_BULK_IN (6 << 8)
+#define AT91_UDP_EPTYPE_INT_IN (7 << 8)
+#define AT91_UDP_DTGLE (1 << 11) /* Data Toggle */
+#define AT91_UDP_EPEDS (1 << 15) /* Endpoint Enable/Disable */
+#define AT91_UDP_RXBYTECNT (0x7ff << 16) /* Number of bytes in FIFO */
+
+#define AT91_UDP_FDR(n) (0x50+((n)*4)) /* Endpoint FIFO Data Registers 0-7 */
+
+#define AT91_UDP_TXVC 0x74 /* Transceiver Control Register */
+#define AT91_UDP_TXVC_TXVDIS (1 << 8) /* Transceiver Disable */
+#define AT91_UDP_TXVC_PUON (1 << 9) /* PullUp On [AT91SAM9260 only] */
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * controller driver data structures
+ */
+
+#define NUM_ENDPOINTS 6
+
+/*
+ * hardware won't disable bus reset, or resume while the controller
+ * is suspended ... watching suspend helps keep the logic symmetric.
+ */
+#define MINIMUS_INTERRUPTUS \
+ (AT91_UDP_ENDBUSRES | AT91_UDP_RXRSM | AT91_UDP_RXSUSP)
+
+struct at91_ep {
+ struct usb_ep ep;
+ struct list_head queue;
+ struct at91_udc *udc;
+ void __iomem *creg;
+
+ unsigned maxpacket:16;
+ u8 int_mask;
+ unsigned is_pingpong:1;
+
+ unsigned stopped:1;
+ unsigned is_in:1;
+ unsigned is_iso:1;
+ unsigned fifo_bank:1;
+
+ const struct usb_endpoint_descriptor
+ *desc;
+};
+
+/*
+ * driver is non-SMP, and just blocks IRQs whenever it needs
+ * access protection for chip registers or driver state
+ */
+struct at91_udc {
+ struct usb_gadget gadget;
+ struct at91_ep ep[NUM_ENDPOINTS];
+ struct usb_gadget_driver *driver;
+ unsigned vbus:1;
+ unsigned enabled:1;
+ unsigned clocked:1;
+ unsigned suspended:1;
+ unsigned req_pending:1;
+ unsigned wait_for_addr_ack:1;
+ unsigned wait_for_config_ack:1;
+ unsigned selfpowered:1;
+ unsigned active_suspend:1;
+ u8 addr;
+ u32 gpio_vbus_val;
+ struct at91_udc_data board;
+ struct clk *iclk, *fclk;
+ struct device_d *dev;
+ void __iomem *udp_baseaddr;
+ int udp_irq;
+};
+
+static inline struct at91_udc *to_udc(struct usb_gadget *g)
+{
+ return container_of(g, struct at91_udc, gadget);
+}
+
+struct at91_request {
+ struct usb_request req;
+ struct list_head queue;
+};
+
+/*-------------------------------------------------------------------------*/
+
+#ifdef VERBOSE_DEBUG
+# define VDBG DBG
+#else
+# define VDBG(stuff...) do{}while(0)
+#endif
+
+#ifdef PACKET_TRACE
+# define PACKET VDBG
+#else
+# define PACKET(stuff...) do{}while(0)
+#endif
+
+#define ERR(udc, stuff...) dev_err((udc)->dev, ##stuff)
+#define WARNING(udc, stuff...) dev_warn((udc)->dev, ##stuff)
+#define INFO(udc, stuff...) dev_info((udc)->dev, ##stuff)
+#define DBG(udc, stuff...) dev_dbg((udc)->dev, ##stuff)
+
+#endif
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index 0a0d244106..f26c1e43d0 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -67,6 +67,7 @@ static int dfualt;
static int dfufd = -EINVAL;;
static struct usb_dfu_dev *dfu_devs;
static int dfu_num_alt;
+static int dfudetach;
/* USB DFU functional descriptor */
static struct usb_dfu_func_descriptor usb_dfu_func = {
@@ -204,6 +205,9 @@ static int dfu_status(struct usb_function *f, const struct usb_ctrlrequest *ctrl
dstat->bStatus = dfu->dfu_status;
dstat->bState = dfu->dfu_state;
dstat->iString = 0;
+ dstat->bwPollTimeout[0] = 10;
+ dstat->bwPollTimeout[1] = 0;
+ dstat->bwPollTimeout[2] = 0;
return sizeof(*dstat);
}
@@ -425,6 +429,8 @@ static int dfu_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
* least the Linux USB stack likes to send a number of resets
* in a row :( */
dfu->dfu_state = DFU_STATE_dfuMANIFEST_WAIT_RST;
+ value = 0;
+ dfudetach = 1;
break;
default:
dfu->dfu_state = DFU_STATE_dfuERROR;
@@ -690,11 +696,12 @@ int usb_dfu_register(struct usb_dfu_pdata *pdata)
while (1) {
usb_gadget_poll();
- if (ctrlc())
+ if (ctrlc() || dfudetach)
goto out;
}
out:
+ dfudetach = 0;
usb_composite_unregister(&dfu_driver);
return 0;
diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c
index 43b4992560..218aed219c 100644
--- a/drivers/usb/gadget/f_acm.c
+++ b/drivers/usb/gadget/f_acm.c
@@ -407,7 +407,7 @@ static void acm_disable(struct usb_function *f)
{
struct f_acm *acm = func_to_acm(f);
- printf("acm ttyGS%d deactivated\n", acm->port_num);
+ VDBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num);
gserial_disconnect(&acm->port);
usb_ep_disable(acm->notify);
acm->notify->driver_data = NULL;
@@ -473,7 +473,7 @@ static int acm_notify_serial_state(struct f_acm *acm)
int status;
if (acm->notify_req) {
- printf("acm ttyGS%d serial state %04x\n",
+ VDBG(cdev, "acm ttyGS%d serial state %04x\n",
acm->port_num, acm->serial_state);
status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE,
0, &acm->serial_state, sizeof(acm->serial_state));
diff --git a/drivers/usb/gadget/fsl_udc.c b/drivers/usb/gadget/fsl_udc.c
index fbc6e4ecc7..5b64ec2011 100644
--- a/drivers/usb/gadget/fsl_udc.c
+++ b/drivers/usb/gadget/fsl_udc.c
@@ -6,6 +6,7 @@
#include <usb/gadget.h>
#include <usb/fsl_usb2.h>
#include <io.h>
+#include <poller.h>
#include <asm/byteorder.h>
#include <asm/mmu.h>
@@ -233,6 +234,7 @@ struct usb_dr_device {
#define USB_MODE_CTRL_MODE_DEVICE 0x00000002
#define USB_MODE_CTRL_MODE_HOST 0x00000003
#define USB_MODE_CTRL_MODE_RSV 0x00000001
+#define USB_MODE_CTRL_MODE_MASK 0x00000003
#define USB_MODE_SETUP_LOCK_OFF 0x00000008
#define USB_MODE_STREAM_DISABLE 0x00000010
/* Endpoint Flush Register */
@@ -603,7 +605,8 @@ static void nuke(struct fsl_ep *ep, int status)
static int dr_controller_setup(struct fsl_udc *udc)
{
- unsigned int tmp, portctrl;
+ unsigned int tmp, portctrl, ep_num;
+ unsigned int max_no_of_ep;
uint64_t to;
/* Config PHY interface */
@@ -647,6 +650,7 @@ static int dr_controller_setup(struct fsl_udc *udc)
/* Set the controller as device mode */
tmp = readl(&dr_regs->usbmode);
+ tmp &= ~USB_MODE_CTRL_MODE_MASK; /* clear mode bits */
tmp |= USB_MODE_CTRL_MODE_DEVICE;
/* Disable Setup Lockout */
tmp |= USB_MODE_SETUP_LOCK_OFF;
@@ -659,6 +663,14 @@ static int dr_controller_setup(struct fsl_udc *udc)
tmp &= USB_EP_LIST_ADDRESS_MASK;
writel(tmp, &dr_regs->endpointlistaddr);
+ max_no_of_ep = (0x0000001F & readl(&dr_regs->dccparams));
+ for (ep_num = 1; ep_num < max_no_of_ep; ep_num++) {
+ tmp = readl(&dr_regs->endptctrl[ep_num]);
+ tmp &= ~(EPCTRL_TX_TYPE | EPCTRL_RX_TYPE);
+ tmp |= (EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT)
+ | (EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT);
+ writel(tmp, &dr_regs->endptctrl[ep_num]);
+ }
VDBG("vir[qh_base] is %p phy[qh_base] is 0x%8x reg is 0x%8x",
udc->ep_qh, (int)tmp,
readl(&dr_regs->endpointlistaddr));
@@ -725,12 +737,14 @@ static void dr_ep_setup(unsigned char ep_num, unsigned char dir,
if (ep_num)
tmp_epctrl |= EPCTRL_TX_DATA_TOGGLE_RST;
tmp_epctrl |= EPCTRL_TX_ENABLE;
+ tmp_epctrl &= ~EPCTRL_TX_TYPE;
tmp_epctrl |= ((unsigned int)(ep_type)
<< EPCTRL_TX_EP_TYPE_SHIFT);
} else {
if (ep_num)
tmp_epctrl |= EPCTRL_RX_DATA_TOGGLE_RST;
tmp_epctrl |= EPCTRL_RX_ENABLE;
+ tmp_epctrl &= ~EPCTRL_RX_TYPE;
tmp_epctrl |= ((unsigned int)(ep_type)
<< EPCTRL_RX_EP_TYPE_SHIFT);
}
@@ -887,7 +901,7 @@ static int fsl_ep_enable(struct usb_ep *_ep,
case USB_ENDPOINT_XFER_ISOC:
/* Calculate transactions needed for high bandwidth iso */
mult = (unsigned char)(1 + ((max >> 11) & 0x03));
- max = max & 0x8ff; /* bit 0~10 */
+ max = max & 0x7ff; /* bit 0~10 */
/* 3 transactions at most */
if (mult > 3)
goto en_done;
@@ -924,7 +938,6 @@ static int fsl_ep_enable(struct usb_ep *_ep,
(desc->bEndpointAddress & USB_DIR_IN)
? "in" : "out", max);
en_done:
- printf("%s: %d\n", __func__, retval);
return retval;
}
@@ -948,10 +961,13 @@ static int fsl_ep_disable(struct usb_ep *_ep)
/* disable ep on controller */
ep_num = ep_index(ep);
epctrl = readl(&dr_regs->endptctrl[ep_num]);
- if (ep_is_in(ep))
- epctrl &= ~EPCTRL_TX_ENABLE;
- else
- epctrl &= ~EPCTRL_RX_ENABLE;
+ if (ep_is_in(ep)) {
+ epctrl &= ~(EPCTRL_TX_ENABLE | EPCTRL_TX_TYPE);
+ epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_TX_EP_TYPE_SHIFT;
+ } else {
+ epctrl &= ~(EPCTRL_RX_ENABLE | EPCTRL_TX_TYPE);
+ epctrl |= EPCTRL_EP_TYPE_BULK << EPCTRL_RX_EP_TYPE_SHIFT;
+ }
writel(epctrl, &dr_regs->endptctrl[ep_num]);
udc = (struct fsl_udc *)ep->udc;
@@ -1921,7 +1937,7 @@ int usb_gadget_poll(void)
/* Disable ISR for OTG host mode */
if (udc->stopped)
- return 0;
+ return -EIO;
irq_src = readl(&dr_regs->usbsts) & readl(&dr_regs->usbintr);
/* Clear notification bits */
@@ -1999,7 +2015,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver)
/* bind udc driver to gadget driver */
retval = driver->bind(&udc_controller->gadget);
if (retval) {
- VDBG("bind to %s --> %d", driver->driver.name, retval);
+ VDBG("bind to gadget --> %d", retval);
udc_controller->driver = NULL;
goto out;
}
@@ -2231,6 +2247,15 @@ static int __init struct_ep_setup(struct fsl_udc *udc, unsigned char index,
return 0;
}
+static void fsl_udc_poller(struct poller_struct *poller)
+{
+ usb_gadget_poll();
+}
+
+static struct poller_struct poller = {
+ .func = fsl_udc_poller
+};
+
static int fsl_udc_probe(struct device_d *dev)
{
int ret, i;
@@ -2293,6 +2318,8 @@ static int fsl_udc_probe(struct device_d *dev)
struct_ep_setup(udc_controller, i * 2 + 1, name, 1);
}
+ poller_register(&poller);
+
return 0;
err_out:
return ret;
diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c
index f6a712b1c4..98a501b891 100644
--- a/drivers/usb/gadget/serial.c
+++ b/drivers/usb/gadget/serial.c
@@ -4,6 +4,7 @@
#include <usb/ch9.h>
#include <usb/gadget.h>
#include <usb/composite.h>
+#include <usb/usbserial.h>
#include <asm/byteorder.h>
#include "u_serial.h"
@@ -52,7 +53,9 @@ static struct usb_gadget_strings *dev_strings[] = {
};
static int use_acm = 1;
+#ifdef HAVE_OBEX
static int use_obex = 0;
+#endif
static unsigned n_ports = 1;
static int serial_bind_config(struct usb_configuration *c)
@@ -63,8 +66,10 @@ static int serial_bind_config(struct usb_configuration *c)
for (i = 0; i < n_ports && status == 0; i++) {
if (use_acm)
status = acm_bind_config(c, i);
+#ifdef HAVE_OBEX
else if (use_obex)
status = obex_bind_config(c, i);
+#endif
else
status = gser_bind_config(c, i);
}
@@ -100,7 +105,7 @@ static int gs_bind(struct usb_composite_dev *cdev)
int gcnum;
struct usb_gadget *gadget = cdev->gadget;
int status;
-printf("%s\n", __func__);
+
status = gserial_setup(cdev->gadget, n_ports);
if (status < 0)
return status;
@@ -174,24 +179,56 @@ static struct usb_composite_driver gserial_driver = {
.bind = gs_bind,
};
-static int __init gserial_init(void)
+int usb_serial_register(struct usb_serial_pdata *pdata)
{
/* We *could* export two configs; that'd be much cleaner...
* but neither of these product IDs was defined that way.
*/
+
+ /*
+ * PXA CPU suffer a silicon bug which prevents them from being a
+ * compound device, forbiding the ACM configurations.
+ */
+#ifdef CONFIG_ARCH_PXA2XX
+ use_acm = 0;
+#endif
+ switch (pdata->mode) {
+ case 1:
+#ifdef HAVE_OBEX
+ use_obex = 1;
+#endif
+ use_acm = 0;
+ break;
+ case 2:
+#ifdef HAVE_OBEX
+ use_obex = 1;
+#endif
+ use_acm = 0;
+ break;
+ default:
+#ifdef HAVE_OBEX
+ use_obex = 0;
+#endif
+ use_acm = 1;
+ }
+
if (use_acm) {
serial_config_driver.label = "CDC ACM config";
serial_config_driver.bConfigurationValue = 2;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_PRODUCT_ID);
- } else if (use_obex) {
+ }
+#ifdef HAVE_OBEX
+ else if (use_obex) {
serial_config_driver.label = "CDC OBEX config";
serial_config_driver.bConfigurationValue = 3;
device_desc.bDeviceClass = USB_CLASS_COMM;
device_desc.idProduct =
cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID);
- } else {
+ }
+#endif
+ else {
serial_config_driver.label = "Generic Serial config";
serial_config_driver.bConfigurationValue = 1;
device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC;
@@ -199,9 +236,17 @@ static int __init gserial_init(void)
cpu_to_le16(GS_PRODUCT_ID);
}
strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label;
+ if (pdata->idVendor)
+ device_desc.idVendor = pdata->idVendor;
+ if (pdata->idProduct)
+ device_desc.idProduct = pdata->idProduct;
+ strings_dev[STRING_MANUFACTURER_IDX].s = pdata->manufacturer;
+ strings_dev[STRING_PRODUCT_IDX].s = pdata->productname;
return usb_composite_register(&gserial_driver);
}
-late_initcall(gserial_init);
-
+void usb_serial_unregister(void)
+{
+ usb_composite_unregister(&gserial_driver);
+}
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 49aedc23ef..e310c3ae1d 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -20,6 +20,7 @@
#include <common.h>
#include <usb/cdc.h>
#include <kfifo.h>
+#include <clock.h>
#include "u_serial.h"
@@ -107,8 +108,6 @@ static unsigned n_ports;
#define GS_CLOSE_TIMEOUT 15 /* seconds */
-
-
#ifdef VERBOSE_DEBUG
#define pr_vdebug(fmt, arg...) \
pr_debug(fmt, ##arg)
@@ -370,6 +369,7 @@ static void serial_putc(struct console_device *cdev, char c)
struct usb_ep *in;
struct usb_request *req;
int status;
+ uint64_t to;
if (list_empty(pool))
return;
@@ -382,8 +382,12 @@ static void serial_putc(struct console_device *cdev, char c)
*(unsigned char *)req->buf = c;
status = usb_ep_queue(in, req);
- while (status >= 0 && list_empty(pool))
+ to = get_time_ns();
+ while (status >= 0 && list_empty(pool)) {
status = usb_gadget_poll();
+ if (is_timeout(to, 300 * MSECOND))
+ break;
+ }
}
static int serial_tstc(struct console_device *cdev)
@@ -399,11 +403,16 @@ static int serial_getc(struct console_device *cdev)
struct gs_port *port = container_of(cdev,
struct gs_port, cdev);
unsigned char ch;
+ uint64_t to;
if (!port->port_usb)
return -EIO;
- while (kfifo_getc(port->recv_fifo, &ch))
+ to = get_time_ns();
+ while (kfifo_getc(port->recv_fifo, &ch)) {
usb_gadget_poll();
+ if (is_timeout(to, 300 * MSECOND))
+ break;
+ }
return ch;
}
@@ -420,8 +429,6 @@ int gserial_connect(struct gserial *gser, u8 port_num)
int status;
struct console_device *cdev;
- printf("%s %p %d\n", __func__, gser, port_num);
-
/* we "know" gserial_cleanup() hasn't been called */
port = ports[port_num].port;
@@ -451,7 +458,7 @@ int gserial_connect(struct gserial *gser, u8 port_num)
port->recv_fifo = kfifo_alloc(1024);
- printf("gserial_connect: start ttyGS%d\n", port->port_num);
+ /*printf("gserial_connect: start ttyGS%d\n", port->port_num);*/
gs_start_io(port);
if (gser->connect)
gser->connect(gser);
@@ -508,7 +515,6 @@ void gserial_disconnect(struct gserial *gser)
struct gs_port *port = gser->ioport;
struct console_device *cdev;
- printf("%s\n", __func__);
if (!port)
return;
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index 96e09e28a0..439d8ebbb4 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -3,6 +3,7 @@ config USB_EHCI
config USB_EHCI_OMAP
depends on ARCH_OMAP3
+ depends on USB_TWL4030
bool "OMAP EHCI driver"
config USB_OHCI
diff --git a/drivers/usb/otg/twl4030.c b/drivers/usb/otg/twl4030.c
index 40771699ea..123f0a52ac 100644
--- a/drivers/usb/otg/twl4030.c
+++ b/drivers/usb/otg/twl4030.c
@@ -118,10 +118,10 @@ static void twl4030_usb_ldo_init(void)
twl4030_reg_write(twl4030, TWL4030_PM_RECEIVER_VUSB1V8_TYPE, 0x00);
/* disable access to power configuration registers */
- twl4030_reg_write(twl4030, TWL4030_PM_MASTER_PROTECT_KEY, 0x0 );
-
- twl4030_reg_write(twl4030, TWL4030_BASEADD_LED, 0x33); /* FIXME *need to enable LED to get USB power? */
+ twl4030_reg_write(twl4030, TWL4030_PM_MASTER_PROTECT_KEY, 0x0);
+ /* FIXME *need to enable LED to get USB power? */
+ twl4030_reg_write(twl4030, TWL4030_BASEADD_LED, 0x33);
}
static void twl4030_phy_power(void)
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index df2157eec7..4a05af99d8 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -27,7 +27,7 @@ config DRIVER_VIDEO_STM
Say 'Y' here to enable framebuffer and splash screen support for
i.MX23 and i.MX28 based systems.
-config DRIVER_VIDEO_S3C
+config DRIVER_VIDEO_S3C24XX
bool "S3C244x framebuffer driver"
depends on ARCH_S3C24xx
help
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index 123c46f588..913c78d92b 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -3,5 +3,5 @@ obj-$(CONFIG_VIDEO) += fb.o
obj-$(CONFIG_DRIVER_VIDEO_STM) += stm.o
obj-$(CONFIG_DRIVER_VIDEO_IMX) += imx.o
obj-$(CONFIG_DRIVER_VIDEO_IMX_IPU) += imx-ipu-fb.o
-obj-$(CONFIG_DRIVER_VIDEO_S3C) += s3c.o
+obj-$(CONFIG_DRIVER_VIDEO_S3C24XX) += s3c24xx.o
obj-$(CONFIG_DRIVER_VIDEO_PXA) += pxa.o
diff --git a/drivers/video/imx.c b/drivers/video/imx.c
index 7ffbcb550b..452e558cfe 100644
--- a/drivers/video/imx.c
+++ b/drivers/video/imx.c
@@ -303,6 +303,14 @@ static int imxfb_activate_var(struct fb_info *info)
unsigned long long tmp;
struct imxfb_info *fbi = info->priv;
u32 pcr;
+ int i;
+
+ for (i = 0; i < info->num_modes; i++) {
+ if (!strcmp(fbi->mode[i].mode.name, mode->name)) {
+ fbi->pcr = fbi->mode[i].pcr;
+ break;
+ }
+ }
/* physical screen start address */
writel(VPW_VPW(mode->xres * info->bits_per_pixel / 8 / 4),
@@ -390,6 +398,7 @@ static struct fb_ops imxfb_ops = {
.fb_setcolreg = imxfb_setcolreg,
.fb_enable = imxfb_enable_controller,
.fb_disable = imxfb_disable_controller,
+ .fb_activate_var = imxfb_activate_var,
};
#ifdef CONFIG_IMXFB_DRIVER_VIDEO_IMX_OVERLAY
@@ -524,7 +533,8 @@ static int imxfb_probe(struct device_d *dev)
struct imxfb_info *fbi;
struct fb_info *info;
struct imx_fb_platform_data *pdata = dev->platform_data;
- int ret;
+ struct fb_videomode *mode_list;
+ int ret, i;
if (!pdata)
return -ENODEV;
@@ -542,6 +552,14 @@ static int imxfb_probe(struct device_d *dev)
writel(readl(IMX_CCM_BASE + CCM_CGCR1) & ~(1 << 29),
IMX_CCM_BASE + CCM_CGCR1);
#endif
+ if (!pdata->num_modes) {
+ dev_err(dev, "no modes. bailing out\n");
+ return -EINVAL;
+ }
+
+ mode_list = xzalloc(sizeof(*mode_list) * pdata->num_modes);
+ for (i = 0; i < pdata->num_modes; i++)
+ mode_list[i] = pdata->mode[i].mode;
fbi = xzalloc(sizeof(*fbi));
info = &fbi->info;
@@ -555,6 +573,8 @@ static int imxfb_probe(struct device_d *dev)
fbi->enable = pdata->enable;
fbi->dev = dev;
info->priv = fbi;
+ info->mode_list = mode_list;
+ info->num_modes = pdata->num_modes;
info->mode = &pdata->mode->mode;
info->xres = pdata->mode->mode.xres;
info->yres = pdata->mode->mode.yres;
diff --git a/drivers/video/s3c.c b/drivers/video/s3c24xx.c
index b17aeb69ff..564ccbd6f4 100644
--- a/drivers/video/s3c.c
+++ b/drivers/video/s3c24xx.c
@@ -30,9 +30,8 @@
#include <malloc.h>
#include <errno.h>
#include <io.h>
-#include <mach/gpio.h>
-#include <mach/s3c24xx-generic.h>
-#include <mach/fb.h>
+#include <mach/s3c-generic.h>
+#include <mach/s3c24xx-fb.h>
#define LCDCON1 0x00
# define PNRMODE(x) (((x) & 3) << 5)
@@ -227,7 +226,7 @@ static int s3cfb_activate_var(struct fb_info *fb_info)
/* ensure video output is _off_ */
writel(0x00000000, fbi->base + LCDCON1);
- hclk = s3c24xx_get_hclk() / 1000U; /* hclk in kHz */
+ hclk = s3c_get_hclk() / 1000U; /* hclk in kHz */
div = hclk / PICOS2KHZ(mode->pixclock);
if (div < 3)
div = 3;
@@ -339,7 +338,7 @@ static void s3cfb_info(struct device_d *hw_dev)
addr3 = readl(fbi->base + LCDSADDR3);
printf(" Video hardware info:\n");
- printf(" Video clock is running at %u Hz\n", s3c24xx_get_hclk() / ((GET_CLKVAL(con1) + 1) * 2));
+ printf(" Video clock is running at %u Hz\n", s3c_get_hclk() / ((GET_CLKVAL(con1) + 1) * 2));
printf(" Video memory bank starts at 0x%08X\n", GET_LCDBANK(addr1) << 22);
printf(" Video memory bank offset: 0x%08X\n", GET_LCDBASEU(addr1));
printf(" Video memory end: 0x%08X\n", GET_LCDBASEU(addr2));
diff --git a/fs/devfs-core.c b/fs/devfs-core.c
index 9bc3126d6b..5f22ce72f9 100644
--- a/fs/devfs-core.c
+++ b/fs/devfs-core.c
@@ -63,7 +63,7 @@ struct cdev *cdev_open(const char *name, unsigned long flags)
return NULL;
if (cdev->ops->open) {
- ret = cdev->ops->open(cdev);
+ ret = cdev->ops->open(cdev, flags);
if (ret)
return NULL;
}
diff --git a/fs/devfs.c b/fs/devfs.c
index 66f7ca4162..2e70cc52fa 100644
--- a/fs/devfs.c
+++ b/fs/devfs.c
@@ -116,7 +116,7 @@ static int devfs_open(struct device_d *_dev, FILE *f, const char *filename)
f->inode = cdev;
if (cdev->ops->open) {
- ret = cdev->ops->open(cdev);
+ ret = cdev->ops->open(cdev, f->flags);
if (ret)
return ret;
}
diff --git a/include/boot.h b/include/boot.h
index b67e034801..a17bf25a4c 100644
--- a/include/boot.h
+++ b/include/boot.h
@@ -2,25 +2,73 @@
#define __BOOT_H
#include <image.h>
+#include <filetype.h>
+#include <of.h>
#include <linux/list.h>
struct image_data {
- struct image_handle *os;
- struct image_handle *initrd;
- const char *oftree;
- int verify;
+ /* simplest case. barebox has already loaded the os here */
+ struct resource *os_res;
+
+ /* if os is an uImage this will be provided */
+ struct uimage_handle *os;
+ int os_num;
+
+ /* otherwise only the filename will be provided */
+ char *os_file;
+
+ /*
+ * The address the user wants to load the os image to.
+ * May be UIMAGE_INVALID_ADDRESS to indicate that the
+ * user has not specified any address. In this case the
+ * handler may choose a suitable address
+ */
+ unsigned long os_address;
+
+ /* entry point to the os. relative to the start of the image */
+ unsigned long os_entry;
+
+ /* if initrd is already loaded this resource will be !NULL */
+ struct resource *initrd_res;
+
+ /* if initrd is an uImage this will be provided */
+ struct uimage_handle *initrd;
+ int initrd_num;
+
+ /* otherwise only the filename will be provided */
+ char *initrd_file;
+
unsigned long initrd_address;
- unsigned long initrd_size;
+
+ struct fdt_header *oftree;
+
+ int verify;
+ int verbose;
};
struct image_handler {
+ const char *name;
+
struct list_head list;
- int image_type;
+ int ih_os;
+
+ enum filetype filetype;
int (*bootm)(struct image_data *data);
};
int register_image_handler(struct image_handler *handle);
-#endif /* __BOOT_H */
+#ifdef CONFIG_CMD_BOOTM_VERBOSE
+static inline int bootm_verbose(struct image_data *data)
+{
+ return data->verbose;
+}
+#else
+static inline int bootm_verbose(struct image_data *data)
+{
+ return 0;
+}
+#endif
+#endif /* __BOOT_H */
diff --git a/include/common.h b/include/common.h
index d594e630e4..2f37dd845f 100644
--- a/include/common.h
+++ b/include/common.h
@@ -81,8 +81,6 @@
})
#endif
-typedef void (interrupt_handler_t)(void *);
-
#include <asm/barebox.h> /* boot information for Linux kernel */
/*
@@ -93,8 +91,6 @@ void reginfo(void);
void __noreturn hang (void);
void __noreturn panic(const char *fmt, ...);
-/* */
-void initdram (int);
char *size_human_readable(ulong size);
/* common/main.c */
@@ -133,7 +129,6 @@ struct memarea_info {
unsigned long flags;
};
-int spec_str_to_info(const char *str, struct memarea_info *info);
int parse_area_spec(const char *str, ulong *start, ulong *size);
/* Just like simple_strtoul(), but this one honors a K/M/G suffix */
diff --git a/include/driver.h b/include/driver.h
index bbe724833f..1751d3cc85 100644
--- a/include/driver.h
+++ b/include/driver.h
@@ -232,7 +232,7 @@ static inline struct device_d *add_ns16550_device(int id, resource_size_t start,
IORESOURCE_MEM | flags, pdata);
}
-#ifdef CONFIG_DRIVER_NET_DM9000
+#ifdef CONFIG_DRIVER_NET_DM9K
struct device_d *add_dm9000_device(int id, resource_size_t base,
resource_size_t data, int flags, void *pdata);
#else
@@ -366,7 +366,7 @@ struct file_operations {
int (*ioctl)(struct cdev*, int, void *);
off_t (*lseek)(struct cdev*, off_t);
- int (*open)(struct cdev*);
+ int (*open)(struct cdev*, unsigned long flags);
int (*close)(struct cdev*);
int (*flush)(struct cdev*);
int (*erase)(struct cdev*, size_t count, unsigned long offset);
diff --git a/include/filetype.h b/include/filetype.h
index 64d32ef8b0..88f31dfe3e 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -14,6 +14,7 @@ enum filetype {
filetype_jffs2,
filetype_gzip,
filetype_bzip2,
+ filetype_oftree,
};
const char *file_type_to_string(enum filetype f);
diff --git a/include/ft_build.h b/include/ft_build.h
deleted file mode 100644
index 1fb6b4d11e..0000000000
--- a/include/ft_build.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * OF Flat tree builder
- *
- */
-
-#ifndef FT_BUILD_H
-#define FT_BUILD_H
-
-#include <linux/types.h>
-#include <asm/barebox.h>
-
-/* Definitions used by the flattened device tree */
-#define OF_DT_HEADER 0xd00dfeed /* marker */
-#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
-#define OF_DT_END_NODE 0x2 /* End node */
-#define OF_DT_PROP 0x3 /* Property: name off, size,
- * content */
-#define OF_DT_NOP 0x4 /* nop */
-#define OF_DT_END 0x9
-
-#define OF_DT_VERSION 0x10
-
-struct boot_param_header {
- u32 magic; /* magic word OF_DT_HEADER */
- u32 totalsize; /* total size of DT block */
- u32 off_dt_struct; /* offset to structure */
- u32 off_dt_strings; /* offset to strings */
- u32 off_mem_rsvmap; /* offset to memory reserve map */
- u32 version; /* format version */
- u32 last_comp_version; /* last compatible version */
- /* version 2 fields below */
- u32 boot_cpuid_phys; /* Physical CPU id we're booting on */
- /* version 3 fields below */
- u32 dt_strings_size; /* size of the DT strings block */
-};
-
-struct ft_cxt {
- struct boot_param_header *bph;
- u8 *p_rsvmap;
- u8 *p_start; /* pointer to beginning of dt_struct */
- u8 *p_end; /* pointer to end of dt_strings */
- u8 *p; /* pointer to end of dt_struct and beginning of dt_strings */
-};
-
-void ft_begin_node(struct ft_cxt *cxt, const char *name);
-void ft_init_cxt(struct ft_cxt *cxt, void *blob);
-void ft_end_node(struct ft_cxt *cxt);
-
-void ft_end_tree(struct ft_cxt *cxt);
-void ft_finalize_tree(struct ft_cxt *cxt);
-
-void ft_nop(struct ft_cxt *cxt);
-void ft_prop(struct ft_cxt *cxt, const char *name, const void *data, int sz);
-void ft_prop_str(struct ft_cxt *cxt, const char *name, const char *str);
-void ft_prop_int(struct ft_cxt *cxt, const char *name, int val);
-void ft_begin(struct ft_cxt *cxt, void *blob, int max_size);
-void ft_add_rsvmap(struct ft_cxt *cxt, u64 physaddr, u64 size);
-
-void ft_setup(void *blob, bd_t * bd, ulong initrd_start, ulong initrd_end);
-
-void ft_dump_blob(const void *bphp);
-void ft_merge_blob(struct ft_cxt *cxt, void *blob);
-void *ft_get_prop(void *bphp, const char *propname, int *szp);
-
-void ft_board_setup(void *blob, bd_t *bd);
-void ft_cpu_setup(void *blob, bd_t *bd);
-void ft_pci_setup(void *blob, bd_t *bd);
-
-#endif
diff --git a/include/image.h b/include/image.h
index f3a9949e54..35ff01b1c0 100644
--- a/include/image.h
+++ b/include/image.h
@@ -188,20 +188,6 @@ 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;
-};
-
#if defined(CONFIG_CMD_BOOTM_SHOW_TYPE) || !defined(__BAREBOX__)
const char *image_get_os_name(uint8_t os);
const char *image_get_arch_name(uint8_t arch);
@@ -232,121 +218,34 @@ static inline const char *image_get_comp_name(uint8_t comp)
#define uimage_to_cpu(x) be32_to_cpu(x)
#define cpu_to_uimage(x) cpu_to_be32(x)
-static inline uint32_t image_get_header_size(void)
-{
- return sizeof(image_header_t);
-}
-
-#define image_get_hdr_u32(x) \
-static inline uint32_t image_get_##x(const image_header_t *hdr) \
-{ \
- return uimage_to_cpu(hdr->ih_##x); \
-}
-
-image_get_hdr_u32(magic); /* image_get_magic */
-image_get_hdr_u32(hcrc); /* image_get_hcrc */
-image_get_hdr_u32(time); /* image_get_time */
-image_get_hdr_u32(size); /* image_get_size */
-image_get_hdr_u32(load); /* image_get_load */
-image_get_hdr_u32(ep); /* image_get_ep */
-image_get_hdr_u32(dcrc); /* image_get_dcrc */
-
-#define image_get_hdr_u8(x) \
-static inline uint8_t image_get_##x(const image_header_t *hdr) \
-{ \
- return hdr->ih_##x; \
-}
-image_get_hdr_u8(os); /* image_get_os */
-image_get_hdr_u8(arch); /* image_get_arch */
-image_get_hdr_u8(type); /* image_get_type */
-image_get_hdr_u8(comp); /* image_get_comp */
-
-static inline char *image_get_name(const image_header_t *hdr)
-{
- return (char*)hdr->ih_name;
-}
-
-static inline uint32_t image_get_data_size(const image_header_t *hdr)
-{
- return image_get_size(hdr);
-}
-
-/**
- * image_get_data - get image payload start address
- * @hdr: image header
- *
- * image_get_data() returns address of the image payload. For single
- * component images it is image data start. For multi component
- * images it points to the null terminated table of sub-images sizes.
- *
- * returns:
- * image payload data start address
- */
-static inline ulong image_get_data(const image_header_t *hdr)
-{
- return ((ulong)hdr + image_get_header_size());
-}
-
-static inline uint32_t image_get_image_size(const image_header_t *hdr)
-{
- return (image_get_size(hdr) + image_get_header_size());
-}
-
-static inline ulong image_get_image_end(const image_header_t *hdr)
-{
- return ((ulong)hdr + image_get_image_size(hdr));
-}
-
-#define image_set_hdr_u32(x) \
-static inline void image_set_##x(image_header_t *hdr, uint32_t val) \
-{ \
- hdr->ih_##x = cpu_to_uimage(val); \
-}
-
-image_set_hdr_u32(magic); /* image_set_magic */
-image_set_hdr_u32(hcrc); /* image_set_hcrc */
-image_set_hdr_u32(time); /* image_set_time */
-image_set_hdr_u32(size); /* image_set_size */
-image_set_hdr_u32(load); /* image_set_load */
-image_set_hdr_u32(ep); /* image_set_ep */
-image_set_hdr_u32(dcrc); /* image_set_dcrc */
-
-#define image_set_hdr_u8(x) \
-static inline void image_set_##x(image_header_t *hdr, uint8_t val) \
-{ \
- hdr->ih_##x = val; \
-}
-
-image_set_hdr_u8(os); /* image_set_os */
-image_set_hdr_u8(arch); /* image_set_arch */
-image_set_hdr_u8(type); /* image_set_type */
-image_set_hdr_u8(comp); /* image_set_comp */
-
-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(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 image_header_t *hdr, void *data);
+struct uimage_handle_data {
+ size_t offset; /* offset in the image */
+ ulong len;
+};
-/*
- * Load an image into memory. Returns a pointer to the loaded
- * image.
- */
-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);
+struct uimage_handle *uimage_open(const char *filename);
+void uimage_close(struct uimage_handle *handle);
+int uimage_verify(struct uimage_handle *handle);
+int uimage_load(struct uimage_handle *handle, unsigned int image_no,
+ int(*flush)(void*, unsigned int));
+void uimage_print_contents(struct uimage_handle *handle);
+size_t uimage_get_size(struct uimage_handle *handle, unsigned int image_no);
+struct resource *uimage_load_to_sdram(struct uimage_handle *handle,
+ int image_no, unsigned long load_address);
+void *uimage_load_to_buf(struct uimage_handle *handle, int image_no,
+ size_t *size);
+struct resource *file_to_sdram(const char *filename, unsigned long adr);
+#define MAX_MULTI_IMAGE_COUNT 16
+
+struct uimage_handle {
+ struct image_header header;
+ char *name;
+ struct uimage_handle_data ihd[MAX_MULTI_IMAGE_COUNT];
+ int nb_data_entries;
+ size_t data_offset;
+ int fd;
+};
-/*
- * Relocate an image to load_address by uncompressing
- * or just copying.
- */
-int relocate_image(struct image_handle *handle, void *load_address);
+#define UIMAGE_INVALID_ADDRESS (~0)
#endif /* __IMAGE_H__ */
diff --git a/include/keyboard.h b/include/keyboard.h
deleted file mode 100644
index 88ae12bc0f..0000000000
--- a/include/keyboard.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __KEYBOARD_H
-#define __KEYBOARD_H
-
-#ifdef CONFIG_PS2MULT
-#include <ps2mult.h>
-#endif
-
-#if !defined(kbd_request_region) || \
- !defined(kbd_request_irq) || \
- !defined(kbd_read_input) || \
- !defined(kbd_read_status) || \
- !defined(kbd_write_output) || \
- !defined(kbd_write_command)
-#error PS/2 low level routines not defined
-#endif
-
-extern int kbd_init (void);
-extern void handle_scancode(unsigned char scancode);
-extern int kbd_init_hw(void);
-extern void pckbd_leds(unsigned char leds);
-
-#endif /* __KEYBOARD_H */
diff --git a/include/libbb.h b/include/libbb.h
index 2d17c3fc95..110e8ec39d 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -32,4 +32,7 @@ int process_escape_sequence(const char *source, char *dest, int destlen);
char *simple_itoa(unsigned int i);
+int write_full(int fd, void *buf, size_t size);
+int read_full(int fd, void *buf, size_t size);
+
#endif /* __LIBBB_H */
diff --git a/include/linux/bch.h b/include/linux/bch.h
new file mode 100644
index 0000000000..295b4ef153
--- /dev/null
+++ b/include/linux/bch.h
@@ -0,0 +1,79 @@
+/*
+ * Generic binary BCH encoding/decoding library
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright © 2011 Parrot S.A.
+ *
+ * Author: Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * Description:
+ *
+ * This library provides runtime configurable encoding/decoding of binary
+ * Bose-Chaudhuri-Hocquenghem (BCH) codes.
+*/
+#ifndef _BCH_H
+#define _BCH_H
+
+#include <linux/types.h>
+
+/**
+ * struct bch_control - BCH control structure
+ * @m: Galois field order
+ * @n: maximum codeword size in bits (= 2^m-1)
+ * @t: error correction capability in bits
+ * @ecc_bits: ecc exact size in bits, i.e. generator polynomial degree (<=m*t)
+ * @ecc_bytes: ecc max size (m*t bits) in bytes
+ * @a_pow_tab: Galois field GF(2^m) exponentiation lookup table
+ * @a_log_tab: Galois field GF(2^m) log lookup table
+ * @mod8_tab: remainder generator polynomial lookup tables
+ * @ecc_buf: ecc parity words buffer
+ * @ecc_buf2: ecc parity words buffer
+ * @xi_tab: GF(2^m) base for solving degree 2 polynomial roots
+ * @syn: syndrome buffer
+ * @cache: log-based polynomial representation buffer
+ * @elp: error locator polynomial
+ * @poly_2t: temporary polynomials of degree 2t
+ */
+struct bch_control {
+ unsigned int m;
+ unsigned int n;
+ unsigned int t;
+ unsigned int ecc_bits;
+ unsigned int ecc_bytes;
+/* private: */
+ uint16_t *a_pow_tab;
+ uint16_t *a_log_tab;
+ uint32_t *mod8_tab;
+ uint32_t *ecc_buf;
+ uint32_t *ecc_buf2;
+ unsigned int *xi_tab;
+ unsigned int *syn;
+ int *cache;
+ struct gf_poly *elp;
+ struct gf_poly *poly_2t[4];
+};
+
+struct bch_control *init_bch(int m, int t, unsigned int prim_poly);
+
+void free_bch(struct bch_control *bch);
+
+void encode_bch(struct bch_control *bch, const uint8_t *data,
+ unsigned int len, uint8_t *ecc);
+
+int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
+ const uint8_t *recv_ecc, const uint8_t *calc_ecc,
+ const unsigned int *syn, unsigned int *errloc);
+
+#endif /* _BCH_H */
diff --git a/include/linux/bitrev.h b/include/linux/bitrev.h
new file mode 100644
index 0000000000..7ffe03f469
--- /dev/null
+++ b/include/linux/bitrev.h
@@ -0,0 +1,16 @@
+#ifndef _LINUX_BITREV_H
+#define _LINUX_BITREV_H
+
+#include <linux/types.h>
+
+extern u8 const byte_rev_table[256];
+
+static inline u8 bitrev8(u8 byte)
+{
+ return byte_rev_table[byte];
+}
+
+extern u16 bitrev16(u16 in);
+extern u32 bitrev32(u32 in);
+
+#endif /* _LINUX_BITREV_H */
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 29591e2643..71d3c6f49f 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -202,7 +202,6 @@ struct mtd_info {
struct device_d class_dev;
struct device_d *dev;
struct cdev cdev;
- struct cdev cdev_oob;
struct param_d param_size;
char *size_str;
@@ -220,7 +219,7 @@ static inline uint32_t mtd_mod_by_eb(uint64_t sz, struct mtd_info *mtd)
}
/* Kernel-side ioctl definitions */
-extern int add_mtd_device(struct mtd_info *mtd);
+extern int add_mtd_device(struct mtd_info *mtd, char *devname);
extern int del_mtd_device (struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
diff --git a/include/mfd/twl-core.h b/include/mfd/twl-core.h
new file mode 100644
index 0000000000..2ab6169433
--- /dev/null
+++ b/include/mfd/twl-core.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ *
+ * Based on:
+ * Copyright (C) 2010 Michael Grzeschik <mgr@pengutronix.de>
+ * Copyright (C) 2010 Sascha Hauer <sha@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __I2C_TWLCORE_H__
+#define __I2C_TWLCORE_H__
+
+#include <common.h>
+#include <i2c/i2c.h>
+#include <linux/err.h>
+
+struct twlcore {
+ struct cdev cdev;
+ struct i2c_client *client;
+};
+
+extern struct file_operations twl_fops;
+
+extern int twlcore_reg_read(struct twlcore *twlcore, u16 reg, u8 *val);
+extern int twlcore_reg_write(struct twlcore *twlcore, u16 reg, u8 val);
+extern int twlcore_set_bits(struct twlcore *twlcore, u16 reg, u8 mask, u8 val);
+
+#endif /* __I2C_TWLCORE_H__ */
diff --git a/include/mfd/twl4030.h b/include/mfd/twl4030.h
index 3fef4d9ad6..bc54ea66a1 100644
--- a/include/mfd/twl4030.h
+++ b/include/mfd/twl4030.h
@@ -6,12 +6,10 @@
*
*/
-#ifndef __I2C_TWL4030_H
-#define __I2C_TWL4030_H
+#ifndef __I2C_TWL4030_H__
+#define __I2C_TWL4030_H__
-#include <common.h>
-#include <i2c/i2c.h>
-#include <linux/err.h>
+#include <mfd/twl-core.h>
/* LED */
#define TWL4030_LED_LEDEN_LEDAON (1 << 0)
@@ -76,7 +74,7 @@ enum twl4030_reg {
TWL4030_PM_RECEIVER_VAUX2_VSEL_18 = 0x05,
TWL4030_PM_RECEIVER_VAUX3_VSEL_28 = 0x03,
TWL4030_PM_RECEIVER_VPLL2_VSEL_18 = 0x05,
- TWL4030_PM_RECEIVER_VDAC_VSEL_18 = 0x03,
+ TWL4030_PM_RECEIVER_VDAC_VSEL_18 = 0x03,
TWL4030_PM_RECEIVER_VMMC1_VSEL_30 = 0x02,
/*
@@ -448,14 +446,27 @@ enum twl4030_reg {
};
struct twl4030 {
- struct cdev cdev;
- struct i2c_client *client;
+ struct twlcore core;
};
extern struct twl4030 *twl4030_get(void);
-extern int twl4030_reg_read(struct twl4030 *twl4030, u16 reg, u8 *val);
-extern int twl4030_reg_write(struct twl4030 *twl4030, u16 reg, u8 val);
-extern int twl4030_set_bits(struct twl4030 *twl4030, enum twl4030_reg reg, u8 mask, u8 val);
+static inline int twl4030_reg_read(struct twl4030 *twl4030,
+ enum twl4030_reg reg, u8 *val)
+{
+ return twlcore_reg_read(&(twl4030->core), reg, val);
+}
-#endif /* __I2C_TWL4030_H */
+static inline int twl4030_reg_write(struct twl4030 *twl4030,
+ enum twl4030_reg reg, u8 val)
+{
+ return twlcore_reg_write(&(twl4030->core), reg, val);
+}
+
+static inline int twl4030_set_bits(struct twl4030 *twl4030,
+ enum twl4030_reg reg, u8 mask, u8 val)
+{
+ return twlcore_set_bits(&(twl4030->core), reg, mask, val);
+}
+
+#endif /* __I2C_TWL4030_H__ */
diff --git a/include/mfd/twl6030.h b/include/mfd/twl6030.h
new file mode 100644
index 0000000000..f1278d4485
--- /dev/null
+++ b/include/mfd/twl6030.h
@@ -0,0 +1,419 @@
+/*
+ * Copyright (C) 2011 Alexander Aring <a.aring@phytec.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __I2C_TWL6030_H__
+#define __I2C_TWL6030_H__
+
+#include <mfd/twl-core.h>
+
+/* VMMC_CFG_VOLTAGE */
+#define TWL6030_VMMC_VSEL_0 (1 << 0)
+#define TWL6030_VMMC_VSEL_1 (1 << 1)
+#define TWL6030_VMMC_VSEL_2 (1 << 2)
+#define TWL6030_VMMC_VSEL_3 (1 << 3)
+#define TWL6030_VMMC_VSEL_4 (1 << 4)
+#define TWL6030_VMMC_WR_S (1 << 7)
+
+/* VMMC_CFG_STATE (W) */
+#define TWL6030_VMMC_STATE0 (1 << 0)
+#define TWL6030_VMMC_STATE1 (1 << 1)
+#define TWL6030_VMMC_GRP_APP (1 << 5)
+#define TWL6030_VMMC_GRP_CON (1 << 6)
+#define TWL6030_VMMC_GRP_MOD (1 << 7)
+
+enum twl6030_reg {
+ /* RTC */
+ TWL6030_RTC_SECONDS = 0x0000,
+ TWL6030_RTC_MINUTES = 0x0001,
+ TWL6030_RTC_HOURS = 0x0002,
+ TWL6030_RTC_DAYS = 0x0003,
+ TWL6030_RTC_MONTHS = 0x0004,
+ TWL6030_RTC_YEARS = 0x0005,
+ TWL6030_RTC_WEEKS = 0x0006,
+ TWL6030_RTC_ALARM_SECONDS = 0x0008,
+ TWL6030_RTC_ALARM_MINUTES = 0x0009,
+ TWL6030_RTC_ALARM_HOURS = 0x000A,
+ TWL6030_RTC_ALARM_DAYS = 0x000B,
+ TWL6030_RTC_ALARM_MONTHS = 0x000C,
+ TWL6030_RTC_ALARM_YEARS = 0x000D,
+ TWL6030_RTC_CTRL = 0x0010,
+ TWL6030_RTC_STATUS = 0x0011,
+ TWL6030_RTC_INTERRUPTS = 0x0012,
+ TWL6030_RTC_COMP_LSB = 0x0013,
+ TWL6030_RTC_COMP_MSB = 0x0014,
+ TWL6030_RTC_RESET_STATUS = 0x0016,
+ /* MEM */
+ TWL6030_MEM_VALIDITY0 = 0x0017,
+ TWL6030_MEM_VALIDITY1 = 0x0018,
+ TWL6030_MEM_VALIDITY2 = 0x0019,
+ TWL6030_MEM_VALIDITY3 = 0x001A,
+ TWL6030_MEM_VALIDITY4 = 0x001B,
+ TWL6030_MEM_VALIDITY5 = 0x001C,
+ TWL6030_MEM_VALIDITY6 = 0x001D,
+ TWL6030_MEM_VALIDITY7 = 0x001E,
+ /* PMC Master */
+ TWL6030_PMCM_START = 0x001F,
+ TWL6030_PMCM_MSK = 0x0020,
+ TWL6030_PMCM_HW = 0x0021,
+ TWL6030_PMCM_TURNOFF = 0x0022,
+ TWL6030_PMCM_VBAT_THRESHOLD_LO = 0x0023,
+ TWL6030_PMCM_VBAT_THRESHOLD_HI = 0x0024,
+ TWL6030_PMCM_DEV_ON = 0x0025,
+ TWL6030_PMCM_PWR_GRP_STATE = 0x0027,
+ TWL6030_PMCM_CFG_VBATLOWV = 0x0028,
+ TWL6030_PMCM_STS_BOOT = 0x0029,
+ TWL6030_PMCM_SENS_TRANSITION = 0x002A,
+ TWL6030_PMCM_SEQ_CFG = 0x002B,
+ TWL6030_PMCM_PRIMARY_WATCHDOG_CFG = 0x002C,
+ TWL6030_PMCM_KEY_PRESS_DURATION_CFG = 0x002D,
+ /* PMC Slave MISC */
+ TWL6030_PMCS_ADDRESS_ALL = 0x0031,
+ TWL6030_PMCS_ADDRESS_REF = 0x0032,
+ TWL6030_PMCS_ADDRESS_PROV = 0x0033,
+ TWL6030_PMCS_ADDRESS_CLK_RST = 0x0034,
+ /* PMC Slave SMPS */
+ TWL6030_PMCS_V1V29_CFG_GRP = 0x0040,
+ TWL6030_PMCS_V1V29_CFG_TRANS = 0x0041,
+ TWL6030_PMCS_V1V29_CFG_STATE = 0x0042,
+ TWL6030_PMCS_V1V29_CFG_VOLTAGE = 0x0044,
+ TWL6030_PMCS_V1V8_CFG_GRP = 0x0046,
+ TWL6030_PMCS_V1V8_CFG_TRANS = 0x0047,
+ TWL6030_PMCS_V1V8_CFG_STATE = 0x0048,
+ TWL6030_PMCS_V1V8_CFG_VOLTAGE = 0x004A,
+ TWL6030_PMCS_V2V1_CFG_GRP = 0x004C,
+ TWL6030_PMCS_V2V1_CFG_TRANS = 0x004D,
+ TWL6030_PMCS_V2V1_CFG_STATE = 0x004E,
+ TWL6030_PMCS_V2V1_CFG_VOLTAGE = 0x0050,
+ TWL6030_PMCS_VCORE1_CFG_GRP = 0x0052,
+ TWL6030_PMCS_VCORE1_CFG_TRANS = 0x0053,
+ TWL6030_PMCS_VCORE1_CFG_STATE = 0x0054,
+ TWL6030_PMCS_VCORE1_CFG_STEP = 0x0057,
+ TWL6030_PMCS_VCORE2_CFG_GRP = 0x0058,
+ TWL6030_PMCS_VCORE2_CFG_TRANS = 0x0059,
+ TWL6030_PMCS_VCORE2_CFG_STATE = 0x005A,
+ TWL6030_PMCS_VCORE2_CFG_STEP = 0x005D,
+ TWL6030_PMCS_VCORE3_CFG_GRP = 0x005E,
+ TWL6030_PMCS_VCORE3_CFG_TRANS = 0x005F,
+ TWL6030_PMCS_VCORE3_CFG_STATE = 0x0060,
+ TWL6030_PMCS_VCORE3_CFG_STEP = 0x0063,
+ TWL6030_PMCS_VMEM_CFG_GRP = 0x0064,
+ TWL6030_PMCS_VMEM_CFG_TRANS = 0x0065,
+ TWL6030_PMCS_VMEM_CFG_STATE = 0x0066,
+ TWL6030_PMCS_VMEM_CFG_VOLTAGE = 0x0068,
+ /* PMC Slave LDO */
+ TWL6030_PMCS_VANA_CFG_GRP = 0x0080,
+ TWL6030_PMCS_VANA_CFG_TRANS = 0x0081,
+ TWL6030_PMCS_VANA_CFG_STATE = 0x0082,
+ TWL6030_PMCS_VANA_CFG_VOLTAGE = 0x0083,
+ TWL6030_PMCS_VAUX1_CFG_GRP = 0x0084,
+ TWL6030_PMCS_VAUX1_CFG_TRANS = 0x0085,
+ TWL6030_PMCS_VAUX1_CFG_STATE = 0x0086,
+ TWL6030_PMCS_VAUX1_CFG_VOLTAGE = 0x0087,
+ TWL6030_PMCS_VAUX2_CFG_GRP = 0x0088,
+ TWL6030_PMCS_VAUX2_CFG_TRANS = 0x0089,
+ TWL6030_PMCS_VAUX2_CFG_STATE = 0x008A,
+ TWL6030_PMCS_VAUX2_CFG_VOLTAGE = 0x008B,
+ TWL6030_PMCS_VAUX3_CFG_GRP = 0x008C,
+ TWL6030_PMCS_VAUX3_CFG_TRANS = 0x008D,
+ TWL6030_PMCS_VAUX3_CFG_STATE = 0x008E,
+ TWL6030_PMCS_VAUX3_CFG_VOLTAGE = 0x008F,
+ TWL6030_PMCS_VCXIO_CFG_GRP = 0x0090,
+ TWL6030_PMCS_VCXIO_CFG_TRANS = 0x0091,
+ TWL6030_PMCS_VCXIO_CFG_STATE = 0x0092,
+ TWL6030_PMCS_VCXIO_CFG_VOLTAGE = 0x0093,
+ TWL6030_PMCS_VDAC_CFG_GRP = 0x0094,
+ TWL6030_PMCS_VDAC_CFG_TRANS = 0x0095,
+ TWL6030_PMCS_VDAC_CFG_STATE = 0x0096,
+ TWL6030_PMCS_VDAC_CFG_VOLTAGE = 0x0097,
+ TWL6030_PMCS_VMMC_CFG_GRP = 0x0098,
+ TWL6030_PMCS_VMMC_CFG_TRANS = 0x0099,
+ TWL6030_PMCS_VMMC_CFG_STATE = 0x009A,
+ TWL6030_PMCS_VMMC_CFG_VOLTAGE = 0x009B,
+ TWL6030_PMCS_VPP_CFG_GRP = 0x009C,
+ TWL6030_PMCS_VPP_CFG_TRANS = 0x009D,
+ TWL6030_PMCS_VPP_CFG_STATE = 0x009E,
+ TWL6030_PMCS_VPP_CFG_VOLTAGE = 0x009F,
+ TWL6030_PMCS_VUSB_CFG_GRP = 0x00A0,
+ TWL6030_PMCS_VUSB_CFG_TRANS = 0x00A1,
+ TWL6030_PMCS_VUSB_CFG_STATE = 0x00A2,
+ TWL6030_PMCS_VUSB_CFG_VOLTAGE = 0x00A3,
+ TWL6030_PMCS_VUSIM_CFG_GRP = 0x00A4,
+ TWL6030_PMCS_VUSIM_CFG_TRANS = 0x00A5,
+ TWL6030_PMCS_VUSIM_CFG_STATE = 0x00A6,
+ TWL6030_PMCS_VUSIM_CFG_VOLTAGE = 0x00A7,
+ /* Resource Register Map */
+ TWL6030_PMCS_REGEN1_CFG_GRP = 0x00AD,
+ TWL6030_PMCS_REGEN1_CFG_TRANS = 0x00AE,
+ TWL6030_PMCS_REGEN1_CFG_STATE = 0x00AF,
+ TWL6030_PMCS_REGEN2_CFG_GRP = 0x00B0,
+ TWL6030_PMCS_REGEN2_CFG_TRANS = 0x00B1,
+ TWL6030_PMCS_REGEN2_CFG_STATE = 0x00B2,
+ TWL6030_PMCS_SYSEN_CFG_GRP = 0x00B3,
+ TWL6030_PMCS_SYSEN_CFG_TRANS = 0x00B4,
+ TWL6030_PMCS_SYSEN_CFG_STATE = 0x00B5,
+ TWL6030_PMCS_NRESPWRON_CFG_GRP = 0x00B6,
+ TWL6030_PMCS_NRESPWRON_CFG_TRANS = 0x00B7,
+ TWL6030_PMCS_NRESPWRON_CFG_STATE = 0x00B8,
+ TWL6030_PMCS_CLK32KAO_CFG_GRP = 0x00B9,
+ TWL6030_PMCS_CLK32KAO_CFG_TRANS = 0x00BA,
+ TWL6030_PMCS_CLK32KAO_CFG_STATE = 0x00BB,
+ TWL6030_PMCS_CLK32KG_CFG_GRP = 0x00BC,
+ TWL6030_PMCS_CLK32KG_CFG_TRANS = 0x00BD,
+ TWL6030_PMCS_CLK32KG_CFG_STATE = 0x00BE,
+ TWL6030_PMCS_CLK32KAUDIO_CFG_GRP = 0x00BF,
+ TWL6030_PMCS_CLK32KAUDIO_CFG_TRANS = 0x00C0,
+ TWL6030_PMCS_CLK32KAUDIO_CFG_STATE = 0x00C1,
+ TWL6030_PMCS_VRTC_CFG_GRP = 0x00C2,
+ TWL6030_PMCS_VRTC_CFG_TRANS = 0x00C3,
+ TWL6030_PMCS_VRTC_CFG_STATE = 0x00C4,
+ TWL6030_PMCS_BIAS_CFG_GRP = 0x00C5,
+ TWL6030_PMCS_BIAS_CFG_TRANS = 0x00C6,
+ TWL6030_PMCS_BIAS_CFG_STATE = 0x00C7,
+ TWL6030_PMCS_VBATMIN_CFG_GRP = 0x00C8,
+ TWL6030_PMCS_VBATMIN_CFG_TRANS = 0x00C9,
+ TWL6030_PMCS_VBATMIN_CFG_STATE = 0x00CA,
+ TWL6030_PMCS_RC6MHZ_CFG_GRP = 0x00CB,
+ TWL6030_PMCS_RC6MHZ_CFG_TRANS = 0x00CC,
+ TWL6030_PMCS_RC6MHZ_CFG_STATE = 0x00CD,
+ TWL6030_PMCS_TMP_CFG_GRP = 0x00CE,
+ TWL6030_PMCS_TMP_CFG_TRANS = 0x00CF,
+ TWL6030_PMCS_TMP_CFG_STATE = 0x00D0,
+ /* Misc Register */
+ TWL6030_PMC_SMPS_OFFSET = 0x00E0,
+ TWL6030_PMC_SMPS_MULT = 0x00E3,
+ TWL6030_PMC_SMPS_MISC1 = 0x00E4,
+ TWL6030_PMC_SMPS_MISC2 = 0x00E5,
+ TWL6030_PMC_SMPS_BBSPOR_CFG = 0x00E6,
+ TWL6030_PMC_SMPS_TMP_CFG = 0x00E7,
+ TWL6030_PMC_SMPS_FORCE_SMPS_CLK = 0x00E8,
+ TWL6030_PMC_SMPS_SIMDEBOUNCING = 0x00EB,
+ TWL6030_PMC_SMPS_SIMCTRL = 0x00EC,
+ TWL6030_PMC_SMPS_MMCDEBOUNCING = 0x00ED,
+ TWL6030_PMC_SMPS_MMCCTRL = 0x00EE,
+ TWL6030_PMC_SMPS_BATDEBOUNCING = 0x00EF,
+ /* Pull-up | Pull-down | High-Z */
+ TWL6030_PMC_CFG_INPUT_PUPD1 = 0x00F0,
+ TWL6030_PMC_CFG_INPUT_PUPD2 = 0x00F1,
+ TWL6030_PMC_CFG_INPUT_PUPD3 = 0x00F2,
+ TWL6030_PMC_CFG_INPUT_PUPD4 = 0x00F3,
+ TWL6030_PMC_CFG_LDO_PD1 = 0x00F4,
+ TWL6030_PMC_CFG_LDO_PD2 = 0x00F5,
+ TWL6030_PMC_CFG_SMPS_PD = 0x00F6,
+ /* OTG Backup */
+ TWL6030_OTG_BACKUP_REG = 0x00FA,
+ /* USB OTG */
+ TWL6030_OTG_USB_VENDORID_LO = 0x0100,
+ TWL6030_OTG_USB_VENDORID_HI = 0x0101,
+ TWL6030_OTG_USB_PRODUCTID_LO = 0x0102,
+ TWL6030_OTG_USB_PRODUCTID_HI = 0x0103,
+ TWL6030_OTG_USB_VBUS_CTRL_SET = 0x0104,
+ TWL6030_OTG_USB_VBUS_CTRL_CLR = 0x0105,
+ TWL6030_OTG_USB_ID_CTRL_SET = 0x0106,
+ TWL6030_OTG_USB_ID_CTRL_CLR = 0x0107,
+ TWL6030_OTG_USB_VBUS_INT_SRC = 0x0108,
+ TWL6030_OTG_USB_VBUS_INT_LATCH_SET = 0x0109,
+ TWL6030_OTG_USB_VBUS_INT_LATCH_CLR = 0x010A,
+ TWL6030_OTG_USB_VBUS_INT_EN_LO_SET = 0x010B,
+ TWL6030_OTG_USB_VBUS_INT_EN_LO_CLR = 0x010C,
+ TWL6030_OTG_USB_VBUS_INT_EN_HI_SET = 0x010D,
+ TWL6030_OTG_USB_VBUS_INT_EN_HI_CLR = 0x010E,
+ TWL6030_OTG_USB_ID_INT_SRC = 0x010F,
+ TWL6030_OTG_USB_ID_INT_LATCH_SET = 0x0110,
+ TWL6030_OTG_USB_ID_INT_LATCH_CLR = 0x0111,
+ TWL6030_OTG_USB_ID_INT_EN_LO_SET = 0x0112,
+ TWL6030_OTG_USB_ID_INT_EN_LO_CLR = 0x0113,
+ TWL6030_OTG_USB_ID_INT_EN_HI_SET = 0x0114,
+ TWL6030_OTG_USB_ID_INT_EN_HI_CLR = 0x0115,
+ TWL6030_OTG_USB_ADP_CTRL = 0x0116,
+ TWL6030_OTG_USB_ADP_HIGH = 0x0117,
+ TWL6030_OTG_USB_ADP_LOW = 0x0118,
+ TWL6030_OTG_USB_ADP_RISE = 0x0119,
+ /* GPADC Control */
+ TWL6030_GPADC_CTRL = 0x012E,
+ TWL6030_GPADC_RTSELECT_LSB = 0x0130,
+ TWL6030_GPADC_RTSELECT_ISB = 0x0131,
+ TWL6030_GPADC_RTSELECT_MSB = 0x0132,
+ TWL6030_GPADC_CTRL_P1 = 0x0133,
+ TWL6030_GPADC_CTRL_P2 = 0x0134,
+ /* GPADC Real Time */
+ TWL6030_GPADC_RTCH0_LO = 0x0135,
+ TWL6030_GPADC_RTCH0_HI = 0x0136,
+ TWL6030_GPADC_RTCH1_LO = 0x0137,
+ TWL6030_GPADC_RTCH1_HI = 0x0138,
+ TWL6030_GPADC_RTCH2_LO = 0x0139,
+ TWL6030_GPADC_RTCH2_HI = 0x013A,
+ TWL6030_GPADC_RTCH3_LO = 0x013B,
+ TWL6030_GPADC_RTCH3_HI = 0x013C,
+ TWL6030_GPADC_RTCH4_LO = 0x013D,
+ TWL6030_GPADC_RTCH4_HI = 0x013E,
+ TWL6030_GPADC_RTCH5_LO = 0x013F,
+ TWL6030_GPADC_RTCH5_HI = 0x0140,
+ TWL6030_GPADC_RTCH6_LO = 0x0141,
+ TWL6030_GPADC_RTCH6_HI = 0x0142,
+ TWL6030_GPADC_RTCH7_LO = 0x0143,
+ TWL6030_GPADC_RTCH7_HI = 0x0144,
+ TWL6030_GPADC_RTCH8_LO = 0x0145,
+ TWL6030_GPADC_RTCH8_HI = 0x0146,
+ TWL6030_GPADC_RTCH9_LO = 0x0147,
+ TWL6030_GPADC_RTCH9_HI = 0x0148,
+ TWL6030_GPADC_RTCH10_LO = 0x0149,
+ TWL6030_GPADC_RTCH10_HI = 0x014A,
+ TWL6030_GPADC_RTCH11_LO = 0x014B,
+ TWL6030_GPADC_RTCH11_HI = 0x014C,
+ TWL6030_GPADC_RTCH12_LO = 0x014D,
+ TWL6030_GPADC_RTCH12_HI = 0x014E,
+ TWL6030_GPADC_RTCH13_LO = 0x014F,
+ TWL6030_GPADC_RTCH13_HI = 0x0150,
+ TWL6030_GPADC_RTCH14_LO = 0x0151,
+ TWL6030_GPADC_RTCH14_HI = 0x0152,
+ TWL6030_GPADC_RTCH15_LO = 0x0153,
+ TWL6030_GPADC_RTCH15_HI = 0x0154,
+ TWL6030_GPADC_RTCH16_LO = 0x0155,
+ TWL6030_GPADC_RTCH16_HI = 0x0156,
+ /* GPADC General Purpose */
+ TWL6030_GPADC_GPCH0_LO = 0x0157,
+ TWL6030_GPADC_GPCH0_HI = 0x0158,
+ TWL6030_GPADC_GPCH1_LO = 0x0159,
+ TWL6030_GPADC_GPCH1_HI = 0x015A,
+ TWL6030_GPADC_GPCH2_LO = 0x015B,
+ TWL6030_GPADC_GPCH2_HI = 0x015C,
+ TWL6030_GPADC_GPCH3_LO = 0x015D,
+ TWL6030_GPADC_GPCH3_HI = 0x015E,
+ TWL6030_GPADC_GPCH4_LO = 0x015F,
+ TWL6030_GPADC_GPCH4_HI = 0x0160,
+ TWL6030_GPADC_GPCH5_LO = 0x0161,
+ TWL6030_GPADC_GPCH5_HI = 0x0162,
+ TWL6030_GPADC_GPCH6_LO = 0x0163,
+ TWL6030_GPADC_GPCH6_HI = 0x0164,
+ TWL6030_GPADC_GPCH7_LO = 0x0165,
+ TWL6030_GPADC_GPCH7_HI = 0x0166,
+ TWL6030_GPADC_GPCH8_LO = 0x0167,
+ TWL6030_GPADC_GPCH8_HI = 0x0168,
+ TWL6030_GPADC_GPCH9_LO = 0x0169,
+ TWL6030_GPADC_GPCH9_HI = 0x016A,
+ TWL6030_GPADC_GPCH10_LO = 0x016B,
+ TWL6030_GPADC_GPCH10_HI = 0x016C,
+ TWL6030_GPADC_GPCH11_LO = 0x016D,
+ TWL6030_GPADC_GPCH11_HI = 0x016E,
+ TWL6030_GPADC_GPCH12_LO = 0x016F,
+ TWL6030_GPADC_GPCH12_HI = 0x0170,
+ TWL6030_GPADC_GPCH13_LO = 0x0171,
+ TWL6030_GPADC_GPCH13_HI = 0x0172,
+ TWL6030_GPADC_GPCH14_LO = 0x0173,
+ TWL6030_GPADC_GPCH14_HI = 0x0174,
+ TWL6030_GPADC_GPCH15_LO = 0x0175,
+ TWL6030_GPADC_GPCH15_HI = 0x0176,
+ TWL6030_GPADC_GPCH16_LO = 0x0177,
+ TWL6030_GPADC_GPCH16_HI = 0x0178,
+ /* Auxiliaries Register */
+ TWL6030_AUX_TOGGLE1 = 0x0190,
+ TWL6030_AUX_TOGGLE2 = 0x0191,
+ TWL6030_AUX_TOGGLE3 = 0x0192,
+ TWL6030_AUX_PWDNSTATUS1 = 0x0193,
+ TWL6030_AUX_PWDNSTATUS2 = 0x0194,
+ TWL6030_AUX_VIBCTRL = 0x019B,
+ TWL6030_AUX_VIBMODE = 0x019C,
+ /* PWM Register */
+ TWL6030_PWM_PWM1ON = 0x019C,
+ TWL6030_PWM_PWM1OFF = 0x019C,
+ TWL6030_PWM_PWM2ON = 0x019C,
+ TWL6030_PWM_PWM2OFF = 0x019C,
+ /* Gas Gauge Register */
+ TWL6030_FG_REG_00 = 0x01C0,
+ TWL6030_FG_REG_01 = 0x01C1,
+ TWL6030_FG_REG_02 = 0x01C2,
+ TWL6030_FG_REG_03 = 0x01C3,
+ TWL6030_FG_REG_04 = 0x01C4,
+ TWL6030_FG_REG_05 = 0x01C5,
+ TWL6030_FG_REG_06 = 0x01C6,
+ TWL6030_FG_REG_07 = 0x01C7,
+ TWL6030_FG_REG_08 = 0x01C8,
+ TWL6030_FG_REG_09 = 0x01C9,
+ TWL6030_FG_REG_10 = 0x01CA,
+ TWL6030_FG_REG_11 = 0x01CB,
+ /* Interfaces Interrupts */
+ TWL6030_INT_STS_A = 0x01D0,
+ TWL6030_INT_STS_B = 0x01D1,
+ TWL6030_INT_STS_C = 0x01D2,
+ TWL6030_INT_MSK_LINE_A = 0x01D3,
+ TWL6030_INT_MSK_LINE_B = 0x01D4,
+ TWL6030_INT_MSK_LINE_C = 0x01D5,
+ TWL6030_INT_MSK_STS_A = 0x01D6,
+ TWL6030_INT_MSK_STS_B = 0x01D7,
+ TWL6030_INT_MSK_STS_C = 0x01D8,
+ /* Charger Regisers */
+ TWL6030_CHR_CONTROLLER_INT_MASK = 0x01E0,
+ TWL6030_CHR_CONTROLLER_CTRL1 = 0x01E1,
+ TWL6030_CHR_CONTROLLER_WDG = 0x01E2,
+ TWL6030_CHR_CONTROLLER_STAT1 = 0x01E3,
+ TWL6030_CHR_CHARGERUSB_INT_STATUS = 0x01E4,
+ TWL6030_CHR_CHARGERUSB_INT_MASK = 0x01E5,
+ TWL6030_CHR_CHARGERUSB_STATUS_INT1 = 0x01E6,
+ TWL6030_CHR_CHARGERUSB_STATUS_INT2 = 0x01E7,
+ TWL6030_CHR_CHARGERUSB_CTRL1 = 0x01E8,
+ TWL6030_CHR_CHARGERUSB_CTRL2 = 0x01E9,
+ TWL6030_CHR_CHARGERUSB_CTRL3 = 0x01EA,
+ TWL6030_CHR_CHARGERUSB_STAT1 = 0x01EB,
+ TWL6030_CHR_CHARGERUSB_VOREG = 0x01EC,
+ TWL6030_CHR_CHARGERUSB_VICHRG = 0x01ED,
+ TWL6030_CHR_CHARGERUSB_CINLIMIT = 0x01EE,
+ TWL6030_CHR_CHARGERUSB_CTRLLIMIT1 = 0x01EF,
+ TWL6030_CHR_CHARGERUSB_CTRLLIMIT2 = 0x01F0,
+ TWL6030_CHR_ANTICOLLAPSE_CTRL1 = 0x01F1,
+ TWL6030_CHR_ANTICOLLAPSE_CTRL2 = 0x01F2,
+ TWL6030_CHR_ANTICOLLAPSE_STAT1 = 0x01F3,
+ TWL6030_CHR_LED_PWM_CTRL1 = 0x01F4,
+ TWL6030_CHR_LED_PWM_CTRL2 = 0x01F5,
+ /* JTAG */
+ TWL6030_JTAG_JTAGVERNUM = 0x0287,
+ TWL6030_JTAG_EPROM_REV = 0x02DF,
+ /* GPADC Trimming */
+ TWL6030_GPADC_TRIM1 = 0x02CD,
+ TWL6030_GPADC_TRIM2 = 0x02CE,
+ TWL6030_GPADC_TRIM3 = 0x02CF,
+ TWL6030_GPADC_TRIM4 = 0x02D0,
+ TWL6030_GPADC_TRIM5 = 0x02D1,
+ TWL6030_GPADC_TRIM6 = 0x02D2,
+ TWL6030_GPADC_TRIM7 = 0x02D3,
+ TWL6030_GPADC_TRIM8 = 0x02D4,
+ TWL6030_GPADC_TRIM9 = 0x02D5,
+ TWL6030_GPADC_TRIM10 = 0x02D6,
+ TWL6030_GPADC_TRIM11 = 0x02D7,
+ TWL6030_GPADC_TRIM12 = 0x02D8,
+ TWL6030_GPADC_TRIM13 = 0x02D9,
+ TWL6030_GPADC_TRIM14 = 0x02DA,
+ TWL6030_GPADC_TRIM15 = 0x02DB,
+ TWL6030_GPADC_TRIM16 = 0x02DC,
+ TWL6030_GPADC_TRIM17 = 0x02DD,
+ TWL6030_GPADC_TRIM18 = 0x02DE,
+};
+
+struct twl6030 {
+ struct twlcore core;
+};
+
+extern struct twl6030 *twl6030_get(void);
+
+static inline int twl6030_reg_read(struct twl6030 *twl6030,
+ enum twl6030_reg reg, u8 *val)
+{
+ return twlcore_reg_read(&twl6030->core, reg, val);
+}
+
+static inline int twl6030_reg_write(struct twl6030 *twl6030,
+ enum twl6030_reg reg, u8 val)
+{
+ return twlcore_reg_write(&twl6030->core, reg, val);
+}
+
+static inline int twl6030_set_bits(struct twl6030 *twl6030,
+ enum twl6030_reg reg, u8 mask, u8 val)
+{
+ return twlcore_set_bits(&twl6030->core, reg, mask, val);
+}
+
+#endif /* __I2C_TWL6030_H__ */
diff --git a/include/of.h b/include/of.h
index c2661efaea..609b3b587b 100644
--- a/include/of.h
+++ b/include/of.h
@@ -8,6 +8,7 @@ extern struct fdt_header *barebox_fdt;
int fdt_print(struct fdt_header *working_fdt, const char *pathp);
struct fdt_header *of_get_fixed_tree(void);
+int of_fix_tree(struct fdt_header *fdt);
int of_register_fixup(int (*fixup)(struct fdt_header *));
int fdt_find_and_setprop(struct fdt_header *fdt, const char *node, const char *prop,
diff --git a/include/stringlist.h b/include/stringlist.h
index 3453e9a4f6..c92354281e 100644
--- a/include/stringlist.h
+++ b/include/stringlist.h
@@ -9,6 +9,8 @@ struct string_list {
};
int string_list_add(struct string_list *sl, char *str);
+int string_list_add_sorted(struct string_list *sl, char *str);
+int string_list_contains(struct string_list *sl, char *str);
void string_list_print_by_column(struct string_list *sl);
static inline void string_list_init(struct string_list *sl)
diff --git a/include/tlsf.h b/include/tlsf.h
new file mode 100644
index 0000000000..d575e165bf
--- /dev/null
+++ b/include/tlsf.h
@@ -0,0 +1,52 @@
+#ifndef INCLUDED_tlsf
+#define INCLUDED_tlsf
+
+/*
+** Two Level Segregated Fit memory allocator, version 1.9.
+** Written by Matthew Conte, and placed in the Public Domain.
+** http://tlsf.baisoku.org
+**
+** Based on the original documentation by Miguel Masmano:
+** http://rtportal.upv.es/rtmalloc/allocators/tlsf/index.shtml
+**
+** Please see the accompanying Readme.txt for implementation
+** notes and caveats.
+**
+** This implementation was written to the specification
+** of the document, therefore no GPL restrictions apply.
+*/
+
+#include <stddef.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/* Create/destroy a memory pool. */
+typedef void* tlsf_pool;
+tlsf_pool tlsf_create(void* mem, size_t bytes);
+void tlsf_destroy(tlsf_pool pool);
+
+/* malloc/memalign/realloc/free replacements. */
+void* tlsf_malloc(tlsf_pool pool, size_t bytes);
+void* tlsf_memalign(tlsf_pool pool, size_t align, size_t bytes);
+void* tlsf_realloc(tlsf_pool pool, void* ptr, size_t size);
+void tlsf_free(tlsf_pool pool, void* ptr);
+
+/* Debugging. */
+typedef void (*tlsf_walker)(void* ptr, size_t size, int used, void* user);
+void tlsf_walk_heap(tlsf_pool pool, tlsf_walker walker, void* user);
+/* Returns nonzero if heap check fails. */
+int tlsf_check_heap(tlsf_pool pool);
+
+/* Returns internal block size, not original request size */
+size_t tlsf_block_size(void* ptr);
+
+/* Overhead of per-pool internal structures. */
+size_t tlsf_overhead(void);
+
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
diff --git a/include/usb/usbserial.h b/include/usb/usbserial.h
new file mode 100644
index 0000000000..43c839c4d6
--- /dev/null
+++ b/include/usb/usbserial.h
@@ -0,0 +1,19 @@
+#ifndef _USB_SERIAL_H
+#define _USB_SERIAL_H
+
+struct usb_serial_pdata {
+ char *manufacturer;
+ char *productname;
+ u16 idVendor;
+ u16 idProduct;
+ int mode;
+};
+
+int usb_serial_register(struct usb_serial_pdata *pdata);
+void usb_serial_unregister(void);
+
+/* OBEX support is missing in barebox */
+/* #define HAVE_OBEX */
+
+#endif /* _USB_SERIAL_H */
+
diff --git a/include/watchdog.h b/include/watchdog.h
deleted file mode 100644
index 9265be9737..0000000000
--- a/include/watchdog.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * (C) Copyright 2001
- * Erik Theisen, Wave 7 Optics, etheisen@mindspring.com.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
- */
-
-/*
- * Watchdog functions and macros.
- */
-#ifndef _WATCHDOG_H_
-#define _WATCHDOG_H_
-
-#if defined(CONFIG_HW_WATCHDOG) && defined(CONFIG_WATCHDOG)
-# error "Configuration error: CONFIG_HW_WATCHDOG and CONFIG_WATCHDOG can't be used together."
-#endif
-
-#if defined(__ASSEMBLY__) && defined(__NIOS__)
-# error "Configuration error: WATCHDOG_RESET inside assembler not supported for Nios platforms."
-#endif
-
-/*
- * Hardware watchdog
- */
-#ifdef CONFIG_HW_WATCHDOG
- #if defined(__ASSEMBLY__)
- #define WATCHDOG_RESET bl hw_watchdog_reset
- #else
- extern void hw_watchdog_reset(void);
-
- #define WATCHDOG_RESET hw_watchdog_reset
- #endif /* __ASSEMBLY__ */
-#else
- /*
- * Maybe a software watchdog?
- */
- #if defined(CONFIG_WATCHDOG)
- #if defined(__ASSEMBLY__)
- #define WATCHDOG_RESET bl watchdog_reset
- #else
- extern void watchdog_reset(void);
-
- #define WATCHDOG_RESET watchdog_reset
- #endif
- #else
- /*
- * No hardware or software watchdog.
- */
- #if defined(__ASSEMBLY__)
- #define WATCHDOG_RESET /*XXX DO_NOT_DEL_THIS_COMMENT*/
- #else
- #define WATCHDOG_RESET() {}
- #endif /* __ASSEMBLY__ */
- #endif /* CONFIG_WATCHDOG && !__ASSEMBLY__ */
-#endif /* CONFIG_HW_WATCHDOG */
-
-/*
- * Prototypes from $(CPU)/cpu.c.
- */
-
-/* MPC 8xx */
-#if (defined(CONFIG_8xx) || defined(CONFIG_MPC860)) && !defined(__ASSEMBLY__)
- void reset_8xx_watchdog(volatile immap_t *immr);
-#endif
-
-/* MPC 5xx */
-#if defined(CONFIG_5xx) && !defined(__ASSEMBLY__)
- void reset_5xx_watchdog(volatile immap_t *immr);
-#endif
-
-/* AMCC 4xx */
-#if defined(CONFIG_4xx) && !defined(__ASSEMBLY__)
- void reset_4xx_watchdog(void);
-#endif
-
-#endif /* _WATCHDOG_H_ */
diff --git a/lib/Kconfig b/lib/Kconfig
index e16dd35715..3339a9aa23 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -19,4 +19,11 @@ config FDT
config OFTREE
select FDT
bool
+
+config BCH
+ bool
+
+config BITREV
+ bool
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index ae76b4c9a7..7799e69d86 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -31,3 +31,5 @@ obj-$(CONFIG_LZO_DECOMPRESS) += decompress_unlzo.o
obj-$(CONFIG_PROCESS_ESCAPE_SEQUENCE) += process_escape_sequence.o
obj-$(CONFIG_FDT) += fdt/
obj-y += uncompress.o
+obj-$(CONFIG_BCH) += bch.o
+obj-$(CONFIG_BITREV) += bitrev.o
diff --git a/lib/bch.c b/lib/bch.c
new file mode 100644
index 0000000000..5797c3faf8
--- /dev/null
+++ b/lib/bch.c
@@ -0,0 +1,1366 @@
+/*
+ * Generic binary BCH encoding/decoding library
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ *
+ * Copyright © 2011 Parrot S.A.
+ *
+ * Author: Ivan Djelic <ivan.djelic@parrot.com>
+ *
+ * Description:
+ *
+ * This library provides runtime configurable encoding/decoding of binary
+ * Bose-Chaudhuri-Hocquenghem (BCH) codes.
+ *
+ * Call init_bch to get a pointer to a newly allocated bch_control structure for
+ * the given m (Galois field order), t (error correction capability) and
+ * (optional) primitive polynomial parameters.
+ *
+ * Call encode_bch to compute and store ecc parity bytes to a given buffer.
+ * Call decode_bch to detect and locate errors in received data.
+ *
+ * On systems supporting hw BCH features, intermediate results may be provided
+ * to decode_bch in order to skip certain steps. See decode_bch() documentation
+ * for details.
+ *
+ * Option CONFIG_BCH_CONST_PARAMS can be used to force fixed values of
+ * parameters m and t; thus allowing extra compiler optimizations and providing
+ * better (up to 2x) encoding performance. Using this option makes sense when
+ * (m,t) are fixed and known in advance, e.g. when using BCH error correction
+ * on a particular NAND flash device.
+ *
+ * Algorithmic details:
+ *
+ * Encoding is performed by processing 32 input bits in parallel, using 4
+ * remainder lookup tables.
+ *
+ * The final stage of decoding involves the following internal steps:
+ * a. Syndrome computation
+ * b. Error locator polynomial computation using Berlekamp-Massey algorithm
+ * c. Error locator root finding (by far the most expensive step)
+ *
+ * In this implementation, step c is not performed using the usual Chien search.
+ * Instead, an alternative approach described in [1] is used. It consists in
+ * factoring the error locator polynomial using the Berlekamp Trace algorithm
+ * (BTA) down to a certain degree (4), after which ad hoc low-degree polynomial
+ * solving techniques [2] are used. The resulting algorithm, called BTZ, yields
+ * much better performance than Chien search for usual (m,t) values (typically
+ * m >= 13, t < 32, see [1]).
+ *
+ * [1] B. Biswas, V. Herbert. Efficient root finding of polynomials over fields
+ * of characteristic 2, in: Western European Workshop on Research in Cryptology
+ * - WEWoRC 2009, Graz, Austria, LNCS, Springer, July 2009, to appear.
+ * [2] [Zin96] V.A. Zinoviev. On the solution of equations of degree 10 over
+ * finite fields GF(2^q). In Rapport de recherche INRIA no 2829, 1996.
+ *
+ * Taken from the linux kernel.
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <init.h>
+#include <malloc.h>
+#include <linux/kernel.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
+#include <linux/bch.h>
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+#define GF_M(_p) (CONFIG_BCH_CONST_M)
+#define GF_T(_p) (CONFIG_BCH_CONST_T)
+#define GF_N(_p) ((1 << (CONFIG_BCH_CONST_M))-1)
+#else
+#define GF_M(_p) ((_p)->m)
+#define GF_T(_p) ((_p)->t)
+#define GF_N(_p) ((_p)->n)
+#endif
+
+#define BCH_ECC_WORDS(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 32)
+#define BCH_ECC_BYTES(_p) DIV_ROUND_UP(GF_M(_p)*GF_T(_p), 8)
+
+#ifndef dbg
+#define dbg(_fmt, args...) do {} while (0)
+#endif
+
+/*
+ * represent a polynomial over GF(2^m)
+ */
+struct gf_poly {
+ unsigned int deg; /* polynomial degree */
+ unsigned int c[0]; /* polynomial terms */
+};
+
+/* given its degree, compute a polynomial size in bytes */
+#define GF_POLY_SZ(_d) (sizeof(struct gf_poly)+((_d)+1)*sizeof(unsigned int))
+
+/* polynomial of degree 1 */
+struct gf_poly_deg1 {
+ struct gf_poly poly;
+ unsigned int c[2];
+};
+
+/*
+ * same as encode_bch(), but process input data one byte at a time
+ */
+static void encode_bch_unaligned(struct bch_control *bch,
+ const unsigned char *data, unsigned int len,
+ uint32_t *ecc)
+{
+ int i;
+ const uint32_t *p;
+ const int l = BCH_ECC_WORDS(bch)-1;
+
+ while (len--) {
+ p = bch->mod8_tab + (l+1)*(((ecc[0] >> 24)^(*data++)) & 0xff);
+
+ for (i = 0; i < l; i++)
+ ecc[i] = ((ecc[i] << 8)|(ecc[i+1] >> 24))^(*p++);
+
+ ecc[l] = (ecc[l] << 8)^(*p);
+ }
+}
+
+/*
+ * convert ecc bytes to aligned, zero-padded 32-bit ecc words
+ */
+static void load_ecc8(struct bch_control *bch, uint32_t *dst,
+ const uint8_t *src)
+{
+ uint8_t pad[4] = {0, 0, 0, 0};
+ unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+ for (i = 0; i < nwords; i++, src += 4)
+ dst[i] = (src[0] << 24)|(src[1] << 16)|(src[2] << 8)|src[3];
+
+ memcpy(pad, src, BCH_ECC_BYTES(bch)-4*nwords);
+ dst[nwords] = (pad[0] << 24)|(pad[1] << 16)|(pad[2] << 8)|pad[3];
+}
+
+/*
+ * convert 32-bit ecc words to ecc bytes
+ */
+static void store_ecc8(struct bch_control *bch, uint8_t *dst,
+ const uint32_t *src)
+{
+ uint8_t pad[4];
+ unsigned int i, nwords = BCH_ECC_WORDS(bch)-1;
+
+ for (i = 0; i < nwords; i++) {
+ *dst++ = (src[i] >> 24);
+ *dst++ = (src[i] >> 16) & 0xff;
+ *dst++ = (src[i] >> 8) & 0xff;
+ *dst++ = (src[i] >> 0) & 0xff;
+ }
+ pad[0] = (src[nwords] >> 24);
+ pad[1] = (src[nwords] >> 16) & 0xff;
+ pad[2] = (src[nwords] >> 8) & 0xff;
+ pad[3] = (src[nwords] >> 0) & 0xff;
+ memcpy(dst, pad, BCH_ECC_BYTES(bch)-4*nwords);
+}
+
+/**
+ * encode_bch - calculate BCH ecc parity of data
+ * @bch: BCH control structure
+ * @data: data to encode
+ * @len: data length in bytes
+ * @ecc: ecc parity data, must be initialized by caller
+ *
+ * The @ecc parity array is used both as input and output parameter, in order to
+ * allow incremental computations. It should be of the size indicated by member
+ * @ecc_bytes of @bch, and should be initialized to 0 before the first call.
+ *
+ * The exact number of computed ecc parity bits is given by member @ecc_bits of
+ * @bch; it may be less than m*t for large values of t.
+ */
+void encode_bch(struct bch_control *bch, const uint8_t *data,
+ unsigned int len, uint8_t *ecc)
+{
+ const unsigned int l = BCH_ECC_WORDS(bch)-1;
+ unsigned int i, mlen;
+ unsigned long m;
+ uint32_t w, r[l+1];
+ const uint32_t * const tab0 = bch->mod8_tab;
+ const uint32_t * const tab1 = tab0 + 256*(l+1);
+ const uint32_t * const tab2 = tab1 + 256*(l+1);
+ const uint32_t * const tab3 = tab2 + 256*(l+1);
+ const uint32_t *pdata, *p0, *p1, *p2, *p3;
+
+ if (ecc) {
+ /* load ecc parity bytes into internal 32-bit buffer */
+ load_ecc8(bch, bch->ecc_buf, ecc);
+ } else {
+ memset(bch->ecc_buf, 0, sizeof(r));
+ }
+
+ /* process first unaligned data bytes */
+ m = ((unsigned long)data) & 3;
+ if (m) {
+ mlen = (len < (4-m)) ? len : 4-m;
+ encode_bch_unaligned(bch, data, mlen, bch->ecc_buf);
+ data += mlen;
+ len -= mlen;
+ }
+
+ /* process 32-bit aligned data words */
+ pdata = (uint32_t *)data;
+ mlen = len/4;
+ data += 4*mlen;
+ len -= 4*mlen;
+ memcpy(r, bch->ecc_buf, sizeof(r));
+
+ /*
+ * split each 32-bit word into 4 polynomials of weight 8 as follows:
+ *
+ * 31 ...24 23 ...16 15 ... 8 7 ... 0
+ * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt
+ * tttttttt mod g = r0 (precomputed)
+ * zzzzzzzz 00000000 mod g = r1 (precomputed)
+ * yyyyyyyy 00000000 00000000 mod g = r2 (precomputed)
+ * xxxxxxxx 00000000 00000000 00000000 mod g = r3 (precomputed)
+ * xxxxxxxx yyyyyyyy zzzzzzzz tttttttt mod g = r0^r1^r2^r3
+ */
+ while (mlen--) {
+ /* input data is read in big-endian format */
+ w = r[0]^cpu_to_be32(*pdata++);
+ p0 = tab0 + (l+1)*((w >> 0) & 0xff);
+ p1 = tab1 + (l+1)*((w >> 8) & 0xff);
+ p2 = tab2 + (l+1)*((w >> 16) & 0xff);
+ p3 = tab3 + (l+1)*((w >> 24) & 0xff);
+
+ for (i = 0; i < l; i++)
+ r[i] = r[i+1]^p0[i]^p1[i]^p2[i]^p3[i];
+
+ r[l] = p0[l]^p1[l]^p2[l]^p3[l];
+ }
+ memcpy(bch->ecc_buf, r, sizeof(r));
+
+ /* process last unaligned bytes */
+ if (len)
+ encode_bch_unaligned(bch, data, len, bch->ecc_buf);
+
+ /* store ecc parity bytes into original parity buffer */
+ if (ecc)
+ store_ecc8(bch, ecc, bch->ecc_buf);
+}
+EXPORT_SYMBOL_GPL(encode_bch);
+
+static inline int modulo(struct bch_control *bch, unsigned int v)
+{
+ const unsigned int n = GF_N(bch);
+ while (v >= n) {
+ v -= n;
+ v = (v & n) + (v >> GF_M(bch));
+ }
+ return v;
+}
+
+/*
+ * shorter and faster modulo function, only works when v < 2N.
+ */
+static inline int mod_s(struct bch_control *bch, unsigned int v)
+{
+ const unsigned int n = GF_N(bch);
+ return (v < n) ? v : v-n;
+}
+
+static inline int deg(unsigned int poly)
+{
+ /* polynomial degree is the most-significant bit index */
+ return fls(poly)-1;
+}
+
+static inline int parity(unsigned int x)
+{
+ /*
+ * public domain code snippet, lifted from
+ * http://www-graphics.stanford.edu/~seander/bithacks.html
+ */
+ x ^= x >> 1;
+ x ^= x >> 2;
+ x = (x & 0x11111111U) * 0x11111111U;
+ return (x >> 28) & 1;
+}
+
+/* Galois field basic operations: multiply, divide, inverse, etc. */
+
+static inline unsigned int gf_mul(struct bch_control *bch, unsigned int a,
+ unsigned int b)
+{
+ return (a && b) ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+ bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_sqr(struct bch_control *bch, unsigned int a)
+{
+ return a ? bch->a_pow_tab[mod_s(bch, 2*bch->a_log_tab[a])] : 0;
+}
+
+static inline unsigned int gf_div(struct bch_control *bch, unsigned int a,
+ unsigned int b)
+{
+ return a ? bch->a_pow_tab[mod_s(bch, bch->a_log_tab[a]+
+ GF_N(bch)-bch->a_log_tab[b])] : 0;
+}
+
+static inline unsigned int gf_inv(struct bch_control *bch, unsigned int a)
+{
+ return bch->a_pow_tab[GF_N(bch)-bch->a_log_tab[a]];
+}
+
+static inline unsigned int a_pow(struct bch_control *bch, int i)
+{
+ return bch->a_pow_tab[modulo(bch, i)];
+}
+
+static inline int a_log(struct bch_control *bch, unsigned int x)
+{
+ return bch->a_log_tab[x];
+}
+
+static inline int a_ilog(struct bch_control *bch, unsigned int x)
+{
+ return mod_s(bch, GF_N(bch)-bch->a_log_tab[x]);
+}
+
+/*
+ * compute 2t syndromes of ecc polynomial, i.e. ecc(a^j) for j=1..2t
+ */
+static void compute_syndromes(struct bch_control *bch, uint32_t *ecc,
+ unsigned int *syn)
+{
+ int i, j, s;
+ unsigned int m;
+ uint32_t poly;
+ const int t = GF_T(bch);
+
+ s = bch->ecc_bits;
+
+ /* make sure extra bits in last ecc word are cleared */
+ m = ((unsigned int)s) & 31;
+ if (m)
+ ecc[s/32] &= ~((1u << (32-m))-1);
+ memset(syn, 0, 2*t*sizeof(*syn));
+
+ /* compute v(a^j) for j=1 .. 2t-1 */
+ do {
+ poly = *ecc++;
+ s -= 32;
+ while (poly) {
+ i = deg(poly);
+ for (j = 0; j < 2*t; j += 2)
+ syn[j] ^= a_pow(bch, (j+1)*(i+s));
+
+ poly ^= (1 << i);
+ }
+ } while (s > 0);
+
+ /* v(a^(2j)) = v(a^j)^2 */
+ for (j = 0; j < t; j++)
+ syn[2*j+1] = gf_sqr(bch, syn[j]);
+}
+
+static void gf_poly_copy(struct gf_poly *dst, struct gf_poly *src)
+{
+ memcpy(dst, src, GF_POLY_SZ(src->deg));
+}
+
+static int compute_error_locator_polynomial(struct bch_control *bch,
+ const unsigned int *syn)
+{
+ const unsigned int t = GF_T(bch);
+ const unsigned int n = GF_N(bch);
+ unsigned int i, j, tmp, l, pd = 1, d = syn[0];
+ struct gf_poly *elp = bch->elp;
+ struct gf_poly *pelp = bch->poly_2t[0];
+ struct gf_poly *elp_copy = bch->poly_2t[1];
+ int k, pp = -1;
+
+ memset(pelp, 0, GF_POLY_SZ(2*t));
+ memset(elp, 0, GF_POLY_SZ(2*t));
+
+ pelp->deg = 0;
+ pelp->c[0] = 1;
+ elp->deg = 0;
+ elp->c[0] = 1;
+
+ /* use simplified binary Berlekamp-Massey algorithm */
+ for (i = 0; (i < t) && (elp->deg <= t); i++) {
+ if (d) {
+ k = 2*i-pp;
+ gf_poly_copy(elp_copy, elp);
+ /* e[i+1](X) = e[i](X)+di*dp^-1*X^2(i-p)*e[p](X) */
+ tmp = a_log(bch, d)+n-a_log(bch, pd);
+ for (j = 0; j <= pelp->deg; j++) {
+ if (pelp->c[j]) {
+ l = a_log(bch, pelp->c[j]);
+ elp->c[j+k] ^= a_pow(bch, tmp+l);
+ }
+ }
+ /* compute l[i+1] = max(l[i]->c[l[p]+2*(i-p]) */
+ tmp = pelp->deg+k;
+ if (tmp > elp->deg) {
+ elp->deg = tmp;
+ gf_poly_copy(pelp, elp_copy);
+ pd = d;
+ pp = 2*i;
+ }
+ }
+ /* di+1 = S(2i+3)+elp[i+1].1*S(2i+2)+...+elp[i+1].lS(2i+3-l) */
+ if (i < t-1) {
+ d = syn[2*i+2];
+ for (j = 1; j <= elp->deg; j++)
+ d ^= gf_mul(bch, elp->c[j], syn[2*i+2-j]);
+ }
+ }
+ dbg("elp=%s\n", gf_poly_str(elp));
+ return (elp->deg > t) ? -1 : (int)elp->deg;
+}
+
+/*
+ * solve a m x m linear system in GF(2) with an expected number of solutions,
+ * and return the number of found solutions
+ */
+static int solve_linear_system(struct bch_control *bch, unsigned int *rows,
+ unsigned int *sol, int nsol)
+{
+ const int m = GF_M(bch);
+ unsigned int tmp, mask;
+ int rem, c, r, p, k, param[m];
+
+ k = 0;
+ mask = 1 << m;
+
+ /* Gaussian elimination */
+ for (c = 0; c < m; c++) {
+ rem = 0;
+ p = c-k;
+ /* find suitable row for elimination */
+ for (r = p; r < m; r++) {
+ if (rows[r] & mask) {
+ if (r != p) {
+ tmp = rows[r];
+ rows[r] = rows[p];
+ rows[p] = tmp;
+ }
+ rem = r+1;
+ break;
+ }
+ }
+ if (rem) {
+ /* perform elimination on remaining rows */
+ tmp = rows[p];
+ for (r = rem; r < m; r++) {
+ if (rows[r] & mask)
+ rows[r] ^= tmp;
+ }
+ } else {
+ /* elimination not needed, store defective row index */
+ param[k++] = c;
+ }
+ mask >>= 1;
+ }
+ /* rewrite system, inserting fake parameter rows */
+ if (k > 0) {
+ p = k;
+ for (r = m-1; r >= 0; r--) {
+ if ((r > m-1-k) && rows[r])
+ /* system has no solution */
+ return 0;
+
+ rows[r] = (p && (r == param[p-1])) ?
+ p--, 1u << (m-r) : rows[r-p];
+ }
+ }
+
+ if (nsol != (1 << k))
+ /* unexpected number of solutions */
+ return 0;
+
+ for (p = 0; p < nsol; p++) {
+ /* set parameters for p-th solution */
+ for (c = 0; c < k; c++)
+ rows[param[c]] = (rows[param[c]] & ~1)|((p >> c) & 1);
+
+ /* compute unique solution */
+ tmp = 0;
+ for (r = m-1; r >= 0; r--) {
+ mask = rows[r] & (tmp|1);
+ tmp |= parity(mask) << (m-r);
+ }
+ sol[p] = tmp >> 1;
+ }
+ return nsol;
+}
+
+/*
+ * this function builds and solves a linear system for finding roots of a degree
+ * 4 affine monic polynomial X^4+aX^2+bX+c over GF(2^m).
+ */
+static int find_affine4_roots(struct bch_control *bch, unsigned int a,
+ unsigned int b, unsigned int c,
+ unsigned int *roots)
+{
+ int i, j, k;
+ const int m = GF_M(bch);
+ unsigned int mask = 0xff, t, rows[16] = {0,};
+
+ j = a_log(bch, b);
+ k = a_log(bch, a);
+ rows[0] = c;
+
+ /* buid linear system to solve X^4+aX^2+bX+c = 0 */
+ for (i = 0; i < m; i++) {
+ rows[i+1] = bch->a_pow_tab[4*i]^
+ (a ? bch->a_pow_tab[mod_s(bch, k)] : 0)^
+ (b ? bch->a_pow_tab[mod_s(bch, j)] : 0);
+ j++;
+ k += 2;
+ }
+ /*
+ * transpose 16x16 matrix before passing it to linear solver
+ * warning: this code assumes m < 16
+ */
+ for (j = 8; j != 0; j >>= 1, mask ^= (mask << j)) {
+ for (k = 0; k < 16; k = (k+j+1) & ~j) {
+ t = ((rows[k] >> j)^rows[k+j]) & mask;
+ rows[k] ^= (t << j);
+ rows[k+j] ^= t;
+ }
+ }
+ return solve_linear_system(bch, rows, roots, 4);
+}
+
+/*
+ * compute root r of a degree 1 polynomial over GF(2^m) (returned as log(1/r))
+ */
+static int find_poly_deg1_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int n = 0;
+
+ if (poly->c[0])
+ /* poly[X] = bX+c with c!=0, root=c/b */
+ roots[n++] = mod_s(bch, GF_N(bch)-bch->a_log_tab[poly->c[0]]+
+ bch->a_log_tab[poly->c[1]]);
+ return n;
+}
+
+/*
+ * compute roots of a degree 2 polynomial over GF(2^m)
+ */
+static int find_poly_deg2_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int n = 0, i, l0, l1, l2;
+ unsigned int u, v, r;
+
+ if (poly->c[0] && poly->c[1]) {
+
+ l0 = bch->a_log_tab[poly->c[0]];
+ l1 = bch->a_log_tab[poly->c[1]];
+ l2 = bch->a_log_tab[poly->c[2]];
+
+ /* using z=a/bX, transform aX^2+bX+c into z^2+z+u (u=ac/b^2) */
+ u = a_pow(bch, l0+l2+2*(GF_N(bch)-l1));
+ /*
+ * let u = sum(li.a^i) i=0..m-1; then compute r = sum(li.xi):
+ * r^2+r = sum(li.(xi^2+xi)) = sum(li.(a^i+Tr(a^i).a^k)) =
+ * u + sum(li.Tr(a^i).a^k) = u+a^k.Tr(sum(li.a^i)) = u+a^k.Tr(u)
+ * i.e. r and r+1 are roots iff Tr(u)=0
+ */
+ r = 0;
+ v = u;
+ while (v) {
+ i = deg(v);
+ r ^= bch->xi_tab[i];
+ v ^= (1 << i);
+ }
+ /* verify root */
+ if ((gf_sqr(bch, r)^r) == u) {
+ /* reverse z=a/bX transformation and compute log(1/r) */
+ roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+ bch->a_log_tab[r]+l2);
+ roots[n++] = modulo(bch, 2*GF_N(bch)-l1-
+ bch->a_log_tab[r^1]+l2);
+ }
+ }
+ return n;
+}
+
+/*
+ * compute roots of a degree 3 polynomial over GF(2^m)
+ */
+static int find_poly_deg3_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int i, n = 0;
+ unsigned int a, b, c, a2, b2, c2, e3, tmp[4];
+
+ if (poly->c[0]) {
+ /* transform polynomial into monic X^3 + a2X^2 + b2X + c2 */
+ e3 = poly->c[3];
+ c2 = gf_div(bch, poly->c[0], e3);
+ b2 = gf_div(bch, poly->c[1], e3);
+ a2 = gf_div(bch, poly->c[2], e3);
+
+ /* (X+a2)(X^3+a2X^2+b2X+c2) = X^4+aX^2+bX+c (affine) */
+ c = gf_mul(bch, a2, c2); /* c = a2c2 */
+ b = gf_mul(bch, a2, b2)^c2; /* b = a2b2 + c2 */
+ a = gf_sqr(bch, a2)^b2; /* a = a2^2 + b2 */
+
+ /* find the 4 roots of this affine polynomial */
+ if (find_affine4_roots(bch, a, b, c, tmp) == 4) {
+ /* remove a2 from final list of roots */
+ for (i = 0; i < 4; i++) {
+ if (tmp[i] != a2)
+ roots[n++] = a_ilog(bch, tmp[i]);
+ }
+ }
+ }
+ return n;
+}
+
+/*
+ * compute roots of a degree 4 polynomial over GF(2^m)
+ */
+static int find_poly_deg4_roots(struct bch_control *bch, struct gf_poly *poly,
+ unsigned int *roots)
+{
+ int i, l, n = 0;
+ unsigned int a, b, c, d, e = 0, f, a2, b2, c2, e4;
+
+ if (poly->c[0] == 0)
+ return 0;
+
+ /* transform polynomial into monic X^4 + aX^3 + bX^2 + cX + d */
+ e4 = poly->c[4];
+ d = gf_div(bch, poly->c[0], e4);
+ c = gf_div(bch, poly->c[1], e4);
+ b = gf_div(bch, poly->c[2], e4);
+ a = gf_div(bch, poly->c[3], e4);
+
+ /* use Y=1/X transformation to get an affine polynomial */
+ if (a) {
+ /* first, eliminate cX by using z=X+e with ae^2+c=0 */
+ if (c) {
+ /* compute e such that e^2 = c/a */
+ f = gf_div(bch, c, a);
+ l = a_log(bch, f);
+ l += (l & 1) ? GF_N(bch) : 0;
+ e = a_pow(bch, l/2);
+ /*
+ * use transformation z=X+e:
+ * z^4+e^4 + a(z^3+ez^2+e^2z+e^3) + b(z^2+e^2) +cz+ce+d
+ * z^4 + az^3 + (ae+b)z^2 + (ae^2+c)z+e^4+be^2+ae^3+ce+d
+ * z^4 + az^3 + (ae+b)z^2 + e^4+be^2+d
+ * z^4 + az^3 + b'z^2 + d'
+ */
+ d = a_pow(bch, 2*l)^gf_mul(bch, b, f)^d;
+ b = gf_mul(bch, a, e)^b;
+ }
+ /* now, use Y=1/X to get Y^4 + b/dY^2 + a/dY + 1/d */
+ if (d == 0)
+ /* assume all roots have multiplicity 1 */
+ return 0;
+
+ c2 = gf_inv(bch, d);
+ b2 = gf_div(bch, a, d);
+ a2 = gf_div(bch, b, d);
+ } else {
+ /* polynomial is already affine */
+ c2 = d;
+ b2 = c;
+ a2 = b;
+ }
+ /* find the 4 roots of this affine polynomial */
+ if (find_affine4_roots(bch, a2, b2, c2, roots) == 4) {
+ for (i = 0; i < 4; i++) {
+ /* post-process roots (reverse transformations) */
+ f = a ? gf_inv(bch, roots[i]) : roots[i];
+ roots[i] = a_ilog(bch, f^e);
+ }
+ n = 4;
+ }
+ return n;
+}
+
+/*
+ * build monic, log-based representation of a polynomial
+ */
+static void gf_poly_logrep(struct bch_control *bch,
+ const struct gf_poly *a, int *rep)
+{
+ int i, d = a->deg, l = GF_N(bch)-a_log(bch, a->c[a->deg]);
+
+ /* represent 0 values with -1; warning, rep[d] is not set to 1 */
+ for (i = 0; i < d; i++)
+ rep[i] = a->c[i] ? mod_s(bch, a_log(bch, a->c[i])+l) : -1;
+}
+
+/*
+ * compute polynomial Euclidean division remainder in GF(2^m)[X]
+ */
+static void gf_poly_mod(struct bch_control *bch, struct gf_poly *a,
+ const struct gf_poly *b, int *rep)
+{
+ int la, p, m;
+ unsigned int i, j, *c = a->c;
+ const unsigned int d = b->deg;
+
+ if (a->deg < d)
+ return;
+
+ /* reuse or compute log representation of denominator */
+ if (!rep) {
+ rep = bch->cache;
+ gf_poly_logrep(bch, b, rep);
+ }
+
+ for (j = a->deg; j >= d; j--) {
+ if (c[j]) {
+ la = a_log(bch, c[j]);
+ p = j-d;
+ for (i = 0; i < d; i++, p++) {
+ m = rep[i];
+ if (m >= 0)
+ c[p] ^= bch->a_pow_tab[mod_s(bch,
+ m+la)];
+ }
+ }
+ }
+ a->deg = d-1;
+ while (!c[a->deg] && a->deg)
+ a->deg--;
+}
+
+/*
+ * compute polynomial Euclidean division quotient in GF(2^m)[X]
+ */
+static void gf_poly_div(struct bch_control *bch, struct gf_poly *a,
+ const struct gf_poly *b, struct gf_poly *q)
+{
+ if (a->deg >= b->deg) {
+ q->deg = a->deg-b->deg;
+ /* compute a mod b (modifies a) */
+ gf_poly_mod(bch, a, b, NULL);
+ /* quotient is stored in upper part of polynomial a */
+ memcpy(q->c, &a->c[b->deg], (1+q->deg)*sizeof(unsigned int));
+ } else {
+ q->deg = 0;
+ q->c[0] = 0;
+ }
+}
+
+/*
+ * compute polynomial GCD (Greatest Common Divisor) in GF(2^m)[X]
+ */
+static struct gf_poly *gf_poly_gcd(struct bch_control *bch, struct gf_poly *a,
+ struct gf_poly *b)
+{
+ struct gf_poly *tmp;
+
+ dbg("gcd(%s,%s)=", gf_poly_str(a), gf_poly_str(b));
+
+ if (a->deg < b->deg) {
+ tmp = b;
+ b = a;
+ a = tmp;
+ }
+
+ while (b->deg > 0) {
+ gf_poly_mod(bch, a, b, NULL);
+ tmp = b;
+ b = a;
+ a = tmp;
+ }
+
+ dbg("%s\n", gf_poly_str(a));
+
+ return a;
+}
+
+/*
+ * Given a polynomial f and an integer k, compute Tr(a^kX) mod f
+ * This is used in Berlekamp Trace algorithm for splitting polynomials
+ */
+static void compute_trace_bk_mod(struct bch_control *bch, int k,
+ const struct gf_poly *f, struct gf_poly *z,
+ struct gf_poly *out)
+{
+ const int m = GF_M(bch);
+ int i, j;
+
+ /* z contains z^2j mod f */
+ z->deg = 1;
+ z->c[0] = 0;
+ z->c[1] = bch->a_pow_tab[k];
+
+ out->deg = 0;
+ memset(out, 0, GF_POLY_SZ(f->deg));
+
+ /* compute f log representation only once */
+ gf_poly_logrep(bch, f, bch->cache);
+
+ for (i = 0; i < m; i++) {
+ /* add a^(k*2^i)(z^(2^i) mod f) and compute (z^(2^i) mod f)^2 */
+ for (j = z->deg; j >= 0; j--) {
+ out->c[j] ^= z->c[j];
+ z->c[2*j] = gf_sqr(bch, z->c[j]);
+ z->c[2*j+1] = 0;
+ }
+ if (z->deg > out->deg)
+ out->deg = z->deg;
+
+ if (i < m-1) {
+ z->deg *= 2;
+ /* z^(2(i+1)) mod f = (z^(2^i) mod f)^2 mod f */
+ gf_poly_mod(bch, z, f, bch->cache);
+ }
+ }
+ while (!out->c[out->deg] && out->deg)
+ out->deg--;
+
+ dbg("Tr(a^%d.X) mod f = %s\n", k, gf_poly_str(out));
+}
+
+/*
+ * factor a polynomial using Berlekamp Trace algorithm (BTA)
+ */
+static void factor_polynomial(struct bch_control *bch, int k, struct gf_poly *f,
+ struct gf_poly **g, struct gf_poly **h)
+{
+ struct gf_poly *f2 = bch->poly_2t[0];
+ struct gf_poly *q = bch->poly_2t[1];
+ struct gf_poly *tk = bch->poly_2t[2];
+ struct gf_poly *z = bch->poly_2t[3];
+ struct gf_poly *gcd;
+
+ dbg("factoring %s...\n", gf_poly_str(f));
+
+ *g = f;
+ *h = NULL;
+
+ /* tk = Tr(a^k.X) mod f */
+ compute_trace_bk_mod(bch, k, f, z, tk);
+
+ if (tk->deg > 0) {
+ /* compute g = gcd(f, tk) (destructive operation) */
+ gf_poly_copy(f2, f);
+ gcd = gf_poly_gcd(bch, f2, tk);
+ if (gcd->deg < f->deg) {
+ /* compute h=f/gcd(f,tk); this will modify f and q */
+ gf_poly_div(bch, f, gcd, q);
+ /* store g and h in-place (clobbering f) */
+ *h = &((struct gf_poly_deg1 *)f)[gcd->deg].poly;
+ gf_poly_copy(*g, gcd);
+ gf_poly_copy(*h, q);
+ }
+ }
+}
+
+/*
+ * find roots of a polynomial, using BTZ algorithm; see the beginning of this
+ * file for details
+ */
+static int find_poly_roots(struct bch_control *bch, unsigned int k,
+ struct gf_poly *poly, unsigned int *roots)
+{
+ int cnt;
+ struct gf_poly *f1, *f2;
+
+ switch (poly->deg) {
+ /* handle low degree polynomials with ad hoc techniques */
+ case 1:
+ cnt = find_poly_deg1_roots(bch, poly, roots);
+ break;
+ case 2:
+ cnt = find_poly_deg2_roots(bch, poly, roots);
+ break;
+ case 3:
+ cnt = find_poly_deg3_roots(bch, poly, roots);
+ break;
+ case 4:
+ cnt = find_poly_deg4_roots(bch, poly, roots);
+ break;
+ default:
+ /* factor polynomial using Berlekamp Trace Algorithm (BTA) */
+ cnt = 0;
+ if (poly->deg && (k <= GF_M(bch))) {
+ factor_polynomial(bch, k, poly, &f1, &f2);
+ if (f1)
+ cnt += find_poly_roots(bch, k+1, f1, roots);
+ if (f2)
+ cnt += find_poly_roots(bch, k+1, f2, roots+cnt);
+ }
+ break;
+ }
+ return cnt;
+}
+
+#if defined(USE_CHIEN_SEARCH)
+/*
+ * exhaustive root search (Chien) implementation - not used, included only for
+ * reference/comparison tests
+ */
+static int chien_search(struct bch_control *bch, unsigned int len,
+ struct gf_poly *p, unsigned int *roots)
+{
+ int m;
+ unsigned int i, j, syn, syn0, count = 0;
+ const unsigned int k = 8*len+bch->ecc_bits;
+
+ /* use a log-based representation of polynomial */
+ gf_poly_logrep(bch, p, bch->cache);
+ bch->cache[p->deg] = 0;
+ syn0 = gf_div(bch, p->c[0], p->c[p->deg]);
+
+ for (i = GF_N(bch)-k+1; i <= GF_N(bch); i++) {
+ /* compute elp(a^i) */
+ for (j = 1, syn = syn0; j <= p->deg; j++) {
+ m = bch->cache[j];
+ if (m >= 0)
+ syn ^= a_pow(bch, m+j*i);
+ }
+ if (syn == 0) {
+ roots[count++] = GF_N(bch)-i;
+ if (count == p->deg)
+ break;
+ }
+ }
+ return (count == p->deg) ? count : 0;
+}
+#define find_poly_roots(_p, _k, _elp, _loc) chien_search(_p, len, _elp, _loc)
+#endif /* USE_CHIEN_SEARCH */
+
+/**
+ * decode_bch - decode received codeword and find bit error locations
+ * @bch: BCH control structure
+ * @data: received data, ignored if @calc_ecc is provided
+ * @len: data length in bytes, must always be provided
+ * @recv_ecc: received ecc, if NULL then assume it was XORed in @calc_ecc
+ * @calc_ecc: calculated ecc, if NULL then calc_ecc is computed from @data
+ * @syn: hw computed syndrome data (if NULL, syndrome is calculated)
+ * @errloc: output array of error locations
+ *
+ * Returns:
+ * The number of errors found, or -EBADMSG if decoding failed, or -EINVAL if
+ * invalid parameters were provided
+ *
+ * Depending on the available hw BCH support and the need to compute @calc_ecc
+ * separately (using encode_bch()), this function should be called with one of
+ * the following parameter configurations -
+ *
+ * by providing @data and @recv_ecc only:
+ * decode_bch(@bch, @data, @len, @recv_ecc, NULL, NULL, @errloc)
+ *
+ * by providing @recv_ecc and @calc_ecc:
+ * decode_bch(@bch, NULL, @len, @recv_ecc, @calc_ecc, NULL, @errloc)
+ *
+ * by providing ecc = recv_ecc XOR calc_ecc:
+ * decode_bch(@bch, NULL, @len, NULL, ecc, NULL, @errloc)
+ *
+ * by providing syndrome results @syn:
+ * decode_bch(@bch, NULL, @len, NULL, NULL, @syn, @errloc)
+ *
+ * Once decode_bch() has successfully returned with a positive value, error
+ * locations returned in array @errloc should be interpreted as follows -
+ *
+ * if (errloc[n] >= 8*len), then n-th error is located in ecc (no need for
+ * data correction)
+ *
+ * if (errloc[n] < 8*len), then n-th error is located in data and can be
+ * corrected with statement data[errloc[n]/8] ^= 1 << (errloc[n] % 8);
+ *
+ * Note that this function does not perform any data correction by itself, it
+ * merely indicates error locations.
+ */
+int decode_bch(struct bch_control *bch, const uint8_t *data, unsigned int len,
+ const uint8_t *recv_ecc, const uint8_t *calc_ecc,
+ const unsigned int *syn, unsigned int *errloc)
+{
+ const unsigned int ecc_words = BCH_ECC_WORDS(bch);
+ unsigned int nbits;
+ int i, err, nroots;
+ uint32_t sum;
+
+ /* sanity check: make sure data length can be handled */
+ if (8*len > (bch->n-bch->ecc_bits))
+ return -EINVAL;
+
+ /* if caller does not provide syndromes, compute them */
+ if (!syn) {
+ if (!calc_ecc) {
+ /* compute received data ecc into an internal buffer */
+ if (!data || !recv_ecc)
+ return -EINVAL;
+ encode_bch(bch, data, len, NULL);
+ } else {
+ /* load provided calculated ecc */
+ load_ecc8(bch, bch->ecc_buf, calc_ecc);
+ }
+ /* load received ecc or assume it was XORed in calc_ecc */
+ if (recv_ecc) {
+ load_ecc8(bch, bch->ecc_buf2, recv_ecc);
+ /* XOR received and calculated ecc */
+ for (i = 0, sum = 0; i < (int)ecc_words; i++) {
+ bch->ecc_buf[i] ^= bch->ecc_buf2[i];
+ sum |= bch->ecc_buf[i];
+ }
+ if (!sum)
+ /* no error found */
+ return 0;
+ }
+ compute_syndromes(bch, bch->ecc_buf, bch->syn);
+ syn = bch->syn;
+ }
+
+ err = compute_error_locator_polynomial(bch, syn);
+ if (err > 0) {
+ nroots = find_poly_roots(bch, 1, bch->elp, errloc);
+ if (err != nroots)
+ err = -1;
+ }
+ if (err > 0) {
+ /* post-process raw error locations for easier correction */
+ nbits = (len*8)+bch->ecc_bits;
+ for (i = 0; i < err; i++) {
+ if (errloc[i] >= nbits) {
+ err = -1;
+ break;
+ }
+ errloc[i] = nbits-1-errloc[i];
+ errloc[i] = (errloc[i] & ~7)|(7-(errloc[i] & 7));
+ }
+ }
+ return (err >= 0) ? err : -EBADMSG;
+}
+EXPORT_SYMBOL_GPL(decode_bch);
+
+/*
+ * generate Galois field lookup tables
+ */
+static int build_gf_tables(struct bch_control *bch, unsigned int poly)
+{
+ unsigned int i, x = 1;
+ const unsigned int k = 1 << deg(poly);
+
+ /* primitive polynomial must be of degree m */
+ if (k != (1u << GF_M(bch)))
+ return -1;
+
+ for (i = 0; i < GF_N(bch); i++) {
+ bch->a_pow_tab[i] = x;
+ bch->a_log_tab[x] = i;
+ if (i && (x == 1))
+ /* polynomial is not primitive (a^i=1 with 0<i<2^m-1) */
+ return -1;
+ x <<= 1;
+ if (x & k)
+ x ^= poly;
+ }
+ bch->a_pow_tab[GF_N(bch)] = 1;
+ bch->a_log_tab[0] = 0;
+
+ return 0;
+}
+
+/*
+ * compute generator polynomial remainder tables for fast encoding
+ */
+static void build_mod8_tables(struct bch_control *bch, const uint32_t *g)
+{
+ int i, j, b, d;
+ uint32_t data, hi, lo, *tab;
+ const int l = BCH_ECC_WORDS(bch);
+ const int plen = DIV_ROUND_UP(bch->ecc_bits+1, 32);
+ const int ecclen = DIV_ROUND_UP(bch->ecc_bits, 32);
+
+ memset(bch->mod8_tab, 0, 4*256*l*sizeof(*bch->mod8_tab));
+
+ for (i = 0; i < 256; i++) {
+ /* p(X)=i is a small polynomial of weight <= 8 */
+ for (b = 0; b < 4; b++) {
+ /* we want to compute (p(X).X^(8*b+deg(g))) mod g(X) */
+ tab = bch->mod8_tab + (b*256+i)*l;
+ data = i << (8*b);
+ while (data) {
+ d = deg(data);
+ /* subtract X^d.g(X) from p(X).X^(8*b+deg(g)) */
+ data ^= g[0] >> (31-d);
+ for (j = 0; j < ecclen; j++) {
+ hi = (d < 31) ? g[j] << (d+1) : 0;
+ lo = (j+1 < plen) ?
+ g[j+1] >> (31-d) : 0;
+ tab[j] ^= hi|lo;
+ }
+ }
+ }
+ }
+}
+
+/*
+ * build a base for factoring degree 2 polynomials
+ */
+static int build_deg2_base(struct bch_control *bch)
+{
+ const int m = GF_M(bch);
+ int i, j, r;
+ unsigned int sum, x, y, remaining, ak = 0, xi[m];
+
+ /* find k s.t. Tr(a^k) = 1 and 0 <= k < m */
+ for (i = 0; i < m; i++) {
+ for (j = 0, sum = 0; j < m; j++)
+ sum ^= a_pow(bch, i*(1 << j));
+
+ if (sum) {
+ ak = bch->a_pow_tab[i];
+ break;
+ }
+ }
+ /* find xi, i=0..m-1 such that xi^2+xi = a^i+Tr(a^i).a^k */
+ remaining = m;
+ memset(xi, 0, sizeof(xi));
+
+ for (x = 0; (x <= GF_N(bch)) && remaining; x++) {
+ y = gf_sqr(bch, x)^x;
+ for (i = 0; i < 2; i++) {
+ r = a_log(bch, y);
+ if (y && (r < m) && !xi[r]) {
+ bch->xi_tab[r] = x;
+ xi[r] = 1;
+ remaining--;
+ dbg("x%d = %x\n", r, x);
+ break;
+ }
+ y ^= ak;
+ }
+ }
+ /* should not happen but check anyway */
+ return remaining ? -1 : 0;
+}
+
+static void *bch_alloc(size_t size, int *err)
+{
+ void *ptr;
+
+ ptr = kmalloc(size, GFP_KERNEL);
+ if (ptr == NULL)
+ *err = 1;
+ return ptr;
+}
+
+/*
+ * compute generator polynomial for given (m,t) parameters.
+ */
+static uint32_t *compute_generator_polynomial(struct bch_control *bch)
+{
+ const unsigned int m = GF_M(bch);
+ const unsigned int t = GF_T(bch);
+ int n, err = 0;
+ unsigned int i, j, nbits, r, word, *roots;
+ struct gf_poly *g;
+ uint32_t *genpoly;
+
+ g = bch_alloc(GF_POLY_SZ(m*t), &err);
+ roots = bch_alloc((bch->n+1)*sizeof(*roots), &err);
+ genpoly = bch_alloc(DIV_ROUND_UP(m*t+1, 32)*sizeof(*genpoly), &err);
+
+ if (err) {
+ kfree(genpoly);
+ genpoly = NULL;
+ goto finish;
+ }
+
+ /* enumerate all roots of g(X) */
+ memset(roots , 0, (bch->n+1)*sizeof(*roots));
+ for (i = 0; i < t; i++) {
+ for (j = 0, r = 2*i+1; j < m; j++) {
+ roots[r] = 1;
+ r = mod_s(bch, 2*r);
+ }
+ }
+ /* build generator polynomial g(X) */
+ g->deg = 0;
+ g->c[0] = 1;
+ for (i = 0; i < GF_N(bch); i++) {
+ if (roots[i]) {
+ /* multiply g(X) by (X+root) */
+ r = bch->a_pow_tab[i];
+ g->c[g->deg+1] = 1;
+ for (j = g->deg; j > 0; j--)
+ g->c[j] = gf_mul(bch, g->c[j], r)^g->c[j-1];
+
+ g->c[0] = gf_mul(bch, g->c[0], r);
+ g->deg++;
+ }
+ }
+ /* store left-justified binary representation of g(X) */
+ n = g->deg+1;
+ i = 0;
+
+ while (n > 0) {
+ nbits = (n > 32) ? 32 : n;
+ for (j = 0, word = 0; j < nbits; j++) {
+ if (g->c[n-1-j])
+ word |= 1u << (31-j);
+ }
+ genpoly[i++] = word;
+ n -= nbits;
+ }
+ bch->ecc_bits = g->deg;
+
+finish:
+ kfree(g);
+ kfree(roots);
+
+ return genpoly;
+}
+
+/**
+ * init_bch - initialize a BCH encoder/decoder
+ * @m: Galois field order, should be in the range 5-15
+ * @t: maximum error correction capability, in bits
+ * @prim_poly: user-provided primitive polynomial (or 0 to use default)
+ *
+ * Returns:
+ * a newly allocated BCH control structure if successful, NULL otherwise
+ *
+ * This initialization can take some time, as lookup tables are built for fast
+ * encoding/decoding; make sure not to call this function from a time critical
+ * path. Usually, init_bch() should be called on module/driver init and
+ * free_bch() should be called to release memory on exit.
+ *
+ * You may provide your own primitive polynomial of degree @m in argument
+ * @prim_poly, or let init_bch() use its default polynomial.
+ *
+ * Once init_bch() has successfully returned a pointer to a newly allocated
+ * BCH control structure, ecc length in bytes is given by member @ecc_bytes of
+ * the structure.
+ */
+struct bch_control *init_bch(int m, int t, unsigned int prim_poly)
+{
+ int err = 0;
+ unsigned int i, words;
+ uint32_t *genpoly;
+ struct bch_control *bch = NULL;
+
+ const int min_m = 5;
+ const int max_m = 15;
+
+ /* default primitive polynomials */
+ static const unsigned int prim_poly_tab[] = {
+ 0x25, 0x43, 0x83, 0x11d, 0x211, 0x409, 0x805, 0x1053, 0x201b,
+ 0x402b, 0x8003,
+ };
+
+#if defined(CONFIG_BCH_CONST_PARAMS)
+ if ((m != (CONFIG_BCH_CONST_M)) || (t != (CONFIG_BCH_CONST_T))) {
+ printk(KERN_ERR "bch encoder/decoder was configured to support "
+ "parameters m=%d, t=%d only!\n",
+ CONFIG_BCH_CONST_M, CONFIG_BCH_CONST_T);
+ goto fail;
+ }
+#endif
+ if ((m < min_m) || (m > max_m))
+ /*
+ * values of m greater than 15 are not currently supported;
+ * supporting m > 15 would require changing table base type
+ * (uint16_t) and a small patch in matrix transposition
+ */
+ goto fail;
+
+ /* sanity checks */
+ if ((t < 1) || (m*t >= ((1 << m)-1)))
+ /* invalid t value */
+ goto fail;
+
+ /* select a primitive polynomial for generating GF(2^m) */
+ if (prim_poly == 0)
+ prim_poly = prim_poly_tab[m-min_m];
+
+ bch = kzalloc(sizeof(*bch), GFP_KERNEL);
+ if (bch == NULL)
+ goto fail;
+
+ bch->m = m;
+ bch->t = t;
+ bch->n = (1 << m)-1;
+ words = DIV_ROUND_UP(m*t, 32);
+ bch->ecc_bytes = DIV_ROUND_UP(m*t, 8);
+ bch->a_pow_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_pow_tab), &err);
+ bch->a_log_tab = bch_alloc((1+bch->n)*sizeof(*bch->a_log_tab), &err);
+ bch->mod8_tab = bch_alloc(words*1024*sizeof(*bch->mod8_tab), &err);
+ bch->ecc_buf = bch_alloc(words*sizeof(*bch->ecc_buf), &err);
+ bch->ecc_buf2 = bch_alloc(words*sizeof(*bch->ecc_buf2), &err);
+ bch->xi_tab = bch_alloc(m*sizeof(*bch->xi_tab), &err);
+ bch->syn = bch_alloc(2*t*sizeof(*bch->syn), &err);
+ bch->cache = bch_alloc(2*t*sizeof(*bch->cache), &err);
+ bch->elp = bch_alloc((t+1)*sizeof(struct gf_poly_deg1), &err);
+
+ for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+ bch->poly_2t[i] = bch_alloc(GF_POLY_SZ(2*t), &err);
+
+ if (err)
+ goto fail;
+
+ err = build_gf_tables(bch, prim_poly);
+ if (err)
+ goto fail;
+
+ /* use generator polynomial for computing encoding tables */
+ genpoly = compute_generator_polynomial(bch);
+ if (genpoly == NULL)
+ goto fail;
+
+ build_mod8_tables(bch, genpoly);
+ kfree(genpoly);
+
+ err = build_deg2_base(bch);
+ if (err)
+ goto fail;
+
+ return bch;
+
+fail:
+ free_bch(bch);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(init_bch);
+
+/**
+ * free_bch - free the BCH control structure
+ * @bch: BCH control structure to release
+ */
+void free_bch(struct bch_control *bch)
+{
+ unsigned int i;
+
+ if (bch) {
+ kfree(bch->a_pow_tab);
+ kfree(bch->a_log_tab);
+ kfree(bch->mod8_tab);
+ kfree(bch->ecc_buf);
+ kfree(bch->ecc_buf2);
+ kfree(bch->xi_tab);
+ kfree(bch->syn);
+ kfree(bch->cache);
+ kfree(bch->elp);
+
+ for (i = 0; i < ARRAY_SIZE(bch->poly_2t); i++)
+ kfree(bch->poly_2t[i]);
+
+ kfree(bch);
+ }
+}
+EXPORT_SYMBOL_GPL(free_bch);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
+MODULE_DESCRIPTION("Binary BCH encoder/decoder");
diff --git a/lib/bitrev.c b/lib/bitrev.c
new file mode 100644
index 0000000000..2662760e74
--- /dev/null
+++ b/lib/bitrev.c
@@ -0,0 +1,68 @@
+/*
+ * Bit reversal module
+ *
+ * Copyright (C) Akinobu Mita
+ *
+ * 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.
+ *
+ * Taken from linux kernel.
+ */
+#include <linux/types.h>
+#include <linux/bitrev.h>
+
+const u8 byte_rev_table[256] = {
+ 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
+ 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
+ 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
+ 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
+ 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
+ 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
+ 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
+ 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
+ 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
+ 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
+ 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
+ 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
+ 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
+ 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
+ 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
+ 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
+ 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
+ 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
+ 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
+ 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
+ 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
+ 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
+ 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
+ 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
+ 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
+ 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
+ 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
+ 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
+ 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
+ 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
+ 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
+ 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
+};
+
+u16 bitrev16(u16 x)
+{
+ return (bitrev8(x & 0xff) << 8) | bitrev8(x >> 8);
+}
+
+/**
+ * bitrev32 - reverse the order of bits in a u32 value
+ * @x: value to be bit-reversed
+ */
+u32 bitrev32(u32 x)
+{
+ return (bitrev16(x & 0xffff) << 16) | bitrev16(x >> 16);
+}
diff --git a/lib/libbb.c b/lib/libbb.c
index 3d02202634..9a0a60bdb8 100644
--- a/lib/libbb.c
+++ b/lib/libbb.c
@@ -127,3 +127,53 @@ char *simple_itoa(unsigned int i)
return p + 1;
}
EXPORT_SYMBOL(simple_itoa);
+
+/*
+ * write_full - write to filedescriptor
+ *
+ * Like write, but guarantees to write the full buffer out, else
+ * it returns with an error.
+ */
+int write_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+
+ while (size) {
+ now = write(fd, buf, size);
+ if (now <= 0)
+ return now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(write_full);
+
+/*
+ * read_full - read from filedescriptor
+ *
+ * Like read, but this function only returns less bytes than
+ * requested when the end of file is reached.
+ */
+int read_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+ int total = 0;
+
+ while (size) {
+ now = read(fd, buf, size);
+ if (now == 0)
+ return total;
+ if (now < 0)
+ return now;
+ total += now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(read_full);
diff --git a/lib/readline_simple.c b/lib/readline_simple.c
index 9dd21545e2..1a40d113e3 100644
--- a/lib/readline_simple.c
+++ b/lib/readline_simple.c
@@ -1,5 +1,4 @@
#include <common.h>
-#include <watchdog.h>
static char erase_seq[] = "\b \b"; /* erase sequence */
static char tab_seq[] = " "; /* used to expand TABs */
@@ -64,7 +63,6 @@ int readline (const char *prompt, char *line, int len)
return (-2); /* timed out */
}
#endif
- WATCHDOG_RESET(); /* Trigger watchdog, if needed */
#ifdef CONFIG_SHOW_ACTIVITY
while (!tstc()) {
diff --git a/lib/stringlist.c b/lib/stringlist.c
index 9ccf8fa836..a8ff97964f 100644
--- a/lib/stringlist.c
+++ b/lib/stringlist.c
@@ -3,6 +3,15 @@
#include <malloc.h>
#include <stringlist.h>
+static int string_list_compare(struct list_head *a, struct list_head *b)
+{
+ char *astr, *bstr;
+ astr = (char *)list_entry(a, struct string_list, list)->str;
+ bstr = (char *)list_entry(b, struct string_list, list)->str;
+
+ return strcmp(astr, bstr);
+}
+
int string_list_add(struct string_list *sl, char *str)
{
struct string_list *new;
@@ -16,6 +25,31 @@ int string_list_add(struct string_list *sl, char *str)
return 0;
}
+int string_list_add_sorted(struct string_list *sl, char *str)
+{
+ struct string_list *new;
+
+ new = xmalloc(sizeof(struct string_list) + strlen(str) + 1);
+
+ strcpy(new->str, str);
+
+ list_add_sort(&new->list, &sl->list, string_list_compare);
+
+ return 0;
+}
+
+int string_list_contains(struct string_list *sl, char *str)
+{
+ struct string_list *entry;
+
+ list_for_each_entry(entry, &sl->list, list) {
+ if (!strcmp(str, entry->str))
+ return 1;
+ }
+
+ return 0;
+}
+
void string_list_print_by_column(struct string_list *sl)
{
int len = 0, num, i;
diff --git a/lib/uncompress.c b/lib/uncompress.c
index beb96d167a..cdfebe9173 100644
--- a/lib/uncompress.c
+++ b/lib/uncompress.c
@@ -158,3 +158,11 @@ int uncompress_fd_to_fd(int infd, int outfd,
NULL,
error_fn);
}
+
+int uncompress_fd_to_buf(int infd, void *output,
+ void(*error_fn)(char *x))
+{
+ uncompress_infd = infd;
+
+ return uncompress(NULL, 0, fill_fd, NULL, output, NULL, error_fn);
+}
diff --git a/net/net.c b/net/net.c
index 84168613f2..26ba44e221 100644
--- a/net/net.c
+++ b/net/net.c
@@ -28,7 +28,6 @@
*/
#include <common.h>
#include <clock.h>
-#include <watchdog.h>
#include <command.h>
#include <environment.h>
#include <param.h>
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index 95e7746366..912cfd83db 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -1,7 +1,7 @@
####
# kbuild: Generic definitions
-# Convinient variables
+# Convenient variables
comma := ,
squote := '
empty :=
@@ -21,10 +21,21 @@ depfile = $(subst $(comma),_,$(dot-target).d)
basetarget = $(basename $(notdir $@))
###
+# filename of first prerequisite with directory and extension stripped
+baseprereq = $(basename $(notdir $<))
+
+###
# Escape single quote for use in echo statements
escsq = $(subst $(squote),'\$(squote)',$1)
###
+# Easy method for doing a status message
+ kecho := :
+ quiet_kecho := echo
+silent_kecho := :
+kecho := $($(quiet)kecho)
+
+###
# filechk is used to check if the content of a generated file is updated.
# Sample usage:
# define filechk_sample
@@ -41,13 +52,13 @@ escsq = $(subst $(squote),'\$(squote)',$1)
# to specify a valid file as first prerequisite (often the kbuild file)
define filechk
$(Q)set -e; \
- echo ' CHK $@'; \
+ $(kecho) ' CHK $@'; \
mkdir -p $(dir $@); \
$(filechk_$(1)) < $< > $@.tmp; \
if [ -r $@ ] && cmp -s $@ $@.tmp; then \
rm -f $@.tmp; \
else \
- echo ' UPD $@'; \
+ $(kecho) ' UPD $@'; \
mv -f $@.tmp $@; \
fi
endef
@@ -56,56 +67,95 @@ endef
# gcc support functions
# See documentation in Documentation/kbuild/makefiles.txt
+# cc-cross-prefix
+# Usage: CROSS_COMPILE := $(call cc-cross-prefix, m68k-linux-gnu- m68k-linux-)
+# Return first prefix where a prefix$(CC) is found in PATH.
+# If no $(CC) found in PATH with listed prefixes return nothing
+cc-cross-prefix = \
+ $(word 1, $(foreach c,$(1), \
+ $(shell set -e; \
+ if (which $(strip $(c))$(CC)) > /dev/null 2>&1 ; then \
+ echo $(c); \
+ fi)))
+
# output directory for tests below
TMPOUT := $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/)
+# try-run
+# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
+# Exit code chooses option. "$$TMP" is can be used as temporary file and
+# is automatically cleaned up.
+try-run = $(shell set -e; \
+ TMP="$(TMPOUT).$$$$.tmp"; \
+ TMPO="$(TMPOUT).$$$$.o"; \
+ if ($(1)) >/dev/null 2>&1; \
+ then echo "$(2)"; \
+ else echo "$(3)"; \
+ fi; \
+ rm -f "$$TMP" "$$TMPO")
+
# as-option
-# Usage: cflags-y += $(call as-option, -Wa$(comma)-isa=foo,)
+# Usage: cflags-y += $(call as-option,-Wa$(comma)-isa=foo,)
-as-option = $(shell if $(CC) $(CFLAGS) $(1) -Wa,-Z -c -o /dev/null \
- -xassembler /dev/null > /dev/null 2>&1; then echo "$(1)"; \
- else echo "$(2)"; fi ;)
+as-option = $(call try-run,\
+ $(CC) $(CFLAGS) $(1) -c -xassembler /dev/null -o "$$TMP",$(1),$(2))
# as-instr
-# Usage: cflags-y += $(call as-instr, instr, option1, option2)
+# Usage: cflags-y += $(call as-instr,instr,option1,option2)
-as-instr = $(shell if echo -e "$(1)" | \
- $(CC) $(AFLAGS) -c -xassembler - \
- -o $(TMPOUT)astest$$$$.out > /dev/null 2>&1; \
- then rm $(TMPOUT)astest$$$$.out; echo "$(2)"; \
- else echo "$(3)"; fi)
+as-instr = $(call try-run,\
+ /bin/echo -e "$(1)" | $(CC) $(KBUILD_AFLAGS) -c -xassembler -o "$$TMP" -,$(2),$(3))
# cc-option
-# Usage: cflags-y += $(call cc-option, -march=winchip-c6, -march=i586)
+# Usage: cflags-y += $(call cc-option,-march=winchip-c6,-march=i586)
-cc-option = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;)
+cc-option = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",$(1),$(2))
# cc-option-yn
-# Usage: flag := $(call cc-option-yn, -march=winchip-c6)
-cc-option-yn = $(shell if $(CC) $(CFLAGS) $(1) -S -o /dev/null -xc /dev/null \
- > /dev/null 2>&1; then echo "y"; else echo "n"; fi;)
+# Usage: flag := $(call cc-option-yn,-march=winchip-c6)
+cc-option-yn = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(CFLAGS) $(1) -c -xc /dev/null -o "$$TMP",y,n)
# cc-option-align
# Prefix align with either -falign or -malign
cc-option-align = $(subst -functions=0,,\
$(call cc-option,-falign-functions=0,-malign-functions=0))
+# cc-disable-warning
+# Usage: cflags-y += $(call cc-disable-warning,unused-but-set-variable)
+cc-disable-warning = $(call try-run,\
+ $(CC) $(KBUILD_CPPFLAGS) $(CFLAGS) -W$(strip $(1)) -c -xc /dev/null -o "$$TMP",-Wno-$(strip $(1)))
+
# cc-version
-# Usage gcc-ver := $(call cc-version, $(CC))
+# Usage gcc-ver := $(call cc-version)
cc-version = $(shell $(CONFIG_SHELL) $(srctree)/scripts/gcc-version.sh $(CC))
+# cc-fullversion
+# Usage gcc-ver := $(call cc-fullversion)
+cc-fullversion = $(shell $(CONFIG_SHELL) \
+ $(srctree)/scripts/gcc-version.sh -p $(CC))
+
# cc-ifversion
# Usage: EXTRA_CFLAGS += $(call cc-ifversion, -lt, 0402, -O1)
-cc-ifversion = $(shell if [ $(call cc-version, $(CC)) $(1) $(2) ]; then \
- echo $(3); fi;)
+cc-ifversion = $(shell [ $(call cc-version, $(CC)) $(1) $(2) ] && echo $(3))
+
+# cc-ldoption
+# Usage: ldflags += $(call cc-ldoption, -Wl$(comma)--hash-style=both)
+cc-ldoption = $(call try-run,\
+ $(CC) $(1) -nostdlib -xc /dev/null -o "$$TMP",$(1),$(2))
# ld-option
-# Usage: ldflags += $(call ld-option, -Wl$(comma)--hash-style=both)
-ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
- -o $(TMPOUT)ldtest$$$$.out > /dev/null 2>&1; \
- then rm $(TMPOUT)ldtest$$$$.out; echo "$(1)"; \
- else echo "$(2)"; fi)
+# Usage: LDFLAGS += $(call ld-option, -X)
+ld-option = $(call try-run,\
+ $(CC) /dev/null -c -o "$$TMPO" ; $(LD) $(1) "$$TMPO" -o "$$TMP",$(1),$(2))
+
+# ar-option
+# Usage: KBUILD_ARFLAGS := $(call ar-option,D)
+# Important: no spaces around options
+ar-option = $(call try-run, $(AR) rc$(1) "$$TMP",$(1),$(2))
+
+######
###
# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.build obj=
@@ -113,15 +163,29 @@ ld-option = $(shell if $(CC) $(1) -nostdlib -xc /dev/null \
# $(Q)$(MAKE) $(build)=dir
build := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.build obj
-# Prefix -I with $(srctree) if it is not an absolute path
-addtree = $(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1)
+###
+# Shorthand for $(Q)$(MAKE) -f scripts/Makefile.modbuiltin obj=
+# Usage:
+# $(Q)$(MAKE) $(modbuiltin)=dir
+modbuiltin := -f $(if $(KBUILD_SRC),$(srctree)/)scripts/Makefile.modbuiltin obj
+
+# Prefix -I with $(srctree) if it is not an absolute path.
+# skip if -I has no parameter
+addtree = $(if $(patsubst -I%,%,$(1)), \
+$(if $(filter-out -I/%,$(1)),$(patsubst -I%,-I$(srctree)/%,$(1))) $(1))
+
# Find all -I options and call addtree
flags = $(foreach o,$($(1)),$(if $(filter -I%,$(o)),$(call addtree,$(o)),$(o)))
-# If quiet is set, only print short version of command
+# echo command.
+# Short version is used, if $(quiet) equals `quiet_', otherwise full one.
+echo-cmd = $(if $($(quiet)cmd_$(1)),\
+ echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
+
+# printing commands
cmd = @$(echo-cmd) $(cmd_$(1))
-# Add $(obj)/ for paths that is not absolute
+# Add $(obj)/ for paths that are not absolute
objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
###
@@ -133,16 +197,14 @@ objectify = $(foreach o,$(1),$(if $(filter /%,$(o)),$(o),$(obj)/$(o)))
# See Documentation/kbuild/makefiles.txt for more info
ifneq ($(KBUILD_NOCMDDEP),1)
-# Check if both arguments has same arguments. Result in empty string if equal
+# Check if both arguments has same arguments. Result is empty string if equal.
# User may override this check using make KBUILD_NOCMDDEP=1
arg-check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \
$(filter-out $(cmd_$@), $(cmd_$(1))) )
+else
+arg-check = $(if $(strip $(cmd_$@)),,1)
endif
-# echo command. Short version is $(quiet) equals quiet, otherwise full command
-echo-cmd = $(if $($(quiet)cmd_$(1)), \
- echo ' $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
-
# >'< substitution is for echo to work,
# >$< substitution to preserve $ when reloading .cmd file
# note: when using inline perl scripts [perl -e '...$$t=1;...']
@@ -153,15 +215,14 @@ make-cmd = $(subst \#,\\\#,$(subst $$,$$$$,$(call escsq,$(cmd_$(1)))))
# PHONY targets skipped in both cases.
any-prereq = $(filter-out $(PHONY),$?) $(filter-out $(PHONY) $(wildcard $^),$^)
-# Execute command if command has changed or prerequisitei(s) are updated
+# Execute command if command has changed or prerequisite(s) are updated.
#
if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
echo 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd)
-# execute the command and also postprocess generated .d dependencies
-# file
+# Execute the command and also postprocess generated .d dependencies file.
if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
@set -e; \
$(echo-cmd) $(cmd_$(1)); \
@@ -170,8 +231,8 @@ if_changed_dep = $(if $(strip $(any-prereq) $(arg-check) ), \
mv -f $(dot-target).tmp $(dot-target).cmd)
# Usage: $(call if_changed_rule,foo)
-# will check if $(cmd_foo) changed, or any of the prequisites changed,
-# and if so will execute $(rule_foo)
+# Will check if $(cmd_foo) or any of the prerequisites changed,
+# and if so will execute $(rule_foo).
if_changed_rule = $(if $(strip $(any-prereq) $(arg-check) ), \
@set -e; \
$(rule_$(1)))
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index d7e25630dd..b842c48801 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -160,6 +160,71 @@ cmd_objcopy = $(OBJCOPY) $(OBJCOPYFLAGS) $(OBJCOPYFLAGS_$(@F)) $< $@
# ---------------------------------------------------------------------------
quiet_cmd_gzip = GZIP $@
-cmd_gzip = gzip -f -9 < $< > $@
+cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
+ (rm -f $@ ; false)
+# Bzip2
+# ---------------------------------------------------------------------------
+
+# Bzip2 and LZMA do not include size in file... so we have to fake that;
+# append the size as a 32-bit littleendian number as gzip does.
+size_append = printf $(shell \
+dec_size=0; \
+for F in $1; do \
+ fsize=$$(stat -c "%s" $$F); \
+ dec_size=$$(expr $$dec_size + $$fsize); \
+done; \
+printf "%08x\n" $$dec_size | \
+ sed 's/\(..\)/\1 /g' | { \
+ read ch0 ch1 ch2 ch3; \
+ for ch in $$ch3 $$ch2 $$ch1 $$ch0; do \
+ printf '%s%03o' '\\' $$((0x$$ch)); \
+ done; \
+ } \
+)
+
+quiet_cmd_bzip2 = BZIP2 $@
+cmd_bzip2 = (cat $(filter-out FORCE,$^) | \
+ bzip2 -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+# Lzma
+# ---------------------------------------------------------------------------
+
+quiet_cmd_lzma = LZMA $@
+cmd_lzma = (cat $(filter-out FORCE,$^) | \
+ lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+quiet_cmd_lzo = LZO $@
+cmd_lzo = (cat $(filter-out FORCE,$^) | \
+ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+# XZ
+# ---------------------------------------------------------------------------
+# Use xzkern to compress the kernel image and xzmisc to compress other things.
+#
+# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage
+# of the kernel decompressor. A BCJ filter is used if it is available for
+# the target architecture. xzkern also appends uncompressed size of the data
+# using size_append. The .xz format has the size information available at
+# the end of the file too, but it's in more complex format and it's good to
+# avoid changing the part of the boot code that reads the uncompressed size.
+# Note that the bytes added by size_append will make the xz tool think that
+# the file is corrupt. This is expected.
+#
+# xzmisc doesn't use size_append, so it can be used to create normal .xz
+# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very
+# big dictionary would increase the memory usage too much in the multi-call
+# decompression mode. A BCJ filter isn't used either.
+quiet_cmd_xzkern = XZKERN $@
+cmd_xzkern = (cat $(filter-out FORCE,$^) | \
+ sh $(srctree)/scripts/xz_wrap.sh && \
+ $(call size_append, $(filter-out FORCE,$^))) > $@ || \
+ (rm -f $@ ; false)
+
+quiet_cmd_xzmisc = XZMISC $@
+cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
+ xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
+ (rm -f $@ ; false)
diff --git a/scripts/mkimage.c b/scripts/mkimage.c
index b219cb8f2b..64290cfe80 100644
--- a/scripts/mkimage.c
+++ b/scripts/mkimage.c
@@ -62,6 +62,246 @@ int opt_comp = IH_COMP_GZIP;
image_header_t header;
image_header_t *hdr = &header;
+static inline uint32_t image_get_header_size(void)
+{
+ return sizeof(image_header_t);
+}
+
+#define image_get_hdr_u32(x) \
+static inline uint32_t image_get_##x(const image_header_t *hdr) \
+{ \
+ return uimage_to_cpu(hdr->ih_##x); \
+}
+
+image_get_hdr_u32(magic); /* image_get_magic */
+image_get_hdr_u32(hcrc); /* image_get_hcrc */
+image_get_hdr_u32(time); /* image_get_time */
+image_get_hdr_u32(size); /* image_get_size */
+image_get_hdr_u32(load); /* image_get_load */
+image_get_hdr_u32(ep); /* image_get_ep */
+image_get_hdr_u32(dcrc); /* image_get_dcrc */
+
+#define image_get_hdr_u8(x) \
+static inline uint8_t image_get_##x(const image_header_t *hdr) \
+{ \
+ return hdr->ih_##x; \
+}
+image_get_hdr_u8(os); /* image_get_os */
+image_get_hdr_u8(arch); /* image_get_arch */
+image_get_hdr_u8(type); /* image_get_type */
+image_get_hdr_u8(comp); /* image_get_comp */
+
+static inline char *image_get_name(const image_header_t *hdr)
+{
+ return (char*)hdr->ih_name;
+}
+
+static inline uint32_t image_get_data_size(const image_header_t *hdr)
+{
+ return image_get_size(hdr);
+}
+
+/**
+ * image_get_data - get image payload start address
+ * @hdr: image header
+ *
+ * image_get_data() returns address of the image payload. For single
+ * component images it is image data start. For multi component
+ * images it points to the null terminated table of sub-images sizes.
+ *
+ * returns:
+ * image payload data start address
+ */
+static inline ulong image_get_data(const image_header_t *hdr)
+{
+ return ((ulong)hdr + image_get_header_size());
+}
+
+static inline uint32_t image_get_image_size(const image_header_t *hdr)
+{
+ return (image_get_size(hdr) + image_get_header_size());
+}
+
+static inline ulong image_get_image_end(const image_header_t *hdr)
+{
+ return ((ulong)hdr + image_get_image_size(hdr));
+}
+
+#define image_set_hdr_u32(x) \
+static inline void image_set_##x(image_header_t *hdr, uint32_t val) \
+{ \
+ hdr->ih_##x = cpu_to_uimage(val); \
+}
+
+image_set_hdr_u32(magic); /* image_set_magic */
+image_set_hdr_u32(hcrc); /* image_set_hcrc */
+image_set_hdr_u32(time); /* image_set_time */
+image_set_hdr_u32(size); /* image_set_size */
+image_set_hdr_u32(load); /* image_set_load */
+image_set_hdr_u32(ep); /* image_set_ep */
+image_set_hdr_u32(dcrc); /* image_set_dcrc */
+
+#define image_set_hdr_u8(x) \
+static inline void image_set_##x(image_header_t *hdr, uint8_t val) \
+{ \
+ hdr->ih_##x = val; \
+}
+
+image_set_hdr_u8(os); /* image_set_os */
+image_set_hdr_u8(arch); /* image_set_arch */
+image_set_hdr_u8(type); /* image_set_type */
+image_set_hdr_u8(comp); /* image_set_comp */
+
+static inline void image_set_name(image_header_t *hdr, const char *name)
+{
+ strncpy(image_get_name(hdr), name, IH_NMLEN);
+}
+
+/**
+ * image_multi_count - get component (sub-image) count
+ * @hdr: pointer to the header of the multi component image
+ *
+ * image_multi_count() returns number of components in a multi
+ * component image.
+ *
+ * Note: no checking of the image type is done, caller must pass
+ * a valid multi component image.
+ *
+ * returns:
+ * number of components
+ */
+static 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 *)data;
+
+ /* count non empty slots */
+ for (i = 0; size[i]; ++i)
+ count++;
+
+ return count;
+}
+
+/**
+ * image_multi_getimg - get component data address and size
+ * @hdr: pointer to the header of the multi component image
+ * @idx: index of the requested component
+ * @data: pointer to a ulong variable, will hold component data address
+ * @len: pointer to a ulong variable, will hold component size
+ *
+ * image_multi_getimg() returns size and data address for the requested
+ * component in a multi component image.
+ *
+ * Note: no checking of the image type is done, caller must pass
+ * a valid multi component image.
+ *
+ * returns:
+ * data address and size of the component, if idx is valid
+ * 0 in data and len, if idx is out of range
+ */
+static void image_multi_getimg(void *data, ulong idx,
+ ulong *img_data, ulong *len)
+{
+ int i;
+ uint32_t *size;
+ ulong offset, count, tmp_img_data;
+
+ /* get number of component */
+ 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 *)data;
+
+ /* get address of the proper component data start, which means
+ * skipping sizes table (add 1 for last, null entry) */
+ tmp_img_data = (ulong)data + (count + 1) * sizeof (uint32_t);
+
+ if (idx < count) {
+ *len = uimage_to_cpu(size[idx]);
+ offset = 0;
+
+ /* go over all indices preceding requested component idx */
+ for (i = 0; i < idx; i++) {
+ /* add up i-th component size, rounding up to 4 bytes */
+ offset += (uimage_to_cpu(size[i]) + 3) & ~3 ;
+ }
+
+ /* calculate idx-th component data address */
+ *img_data = tmp_img_data + offset;
+ } else {
+ *len = 0;
+ *img_data = 0;
+ }
+}
+
+static void image_print_type(const image_header_t *hdr)
+{
+ const char *os, *arch, *type, *comp;
+
+ os = image_get_os_name(image_get_os(hdr));
+ arch = image_get_arch_name(image_get_arch(hdr));
+ type = image_get_type_name(image_get_type(hdr));
+ comp = image_get_comp_name(image_get_comp(hdr));
+
+ printf ("%s %s %s (%s)\n", arch, os, type, comp);
+}
+
+static void image_print_time(time_t timestamp)
+{
+ printf("%s", ctime(&timestamp));
+}
+
+static void image_print_size(uint32_t size)
+{
+ printf("%d Bytes = %.2f kB = %.2f MB\n",
+ size, (double)size / 1.024e3,
+ (double)size / 1.048576e6);
+}
+
+static void image_print_contents(const image_header_t *hdr, void *data)
+{
+ int type;
+
+ printf("Image Name: %.*s\n", IH_NMLEN, image_get_name(hdr));
+ printf("Created: ");
+ image_print_time((time_t)image_get_time(hdr));
+ printf ("Image Type: ");
+ image_print_type(hdr);
+ printf ("Data Size: ");
+ image_print_size(image_get_data_size(hdr));
+ printf ("Load Address: %08x\n", image_get_load(hdr));
+ printf ("Entry Point: %08x\n", image_get_ep(hdr));
+
+ type = image_get_type(hdr);
+ if (data && (type == IH_TYPE_MULTI || type == IH_TYPE_SCRIPT)) {
+ int i;
+ ulong img_data, len;
+ ulong count = image_multi_count(data);
+
+ printf ("Contents:\n");
+ for (i = 0; i < count; i++) {
+ image_multi_getimg(data, i, &img_data, &len);
+
+ printf(" Image %d: ", i);
+ image_print_size(len);
+
+ if (image_get_type(hdr) != IH_TYPE_SCRIPT && i > 0) {
+ /*
+ * the user may need to know offsets
+ * if planning to do something with
+ * multiple files
+ */
+ printf(" Offset = 0x%08lx\n", img_data);
+ }
+ }
+ }
+}
+
int
main (int argc, char **argv)
{