summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.mailmap5
-rw-r--r--Documentation/boards/imx.rst27
-rw-r--r--Documentation/boards/socfpga.rst56
-rw-r--r--Documentation/devicetree/bindings/barebox/barebox,state.rst23
-rw-r--r--Documentation/user/booting-linux.rst13
-rw-r--r--Documentation/user/reset-reason.rst47
-rw-r--r--Documentation/user/system-reset.rst64
-rw-r--r--Documentation/user/ubi.rst44
-rw-r--r--Documentation/user/usb.rst2
-rw-r--r--Documentation/user/user-manual.rst2
-rw-r--r--Makefile4
-rw-r--r--arch/arm/boards/beagle/Makefile1
-rw-r--r--arch/arm/boards/beagle/board.c20
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/mmc (renamed from arch/arm/boards/beagle/env/boot/mmc)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi (renamed from arch/arm/boards/beagle/env/boot/nand-ubi)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt (renamed from arch/arm/boards/beagle/env/boot/nand-ubi-dt)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand (renamed from arch/arm/boards/beagle/env/init/mtdparts-nand)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover (renamed from arch/arm/boards/beagle/env/network/eth0-discover)0
-rw-r--r--arch/arm/boards/beagle/lowlevel.c39
-rw-r--r--arch/arm/boards/eltec-hipercam/lowlevel.c18
-rw-r--r--arch/arm/boards/embest-riotboard/lowlevel.c16
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/Makefile3
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/board.c60
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/flash-header-common.imxcfg58
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage-xload.imxcfg3
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg60
-rw-r--r--arch/arm/boards/freescale-mx51-babbage/lowlevel.c61
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg3
-rw-r--r--arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c20
-rw-r--r--arch/arm/boards/guf-santaro/lowlevel.c19
-rw-r--r--arch/arm/boards/karo-tx6x/lowlevel.c21
-rw-r--r--arch/arm/boards/phytec-phycard-imx6/lowlevel.c21
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/lowlevel.c21
-rw-r--r--arch/arm/boards/phytec-som-am335x/board.c5
-rw-r--r--arch/arm/boards/tqma6x/lowlevel.c18
-rw-r--r--arch/arm/boards/variscite-mx6/lowlevel.c21
-rw-r--r--arch/arm/configs/am335x_mlo_defconfig1
-rw-r--r--arch/arm/configs/imx_v7-xload_defconfig52
-rw-r--r--arch/arm/configs/lubbock_defconfig1
-rw-r--r--arch/arm/configs/omap3530_beagle_defconfig81
-rw-r--r--arch/arm/configs/omap3530_beagle_xload_defconfig17
-rw-r--r--arch/arm/configs/phytec-phycard-omap3_defconfig1
-rw-r--r--arch/arm/configs/socfpga_defconfig70
-rw-r--r--arch/arm/cpu/start.c45
-rw-r--r--arch/arm/crypto/.gitignore1
-rw-r--r--arch/arm/dts/am335x-phytec-phycard-som-mlo.dts1
-rw-r--r--arch/arm/dts/am335x-phytec-phycore-som-mlo.dts1
-rw-r--r--arch/arm/dts/am335x-phytec-phyflex-som-mlo.dts1
-rw-r--r--arch/arm/dts/am33xx-strip.dtsi47
-rw-r--r--arch/arm/dts/imx6dl-tx6u-801x.dts4
-rw-r--r--arch/arm/dts/socfpga.dtsi14
-rw-r--r--arch/arm/dts/socfpga_cyclone5_socdk.dts20
-rw-r--r--arch/arm/dts/socfpga_cyclone5_sockit.dts20
-rw-r--r--arch/arm/dts/socfpga_cyclone5_socrates.dts20
-rw-r--r--arch/arm/include/asm/barebox-arm.h27
-rw-r--r--arch/arm/include/asm/bitsperlong.h1
-rw-r--r--arch/arm/include/asm/posix_types.h79
-rw-r--r--arch/arm/include/asm/types.h7
-rw-r--r--arch/arm/mach-clps711x/reset.c2
-rw-r--r--arch/arm/mach-imx/Kconfig24
-rw-r--r--arch/arm/mach-imx/Makefile2
-rw-r--r--arch/arm/mach-imx/imx6.c48
-rw-r--r--arch/arm/mach-imx/include/mach/bbu.h9
-rw-r--r--arch/arm/mach-imx/include/mach/clock-imx51_53.h5
-rw-r--r--arch/arm/mach-imx/include/mach/debug_ll.h77
-rw-r--r--arch/arm/mach-imx/xload.c52
-rw-r--r--arch/arm/mach-mxs/ocotp.c9
-rw-r--r--arch/arm/mach-omap/Kconfig46
-rw-r--r--arch/arm/mach-omap/Makefile6
-rw-r--r--arch/arm/mach-omap/am33xx_bbu_spi_mlo.c56
-rw-r--r--arch/arm/mach-omap/am33xx_generic.c3
-rw-r--r--arch/arm/mach-omap/include/mach/bbu.h5
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-clock.h2
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-generic.h2
-rw-r--r--arch/arm/mach-omap/omap3_generic.c5
-rw-r--r--arch/arm/mach-omap/omap3_xload_usb.c185
-rw-r--r--arch/arm/mach-omap/xload.c59
-rw-r--r--arch/arm/mach-pxa/Kconfig1
-rw-r--r--arch/arm/mach-socfpga/Kconfig4
-rw-r--r--arch/arm/mach-socfpga/include/mach/generic.h5
-rw-r--r--arch/arm/mach-socfpga/include/mach/sequencer.c293
-rw-r--r--arch/arm/mach-socfpga/include/mach/sequencer.h2
-rw-r--r--arch/arm/mach-socfpga/include/mach/socfpga-regs.h2
-rw-r--r--arch/arm/mach-socfpga/xload.c58
-rw-r--r--arch/arm/mach-tegra/include/mach/lowlevel.h19
-rw-r--r--arch/arm/mach-tegra/tegra_avp_init.c3
-rw-r--r--arch/arm/pbl/Makefile2
-rw-r--r--arch/blackfin/include/asm/io.h8
-rw-r--r--arch/blackfin/include/asm/posix_types.h86
-rw-r--r--arch/blackfin/include/asm/processor.h6
-rw-r--r--arch/blackfin/include/asm/swab.h8
-rw-r--r--arch/blackfin/include/asm/types.h6
-rw-r--r--arch/efi/include/asm/bitsperlong.h10
-rw-r--r--arch/efi/include/asm/posix_types.h94
-rw-r--r--arch/efi/include/asm/types.h10
-rw-r--r--arch/mips/Kconfig1
-rw-r--r--arch/mips/configs/dlink-dir-320_defconfig3
-rw-r--r--arch/mips/configs/img-ci20_defconfig11
-rw-r--r--arch/mips/dts/img-ci20.dts15
-rw-r--r--arch/mips/include/asm/bitsperlong.h4
-rw-r--r--arch/mips/include/asm/debug_ll_ns16550.h2
-rw-r--r--arch/mips/include/asm/posix_types.h130
-rw-r--r--arch/mips/include/asm/types.h12
-rw-r--r--arch/mips/mach-ath79/include/mach/debug_ll.h4
-rw-r--r--arch/mips/mach-bcm47xx/include/mach/debug_ll.h14
-rw-r--r--arch/mips/mach-bcm47xx/reset.c5
-rw-r--r--arch/mips/mach-xburst/Kconfig1
-rw-r--r--arch/mips/pbl/Makefile2
-rw-r--r--arch/nios2/include/asm/posix_types.h78
-rw-r--r--arch/nios2/include/asm/types.h3
-rw-r--r--arch/openrisc/include/asm/bitsperlong.h1
-rw-r--r--arch/openrisc/include/asm/posix_types.h72
-rw-r--r--arch/openrisc/include/asm/types.h6
-rw-r--r--arch/ppc/include/asm/atomic.h8
-rw-r--r--arch/ppc/include/asm/bitops.h83
-rw-r--r--arch/ppc/include/asm/bitsperlong.h1
-rw-r--r--arch/ppc/include/asm/io.h20
-rw-r--r--arch/ppc/include/asm/posix_types.h109
-rw-r--r--arch/ppc/include/asm/swab.h8
-rw-r--r--arch/ppc/include/asm/types.h5
-rw-r--r--arch/sandbox/include/asm/bitsperlong.h10
-rw-r--r--arch/sandbox/include/asm/byteorder.h6
-rw-r--r--arch/sandbox/include/asm/posix_types.h94
-rw-r--r--arch/sandbox/include/asm/types.h6
-rw-r--r--arch/x86/include/asm/bitsperlong.h1
-rw-r--r--arch/x86/include/asm/posix_types.h45
-rw-r--r--arch/x86/include/asm/types.h2
-rw-r--r--commands/Kconfig1
-rw-r--r--commands/Makefile1
-rw-r--r--commands/automount.c1
-rw-r--r--commands/detect.c5
-rw-r--r--commands/devinfo.c7
-rw-r--r--commands/dhcp.c78
-rw-r--r--commands/digest.c2
-rw-r--r--commands/export.c1
-rw-r--r--commands/false.c1
-rw-r--r--commands/help.c1
-rw-r--r--commands/loadb.c39
-rw-r--r--commands/loadxy.c81
-rw-r--r--commands/login.c2
-rw-r--r--commands/md.c3
-rw-r--r--commands/mem.c3
-rw-r--r--commands/memcmp.c3
-rw-r--r--commands/memcpy.c3
-rw-r--r--commands/memset.c3
-rw-r--r--commands/memtest.c12
-rw-r--r--commands/mm.c20
-rw-r--r--commands/mount.c2
-rw-r--r--commands/mw.c10
-rw-r--r--commands/net.c1
-rw-r--r--commands/readline.c1
-rw-r--r--commands/timeout.c1
-rw-r--r--commands/trigger.c1
-rw-r--r--commands/true.c1
-rw-r--r--commands/ubi.c1
-rw-r--r--commands/ubiformat.c2
-rw-r--r--commands/version.c1
-rw-r--r--common/Kconfig21
-rw-r--r--common/Makefile1
-rw-r--r--common/bbu.c113
-rw-r--r--common/blspec.c59
-rw-r--r--common/bootsource.c1
-rw-r--r--common/complete.c1
-rw-r--r--common/console.c126
-rw-r--r--common/console_common.c27
-rw-r--r--common/filetype.c3
-rw-r--r--common/imx-bbu-nand-fcb.c (renamed from arch/arm/mach-imx/imx6-bbu-nand.c)248
-rw-r--r--common/kallsyms.c1
-rw-r--r--common/memory_display.c42
-rw-r--r--common/memtest.c176
-rw-r--r--common/oftree.c19
-rw-r--r--common/parser.c1
-rw-r--r--common/startup.c28
-rw-r--r--common/state.c402
-rw-r--r--common/tlsfbits.h6
-rw-r--r--crypto/crc16.c2
-rw-r--r--crypto/digest.c10
-rw-r--r--drivers/base/driver.c25
-rw-r--r--drivers/bus/omap-gpmc.c144
-rw-r--r--drivers/i2c/i2c.c2
-rw-r--r--drivers/mci/Kconfig2
-rw-r--r--drivers/mci/imx-esdhc.c141
-rw-r--r--drivers/misc/state.c72
-rw-r--r--drivers/mtd/Kconfig11
-rw-r--r--drivers/mtd/Makefile2
-rw-r--r--drivers/mtd/core.c44
-rw-r--r--drivers/mtd/devices/Kconfig1
-rw-r--r--drivers/mtd/devices/m25p80.c1000
-rw-r--r--drivers/mtd/mtd.h2
-rw-r--r--drivers/mtd/mtdconcat.c765
-rw-r--r--drivers/mtd/mtdoob.c2
-rw-r--r--drivers/mtd/mtdraw.c2
-rw-r--r--drivers/mtd/nand/nand-bb.c4
-rw-r--r--drivers/mtd/nor/cfi_flash.c747
-rw-r--r--drivers/mtd/nor/cfi_flash.h150
-rw-r--r--drivers/mtd/nor/cfi_flash_amd.c41
-rw-r--r--drivers/mtd/nor/cfi_flash_intel.c107
-rw-r--r--drivers/mtd/partition.c13
-rw-r--r--drivers/mtd/spi-nor/Kconfig15
-rw-r--r--drivers/mtd/spi-nor/Makefile2
-rw-r--r--drivers/mtd/spi-nor/cadence-quadspi.c1211
-rw-r--r--drivers/mtd/spi-nor/spi-nor.c1148
-rw-r--r--drivers/mtd/ubi/build.c9
-rw-r--r--drivers/mtd/ubi/cdev.c4
-rw-r--r--drivers/net/altera_tse.c2
-rw-r--r--drivers/net/ar231x.c2
-rw-r--r--drivers/net/arc_emac.c2
-rw-r--r--drivers/net/at91_ether.c2
-rw-r--r--drivers/net/cpsw.c2
-rw-r--r--drivers/net/cs8900.c2
-rw-r--r--drivers/net/davinci_emac.c2
-rw-r--r--drivers/net/designware.c2
-rw-r--r--drivers/net/dm9k.c140
-rw-r--r--drivers/net/ep93xx.c2
-rw-r--r--drivers/net/ethoc.c2
-rw-r--r--drivers/net/fec_imx.c2
-rw-r--r--drivers/net/fec_mpc5200.c2
-rw-r--r--drivers/net/gianfar.c2
-rw-r--r--drivers/net/ks8851_mll.c2
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/net/mvneta.c2
-rw-r--r--drivers/net/netx_eth.c2
-rw-r--r--drivers/net/orion-gbe.c2
-rw-r--r--drivers/net/rtl8139.c2
-rw-r--r--drivers/net/rtl8169.c2
-rw-r--r--drivers/net/smc91111.c2
-rw-r--r--drivers/net/smc911x.c8
-rw-r--r--drivers/net/tap.c2
-rw-r--r--drivers/net/usb/asix.c2
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/xgmac.c2
-rw-r--r--drivers/of/fdt.c1
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/pci/pci.c44
-rw-r--r--drivers/serial/serial_ar933x.c4
-rw-r--r--drivers/serial/serial_imx.c116
-rw-r--r--drivers/serial/serial_ns16550.c9
-rw-r--r--drivers/spi/ath79_spi.c4
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/gadget/u_serial.c3
-rw-r--r--drivers/usb/musb/musb_core.c13
-rw-r--r--dts/Bindings/arm/omap/l3-noc.txt1
-rw-r--r--dts/Bindings/clock/silabs,si5351.txt4
-rw-r--r--dts/Bindings/dma/fsl-mxs-dma.txt2
-rw-r--r--dts/Bindings/input/touchscreen/tsc2005.txt4
-rw-r--r--dts/Bindings/mtd/jedec,spi-nor.txt (renamed from dts/Bindings/mtd/m25p80.txt)6
-rw-r--r--dts/Bindings/net/cdns-emac.txt3
-rw-r--r--dts/Bindings/rtc/abracon,abx80x.txt30
-rw-r--r--dts/Bindings/usb/renesas_usbhs.txt6
-rw-r--r--dts/src/arm/am335x-bone-common.dtsi19
-rw-r--r--dts/src/arm/am335x-boneblack.dts4
-rw-r--r--dts/src/arm/am335x-evmsk.dts2
-rw-r--r--dts/src/arm/am35xx-clocks.dtsi14
-rw-r--r--dts/src/arm/am437x-sk-evm.dts4
-rw-r--r--dts/src/arm/am57xx-beagle-x15.dts11
-rw-r--r--dts/src/arm/armada-375.dtsi2
-rw-r--r--dts/src/arm/armada-38x.dtsi2
-rw-r--r--dts/src/arm/armada-39x.dtsi2
-rw-r--r--dts/src/arm/armada-xp-linksys-mamba.dts5
-rw-r--r--dts/src/arm/armada-xp-openblocks-ax3-4.dts4
-rw-r--r--dts/src/arm/dm816x.dtsi4
-rw-r--r--dts/src/arm/dove-cubox.dts1
-rw-r--r--dts/src/arm/dra7.dtsi10
-rw-r--r--dts/src/arm/exynos4412-odroid-common.dtsi3
-rw-r--r--dts/src/arm/exynos4412-trats2.dts2
-rw-r--r--dts/src/arm/exynos5250-snow.dts1
-rw-r--r--dts/src/arm/exynos5420-peach-pit.dts1
-rw-r--r--dts/src/arm/exynos5420-trip-points.dtsi2
-rw-r--r--dts/src/arm/exynos5420.dtsi1
-rw-r--r--dts/src/arm/exynos5440-trip-points.dtsi2
-rw-r--r--dts/src/arm/exynos5800-peach-pi.dts1
-rw-r--r--dts/src/arm/imx23-olinuxino.dts4
-rw-r--r--dts/src/arm/imx25.dtsi1
-rw-r--r--dts/src/arm/imx27.dtsi2
-rw-r--r--dts/src/arm/imx28.dtsi2
-rw-r--r--dts/src/arm/imx6qdl-phytec-pfla02.dtsi2
-rw-r--r--dts/src/arm/imx6qdl-sabreauto.dtsi1
-rw-r--r--dts/src/arm/omap3-devkit8000.dts2
-rw-r--r--dts/src/arm/omap3-n900.dts8
-rw-r--r--dts/src/arm/omap3.dtsi2
-rw-r--r--dts/src/arm/omap5.dtsi2
-rw-r--r--dts/src/arm/r8a7791-koelsch.dts2
-rw-r--r--dts/src/arm/ste-dbx5x0.dtsi17
-rw-r--r--dts/src/arm/ste-href.dtsi15
-rw-r--r--dts/src/arm/ste-snowball.dts13
-rw-r--r--dts/src/arm/tegra124.dtsi8
-rw-r--r--dts/src/arm/vexpress-v2p-ca15_a7.dts1
-rw-r--r--dts/src/arm/vexpress-v2p-ca9.dts11
-rw-r--r--dts/src/arm/zynq-7000.dtsi4
-rw-r--r--dts/src/arm64/arm/juno-motherboard.dtsi31
-rw-r--r--dts/src/arm64/mediatek/mt8173-evb.dts3
-rw-r--r--fs/cramfs/cramfs.c1
-rw-r--r--fs/fat/fat.c1
-rw-r--r--fs/fs.c16
-rw-r--r--fs/ramfs.c1
-rw-r--r--fs/tftp.c47
-rw-r--r--images/Makefile3
-rw-r--r--images/Makefile.am33xx28
-rw-r--r--images/Makefile.imx20
-rw-r--r--images/Makefile.omap319
-rw-r--r--include/asm-generic/barebox.lds.h7
-rw-r--r--include/asm-generic/bitsperlong.h22
-rw-r--r--include/asm-generic/posix_types.h90
-rw-r--r--include/asm-generic/swab.h2
-rw-r--r--include/bbu.h23
-rw-r--r--include/blspec.h1
-rw-r--r--include/bootsource.h1
-rw-r--r--include/console.h8
-rw-r--r--include/crc.h2
-rw-r--r--include/dhcp.h25
-rw-r--r--include/digest.h21
-rw-r--r--include/fcntl.h3
-rw-r--r--include/filetype.h1
-rw-r--r--include/habv4.h2
-rw-r--r--include/init.h2
-rw-r--r--include/io.h8
-rw-r--r--include/linux/bitops.h4
-rw-r--r--include/linux/clk.h2
-rw-r--r--include/linux/mod_devicetable.h7
-rw-r--r--include/linux/mtd/concat.h34
-rw-r--r--include/linux/mtd/mtd.h2
-rw-r--r--include/linux/mtd/spi-nor.h204
-rw-r--r--include/linux/types.h8
-rw-r--r--include/net.h4
-rw-r--r--include/of.h3
-rw-r--r--include/platform_data/cadence_qspi.h9
-rw-r--r--include/serial/imx-uart.h128
-rw-r--r--include/state.h9
-rw-r--r--include/watchdog.h17
-rw-r--r--lib/bootstrap/devfs.c59
-rw-r--r--lib/fnmatch.c1
-rw-r--r--lib/gui/bmp.c11
-rw-r--r--lib/gui/image_renderer.c8
-rw-r--r--lib/libfile.c4
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c1
-rw-r--r--lib/parameter.c12
-rw-r--r--lib/random.c1
-rw-r--r--lib/strtox.c1
-rw-r--r--lib/xfuncs.c4
-rw-r--r--net/Kconfig4
-rw-r--r--net/Makefile3
-rw-r--r--net/dhcp.c165
-rw-r--r--net/dns.c13
-rw-r--r--net/eth.c27
-rw-r--r--net/lib.c109
-rw-r--r--net/net.c81
-rw-r--r--net/nfs.c1
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Makefile3
-rw-r--r--scripts/Makefile.lib6
-rw-r--r--scripts/coccinelle/misc/altera_sequencer.cocci3
-rw-r--r--scripts/imx/Makefile2
-rw-r--r--scripts/imx/imx-image.c11
-rw-r--r--scripts/omap3-usb-loader.c921
-rw-r--r--scripts/omap_signGP.c7
-rwxr-xr-xscripts/socfpga_get_sequencer8
-rwxr-xr-xscripts/socfpga_sequencer_defines_defaults4
357 files changed, 9254 insertions, 4185 deletions
diff --git a/.mailmap b/.mailmap
index 09ecaebde6..82631b2846 100644
--- a/.mailmap
+++ b/.mailmap
@@ -13,6 +13,11 @@ Eric Bénard <eric@eukrea.com>
Franck Jullien <franck.jullien@gmail.com>
Jin Zhengxiong <Jason.Jin@freescale.com>
Juergen Borleis <jbe@pengutronix.de>
+Juergen Borleis <j.beisert@pengutronix.de>
+Juergen Borleis <jbe@isonoe.(none)>
+Juergen Borleis <jbe@kreuzholzen.de>
+Juergen Borleis <jbe@octopus.labnet.pengutronix.de>
+Juergen Borleis <juergen@kreuzholzen.de>
Marc Reilly <marc@cpdesign.com.au>
Nishanth Menon <x0nishan@ti.com>
Raphaël Poggi <poggi.raph@gmail.com>
diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst
index 466f69c5ba..837bf5cf32 100644
--- a/Documentation/boards/imx.rst
+++ b/Documentation/boards/imx.rst
@@ -46,6 +46,33 @@ The images can also always be started second stage::
bootm /mnt/tftp/barebox-freescale-imx51-babbage.img
+Internal Boot Mode Through Internal RAM(IRAM)
+---------------------------------------------
+
+The Internal Boot Mode Through Internal RAM is supported on:
+
+* i.MX51
+
+As can be easily deduced from its name, the Internal Boot Mode Through
+Internal RAM is just a variant of Internal Boot Mode so all of the
+stated above still applies in this case. What it differs in is the following:
+
+* Boot process is done in two stages(First stage binary can be
+ produced with ``imx_v7-xload_defconfig``)
+* DCD of the first stage image is set such that the image is fetched
+ into an unoccupied area or IRAM
+* First stage image once uncompressed and set up will look for a
+ second stage bootloader on the same media it booted from and start
+ it(see mach-imx/xload.c for more details)
+* Second stage images are just regular i.MX boot images
+
+Since on a typical i.MX SoC unused IRAM area is not enough to run
+anything but a PBL this mode, due to its very limited usability,
+serves only one purpose -- allow for a portion of a bootloader to be
+executed without depending on DRAM to be functional. This peculiarity
+of the mode can be used to implement various memory testing
+scenarious.
+
USB Boot
^^^^^^^^
diff --git a/Documentation/boards/socfpga.rst b/Documentation/boards/socfpga.rst
index e956bccbe2..358e5ab910 100644
--- a/Documentation/boards/socfpga.rst
+++ b/Documentation/boards/socfpga.rst
@@ -11,10 +11,34 @@ build the ``socfpga-xload_defconfig``; for second stage use the normal
Bootstrapping
-------------
-The supported bootsource is a SD card. The Boot ROM searches for a partition of
-type A2 and loads what it finds there. When barebox is placed in such a partition
-it will then itself try and mount the second partition of the SD card, which must
-be of type FAT32. On this partition barebox searches for a file called barebox.bin.
+The supported bootsources are: SD card and QSPI.
+
+Bootsource selection
+^^^^^^^^^^^^^^^^^^^^
+
++--------------+-----------+-----------+
+| Board | BSEL[2:0] | CSEL[1:0] |
++==============+===========+===========+
+| Sockit SD | 0b100 | 0b00 |
++--------------+-----------+-----------+
+| Sockit QSPI | 0b110 | 0b00 |
++--------------+-----------+-----------+
+| Socrates SD | 0b101 | 0b11 |
++--------------+-----------+-----------+
+| Socrates QSPI| 0b111 | 0b11 |
++--------------+-----------+-----------+
+| SocDK SD | 0b100 | 0b00 |
++--------------+-----------+-----------+
+| SocDK QSPI | 0b110 | 0b00 |
++--------------+-----------+-----------+
+
+SD card
+^^^^^^^
+
+The Boot ROM searches for a partition of type A2 and loads what it finds there.
+When barebox is placed in such a partition it will then itself try and mount the
+second partition of the SD card, which must be of type FAT32. On this partition
+barebox searches for a file called barebox.bin.
To boot barebox on a Terasic SoCkit, the procedure is as follows (sdb1 is the A2 and
sdb2 the FAT32 partition)::
@@ -34,6 +58,30 @@ proceed with::
For the EBV Socrates use ``images/barebox-socfpga-socrates(-xload).img`` instead.
+QSPI
+^^^^
+
+The Boot ROM loads the preloader starting from address 0x0 on the QSPI flash.
+barebox then searches for a barebox image at the 256K offset and loads it.
+
+The default bootsource is SD card, so to change that to QSPI, you have to::
+
+ make socfpga-xload_defconfig
+ make menuconfig
+
+And then select the options `MTD` and `SPI_CADENCE_QUADSPI`. Now::
+
+ make
+ cat images/barebox-socfpga-<board>-xload.img > /dev/mtd0
+
+For barebox itself, the build step is like for SD card. The resulting image has to be
+written to the offset 256K.
+
+Warning! There is a known issue with booting from QSPI and doing Cold/Warm-Resets.
+Please consult `Rocketboards <http://rocketboards.org/foswiki/Documentation/SocBoardQspiBoot#Serial_Flash_Challenges>`_
+to see how to fix this.
+
+
Updating handoff files
----------------------
diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index 42b2a34d3a..3d664f1f02 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -1,4 +1,6 @@
-barebox,state
+.. _barebox,state:
+
+barebox state
=============
Overview
@@ -27,9 +29,6 @@ Required properties:
* ``compatible``: should be ``barebox,state``;
* ``magic``: A 32bit number used as a magic to identify the state
-
-Optional properties:
-
* ``backend``: describes where the data for this state is stored
* ``backend-type``: should be ``raw`` or ``dtb``.
@@ -40,9 +39,9 @@ These are subnodes of a state node each describing a single
variable. The node name may end with ``@<ADDRESS>``, but the suffix is
sripped from the variable name.
-State variables have a type. Currenty supported types are: ``uint32``,
-``enum32`` and ``mac`` address. Fixed length strings are planned but
-not implemented. Variable length strings are not planned.
+State variables have a type. Currenty supported types are: ``uint8``,
+``uint32``, ``enum32`` and ``mac`` address. Fixed length strings are
+planned but not implemented. Variable length strings are not planned.
Required properties:
@@ -50,8 +49,8 @@ Required properties:
``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the
variable in the ``raw`` backend. ``size`` must fit the node
``type``. Variables are not allowed to overlap.
-* ``type``: Should be ``uint32``, ``enum32`` or ``mac`` for the type
- of the variable
+* ``type``: Should be ``uint8``, ``uint32``, ``enum32`` or ``mac`` for
+ the type of the variable
* ``names``: For ``enum32`` values only, this specifies the values
possible for ``enum32``.
@@ -71,15 +70,15 @@ Example::
foo {
reg = <0x00 0x4>;
- type = "u32";
+ type = "uint32";
default = <0x0>;
};
bar {
reg = <0x10 0x4>;
- type = "enum32";
+ type = "enum32";
names = "baz", "qux";
- default ="qux";
+ default = <1>;
};
};
diff --git a/Documentation/user/booting-linux.rst b/Documentation/user/booting-linux.rst
index ac44cbad62..6e7d1550bf 100644
--- a/Documentation/user/booting-linux.rst
+++ b/Documentation/user/booting-linux.rst
@@ -55,12 +55,13 @@ to free the internal devicetree before calling ``bootm``
Passing Kernel Arguments
^^^^^^^^^^^^^^^^^^^^^^^^
-Depending on the barebox configuration (``CONFIG_FLEXIBLE_BOOTARGS``) there
-are to ways to pass bootargs to the Kernel. With ``CONFIG_FLEXIBLE_BOOTARGS``
-disabled the bootm command takes the bootargs from the ``bootargs`` environment
-variable. With ``CONFIG_FLEXIBLE_BOOTARGS`` enabled the bootargs are composed
-from different :ref:`global_device` variables. All variables beginning with
-``global.linux.bootargs.`` will be concatenated to the bootargs:
+The simple method to pass bootargs to the kernel is with
+``CONFIG_FLEXIBLE_BOOTARGS`` disabled: in this case the bootm command
+takes the bootargs from the ``bootargs`` environment variable.
+
+With ``CONFIG_FLEXIBLE_BOOTARGS`` enabled, the bootargs are composed
+from different :ref:`global device<global_device>` variables. All variables beginning
+with ``global.linux.bootargs.`` will be concatenated to the bootargs:
.. code-block:: sh
diff --git a/Documentation/user/reset-reason.rst b/Documentation/user/reset-reason.rst
new file mode 100644
index 0000000000..26d37f86dd
--- /dev/null
+++ b/Documentation/user/reset-reason.rst
@@ -0,0 +1,47 @@
+.. _reset_reason:
+
+Reset Reason
+------------
+
+To handle a device in a secure and safe manner many applications are using
+a watchdog or other ways to reset a system to bring it back into life if it
+hangs or crashes somehow.
+
+In these cases the hardware restarts and runs the bootloader again. Depending on
+the root cause of the hang or crash, the bootloader sometimes should not just
+re-start the main system again. Maybe it should do some kind of recovery instead.
+For example it should wait for another update (for the case the cause of a
+crash is a failed update) or should start into a fall back system instead.
+
+In order to handle failing systems gracefully the bootloader needs the
+information why it runs. This is called the "reset reason". It is provided by
+the global variable ``system.reset`` and can be used in scripts via
+``$global.system.reset``.
+
+The following values can help to detect the reason why the bootloader runs:
+
+* ``unknown``: the software wasn't able to detect the reset cause or there
+ isn't support for this feature at all.
+* ``POR`` (Power On Reset): a cold start. The power of the system
+ was switched on. This is a regular state and nothing to worry about.
+* ``RST`` (ReSeT): a warm start. The user has triggered a reset somehow. This
+ is a regular state and nothing to worry about.
+* ``WDG`` (WatchDoG): also some kind of warm start, but triggered by a watchdog
+ unit. It depends on the application if this reason signals a regular state
+ and therefore nothing to worry about, or if this state was entered by a hanging
+ or crashed system and must implicitly be handled.
+* ``WKE`` (WaKEup): a mixture of cold and warm start. The system is woken up
+ from some state of suspend. This is a regular state and nothing to worry
+ about.
+* ``JTAG``: an external JTAG based debugger has triggered the reset.
+* ``THERM`` (THERMal): some SoCs are able to detect if they got reset in
+ response to an overtemperature event. This can be a regular state and nothing
+ to worry about (the reset has brought the system back into a safe state) or
+ must implicitly be handled.
+* ``EXT`` (EXTernal): some SoCs have special device pins for external reset
+ signals other than the ``RST`` one. Application specific how to handle this
+ state.
+
+It depends on your board/SoC and its features if the hardware is able to detect
+these reset reasons. Most of the time only ``POR`` and ``RST`` are supported
+but often ``WDG`` as well.
diff --git a/Documentation/user/system-reset.rst b/Documentation/user/system-reset.rst
new file mode 100644
index 0000000000..e76e3a23c1
--- /dev/null
+++ b/Documentation/user/system-reset.rst
@@ -0,0 +1,64 @@
+.. _system_reset:
+
+System Restart
+--------------
+
+When running the reset command barebox restarts the SoC somehow. Restart can
+be done in software, but a more reliable way is to use a hard reset line, which
+really resets the whole machine.
+The most common way to force such a hard reset is by using a watchdog. Its
+trigger time will be setup as short as possible and after that the software just
+waits for its reset. Very simple and most of the time it does what's expected.
+
+But there are some drawbacks within this simple approach.
+
+* most used watchdogs are built-in units in the SoCs. There is nothing wrong
+ with that, but these units can mostly reset the CPU core and sometimes a little
+ bit more of the SoC. This means this reset is not exactly the same than the
+ real POR (e.g. power on reset). In this case you must still handle different
+ hardware in a special way because it hasn't seen the reset the CPU has seen.
+ Enabled DMA units for example can continue to run and transfer data while the
+ CPU core runs through its reset code. This can trigger very strange failures.
+
+* when interacting with flash memories (mostly NOR types and used to store the
+ root filesystem) it cannot provide data (sometimes called 'array mode') the
+ CPU wants to read after a reset while it is still in some programming mode.
+ And if the software is currently changing some data inside the flash and
+ an internal reset happens the CPU and the flash memory are doing different
+ things and the system hangs until a real POR which also resets the flash
+ memory into the 'array mode'.
+
+* some SoC's boot behaviour gets parametrized by so called 'bootstrap pins'.
+ These pins can have a different meaning at reset time and at run-time later
+ on (multi purpose pins) but their correct values at reset time are very
+ important to boot the SoC sucessfully. If external devices are connected to
+ these multi purpose pins they can disturb the reset values, and so parametrizing
+ the boot behaviour differently and hence crashing the SoC until the next real
+ POR happens which also resets the external devices (and keep them away from the
+ multi purpose pins).
+
+* when power management comes into play another level of failure is
+ possible. To save power the software can lower the clock(s), but to really
+ save power, the power supply voltages must be lowered as well. Most PMICs
+ (e.g. power management controllers) are dedicated external companion devices,
+ loosely connected to their SoC. If the SoC's internal reset source now resets
+ the CPU it may increases its clock(s) back to the frequencies after a POR, but
+ the external PMIC still provides voltages related to lower frequencies. The
+ system isn't consistent any more. If you are in luck, the SoC still works
+ somehow, even if the voltages are out of their specifications for the
+ currently used clock speeds. But don't rely on it.
+
+To workaround these issues the reset signal triggered by a SoC internal source
+must be 'visible' to the external devices to also reset them like a real POR does.
+But many SoCs do not provide such a signal. So you can't use the internal reset
+source if you face one of the above listed issues!
+
+A different solution is to use the PMIC (if available) to trigger the reset.
+Many PMICs provide their own watchdog units and if they trigger a reset they
+also switch their voltages back to the real POR values. This will be a system
+wide reset, like the POR is.
+
+Drawback of the PMIC solution is, you can't use the SoC's internal mechanisms to
+detect the :ref:`reset_reason` anymore. From the SoC point of view it is always
+a POR when the PMIC handles the system reset. If you are in luck the PMIC
+instead can provide this information if you depend on it.
diff --git a/Documentation/user/ubi.rst b/Documentation/user/ubi.rst
index a187680e2c..c300c0f951 100644
--- a/Documentation/user/ubi.rst
+++ b/Documentation/user/ubi.rst
@@ -5,9 +5,6 @@ barebox has both UBI and UBIFS support. For handling UBI barebox has commands si
the Linux commands :ref:`command_ubiformat`, :ref:`command_ubiattach`, :ref:`command_ubidetach`,
:ref:`command_ubimkvol` and :ref:`command_ubirmvol`.
-The following examples assume we work on the first UBI device. Replace ``ubi0`` with
-the appropriate number when you have multiple UBI devices.
-
The first step for preparing a pristine Flash for UBI is to :ref:`command_ubiformat` the
device:
@@ -28,17 +25,17 @@ After a device has been formatted it can be attached with :ref:`command_ubiattac
ubiattach /dev/nand0.root
-This will create the controlling node ``/dev/ubi0`` and also register all volumes present
-on the device as ``/dev/ubi0.<volname>``. When freshly formatted there won't be any volumes
-present. A volume can be created with:
+This will create the controlling node ``/dev/nand0.root.ubi`` and also register all volumes
+present on the device as ``/dev/nand0.root.ubi.<volname>``. When freshly formatted there won't
+be any volumes present. A volume can be created with:
.. code-block:: sh
- ubimkvol /dev/ubi0 root 0
+ ubimkvol /dev/nand0.root.ubi root 0
The first parameter is the controlling node. The second parameter is the name of the volume.
-In this case the volume can be found under ``/dev/ubi.root``. The third parameter contains
-the size. A size of zero means that all available space shall be used.
+In this case the volume can be found under ``/dev/dev/nand0.root.ubi.root``. The third
+parameter contains the size. A size of zero means that all available space shall be used.
The next step is to write a UBIFS image to the volume. The image must be created on a host using
the ``mkfs.ubifs`` command. ``mkfs.ubifs`` requires several arguments for describing the
@@ -46,7 +43,7 @@ flash layout. Values for these arguments can be retrieved from a ``devinfo ubi``
.. code-block:: sh
- barebox@Phytec pcm970:/ devinfo ubi0
+ barebox@Phytec pcm970:/ devinfo nand0.root.ubi
Parameters:
peb_size: 16384
leb_size: 15360
@@ -76,38 +73,27 @@ The UBIFS image can be transferred to the board for example with TFTP:
.. code-block:: sh
- cp /mnt/tftp/root.ubifs /dev/ubi0.root
+ cp /mnt/tftp/root.ubifs /dev/nand0.root.ubi.root
Finally it can be mounted using the :ref:`command_mount` command:
.. code-block:: sh
- mkdir -p /mnt/ubi
- mount -t ubifs /dev/ubi0.root /mnt/ubi
+ mount /dev/nand0.root.ubi.root
+The default mount path when the mount point is skipped is ``/mnt/<devname>``,
+so in this example it will be ``/mnt/nand0.root.ubi.root``.
The second time the UBIFS is mounted the above can be simplified to:
.. code-block:: sh
ubiattach /dev/nand0.root
- mount -t ubifs /dev/ubi0.root /mnt/ubi
+ mount /dev/nand0.root.ubi.root
Mounting the UBIFS can also be made transparent with the automount command.
-With this helper script in ``/env/bin/automount-ubi:``:
-
-.. code-block:: sh
-
- #!/bin/sh
-
- if [ ! -e /dev/ubi0 ]; then
- ubiattach /dev/nand0 || exit 1
- fi
-
- mount -t ubifs /dev/ubi0.root $automount_path
-
-
-The command ``automount -d /mnt/ubi/ '/env/bin/automount-ubi'`` will automatically
-attach the UBI device and mount the UBIFS image to ``/mnt/ubi`` whenever ``/mnt/ubi``
+The command ``automount -d /mnt/nand0.root.ubi.root 'mount nand0.root.ubi.root'``
+will automatically attach the UBI device and mount the UBIFS image to
+``/mnt/nand0.root.ubi.root`` whenever ``/mnt/nand0.root.ubi.root``
is first accessed. The automount command can be added to ``/env/init/automount`` to
execute it during startup.
diff --git a/Documentation/user/usb.rst b/Documentation/user/usb.rst
index 0ff982bac4..9eb1437135 100644
--- a/Documentation/user/usb.rst
+++ b/Documentation/user/usb.rst
@@ -101,7 +101,7 @@ Android Fastboot support
barebox has support for the android fastboot protocol. There is no dedicated command
for initializing the fastboot protocol, instead it is integrated into the Multifunction
-Composite Gadget, see :`ref:command_usbgadget` for a usage description.
+Composite Gadget, see :ref:`command_usbgadget` for a usage description.
The Fastboot gadget supports the following commands:
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 3d68bbb9ae..0d6daee70e 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -28,6 +28,8 @@ Contents:
ubi
booting-linux
system-setup
+ reset-reason
+ system-reset
* :ref:`search`
* :ref:`genindex`
diff --git a/Makefile b/Makefile
index a00800352d..e7db67af85 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2015
-PATCHLEVEL = 06
+PATCHLEVEL = 07
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
@@ -700,7 +700,7 @@ OBJCOPYFLAGS_barebox.bin = -O binary
barebox.bin: barebox FORCE
$(call if_changed,objcopy)
ifndef CONFIG_PBL_IMAGE
- $(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
+ $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
endif
# By default the uImage load address is 2MB below CONFIG_TEXT_BASE,
diff --git a/arch/arm/boards/beagle/Makefile b/arch/arm/boards/beagle/Makefile
index 01c7a259e9..3bee9a22ab 100644
--- a/arch/arm/boards/beagle/Makefile
+++ b/arch/arm/boards/beagle/Makefile
@@ -1,2 +1,3 @@
obj-y += board.o
lwl-y += lowlevel.o
+bbenv-y += defaultenv-beagle
diff --git a/arch/arm/boards/beagle/board.c b/arch/arm/boards/beagle/board.c
index 775621069c..4ac9517dbe 100644
--- a/arch/arm/boards/beagle/board.c
+++ b/arch/arm/boards/beagle/board.c
@@ -21,7 +21,10 @@
#include <driver.h>
#include <linux/sizes.h>
#include <io.h>
+#include <bbu.h>
+#include <filetype.h>
#include <ns16550.h>
+#include <envfs.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
#include <mach/gpmc.h>
@@ -31,6 +34,7 @@
#include <i2c/i2c.h>
#include <linux/err.h>
#include <usb/ehci.h>
+#include <asm/barebox-arm.h>
#ifdef CONFIG_DRIVER_SERIAL_NS16550
@@ -42,6 +46,9 @@
*/
static int beagle_console_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
barebox_set_model("Texas Instruments beagle");
barebox_set_hostname("beagle");
@@ -82,6 +89,9 @@ static struct gpmc_nand_platform_data nand_plat = {
static int beagle_mem_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
omap_add_ram0(SZ_128M);
return 0;
@@ -90,6 +100,9 @@ mem_initcall(beagle_mem_init);
static int beagle_devices_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
omap3_add_i2c1(NULL);
@@ -107,6 +120,13 @@ static int beagle_devices_init(void)
armlinux_set_architecture(MACH_TYPE_OMAP3_BEAGLE);
+ bbu_register_std_file_update("nand-xload", 0,
+ "/dev/nand0.xload.bb", filetype_ch_image);
+ bbu_register_std_file_update("nand", 0,
+ "/dev/nand0.barebox.bb", filetype_arm_barebox);
+
+ defaultenv_append_directory(defaultenv_beagle);
+
return 0;
}
device_initcall(beagle_devices_init);
diff --git a/arch/arm/boards/beagle/env/boot/mmc b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
index db638f8cf8..db638f8cf8 100644
--- a/arch/arm/boards/beagle/env/boot/mmc
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
index e0ef904432..e0ef904432 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi-dt b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
index 5fc0a6c53a..5fc0a6c53a 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi-dt
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
diff --git a/arch/arm/boards/beagle/env/init/mtdparts-nand b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
index 9335bb17a3..9335bb17a3 100644
--- a/arch/arm/boards/beagle/env/init/mtdparts-nand
+++ b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
diff --git a/arch/arm/boards/beagle/env/network/eth0-discover b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
index 86d13f5c43..86d13f5c43 100644
--- a/arch/arm/boards/beagle/env/network/eth0-discover
+++ b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
diff --git a/arch/arm/boards/beagle/lowlevel.c b/arch/arm/boards/beagle/lowlevel.c
index d6e6b9f91c..30cc1f2c54 100644
--- a/arch/arm/boards/beagle/lowlevel.c
+++ b/arch/arm/boards/beagle/lowlevel.c
@@ -1,4 +1,5 @@
#include <init.h>
+#include <debug_ll.h>
#include <io.h>
#include <linux/sizes.h>
#include <asm/barebox-arm-head.h>
@@ -11,6 +12,7 @@
#include <mach/sdrc.h>
#include <mach/syslib.h>
#include <mach/sys_info.h>
+#include <generated/mach-types.h>
/**
* @brief Do the pin muxing required for Board operation.
@@ -157,6 +159,22 @@ static void sdrc_init(void)
return;
}
+static noinline int beagle_board_init_sdram(void)
+{
+ struct barebox_arm_boarddata *bd = (void *)OMAP3_SRAM_SCRATCH_SPACE + 0x10;
+
+ boarddata_create(bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, bd);
+}
+
+ENTRY_FUNCTION(start_omap3_beagleboard_sdram, bootinfo, r1, r2)
+{
+ omap3_save_bootinfo((void *)bootinfo);
+
+ beagle_board_init_sdram();
+}
+
/**
* @brief The basic entry point for board initialization.
*
@@ -166,28 +184,37 @@ static void sdrc_init(void)
*
* @return void
*/
-static int beagle_board_init(void)
+static noinline int beagle_board_init(void)
{
int in_sdram = omap3_running_in_sdram();
+ struct barebox_arm_boarddata bd;
if (!in_sdram)
omap3_core_init();
mux_config();
+
+ omap_uart_lowlevel_init((void *)OMAP3_UART3_BASE);
+
/* Dont reconfigure SDRAM while running in SDRAM! */
if (!in_sdram)
sdrc_init();
- return 0;
+ boarddata_create(&bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, &bd);
}
-void __naked __bare_init barebox_arm_reset_vector(uint32_t *data)
+ENTRY_FUNCTION(start_omap3_beagleboard_sram, bootinfo, r1, r2)
{
- omap3_save_bootinfo(data);
+ omap3_save_bootinfo((void *)bootinfo);
arm_cpu_lowlevel_init();
- beagle_board_init();
+ omap3_gp_romcode_call(OMAP3_GP_ROMCODE_API_L2_INVAL, 0);
+
+ relocate_to_current_adr();
+ setup_c();
- barebox_arm_entry(0x80000000, SZ_128M, NULL);
+ beagle_board_init();
}
diff --git a/arch/arm/boards/eltec-hipercam/lowlevel.c b/arch/arm/boards/eltec-hipercam/lowlevel.c
index 8f11f6796f..21542e49e9 100644
--- a/arch/arm/boards/eltec-hipercam/lowlevel.c
+++ b/arch/arm/boards/eltec-hipercam/lowlevel.c
@@ -24,18 +24,10 @@
static void setup_uart(void)
{
- void __iomem *uart_base = (void *)0x02020000;
-
writel(0x1, 0x020e0330);
- writel(0x00000000, uart_base + 0x80);
- writel(0x00004027, uart_base + 0x84);
- writel(0x00000704, uart_base + 0x88);
- writel(0x00000a81, uart_base + 0x90);
- writel(0x0000002b, uart_base + 0x9c);
- writel(0x00013880, uart_base + 0xb0);
- writel(0x0000047f, uart_base + 0xa4);
- writel(0x0000c34f, uart_base + 0xa8);
- writel(0x00000001, uart_base + 0x80);
+
+ imx6_uart_setup_ll();
+
putc_ll('>');
}
@@ -48,7 +40,9 @@ ENTRY_FUNCTION(start_imx6dl_eltec_hipercam, r0, r1, r2)
imx6_cpu_lowlevel_init();
arm_setup_stack(0x00940000 - 8);
- setup_uart();
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
fdt = __dtb_imx6dl_eltec_hipercam_start - get_runtime_offset();
diff --git a/arch/arm/boards/embest-riotboard/lowlevel.c b/arch/arm/boards/embest-riotboard/lowlevel.c
index fe21b9aadc..59010da511 100644
--- a/arch/arm/boards/embest-riotboard/lowlevel.c
+++ b/arch/arm/boards/embest-riotboard/lowlevel.c
@@ -10,20 +10,6 @@
#include <mach/imx6-mmdc.h>
#include <mach/imx6.h>
-static inline void setup_uart(void)
-{
- /* Enable UART for lowlevel debugging purposes */
- writel(0x00000000, 0x021e8080);
- writel(0x00004027, 0x021e8084);
- writel(0x00000704, 0x021e8088);
- writel(0x00000a81, 0x021e8090);
- writel(0x0000002b, 0x021e809c);
- writel(0x00013880, 0x021e80b0);
- writel(0x0000047f, 0x021e80a4);
- writel(0x0000c34f, 0x021e80a8);
- writel(0x00000001, 0x021e8080);
-}
-
extern char __dtb_imx6s_riotboard_start[];
ENTRY_FUNCTION(start_imx6s_riotboard, r0, r1, r2)
@@ -34,7 +20,7 @@ ENTRY_FUNCTION(start_imx6s_riotboard, r0, r1, r2)
if (IS_ENABLED(CONFIG_DEBUG_LL)) {
writel(0x4, 0x020e016c);
- setup_uart();
+ imx6_uart_setup_ll();
putc_ll('a');
}
diff --git a/arch/arm/boards/freescale-mx51-babbage/Makefile b/arch/arm/boards/freescale-mx51-babbage/Makefile
index 6252c88631..31b8fcd8a2 100644
--- a/arch/arm/boards/freescale-mx51-babbage/Makefile
+++ b/arch/arm/boards/freescale-mx51-babbage/Makefile
@@ -1,3 +1,6 @@
obj-y += board.o flash-header-imx51-babbage.dcd.o
extra-y += flash-header-imx51-babbage.dcd.S flash-header-imx51-babbage.dcd
lwl-y += lowlevel.o
+
+obj-$(CONFIG_ARCH_IMX_XLOAD) += flash-header-imx51-babbage-xload.dcd.o
+extra-$(CONFIG_ARCH_IMX_XLOAD) += flash-header-imx51-babbage-xload.dcd.S flash-header-imx51-babbage-xload.dcd
diff --git a/arch/arm/boards/freescale-mx51-babbage/board.c b/arch/arm/boards/freescale-mx51-babbage/board.c
index 001873b01c..6650ff3408 100644
--- a/arch/arm/boards/freescale-mx51-babbage/board.c
+++ b/arch/arm/boards/freescale-mx51-babbage/board.c
@@ -169,3 +169,63 @@ static int imx51_babbage_init(void)
return 0;
}
coredevice_initcall(imx51_babbage_init);
+
+#ifdef CONFIG_ARCH_IMX_XLOAD
+
+static int imx51_babbage_xload_init_pinmux(void)
+{
+ static const iomux_v3_cfg_t pinmux[] = {
+ /* (e)CSPI */
+ MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+ MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+ MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+
+ /* (e)CSPI chip select lines */
+ MX51_PAD_CSPI1_SS1__GPIO4_25,
+
+
+ /* eSDHC 1 */
+ MX51_PAD_SD1_CMD__SD1_CMD,
+ MX51_PAD_SD1_CLK__SD1_CLK,
+ MX51_PAD_SD1_DATA0__SD1_DATA0,
+ MX51_PAD_SD1_DATA1__SD1_DATA1,
+ MX51_PAD_SD1_DATA2__SD1_DATA2,
+ MX51_PAD_SD1_DATA3__SD1_DATA3,
+ };
+
+ mxc_iomux_v3_setup_multiple_pads(ARRAY_AND_SIZE(pinmux));
+
+ return 0;
+}
+coredevice_initcall(imx51_babbage_xload_init_pinmux);
+
+static int imx51_babbage_xload_init_devices(void)
+{
+ static int spi0_chipselects[] = {
+ IMX_GPIO_NR(4, 25),
+ };
+
+ static struct spi_imx_master spi0_pdata = {
+ .chipselect = spi0_chipselects,
+ .num_chipselect = ARRAY_SIZE(spi0_chipselects),
+ };
+
+ static const struct spi_board_info spi0_devices[] = {
+ {
+ .name = "mtd_dataflash",
+ .chip_select = 0,
+ .max_speed_hz = 25 * 1000 * 1000,
+ .bus_num = 0,
+ },
+ };
+
+ imx51_add_mmc0(NULL);
+
+ spi_register_board_info(ARRAY_AND_SIZE(spi0_devices));
+ imx51_add_spi0(&spi0_pdata);
+
+ return 0;
+}
+device_initcall(imx51_babbage_xload_init_devices);
+
+#endif
diff --git a/arch/arm/boards/freescale-mx51-babbage/flash-header-common.imxcfg b/arch/arm/boards/freescale-mx51-babbage/flash-header-common.imxcfg
new file mode 100644
index 0000000000..1332b74707
--- /dev/null
+++ b/arch/arm/boards/freescale-mx51-babbage/flash-header-common.imxcfg
@@ -0,0 +1,58 @@
+soc imx51
+dcdofs 0x400
+wm 32 0x73fa88a0 0x00000200
+wm 32 0x73fa850c 0x000020c5
+wm 32 0x73fa8510 0x000020c5
+wm 32 0x73fa883c 0x00000002
+wm 32 0x73fa8848 0x00000002
+wm 32 0x73fa84b8 0x000000e7
+wm 32 0x73fa84bc 0x00000045
+wm 32 0x73fa84c0 0x00000045
+wm 32 0x73fa84c4 0x00000045
+wm 32 0x73fa84c8 0x00000045
+wm 32 0x73fa8820 0x00000000
+wm 32 0x73fa84a4 0x00000003
+wm 32 0x73fa84a8 0x00000003
+wm 32 0x73fa84ac 0x000000e3
+wm 32 0x73fa84b0 0x000000e3
+wm 32 0x73fa84b4 0x000000e3
+wm 32 0x73fa84cc 0x000000e3
+wm 32 0x73fa84d0 0x000000e2
+wm 32 0x73fa882c 0x00000004
+wm 32 0x73fa88a4 0x00000004
+wm 32 0x73fa88ac 0x00000004
+wm 32 0x73fa88b8 0x00000004
+wm 32 0x83fd9000 0x82a20000
+wm 32 0x83fd9008 0x82a20000
+wm 32 0x83fd9010 0x000ad0d0
+wm 32 0x83fd9004 0x3f3584ab
+wm 32 0x83fd900c 0x3f3584ab
+wm 32 0x83fd9014 0x04008008
+wm 32 0x83fd9014 0x0000801a
+wm 32 0x83fd9014 0x0000801b
+wm 32 0x83fd9014 0x00448019
+wm 32 0x83fd9014 0x07328018
+wm 32 0x83fd9014 0x04008008
+wm 32 0x83fd9014 0x00008010
+wm 32 0x83fd9014 0x00008010
+wm 32 0x83fd9014 0x06328018
+wm 32 0x83fd9014 0x03808019
+wm 32 0x83fd9014 0x00408019
+wm 32 0x83fd9014 0x00008000
+wm 32 0x83fd9014 0x0400800c
+wm 32 0x83fd9014 0x0000801e
+wm 32 0x83fd9014 0x0000801f
+wm 32 0x83fd9014 0x0000801d
+wm 32 0x83fd9014 0x0732801c
+wm 32 0x83fd9014 0x0400800c
+wm 32 0x83fd9014 0x00008014
+wm 32 0x83fd9014 0x00008014
+wm 32 0x83fd9014 0x0632801c
+wm 32 0x83fd9014 0x0380801d
+wm 32 0x83fd9014 0x0040801d
+wm 32 0x83fd9014 0x00008004
+wm 32 0x83fd9000 0xb2a20000
+wm 32 0x83fd9008 0xb2a20000
+wm 32 0x83fd9010 0x000ad6d0
+wm 32 0x83fd9034 0x90000000
+wm 32 0x83fd9014 0x00000000
diff --git a/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage-xload.imxcfg b/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage-xload.imxcfg
new file mode 100644
index 0000000000..b249a7d4bc
--- /dev/null
+++ b/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage-xload.imxcfg
@@ -0,0 +1,3 @@
+loadaddr CONFIG_ARCH_IMX_UNUSED_IRAM_BASE
+
+#include "flash-header-common.imxcfg" \ No newline at end of file
diff --git a/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg b/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg
index bac6816fee..cb60e4752a 100644
--- a/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg
+++ b/arch/arm/boards/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg
@@ -1,59 +1,3 @@
loadaddr 0x90000000
-soc imx51
-dcdofs 0x400
-wm 32 0x73fa88a0 0x00000200
-wm 32 0x73fa850c 0x000020c5
-wm 32 0x73fa8510 0x000020c5
-wm 32 0x73fa883c 0x00000002
-wm 32 0x73fa8848 0x00000002
-wm 32 0x73fa84b8 0x000000e7
-wm 32 0x73fa84bc 0x00000045
-wm 32 0x73fa84c0 0x00000045
-wm 32 0x73fa84c4 0x00000045
-wm 32 0x73fa84c8 0x00000045
-wm 32 0x73fa8820 0x00000000
-wm 32 0x73fa84a4 0x00000003
-wm 32 0x73fa84a8 0x00000003
-wm 32 0x73fa84ac 0x000000e3
-wm 32 0x73fa84b0 0x000000e3
-wm 32 0x73fa84b4 0x000000e3
-wm 32 0x73fa84cc 0x000000e3
-wm 32 0x73fa84d0 0x000000e2
-wm 32 0x73fa882c 0x00000004
-wm 32 0x73fa88a4 0x00000004
-wm 32 0x73fa88ac 0x00000004
-wm 32 0x73fa88b8 0x00000004
-wm 32 0x83fd9000 0x82a20000
-wm 32 0x83fd9008 0x82a20000
-wm 32 0x83fd9010 0x000ad0d0
-wm 32 0x83fd9004 0x3f3584ab
-wm 32 0x83fd900c 0x3f3584ab
-wm 32 0x83fd9014 0x04008008
-wm 32 0x83fd9014 0x0000801a
-wm 32 0x83fd9014 0x0000801b
-wm 32 0x83fd9014 0x00448019
-wm 32 0x83fd9014 0x07328018
-wm 32 0x83fd9014 0x04008008
-wm 32 0x83fd9014 0x00008010
-wm 32 0x83fd9014 0x00008010
-wm 32 0x83fd9014 0x06328018
-wm 32 0x83fd9014 0x03808019
-wm 32 0x83fd9014 0x00408019
-wm 32 0x83fd9014 0x00008000
-wm 32 0x83fd9014 0x0400800c
-wm 32 0x83fd9014 0x0000801e
-wm 32 0x83fd9014 0x0000801f
-wm 32 0x83fd9014 0x0000801d
-wm 32 0x83fd9014 0x0732801c
-wm 32 0x83fd9014 0x0400800c
-wm 32 0x83fd9014 0x00008014
-wm 32 0x83fd9014 0x00008014
-wm 32 0x83fd9014 0x0632801c
-wm 32 0x83fd9014 0x0380801d
-wm 32 0x83fd9014 0x0040801d
-wm 32 0x83fd9014 0x00008004
-wm 32 0x83fd9000 0xb2a20000
-wm 32 0x83fd9008 0xb2a20000
-wm 32 0x83fd9010 0x000ad6d0
-wm 32 0x83fd9034 0x90000000
-wm 32 0x83fd9014 0x00000000
+
+#include "flash-header-common.imxcfg" \ No newline at end of file
diff --git a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c
index 0f453f3367..af40f4405e 100644
--- a/arch/arm/boards/freescale-mx51-babbage/lowlevel.c
+++ b/arch/arm/boards/freescale-mx51-babbage/lowlevel.c
@@ -1,9 +1,42 @@
+#include <debug_ll.h>
+#include <mach/clock-imx51_53.h>
#include <common.h>
#include <mach/esdctl.h>
#include <mach/generic.h>
+#include <asm/cache.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
+static inline void setup_uart(void)
+{
+ void __iomem *iomuxbase = IOMEM(MX51_IOMUXC_BASE_ADDR);
+ void __iomem *ccmbase = IOMEM(MX51_CCM_BASE_ADDR);
+
+ /*
+ * Restore CCM values that might be changed by the Mask ROM
+ * code.
+ *
+ * Source: RealView debug scripts provided by Freescale
+ */
+ writel(MX5_CCM_CBCDR_RESET_VALUE, ccmbase + MX5_CCM_CBCDR);
+ writel(MX5_CCM_CSCMR1_RESET_VALUE, ccmbase + MX5_CCM_CSCMR1);
+ writel(MX5_CCM_CSCDR1_RESET_VALUE, ccmbase + MX5_CCM_CSCDR1);
+
+ /*
+ * The code below should be more or less a "moral equivalent"
+ * of:
+ * MX51_PAD_UART1_TXD__UART1_TXD 0x1c5
+ *
+ * in device tree
+ */
+ writel(0x00000000, iomuxbase + 0x022c);
+ writel(0x000001c5, iomuxbase + 0x061c);
+
+ imx51_uart_setup_ll();
+
+ putc_ll('>');
+}
+
extern char __dtb_imx51_babbage_start[];
ENTRY_FUNCTION(start_imx51_babbage, r0, r1, r2)
@@ -11,9 +44,37 @@ ENTRY_FUNCTION(start_imx51_babbage, r0, r1, r2)
void *fdt;
imx5_cpu_lowlevel_init();
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
+
arm_setup_stack(0x20000000 - 16);
fdt = __dtb_imx51_babbage_start - get_runtime_offset();
imx51_barebox_entry(fdt);
}
+
+static noinline void babbage_entry(void)
+{
+ arm_early_mmu_cache_invalidate();
+
+ relocate_to_current_adr();
+ setup_c();
+
+ puts_ll("lowlevel init done\n");
+
+ imx51_barebox_entry(NULL);
+}
+
+ENTRY_FUNCTION(start_imx51_babbage_xload, r0, r1, r2)
+{
+ imx5_cpu_lowlevel_init();
+
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
+
+ arm_setup_stack(0x20000000 - 16);
+
+ babbage_entry();
+}
diff --git a/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg b/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
index 95bcd19805..f43b484ee6 100644
--- a/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
+++ b/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
@@ -30,7 +30,7 @@ wm 32 0x63fd9090 0x4d444c44
wm 32 0x63fd907c 0x01370138
wm 32 0x63fd9080 0x013b013c
wm 32 0x63fd9018 0x00011740
-wm 32 0x63fd9000 0xc3190000
+wm 32 0x63fd9000 0x83190000
wm 32 0x63fd900c 0x9f5152e3
wm 32 0x63fd9010 0xb68e8a63
wm 32 0x63fd9014 0x01ff00db
@@ -43,6 +43,7 @@ wm 32 0x63fd901c 0x00008033
wm 32 0x63fd901c 0x00028031
wm 32 0x63fd901c 0x052080b0
wm 32 0x63fd901c 0x04008040
+wm 32 0x63fd9000 0xc3190000
wm 32 0x63fd901c 0x0000803a
wm 32 0x63fd901c 0x0000803b
wm 32 0x63fd901c 0x00028039
diff --git a/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c b/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c
index 4c5a74ea63..af26557e90 100644
--- a/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c
+++ b/arch/arm/boards/freescale-mx6sx-sabresdb/lowlevel.c
@@ -21,32 +21,16 @@
static inline void setup_uart(void)
{
- void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
- void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
- writel(0xffffffff, ccmbase + 0x68);
- writel(0xffffffff, ccmbase + 0x6c);
- writel(0xffffffff, ccmbase + 0x70);
- writel(0xffffffff, ccmbase + 0x74);
- writel(0xffffffff, ccmbase + 0x78);
- writel(0xffffffff, ccmbase + 0x7c);
- writel(0xffffffff, ccmbase + 0x80);
+ imx6_ungate_all_peripherals();
writel(0x0, iomuxbase + 0x24);
writel(0x1b0b1, iomuxbase + 0x036C);
writel(0x0, iomuxbase + 0x28);
writel(0x1b0b1, iomuxbase + 0x0370);
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000784, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x0001b0b0, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_uart_setup_ll();
putc_ll('>');
}
diff --git a/arch/arm/boards/guf-santaro/lowlevel.c b/arch/arm/boards/guf-santaro/lowlevel.c
index 7753cea4e2..e2b6df5839 100644
--- a/arch/arm/boards/guf-santaro/lowlevel.c
+++ b/arch/arm/boards/guf-santaro/lowlevel.c
@@ -9,20 +9,12 @@
static inline void setup_uart(void)
{
- void __iomem *uartbase = (void *)MX6_UART2_BASE_ADDR;
void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
writel(0x1, iomuxbase + 0x2b0);
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000704, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x00013880, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_ungate_all_peripherals();
+ imx6_uart_setup_ll();
putc_ll('>');
}
@@ -32,16 +24,13 @@ extern char __dtb_imx6q_guf_santaro_start[];
ENTRY_FUNCTION(start_imx6q_guf_santaro, r0, r1, r2)
{
void *fdt;
- int i;
imx6_cpu_lowlevel_init();
arm_setup_stack(0x00920000 - 8);
- for (i = 0x68; i <= 0x80; i += 4)
- writel(0xffffffff, MX6_CCM_BASE_ADDR + i);
-
- setup_uart();
+ if (IS_ENABLED(CONFIG_DEBUG_LL))
+ setup_uart();
fdt = __dtb_imx6q_guf_santaro_start - get_runtime_offset();
diff --git a/arch/arm/boards/karo-tx6x/lowlevel.c b/arch/arm/boards/karo-tx6x/lowlevel.c
index cd4be5e9e7..1e44b1b38d 100644
--- a/arch/arm/boards/karo-tx6x/lowlevel.c
+++ b/arch/arm/boards/karo-tx6x/lowlevel.c
@@ -22,8 +22,6 @@
static inline void setup_uart(void)
{
- void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
- void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
writel(0x1, iomuxbase + 0x0314);
@@ -31,23 +29,8 @@ static inline void setup_uart(void)
writel(0x1, iomuxbase + 0x0330);
writel(0x1, iomuxbase + 0x032c);
- writel(0xffffffff, ccmbase + 0x68);
- writel(0xffffffff, ccmbase + 0x6c);
- writel(0xffffffff, ccmbase + 0x70);
- writel(0xffffffff, ccmbase + 0x74);
- writel(0xffffffff, ccmbase + 0x78);
- writel(0xffffffff, ccmbase + 0x7c);
- writel(0xffffffff, ccmbase + 0x80);
-
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000784, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x0001b0b0, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_ungate_all_peripherals();
+ imx6_uart_setup_ll();
putc_ll('>');
}
diff --git a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
index dc106490e7..d85a1ab0a1 100644
--- a/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phycard-imx6/lowlevel.c
@@ -26,29 +26,12 @@
static inline void setup_uart(void)
{
- void __iomem *ccmbase = IOMEM(MX6_CCM_BASE_ADDR);
- void __iomem *uartbase = IOMEM(MX6_UART3_BASE_ADDR);
void __iomem *iomuxbase = IOMEM(MX6_IOMUXC_BASE_ADDR);
writel(0x4, iomuxbase + 0x01f8);
- writel(0xffffffff, ccmbase + 0x68);
- writel(0xffffffff, ccmbase + 0x6c);
- writel(0xffffffff, ccmbase + 0x70);
- writel(0xffffffff, ccmbase + 0x74);
- writel(0xffffffff, ccmbase + 0x78);
- writel(0xffffffff, ccmbase + 0x7c);
- writel(0xffffffff, ccmbase + 0x80);
-
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000704, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x00013880, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_ungate_all_peripherals();
+ imx6_uart_setup_ll();
putc_ll('>');
}
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index ee6d7fb262..cd37f88e05 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -27,29 +27,12 @@
static inline void setup_uart(void)
{
- void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
- void __iomem *uartbase = (void *)MX6_UART4_BASE_ADDR;
void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
writel(0x4, iomuxbase + 0x01f8);
- writel(0xffffffff, ccmbase + 0x68);
- writel(0xffffffff, ccmbase + 0x6c);
- writel(0xffffffff, ccmbase + 0x70);
- writel(0xffffffff, ccmbase + 0x74);
- writel(0xffffffff, ccmbase + 0x78);
- writel(0xffffffff, ccmbase + 0x7c);
- writel(0xffffffff, ccmbase + 0x80);
-
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000704, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x00013880, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_ungate_all_peripherals();
+ imx6_uart_setup_ll();
putc_ll('>');
}
diff --git a/arch/arm/boards/phytec-som-am335x/board.c b/arch/arm/boards/phytec-som-am335x/board.c
index 74e39d70fc..7a878415f8 100644
--- a/arch/arm/boards/phytec-som-am335x/board.c
+++ b/arch/arm/boards/phytec-som-am335x/board.c
@@ -68,7 +68,10 @@ static int physom_devices_init(void)
of_device_enable_path("/chosen/environment-spi");
break;
case BOOTSOURCE_MMC:
- omap_set_bootmmc_devname("mmc0");
+ if (bootsource_get_instance() == 0)
+ omap_set_bootmmc_devname("mmc0");
+ else
+ omap_set_bootmmc_devname("mmc1");
break;
default:
of_device_enable_path("/chosen/environment-nand");
diff --git a/arch/arm/boards/tqma6x/lowlevel.c b/arch/arm/boards/tqma6x/lowlevel.c
index 23f3407c05..aec84b176b 100644
--- a/arch/arm/boards/tqma6x/lowlevel.c
+++ b/arch/arm/boards/tqma6x/lowlevel.c
@@ -24,20 +24,6 @@
#include <mach/imx6-mmdc.h>
#include <mach/imx6.h>
-static inline void setup_uart(void)
-{
- /* Enable UART for lowlevel debugging purposes */
- writel(0x00000000, 0x021e8080);
- writel(0x00004027, 0x021e8084);
- writel(0x00000704, 0x021e8088);
- writel(0x00000a81, 0x021e8090);
- writel(0x0000002b, 0x021e809c);
- writel(0x00013880, 0x021e80b0);
- writel(0x0000047f, 0x021e80a4);
- writel(0x0000c34f, 0x021e80a8);
- writel(0x00000001, 0x021e8080);
-}
-
extern char __dtb_imx6q_mba6x_start[];
extern char __dtb_imx6dl_mba6x_start[];
@@ -51,7 +37,7 @@ ENTRY_FUNCTION(start_imx6q_mba6x, r0, r1, r2)
if (IS_ENABLED(CONFIG_DEBUG_LL)) {
writel(0x2, 0x020e0338);
- setup_uart();
+ imx6_uart_setup_ll();
putc_ll('a');
}
@@ -72,7 +58,7 @@ ENTRY_FUNCTION(start_imx6dl_mba6x, r0, r1, r2)
if (IS_ENABLED(CONFIG_DEBUG_LL)) {
writel(0x2, 0x020e035c);
- setup_uart();
+ imx6_uart_setup_ll();
putc_ll('a');
}
diff --git a/arch/arm/boards/variscite-mx6/lowlevel.c b/arch/arm/boards/variscite-mx6/lowlevel.c
index 22e7eae32b..b0b930d438 100644
--- a/arch/arm/boards/variscite-mx6/lowlevel.c
+++ b/arch/arm/boards/variscite-mx6/lowlevel.c
@@ -28,30 +28,13 @@
static inline void setup_uart(void)
{
- void __iomem *ccmbase = (void *)MX6_CCM_BASE_ADDR;
- void __iomem *uartbase = (void *)MX6_UART1_BASE_ADDR;
void __iomem *iomuxbase = (void *)MX6_IOMUXC_BASE_ADDR;
writel(0x03, iomuxbase + 0x0280);
writel(0x03, iomuxbase + 0x0284);
- writel(0xffffffff, ccmbase + 0x68);
- writel(0xffffffff, ccmbase + 0x6c);
- writel(0xffffffff, ccmbase + 0x70);
- writel(0xffffffff, ccmbase + 0x74);
- writel(0xffffffff, ccmbase + 0x78);
- writel(0xffffffff, ccmbase + 0x7c);
- writel(0xffffffff, ccmbase + 0x80);
-
- writel(0x00000000, uartbase + 0x80);
- writel(0x00004027, uartbase + 0x84);
- writel(0x00000704, uartbase + 0x88);
- writel(0x00000a81, uartbase + 0x90);
- writel(0x0000002b, uartbase + 0x9c);
- writel(0x00013880, uartbase + 0xb0);
- writel(0x0000047f, uartbase + 0xa4);
- writel(0x0000c34f, uartbase + 0xa8);
- writel(0x00000001, uartbase + 0x80);
+ imx6_ungate_all_peripherals();
+ imx6_uart_setup_ll();
putc_ll('>');
}
diff --git a/arch/arm/configs/am335x_mlo_defconfig b/arch/arm/configs/am335x_mlo_defconfig
index 1dd7567d0d..b66a653681 100644
--- a/arch/arm/configs/am335x_mlo_defconfig
+++ b/arch/arm/configs/am335x_mlo_defconfig
@@ -9,6 +9,7 @@ CONFIG_THUMB2_BAREBOX=y
# CONFIG_MEMINFO is not set
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x0
+CONFIG_BAREBOX_MAX_PBLX_SIZE=0x1b400
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_RELOCATABLE=y
diff --git a/arch/arm/configs/imx_v7-xload_defconfig b/arch/arm/configs/imx_v7-xload_defconfig
new file mode 100644
index 0000000000..1d82f98f49
--- /dev/null
+++ b/arch/arm/configs/imx_v7-xload_defconfig
@@ -0,0 +1,52 @@
+CONFIG_ARCH_IMX=y
+CONFIG_ARCH_IMX_IMXIMAGE=y
+CONFIG_ARCH_IMX_XLOAD=y
+
+CONFIG_ARCH_IMX51=y
+CONFIG_IMX_MULTI_BOARDS=y
+CONFIG_MACH_FREESCALE_MX51_PDK=y
+
+CONFIG_THUMB2_BAREBOX=y
+# CONFIG_CMD_ARM_CPUINFO is not set
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x0
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_DUMMY=y
+CONFIG_RELOCATABLE=y
+CONFIG_BAUDRATE=115200
+CONFIG_SHELL_NONE=y
+
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_IMX51_UART=y
+CONFIG_DEBUG_IMX_UART_PORT=1
+
+CONFIG_HAS_DEBUG_LL=y
+
+CONFIG_MTD=y
+# CONFIG_MTD_WRITE is not set
+CONFIG_MTD_DATAFLASH=y
+
+# CONFIG_ERRNO_MESSAGES is not set
+# CONFIG_TIMESTAMP is not set
+# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_DRIVER_SERIAL_IMX=y
+
+CONFIG_MCI=y
+CONFIG_MCI_STARTUP=y
+# CONFIG_MCI_WRITE is not set
+
+CONFIG_MCI_IMX_ESDHC=y
+
+CONFIG_EEPROM_AT25=y
+
+CONFIG_WATCHDOG_IMX_RESET_SOURCE=y
+CONFIG_WATCHDOG=y
+CONFIG_WATCHDOG_IMX=y
+
+# CONFIG_FS_RAMFS is not set
+# CONFIG_FS_DEVFS is not set
+CONFIG_FS_FAT=y
+CONFIG_BOOTSTRAP=y
+CONFIG_BOOTSTRAP_DISK=y
+CONFIG_BOOTSTRAP_DEVFS=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index bf04fa3b18..224854c7cc 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -6,7 +6,6 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
# CONFIG_BANNER is not set
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0xa3d00000
CONFIG_BAREBOX_MAX_BARE_INIT_SIZE=0x80000
CONFIG_MALLOC_SIZE=0x1000000
CONFIG_EXPERIMENTAL=y
diff --git a/arch/arm/configs/omap3530_beagle_defconfig b/arch/arm/configs/omap3530_beagle_defconfig
index 3068fbb94b..070f1566ee 100644
--- a/arch/arm/configs/omap3530_beagle_defconfig
+++ b/arch/arm/configs/omap3530_beagle_defconfig
@@ -1,67 +1,79 @@
CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
-CONFIG_PBL_IMAGE=y
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x87e00000
-CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_TEXT_BASE=0x0
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="barebox> "
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+CONFIG_BLSPEC=y
+CONFIG_IMD_TARGET=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/beagle/env"
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_DIRNAME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
-CONFIG_CMD_TFTP=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADB=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_RESET_SOURCE=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_OMAP_UART_PORT=3
+CONFIG_DEBUG_INITCALLS=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
-CONFIG_CMD_FLASH=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=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_BOOTU is not set
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
-CONFIG_CMD_I2C=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_TIME=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
CONFIG_NET_NFS=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
-CONFIG_NET_RESOLV=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
CONFIG_NET_USB=y
@@ -81,6 +93,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_OMAP_HSMMC=y
CONFIG_MFD_TWL4030=y
+CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/omap3530_beagle_xload_defconfig b/arch/arm/configs/omap3530_beagle_xload_defconfig
index 585ee0f1d1..074cc2116b 100644
--- a/arch/arm/configs/omap3530_beagle_xload_defconfig
+++ b/arch/arm/configs/omap3530_beagle_xload_defconfig
@@ -1,21 +1,25 @@
CONFIG_ARCH_OMAP=y
CONFIG_OMAP_BUILD_IFT=y
+CONFIG_OMAP3_USBBOOT=y
+CONFIG_OMAP3_USB_LOADER=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-# CONFIG_CMD_ARM_CPUINFO is not set
-# CONFIG_ARM_EXCEPTIONS is not set
-CONFIG_TEXT_BASE=0x40200000
-CONFIG_MEMORY_LAYOUT_FIXED=y
-CONFIG_STACK_BASE=0x4020F000
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x0
CONFIG_STACK_SIZE=0xc00
-CONFIG_MALLOC_BASE=0x87BFFF10
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_DUMMY=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="X-load Beagle>"
CONFIG_SHELL_NONE=y
# CONFIG_ERRNO_MESSAGES is not set
# CONFIG_TIMESTAMP is not set
CONFIG_CONSOLE_SIMPLE=y
# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_OFDEVICE=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
# CONFIG_SPI is not set
@@ -33,6 +37,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
# CONFIG_MCI_WRITE is not set
CONFIG_MCI_OMAP_HSMMC=y
+# CONFIG_PINCTRL is not set
# CONFIG_FS_RAMFS is not set
# CONFIG_FS_DEVFS is not set
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/phytec-phycard-omap3_defconfig b/arch/arm/configs/phytec-phycard-omap3_defconfig
index a2564d4459..5865ebd8b9 100644
--- a/arch/arm/configs/phytec-phycard-omap3_defconfig
+++ b/arch/arm/configs/phytec-phycard-omap3_defconfig
@@ -7,7 +7,6 @@ CONFIG_CPU_V7=y
CONFIG_CPU_32v7=y
CONFIG_ARCH_OMAP3=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
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index ca54a1a491..ec369ae42e 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -1,70 +1,68 @@
CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SOCFPGA_FPGA=y
CONFIG_MACH_SOCFPGA_EBV_SOCRATES=y
CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT=y
CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x0
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_RELOCATABLE=y
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
# CONFIG_TIMESTAMP is not set
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_LET=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_FILETYPE=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_MM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_OFTREE=y
-CONFIG_CMD_OF_PROPERTY=y
-CONFIG_CMD_OF_NODE=y
-CONFIG_CMD_MEMTEST=y
-CONFIG_CMD_BAREBOX_UPDATE=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_LED=y
-CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
CONFIG_CMD_CLK=y
CONFIG_CMD_DETECT=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 304ed0cee7..8e5097b560 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -28,17 +28,22 @@
#include <asm/cache.h>
#include <memory.h>
+#include <debug_ll.h>
#include "mmu-early.h"
unsigned long arm_stack_top;
static void *barebox_boarddata;
-/*
- * return the boarddata variable passed to barebox_arm_entry
- */
-void *barebox_arm_boarddata(void)
+u32 barebox_arm_machine(void)
{
- return barebox_boarddata;
+ struct barebox_arm_boarddata *bd;
+
+ if (!barebox_boarddata)
+ return 0;
+
+ bd = barebox_boarddata;
+
+ return bd->machine;
}
static void *barebox_boot_dtb;
@@ -61,6 +66,8 @@ static noinline __noreturn void __start(unsigned long membase,
setup_c();
+ barrier();
+
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
barebox_boarddata = boarddata;
@@ -81,17 +88,23 @@ static noinline __noreturn void __start(unsigned long membase,
}
}
- /*
- * If boarddata is a pointer inside valid memory and contains a
- * FDT magic then use it as later to probe devices
- */
- if (boarddata && get_unaligned_be32(boarddata) == FDT_MAGIC) {
- uint32_t totalsize = get_unaligned_be32(boarddata + 4);
- endmem -= ALIGN(totalsize, 64);
- barebox_boot_dtb = (void *)endmem;
- pr_debug("found DTB in boarddata, copying to 0x%p\n",
- barebox_boot_dtb);
- memcpy(barebox_boot_dtb, boarddata, totalsize);
+ if (boarddata) {
+ if (get_unaligned_be32(boarddata) == FDT_MAGIC) {
+ uint32_t totalsize = get_unaligned_be32(boarddata + 4);
+ endmem -= ALIGN(totalsize, 64);
+ barebox_boot_dtb = (void *)endmem;
+ pr_debug("found DTB in boarddata, copying to 0x%p\n",
+ barebox_boot_dtb);
+ memcpy(barebox_boot_dtb, boarddata, totalsize);
+ } else if (((struct barebox_arm_boarddata *)boarddata)->magic ==
+ BAREBOX_ARM_BOARDDATA_MAGIC) {
+ endmem -= ALIGN(sizeof(struct barebox_arm_boarddata), 64);
+ barebox_boarddata = (void *)endmem;
+ pr_debug("found machine type in boarddata, copying to 0x%p\n",
+ barebox_boarddata);
+ memcpy(barebox_boarddata, boarddata,
+ sizeof(struct barebox_arm_boarddata));
+ }
}
if ((unsigned long)_text > membase + memsize ||
diff --git a/arch/arm/crypto/.gitignore b/arch/arm/crypto/.gitignore
new file mode 100644
index 0000000000..b22a068f76
--- /dev/null
+++ b/arch/arm/crypto/.gitignore
@@ -0,0 +1 @@
+/sha256-core.S
diff --git a/arch/arm/dts/am335x-phytec-phycard-som-mlo.dts b/arch/arm/dts/am335x-phytec-phycard-som-mlo.dts
index 17d9152977..f9ed627120 100644
--- a/arch/arm/dts/am335x-phytec-phycard-som-mlo.dts
+++ b/arch/arm/dts/am335x-phytec-phycard-som-mlo.dts
@@ -9,6 +9,7 @@
#include "am33xx.dtsi"
#include "am335x-phytec-phycard-som.dtsi"
+#include "am33xx-strip.dtsi"
/ {
model = "Phytec phyCARD AM335x";
diff --git a/arch/arm/dts/am335x-phytec-phycore-som-mlo.dts b/arch/arm/dts/am335x-phytec-phycore-som-mlo.dts
index b08a59e0f5..f70835f8cd 100644
--- a/arch/arm/dts/am335x-phytec-phycore-som-mlo.dts
+++ b/arch/arm/dts/am335x-phytec-phycore-som-mlo.dts
@@ -9,6 +9,7 @@
#include "am33xx.dtsi"
#include "am335x-phytec-phycore-som.dtsi"
+#include "am33xx-strip.dtsi"
/ {
model = "Phytec phyCORE AM335x";
diff --git a/arch/arm/dts/am335x-phytec-phyflex-som-mlo.dts b/arch/arm/dts/am335x-phytec-phyflex-som-mlo.dts
index 5294ff5976..736d7ef664 100644
--- a/arch/arm/dts/am335x-phytec-phyflex-som-mlo.dts
+++ b/arch/arm/dts/am335x-phytec-phyflex-som-mlo.dts
@@ -9,6 +9,7 @@
#include "am33xx.dtsi"
#include "am335x-phytec-phyflex-som.dtsi"
+#include "am33xx-strip.dtsi"
/ {
model = "Phytec phyFLEX AM335x";
diff --git a/arch/arm/dts/am33xx-strip.dtsi b/arch/arm/dts/am33xx-strip.dtsi
new file mode 100644
index 0000000000..04cf3151ea
--- /dev/null
+++ b/arch/arm/dts/am33xx-strip.dtsi
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2015 PHYTEC Messtechnik GmbH,
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+/ {
+ aliases {
+ /delete-property/ i2c1;
+ /delete-property/ i2c2;
+ /delete-property/ mmc2;
+ /delete-property/ d_can0;
+ /delete-property/ d_can1;
+ };
+};
+
+/delete-node/ &i2c1;
+/delete-node/ &i2c2;
+/delete-node/ &mmc3;
+/delete-node/ &hwspinlock;
+/delete-node/ &wdt2;
+/delete-node/ &dcan0;
+/delete-node/ &dcan1;
+/delete-node/ &mailbox;
+/delete-node/ &timer1;
+/delete-node/ &timer2;
+/delete-node/ &timer3;
+/delete-node/ &timer4;
+/delete-node/ &timer5;
+/delete-node/ &timer6;
+/delete-node/ &timer7;
+/delete-node/ &spi1;
+/delete-node/ &epwmss0;
+/delete-node/ &epwmss1;
+/delete-node/ &epwmss2;
+/delete-node/ &lcdc;
+/delete-node/ &tscadc;
+/delete-node/ &sham;
+/delete-node/ &aes;
+/delete-node/ &mcasp0;
+/delete-node/ &mcasp1;
+/delete-node/ &rng;
+/delete-node/ &rtc;
+/delete-node/ &wkup_m3;
diff --git a/arch/arm/dts/imx6dl-tx6u-801x.dts b/arch/arm/dts/imx6dl-tx6u-801x.dts
index 43104b2b88..a480408f50 100644
--- a/arch/arm/dts/imx6dl-tx6u-801x.dts
+++ b/arch/arm/dts/imx6dl-tx6u-801x.dts
@@ -18,12 +18,12 @@
&gpmi {
partition@0 {
label = "barebox";
- reg = <0x0 0x100000>;
+ reg = <0x0 0x400000>;
};
partition@1 {
label = "barebox-environment";
- reg = <0x100000 0x100000>;
+ reg = <0x400000 0x100000>;
};
};
diff --git a/arch/arm/dts/socfpga.dtsi b/arch/arm/dts/socfpga.dtsi
index afac867c99..14c0654b2a 100644
--- a/arch/arm/dts/socfpga.dtsi
+++ b/arch/arm/dts/socfpga.dtsi
@@ -587,6 +587,20 @@
status = "disabled";
};
+ qspi: spi@ff705000 {
+ compatible = "cdns,qspi-nor";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xff705000 0x1000>,
+ <0xffa00000 0x1000>;
+ interrupts = <0 151 4>;
+ ext-decoder = <0>; /* external decoder */
+ fifo-depth = <128>;
+ clocks = <&qspi_clk>;
+ clock-names = "qspi_clk";
+ status = "disabled";
+ };
+
/* Local timer */
timer@fffec600 {
compatible = "arm,cortex-a9-twd-timer";
diff --git a/arch/arm/dts/socfpga_cyclone5_socdk.dts b/arch/arm/dts/socfpga_cyclone5_socdk.dts
index 025d07c18c..fec321a9d5 100644
--- a/arch/arm/dts/socfpga_cyclone5_socdk.dts
+++ b/arch/arm/dts/socfpga_cyclone5_socdk.dts
@@ -61,3 +61,23 @@
vmmc-supply = <&regulator_3_3v>;
vqmmc-supply = <&regulator_3_3v>;
};
+
+&qspi {
+ status = "okay";
+
+ flash: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "n25q00";
+ reg = <0>;
+ spi-max-frequency = <108000000>;
+ m25p,fast-read;
+ cdns,page-size = <256>;
+ cdns,block-size = <16>;
+ cdns,read-delay = <4>;
+ cdns,tshsl-ns = <50>;
+ cdns,tsd2d-ns = <50>;
+ cdns,tchsh-ns = <4>;
+ cdns,tslch-ns = <4>;
+ };
+};
diff --git a/arch/arm/dts/socfpga_cyclone5_sockit.dts b/arch/arm/dts/socfpga_cyclone5_sockit.dts
index e8e00aedfc..1c3fb4d39c 100644
--- a/arch/arm/dts/socfpga_cyclone5_sockit.dts
+++ b/arch/arm/dts/socfpga_cyclone5_sockit.dts
@@ -119,3 +119,23 @@
interrupts = <0x0 0xa6 0x4>;
};
};
+
+&qspi {
+ status = "okay";
+
+ flash: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "n25q00";
+ reg = <0>;
+ spi-max-frequency = <108000000>;
+ m25p,fast-read;
+ cdns,page-size = <256>;
+ cdns,block-size = <16>;
+ cdns,read-delay = <4>;
+ cdns,tshsl-ns = <50>;
+ cdns,tsd2d-ns = <50>;
+ cdns,tchsh-ns = <4>;
+ cdns,tslch-ns = <4>;
+ };
+};
diff --git a/arch/arm/dts/socfpga_cyclone5_socrates.dts b/arch/arm/dts/socfpga_cyclone5_socrates.dts
index 7fa5e63076..125ad1b850 100644
--- a/arch/arm/dts/socfpga_cyclone5_socrates.dts
+++ b/arch/arm/dts/socfpga_cyclone5_socrates.dts
@@ -62,3 +62,23 @@
&mmc {
status = "okay";
};
+
+&qspi {
+ status = "okay";
+
+ flash: flash@0 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "n25q00";
+ reg = <0>;
+ spi-max-frequency = <100000000>;
+ m25p,fast-read;
+ cdns,page-size = <256>;
+ cdns,block-size = <16>;
+ cdns,read-delay = <4>;
+ cdns,tshsl-ns = <50>;
+ cdns,tsd2d-ns = <50>;
+ cdns,tchsh-ns = <4>;
+ cdns,tslch-ns = <4>;
+ };
+};
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index dbc8aaaba7..0b8acb8b8e 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -48,7 +48,32 @@ void setup_c(void);
void relocate_to_current_adr(void);
void relocate_to_adr(unsigned long target);
void __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata);
-void *barebox_arm_boarddata(void);
+
+struct barebox_arm_boarddata {
+#define BAREBOX_ARM_BOARDDATA_MAGIC 0xabe742c3
+ u32 magic;
+ u32 machine; /* machine number to pass to barebox. This may or may
+ * not be a ARM machine number registered on arm.linux.org.uk.
+ * It must only be unique across barebox. Please use a number
+ * that do not potientially clashes with registered machines,
+ * i.e. use a number > 0x10000.
+ */
+};
+
+/*
+ * Create a boarddata struct at given address. Suitable to be passed
+ * as boarddata to barebox_arm_entry(). The machine can be retrieved
+ * later with barebox_arm_machine().
+ */
+static inline void boarddata_create(void *adr, u32 machine)
+{
+ struct barebox_arm_boarddata *bd = adr;
+
+ bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC;
+ bd->machine = machine;
+}
+
+u32 barebox_arm_machine(void);
#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_ARM_EXCEPTIONS)
void arm_fixup_vectors(void);
diff --git a/arch/arm/include/asm/bitsperlong.h b/arch/arm/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..6dc0bb0c13
--- /dev/null
+++ b/arch/arm/include/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/arm/include/asm/posix_types.h b/arch/arm/include/asm/posix_types.h
index aee050eeb8..22cae6230c 100644
--- a/arch/arm/include/asm/posix_types.h
+++ b/arch/arm/include/asm/posix_types.h
@@ -1,78 +1 @@
-/*
- * linux/include/asm-arm/posix_types.h
- *
- * Copyright (C) 1996-1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Changelog:
- * 27-06-1996 RMK Created
- */
-#ifndef __ARCH_ARM_POSIX_TYPES_H
-#define __ARCH_ARM_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __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;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-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, fdsetp) \
- (((fd_set *)fdsetp)->fds_bits[fd >> 5] |= (1<<(fd & 31)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd, fdsetp) \
- (((fd_set *)fdsetp)->fds_bits[fd >> 5] &= ~(1<<(fd & 31)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd, fdsetp) \
- ((((fd_set *)fdsetp)->fds_bits[fd >> 5] & (1<<(fd & 31))) != 0)
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) \
- (memset (fdsetp, 0, sizeof (*(fd_set *)fdsetp)))
-
-#endif
-
-#endif
+#include <asm-generic/posix_types.h>
diff --git a/arch/arm/include/asm/types.h b/arch/arm/include/asm/types.h
index 81bd357ada..1a7f47add0 100644
--- a/arch/arm/include/asm/types.h
+++ b/arch/arm/include/asm/types.h
@@ -31,7 +31,7 @@ typedef unsigned long long __u64;
*/
#ifdef __KERNEL__
-#define BITS_PER_LONG 32
+#include <asm/bitsperlong.h>
#ifndef __ASSEMBLY__
@@ -47,11 +47,6 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
-typedef u32 dma64_addr_t;
-
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
diff --git a/arch/arm/mach-clps711x/reset.c b/arch/arm/mach-clps711x/reset.c
index 67c9c8b8c5..859d8ae574 100644
--- a/arch/arm/mach-clps711x/reset.c
+++ b/arch/arm/mach-clps711x/reset.c
@@ -11,7 +11,7 @@
void __noreturn reset_cpu(unsigned long addr)
{
- arch_shutdown();
+ shutdown_barebox();
asm("mov pc, #0");
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index c713477701..f8f6004630 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -68,6 +68,21 @@ config ARCH_IMX_IMXIMAGE
help
if enabled the imx-image tool is compiled
+config ARCH_IMX_XLOAD
+ bool
+ depends on ARCH_IMX51
+ prompt "Build preloader image"
+
+config ARCH_IMX_UNUSED_IRAM_BASE
+ hex
+ depends on ARCH_IMX_XLOAD
+ default 0x1ffe2000 if ARCH_IMX51
+
+config ARCH_IMX_UNUSED_IRAM_SIZE
+ hex
+ depends on ARCH_IMX_XLOAD
+ default 0x16000 if ARCH_IMX51
+
choice
depends on ARCH_IMX_INTERNAL_BOOT
prompt "Internal boot source"
@@ -112,15 +127,6 @@ config BAREBOX_UPDATE_IMX_EXTERNAL_NAND
depends on MTD_WRITE
default y
-config BAREBOX_UPDATE_IMX6_NAND
- bool
- depends on ARCH_IMX6
- depends on BAREBOX_UPDATE
- depends on MTD
- depends on MTD_WRITE
- depends on NAND_MXS
- default y
-
comment "Freescale i.MX System-on-Chip"
config ARCH_IMX1
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index ae953b1bf8..458d7b45bb 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -12,6 +12,7 @@ pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o
obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o clk-imx6.o
lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o
obj-$(CONFIG_ARCH_IMX6SX) += clk-imx6sx.o
+obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o
obj-$(CONFIG_IMX_IIM) += iim.o
obj-$(CONFIG_IMX_OCOTP) += ocotp.o
obj-$(CONFIG_NAND_IMX) += nand.o
@@ -21,6 +22,5 @@ obj-y += devices.o imx.o esdctl.o
obj-y += boot.o
obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
-obj-$(CONFIG_BAREBOX_UPDATE_IMX6_NAND) += imx6-bbu-nand.o
pbl-y += esdctl.o
lwl-y += cpu_init.o
diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c
index 73630e7092..7508964bf5 100644
--- a/arch/arm/mach-imx/imx6.c
+++ b/arch/arm/mach-imx/imx6.c
@@ -30,7 +30,8 @@ void imx6_init_lowlevel(void)
void __iomem *aips1 = (void *)MX6_AIPS1_ON_BASE_ADDR;
void __iomem *aips2 = (void *)MX6_AIPS2_ON_BASE_ADDR;
void __iomem *iomux = (void *)MX6_IOMUXC_BASE_ADDR;
- int is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+ bool is_imx6q = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6Q;
+ bool is_imx6d = __imx6_cpu_type() == IMX6_CPUTYPE_IMX6D;
uint32_t val;
/*
@@ -67,28 +68,29 @@ void imx6_init_lowlevel(void)
* not output clock after reset, MX6DL and MX6SL have added 396M pfd
* workaround in ROM code, as bus clock need it
*/
- writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
- BM_ANADIG_PFD_480_PFD2_CLKGATE |
- BM_ANADIG_PFD_480_PFD1_CLKGATE |
- BM_ANADIG_PFD_480_PFD0_CLKGATE,
- MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
- writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
- (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
- BM_ANADIG_PFD_528_PFD1_CLKGATE |
- BM_ANADIG_PFD_528_PFD0_CLKGATE,
- MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
-
- writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
- BM_ANADIG_PFD_480_PFD2_CLKGATE |
- BM_ANADIG_PFD_480_PFD1_CLKGATE |
- BM_ANADIG_PFD_480_PFD0_CLKGATE,
- MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
- writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
- (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
- BM_ANADIG_PFD_528_PFD2_CLKGATE |
- BM_ANADIG_PFD_528_PFD1_CLKGATE |
- BM_ANADIG_PFD_528_PFD0_CLKGATE,
- MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
+ if (is_imx6q || is_imx6d) {
+ writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
+ BM_ANADIG_PFD_480_PFD2_CLKGATE |
+ BM_ANADIG_PFD_480_PFD1_CLKGATE |
+ BM_ANADIG_PFD_480_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_SET);
+ writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
+ (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
+ BM_ANADIG_PFD_528_PFD1_CLKGATE |
+ BM_ANADIG_PFD_528_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_SET);
+
+ writel(BM_ANADIG_PFD_480_PFD3_CLKGATE |
+ BM_ANADIG_PFD_480_PFD2_CLKGATE |
+ BM_ANADIG_PFD_480_PFD1_CLKGATE |
+ BM_ANADIG_PFD_480_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_480_CLR);
+ writel(BM_ANADIG_PFD_528_PFD3_CLKGATE |
+ (is_imx6q ? BM_ANADIG_PFD_528_PFD2_CLKGATE : 0) |
+ BM_ANADIG_PFD_528_PFD1_CLKGATE |
+ BM_ANADIG_PFD_528_PFD0_CLKGATE,
+ MX6_ANATOP_BASE_ADDR + HW_ANADIG_PFD_528_CLR);
+ }
val = readl(iomux + IOMUXC_GPR4);
val |= IMX6Q_GPR4_VPU_WR_CACHE_SEL | IMX6Q_GPR4_VPU_RD_CACHE_SEL |
diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h
index 5eb9a47363..8039091395 100644
--- a/arch/arm/mach-imx/include/mach/bbu.h
+++ b/arch/arm/mach-imx/include/mach/bbu.h
@@ -75,15 +75,6 @@ static inline int imx_bbu_external_nor_register_handler(const char *name, char *
}
#endif
-#if defined(CONFIG_BAREBOX_UPDATE_IMX6_NAND)
-int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
-#else
-static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
-{
- return -ENOSYS;
-}
-#endif
-
#if defined(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND)
int imx_bbu_external_nand_register_handler(const char *name, char *devicefile,
unsigned long flags);
diff --git a/arch/arm/mach-imx/include/mach/clock-imx51_53.h b/arch/arm/mach-imx/include/mach/clock-imx51_53.h
index 6004a6d36c..0f25dfbf2f 100644
--- a/arch/arm/mach-imx/include/mach/clock-imx51_53.h
+++ b/arch/arm/mach-imx/include/mach/clock-imx51_53.h
@@ -149,6 +149,7 @@
#define MX5_CCM_CACRR_ARM_PODF_MASK (0x7)
/* Define the bits in register CBCDR */
+#define MX5_CCM_CBCDR_RESET_VALUE (0x19239145)
#define MX5_CCM_CBCDR_EMI_CLK_SEL (0x1 << 26)
#define MX5_CCM_CBCDR_PERIPH_CLK_SEL (0x1 << 25)
#define MX5_CCM_CBCDR_DDR_HF_SEL_OFFSET (30)
@@ -193,6 +194,7 @@
#define MX5_CCM_CBCMR_PERCLK_IPG_CLK_SEL (0x1 << 0)
/* Define the bits in register CSCMR1 */
+#define MX5_CCM_CSCMR1_RESET_VALUE (0xa6a2a020)
#define MX5_CCM_CSCMR1_SSI_EXT2_CLK_SEL_OFFSET (30)
#define MX5_CCM_CSCMR1_SSI_EXT2_CLK_SEL_MASK (0x3 << 30)
#define MX5_CCM_CSCMR1_SSI_EXT1_CLK_SEL_OFFSET (28)
@@ -259,6 +261,7 @@
#define MX5_CCM_CSCMR2_SPDIF0_CLK_SEL_MASK (0x3)
/* Define the bits in register CSCDR1 */
+#define MX5_CCM_CSCDR1_RESET_VALUE (0x00c30318)
#define MX5_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_OFFSET (22)
#define MX5_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK (0x7 << 22)
#define MX5_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET (19)
@@ -585,5 +588,3 @@
#define MX5_SRPGC_EMI_PDNSCR (MX5_SRPGC_EMI_BASE + 0x8)
#endif /* __ARCH_ARM_MACH_MX51_CRM_REGS_H__ */
-
-
diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h
index f34eaa139f..ab939b3a88 100644
--- a/arch/arm/mach-imx/include/mach/debug_ll.h
+++ b/arch/arm/mach-imx/include/mach/debug_ll.h
@@ -3,6 +3,7 @@
#include <io.h>
#include <config.h>
+#include <common.h>
#include <mach/imx1-regs.h>
#include <mach/imx21-regs.h>
#include <mach/imx25-regs.h>
@@ -13,8 +14,40 @@
#include <mach/imx53-regs.h>
#include <mach/imx6-regs.h>
+#include <serial/imx-uart.h>
+
#ifdef CONFIG_DEBUG_LL
+#define __IMX_UART_BASE(soc, num) soc##_UART##num##_BASE_ADDR
+#define IMX_UART_BASE(soc, num) __IMX_UART_BASE(soc, num)
+
+static inline void imx_uart_setup_ll(void __iomem *uartbase,
+ unsigned int refclock)
+{
+ writel(0x00000000, uartbase + UCR1);
+
+ writel(UCR2_IRTS | UCR2_WS | UCR2_TXEN | UCR2_RXEN | UCR2_SRST,
+ uartbase + UCR2);
+ writel(UCR3_DSR | UCR3_DCD | UCR3_RI | UCR3_ADNIMP | UCR3_RXDMUXSEL,
+ uartbase + UCR3);
+ writel((0b10 << UFCR_TXTL_SHF) | UFCR_RFDIV1 | (1 << UFCR_RXTL_SHF),
+ uartbase + UFCR);
+
+ writel(baudrate_to_ubir(CONFIG_BAUDRATE),
+ uartbase + UBIR);
+ writel(refclock_to_ubmr(refclock),
+ uartbase + UBMR);
+
+ writel(UCR1_UARTEN, uartbase + UCR1);
+}
+
+#define __imx_uart_setup_ll(refclock) \
+ do { \
+ imx_uart_setup_ll(IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC, \
+ CONFIG_DEBUG_IMX_UART_PORT)), \
+ refclock); \
+ } while(0)
+
#ifdef CONFIG_DEBUG_IMX1_UART
#define IMX_DEBUG_SOC MX1
#elif defined CONFIG_DEBUG_IMX21_UART
@@ -37,21 +70,20 @@
#error "unknown i.MX debug uart soc type"
#endif
-#define __IMX_UART_BASE(soc, num) soc##_UART##num##_BASE_ADDR
-#define IMX_UART_BASE(soc, num) __IMX_UART_BASE(soc, num)
-
-#define URTX0 0x40 /* Transmitter Register */
-
-#define UCR1 0x80 /* Control Register 1 */
-#define UCR1_UARTEN (1 << 0) /* UART enabled */
+static inline void imx51_uart_setup_ll(void)
+{
+ __imx_uart_setup_ll(54000000);
+}
-#define USR2 0x98 /* Status Register 2 */
-#define USR2_TXDC (1 << 3) /* Transmitter complete */
+static inline void imx6_uart_setup_ll(void)
+{
+ __imx_uart_setup_ll(80000000);
+}
static inline void PUTC_LL(int c)
{
- void __iomem *base = (void *)IMX_UART_BASE(IMX_DEBUG_SOC,
- CONFIG_DEBUG_IMX_UART_PORT);
+ void __iomem *base = IOMEM(IMX_UART_BASE(IMX_DEBUG_SOC,
+ CONFIG_DEBUG_IMX_UART_PORT));
if (!base)
return;
@@ -63,5 +95,28 @@ static inline void PUTC_LL(int c)
writel(c, base + URTX0);
}
+#else
+
+static inline void imx_uart_setup_ll(void __iomem *uartbase,
+ unsigned int refclock)
+{
+}
+
+static inline void imx51_uart_setup_ll(void) {}
+static inline void imx6_uart_setup_ll(void) {}
+
#endif /* CONFIG_DEBUG_LL */
+
+static inline void imx_ungate_all_peripherals(void __iomem *ccmbase)
+{
+ int i;
+ for (i = 0x68; i <= 0x80; i += 4)
+ writel(0xffffffff, ccmbase + i);
+}
+
+static inline void imx6_ungate_all_peripherals(void)
+{
+ imx_ungate_all_peripherals(IOMEM(MX6_CCM_BASE_ADDR));
+}
+
#endif /* __MACH_DEBUG_LL_H__ */
diff --git a/arch/arm/mach-imx/xload.c b/arch/arm/mach-imx/xload.c
new file mode 100644
index 0000000000..16d56ab288
--- /dev/null
+++ b/arch/arm/mach-imx/xload.c
@@ -0,0 +1,52 @@
+#include <bootsource.h>
+#include <bootstrap.h>
+#include <common.h>
+#include <malloc.h>
+#include <init.h>
+#include <envfs.h>
+#include <linux/sizes.h>
+#include <fs.h>
+#include <io.h>
+
+#include <linux/clkdev.h>
+#include <linux/stat.h>
+#include <linux/clk.h>
+
+#include <mach/devices-imx51.h>
+
+static __noreturn int imx_xload(void)
+{
+ enum bootsource bootsource = bootsource_get();
+ void *buf;
+
+ switch (bootsource) {
+ case BOOTSOURCE_MMC:
+ pr_info("booting from MMC\n");
+ buf = bootstrap_read_disk("disk0.0", "fat");
+ break;
+ case BOOTSOURCE_SPI:
+ pr_info("booting from SPI\n");
+ buf = bootstrap_read_devfs("dataflash0", false,
+ SZ_256K, SZ_1M, SZ_1M);
+ break;
+ default:
+ pr_err("unknown bootsource %d\n", bootsource);
+ hang();
+ }
+
+ if (!buf) {
+ pr_err("failed to load barebox.bin\n");
+ hang();
+ }
+
+ bootstrap_boot(buf, 0);
+
+ hang();
+}
+
+static int imx_devices_init(void)
+{
+ barebox_main = imx_xload;
+ return 0;
+}
+coredevice_initcall(imx_devices_init);
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
index 2029b90acb..00758450cc 100644
--- a/arch/arm/mach-mxs/ocotp.c
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -43,6 +43,7 @@
#define OCOTP_WORD_OFFSET 0x20
struct ocotp_priv {
+ struct device_d dev;
struct cdev cdev;
void __iomem *base;
unsigned int write_enable;
@@ -194,13 +195,19 @@ static int mxs_ocotp_probe(struct device_d *dev)
priv->cdev.size = cpu_is_mx23() ? 128 : 160;
priv->cdev.name = DRIVERNAME;
+ strcpy(priv->dev.name, "ocotp");
+ priv->dev.parent = dev;
+ err = register_device(&priv->dev);
+ if (err)
+ return err;
+
err = devfs_create(&priv->cdev);
if (err < 0)
return err;
if (IS_ENABLED(CONFIG_MXS_OCOTP_WRITABLE)) {
mxs_ocotp_ops.write = mxs_ocotp_cdev_write;
- dev_add_param_bool(dev, "permanent_write_enable",
+ dev_add_param_bool(&priv->dev, "permanent_write_enable",
NULL, NULL, &priv->write_enable, NULL);
}
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index 444ddf8377..af359756ba 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -54,14 +54,6 @@ config OMAP_CLOCK_SOURCE_S32K
config OMAP_CLOCK_SOURCE_DMTIMER0
bool
-config OMAP3_CLOCK_CONFIG
- prompt "Clock Configuration"
- bool
- depends on ARCH_OMAP3
- default y
- help
- Say Y here if you like to have OMAP3 Clock configuration done.
-
config OMAP_GPMC
prompt "Support for GPMC configuration"
bool
@@ -110,6 +102,15 @@ config ARCH_TEXT_BASE
default 0x80e80000 if MACH_OMAP343xSDP
default 0x80e80000 if MACH_BEAGLE
+config AM33XX_NET_BOOT
+ bool "enable AM335x network boot"
+ select ENVIRONMENT_VARIABLES
+ select NET_DHCP
+ select FS_TFTP
+ select DRIVER_NET_CPSW
+ default n
+ depends on ARCH_AM33XX && NET
+
config OMAP4_USBBOOT
bool "enable booting from USB"
default n
@@ -119,6 +120,21 @@ config OMAP4_USBBOOT
You need the utility program omap4_usbboot to boot from USB.
Please read omap4_usb_booting.txt for more information.
+config OMAP3_USBBOOT
+ bool "enable booting from USB"
+ depends on ARCH_OMAP3
+ help
+ Say Y here if you want to be able to boot the 2nd stage via USB. This
+ works by transferring the 2nd stage image using the MUSB controller
+ which is already initialized by the ROM code. Use the omap3-usb-loader
+ tool selectable below to upload images.
+
+config OMAP3_USB_LOADER
+ bool "enable omap3 USB loader host tool"
+ depends on ARCH_OMAP3
+ help
+ Say Y here to build the omap3 usb loader tool.
+
config OMAP_SERIALBOOT
bool "enable booting from serial"
select XYMODEM
@@ -141,6 +157,13 @@ config MACH_AFI_GF
help
Say Y here if you are using afis GF
+config MACH_BEAGLE
+ bool "Texas Instrument's Beagle Board"
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select ARCH_OMAP3
+ help
+ Say Y here if you are using Beagle Board
+
config MACH_BEAGLEBONE
bool "Texas Instrument's Beagle Bone"
select ARCH_AM33XX
@@ -164,13 +187,6 @@ config MACH_OMAP343xSDP
help
Say Y here if you are using SDP343x platform
-config MACH_BEAGLE
- bool "Texas Instrument's Beagle Board"
- select HAVE_DEFAULT_ENVIRONMENT_NEW
- select ARCH_OMAP3
- help
- Say Y here if you are using Beagle Board
-
config MACH_OMAP3EVM
bool "Texas Instrument's OMAP3 EVM"
select ARCH_OMAP3
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index bef1d0500f..65072b91e4 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -25,12 +25,14 @@ obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
pbl-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
obj-pbl-$(CONFIG_ARCH_AM33XX) += am33xx_generic.o am33xx_clock.o am33xx_mux.o
obj-$(CONFIG_ARCH_AM33XX) += am33xx_scrm.o
-obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
-pbl-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
+obj-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
+pbl-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
obj-$(CONFIG_SHELL_NONE) += xload.o
obj-$(CONFIG_MFD_TWL6030) += omap4_twl6030_mmc.o
obj-$(CONFIG_OMAP4_USBBOOT) += omap4_rom_usb.o
+obj-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
+pbl-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
obj-$(CONFIG_CMD_BOOT_ORDER) += boot_order.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO) += am33xx_bbu_spi_mlo.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_NAND) += am33xx_bbu_nand.o
diff --git a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
index 97dc54ee10..702bb9af59 100644
--- a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
+++ b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
@@ -97,41 +97,6 @@ out:
return ret;
}
-static int spi_nor_handler(struct bbu_handler *handler,
- struct bbu_data *data)
-{
- int fd, ret;
-
- if (file_detect_type(data->image, data->len) != filetype_arm_barebox) {
- if (!bbu_force(data, "Not an ARM barebox image"))
- return -EINVAL;
- }
-
- fd = open(data->devicefile, O_RDWR | O_CREAT);
- if (fd < 0)
- return fd;
-
- debug("%s: eraseing %s from 0 to 0x%08x\n", __func__,
- data->devicefile, data->len);
- ret = erase(fd, data->len, 0);
- if (ret) {
- printf("erasing %s failed with %s\n", data->devicefile,
- strerror(-ret));
- goto err_close;
- }
-
- ret = write(fd, data->image, data->len);
- if (ret < 0)
- goto err_close;
-
- ret = 0;
-
-err_close:
- close(fd);
-
- return ret;
-}
-
/*
* Register a am33xx MLO update handler for SPI NOR
*/
@@ -152,24 +117,3 @@ int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile)
return ret;
}
-
-/*
- * Register a am33xx update handler for SPI NOR
- */
-int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile)
-{
- struct bbu_handler *handler;
- int ret;
-
- handler = xzalloc(sizeof(*handler));
- handler->devicefile = devicefile;
- handler->name = name;
- handler->handler = spi_nor_handler;
-
- ret = bbu_register_handler(handler);
-
- if (ret)
- free(handler);
-
- return ret;
-}
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index ee30351fa4..7ce32f01e1 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -145,6 +145,9 @@ static int am33xx_bootsource(void)
case 0x44:
src = BOOTSOURCE_USB;
break;
+ case 0x46:
+ src = BOOTSOURCE_NET;
+ break;
default:
src = BOOTSOURCE_UNKNOWN;
}
diff --git a/arch/arm/mach-omap/include/mach/bbu.h b/arch/arm/mach-omap/include/mach/bbu.h
index 36d87e1a00..da5c214d3a 100644
--- a/arch/arm/mach-omap/include/mach/bbu.h
+++ b/arch/arm/mach-omap/include/mach/bbu.h
@@ -5,18 +5,17 @@
#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO
int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile);
-int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile);
#else
static inline int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile)
{
return 0;
}
+#endif
static inline int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile)
{
- return 0;
+ return bbu_register_std_file_update(name, 0, devicefile, filetype_arm_barebox);
}
-#endif
#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_NAND
int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
diff --git a/arch/arm/mach-omap/include/mach/omap3-clock.h b/arch/arm/mach-omap/include/mach/omap3-clock.h
index 1ef46aa3e5..7c52da754f 100644
--- a/arch/arm/mach-omap/include/mach/omap3-clock.h
+++ b/arch/arm/mach-omap/include/mach/omap3-clock.h
@@ -107,7 +107,7 @@
/* PER DPLL */
#define PER_M6X2 3 /* 288MHz: CM_CLKSEL1_EMU */
#define PER_M5X2 4 /* 216MHz: CM_CLKSEL_CAM */
-#define PER_M4X2 9 /* 96MHz : CM_CLKSEL_DSS-dss1 */
+#define PER_M4X2 2 /* 432MHz: CM_CLKSEL_DSS-dss1 */
#define PER_M3X2 16 /* 54MHz : CM_CLKSEL_DSS-tv */
#define CLSEL1_EMU_VAL ((CORE_M3X2 << 16) | (PER_M6X2 << 24) | (0x0a50))
diff --git a/arch/arm/mach-omap/include/mach/omap3-generic.h b/arch/arm/mach-omap/include/mach/omap3-generic.h
index 7db0838a5f..ab53b98971 100644
--- a/arch/arm/mach-omap/include/mach/omap3-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap3-generic.h
@@ -29,4 +29,6 @@ void __noreturn omap3_reset_cpu(unsigned long addr);
int omap3_init(void);
int omap3_devices_init(void);
+void *omap3_xload_boot_usb(void);
+
#endif /* __MACH_OMAP3_GENERIC_H */
diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c
index dbb0b5f86c..0f2e9ce6b7 100644
--- a/arch/arm/mach-omap/omap3_generic.c
+++ b/arch/arm/mach-omap/omap3_generic.c
@@ -435,9 +435,6 @@ static void try_unlock_memory(void)
* Does early system init of disabling the watchdog, enable
* memory and configuring the clocks.
*
- * prcm_init is called only if CONFIG_OMAP3_CLOCK_CONFIG is defined.
- * We depend on link time clean up to remove a_init if no caller exists.
- *
* @warning Called path is with SRAM stack
*
* @return void
@@ -459,9 +456,7 @@ void omap3_core_init(void)
sdelay(100);
-#ifdef CONFIG_OMAP3_CLOCK_CONFIG
prcm_init();
-#endif
}
#define OMAP3_TRACING_VECTOR1 0x4020ffb4
diff --git a/arch/arm/mach-omap/omap3_xload_usb.c b/arch/arm/mach-omap/omap3_xload_usb.c
new file mode 100644
index 0000000000..e7dc21e4a7
--- /dev/null
+++ b/arch/arm/mach-omap/omap3_xload_usb.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * Based on a patch by:
+ *
+ * Copyright (C) 2011 Rick Bronson
+ *
+ * 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 <io.h>
+#include <malloc.h>
+#include <mach/omap3-silicon.h>
+#include <mach/omap3-generic.h>
+
+static void __iomem *omap3_usb_base = (void __iomem *)OMAP3_MUSB0_BASE;
+
+#define OMAP34XX_USB_EP(n) (omap3_usb_base + 0x100 + 0x10 * (n))
+
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_TXCSR 0x02
+#define MUSB_FIFOSIZE 0x0F
+#define OMAP34XX_USB_RXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_RXCSR)
+#define OMAP34XX_USB_RXCOUNT(n) (OMAP34XX_USB_EP(n) + MUSB_RXCOUNT)
+#define OMAP34XX_USB_TXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_TXCSR)
+#define OMAP34XX_USB_FIFOSIZE(n) (OMAP34XX_USB_EP(n) + MUSB_FIFOSIZE)
+#define OMAP34XX_USB_FIFO(n) (omap3_usb_base + 0x20 + ((n) * 4))
+
+/* memory mapped registers */
+#define BULK_ENDPOINT 1
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+
+#define PACK4(a,b,c,d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U', 'S', 'B', 's') /* send file size */
+#define USBLOAD_CMD_JUMP PACK4('U', 'S', 'B', 'j') /* go where I tell you */
+#define USBLOAD_CMD_FILE_REQ PACK4('U', 'S', 'B', 'f') /* file request */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U', 'S', 'B', 'n') /* echo file size */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U', 'S', 'B', 'o') /* report file size */
+#define USBLOAD_CMD_MESSAGE PACK4('U', 'S', 'B', 'm') /* message for debug */
+
+static int usb_send(unsigned char *buffer, unsigned int buffer_size)
+{
+ unsigned int cntr;
+ u16 txcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_TXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ txcsr = readw(reg);
+
+ if (txcsr & MUSB_TXCSR_TXPKTRDY)
+ return 0;
+
+ for (cntr = 0; cntr < buffer_size; cntr++)
+ writeb(buffer[cntr], bulk_fifo);
+
+ txcsr = readw(reg);
+ txcsr |= MUSB_TXCSR_TXPKTRDY;
+ writew(txcsr, reg);
+
+ return buffer_size;
+}
+
+static int usb_recv(u8 *buffer)
+{
+ int cntr;
+ u16 count = 0;
+ u16 rxcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_RXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ rxcsr = readw(reg);
+
+ if (!(rxcsr & MUSB_RXCSR_RXPKTRDY))
+ return 0;
+
+ count = readw((void *)OMAP34XX_USB_RXCOUNT(BULK_ENDPOINT));
+ for (cntr = 0; cntr < count; cntr++)
+ *buffer++ = readb(bulk_fifo);
+
+ /* Clear the RXPKTRDY bit */
+ rxcsr = readw(reg);
+ rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
+ writew(rxcsr, reg);
+
+ return count;
+}
+
+static unsigned char usb_outbuffer[64];
+
+static void usb_msg(unsigned int cmd, const char *msg)
+{
+ unsigned char *p_char = usb_outbuffer;
+
+ *(int *)p_char = cmd;
+
+ p_char += sizeof(cmd);
+
+ if (msg) {
+ while (*msg)
+ *p_char++= *msg++;
+ *p_char++= 0;
+ }
+
+ usb_send(usb_outbuffer, p_char - usb_outbuffer);
+}
+
+static void usb_code(unsigned int cmd, u32 code)
+{
+ unsigned int *p_int = (unsigned int *)usb_outbuffer;
+
+ *p_int++ = cmd;
+ *p_int++ = code;
+ usb_send (usb_outbuffer, ((unsigned char *) p_int) - usb_outbuffer);
+}
+
+void *omap3_xload_boot_usb(void)
+{
+ int res;
+ void *buf;
+ u32 *buf32;
+ u32 total;
+ void *addr;
+ u32 bytes;
+ int size;
+ int cntr;
+ void *fn;
+ u8 __buf[512];
+
+ buf32 = buf = __buf;
+
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req");
+ for (cntr = 0; cntr < 10000000; cntr++) {
+ size = usb_recv(buf);
+ if (!size)
+ continue;
+
+ switch (buf32[0]) {
+ case USBLOAD_CMD_FILE:
+ pr_debug ("USBLOAD_CMD_FILE total = %d size = 0x%x addr = 0x%x\n",
+ res, buf32[1], buf32[2]);
+ total = buf32[1]; /* get size and address */
+ addr = (void *)buf32[2];
+ usb_code(USBLOAD_CMD_ECHO_SZ, total);
+
+ bytes = 0;
+
+ while (bytes < total) {
+ size = usb_recv(buf);
+ memcpy(addr, buf, size);
+ addr += size;
+ bytes += size;
+ }
+
+ usb_code(USBLOAD_CMD_REPORT_SZ, total); /* tell him we got this many bytes */
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req"); /* see if they have another file for us */
+ break;
+ case USBLOAD_CMD_JUMP:
+ pr_debug("USBLOAD_CMD_JUMP total = %d addr = 0x%x val = 0x%x\n",
+ res, buf32[0], buf32[1]);
+ fn = (void *)buf32[1];
+ goto out;
+ default:
+ break;
+ }
+ }
+
+ fn = NULL;
+out:
+
+ return fn;
+}
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index 7c8c350114..4a0714ed93 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -13,6 +13,11 @@
#include <filetype.h>
#include <xymodem.h>
#include <mach/generic.h>
+#include <mach/am33xx-generic.h>
+#include <mach/omap3-generic.h>
+#include <net.h>
+#include <environment.h>
+#include <dhcp.h>
struct omap_barebox_part *barebox_part;
@@ -224,6 +229,45 @@ static void *omap_serial_boot(void){
return buf;
}
+static void *am33xx_net_boot(void)
+{
+ void *buf = NULL;
+ int err;
+ int len;
+ struct dhcp_req_param dhcp_param;
+ const char *bootfile;
+
+ am33xx_register_ethaddr(0, 0);
+
+ memset(&dhcp_param, 0, sizeof(struct dhcp_req_param));
+ dhcp_param.vendor_id = "am335x barebox-mlo";
+ err = dhcp(20, &dhcp_param);
+ if (err) {
+ printf("dhcp failed\n");
+ return NULL;
+ }
+
+ err = mount(ip_to_string(net_get_serverip()), "tftp", "/", NULL);
+ if (err < 0) {
+ printf("Unable to mount.\n");
+ return NULL;
+ }
+
+ bootfile = getenv("bootfile");
+ if (!bootfile) {
+ printf("bootfile not found.\n");
+ return NULL;
+ }
+
+ buf = read_file(bootfile, &len);
+ if (!buf)
+ printf("could not read %s.\n", bootfile);
+
+ umount("/");
+
+ return buf;
+}
+
/*
* Replaces the default shell in xload configuration
*/
@@ -241,13 +285,16 @@ static __noreturn int omap_xload(void)
func = omap_xload_boot_mmc();
break;
case BOOTSOURCE_USB:
- if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
+ if (IS_ENABLED(CONFIG_OMAP3_USBBOOT) && cpu_is_omap3()) {
+ printf("booting from USB\n");
+ func = omap3_xload_boot_usb();
+ } else if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
printf("booting from USB\n");
func = omap4_xload_boot_usb();
- break;
} else {
printf("booting from USB not enabled\n");
}
+ break;
case BOOTSOURCE_NAND:
printf("booting from NAND\n");
func = omap_xload_boot_nand(barebox_part->nand_offset,
@@ -264,6 +311,14 @@ static __noreturn int omap_xload(void)
func = omap_serial_boot();
break;
}
+ case BOOTSOURCE_NET:
+ if (IS_ENABLED(CONFIG_AM33XX_NET_BOOT)) {
+ printf("booting from NET\n");
+ func = am33xx_net_boot();
+ break;
+ } else {
+ printf("booting from network not enabled\n");
+ }
default:
printf("unknown boot source. Fall back to nand\n");
func = omap_xload_boot_nand(barebox_part->nand_offset,
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 610fb1c80e..2b7f631757 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,7 @@ config ARCH_TEXT_BASE
hex
default 0xa0000000 if MACH_MIOA701
default 0xa3f00000 if MACH_PCM027
+ default 0xa3d00000 if MACH_LUBBOCK
default 0x83f00000 if MACH_ZYLONITE
# ----------------------------------------------------------
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 90b3533b1f..73b26efd20 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -1,5 +1,9 @@
if ARCH_SOCFPGA
+config ARCH_TEXT_BASE
+ hex
+ default 0x0
+
config ARCH_SOCFPGA_XLOAD
bool
prompt "Build preloader image"
diff --git a/arch/arm/mach-socfpga/include/mach/generic.h b/arch/arm/mach-socfpga/include/mach/generic.h
index 2f5cda0d02..1f4247f803 100644
--- a/arch/arm/mach-socfpga/include/mach/generic.h
+++ b/arch/arm/mach-socfpga/include/mach/generic.h
@@ -15,4 +15,9 @@ static inline void __udelay(unsigned us)
for (i = 0; i < us * 3; i++);
}
+struct socfpga_barebox_part {
+ unsigned int nor_offset;
+ unsigned int nor_size;
+};
+
#endif /* __MACH_SOCFPGA_GENERIC_H */
diff --git a/arch/arm/mach-socfpga/include/mach/sequencer.c b/arch/arm/mach-socfpga/include/mach/sequencer.c
index 90efcc826b..c299f754a8 100644
--- a/arch/arm/mach-socfpga/include/mach/sequencer.c
+++ b/arch/arm/mach-socfpga/include/mach/sequencer.c
@@ -48,11 +48,14 @@
******************************************************************************
******************************************************************************/
+#ifndef ARMCOMPILER
+
// Temporary workaround to place the initial stack pointer at a safe offset from end
#define STRINGIFY(s) STRINGIFY_STR(s)
#define STRINGIFY_STR(s) #s
asm(".global __alt_stack_pointer");
asm("__alt_stack_pointer = " STRINGIFY(STACK_POINTER));
+#endif
#include <mach/sdram.h>
@@ -222,18 +225,13 @@ static int check_test_mem(int start)
static void set_failing_group_stage(uint32_t group, uint32_t stage, uint32_t substage)
{
- ALTERA_ASSERT(group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
- // Only set the global stage if there was not been any other failing group
if (gbl->error_stage == CAL_STAGE_NIL) {
gbl->error_substage = substage;
gbl->error_stage = stage;
gbl->error_group = group;
- TCLRPT_SET(debug_summary_report->error_sub_stage, substage);
- TCLRPT_SET(debug_summary_report->error_stage, stage);
- TCLRPT_SET(debug_summary_report->error_group, group);
}
+
}
static inline void reg_file_set_group(uint32_t set_group)
@@ -292,13 +290,6 @@ static inline void select_curr_shadow_reg_using_rank(uint32_t rank)
static void initialize(void)
{
- TRACE_FUNC();
-
- //USER calibration has control over path to memory
-
- // In Hard PHY this is a 2-bit control:
- // 0: AFI Mux Select
- // 1: DDIO Mux Select
IOWR_32DIRECT(PHY_MGR_MUX_SEL, 0, 0x3);
//USER memory clock is not stable we begin initialization
@@ -480,27 +471,18 @@ static void scc_mgr_initialize(void)
static inline void scc_mgr_set_dqs_bus_in_delay(uint32_t read_group, uint32_t delay)
{
- ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_IN_DELAY(read_group, delay);
}
static inline void scc_mgr_set_dqs_io_in_delay(uint32_t write_group, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_IO_IN_DELAY(delay);
}
static inline void scc_mgr_set_dqs_en_phase(uint32_t read_group, uint32_t phase)
{
- ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_EN_PHASE(read_group, phase);
}
@@ -529,9 +511,6 @@ static void scc_mgr_set_dqs_en_phase_all_ranks(uint32_t read_group, uint32_t pha
static inline void scc_mgr_set_dqdqs_output_phase(uint32_t write_group, uint32_t phase)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQDQS_OUT_PHASE(write_group, phase);
}
@@ -560,9 +539,6 @@ static void scc_mgr_set_dqdqs_output_phase_all_ranks(uint32_t write_group, uint3
static inline void scc_mgr_set_dqs_en_delay(uint32_t read_group, uint32_t delay)
{
- ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_EN_DELAY(read_group, delay);
}
@@ -592,8 +568,6 @@ static void scc_mgr_set_oct_out1_delay(uint32_t write_group, uint32_t delay)
{
uint32_t read_group;
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
// Load the setting in the SCC manager
// Although OCT affects only write data, the OCT delay is controlled by the DQS logic block
// which is instantiated once per read group. For protocols where a write group consists
@@ -613,8 +587,6 @@ static void scc_mgr_set_oct_out2_delay(uint32_t write_group, uint32_t delay)
{
uint32_t read_group;
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
// Load the setting in the SCC manager
// Although OCT affects only write data, the OCT delay is controlled by the DQS logic block
// which is instantiated once per read group. For protocols where a write group consists
@@ -640,9 +612,6 @@ static inline void scc_mgr_set_dq_out1_delay(uint32_t write_group, uint32_t dq_i
uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
-
// Load the setting in the SCC manager
WRITE_SCC_DQ_OUT1_DELAY(dq_in_group, delay);
@@ -652,9 +621,6 @@ static inline void scc_mgr_set_dq_out2_delay(uint32_t write_group, uint32_t dq_i
uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
-
// Load the setting in the SCC manager
WRITE_SCC_DQ_OUT2_DELAY(dq_in_group, delay);
@@ -664,9 +630,6 @@ static inline void scc_mgr_set_dq_in_delay(uint32_t write_group, uint32_t dq_in_
uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dq < RW_MGR_MEM_DATA_WIDTH);
-
// Load the setting in the SCC manager
WRITE_SCC_DQ_IN_DELAY(dq_in_group, delay);
@@ -706,50 +669,29 @@ static inline void scc_mgr_set_hhp_dqse_map(void)
static inline void scc_mgr_set_dqs_out1_delay(uint32_t write_group, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_IO_OUT1_DELAY(delay);
}
static inline void scc_mgr_set_dqs_out2_delay(uint32_t write_group, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
- // Load the setting in the SCC manager
WRITE_SCC_DQS_IO_OUT2_DELAY(delay);
}
static inline void scc_mgr_set_dm_out1_delay(uint32_t write_group, uint32_t dm, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
-
- // Load the setting in the SCC manager
WRITE_SCC_DM_IO_OUT1_DELAY(dm, delay);
-
}
static inline void scc_mgr_set_dm_out2_delay(uint32_t write_group, uint32_t dm, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
-
- // Load the setting in the SCC manager
WRITE_SCC_DM_IO_OUT2_DELAY(dm, delay);
-
}
static inline void scc_mgr_set_dm_in_delay(uint32_t write_group, uint32_t dm, uint32_t delay)
{
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
- ALTERA_ASSERT(dm < RW_MGR_NUM_DM_PER_WRITE_GROUP);
-
- // Load the setting in the SCC manager
WRITE_SCC_DM_IO_IN_DELAY(dm, delay);
-
}
static inline void scc_mgr_set_dm_bypass(uint32_t write_group, uint32_t dm, uint32_t bypass)
@@ -1144,8 +1086,6 @@ static inline void delay_for_n_mem_clocks(const uint32_t clocks)
uint8_t outer;
uint16_t c_loop;
- TRACE_FUNC("clocks=%lu ... start", clocks);
-
afi_clocks = (clocks + AFI_RATE_RATIO - 1) / AFI_RATE_RATIO; /* scale (rounding up) to get afi clocks */
// Note, we don't bother accounting for being off a little bit because of a few extra instructions in outer loops
@@ -1204,14 +1144,11 @@ static inline void delay_for_n_mem_clocks(const uint32_t clocks)
} while (c_loop-- != 0);
}
}
-
- TRACE_FUNC("clocks=%lu ... end", clocks);
}
// should always use constants as argument to ensure all computations are performed at compile time
static inline void delay_for_n_ns(const uint32_t nanoseconds)
{
- TRACE_FUNC("nanoseconds=%lu ... end", nanoseconds);
delay_for_n_mem_clocks((1000 * nanoseconds) / (1000000 / AFI_CLK_FREQ) * AFI_RATE_RATIO);
}
@@ -1230,8 +1167,6 @@ static void rw_mgr_mem_initialize(void)
{
uint32_t r;
- TRACE_FUNC();
-
//USER The reset / cke part of initialization is broadcasted to all ranks
IOWR_32DIRECT(RW_MGR_SET_CS_AND_ODT_MASK, 0, RW_MGR_RANK_ALL);
@@ -1295,6 +1230,7 @@ static void rw_mgr_mem_initialize(void)
continue;
}
+
//USER set rank
set_rank_and_odt_mask(r, RW_MGR_ODT_MODE_OFF);
@@ -1343,8 +1279,6 @@ static void rw_mgr_mem_handoff(void)
{
uint32_t r;
- TRACE_FUNC();
-
for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r++) {
if (param->skip_ranks[r]) {
//USER request to skip the rank
@@ -1484,8 +1418,6 @@ static void rw_mgr_mem_calibrate_read_load_patterns(uint32_t rank_bgn, uint32_t
uint32_t rank_end =
all_ranks ? RW_MGR_MEM_NUMBER_OF_RANKS : (rank_bgn + NUM_RANKS_PER_SHADOW_REG);
- TRACE_FUNC();
-
for (r = rank_bgn; r < rank_end; r++) {
if (param->skip_ranks[r]) {
//USER request to skip the rank
@@ -1794,7 +1726,7 @@ static void rw_mgr_decr_vfifo(uint32_t grp, uint32_t * v)
static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
{
- uint32_t i, d, v, p, sr;
+ uint32_t i, d, v, p;
uint32_t max_working_cnt;
uint32_t fail_cnt;
t_btfld bit_chk;
@@ -1804,10 +1736,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
uint32_t test_status;
uint32_t found_passing_read, found_failing_read, initial_failing_dtap;
- TRACE_FUNC("%lu", grp);
- BFM_STAGE("find_dqs_en_phase");
- ALTERA_ASSERT(grp < RW_MGR_MEM_IF_READ_DQS_WIDTH);
-
reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
@@ -1825,9 +1753,7 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP;
}
dtaps_per_ptap--;
- ALTERA_ASSERT(dtaps_per_ptap <= IO_DQS_EN_DELAY_MAX);
tmp_delay = 0;
- TCLRPT_SET(debug_summary_report->computed_dtap_per_ptap, dtaps_per_ptap);
// VFIFO sweep
@@ -1938,35 +1864,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
}
}
- // Record the debug data
- // Currently dqsen is the same for all ranks
- for (sr = 0; sr < NUM_SHADOW_REGS; sr++) {
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].work_begin,
- work_bgn);
- if (found_begin) {
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin,
- p);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin,
- d);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin,
- v % VFIFO_SIZE);
- } else if (p == IO_DQS_EN_PHASE_MAX) {
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin,
- 0);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin,
- 0);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin,
- (v + 1) % VFIFO_SIZE);
- } else {
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_begin,
- p + 1);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_begin,
- 0);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_begin,
- v % VFIFO_SIZE);
- }
- }
-
//USER We have found a working dtap before the ptap found above
if (found_begin == 1) {
max_working_cnt++;
@@ -2086,14 +1983,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
BFM_GBL_SET(dqs_enable_right_edge[grp].d, d - 1);
BFM_GBL_SET(dqs_enable_right_edge[grp].ps, work_end);
- // Record the debug data
- for (sr = 0; sr < NUM_SHADOW_REGS; sr++) {
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].work_end, work_end);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].phase_end, p);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].delay_end, d - 1);
- TCLRPT_SET(debug_cal_report->cal_dqsen_margins[sr][grp].vfifo_end, v % VFIFO_SIZE);
- }
-
if (work_end >= work_bgn) {
//USER we have a working range
} else {
@@ -2168,7 +2057,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
dtaps_per_ptap = d - initial_failing_dtap;
}
- ALTERA_ASSERT(dtaps_per_ptap <= IO_DQS_EN_DELAY_MAX);
IOWR_32DIRECT(REG_FILE_DTAPS_PER_PTAP, 0, dtaps_per_ptap);
DPRINT(2, "find_dqs_en_phase: dtaps_per_ptap=%lu - %lu = %lu", d, initial_failing_dtap,
@@ -2196,12 +2084,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
d++, tmp_delay += IO_DELAY_PER_DQS_EN_DCHAIN_TAP) ;
DPRINT(2, "new d %ld, tmp_delay=%ld", d, tmp_delay);
- // DQSEN same for all shadow reg
- for (sr = 0; sr < NUM_SHADOW_REGS; sr++) {
- TCLRPT_SET(debug_cal_report->cal_dqs_in_margins[sr][grp].dqsen_margin,
- max_working_cnt - 1);
- }
-
scc_mgr_set_dqs_en_phase_all_ranks(grp, p - 1);
scc_mgr_set_dqs_en_delay_all_ranks(grp, d);
@@ -2543,8 +2425,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase(uint32_t grp)
t_btfld bit_chk;
uint32_t delay_per_ptap_mid;
- TRACE_FUNC("%lu", grp);
-
reg_file_set_sub_stage(CAL_SUBSTAGE_VFIFO_CENTER);
scc_mgr_set_dqs_en_delay_all_ranks(grp, 0);
@@ -2667,9 +2547,7 @@ static inline uint32_t rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_
uint32_t d;
uint32_t r;
- const uint32_t delay_step = IO_IO_IN_DELAY_MAX / (RW_MGR_MEM_DQ_PER_READ_DQS - 1); /* we start at zero, so have one less dq to devide among */
-
- TRACE_FUNC("(%lu,%lu,%lu)", write_group, read_group, test_bgn);
+ const uint32_t delay_step = IO_IO_IN_DELAY_MAX / (RW_MGR_MEM_DQ_PER_READ_DQS - 1);
// try different dq_in_delays since the dq path is shorter than dqs
@@ -2725,11 +2603,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_center(uint32_t rank_bgn, uint32_t wr
int32_t dq_margin, dqs_margin;
uint32_t stop;
- TRACE_FUNC("%lu %lu", read_group, test_bgn);
-
- ALTERA_ASSERT(read_group < RW_MGR_MEM_IF_READ_DQS_WIDTH);
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
start_dqs = READ_SCC_DQS_IN_DELAY(read_group);
if (IO_SHIFT_DQS_EN_WHEN_SHIFT_DQS) {
start_dqs_en = READ_SCC_DQS_EN_DELAY(read_group);
@@ -3041,8 +2914,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_center(uint32_t rank_bgn, uint32_t gr
uint32_t dq_margin, dqs_margin;
uint32_t start_dqs;
- TRACE_FUNC("%lu %lu", grp, test_bgn);
-
//USER per-bit deskew.
//USER start of the per-bit sweep with the minimum working delay setting for
//USER all bits.
@@ -3177,8 +3048,7 @@ static uint32_t rw_mgr_mem_calibrate_vfifo(uint32_t read_group, uint32_t test_bg
uint32_t grp_calibrated;
uint32_t write_group, write_test_bgn;
uint32_t failed_substage;
-
- TRACE_FUNC("%lu %lu", read_group, test_bgn);
+ uint32_t dqs_in_dtaps, orig_start_dqs;
//USER update info for sims
@@ -3253,33 +3123,65 @@ static uint32_t rw_mgr_mem_calibrate_vfifo(uint32_t read_group, uint32_t test_bg
break;
}
}
-// case:56390
- grp_calibrated = 1;
- if (rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay
- (write_group, read_group, test_bgn)) {
- // USER Read per-bit deskew can be done on a per shadow register basis
+ // Loop over different DQS in delay chains for the purpose of DQS Enable calibration finding one bit working
+ orig_start_dqs = READ_SCC_DQS_IN_DELAY(read_group);
+ for (dqs_in_dtaps = orig_start_dqs;
+ dqs_in_dtaps <= IO_DQS_IN_DELAY_MAX && grp_calibrated == 0;
+ dqs_in_dtaps++) {
+
for (rank_bgn = 0, sr = 0; rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS;
rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
- //USER Determine if this set of ranks should be skipped entirely
+
if (!param->skip_shadow_regs[sr]) {
//USER Select shadow register set
select_shadow_regs_for_update(rank_bgn, read_group,
1);
- // If doing read after write calibration, do not update FOM now - do it then
- if (!rw_mgr_mem_calibrate_vfifo_center
- (rank_bgn, write_group, read_group, test_bgn, 1,
- 0)) {
- grp_calibrated = 0;
- failed_substage = CAL_SUBSTAGE_VFIFO_CENTER;
+ WRITE_SCC_DQS_IN_DELAY(read_group, dqs_in_dtaps);
+ scc_mgr_load_dqs(read_group);
+ IOWR_32DIRECT(SCC_MGR_UPD, 0, 0);
+ }
+ }
+
+// case:56390
+ grp_calibrated = 1;
+ if (rw_mgr_mem_calibrate_vfifo_find_dqs_en_phase_sweep_dq_in_delay
+ (write_group, read_group, test_bgn)) {
+ // USER Read per-bit deskew can be done on a per shadow register basis
+ for (rank_bgn = 0, sr = 0;
+ rank_bgn < RW_MGR_MEM_NUMBER_OF_RANKS;
+ rank_bgn += NUM_RANKS_PER_SHADOW_REG, ++sr) {
+ //USER Determine if this set of ranks should be skipped entirely
+ if (!param->skip_shadow_regs[sr]) {
+
+ //USER Select shadow register set
+ select_shadow_regs_for_update(rank_bgn,
+ read_group,
+ 1);
+
+ // Before doing read deskew, set DQS in back to the reserve value
+ WRITE_SCC_DQS_IN_DELAY(read_group,
+ orig_start_dqs);
+ scc_mgr_load_dqs(read_group);
+ IOWR_32DIRECT(SCC_MGR_UPD, 0, 0);
+
+ // If doing read after write calibration, do not update FOM now - do it then
+ if (!rw_mgr_mem_calibrate_vfifo_center
+ (rank_bgn, write_group, read_group,
+ test_bgn, 1, 0)) {
+ grp_calibrated = 0;
+ failed_substage =
+ CAL_SUBSTAGE_VFIFO_CENTER;
+ }
}
}
+ } else {
+ grp_calibrated = 0;
+ failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
}
- } else {
- grp_calibrated = 0;
- failed_substage = CAL_SUBSTAGE_DQS_EN_PHASE;
}
+
}
}
@@ -3307,8 +3209,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo(uint32_t g, uint32_t test_bgn)
uint32_t grp_calibrated;
uint32_t failed_substage;
- TRACE_FUNC("%lu %lu", g, test_bgn);
-
//USER update info for sims
reg_file_set_stage(CAL_STAGE_VFIFO);
@@ -3380,8 +3280,6 @@ static uint32_t rw_mgr_mem_calibrate_vfifo_end(uint32_t read_group, uint32_t tes
uint32_t grp_calibrated;
uint32_t write_group;
- TRACE_FUNC("%lu %lu", read_group, test_bgn);
-
//USER update info for sims
reg_file_set_stage(CAL_STAGE_VFIFO_AFTER_WRITES);
@@ -3432,9 +3330,6 @@ static uint32_t rw_mgr_mem_calibrate_lfifo(void)
uint32_t found_one;
t_btfld bit_chk;
- TRACE_FUNC();
- BFM_STAGE("lfifo");
-
//USER update info for sims
reg_file_set_stage(CAL_STAGE_LFIFO);
@@ -3588,6 +3483,7 @@ static void rw_mgr_mem_calibrate_write_test_issue(uint32_t group, uint32_t test_
}
IOWR_32DIRECT(RW_MGR_RUN_SINGLE_GROUP, (group << 2), mcc_instruction);
+
}
//USER Test writes, can check for a single bit pass or multiple bit pass
@@ -3673,7 +3569,7 @@ static inline uint32_t rw_mgr_mem_calibrate_write_test_all_ranks(uint32_t write_
//USER Write Levelling -- Full Calibration
static uint32_t rw_mgr_mem_calibrate_wlevel(uint32_t g, uint32_t test_bgn)
{
- uint32_t p, d, sr;
+ uint32_t p, d;
uint32_t num_additional_fr_cycles = 0;
@@ -3683,9 +3579,6 @@ static uint32_t rw_mgr_mem_calibrate_wlevel(uint32_t g, uint32_t test_bgn)
uint32_t found_begin;
uint32_t dtaps_per_ptap;
- TRACE_FUNC("%lu %lu", g, test_bgn);
- BFM_STAGE("wlevel");
-
//USER update info for sims
reg_file_set_stage(CAL_STAGE_WLEVEL);
@@ -3864,11 +3757,6 @@ static uint32_t rw_mgr_mem_calibrate_wlevel(uint32_t g, uint32_t test_bgn)
BFM_GBL_SET(dqs_wlevel_right_edge[g].d, d - 1);
BFM_GBL_SET(dqs_wlevel_right_edge[g].ps, work_end);
- for (sr = 0; sr < NUM_SHADOW_REGS; sr++) {
- TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[sr][g].dqdqs_start, work_bgn);
- TCLRPT_SET(debug_cal_report->cal_dqs_out_margins[sr][g].dqdqs_end, work_end);
- }
-
//USER center
work_mid = (work_bgn + work_end) / 2;
@@ -3926,8 +3814,6 @@ static uint32_t rw_mgr_mem_calibrate_wlevel(uint32_t g, uint32_t test_bgn)
uint32_t work_bgn, work_end, work_mid;
uint32_t tmp_delay;
- TRACE_FUNC("%lu %lu", g, test_bgn);
-
//USER update info for sims
reg_file_set_stage(CAL_STAGE_WLEVEL);
@@ -4071,11 +3957,6 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn, uint32_t w
int32_t end_best = IO_IO_OUT1_DELAY_MAX + 1;
int32_t win_best = 0;
- TRACE_FUNC("%lu %lu", write_group, test_bgn);
- BFM_STAGE("writes_center");
-
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
dm_margin = 0;
start_dqs = READ_SCC_DQS_IO_OUT1_DELAY();
@@ -4302,20 +4183,13 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn, uint32_t w
IOWR_32DIRECT(SCC_MGR_UPD, 0, 0);
}
- //////////////////////
- //////////////////////
- //USER Centre DM
- //////////////////////
- //////////////////////
-
- BFM_STAGE("dm_center");
-
DPRINT(2, "write_center: DM");
//USER set the left and right edge of each bit to an illegal value
//USER use (IO_IO_OUT1_DELAY_MAX + 1) as an illegal value
left_edge[0] = IO_IO_OUT1_DELAY_MAX + 1;
right_edge[0] = IO_IO_OUT1_DELAY_MAX + 1;
+
//USER Search for the/part of the window with DM shift
for (d = IO_IO_OUT1_DELAY_MAX; d >= 0; d -= DELTA_D) {
scc_mgr_apply_group_dm_out1_delay(write_group, d);
@@ -4447,10 +4321,6 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn, uint32_t w
uint32_t start_dqs;
uint32_t stop;
- TRACE_FUNC("%lu %lu", write_group, test_bgn);
-
- ALTERA_ASSERT(write_group < RW_MGR_MEM_IF_WRITE_DQS_WIDTH);
-
//USER per-bit deskew
for (i = 0; i < RW_MGR_MEM_DQ_PER_WRITE_DQS; i++) {
@@ -4622,9 +4492,6 @@ static uint32_t rw_mgr_mem_calibrate_writes_center(uint32_t rank_bgn, uint32_t w
static uint32_t rw_mgr_mem_calibrate_writes(uint32_t rank_bgn, uint32_t g, uint32_t test_bgn)
{
- //USER update info for sims
-
- TRACE_FUNC("%lu %lu", g, test_bgn);
reg_file_set_stage(CAL_STAGE_WRITES);
reg_file_set_sub_stage(CAL_SUBSTAGE_WRITES_CENTER);
@@ -4681,8 +4548,6 @@ static void mem_config(void)
uint32_t rw_wl_nop_cycles;
uint32_t max_latency;
- TRACE_FUNC();
-
//USER read in write and read latency
wlat = IORD_32DIRECT(MEM_T_WL_ADD, 0);
@@ -4771,8 +4636,6 @@ static void mem_skip_calibrate(void)
uint32_t vfifo_offset;
uint32_t i, j, r;
- TRACE_FUNC();
-
// Need to update every shadow register set used by the interface
for (r = 0; r < RW_MGR_MEM_NUMBER_OF_RANKS; r += NUM_RANKS_PER_SHADOW_REG) {
@@ -4857,8 +4720,6 @@ static uint32_t mem_calibrate(void)
uint32_t group_failed = 0;
uint32_t sr_failed = 0;
- TRACE_FUNC();
-
// Initialize the data settings
DPRINT(1, "Preparing to init data");
DPRINT(1, "Init complete");
@@ -4869,9 +4730,6 @@ static uint32_t mem_calibrate(void)
gbl->fom_in = 0;
gbl->fom_out = 0;
- TCLRPT_SET(debug_summary_report->cal_read_latency, 0);
- TCLRPT_SET(debug_summary_report->cal_write_latency, 0);
-
mem_config();
if (ARRIAV || CYCLONEV) {
@@ -4991,10 +4849,6 @@ static uint32_t mem_calibrate(void)
}
}
if (sr_failed == 0) {
- TCLRPT_SET(debug_cal_report->
- cal_status_per_group[sr]
- [write_group].error_stage,
- CAL_STAGE_NIL);
} else {
group_failed = 1;
}
@@ -5057,19 +4911,6 @@ static uint32_t mem_calibrate(void)
}
}
- TCLRPT_SET(debug_summary_report->cal_write_latency, IORD_32DIRECT(MEM_T_WL_ADD, 0));
- if (QUARTER_RATE == 1) {
- // The read latency is in terms of AFI cycles so we multiply by 4 in quarter
- // rate to get the memory cycles.
- TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat * 4);
- } else if (HALF_RATE == 1) {
- // The read latency is in terms of AFI cycles so we multiply by 2 in half
- // rate to get the memory cycles.
- TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat * 2);
- } else {
- TCLRPT_SET(debug_summary_report->cal_read_latency, gbl->curr_read_lat);
- }
-
//USER Do not remove this line as it makes sure all of our decisions have been applied
IOWR_32DIRECT(SCC_MGR_UPD, 0, 0);
return 1;
@@ -5077,6 +4918,7 @@ static uint32_t mem_calibrate(void)
static uint32_t run_mem_calibrate(void)
{
+
uint32_t pass;
uint32_t debug_info;
uint32_t ctrlcfg = IORD_32DIRECT(CTRL_CONFIG_REG, 0);
@@ -5085,10 +4927,6 @@ static uint32_t run_mem_calibrate(void)
// This should occur before anything else
// Reset pass/fail status shown on afi_cal_success/fail
IOWR_32DIRECT(PHY_MGR_CAL_STATUS, 0, PHY_MGR_CAL_RESET);
-
- TRACE_FUNC();
-
- BFM_STAGE("calibrate");
//stop tracking manger
IOWR_32DIRECT(CTRL_CONFIG_REG, 0, ctrlcfg & 0xFFBFFFFF);
@@ -5106,10 +4944,6 @@ static uint32_t run_mem_calibrate(void)
IOWR_32DIRECT(PHY_MGR_CMD_FIFO_RESET, 0, 0);
if (pass) {
- TCLRPT_SET(debug_summary_report->error_stage, CAL_STAGE_NIL);
-
- BFM_STAGE("handoff");
-
#ifdef TEST_SIZE
if (!check_test_mem(0)) {
gbl->error_stage = 0x92;
@@ -5173,14 +5007,6 @@ static uint32_t run_mem_calibrate(void)
}
- // Mark the reports as being ready to read
- TCLRPT_SET(debug_summary_report->report_flags, debug_summary_report->report_flags |=
- DEBUG_REPORT_STATUS_REPORT_READY);
- TCLRPT_SET(debug_cal_report->report_flags, debug_cal_report->report_flags |=
- DEBUG_REPORT_STATUS_REPORT_READY);
- TCLRPT_SET(debug_margin_report->report_flags, debug_margin_report->report_flags |=
- DEBUG_REPORT_STATUS_REPORT_READY);
-
// Set the debug status to show that calibration has ended.
// This should occur after everything else
return pass;
@@ -5349,7 +5175,6 @@ static int socfpga_mem_calibration(void)
IPRINT("Preparing to start memory calibration");
- TRACE_FUNC();
DPRINT(1,
"%s%s %s ranks=%lu cs/dimm=%lu dq/dqs=%lu,%lu vg/dqs=%lu,%lu dqs=%lu,%lu dq=%lu dm=%lu "
"ptap_delay=%lu dtap_delay=%lu dtap_dqsen_delay=%lu, dll=%lu",
diff --git a/arch/arm/mach-socfpga/include/mach/sequencer.h b/arch/arm/mach-socfpga/include/mach/sequencer.h
index 1671849d6d..dd0378af34 100644
--- a/arch/arm/mach-socfpga/include/mach/sequencer.h
+++ b/arch/arm/mach-socfpga/include/mach/sequencer.h
@@ -65,6 +65,8 @@
#define RW_MGR_LOOPBACK_MODE BASE_RW_MGR + 0x0200
+#define RW_MGR_ENABLE_REFRESH BASE_RW_MGR + 0x3000
+
#define RW_MGR_RANK_NONE 0xFF
#define RW_MGR_RANK_ALL 0x00
diff --git a/arch/arm/mach-socfpga/include/mach/socfpga-regs.h b/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
index b124ed675c..e88daf7189 100644
--- a/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
+++ b/arch/arm/mach-socfpga/include/mach/socfpga-regs.h
@@ -2,6 +2,8 @@
#define __MACH_SOCFPGA_REGS_H
#define CYCLONE5_SDMMC_ADDRESS 0xff704000
+#define CYCLONE5_QSPI_CTRL_ADDRESS 0xff705000
+#define CYCLONE5_QSPI_DATA_ADDRESS 0xffa00000
#define CYCLONE5_FPGAMGRREGS_ADDRESS 0xff706000
#define CYCLONE5_GPIO0_BASE 0xff708000
#define CYCLONE5_GPIO1_BASE 0xff709000
diff --git a/arch/arm/mach-socfpga/xload.c b/arch/arm/mach-socfpga/xload.c
index 3380092168..272896b6bd 100644
--- a/arch/arm/mach-socfpga/xload.c
+++ b/arch/arm/mach-socfpga/xload.c
@@ -1,3 +1,4 @@
+#include <platform_data/cadence_qspi.h>
#include <platform_data/dw_mmc.h>
#include <bootsource.h>
#include <bootstrap.h>
@@ -14,11 +15,19 @@
#include <linux/stat.h>
#include <linux/clk.h>
+#include <mach/generic.h>
#include <mach/system-manager.h>
#include <mach/socfpga-regs.h>
+struct socfpga_barebox_part *barebox_part;
+
+static struct socfpga_barebox_part default_part = {
+ .nor_offset = SZ_256K,
+ .nor_size = SZ_1M,
+};
+
enum socfpga_clks {
- timer, mmc, uart, clk_max
+ timer, mmc, qspi_clk, uart, clk_max
};
static struct clk *clks[clk_max];
@@ -35,6 +44,43 @@ static void socfpga_mmc_init(void)
IORESOURCE_MEM, &mmc_pdata);
}
+#if defined(CONFIG_SPI_CADENCE_QUADSPI)
+static struct cadence_qspi_platform_data qspi_pdata = {
+ .ext_decoder = 0,
+ .fifo_depth = 128,
+};
+
+static __maybe_unused void add_cadence_qspi_device(int id, resource_size_t ctrl,
+ resource_size_t data, void *pdata)
+{
+ struct resource *res;
+
+ res = xzalloc(sizeof(struct resource) * 2);
+ res[0].start = ctrl;
+ res[0].end = ctrl + 0x100 - 1;
+ res[0].flags = IORESOURCE_MEM;
+ res[1].start = data;
+ res[1].end = data + 0x100 - 1;
+ res[1].flags = IORESOURCE_MEM;
+
+ add_generic_device_res("cadence_qspi", id, res, 2, pdata);
+}
+
+static __maybe_unused void socfpga_qspi_init(void)
+{
+ clks[qspi_clk] = clk_fixed("qspi_clk", 370000000);
+ clkdev_add_physbase(clks[qspi_clk], CYCLONE5_QSPI_CTRL_ADDRESS, NULL);
+ clkdev_add_physbase(clks[qspi_clk], CYCLONE5_QSPI_DATA_ADDRESS, NULL);
+ add_cadence_qspi_device(0, CYCLONE5_QSPI_CTRL_ADDRESS,
+ CYCLONE5_QSPI_DATA_ADDRESS, &qspi_pdata);
+}
+#else
+static void socfpga_qspi_init(void)
+{
+ return;
+}
+#endif
+
static struct NS16550_plat uart_pdata = {
.clock = 100000000,
.shift = 2,
@@ -62,10 +108,19 @@ static __noreturn int socfpga_xload(void)
enum bootsource bootsource = bootsource_get();
void *buf;
+ if (!barebox_part)
+ barebox_part = &default_part;
+
switch (bootsource) {
case BOOTSOURCE_MMC:
+ socfpga_mmc_init();
buf = bootstrap_read_disk("disk0.1", "fat");
break;
+ case BOOTSOURCE_SPI:
+ socfpga_qspi_init();
+ buf = bootstrap_read_devfs("mtd0", false, barebox_part->nor_offset,
+ barebox_part->nor_size, SZ_1M);
+ break;
default:
pr_err("unknown bootsource %d\n", bootsource);
hang();
@@ -88,7 +143,6 @@ static int socfpga_devices_init(void)
barebox_set_model("SoCFPGA");
socfpga_timer_init();
socfpga_uart_init();
- socfpga_mmc_init();
barebox_main = socfpga_xload;
diff --git a/arch/arm/mach-tegra/include/mach/lowlevel.h b/arch/arm/mach-tegra/include/mach/lowlevel.h
index f1fea86cf6..0c76b8883c 100644
--- a/arch/arm/mach-tegra/include/mach/lowlevel.h
+++ b/arch/arm/mach-tegra/include/mach/lowlevel.h
@@ -111,9 +111,9 @@ u32 tegra_get_odmdata(void)
return 0;
}
- bctptr = cpu_readl(TEGRA_IRAM_BASE + bctptr_offset);
+ bctptr = __raw_readl(TEGRA_IRAM_BASE + bctptr_offset);
- return cpu_readl(bctptr + odmdata_offset);
+ return __raw_readl(bctptr + odmdata_offset);
}
static __always_inline
@@ -243,11 +243,20 @@ void tegra_ll_delay_usec(int delay)
while ((int)readl(TEGRA_TMRUS_BASE + TIMER_CNTR_1US) - timeout < 0);
}
+/* reset vector for the AVP, to be called from board reset vector */
+void tegra_avp_reset_vector(uint32_t boarddata);
+
+/* reset vector for the main CPU complex */
+void tegra_maincomplex_entry(void);
+
static __always_inline
void tegra_cpu_lowlevel_setup(void)
{
uint32_t r;
+ if (tegra_cpu_is_maincomplex())
+ tegra_maincomplex_entry();
+
/* set the cpu to SVC32 mode */
__asm__ __volatile__("mrs %0, cpsr":"=r"(r));
r &= ~0x1f;
@@ -258,10 +267,4 @@ void tegra_cpu_lowlevel_setup(void)
tegra_ll_delay_setup();
}
-/* reset vector for the AVP, to be called from board reset vector */
-void tegra_avp_reset_vector(uint32_t boarddata);
-
-/* reset vector for the main CPU complex */
-void tegra_maincomplex_entry(void);
-
#endif /* __TEGRA_LOWLEVEL_H */
diff --git a/arch/arm/mach-tegra/tegra_avp_init.c b/arch/arm/mach-tegra/tegra_avp_init.c
index 91fd894dca..20fcf3f1d1 100644
--- a/arch/arm/mach-tegra/tegra_avp_init.c
+++ b/arch/arm/mach-tegra/tegra_avp_init.c
@@ -265,9 +265,6 @@ void tegra_avp_reset_vector(uint32_t boarddata)
/* put boarddata in scratch reg, for main CPU to fetch after startup */
writel(boarddata, TEGRA_PMC_BASE + PMC_SCRATCH(10));
- if (tegra_cpu_is_maincomplex())
- tegra_maincomplex_entry();
-
/* we want to bring up the high performance CPU complex */
if (tegra_get_chiptype() >= TEGRA30)
tegra_cluster_switch_hp();
diff --git a/arch/arm/pbl/Makefile b/arch/arm/pbl/Makefile
index 4c1788dd9d..1ff39dbdfe 100644
--- a/arch/arm/pbl/Makefile
+++ b/arch/arm/pbl/Makefile
@@ -22,7 +22,7 @@ endif
$(obj)/zbarebox.bin: $(obj)/zbarebox FORCE
$(call if_changed,objcopy)
- $(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
+ $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
$(Q)$(kecho) ' Barebox: fix size'
$(Q)$(objtree)/scripts/fix_size -i -f $(objtree)/$@ $(FIX_SIZE)
$(Q)$(kecho) ' Barebox: $@ is ready'
diff --git a/arch/blackfin/include/asm/io.h b/arch/blackfin/include/asm/io.h
index 2837b6a1aa..703104e1b8 100644
--- a/arch/blackfin/include/asm/io.h
+++ b/arch/blackfin/include/asm/io.h
@@ -90,21 +90,21 @@ extern void *__ioremap(unsigned long physaddr, unsigned long size,
int cacheflag);
extern void __iounmap(void *addr, unsigned long size);
-extern inline void *ioremap(unsigned long physaddr, unsigned long size)
+static inline void *ioremap(unsigned long physaddr, unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-extern inline void *ioremap_nocache(unsigned long physaddr,
+static inline void *ioremap_nocache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-extern inline void *ioremap_writethrough(unsigned long physaddr,
+static inline void *ioremap_writethrough(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-extern inline void *ioremap_fullcache(unsigned long physaddr,
+static inline void *ioremap_fullcache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
diff --git a/arch/blackfin/include/asm/posix_types.h b/arch/blackfin/include/asm/posix_types.h
index 9992929ada..22cae6230c 100644
--- a/arch/blackfin/include/asm/posix_types.h
+++ b/arch/blackfin/include/asm/posix_types.h
@@ -1,85 +1 @@
-/*
- * barebox - posix_types.h
- *
- * Copyright (c) 2005 blackfin.uclinux.org
- *
- * (C) Copyright 2000-2004
- * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
- *
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
-
-#ifndef __ARCH_BLACKFIN_POSIX_TYPES_H
-#define __ARCH_BLACKFIN_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-typedef unsigned long __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;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-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(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-
-#undef __FD_CLR
-#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-
-#undef __FD_ISSET
-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) (memset (fdsetp, 0, sizeof(*(fd_set *)fdsetp)))
-
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
-
-#endif
+#include <asm-generic/posix_types.h>
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index eaa1e4a03f..f46363732a 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -36,7 +36,7 @@
#include <asm/ptrace.h>
#include <asm/current.h>
-extern inline unsigned long rdusp(void)
+static inline unsigned long rdusp(void)
{
unsigned long usp;
@@ -44,7 +44,7 @@ extern inline unsigned long rdusp(void)
return usp;
}
-extern inline void wrusp(unsigned long usp)
+static inline void wrusp(unsigned long usp)
{
__asm__ __volatile__("usp = %0;\n\t"::"da"(usp));
}
@@ -130,7 +130,7 @@ static inline void exit_thread(void)
/*
* Return saved PC of a blocked thread.
*/
-extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+static inline unsigned long thread_saved_pc(struct thread_struct *t)
{
extern void scheduling_functions_start_here(void);
extern void scheduling_functions_end_here(void);
diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h
index 89de6507ca..1f645db374 100644
--- a/arch/blackfin/include/asm/swab.h
+++ b/arch/blackfin/include/asm/swab.h
@@ -12,7 +12,7 @@
#ifdef __GNUC__
-static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swahb32(__u32 xx)
{
__u32 tmp;
__asm__("%1 = %0 >> 8 (V);\n\t"
@@ -23,7 +23,7 @@ static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
}
#define __arch_swahb32 __arch_swahb32
-static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swahw32(__u32 xx)
{
__u32 rv;
__asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
@@ -31,13 +31,13 @@ static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
}
#define __arch_swahw32 __arch_swahw32
-static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 xx)
{
return __arch_swahb32(__arch_swahw32(xx));
}
#define __arch_swab32 __arch_swab32
-static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 xx)
{
__u32 xw = xx;
__asm__("%0 <<= 8;\n %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
diff --git a/arch/blackfin/include/asm/types.h b/arch/blackfin/include/asm/types.h
index 3d2bd35ef4..e9d73377eb 100644
--- a/arch/blackfin/include/asm/types.h
+++ b/arch/blackfin/include/asm/types.h
@@ -69,14 +69,10 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
-
#endif
#endif /* __ASSEMBLY__ */
-#define BITS_PER_LONG 32
+#include <asm/bitsperlong.h>
#endif
diff --git a/arch/efi/include/asm/bitsperlong.h b/arch/efi/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..00c1fc2625
--- /dev/null
+++ b/arch/efi/include/asm/bitsperlong.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#ifdef __x86_64__
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+#endif /* __ASM_BITSPERLONG_H */
diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h
index 6985b8eb4a..22cae6230c 100644
--- a/arch/efi/include/asm/posix_types.h
+++ b/arch/efi/include/asm/posix_types.h
@@ -1,93 +1 @@
-#ifndef __ARCH_I386_POSIX_TYPES_H
-#define __ARCH_I386_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-/*
- * Most 32 bit architectures use "unsigned int" size_t,
- * and all 64 bit architectures use "unsigned long" size_t.
- *
- * TODO: It's not clean to use __x86_64__ here. It's better
- * to check on __BITS_PER_LONG here. But this is wrong set in
- * arch/sandbox/include/asm/types.h.
- */
-#ifdef __x86_64__
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef long __kernel_ptrdiff_t;
-#else
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
-#endif
-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;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-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,fdsetp) \
- __asm__ __volatile__("btsl %1,%0": \
- "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd,fdsetp) \
- __asm__ __volatile__("btrl %1,%0": \
- "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
- unsigned char __result; \
- __asm__ __volatile__("btl %1,%2 ; setb %0" \
- :"=q" (__result) :"r" ((int) (fd)), \
- "m" (*(__kernel_fd_set *) (fdsetp))); \
- __result; }))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) \
-do { \
- int __d0, __d1; \
- __asm__ __volatile__("cld ; rep ; stosl" \
- :"=m" (*(__kernel_fd_set *) (fdsetp)), \
- "=&c" (__d0), "=&D" (__d1) \
- :"a" (0), "1" (__FDSET_LONGS), \
- "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
-} while (0)
-
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
-
-#endif
+#include <asm-generic/posix_types.h>
diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h
index 3204448dce..3caac398d8 100644
--- a/arch/efi/include/asm/types.h
+++ b/arch/efi/include/asm/types.h
@@ -56,15 +56,7 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
-#ifdef __x86_64__
-#define BITS_PER_LONG 64
-#else
-#define BITS_PER_LONG 32
-#endif
-
-/* Dma addresses are 32-bits wide. */
-
-typedef u32 dma_addr_t;
+#include <asm/bitsperlong.h>
#endif /* __KERNEL__ */
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index ed6e1ab2df..aeb5c04fce 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -269,6 +269,7 @@ config 32BIT
config 64BIT
bool "64-bit barebox"
depends on CPU_SUPPORTS_64BIT_KERNEL && SYS_SUPPORTS_64BIT_KERNEL
+ select ARCH_DMA_ADDR_T_64BIT
help
Select this option if you want to build a 64-bit barebox.
diff --git a/arch/mips/configs/dlink-dir-320_defconfig b/arch/mips/configs/dlink-dir-320_defconfig
index 4c9a06f2b0..61798bf599 100644
--- a/arch/mips/configs/dlink-dir-320_defconfig
+++ b/arch/mips/configs/dlink-dir-320_defconfig
@@ -2,7 +2,6 @@ CONFIG_BUILTIN_DTB=y
CONFIG_BUILTIN_DTB_NAME="dlink-dir-320"
CONFIG_MACH_MIPS_BCM47XX=y
CONFIG_STACK_SIZE=0x7000
-CONFIG_BROKEN=y
CONFIG_EXPERIMENTAL=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
@@ -35,9 +34,9 @@ CONFIG_CMD_PING=y
CONFIG_CMD_TFTP=y
CONFIG_CMD_ECHO_E=y
CONFIG_CMD_EDIT=y
+CONFIG_CMD_LOGIN=y
CONFIG_CMD_MENU=y
CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_LOGIN=y
CONFIG_CMD_PASSWD=y
CONFIG_CMD_READLINE=y
CONFIG_CMD_TIMEOUT=y
diff --git a/arch/mips/configs/img-ci20_defconfig b/arch/mips/configs/img-ci20_defconfig
index 6702c88b65..28319c523f 100644
--- a/arch/mips/configs/img-ci20_defconfig
+++ b/arch/mips/configs/img-ci20_defconfig
@@ -28,15 +28,18 @@ CONFIG_CMD_UIMAGE=y
CONFIG_CMD_MD5SUM=y
CONFIG_CMD_GETOPT=y
CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_GPIO=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OFTREE=y
+CONFIG_NET=y
CONFIG_OFDEVICE=y
+CONFIG_DRIVER_NET_DM9K=y
# CONFIG_SPI is not set
-CONFIG_CLOCKSOURCE_DUMMY=y
CONFIG_CLOCKSOURCE_DUMMY_RATE=3500
-CONFIG_DIGEST_SHA1_GENERIC=y
-CONFIG_DIGEST_SHA224_GENERIC=y
-CONFIG_DIGEST_SHA256_GENERIC=y
+CONFIG_FS_TFTP=y
diff --git a/arch/mips/dts/img-ci20.dts b/arch/mips/dts/img-ci20.dts
index f2022dd273..da2a5bf625 100644
--- a/arch/mips/dts/img-ci20.dts
+++ b/arch/mips/dts/img-ci20.dts
@@ -28,6 +28,21 @@
device_type = "memory";
reg = <0x0 0x10000000>;
};
+
+ board {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ compatible = "simple-bus";
+ ranges = <>;
+
+ dm9000@16000000 {
+ compatible = "davicom,dm9000";
+ davicom,no-eeprom;
+
+ reg = <0x16000000 1 /* addr */
+ 0x16000002 1>; /* data */
+ };
+ };
};
&uart0 {
diff --git a/arch/mips/include/asm/bitsperlong.h b/arch/mips/include/asm/bitsperlong.h
index 3e4c10a8e7..41712161bc 100644
--- a/arch/mips/include/asm/bitsperlong.h
+++ b/arch/mips/include/asm/bitsperlong.h
@@ -1,8 +1,6 @@
#ifndef __ASM_MIPS_BITSPERLONG_H
#define __ASM_MIPS_BITSPERLONG_H
-#define __BITS_PER_LONG _MIPS_SZLONG
-
-#include <asm-generic/bitsperlong.h>
+#define BITS_PER_LONG _MIPS_SZLONG
#endif /* __ASM_MIPS_BITSPERLONG_H */
diff --git a/arch/mips/include/asm/debug_ll_ns16550.h b/arch/mips/include/asm/debug_ll_ns16550.h
index a3e1c52f63..4a6562f7c1 100644
--- a/arch/mips/include/asm/debug_ll_ns16550.h
+++ b/arch/mips/include/asm/debug_ll_ns16550.h
@@ -57,7 +57,7 @@
#include <asm/io.h>
-static __inline__ void PUTC_LL(char ch)
+static inline void PUTC_LL(char ch)
{
#ifdef CONFIG_DEBUG_LL
while (!(__raw_readb((u8 *)DEBUG_LL_UART_ADDR + UART_LSR) & UART_LSR_THRE))
diff --git a/arch/mips/include/asm/posix_types.h b/arch/mips/include/asm/posix_types.h
index bbeb7211f6..c38e24a4b2 100644
--- a/arch/mips/include/asm/posix_types.h
+++ b/arch/mips/include/asm/posix_types.h
@@ -11,134 +11,6 @@
#include <asm/sgidefs.h>
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned int __kernel_mode_t;
-#if (_MIPS_SZLONG == 32)
-typedef unsigned long __kernel_nlink_t;
-#endif
-#if (_MIPS_SZLONG == 64)
-typedef unsigned int __kernel_nlink_t;
-#endif
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef int __kernel_ipc_pid_t;
-typedef unsigned int __kernel_uid_t;
-typedef unsigned int __kernel_gid_t;
-#if (_MIPS_SZLONG == 32)
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
-#endif
-#if (_MIPS_SZLONG == 64)
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef long __kernel_ptrdiff_t;
-#endif
-typedef long __kernel_time_t;
-typedef long __kernel_suseconds_t;
-typedef long __kernel_clock_t;
-typedef int __kernel_timer_t;
-typedef int __kernel_clockid_t;
-typedef long __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 __kernel_uid_t __kernel_old_uid_t;
-typedef __kernel_gid_t __kernel_old_gid_t;
-typedef unsigned int __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
-#if (_MIPS_SZLONG == 32)
- long val[2];
-#endif
-#if (_MIPS_SZLONG == 64)
- int val[2];
-#endif
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
- unsigned long __tmp = __fd / __NFDBITS;
- unsigned long __rem = __fd % __NFDBITS;
- __fdsetp->fds_bits[__tmp] |= (1UL<<__rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long __fd, __kernel_fd_set *__fdsetp)
-{
- unsigned long __tmp = __fd / __NFDBITS;
- unsigned long __rem = __fd % __NFDBITS;
- __fdsetp->fds_bits[__tmp] &= ~(1UL<<__rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long __fd, const __kernel_fd_set *__p)
-{
- unsigned long __tmp = __fd / __NFDBITS;
- unsigned long __rem = __fd % __NFDBITS;
- return (__p->fds_bits[__tmp] & (1UL<<__rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *__p)
-{
- unsigned long *__tmp = __p->fds_bits;
- int __i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 16:
- __tmp[0] = 0; __tmp[1] = 0;
- __tmp[2] = 0; __tmp[3] = 0;
- __tmp[4] = 0; __tmp[5] = 0;
- __tmp[6] = 0; __tmp[7] = 0;
- __tmp[8] = 0; __tmp[9] = 0;
- __tmp[10] = 0; __tmp[11] = 0;
- __tmp[12] = 0; __tmp[13] = 0;
- __tmp[14] = 0; __tmp[15] = 0;
- return;
-
- case 8:
- __tmp[0] = 0; __tmp[1] = 0;
- __tmp[2] = 0; __tmp[3] = 0;
- __tmp[4] = 0; __tmp[5] = 0;
- __tmp[6] = 0; __tmp[7] = 0;
- return;
-
- case 4:
- __tmp[0] = 0; __tmp[1] = 0;
- __tmp[2] = 0; __tmp[3] = 0;
- return;
- }
- }
- __i = __FDSET_LONGS;
- while (__i) {
- __i--;
- *__tmp = 0;
- __tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) */
+#include <asm-generic/posix_types.h>
#endif /* _ASM_POSIX_TYPES_H */
diff --git a/arch/mips/include/asm/types.h b/arch/mips/include/asm/types.h
index b63687d37b..4140c92e1a 100644
--- a/arch/mips/include/asm/types.h
+++ b/arch/mips/include/asm/types.h
@@ -13,18 +13,6 @@
#include <asm-generic/int-ll64.h>
-#ifndef __ASSEMBLY__
-
-#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \
- || defined(CONFIG_64BIT)
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-typedef u64 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
/*
* We don't use int-l64.h for the kernel anymore but still use it for
* userspace to avoid code changes.
diff --git a/arch/mips/mach-ath79/include/mach/debug_ll.h b/arch/mips/mach-ath79/include/mach/debug_ll.h
index c697318488..64db67499c 100644
--- a/arch/mips/mach-ath79/include/mach/debug_ll.h
+++ b/arch/mips/mach-ath79/include/mach/debug_ll.h
@@ -41,12 +41,12 @@
static inline void ar933x_debug_ll_writel(u32 b, int offset)
{
- cpu_writel(b, (u8 *)DEBUG_LL_UART_ADDR + offset);
+ __raw_writel(b, (u8 *)DEBUG_LL_UART_ADDR + offset);
}
static inline u32 ar933x_debug_ll_readl(int offset)
{
- return cpu_readl((u8 *)DEBUG_LL_UART_ADDR + offset);
+ return __raw_readl((u8 *)DEBUG_LL_UART_ADDR + offset);
}
static inline void PUTC_LL(int ch)
diff --git a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
index 9927b4d945..3e74e0f670 100644
--- a/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
+++ b/arch/mips/mach-bcm47xx/include/mach/debug_ll.h
@@ -24,16 +24,12 @@
#include <io.h>
#include <mach/hardware.h>
-#define rbr 0
-#define lsr 5
-#define LSR_THRE 0x20 /* Xmit holding register empty */
+#define DEBUG_LL_UART_SHIFT 0
-static __inline__ void PUTC_LL(char ch)
-{
- void *base = (void *)DEBUG_LL_UART_ADDR;
+#define DEBUG_LL_UART_CLK (25804800 / 16)
+#define DEBUG_LL_UART_BPS CONFIG_BAUDRATE
+#define DEBUG_LL_UART_DIVISOR (DEBUG_LL_UART_CLK / DEBUG_LL_UART_BPS)
- while (!(__raw_readb(base + lsr) & LSR_THRE));
- __raw_writeb(ch, base + rbr);
-}
+#include <asm/debug_ll_ns16550.h>
#endif /* __INCLUDE_ARCH_DEBUG_LL_H__ */
diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c
index f1dc68afb5..00aee190fe 100644
--- a/arch/mips/mach-bcm47xx/reset.c
+++ b/arch/mips/mach-bcm47xx/reset.c
@@ -15,11 +15,6 @@
*
*/
-/**
- * @file
- * @brief Resetting an malta board
- */
-
#include <common.h>
#include <io.h>
#include <mach/hardware.h>
diff --git a/arch/mips/mach-xburst/Kconfig b/arch/mips/mach-xburst/Kconfig
index 2598c41cdf..fd106fefe0 100644
--- a/arch/mips/mach-xburst/Kconfig
+++ b/arch/mips/mach-xburst/Kconfig
@@ -27,6 +27,7 @@ config BOARD_RZX50
config BOARD_CI20
bool "Imagination Creator CI20"
select CPU_JZ4780
+ select HAS_DM9000
endchoice
diff --git a/arch/mips/pbl/Makefile b/arch/mips/pbl/Makefile
index fea1f249bb..b03bca1258 100644
--- a/arch/mips/pbl/Makefile
+++ b/arch/mips/pbl/Makefile
@@ -15,7 +15,7 @@ extra-y += piggy.gzip piggy.lz4 piggy.lzo piggy.lzma piggy.xzkern piggy.sh
$(obj)/zbarebox.bin: $(obj)/zbarebox FORCE
$(call if_changed,objcopy)
- $(call cmd,check_file_size,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
+ $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_IMAGE_SIZE))
$(Q)$(kecho) ' Barebox: $@ is ready'
$(obj)/zbarebox.S: $(obj)/zbarebox FORCE
diff --git a/arch/nios2/include/asm/posix_types.h b/arch/nios2/include/asm/posix_types.h
index 5a901ffe43..22cae6230c 100644
--- a/arch/nios2/include/asm/posix_types.h
+++ b/arch/nios2/include/asm/posix_types.h
@@ -1,77 +1 @@
-/*
- * arch/arm/include/asm/posix_types.h
- *
- * Copyright (C) 1996-1998 Russell King.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Changelog:
- * 27-06-1996 RMK Created
- */
-#ifndef __ARCH_ARM_POSIX_TYPES_H
-#define __ARCH_ARM_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-typedef unsigned long __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_timer_t;
-typedef int __kernel_clockid_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 unsigned short __kernel_old_dev_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#if defined(__KERNEL__)
-
-#undef __FD_SET
-#define __FD_SET(fd, fdsetp) \
- (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] |= (1<<((fd) & 31)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd, fdsetp) \
- (((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] &= ~(1<<((fd) & 31)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd, fdsetp) \
- ((((fd_set *)(fdsetp))->fds_bits[(fd) >> 5] & (1<<((fd) & 31))) != 0)
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) \
- (memset(fdsetp, 0, sizeof(*(fd_set *)(fdsetp))))
-
-#endif
-
-#endif
+#include <asm-generic/posix_types.h>
diff --git a/arch/nios2/include/asm/types.h b/arch/nios2/include/asm/types.h
index 21c3415f93..0067ea83c1 100644
--- a/arch/nios2/include/asm/types.h
+++ b/arch/nios2/include/asm/types.h
@@ -3,7 +3,4 @@
#include <asm/int-ll64.h>
-typedef u32 dma_addr_t;
-
#endif
-
diff --git a/arch/openrisc/include/asm/bitsperlong.h b/arch/openrisc/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..6dc0bb0c13
--- /dev/null
+++ b/arch/openrisc/include/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/openrisc/include/asm/posix_types.h b/arch/openrisc/include/asm/posix_types.h
index 7f4c9423ca..22cae6230c 100644
--- a/arch/openrisc/include/asm/posix_types.h
+++ b/arch/openrisc/include/asm/posix_types.h
@@ -1,71 +1 @@
-/*
- * 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 */
+#include <asm-generic/posix_types.h>
diff --git a/arch/openrisc/include/asm/types.h b/arch/openrisc/include/asm/types.h
index 3338fcfdeb..5b6391baf0 100644
--- a/arch/openrisc/include/asm/types.h
+++ b/arch/openrisc/include/asm/types.h
@@ -62,11 +62,7 @@ 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;
+#include <asm/bitsperlong.h>
#endif /* __KERNEL__ */
diff --git a/arch/ppc/include/asm/atomic.h b/arch/ppc/include/asm/atomic.h
index 23f22df1b7..a98d892ea7 100644
--- a/arch/ppc/include/asm/atomic.h
+++ b/arch/ppc/include/asm/atomic.h
@@ -21,7 +21,7 @@ typedef struct { int counter; } atomic_t;
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
-extern __inline__ int atomic_add_return(int a, atomic_t *v)
+static inline int atomic_add_return(int a, atomic_t *v)
{
int t;
@@ -37,7 +37,7 @@ extern __inline__ int atomic_add_return(int a, atomic_t *v)
return t;
}
-extern __inline__ int atomic_sub_return(int a, atomic_t *v)
+static inline int atomic_sub_return(int a, atomic_t *v)
{
int t;
@@ -53,7 +53,7 @@ extern __inline__ int atomic_sub_return(int a, atomic_t *v)
return t;
}
-extern __inline__ int atomic_inc_return(atomic_t *v)
+static inline int atomic_inc_return(atomic_t *v)
{
int t;
@@ -69,7 +69,7 @@ extern __inline__ int atomic_inc_return(atomic_t *v)
return t;
}
-extern __inline__ int atomic_dec_return(atomic_t *v)
+static inline int atomic_dec_return(atomic_t *v)
{
int t;
diff --git a/arch/ppc/include/asm/bitops.h b/arch/ppc/include/asm/bitops.h
index c4ed2de65f..2fdd57eff0 100644
--- a/arch/ppc/include/asm/bitops.h
+++ b/arch/ppc/include/asm/bitops.h
@@ -28,7 +28,7 @@
* These used to be if'd out here because using : "cc" as a constraint
* resulted in errors from egcs. Things may be OK with gcc-2.95.
*/
-extern __inline__ void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void * addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -45,7 +45,7 @@ extern __inline__ void set_bit(int nr, volatile void * addr)
: "cc" );
}
-extern __inline__ void clear_bit(int nr, volatile void *addr)
+static inline void clear_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -62,7 +62,7 @@ extern __inline__ void clear_bit(int nr, volatile void *addr)
: "cc");
}
-extern __inline__ void change_bit(int nr, volatile void *addr)
+static inline void change_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -79,7 +79,7 @@ extern __inline__ void change_bit(int nr, volatile void *addr)
: "cc");
}
-extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
+static inline int test_and_set_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -98,7 +98,7 @@ extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
return (old & mask) != 0;
}
-extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
+static inline int test_and_clear_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -117,7 +117,7 @@ extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
return (old & mask) != 0;
}
-extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
+static inline int test_and_change_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -138,7 +138,7 @@ extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
#endif /* __INLINE_BITOPS */
/* Return the bit position of the most significant 1 bit in a word */
-extern __inline__ int __ilog2(unsigned int x)
+static inline int __ilog2(unsigned int x)
{
int lz;
@@ -146,14 +146,14 @@ extern __inline__ int __ilog2(unsigned int x)
return 31 - lz;
}
-extern __inline__ int ffz(unsigned int x)
+static inline int ffz(unsigned int x)
{
if ((x = ~x) == 0)
return 32;
return __ilog2(x & -x);
}
-static __inline__ int __ffs(unsigned long x)
+static inline int __ffs(unsigned long x)
{
return __ilog2(x & -x);
}
@@ -177,7 +177,7 @@ static inline int fls(unsigned int x)
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-extern __inline__ int ffs(int x)
+static inline int ffs(int x)
{
return __ilog2(x & -x) + 1;
}
@@ -189,67 +189,4 @@ extern __inline__ int ffs(int x)
#include <asm-generic/bitops/find.h>
-#define _EXT2_HAVE_ASM_BITOPS_
-
-#ifdef __KERNEL__
-/*
- * test_and_{set,clear}_bit guarantee atomicity without
- * disabling interrupts.
- */
-#define ext2_set_bit(nr, addr) test_and_set_bit((nr) ^ 0x18, addr)
-#define ext2_clear_bit(nr, addr) test_and_clear_bit((nr) ^ 0x18, addr)
-
-#else
-extern __inline__ int ext2_set_bit(int nr, void * addr)
-{
- int mask;
- unsigned char *ADDR = (unsigned char *) addr;
- int oldbit;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- oldbit = (*ADDR & mask) ? 1 : 0;
- *ADDR |= mask;
- return oldbit;
-}
-
-extern __inline__ int ext2_clear_bit(int nr, void * addr)
-{
- int mask;
- unsigned char *ADDR = (unsigned char *) addr;
- int oldbit;
-
- ADDR += nr >> 3;
- mask = 1 << (nr & 0x07);
- oldbit = (*ADDR & mask) ? 1 : 0;
- *ADDR = *ADDR & ~mask;
- return oldbit;
-}
-#endif /* __KERNEL__ */
-
-extern __inline__ int ext2_test_bit(int nr, __const__ void * addr)
-{
- __const__ unsigned char *ADDR = (__const__ unsigned char *) addr;
-
- return (ADDR[nr >> 3] >> (nr & 7)) & 1;
-}
-
-/*
- * This implementation of ext2_find_{first,next}_zero_bit was stolen from
- * Linus' asm-alpha/bitops.h and modified for a big-endian machine.
- */
-
-#define ext2_find_first_zero_bit(addr, size) \
- ext2_find_next_zero_bit((addr), (size), 0)
-
-#define ext2_find_next_zero_bit(addr, size, off) \
- generic_find_next_zero_le_bit((unsigned long*)addr, size, off)
-
-/* Bitmap functions for the minix filesystem. */
-#define minix_test_and_set_bit(nr,addr) ext2_set_bit(nr,addr)
-#define minix_set_bit(nr,addr) ((void)ext2_set_bit(nr,addr))
-#define minix_test_and_clear_bit(nr,addr) ext2_clear_bit(nr,addr)
-#define minix_test_bit(nr,addr) ext2_test_bit(nr,addr)
-#define minix_find_first_zero_bit(addr,size) ext2_find_first_zero_bit(addr,size)
-
#endif /* _PPC_BITOPS_H */
diff --git a/arch/ppc/include/asm/bitsperlong.h b/arch/ppc/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..6dc0bb0c13
--- /dev/null
+++ b/arch/ppc/include/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/ppc/include/asm/io.h b/arch/ppc/include/asm/io.h
index 98bf5132cd..f83ab6ee0b 100644
--- a/arch/ppc/include/asm/io.h
+++ b/arch/ppc/include/asm/io.h
@@ -136,7 +136,7 @@ static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
/*
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
*/
-extern inline u8 in_8(const volatile u8 __iomem *addr)
+static inline u8 in_8(const volatile u8 __iomem *addr)
{
u8 ret;
@@ -145,12 +145,12 @@ extern inline u8 in_8(const volatile u8 __iomem *addr)
return ret;
}
-extern inline void out_8(volatile u8 __iomem *addr, u8 val)
+static inline void out_8(volatile u8 __iomem *addr, u8 val)
{
__asm__ __volatile__("sync;stb%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
-extern inline u16 in_le16(const volatile u16 __iomem *addr)
+static inline u16 in_le16(const volatile u16 __iomem *addr)
{
u16 ret;
@@ -159,7 +159,7 @@ extern inline u16 in_le16(const volatile u16 __iomem *addr)
return ret;
}
-extern inline u16 in_be16(const volatile u16 __iomem *addr)
+static inline u16 in_be16(const volatile u16 __iomem *addr)
{
u16 ret;
@@ -168,18 +168,18 @@ extern inline u16 in_be16(const volatile u16 __iomem *addr)
return ret;
}
-extern inline void out_le16(volatile u16 __iomem *addr, u16 val)
+static inline void out_le16(volatile u16 __iomem *addr, u16 val)
{
__asm__ __volatile__("sync; sthbrx %1,0,%2"
: "=m" (*addr) : "r" (val), "r" (addr));
}
-extern inline void out_be16(volatile u16 __iomem *addr, u16 val)
+static inline void out_be16(volatile u16 __iomem *addr, u16 val)
{
__asm__ __volatile__("sync;sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
-extern inline u32 in_le32(const volatile u32 __iomem *addr)
+static inline u32 in_le32(const volatile u32 __iomem *addr)
{
u32 ret;
@@ -188,7 +188,7 @@ extern inline u32 in_le32(const volatile u32 __iomem *addr)
return ret;
}
-extern inline u32 in_be32(const volatile u32 __iomem *addr)
+static inline u32 in_be32(const volatile u32 __iomem *addr)
{
u32 ret;
@@ -197,13 +197,13 @@ extern inline u32 in_be32(const volatile u32 __iomem *addr)
return ret;
}
-extern inline void out_le32(volatile u32 __iomem *addr, u32 val)
+static inline void out_le32(volatile u32 __iomem *addr, u32 val)
{
__asm__ __volatile__("sync; stwbrx %1,0,%2"
: "=m" (*addr) : "r" (val), "r" (addr));
}
-extern inline void out_be32(volatile u32 __iomem *addr, u32 val)
+static inline void out_be32(volatile u32 __iomem *addr, u32 val)
{
__asm__ __volatile__("sync;stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
diff --git a/arch/ppc/include/asm/posix_types.h b/arch/ppc/include/asm/posix_types.h
index a7af4064ee..22cae6230c 100644
--- a/arch/ppc/include/asm/posix_types.h
+++ b/arch/ppc/include/asm/posix_types.h
@@ -1,108 +1 @@
-#ifndef _PPC_POSIX_TYPES_H
-#define _PPC_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned int __kernel_ino_t;
-typedef unsigned int __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_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 long __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 short __kernel_ipc_pid_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 int __kernel_old_uid_t;
-typedef unsigned int __kernel_old_gid_t;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-typedef struct {
- int val[2];
-} __kernel_fsid_t;
-
-#ifndef __GNUC__
-
-#define __FD_SET(d, set) ((set)->fds_bits[__FDELT(d)] |= __FDMASK(d))
-#define __FD_CLR(d, set) ((set)->fds_bits[__FDELT(d)] &= ~__FDMASK(d))
-#define __FD_ISSET(d, set) ((set)->fds_bits[__FDELT(d)] & __FDMASK(d))
-#define __FD_ZERO(set) \
- ((void) memset ((__ptr_t) (set), 0, sizeof (__kernel_fd_set)))
-
-#else /* __GNUC__ */
-
-#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) \
- || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
-/* With GNU C, use inline functions instead so args are evaluated only once: */
-
-#undef __FD_SET
-static __inline__ void __FD_SET(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] |= (1UL<<_rem);
-}
-
-#undef __FD_CLR
-static __inline__ void __FD_CLR(unsigned long fd, __kernel_fd_set *fdsetp)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- fdsetp->fds_bits[_tmp] &= ~(1UL<<_rem);
-}
-
-#undef __FD_ISSET
-static __inline__ int __FD_ISSET(unsigned long fd, __kernel_fd_set *p)
-{
- unsigned long _tmp = fd / __NFDBITS;
- unsigned long _rem = fd % __NFDBITS;
- return (p->fds_bits[_tmp] & (1UL<<_rem)) != 0;
-}
-
-/*
- * This will unroll the loop for the normal constant case (8 ints,
- * for a 256-bit fd_set)
- */
-#undef __FD_ZERO
-static __inline__ void __FD_ZERO(__kernel_fd_set *p)
-{
- unsigned int *tmp = (unsigned int *)p->fds_bits;
- int i;
-
- if (__builtin_constant_p(__FDSET_LONGS)) {
- switch (__FDSET_LONGS) {
- case 8:
- tmp[0] = 0; tmp[1] = 0; tmp[2] = 0; tmp[3] = 0;
- tmp[4] = 0; tmp[5] = 0; tmp[6] = 0; tmp[7] = 0;
- return;
- }
- }
- i = __FDSET_LONGS;
- while (i) {
- i--;
- *tmp = 0;
- tmp++;
- }
-}
-
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
-#endif /* __GNUC__ */
-#endif /* _PPC_POSIX_TYPES_H */
+#include <asm-generic/posix_types.h>
diff --git a/arch/ppc/include/asm/swab.h b/arch/ppc/include/asm/swab.h
index c581e3ef73..110488e641 100644
--- a/arch/ppc/include/asm/swab.h
+++ b/arch/ppc/include/asm/swab.h
@@ -19,7 +19,7 @@
#ifdef __KERNEL__
-static __inline__ __u16 ld_le16(const volatile __u16 *addr)
+static inline __u16 ld_le16(const volatile __u16 *addr)
{
__u16 val;
@@ -28,7 +28,7 @@ static __inline__ __u16 ld_le16(const volatile __u16 *addr)
}
#define __arch_swab16p ld_le16
-static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
+static inline void st_le16(volatile __u16 *addr, const __u16 val)
{
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
}
@@ -39,7 +39,7 @@ static inline void __arch_swab16s(__u16 *addr)
}
#define __arch_swab16s __arch_swab16s
-static __inline__ __u32 ld_le32(const volatile __u32 *addr)
+static inline __u32 ld_le32(const volatile __u32 *addr)
{
__u32 val;
@@ -48,7 +48,7 @@ static __inline__ __u32 ld_le32(const volatile __u32 *addr)
}
#define __arch_swab32p ld_le32
-static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
+static inline void st_le32(volatile __u32 *addr, const __u32 val)
{
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
}
diff --git a/arch/ppc/include/asm/types.h b/arch/ppc/include/asm/types.h
index 4ebbb9e028..6eb3877032 100644
--- a/arch/ppc/include/asm/types.h
+++ b/arch/ppc/include/asm/types.h
@@ -39,10 +39,7 @@ 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;
+#include <asm-generic/bitsperlong.h>
#endif /* __KERNEL__ */
#endif /* __ASSEMBLY__ */
diff --git a/arch/sandbox/include/asm/bitsperlong.h b/arch/sandbox/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..00c1fc2625
--- /dev/null
+++ b/arch/sandbox/include/asm/bitsperlong.h
@@ -0,0 +1,10 @@
+#ifndef __ASM_BITSPERLONG_H
+#define __ASM_BITSPERLONG_H
+
+#ifdef __x86_64__
+#define BITS_PER_LONG 64
+#else
+#define BITS_PER_LONG 32
+#endif
+
+#endif /* __ASM_BITSPERLONG_H */
diff --git a/arch/sandbox/include/asm/byteorder.h b/arch/sandbox/include/asm/byteorder.h
index 37316f2371..3d82bcba6e 100644
--- a/arch/sandbox/include/asm/byteorder.h
+++ b/arch/sandbox/include/asm/byteorder.h
@@ -1,8 +1,8 @@
-#ifndef _I386_BYTEORDER_H
-#define _I386_BYTEORDER_H
+#ifndef _SANDBOX_BYTEORDER_H
+#define _SANDBOX_BYTEORDER_H
#include <asm/types.h>
#include <linux/byteorder/little_endian.h>
-#endif /* _I386_BYTEORDER_H */
+#endif /* _SANDBOX_BYTEORDER_H */
diff --git a/arch/sandbox/include/asm/posix_types.h b/arch/sandbox/include/asm/posix_types.h
index 6985b8eb4a..22cae6230c 100644
--- a/arch/sandbox/include/asm/posix_types.h
+++ b/arch/sandbox/include/asm/posix_types.h
@@ -1,93 +1 @@
-#ifndef __ARCH_I386_POSIX_TYPES_H
-#define __ARCH_I386_POSIX_TYPES_H
-
-/*
- * This file is generally used by user-level software, so you need to
- * be a little careful about namespace pollution etc. Also, we cannot
- * assume GCC is being used.
- */
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_t;
-typedef unsigned short __kernel_ipc_pid_t;
-typedef unsigned short __kernel_uid_t;
-typedef unsigned short __kernel_gid_t;
-/*
- * Most 32 bit architectures use "unsigned int" size_t,
- * and all 64 bit architectures use "unsigned long" size_t.
- *
- * TODO: It's not clean to use __x86_64__ here. It's better
- * to check on __BITS_PER_LONG here. But this is wrong set in
- * arch/sandbox/include/asm/types.h.
- */
-#ifdef __x86_64__
-typedef unsigned long __kernel_size_t;
-typedef long __kernel_ssize_t;
-typedef long __kernel_ptrdiff_t;
-#else
-typedef unsigned int __kernel_size_t;
-typedef int __kernel_ssize_t;
-typedef int __kernel_ptrdiff_t;
-#endif
-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;
-
-#ifdef __GNUC__
-typedef long long __kernel_loff_t;
-#endif
-
-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,fdsetp) \
- __asm__ __volatile__("btsl %1,%0": \
- "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef __FD_CLR
-#define __FD_CLR(fd,fdsetp) \
- __asm__ __volatile__("btrl %1,%0": \
- "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
-
-#undef __FD_ISSET
-#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
- unsigned char __result; \
- __asm__ __volatile__("btl %1,%2 ; setb %0" \
- :"=q" (__result) :"r" ((int) (fd)), \
- "m" (*(__kernel_fd_set *) (fdsetp))); \
- __result; }))
-
-#undef __FD_ZERO
-#define __FD_ZERO(fdsetp) \
-do { \
- int __d0, __d1; \
- __asm__ __volatile__("cld ; rep ; stosl" \
- :"=m" (*(__kernel_fd_set *) (fdsetp)), \
- "=&c" (__d0), "=&D" (__d1) \
- :"a" (0), "1" (__FDSET_LONGS), \
- "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
-} while (0)
-
-#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
-
-#endif
+#include <asm-generic/posix_types.h>
diff --git a/arch/sandbox/include/asm/types.h b/arch/sandbox/include/asm/types.h
index d471d257be..501883f5aa 100644
--- a/arch/sandbox/include/asm/types.h
+++ b/arch/sandbox/include/asm/types.h
@@ -54,11 +54,7 @@ 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;
+#include <asm/bitsperlong.h>
#endif /* __KERNEL__ */
diff --git a/arch/x86/include/asm/bitsperlong.h b/arch/x86/include/asm/bitsperlong.h
new file mode 100644
index 0000000000..6dc0bb0c13
--- /dev/null
+++ b/arch/x86/include/asm/bitsperlong.h
@@ -0,0 +1 @@
+#include <asm-generic/bitsperlong.h>
diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h
index 066f159cc9..22cae6230c 100644
--- a/arch/x86/include/asm/posix_types.h
+++ b/arch/x86/include/asm/posix_types.h
@@ -1,44 +1 @@
-/*
- * 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.
- *
- *
- */
-
-/**
- * @file
- * @brief x86 posix types
- *
- * Minimal set to make all the other header files copied from the Linux kernel happy
- */
-
-#ifndef _ASM_X86_POSIX_TYPES_H
-#define _ASM_X86_POSIX_TYPES_H
-
-typedef unsigned long __kernel_ino_t;
-typedef unsigned short __kernel_mode_t;
-typedef unsigned short __kernel_nlink_t;
-typedef long __kernel_off_t;
-typedef int __kernel_pid_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 long long __kernel_loff_t;
-
-#endif /* _ASM_X86_POSIX_TYPES_H */
+#include <asm-generic/posix_types.h>
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
index b3fd1f644b..d60612ff74 100644
--- a/arch/x86/include/asm/types.h
+++ b/arch/x86/include/asm/types.h
@@ -41,7 +41,7 @@ typedef unsigned int u32;
typedef signed long long s64;
typedef unsigned long long u64;
-#define BITS_PER_LONG 32
+#include <asm-generic/bitsperlong.h>
#endif /* __ASSEMBLY__ */
diff --git a/commands/Kconfig b/commands/Kconfig
index 25c77a85c5..bb6674e6c2 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -1183,6 +1183,7 @@ menu "Network"
config CMD_DHCP
bool
+ select NET_DHCP
prompt "dhcp"
help
DHCP client to obtain IP or boot params
diff --git a/commands/Makefile b/commands/Makefile
index b902f58ec5..36983477be 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -111,3 +111,4 @@ obj-$(CONFIG_CMD_CMP) += cmp.o
obj-$(CONFIG_CMD_NV) += nv.o
obj-$(CONFIG_CMD_DEFAULTENV) += defaultenv.o
obj-$(CONFIG_CMD_STATE) += state.o
+obj-$(CONFIG_CMD_DHCP) += dhcp.o
diff --git a/commands/automount.c b/commands/automount.c
index a29f286b22..b491d203fd 100644
--- a/commands/automount.c
+++ b/commands/automount.c
@@ -70,4 +70,3 @@ BAREBOX_CMD_START(automount)
BAREBOX_CMD_GROUP(CMD_GRP_PART)
BAREBOX_CMD_HELP(cmd_automount_help)
BAREBOX_CMD_END
-
diff --git a/commands/detect.c b/commands/detect.c
index d8e0afc314..1586a6fb54 100644
--- a/commands/detect.c
+++ b/commands/detect.c
@@ -68,10 +68,7 @@ static int do_detect(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
for (i = optind; i < argc; i++) {
- dev = get_device_by_name(argv[i]);
- if (!dev)
- return -ENODEV;
- ret = device_detect(dev);
+ ret = device_detect_by_name(argv[i]);
if (ret && option_error)
return ret;
}
diff --git a/commands/devinfo.c b/commands/devinfo.c
index e61aaa24e8..3c9d6a6b9d 100644
--- a/commands/devinfo.c
+++ b/commands/devinfo.c
@@ -68,11 +68,8 @@ static int do_devinfo(int argc, char *argv[])
}
} else {
dev = get_device_by_name(argv[1]);
-
- if (!dev) {
- printf("no such device: %s\n",argv[1]);
- return -1;
- }
+ if (!dev)
+ return -ENODEV;
if (dev->num_resources)
printf("Resources:\n");
diff --git a/commands/dhcp.c b/commands/dhcp.c
new file mode 100644
index 0000000000..eb98bfc2a7
--- /dev/null
+++ b/commands/dhcp.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 PHYTEC Messtechnik GmbH,
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * Based on work of Sascha Hauer <s.hauer@pengutronix.de>.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <environment.h>
+#include <getopt.h>
+#include <dhcp.h>
+
+static int do_dhcp(int argc, char *argv[])
+{
+ int ret, opt;
+ int retries = DHCP_DEFAULT_RETRY;
+ struct dhcp_req_param dhcp_param;
+
+ memset(&dhcp_param, 0, sizeof(struct dhcp_req_param));
+ getenv_uint("global.dhcp.retries", &retries);
+
+ while ((opt = getopt(argc, argv, "H:v:c:u:U:r:")) > 0) {
+ switch (opt) {
+ case 'H':
+ dhcp_param.hostname = optarg;
+ break;
+ case 'v':
+ dhcp_param.vendor_id = optarg;
+ break;
+ case 'c':
+ dhcp_param.client_id = optarg;
+ break;
+ case 'u':
+ dhcp_param.client_uuid = optarg;
+ break;
+ case 'U':
+ dhcp_param.user_class = optarg;
+ break;
+ case 'r':
+ retries = simple_strtoul(optarg, NULL, 10);
+ break;
+ }
+ }
+
+ if (!retries) {
+ printf("retries is set to zero, set it to %d\n", DHCP_DEFAULT_RETRY);
+ retries = DHCP_DEFAULT_RETRY;
+ }
+
+ ret = dhcp(retries, &dhcp_param);
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(dhcp)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT("-H HOSTNAME", "hostname to send to the DHCP server")
+BAREBOX_CMD_HELP_OPT("-v ID\t", "DHCP Vendor ID (code 60) submitted in DHCP requests")
+BAREBOX_CMD_HELP_OPT("-c ID\t", "DHCP Client ID (code 61) submitted in DHCP requests")
+BAREBOX_CMD_HELP_OPT("-u UUID\t", "DHCP Client UUID (code 97) submitted in DHCP requests")
+BAREBOX_CMD_HELP_OPT("-U CLASS", "DHCP User class (code 77) submitted in DHCP requests")
+BAREBOX_CMD_HELP_OPT("-r RETRY", "retry limit (default 20)");
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(dhcp)
+ .cmd = do_dhcp,
+ BAREBOX_CMD_DESC("DHCP client to obtain IP or boot params")
+ BAREBOX_CMD_OPTS("[-HvcuUr]")
+ BAREBOX_CMD_GROUP(CMD_GRP_NET)
+ BAREBOX_CMD_HELP(cmd_dhcp_help)
+ BAREBOX_CMD_COMPLETE(empty_complete)
+BAREBOX_CMD_END
diff --git a/commands/digest.c b/commands/digest.c
index 340c07a248..4cc615d775 100644
--- a/commands/digest.c
+++ b/commands/digest.c
@@ -68,7 +68,7 @@ err:
return ret;
}
-static void prints_algo_help(void)
+static void __maybe_unused prints_algo_help(void)
{
puts("\navailable algo:\n");
digest_algo_prints("\t");
diff --git a/commands/export.c b/commands/export.c
index 2e8bb49676..4b4cf1e12e 100644
--- a/commands/export.c
+++ b/commands/export.c
@@ -59,4 +59,3 @@ BAREBOX_CMD_START(export)
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_export_help)
BAREBOX_CMD_END
-
diff --git a/commands/false.c b/commands/false.c
index 6ef9af3155..90aa2cc9ea 100644
--- a/commands/false.c
+++ b/commands/false.c
@@ -32,4 +32,3 @@ BAREBOX_CMD_START(false)
BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/commands/help.c b/commands/help.c
index 6e61bde1af..3d36d9bf48 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -148,4 +148,3 @@ BAREBOX_CMD_START(help)
BAREBOX_CMD_HELP(cmd_help_help)
BAREBOX_CMD_COMPLETE(command_complete)
BAREBOX_CMD_END
-
diff --git a/commands/loadb.c b/commands/loadb.c
index 7424bcc08c..be5830da32 100644
--- a/commands/loadb.c
+++ b/commands/loadb.c
@@ -604,9 +604,8 @@ static int do_load_serial_bin(int argc, char *argv[])
ulong offset = 0;
ulong addr;
int load_baudrate = 0, current_baudrate;
- int rcode = 0;
+ int rcode = 0, ret;
int opt;
- int open_mode = O_WRONLY;
char *output_file = NULL;
struct console_device *cdev = NULL;
@@ -621,9 +620,6 @@ static int do_load_serial_bin(int argc, char *argv[])
case 'o':
offset = (int)simple_strtoul(optarg, NULL, 10);
break;
- case 'c':
- open_mode |= O_CREAT;
- break;
default:
perror(argv[0]);
return 1;
@@ -635,7 +631,7 @@ static int do_load_serial_bin(int argc, char *argv[])
printf("%s:No console device with STDIN and STDOUT\n", argv[0]);
return -ENODEV;
}
- current_baudrate = (int)simple_strtoul(dev_get_param(&cdev->class_dev, "baudrate"), NULL, 10);
+ current_baudrate = console_get_baudrate(cdev);
/* Load Defaults */
if (load_baudrate == 0)
@@ -644,7 +640,7 @@ static int do_load_serial_bin(int argc, char *argv[])
output_file = DEF_FILE;
/* File should exist */
- ofd = open(output_file, open_mode);
+ ofd = open(output_file, O_WRONLY | O_CREAT);
if (ofd < 0) {
perror(argv[0]);
return 3;
@@ -660,17 +656,9 @@ static int do_load_serial_bin(int argc, char *argv[])
}
}
- if (load_baudrate != current_baudrate) {
- printf("## Switch baudrate to %d bps and press ENTER ...\n",
- load_baudrate);
- udelay(50000);
- cdev->setbrg(cdev, load_baudrate);
- udelay(50000);
- for (;;) {
- if (getc() == '\r')
- break;
- }
- }
+ ret = console_set_baudrate(cdev, load_baudrate);
+ if (ret)
+ return ret;
printf("## Ready for binary (kermit) download "
"to 0x%08lX offset on %s device at %d bps...\n", offset,
@@ -681,17 +669,9 @@ static int do_load_serial_bin(int argc, char *argv[])
rcode = 1;
}
- if (load_baudrate != current_baudrate) {
- printf("## Switch baudrate to %d bps and press ESC ...\n",
- current_baudrate);
- udelay(50000);
- cdev->setbrg(cdev, current_baudrate);
- udelay(50000);
- for (;;) {
- if (getc() == 0x1B) /* ESC */
- break;
- }
- }
+ ret = console_set_baudrate(cdev, current_baudrate);
+ if (ret)
+ return ret;
close(ofd);
ofd = 0;
@@ -704,7 +684,6 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT("-f FILE", "download to FILE (default image.bin")
BAREBOX_CMD_HELP_OPT("-o OFFS", "destination file OFFSet (default 0)")
BAREBOX_CMD_HELP_OPT("-b BAUD", "baudrate for download (default: console baudrate")
-BAREBOX_CMD_HELP_OPT("-c", "create file if not present")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(loadb)
diff --git a/commands/loadxy.c b/commands/loadxy.c
index 1e65cb6221..a4b1bec94d 100644
--- a/commands/loadxy.c
+++ b/commands/loadxy.c
@@ -40,45 +40,6 @@
#define DEF_FILE "image.bin"
-static int console_change_speed(struct console_device *cdev, int baudrate)
-{
- int current_baudrate;
- const char *bstr;
-
- bstr = dev_get_param(&cdev->class_dev, "baudrate");
- current_baudrate = bstr ? (int)simple_strtoul(bstr, NULL, 10) : 0;
- if (baudrate && baudrate != current_baudrate) {
- printf("## Switch baudrate from %d to %d bps and press ENTER ...\n",
- current_baudrate, baudrate);
- mdelay(50);
- cdev->setbrg(cdev, baudrate);
- mdelay(50);
- }
- return current_baudrate;
-}
-
-static struct console_device *get_named_console(const char *cname)
-{
- struct console_device *cdev;
- const char *target;
-
- /*
- * Assumption to have BOTH CONSOLE_STDIN AND STDOUT in the
- * same output console
- */
- for_each_console(cdev) {
- target = dev_id(&cdev->class_dev);
- if (strlen(target) != strlen(cname))
- continue;
- printf("RJK: looking for %s in console name %s\n",
- cname, target);
- if ((cdev->f_active & (CONSOLE_STDIN | CONSOLE_STDOUT))
- && !strcmp(cname, target))
- return cdev;
- }
- return NULL;
-}
-
/**
* @brief provide the loady(Y-Modem or Y-Modem/G) support
*
@@ -112,7 +73,7 @@ static int do_loady(int argc, char *argv[])
}
if (cname)
- cdev = get_named_console(cname);
+ cdev = console_get_by_name(cname);
else
cdev = console_get_first_active();
if (!cdev) {
@@ -121,7 +82,15 @@ static int do_loady(int argc, char *argv[])
return -ENODEV;
}
- current_baudrate = console_change_speed(cdev, load_baudrate);
+ current_baudrate = console_get_baudrate(cdev);
+
+ if (!load_baudrate)
+ load_baudrate = current_baudrate;
+
+ rc = console_set_baudrate(cdev, load_baudrate);
+ if (rc)
+ return rc;
+
printf("## Ready for binary (ymodem) download at %d bps...\n",
load_baudrate ? load_baudrate : current_baudrate);
@@ -135,7 +104,9 @@ static int do_loady(int argc, char *argv[])
rcode = 1;
}
- console_change_speed(cdev, current_baudrate);
+ rc = console_set_baudrate(cdev, current_baudrate);
+ if (rc)
+ return rc;
return rcode;
}
@@ -167,8 +138,7 @@ BAREBOX_CMD_END
static int do_loadx(int argc, char *argv[])
{
ulong offset = 0;
- int load_baudrate = 0, current_baudrate, ofd, opt, rcode = 0;
- int open_mode = O_WRONLY;
+ int load_baudrate = 0, current_baudrate, rc, ofd, opt, rcode = 0;
char *output_file = NULL, *cname = NULL;
struct console_device *cdev = NULL;
@@ -183,9 +153,6 @@ static int do_loadx(int argc, char *argv[])
case 'o':
offset = (int)simple_strtoul(optarg, NULL, 10);
break;
- case 'c':
- open_mode |= O_CREAT;
- break;
case 't':
cname = optarg;
break;
@@ -196,7 +163,7 @@ static int do_loadx(int argc, char *argv[])
}
if (cname)
- cdev = get_named_console(cname);
+ cdev = console_get_by_name(cname);
else
cdev = console_get_first_active();
if (!cdev) {
@@ -210,7 +177,7 @@ static int do_loadx(int argc, char *argv[])
output_file = DEF_FILE;
/* File should exist */
- ofd = open(output_file, open_mode);
+ ofd = open(output_file, O_WRONLY | O_CREAT);
if (ofd < 0) {
perror(argv[0]);
return 3;
@@ -226,7 +193,15 @@ static int do_loadx(int argc, char *argv[])
}
}
- current_baudrate = console_change_speed(cdev, load_baudrate);
+ current_baudrate = console_get_baudrate(cdev);
+
+ if (!load_baudrate)
+ load_baudrate = current_baudrate;
+
+ rc = console_set_baudrate(cdev, load_baudrate);
+ if (rc)
+ return rc;
+
printf("## Ready for binary (xmodem) download "
"to 0x%08lX offset on %s device at %d bps...\n", offset,
output_file, load_baudrate ? load_baudrate : current_baudrate);
@@ -235,7 +210,10 @@ static int do_loadx(int argc, char *argv[])
printf("## Binary (xmodem) download aborted (%d)\n", rcode);
rcode = 1;
}
- console_change_speed(cdev, current_baudrate);
+
+ rc = console_set_baudrate(cdev, current_baudrate);
+ if (rc)
+ return rc;
return rcode;
}
@@ -246,7 +224,6 @@ BAREBOX_CMD_HELP_OPT("-f FILE", "download to FILE (default image.bin")
BAREBOX_CMD_HELP_OPT("-o OFFS", "destination file OFFSet (default 0)")
BAREBOX_CMD_HELP_OPT("-b BAUD", "baudrate for download (default: console baudrate")
BAREBOX_CMD_HELP_OPT("-t NAME", "console name to use (default: current)")
-BAREBOX_CMD_HELP_OPT("-c", "create file if not present")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(loadx)
diff --git a/commands/login.c b/commands/login.c
index 210eb203ac..bf5085c854 100644
--- a/commands/login.c
+++ b/commands/login.c
@@ -71,7 +71,7 @@ static int do_login(int argc, char *argv[])
run_command(timeout_cmd);
}
- if (check_passwd(passwd, passwd_len))
+ if (check_passwd(passwd, passwd_len) == 1)
return 0;
} while(1);
diff --git a/commands/md.c b/commands/md.c
index 07a03d51f3..c88259a3f8 100644
--- a/commands/md.c
+++ b/commands/md.c
@@ -49,7 +49,7 @@ static int do_mem_md(int argc, char *argv[])
if (argc < 2)
return COMMAND_ERROR_USAGE;
- if (mem_parse_options(argc, argv, "bwls:x", &mode, &filename, NULL,
+ if (mem_parse_options(argc, argv, "bwlqs:x", &mode, &filename, NULL,
&swab) < 0)
return 1;
@@ -105,6 +105,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-s FILE", "display file (default /dev/mem)")
BAREBOX_CMD_HELP_OPT ("-x", "swap bytes at output")
BAREBOX_CMD_HELP_TEXT("")
diff --git a/commands/mem.c b/commands/mem.c
index 568050d34b..23c703f0b5 100644
--- a/commands/mem.c
+++ b/commands/mem.c
@@ -84,6 +84,9 @@ int mem_parse_options(int argc, char *argv[], char *optstr, int *mode,
case 'l':
*mode = O_RWSIZE_4;
break;
+ case 'q':
+ *mode = O_RWSIZE_8;
+ break;
case 's':
*sourcefile = optarg;
break;
diff --git a/commands/memcmp.c b/commands/memcmp.c
index d048150672..e079d5f78e 100644
--- a/commands/memcmp.c
+++ b/commands/memcmp.c
@@ -49,7 +49,7 @@ static int do_memcmp(int argc, char *argv[])
int offset = 0;
struct stat statbuf;
- if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile,
+ if (mem_parse_options(argc, argv, "bwlqs:d:", &mode, &sourcefile,
&destfile, NULL) < 0)
return 1;
@@ -138,6 +138,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-s FILE", "source file (default /dev/mem)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "destination file (default /dev/mem)")
BAREBOX_CMD_HELP_END
diff --git a/commands/memcpy.c b/commands/memcpy.c
index 78716b1bbc..9c8b64525c 100644
--- a/commands/memcpy.c
+++ b/commands/memcpy.c
@@ -47,7 +47,7 @@ static int do_memcpy(int argc, char *argv[])
struct stat statbuf;
int ret = 0;
- if (mem_parse_options(argc, argv, "bwls:d:", &mode, &sourcefile,
+ if (mem_parse_options(argc, argv, "bwlqs:d:", &mode, &sourcefile,
&destfile, NULL) < 0)
return 1;
@@ -135,6 +135,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-s FILE", "source file (default /dev/mem)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "write file (default /dev/mem)")
BAREBOX_CMD_HELP_END
diff --git a/commands/memset.c b/commands/memset.c
index bb5f46de7a..fc5b659b9b 100644
--- a/commands/memset.c
+++ b/commands/memset.c
@@ -44,7 +44,7 @@ static int do_memset(int argc, char *argv[])
int ret = 1;
char *file = "/dev/mem";
- if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &file,
+ if (mem_parse_options(argc, argv, "bwlqd:", &mode, NULL, &file,
NULL) < 0)
return 1;
@@ -92,6 +92,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "write file (default /dev/mem)")
BAREBOX_CMD_HELP_END
diff --git a/commands/memtest.c b/commands/memtest.c
index 9dec0efcba..756123001a 100644
--- a/commands/memtest.c
+++ b/commands/memtest.c
@@ -62,9 +62,11 @@ static int request_memtest_regions(struct list_head *list)
start = PAGE_ALIGN(bank->res->start);
size = PAGE_ALIGN_DOWN(bank->res->end - start + 1);
- ret = alloc_memtest_region(list, start, size);
- if (ret < 0)
- return ret;
+ if (size) {
+ ret = alloc_memtest_region(list, start, size);
+ if (ret < 0)
+ return ret;
+ }
continue;
}
@@ -95,6 +97,8 @@ static int request_memtest_regions(struct list_head *list)
continue;
size = PAGE_ALIGN_DOWN(end - start + 1);
+ if (size == 0)
+ continue;
ret = alloc_memtest_region(list, start, size);
if (ret < 0)
return ret;
@@ -108,7 +112,7 @@ static int request_memtest_regions(struct list_head *list)
start = PAGE_ALIGN(r->end);
end = bank->res->end;
size = PAGE_ALIGN_DOWN(end - start + 1);
- if (start < end && start > r->end) {
+ if (size && start < end && start > r->end) {
ret = alloc_memtest_region(list, start, size);
if (ret < 0)
return ret;
diff --git a/commands/mm.c b/commands/mm.c
index ff2e746670..7c890a6696 100644
--- a/commands/mm.c
+++ b/commands/mm.c
@@ -38,9 +38,10 @@ static int do_mem_mm(int argc, char *argv[])
u8 val8;
u16 val16;
u32 val32;
- u32 value, mask;
+ u64 val64;
+ u64 value, mask;
- if (mem_parse_options(argc, argv, "bwld:", &mode, NULL, &filename,
+ if (mem_parse_options(argc, argv, "bwlqd:", &mode, NULL, &filename,
&swab) < 0)
return 1;
@@ -48,8 +49,8 @@ static int do_mem_mm(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
adr = strtoull_suffix(argv[optind++], NULL, 0);
- value = simple_strtoul(argv[optind++], NULL, 0);
- mask = simple_strtoul(argv[optind++], NULL, 0);
+ value = simple_strtoull(argv[optind++], NULL, 0);
+ mask = simple_strtoull(argv[optind++], NULL, 0);
fd = open_and_lseek(filename, mode | O_RDWR, adr);
if (fd < 0)
@@ -86,6 +87,16 @@ static int do_mem_mm(int argc, char *argv[])
if (ret < 0)
goto out_write;
break;
+ case O_RWSIZE_8:
+ if (ret < 0)
+ goto out_read;
+ ret = pread(fd, &val64, 8, adr);
+ val64 &= ~mask;
+ val64 |= (value & mask);
+ ret = pwrite(fd, &val64, 8, adr);
+ if (ret < 0)
+ goto out_write;
+ break;
}
close(fd);
@@ -110,6 +121,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "write file (default /dev/mem)")
BAREBOX_CMD_HELP_END
diff --git a/commands/mount.c b/commands/mount.c
index 939e9bc853..aa769d46fe 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -79,6 +79,8 @@ static int do_mount(int argc, char *argv[])
if (!strncmp(devstr, "/dev/", 5))
devstr += 5;
+ device_detect_by_name(devstr);
+
cdev = cdev_by_name(devstr);
if (!cdev)
return -ENOENT;
diff --git a/commands/mw.c b/commands/mw.c
index f0384f6435..8ca3c61d7f 100644
--- a/commands/mw.c
+++ b/commands/mw.c
@@ -42,7 +42,7 @@ static int do_mem_mw(int argc, char *argv[])
loff_t adr;
int swab = 0;
- if (mem_parse_options(argc, argv, "bwld:x", &mode, NULL, &filename,
+ if (mem_parse_options(argc, argv, "bwlqd:x", &mode, NULL, &filename,
&swab) < 0)
return 1;
@@ -59,6 +59,7 @@ static int do_mem_mw(int argc, char *argv[])
u8 val8;
u16 val16;
u32 val32;
+ u64 val64;
switch (mode) {
case O_RWSIZE_1:
val8 = simple_strtoul(argv[optind], NULL, 0);
@@ -76,6 +77,12 @@ static int do_mem_mw(int argc, char *argv[])
val32 = __swab32(val32);
ret = write(fd, &val32, 4);
break;
+ case O_RWSIZE_8:
+ val64 = simple_strtoull(argv[optind], NULL, 0);
+ if (swab)
+ val64 = __swab64(val64);
+ ret = write(fd, &val64, 8);
+ break;
}
if (ret < 0) {
perror("write");
@@ -97,6 +104,7 @@ BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-b", "byte access")
BAREBOX_CMD_HELP_OPT ("-w", "word access (16 bit)")
BAREBOX_CMD_HELP_OPT ("-l", "long access (32 bit)")
+BAREBOX_CMD_HELP_OPT ("-q", "quad access (64 bit)")
BAREBOX_CMD_HELP_OPT ("-d FILE", "write file (default /dev/mem)")
BAREBOX_CMD_HELP_END
diff --git a/commands/net.c b/commands/net.c
index 7508c992f2..219c7efcda 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -64,4 +64,3 @@ BAREBOX_CMD_START(ethact)
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END
-
diff --git a/commands/readline.c b/commands/readline.c
index e537498878..b6e0e3e091 100644
--- a/commands/readline.c
+++ b/commands/readline.c
@@ -53,4 +53,3 @@ BAREBOX_CMD_START(readline)
BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
BAREBOX_CMD_HELP(cmd_readline_help)
BAREBOX_CMD_END
-
diff --git a/commands/timeout.c b/commands/timeout.c
index 2b99d4f749..ef1a037c19 100644
--- a/commands/timeout.c
+++ b/commands/timeout.c
@@ -84,4 +84,3 @@ BAREBOX_CMD_START(timeout)
BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
BAREBOX_CMD_HELP(cmd_timeout_help)
BAREBOX_CMD_END
-
diff --git a/commands/trigger.c b/commands/trigger.c
index b605448a91..2758ce74e8 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -105,4 +105,3 @@ BAREBOX_CMD_START(trigger)
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_trigger_help)
BAREBOX_CMD_END
-
diff --git a/commands/true.c b/commands/true.c
index fbb34e7690..24dea46929 100644
--- a/commands/true.c
+++ b/commands/true.c
@@ -32,4 +32,3 @@ BAREBOX_CMD_START(true)
BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/commands/ubi.c b/commands/ubi.c
index 94da799b8c..9463127151 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -179,4 +179,3 @@ BAREBOX_CMD_START(ubirmvol)
BAREBOX_CMD_GROUP(CMD_GRP_PART)
BAREBOX_CMD_HELP(cmd_ubirmvol_help)
BAREBOX_CMD_END
-
diff --git a/commands/ubiformat.c b/commands/ubiformat.c
index df0b801da9..e63f16e351 100644
--- a/commands/ubiformat.c
+++ b/commands/ubiformat.c
@@ -84,7 +84,7 @@ static int parse_opt(int argc, char *argv[])
int key;
unsigned long int image_seq;
- key = getopt(argc, argv, "nyyqve:x:s:O:f:S:");
+ key = getopt(argc, argv, "nyqve:x:s:O:f:S:Q:");
if (key == -1)
break;
diff --git a/commands/version.c b/commands/version.c
index 898c719433..090f2dd136 100644
--- a/commands/version.c
+++ b/commands/version.c
@@ -33,4 +33,3 @@ BAREBOX_CMD_START(version)
BAREBOX_CMD_GROUP(CMD_GRP_INFO)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/common/Kconfig b/common/Kconfig
index 1c5d14c1c0..983d3059fc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -94,6 +94,17 @@ config EFI_DEVICEPATH
config FILE_LIST
bool
+config ARCH_DMA_ADDR_T_64BIT
+ bool
+
+config BAREBOX_UPDATE_IMX_NAND_FCB
+ bool
+ depends on ARCH_IMX6 || ARCH_IMX28
+ depends on BAREBOX_UPDATE
+ depends on MTD_WRITE
+ depends on NAND_MXS
+ default y
+
menu "General Settings"
config LOCALVERSION
@@ -198,6 +209,16 @@ config BAREBOX_MAX_BARE_INIT_SIZE
this will allow your bare_init to fit in SRAM as example
ARCH can overwrite it via ARCH_BAREBOX_MAX_BARE_INIT_SIZE
+config BAREBOX_MAX_PBLX_SIZE
+ depends on PBL_MULTI_IMAGES
+ depends on IMAGE_COMPRESSION
+ prompt "Maximum PBLX size"
+ hex
+ default 0xffffffff
+ help
+ Define the maximum size of the PBLX image.
+ The pblx is a self extracting barebox binary.
+
config HAVE_CONFIGURABLE_MEMORY_LAYOUT
bool
diff --git a/common/Makefile b/common/Makefile
index 2738238c67..74801f7e28 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -52,6 +52,7 @@ lwl-$(CONFIG_IMD) += imd-barebox.o
obj-$(CONFIG_IMD) += imd.o
obj-$(CONFIG_FILE_LIST) += file-list.o
obj-$(CONFIG_FIRMWARE) += firmware.o
+obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/bbu.c b/common/bbu.c
index 7fb154a230..4d71fa4a87 100644
--- a/common/bbu.c
+++ b/common/bbu.c
@@ -20,6 +20,12 @@
#include <linux/list.h>
#include <errno.h>
#include <readkey.h>
+#include <filetype.h>
+#include <libfile.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <linux/stat.h>
static LIST_HEAD(bbu_image_handlers);
@@ -153,3 +159,110 @@ int bbu_register_handler(struct bbu_handler *handler)
return 0;
}
+
+struct bbu_std {
+ struct bbu_handler handler;
+ enum filetype filetype;
+};
+
+static int bbu_std_file_handler(struct bbu_handler *handler,
+ struct bbu_data *data)
+{
+ struct bbu_std *std = container_of(handler, struct bbu_std, handler);
+ int fd, ret;
+ enum filetype filetype;
+ struct stat s;
+ unsigned oflags = O_WRONLY;
+
+ filetype = file_detect_type(data->image, data->len);
+ if (filetype != std->filetype) {
+ if (!bbu_force(data, "incorrect image type. Expected: %s, got %s",
+ file_type_to_string(std->filetype),
+ file_type_to_string(filetype)))
+ return -EINVAL;
+ }
+
+ ret = stat(data->devicefile, &s);
+ if (ret) {
+ oflags |= O_CREAT;
+ } else {
+ if (!S_ISREG(s.st_mode) && s.st_size < data->len) {
+ printf("Image (%lld) is too big for device (%d)\n",
+ s.st_size, data->len);
+ }
+ }
+
+ ret = bbu_confirm(data);
+ if (ret)
+ return ret;
+
+ fd = open(data->devicefile, oflags);
+ if (fd < 0)
+ return fd;
+
+ ret = protect(fd, data->len, 0, 0);
+ if (ret && ret != -ENOSYS) {
+ printf("unprotecting %s failed with %s\n", data->devicefile,
+ strerror(-ret));
+ goto err_close;
+ }
+
+ ret = erase(fd, data->len, 0);
+ if (ret && ret != -ENOSYS) {
+ printf("erasing %s failed with %s\n", data->devicefile,
+ strerror(-ret));
+ goto err_close;
+ }
+
+ ret = write_full(fd, data->image, data->len);
+ if (ret < 0)
+ goto err_close;
+
+ protect(fd, data->len, 0, 1);
+
+ ret = 0;
+
+err_close:
+ close(fd);
+
+ return ret;
+}
+
+/**
+ * bbu_register_std_file_update() - register a barebox update handler for a
+ * standard file-to-device-copy operation
+ * @name: Name of the handler
+ * @flags: BBU_HANDLER_FLAG_* flags
+ * @devicefile: the file to write the update image to
+ * @imagetype: The filetype that the update image must have
+ *
+ * This update handler us suitable for a standard file-to-device copy operation.
+ * The handler checks for a filetype and unprotects/erases the device if
+ * necessary. If devicefile belongs to a device then the device is checkd for
+ * enough space before touching it.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype)
+{
+ struct bbu_std *std;
+ struct bbu_handler *handler;
+ int ret;
+
+ std = xzalloc(sizeof(*std));
+ std->filetype = imagetype;
+
+ handler = &std->handler;
+
+ handler->flags = flags;
+ handler->devicefile = devicefile;
+ handler->name = name;
+ handler->handler = bbu_std_file_handler;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(std);
+
+ return ret;
+}
diff --git a/common/blspec.c b/common/blspec.c
index 3506388eb5..7e84ff3cec 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -30,6 +30,7 @@
#include <of.h>
#include <linux/stat.h>
#include <linux/err.h>
+#include <mtd/ubi-user.h>
/*
* blspec_entry_var_set - set a variable to a value
@@ -436,6 +437,35 @@ err_out:
}
/*
+ * blspec_scan_ubi - scan over a cdev containing UBI volumes
+ *
+ * This function attaches a cdev as UBI devices and collects all blspec
+ * entries found in the UBI volumes
+ *
+ * returns the number of entries found or a negative error code if some unexpected
+ * error occured.
+ */
+static int blspec_scan_ubi(struct blspec *blspec, struct cdev *cdev)
+{
+ struct device_d *child;
+ int ret, found = 0;
+
+ pr_debug("%s: %s\n", __func__, cdev->name);
+
+ ret = ubi_attach_mtd_dev(cdev->mtd, UBI_DEV_NUM_AUTO, 0, 20);
+ if (ret && ret != -EEXIST)
+ return 0;
+
+ device_for_each_child(cdev->dev, child) {
+ ret = blspec_scan_device(blspec, child);
+ if (ret > 0)
+ found += ret;
+ }
+
+ return found;
+}
+
+/*
* blspec_scan_cdev - scan over a cdev
*
* Given a cdev this function mounts the filesystem and collects all blspec
@@ -446,9 +476,9 @@ err_out:
*/
static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
{
- int ret;
+ int ret, found = 0;
void *buf = xzalloc(512);
- enum filetype type;
+ enum filetype type, filetype;
const char *rootpath;
pr_debug("%s: %s\n", __func__, cdev->name);
@@ -460,16 +490,26 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
}
type = file_detect_partition_table(buf, 512);
+ filetype = file_detect_type(buf, 512);
free(buf);
if (type == filetype_mbr || type == filetype_gpt)
return -EINVAL;
+ if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
+ ret = blspec_scan_ubi(blspec, cdev);
+ if (ret > 0)
+ found += ret;
+ }
+
rootpath = cdev_mount_default(cdev, NULL);
- if (IS_ERR(rootpath))
- return PTR_ERR(rootpath);
+ if (!IS_ERR(rootpath)) {
+ ret = blspec_scan_directory(blspec, rootpath);
+ if (ret > 0)
+ found += ret;
+ }
- return blspec_scan_directory(blspec, rootpath);
+ return found;
}
/*
@@ -575,17 +615,10 @@ int blspec_scan_devicename(struct blspec *blspec, const char *devname)
{
struct device_d *dev;
struct cdev *cdev;
- const char *colon;
pr_debug("%s: %s\n", __func__, devname);
- colon = strchr(devname, '.');
- if (colon) {
- char *name = xstrdup(devname);
- *strchr(name, '.') = 0;
- device_detect_by_name(name);
- free(name);
- }
+ device_detect_by_name(devname);
cdev = cdev_by_name(devname);
if (cdev) {
diff --git a/common/bootsource.c b/common/bootsource.c
index 7f3d51fb75..707b07924c 100644
--- a/common/bootsource.c
+++ b/common/bootsource.c
@@ -35,6 +35,7 @@ static const char *bootsource_str[] = {
[BOOTSOURCE_ONENAND] = "onenand",
[BOOTSOURCE_HD] = "harddisk",
[BOOTSOURCE_USB] = "usb",
+ [BOOTSOURCE_NET] = "net",
};
static enum bootsource bootsource = BOOTSOURCE_UNKNOWN;
diff --git a/common/complete.c b/common/complete.c
index 5b71f03cf8..f0ef576401 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -466,4 +466,3 @@ int complete(char *instr, char **outstr)
return reprint;
}
-
diff --git a/common/console.c b/common/console.c
index 0c32f06b93..0a6fc3e9bf 100644
--- a/common/console.c
+++ b/common/console.c
@@ -58,32 +58,14 @@ static struct kfifo __console_output_fifo;
static struct kfifo *console_input_fifo = &__console_input_fifo;
static struct kfifo *console_output_fifo = &__console_output_fifo;
-static int console_std_set(struct device_d *dev, struct param_d *param,
- const char *val)
+int console_set_active(struct console_device *cdev, unsigned flag)
{
- struct console_device *cdev = to_console_dev(dev);
- char active[4];
- unsigned int flag = 0, i = 0;
- int ret;
-
- if (val) {
- if (strchr(val, 'i') && cdev->getc) {
- active[i++] = 'i';
- flag |= CONSOLE_STDIN;
- }
+ int ret, i;
- if (cdev->putc) {
- if (strchr(val, 'o')) {
- active[i++] = 'o';
- flag |= CONSOLE_STDOUT;
- }
-
- if (strchr(val, 'e')) {
- active[i++] = 'e';
- flag |= CONSOLE_STDERR;
- }
- }
- }
+ if (!cdev->getc)
+ flag &= ~CONSOLE_STDIN;
+ if (!cdev->putc)
+ flag &= ~(CONSOLE_STDOUT | CONSOLE_STDERR);
if (flag && !cdev->f_active) {
/* The device is being activated, set its baudrate */
@@ -97,16 +79,25 @@ static int console_std_set(struct device_d *dev, struct param_d *param,
return ret;
}
- active[i] = 0;
cdev->f_active = flag;
- dev_param_set_generic(dev, param, active);
+ if (IS_ENABLED(CONFIG_PARAMETER)) {
+ i = 0;
+
+ if (flag & CONSOLE_STDIN)
+ cdev->active[i++] = 'i';
+ if (flag & CONSOLE_STDOUT)
+ cdev->active[i++] = 'o';
+ if (flag & CONSOLE_STDERR)
+ cdev->active[i++] = 'e';
+ cdev->active[i] = 0;
+ }
if (initialized < CONSOLE_INIT_FULL) {
char ch;
initialized = CONSOLE_INIT_FULL;
puts_ll("Switch to console [");
- puts_ll(dev_name(dev));
+ puts_ll(dev_name(&cdev->class_dev));
puts_ll("]\n");
barebox_banner();
while (kfifo_getc(console_output_fifo, &ch) == 0)
@@ -116,29 +107,87 @@ static int console_std_set(struct device_d *dev, struct param_d *param,
return 0;
}
-static int console_baudrate_set(struct param_d *param, void *priv)
+unsigned console_get_active(struct console_device *cdev)
{
- struct console_device *cdev = priv;
+ return cdev->f_active;
+}
+
+static int console_active_set(struct device_d *dev, struct param_d *param,
+ const char *val)
+{
+ struct console_device *cdev = to_console_dev(dev);
+ unsigned int flag = 0;
+
+ if (val) {
+ if (strchr(val, 'i'))
+ flag |= CONSOLE_STDIN;
+ if (strchr(val, 'o'))
+ flag |= CONSOLE_STDOUT;
+ if (strchr(val, 'e'))
+ flag |= CONSOLE_STDERR;
+ }
+
+ return console_set_active(cdev, flag);
+}
+
+static const char *console_active_get(struct device_d *dev,
+ struct param_d *param)
+{
+ struct console_device *cdev = to_console_dev(dev);
+
+ return cdev->active;
+}
+
+int console_set_baudrate(struct console_device *cdev, unsigned baudrate)
+{
+ int ret;
unsigned char c;
+ if (!cdev->setbrg)
+ return -ENOSYS;
+
+ if (cdev->baudrate == baudrate)
+ return 0;
+
/*
* If the device is already active, change its baudrate.
* The baudrate of an inactive device will be set at activation time.
*/
if (cdev->f_active) {
- printf("## Switch baudrate to %d bps and press ENTER ...\n",
- cdev->baudrate);
+ printf("## Switch baudrate on console %s to %d bps and press ENTER ...\n",
+ dev_name(&cdev->class_dev), baudrate);
mdelay(50);
- cdev->setbrg(cdev, cdev->baudrate);
+ }
+
+ ret = cdev->setbrg(cdev, baudrate);
+ if (ret)
+ return ret;
+
+ if (cdev->f_active) {
mdelay(50);
do {
c = getc();
} while (c != '\r' && c != '\n');
}
+ cdev->baudrate = baudrate;
+ cdev->baudrate_param = baudrate;
+
return 0;
}
+unsigned console_get_baudrate(struct console_device *cdev)
+{
+ return cdev->baudrate;
+}
+
+static int console_baudrate_set(struct param_d *param, void *priv)
+{
+ struct console_device *cdev = priv;
+
+ return console_set_baudrate(cdev, cdev->baudrate_param);
+}
+
static void console_init_early(void)
{
kfifo_init(console_input_fifo, console_input_buffer,
@@ -208,13 +257,13 @@ int console_register(struct console_device *newcdev)
if (newcdev->setbrg) {
newcdev->baudrate = CONFIG_BAUDRATE;
dev_add_param_int(dev, "baudrate", console_baudrate_set,
- NULL, &newcdev->baudrate, "%u", newcdev);
+ NULL, &newcdev->baudrate_param, "%u", newcdev);
}
if (newcdev->putc && !newcdev->puts)
newcdev->puts = __console_puts;
- dev_add_param(dev, "active", console_std_set, NULL, 0);
+ dev_add_param(dev, "active", console_active_set, console_active_get, 0);
if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) {
if (list_empty(&console_list))
@@ -230,12 +279,9 @@ int console_register(struct console_device *newcdev)
list_add_tail(&newcdev->list, &console_list);
- if (activate) {
- if (IS_ENABLED(CONFIG_PARAMETER))
- dev_set_param(dev, "active", "ioe");
- else
- console_std_set(dev, NULL, "ioe");
- }
+ if (activate)
+ console_set_active(newcdev, CONSOLE_STDIN |
+ CONSOLE_STDOUT | CONSOLE_STDERR);
return 0;
}
diff --git a/common/console_common.c b/common/console_common.c
index 41a6929dba..2c82c6fd46 100644
--- a/common/console_common.c
+++ b/common/console_common.c
@@ -106,15 +106,23 @@ static void pr_puts(int level, const char *str)
log_clean(barebox_log_max_messages - 1);
if (barebox_log_max_messages >= 0) {
- log = xzalloc(sizeof(*log));
- log->msg = xstrdup(str);
+ log = malloc(sizeof(*log));
+ if (!log)
+ goto nolog;
+
+ log->msg = strdup(str);
+ if (!log->msg) {
+ free(log);
+ goto nolog;
+ }
+
log->timestamp = get_time_ns();
log->level = level;
list_add_tail(&log->list, &barebox_logbuf);
barebox_logbuf_num_messages++;
}
}
-
+nolog:
if (level > barebox_loglevel)
return;
@@ -260,6 +268,19 @@ struct console_device *console_get_by_dev(struct device_d *dev)
}
EXPORT_SYMBOL(console_get_by_dev);
+struct console_device *console_get_by_name(const char *name)
+{
+ struct console_device *cdev;
+
+ for_each_console(cdev) {
+ if (!strcmp(cdev->devname, name))
+ return cdev;
+ }
+
+ return NULL;
+}
+EXPORT_SYMBOL(console_get_by_name);
+
/*
* @brief returns current used console device
*
diff --git a/common/filetype.c b/common/filetype.c
index 25d97614e4..28a4b2ca25 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -60,6 +60,7 @@ static const struct filetype_str filetype_str[] = {
"TI OMAP CH boot image (big endian)", "ch-image-be" },
[filetype_xz_compressed] = { "XZ compressed", "xz" },
[filetype_exe] = { "MS-DOS executable", "exe" },
+ [filetype_mxs_bootstream] = { "Freescale MXS bootstream", "mxsbs" },
};
const char *file_type_to_string(enum filetype f)
@@ -292,6 +293,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (buf8[0] == 'M' && buf8[1] == 'Z')
return filetype_exe;
+ if (le32_to_cpu(buf[5]) == 0x504d5453)
+ return filetype_mxs_bootstream;
if (is_barebox_arm_head(_buf))
return filetype_arm_barebox;
diff --git a/arch/arm/mach-imx/imx6-bbu-nand.c b/common/imx-bbu-nand-fcb.c
index d2bfedbad5..22031f5b7f 100644
--- a/arch/arm/mach-imx/imx6-bbu-nand.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -17,7 +17,7 @@
*
*/
-#define pr_fmt(fmt) "imx6-bbu-nand: " fmt
+#define pr_fmt(fmt) "imx-bbu-nand-fcb: " fmt
#include <filetype.h>
#include <common.h>
@@ -28,17 +28,17 @@
#include <linux/sizes.h>
#include <bbu.h>
#include <fs.h>
-#include <mach/bbu.h>
#include <linux/mtd/mtd-abi.h>
#include <linux/mtd/nand_mxs.h>
#include <linux/mtd/mtd.h>
#include <linux/stat.h>
+#include <io.h>
struct dbbt_block {
uint32_t Checksum;
uint32_t FingerPrint;
uint32_t Version;
- uint32_t reserved;
+ uint32_t numberBB; /* reserved on i.MX6 */
uint32_t DBBTNumOfPages;
};
@@ -102,6 +102,16 @@ struct fcb_block {
uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
};
+struct imx_nand_fcb_bbu_handler {
+ struct bbu_handler handler;
+
+ void (*fcb_create)(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd);
+ void (*dbbt_create)(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct dbbt_block *dbbt, int num_bad_blocks);
+ enum filetype filetype;
+};
+
#define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
#define GETBIT(v,n) (((v) >> (n)) & 0x1)
@@ -228,7 +238,8 @@ static ssize_t raw_write_page(struct mtd_info *mtd, void *buf, loff_t offset)
return ret;
}
-static int fcb_create(struct fcb_block *fcb, struct mtd_info *mtd)
+static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
{
fcb->FingerPrint = 0x20424346;
fcb->Version = 0x01000000;
@@ -241,42 +252,37 @@ static int fcb_create(struct fcb_block *fcb, struct mtd_info *mtd)
mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1;
fcb->EccBlockNEccType = fcb->EccBlock0EccType;
- /* Also hardcoded in kobs-ng */
- fcb->DataSetup = 80;
- fcb->DataHold = 60;
- fcb->AddressSetup = 25;
- fcb->DSAMPLE_TIME = 6;
- fcb->MetadataBytes = 0x0000000a;
fcb->EccBlock0Size = 0x00000200;
fcb->EccBlockNSize = 0x00000200;
fcb->NumEccBlocksPerPage = mtd->writesize / fcb->EccBlock0Size - 1;
- /* DBBT search area starts at third block */
- fcb->DBBTSearchAreaStartAddress = mtd->erasesize / mtd->writesize * 2;
+ /* DBBT search area starts at second page on first block */
+ fcb->DBBTSearchAreaStartAddress = 1;
fcb->BadBlockMarkerByte = mxs_nand_mark_byte_offset(mtd);
fcb->BadBlockMarkerStartBit = mxs_nand_mark_bit_offset(mtd);
fcb->BBMarkerPhysicalOffset = mtd->writesize;
+ imx_handler->fcb_create(imx_handler, fcb, mtd);
+
fcb->Checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
return 0;
}
-static int imx6_bbu_erase(struct mtd_info *mtd)
+static int imx_bbu_erase(struct mtd_info *mtd)
{
uint64_t offset = 0;
- int len = SZ_2M;
struct erase_info erase;
int ret;
- while (len > 0) {
+ while (offset < mtd->size) {
pr_debug("erasing at 0x%08llx\n", offset);
if (mtd_block_isbad(mtd, offset)) {
- offset += mtd->erasesize;
pr_debug("erase skip block @ 0x%08llx\n", offset);
+ offset += mtd->erasesize;
continue;
}
@@ -289,13 +295,13 @@ static int imx6_bbu_erase(struct mtd_info *mtd)
return ret;
offset += mtd->erasesize;
- len -= mtd->erasesize;
}
return 0;
}
-static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, size_t len)
+static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned block,
+ unsigned num_blocks, void *buf, size_t len)
{
uint64_t offset = block * mtd->erasesize;
int ret;
@@ -304,13 +310,16 @@ static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, s
while (len > 0) {
int now = min(len, mtd->erasesize);
+ if (!num_blocks)
+ return -ENOSPC;
+
pr_debug("writing %p at 0x%08llx, left 0x%08x\n",
buf, offset, len);
if (mtd_block_isbad(mtd, offset)) {
+ pr_debug("write skip block @ 0x%08llx\n", offset);
offset += mtd->erasesize;
block++;
- pr_debug("write skip block @ 0x%08llx\n", offset);
continue;
}
@@ -322,6 +331,7 @@ static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, s
len -= now;
buf += now;
block++;
+ num_blocks--;
}
return block;
@@ -348,35 +358,40 @@ static int dbbt_data_create(struct mtd_info *mtd, void *buf, int block_last)
return n_bad_blocks;
}
-static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *data)
+static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *data)
{
+ struct imx_nand_fcb_bbu_handler *imx_handler =
+ container_of(handler, struct imx_nand_fcb_bbu_handler, handler);
struct cdev *bcb_cdev;
struct mtd_info *mtd;
- int ret, block_fw1, block_fw2, block_last;
+ int ret, block_fw1, block_fw2;
struct fcb_block *fcb;
struct dbbt_block *dbbt;
void *fcb_raw_page, *dbbt_page, *dbbt_data_page;
void *ecc;
int written;
void *fw;
- unsigned fw_size;
+ unsigned fw_size, partition_size;
int i;
+ enum filetype filetype;
+ unsigned num_blocks_fcb_dbbt, num_blocks, num_blocks_fw;
- if (file_detect_type(data->image, data->len) != filetype_arm_barebox &&
- !bbu_force(data, "Not an ARM barebox image"))
- return -EINVAL;
+ filetype = file_detect_type(data->image, data->len);
- ret = bbu_confirm(data);
- if (ret)
- return ret;
+ if (filetype != imx_handler->filetype &&
+ !bbu_force(data, "Image is not of type %s but of type %s",
+ file_type_to_string(imx_handler->filetype),
+ file_type_to_string(filetype)))
+ return -EINVAL;
- bcb_cdev = cdev_by_name("nand0");
+ bcb_cdev = cdev_by_name(handler->devicefile);
if (!bcb_cdev) {
pr_err("%s: No FCB device!\n", __func__);
return -ENODEV;
}
mtd = bcb_cdev->mtd;
+ partition_size = mtd->size;
fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
@@ -396,30 +411,45 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
fw = xzalloc(fw_size);
memcpy(fw, data->image, data->len);
- block_fw1 = 4;
+ num_blocks_fcb_dbbt = 4;
+ num_blocks = partition_size / mtd->erasesize;
+ num_blocks_fw = (num_blocks - num_blocks_fcb_dbbt) / 2;
+
+ block_fw1 = num_blocks_fcb_dbbt;
+ block_fw2 = num_blocks_fcb_dbbt + num_blocks_fw;
+
+ pr_info("writing first firmware to block %d (ofs 0x%08x)\n",
+ block_fw1, block_fw1 * mtd->erasesize);
+ pr_info("writing second firmware to block %d (ofs 0x%08x)\n",
+ block_fw2, block_fw2 * mtd->erasesize);
+ pr_info("maximum size per firmware: 0x%08x bytes\n",
+ num_blocks_fw * mtd->erasesize);
- ret = imx6_bbu_erase(mtd);
+ if (num_blocks_fw * mtd->erasesize < fw_size)
+ return -ENOSPC;
+
+ ret = bbu_confirm(data);
if (ret)
goto out;
- ret = imx6_bbu_write_firmware(mtd, block_fw1, fw, fw_size);
- if (ret < 0)
+ ret = imx_bbu_erase(mtd);
+ if (ret)
goto out;
- block_fw2 = ret;
-
- ret = imx6_bbu_write_firmware(mtd, block_fw2, fw, fw_size);
+ ret = imx_bbu_write_firmware(mtd, block_fw1, num_blocks_fw, fw, fw_size);
if (ret < 0)
goto out;
- block_last = ret;
+ ret = imx_bbu_write_firmware(mtd, block_fw2, num_blocks_fw, fw, fw_size);
+ if (ret < 0)
+ goto out;
fcb->Firmware1_startingPage = block_fw1 * mtd->erasesize / mtd->writesize;
fcb->Firmware2_startingPage = block_fw2 * mtd->erasesize / mtd->writesize;
fcb->PagesInFirmware1 = ALIGN(data->len, mtd->writesize) / mtd->writesize;
fcb->PagesInFirmware2 = fcb->PagesInFirmware1;
- fcb_create(fcb, mtd);
+ fcb_create(imx_handler, fcb, mtd);
encode_hamming_13_8(fcb, ecc, 512);
/*
@@ -431,10 +461,6 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
*/
memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
- ret = raw_write_page(mtd, fcb_raw_page, 0);
- if (ret)
- goto out;
-
ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize);
if (ret)
goto out;
@@ -443,21 +469,29 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
dbbt->FingerPrint = 0x54424244;
dbbt->Version = 0x01000000;
- ret = dbbt_data_create(mtd, dbbt_data_page, block_last);
+ ret = dbbt_data_create(mtd, dbbt_data_page, block_fw2 + num_blocks_fw);
if (ret < 0)
goto out;
- if (ret > 0)
+ if (ret > 0) {
dbbt->DBBTNumOfPages = 1;
+ if (imx_handler->dbbt_create)
+ imx_handler->dbbt_create(imx_handler, dbbt, ret);
+ }
- for (i = 2; i < 4; i++) {
- ret = mtd_write(mtd, mtd->erasesize * i, 2048, &written, dbbt_page);
+ for (i = 0; i < 4; i++) {
+ ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize * i);
+ if (ret)
+ goto out;
+
+ ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
+ mtd->writesize, &written, dbbt_page);
if (ret)
goto out;
if (dbbt->DBBTNumOfPages > 0) {
- ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize * 4,
- 2048, &written, dbbt_data_page);
+ ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize * 5,
+ mtd->writesize, &written, dbbt_data_page);
if (ret)
goto out;
}
@@ -472,16 +506,127 @@ out:
return ret;
}
+static void imx6_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
+{
+ /* Also hardcoded in kobs-ng */
+ fcb->DataSetup = 80;
+ fcb->DataHold = 60;
+ fcb->AddressSetup = 25;
+ fcb->DSAMPLE_TIME = 6;
+ fcb->MetadataBytes = 10;
+}
+
int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
{
+ struct imx_nand_fcb_bbu_handler *imx_handler;
struct bbu_handler *handler;
int ret;
- handler = xzalloc(sizeof(*handler));
- handler->devicefile = "/dev/nand0";
+ imx_handler = xzalloc(sizeof(*imx_handler));
+ imx_handler->fcb_create = imx6_fcb_create;
+ imx_handler->filetype = filetype_arm_barebox;
+
+ handler = &imx_handler->handler;
+ handler->devicefile = "nand0.barebox";
+ handler->name = name;
+ handler->flags = flags;
+ handler->handler = imx_bbu_nand_update;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(handler);
+
+ return ret;
+}
+
+#ifdef CONFIG_ARCH_IMX28
+#include <mach/imx28-regs.h>
+
+#define GPMI_TIMING0 0x00000070
+#define GPMI_TIMING0_ADDRESS_SETUP_MASK (0xff << 16)
+#define GPMI_TIMING0_ADDRESS_SETUP_OFFSET 16
+#define GPMI_TIMING0_DATA_HOLD_MASK (0xff << 8)
+#define GPMI_TIMING0_DATA_HOLD_OFFSET 8
+#define GPMI_TIMING0_DATA_SETUP_MASK 0xff
+#define GPMI_TIMING0_DATA_SETUP_OFFSET 0
+
+#define GPMI_TIMING1 0x00000080
+
+#define BCH_MODE 0x00000020
+
+#define BCH_FLASH0LAYOUT0 0x00000080
+#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24)
+#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
+#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
+#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
+#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12)
+#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12
+#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
+
+#define BCH_FLASH0LAYOUT1 0x00000090
+#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
+#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
+#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12)
+#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12
+#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
+
+static void imx28_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
+{
+ u32 fl0, fl1, t0;
+ void __iomem *bch_regs = (void *)MXS_BCH_BASE;
+ void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE;
+
+ fl0 = readl(bch_regs + BCH_FLASH0LAYOUT0);
+ fl1 = readl(bch_regs + BCH_FLASH0LAYOUT1);
+ t0 = readl(gpmi_regs + GPMI_TIMING0);
+
+ fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->DataSetup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP);
+ fcb->DataHold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD);
+ fcb->AddressSetup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP);
+ fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->NumEccBlocksPerPage = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+ fcb->EraseThreshold = readl(bch_regs + BCH_MODE);
+}
+
+static void imx28_dbbt_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct dbbt_block *dbbt, int num_bad_blocks)
+{
+ uint32_t a = 0;
+ uint8_t *p = (void *)dbbt;
+ int i;
+
+ dbbt->numberBB = num_bad_blocks;
+
+ for (i = 4; i < 512; i++)
+ a += p[i];
+
+ a ^= 0xffffffff;
+
+ dbbt->Checksum = a;
+}
+
+int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ struct imx_nand_fcb_bbu_handler *imx_handler;
+ struct bbu_handler *handler;
+ int ret;
+
+ imx_handler = xzalloc(sizeof(*imx_handler));
+ imx_handler->fcb_create = imx28_fcb_create;
+ imx_handler->dbbt_create = imx28_dbbt_create;
+
+ imx_handler->filetype = filetype_mxs_bootstream;
+
+ handler = &imx_handler->handler;
+ handler->devicefile = "nand0.barebox";
handler->name = name;
handler->flags = flags;
- handler->handler = imx6_bbu_nand_update;
+ handler->handler = imx_bbu_nand_update;
ret = bbu_register_handler(handler);
if (ret)
@@ -489,3 +634,4 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
return ret;
}
+#endif
diff --git a/common/kallsyms.c b/common/kallsyms.c
index 53e22cdc73..e15dec5dfc 100644
--- a/common/kallsyms.c
+++ b/common/kallsyms.c
@@ -212,4 +212,3 @@ int sprint_symbol(char *buffer, unsigned long address)
return len;
}
EXPORT_SYMBOL_GPL(sprint_symbol);
-
diff --git a/common/memory_display.c b/common/memory_display.c
index 7b1d35ec4b..ea91985e5d 100644
--- a/common/memory_display.c
+++ b/common/memory_display.c
@@ -6,8 +6,8 @@
int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int swab)
{
- ulong linebytes, i;
- u_char *cp;
+ unsigned long linebytes, i;
+ unsigned char *cp;
/* Print the lines.
*
@@ -15,20 +15,34 @@ int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int
* once, and all accesses are with the specified bus width.
*/
do {
- char linebuf[DISP_LINE_LEN];
- uint32_t *uip = (uint *)linebuf;
- uint16_t *usp = (ushort *)linebuf;
- uint8_t *ucp = (u_char *)linebuf;
+ unsigned char linebuf[DISP_LINE_LEN];
+ uint64_t *ullp = (uint64_t *)linebuf;
+ uint32_t *uip = (uint32_t *)linebuf;
+ uint16_t *usp = (uint16_t *)linebuf;
+ uint8_t *ucp = (uint8_t *)linebuf;
unsigned count = 52;
printf("%08llx:", offs);
linebytes = (nbytes > DISP_LINE_LEN) ? DISP_LINE_LEN : nbytes;
for (i = 0; i < linebytes; i += size) {
- if (size == 4) {
- u32 res;
+ if (size == 8) {
+ uint64_t res;
data_abort_mask();
- res = *((uint *)addr);
+ res = *((uint64_t *)addr);
+ if (swab)
+ res = __swab64(res);
+ if (data_abort_unmask()) {
+ res = 0xffffffffffffffffULL;
+ count -= printf(" xxxxxxxxxxxxxxxx");
+ } else {
+ count -= printf(" %016llx", res);
+ }
+ *ullp++ = res;
+ } else if (size == 4) {
+ uint32_t res;
+ data_abort_mask();
+ res = *((uint32_t *)addr);
if (swab)
res = __swab32(res);
if (data_abort_unmask()) {
@@ -39,9 +53,9 @@ int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int
}
*uip++ = res;
} else if (size == 2) {
- u16 res;
+ uint16_t res;
data_abort_mask();
- res = *((ushort *)addr);
+ res = *((uint16_t *)addr);
if (swab)
res = __swab16(res);
if (data_abort_unmask()) {
@@ -52,9 +66,9 @@ int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int
}
*usp++ = res;
} else {
- u8 res;
+ uint8_t res;
data_abort_mask();
- res = *((u_char *)addr);
+ res = *((uint8_t *)addr);
if (data_abort_unmask()) {
res = 0xff;
count -= printf(" xx");
@@ -70,7 +84,7 @@ int memory_display(const void *addr, loff_t offs, unsigned nbytes, int size, int
while (count--)
putchar(' ');
- cp = (uint8_t *)linebuf;
+ cp = linebuf;
for (i = 0; i < linebytes; i++) {
if ((*cp < 0x20) || (*cp > 0x7e))
putchar('.');
diff --git a/common/memtest.c b/common/memtest.c
index 25a97d845c..d8d1154c8b 100644
--- a/common/memtest.c
+++ b/common/memtest.c
@@ -28,35 +28,33 @@
#include <errno.h>
#include <memtest.h>
-static const resource_size_t bitpattern[] = {
- 0x00000001, /* single bit */
- 0x00000003, /* two adjacent bits */
- 0x00000007, /* three adjacent bits */
- 0x0000000F, /* four adjacent bits */
- 0x00000005, /* two non-adjacent bits */
- 0x00000015, /* three non-adjacent bits */
- 0x00000055, /* four non-adjacent bits */
- 0xAAAAAAAA, /* alternating 1/0 */
-};
+static void mem_test_report_failure(const char *failure_description,
+ resource_size_t expected_value,
+ resource_size_t actual_value,
+ volatile resource_size_t *address)
+{
+ printf("FAILURE (%s): "
+ "expected 0x%08x, actual 0x%08x at address 0x%08x.\n",
+ failure_description, expected_value, actual_value,
+ (resource_size_t)address);
+}
-/*
- * Perform a memory test. The complete test
- * loops until interrupted by ctrl-c.
- *
- * Prameters:
- * start: start address for memory test.
- * end: end address of memory test.
- * bus_only: skip integrity check and do only a address/data bus
- * testing.
- *
- * Return value can be -EINVAL for invalid parameter or -EINTR
- * if memory test was interrupted.
- */
-int mem_test(resource_size_t _start,
- resource_size_t _end, int bus_only)
+int mem_test_bus_integrity(resource_size_t _start,
+ resource_size_t _end)
{
- volatile resource_size_t *start, *dummy, val, readback, offset,
- offset2, pattern, temp, anti_pattern, num_words;
+ static const resource_size_t bitpattern[] = {
+ 0x00000001, /* single bit */
+ 0x00000003, /* two adjacent bits */
+ 0x00000007, /* three adjacent bits */
+ 0x0000000F, /* four adjacent bits */
+ 0x00000005, /* two non-adjacent bits */
+ 0x00000015, /* three non-adjacent bits */
+ 0x00000055, /* four non-adjacent bits */
+ 0xAAAAAAAA, /* alternating 1/0 */
+ };
+
+ volatile resource_size_t *start, *dummy, num_words, val, readback, offset,
+ offset2, pattern, temp, anti_pattern;
int i;
_start = ALIGN(_start, sizeof(resource_size_t));
@@ -66,7 +64,7 @@ int mem_test(resource_size_t _start,
return -EINVAL;
start = (resource_size_t *)_start;
- /*
+ /*
* Point the dummy to start[1]
*/
dummy = start + 1;
@@ -91,8 +89,7 @@ int mem_test(resource_size_t _start,
* '0's and '0' bits through a field of '1's (i.e.
* pattern and ~pattern).
*/
- for (i = 0; i < ARRAY_SIZE(bitpattern)/
- sizeof(resource_size_t); i++) {
+ for (i = 0; i < ARRAY_SIZE(bitpattern); i++) {
val = bitpattern[i];
for (; val != 0; val <<= 1) {
@@ -101,9 +98,8 @@ int mem_test(resource_size_t _start,
*dummy = ~val;
readback = *start;
if (readback != val) {
- printf("FAILURE (data line): "
- "expected 0x%08x, actual 0x%08x at address 0x%08x.\n",
- val, readback, (resource_size_t)start);
+ mem_test_report_failure("data line",
+ val, readback, start);
return -EIO;
}
@@ -111,10 +107,8 @@ int mem_test(resource_size_t _start,
*dummy = val;
readback = *start;
if (readback != ~val) {
- printf("FAILURE (data line): "
- "Is 0x%08x, should be 0x%08x at address 0x%08x.\n",
- readback,
- ~val, (resource_size_t)start);
+ mem_test_report_failure("data line",
+ ~val, readback, start);
return -EIO;
}
}
@@ -171,6 +165,15 @@ int mem_test(resource_size_t _start,
for (offset = 1; offset <= num_words; offset <<= 1)
start[offset] = pattern;
+ /*
+ * Now write anti-pattern at offset 0. If during the previous
+ * step one of the address lines got stuck high this
+ * operation would result in a memory cell at power-of-two
+ * offset being set to anti-pattern which hopefully would be
+ * detected byt the loop that follows.
+ */
+ start[0] = anti_pattern;
+
printf("Check for address bits stuck high.\n");
/*
@@ -179,15 +182,17 @@ int mem_test(resource_size_t _start,
for (offset = 1; offset <= num_words; offset <<= 1) {
temp = start[offset];
if (temp != pattern) {
- printf("FAILURE: Address bit "
- "stuck high @ 0x%08x:"
- " expected 0x%08x, actual 0x%08x.\n",
- (resource_size_t)&start[offset],
- pattern, temp);
+ mem_test_report_failure("address bit stuck high",
+ pattern, temp, &start[offset]);
return -EIO;
}
}
+ /*
+ Restore original value
+ */
+ start[0] = pattern;
+
printf("Check for address bits stuck "
"low or shorted.\n");
@@ -197,31 +202,40 @@ int mem_test(resource_size_t _start,
for (offset2 = 1; offset2 <= num_words; offset2 <<= 1) {
start[offset2] = anti_pattern;
- for (offset = 1; offset <= num_words; offset <<= 1) {
+ for (offset = 0; offset <= num_words;
+ offset = (offset) ? offset << 1 : 1) {
temp = start[offset];
if ((temp != pattern) &&
(offset != offset2)) {
- printf("FAILURE: Address bit stuck"
- " low or shorted @"
- " 0x%08x: expected 0x%08x, actual 0x%08x.\n",
- (resource_size_t)&start[offset],
- pattern, temp);
+ mem_test_report_failure(
+ "address bit stuck low or shorted",
+ pattern, temp, &start[offset]);
return -EIO;
}
}
start[offset2] = pattern;
}
- /*
- * We tested only the bus if != 0
- * leaving here
- */
- if (bus_only)
- return 0;
+ return 0;
+}
+
+int mem_test_dram(resource_size_t _start,
+ resource_size_t _end)
+{
+ volatile resource_size_t *start, num_words, offset, temp, anti_pattern;
+
+ _start = ALIGN(_start, sizeof(resource_size_t));
+ _end = ALIGN_DOWN(_end, sizeof(resource_size_t)) - 1;
+
+ if (_end <= _start)
+ return -EINVAL;
+
+ start = (resource_size_t *)_start;
+ num_words = (_end - _start + 1)/sizeof(resource_size_t);
printf("Starting integrity check of physicaly ram.\n"
- "Filling ram with patterns...\n");
+ "Filling ram with patterns...\n");
/*
* Description: Test the integrity of a physical
@@ -238,16 +252,17 @@ int mem_test(resource_size_t _start,
* Fill memory with a known pattern.
*/
init_progression_bar(num_words);
+
for (offset = 0; offset < num_words; offset++) {
/*
* Every 4K we update the progressbar.
*/
+
if (!(offset & (SZ_4K - 1))) {
if (ctrlc())
return -EINTR;
show_progress(offset);
}
-
start[offset] = offset + 1;
}
show_progress(offset);
@@ -266,10 +281,10 @@ int mem_test(resource_size_t _start,
temp = start[offset];
if (temp != (offset + 1)) {
- printf("\nFAILURE (read/write) @ 0x%08x:"
- " expected 0x%08x, actual 0x%08x.\n",
- (resource_size_t)&start[offset],
- (offset + 1), temp);
+ printf("\n");
+ mem_test_report_failure("read/write",
+ (offset + 1),
+ temp, &start[offset]);
return -EIO;
}
@@ -294,10 +309,10 @@ int mem_test(resource_size_t _start,
temp = start[offset];
if (temp != anti_pattern) {
- printf("\nFAILURE (read/write): @ 0x%08x:"
- " expected 0x%08x, actual 0x%08x.\n",
- (resource_size_t)&start[offset],
- anti_pattern, temp);
+ printf("\n");
+ mem_test_report_failure("read/write",
+ anti_pattern,
+ temp, &start[offset]);
return -EIO;
}
@@ -312,3 +327,36 @@ int mem_test(resource_size_t _start,
return 0;
}
+
+/*
+ * Perform a memory test. The complete test
+ * loops until interrupted by ctrl-c.
+ *
+ * Prameters:
+ * start: start address for memory test.
+ * end: end address of memory test.
+ * bus_only: skip integrity check and do only a address/data bus
+ * testing.
+ *
+ * Return value can be -EINVAL for invalid parameter or -EINTR
+ * if memory test was interrupted.
+ */
+int mem_test(resource_size_t _start,
+ resource_size_t _end, int bus_only)
+{
+ int ret;
+
+ ret = mem_test_bus_integrity(_start, _end);
+
+ if (ret < 0)
+ return ret;
+
+ /*
+ * We tested only the bus if != 0
+ * leaving here
+ */
+ if (!bus_only)
+ ret = mem_test_dram(_start, _end);
+
+ return ret;
+}
diff --git a/common/oftree.c b/common/oftree.c
index 50fc95b588..f75d7b4bfe 100644
--- a/common/oftree.c
+++ b/common/oftree.c
@@ -160,6 +160,25 @@ int of_register_fixup(int (*fixup)(struct device_node *, void *), void *context)
}
/*
+ * Remove a previously registered fixup. Only the first (if any) is removed.
+ * Returns 0 if a match was found (and removed), -ENOENT otherwise.
+ */
+int of_unregister_fixup(int (*fixup)(struct device_node *, void *),
+ void *context)
+{
+ struct of_fixup *of_fixup;
+
+ list_for_each_entry(of_fixup, &of_fixup_list, list) {
+ if (of_fixup->fixup == fixup && of_fixup->context == context) {
+ list_del(&of_fixup->list);
+ return 0;
+ }
+ }
+
+ return -ENOENT;
+}
+
+/*
* Apply registered fixups for the given fdt. The fdt must have
* enough free space to apply the fixups.
*/
diff --git a/common/parser.c b/common/parser.c
index 4a48210c4d..207599f429 100644
--- a/common/parser.c
+++ b/common/parser.c
@@ -284,4 +284,3 @@ int run_shell(void)
}
return 0;
}
-
diff --git a/common/startup.c b/common/startup.c
index e59b06d533..6178fc5353 100644
--- a/common/startup.c
+++ b/common/startup.c
@@ -62,6 +62,24 @@ static int mount_root(void)
fs_initcall(mount_root);
#endif
+#ifdef CONFIG_ENV_HANDLING
+static int load_environment(void)
+{
+ const char *default_environment_path;
+
+ default_environment_path = default_environment_path_get();
+
+ if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT))
+ defaultenv_load("/env", 0);
+
+ envfs_load(default_environment_path, "/env", 0);
+ nvvar_load();
+
+ return 0;
+}
+environment_initcall(load_environment);
+#endif
+
int (*barebox_main)(void);
void __noreturn start_barebox(void)
@@ -84,16 +102,6 @@ void __noreturn start_barebox(void)
pr_debug("initcalls done\n");
- if (IS_ENABLED(CONFIG_ENV_HANDLING)) {
- char *default_environment_path = default_environment_path_get();
-
- if (IS_ENABLED(CONFIG_DEFAULT_ENVIRONMENT))
- defaultenv_load("/env", 0);
-
- envfs_load(default_environment_path, "/env", 0);
- nvvar_load();
- }
-
if (IS_ENABLED(CONFIG_COMMAND_SUPPORT)) {
pr_info("running /env/bin/init...\n");
diff --git a/common/state.c b/common/state.c
index b677a9f01d..7076f5764d 100644
--- a/common/state.c
+++ b/common/state.c
@@ -54,12 +54,14 @@ struct state_backend {
int (*load)(struct state_backend *backend, struct state *state);
int (*save)(struct state_backend *backend, struct state *state);
const char *name;
+ const char *of_path;
const char *path;
};
enum state_variable_type {
STATE_TYPE_INVALID = 0,
STATE_TYPE_ENUM,
+ STATE_TYPE_U8,
STATE_TYPE_U32,
STATE_TYPE_MAC,
};
@@ -74,12 +76,20 @@ struct state_variable {
void *raw;
};
+enum state_convert {
+ STATE_CONVERT_FROM_NODE,
+ STATE_CONVERT_FROM_NODE_CREATE,
+ STATE_CONVERT_TO_NODE,
+ STATE_CONVERT_FIXUP,
+};
+
/* A variable type (uint32, enum32) */
struct variable_type {
enum state_variable_type type;
const char *type_name;
struct list_head list;
- int (*export)(struct state_variable *, struct device_node *);
+ int (*export)(struct state_variable *, struct device_node *,
+ enum state_convert);
int (*import)(struct state_variable *, const struct device_node *);
struct state_variable *(*create)(struct state *state,
const char *name, struct device_node *);
@@ -126,15 +136,15 @@ static inline struct state_uint32 *to_state_uint32(struct state_variable *s)
}
static int state_uint32_export(struct state_variable *var,
- struct device_node *node)
+ struct device_node *node, enum state_convert conv)
{
struct state_uint32 *su32 = to_state_uint32(var);
int ret;
- if (su32->value_default) {
+ if (su32->value_default || conv == STATE_CONVERT_FIXUP) {
ret = of_property_write_u32(node, "default",
su32->value_default);
- if (ret)
+ if (ret || conv == STATE_CONVERT_FIXUP)
return ret;
}
@@ -153,7 +163,7 @@ static int state_uint32_import(struct state_variable *sv,
return 0;
}
-static struct state_variable *state_uint32_create(struct state *state,
+static struct state_variable *state_uint8_create(struct state *state,
const char *name, struct device_node *node)
{
struct state_uint32 *su32;
@@ -169,6 +179,32 @@ static struct state_variable *state_uint32_create(struct state *state,
}
su32->param = param;
+ su32->var.size = sizeof(uint8_t);
+#ifdef __LITTLE_ENDIAN
+ su32->var.raw = &su32->value;
+#else
+ su32->var.raw = &su32->value + 3;
+#endif
+
+ return &su32->var;
+}
+
+static struct state_variable *state_uint32_create(struct state *state,
+ const char *name, struct device_node *node)
+{
+ struct state_uint32 *su32;
+ struct param_d *param;
+
+ su32 = xzalloc(sizeof(*su32));
+
+ param = dev_add_param_int(&state->dev, name, state_set_dirty,
+ NULL, &su32->value, "%u", state);
+ if (IS_ERR(param)) {
+ free(su32);
+ return ERR_CAST(param);
+ }
+
+ su32->param = param;
su32->var.size = sizeof(uint32_t);
su32->var.raw = &su32->value;
@@ -193,16 +229,16 @@ static inline struct state_enum32 *to_state_enum32(struct state_variable *s)
}
static int state_enum32_export(struct state_variable *var,
- struct device_node *node)
+ struct device_node *node, enum state_convert conv)
{
struct state_enum32 *enum32 = to_state_enum32(var);
int ret, i, len;
char *prop, *str;
- if (enum32->value_default) {
+ if (enum32->value_default || conv == STATE_CONVERT_FIXUP) {
ret = of_property_write_u32(node, "default",
enum32->value_default);
- if (ret)
+ if (ret || conv == STATE_CONVERT_FIXUP)
return ret;
}
@@ -309,14 +345,14 @@ static inline struct state_mac *to_state_mac(struct state_variable *s)
}
static int state_mac_export(struct state_variable *var,
- struct device_node *node)
+ struct device_node *node, enum state_convert conv)
{
struct state_mac *mac = to_state_mac(var);
int ret;
ret = of_property_write_u8_array(node, "default", mac->value_default,
ARRAY_SIZE(mac->value_default));
- if (ret)
+ if (ret || conv == STATE_CONVERT_FIXUP)
return ret;
return of_property_write_u8_array(node, "value", mac->value,
@@ -363,6 +399,12 @@ out:
static struct variable_type types[] = {
{
+ .type = STATE_TYPE_U8,
+ .type_name = "uint8",
+ .export = state_uint32_export,
+ .import = state_uint32_import,
+ .create = state_uint8_create,
+ }, {
.type = STATE_TYPE_U32,
.type_name = "uint32",
.export = state_uint32_export,
@@ -426,13 +468,6 @@ static struct state *state_new(const char *name)
return state;
}
-static void state_release(struct state *state)
-{
- list_del(&state->list);
- unregister_device(&state->dev);
- free(state);
-}
-
static struct state_variable *state_find_var(struct state *state,
const char *name)
{
@@ -446,12 +481,6 @@ static struct state_variable *state_find_var(struct state *state,
return ERR_PTR(-ENOENT);
}
-enum state_convert {
- STATE_CONVERT_FROM_NODE,
- STATE_CONVERT_FROM_NODE_CREATE,
- STATE_CONVERT_TO_NODE,
-};
-
static int state_convert_node_variable(struct state *state,
struct device_node *node, struct device_node *parent,
const char *parent_name, enum state_convert conv)
@@ -476,7 +505,8 @@ static int state_convert_node_variable(struct state *state,
parent_name, parent_name[0] ? "." : "", short_name);
free(short_name);
- if (conv == STATE_CONVERT_TO_NODE)
+ if ((conv == STATE_CONVERT_TO_NODE) ||
+ (conv == STATE_CONVERT_FIXUP))
new_node = of_new_node(parent, node->name);
for_each_child_of_node(node, child) {
@@ -489,6 +519,15 @@ static int state_convert_node_variable(struct state *state,
/* parents are allowed to have no type */
ret = of_property_read_string(node, "type", &type_name);
if (!list_empty(&node->children) && ret == -EINVAL) {
+ if (conv == STATE_CONVERT_FIXUP) {
+ ret = of_property_write_u32(new_node, "#address-cells", 1);
+ if (ret)
+ goto out_free;
+
+ ret = of_property_write_u32(new_node, "#size-cells", 1);
+ if (ret)
+ goto out_free;
+ }
ret = 0;
goto out_free;
} else if (ret) {
@@ -512,13 +551,16 @@ static int state_convert_node_variable(struct state *state,
ret = of_property_read_u32_array(node, "reg", start_size,
ARRAY_SIZE(start_size));
- if (ret)
+ if (ret) {
+ dev_err(&state->dev,
+ "%s: reg property not found\n", name);
goto out_free;
+ }
if (start_size[1] != sv->size) {
dev_err(&state->dev,
- "size mismatch: type=%s(size=%u) size=%u\n",
- type_name, sv->size, start_size[1]);
+ "%s: size mismatch: type=%s(size=%u) size=%u\n",
+ name, type_name, sv->size, start_size[1]);
ret = -EOVERFLOW;
goto out_free;
}
@@ -539,7 +581,8 @@ static int state_convert_node_variable(struct state *state,
}
free(name);
- if (conv == STATE_CONVERT_TO_NODE) {
+ if ((conv == STATE_CONVERT_TO_NODE) ||
+ (conv == STATE_CONVERT_FIXUP)) {
ret = of_set_property(new_node, "type",
vtype->type_name,
strlen(vtype->type_name) + 1, 1);
@@ -556,8 +599,9 @@ static int state_convert_node_variable(struct state *state,
}
}
- if (conv == STATE_CONVERT_TO_NODE)
- ret = vtype->export(sv, new_node);
+ if ((conv == STATE_CONVERT_TO_NODE) ||
+ (conv == STATE_CONVERT_FIXUP))
+ ret = vtype->export(sv, new_node, conv);
else
ret = vtype->import(sv, node);
@@ -571,20 +615,21 @@ out:
return ret;
}
-static struct device_node *state_to_node(struct state *state)
+static struct device_node *state_to_node(struct state *state, struct device_node *parent,
+ enum state_convert conv)
{
struct device_node *child;
struct device_node *root;
int ret;
- root = of_new_node(NULL, NULL);
+ root = of_new_node(parent, state->root->name);
ret = of_property_write_u32(root, "magic", state->magic);
if (ret)
goto out;
for_each_child_of_node(state->root, child) {
ret = state_convert_node_variable(state, child, root, "",
- STATE_CONVERT_TO_NODE);
+ conv);
if (ret)
goto out;
}
@@ -657,6 +702,101 @@ static int state_from_node(struct state *state, struct device_node *node,
return ret;
}
+static int of_state_fixup(struct device_node *root, void *ctx)
+{
+ struct state *state = ctx;
+ const char *compatible = "barebox,state";
+ struct device_node *new_node, *node, *parent, *backend_node;
+ struct property *p;
+ int ret;
+ phandle phandle;
+
+ node = of_find_node_by_path_from(root, state->root->full_name);
+ if (node) {
+ /* replace existing node - it will be deleted later */
+ parent = node->parent;
+ } else {
+ char *of_path, *c;
+
+ /* look for parent, remove last '/' from path */
+ of_path = xstrdup(state->root->full_name);
+ c = strrchr(of_path, '/');
+ if (!c)
+ return -ENODEV;
+ *c = '0';
+ parent = of_find_node_by_path(of_path);
+ if (!parent)
+ parent = root;
+
+ free(of_path);
+ }
+
+ /* serialize variable definitions */
+ new_node = state_to_node(state, parent, STATE_CONVERT_FIXUP);
+ if (IS_ERR(new_node))
+ return PTR_ERR(new_node);
+
+ /* compatible */
+ p = of_new_property(new_node, "compatible", compatible,
+ strlen(compatible) + 1);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* backend-type */
+ if (!state->backend) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ p = of_new_property(new_node, "backend-type", state->backend->name,
+ strlen(state->backend->name) + 1);
+ if (!p) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* backend phandle */
+ backend_node = of_find_node_by_path_from(root, state->backend->of_path);
+ if (!backend_node) {
+ ret = -ENODEV;
+ goto out;
+ }
+
+ phandle = of_node_create_phandle(backend_node);
+ ret = of_property_write_u32(new_node, "backend", phandle);
+ if (ret)
+ goto out;
+
+ /* address-cells + size-cells */
+ ret = of_property_write_u32(new_node, "#address-cells", 1);
+ if (ret)
+ goto out;
+
+ ret = of_property_write_u32(new_node, "#size-cells", 1);
+ if (ret)
+ goto out;
+
+ /* delete existing node */
+ if (node)
+ of_delete_node(node);
+
+ return 0;
+
+ out:
+ of_delete_node(new_node);
+ return ret;
+}
+
+void state_release(struct state *state)
+{
+ of_unregister_fixup(of_state_fixup, state);
+ list_del(&state->list);
+ unregister_device(&state->dev);
+ free(state);
+}
+
/*
* state_new_from_node - create a new state instance from a device_node
*
@@ -678,27 +818,11 @@ struct state *state_new_from_node(const char *name, struct device_node *node)
return ERR_PTR(ret);
}
- return state;
-}
-
-/*
- * state_new_from_fdt - create a new state instance from a fdt binary blob
- *
- * @name The name of the new state instance
- * @fdt The fdt binary blob describing the new state instance
- */
-struct state *state_new_from_fdt(const char *name, void *fdt)
-{
- struct state *state;
- struct device_node *root;
-
- root = of_unflatten_dtb(fdt);
- if (!root)
- return ERR_PTR(-EINVAL);
-
- state = state_new_from_node(name, root);
-
- of_delete_node(root);
+ ret = of_register_fixup(of_state_fixup, state);
+ if (ret) {
+ state_release(state);
+ return ERR_PTR(ret);
+ }
return state;
}
@@ -757,10 +881,13 @@ int state_load(struct state *state)
return -ENOSYS;
ret = state->backend->load(state->backend, state);
- if (ret)
+ if (ret) {
+ dev_warn(&state->dev, "load failed\n");
state->dirty = 1;
- else
+ } else {
+ dev_info(&state->dev, "load successful\n");
state->dirty = 0;
+ }
return ret;
}
@@ -809,7 +936,7 @@ static int mtd_get_meminfo(const char *path, struct mtd_info_user *meminfo)
{
int fd, ret;
- fd = open(path, O_RDWR);
+ fd = open(path, O_RDONLY);
if (fd < 0)
return fd;
@@ -863,7 +990,7 @@ static int state_backend_dtb_save(struct state_backend *backend,
struct device_node *root;
struct fdt_header *fdt;
- root = state_to_node(state);
+ root = state_to_node(state, NULL, STATE_CONVERT_TO_NODE);
if (IS_ERR(root))
return PTR_ERR(root);
@@ -906,7 +1033,7 @@ out:
* @state The state instance to work on
* @path The path where the state will be stored to
*/
-int state_backend_dtb_file(struct state *state, const char *path)
+int state_backend_dtb_file(struct state *state, const char *of_path, const char *path)
{
struct state_backend_dtb *backend_dtb;
struct state_backend *backend;
@@ -921,13 +1048,14 @@ int state_backend_dtb_file(struct state *state, const char *path)
backend->load = state_backend_dtb_load;
backend->save = state_backend_dtb_save;
+ backend->of_path = xstrdup(of_path);
backend->path = xstrdup(path);
backend->name = "dtb";
state->backend = backend;
ret = mtd_get_meminfo(backend->path, &meminfo);
- if (!ret && !(meminfo.mtd->flags & MTD_NO_ERASE))
+ if (!ret && !(meminfo.flags & MTD_NO_ERASE))
backend_dtb->need_erase = true;
return 0;
@@ -938,9 +1066,9 @@ int state_backend_dtb_file(struct state *state, const char *path)
*/
struct state_backend_raw {
struct state_backend backend;
- unsigned long size_data; /* The raw data size (without magic and crc) */
- unsigned long size_full;
- unsigned long step; /* The step in bytes between two copies */
+ unsigned long size_data; /* The raw data size (without header) */
+ unsigned long size_full; /* The size header + raw data */
+ unsigned long stride; /* The stride size in bytes of the copies */
off_t offset; /* offset in the storage file */
size_t size; /* size of the storage area */
int num_copy_read; /* The first successfully read copy */
@@ -961,16 +1089,23 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
uint32_t crc;
struct state_variable *sv;
struct backend_raw_header header = {};
+ unsigned long max_len;
int ret;
void *buf;
+ max_len = backend_raw->stride;
+
ret = lseek(fd, offset, SEEK_SET);
if (ret < 0)
return ret;
ret = read_full(fd, &header, sizeof(header));
- if (ret < 0)
+ max_len -= sizeof(header);
+ if (ret < 0) {
+ dev_err(&state->dev,
+ "cannot read header from backend device");
return ret;
+ }
crc = crc32(0, &header, sizeof(header) - sizeof(uint32_t));
if (crc != header.header_crc) {
@@ -987,6 +1122,13 @@ static int backend_raw_load_one(struct state_backend_raw *backend_raw,
return -EINVAL;
}
+ if (header.data_len > max_len) {
+ dev_err(&state->dev,
+ "invalid data_len %u in header, max is %lu\n",
+ header.data_len, max_len);
+ return -EINVAL;
+ }
+
buf = xzalloc(header.data_len);
ret = read_full(fd, buf, header.data_len);
@@ -1024,11 +1166,13 @@ static int state_backend_raw_load(struct state_backend *backend,
int ret = 0, fd, i;
fd = open(backend->path, O_RDONLY);
- if (fd < 0)
+ if (fd < 0) {
+ dev_err(&state->dev, "cannot open %s\n", backend->path);
return fd;
+ }
for (i = 0; i < RAW_BACKEND_COPIES; i++) {
- off_t offset = backend_raw->offset + i * backend_raw->step;
+ off_t offset = backend_raw->offset + i * backend_raw->stride;
ret = backend_raw_load_one(backend_raw, state, fd, offset);
if (!ret) {
@@ -1044,11 +1188,11 @@ static int state_backend_raw_load(struct state_backend *backend,
return ret;
}
-static int backend_raw_write_one(struct state_backend_raw *backend_raw,
+static int backend_raw_save_one(struct state_backend_raw *backend_raw,
struct state *state, int fd, int num, void *buf, size_t size)
{
int ret;
- off_t offset = backend_raw->offset + num * backend_raw->step;
+ off_t offset = backend_raw->offset + num * backend_raw->stride;
dev_dbg(&state->dev, "%s: 0x%08lx 0x%08zx\n",
__func__, offset, size);
@@ -1058,7 +1202,7 @@ static int backend_raw_write_one(struct state_backend_raw *backend_raw,
return ret;
if (backend_raw->need_erase) {
- ret = erase(fd, backend_raw->size_full, offset);
+ ret = erase(fd, backend_raw->stride, offset);
if (ret)
return ret;
}
@@ -1075,14 +1219,12 @@ static int state_backend_raw_save(struct state_backend *backend,
{
struct state_backend_raw *backend_raw = container_of(backend,
struct state_backend_raw, backend);
- int ret = 0, size, fd;
+ int ret = 0, fd, i;
void *buf, *data;
struct backend_raw_header *header;
struct state_variable *sv;
- size = backend_raw->size_data + sizeof(struct backend_raw_header);
-
- buf = xzalloc(size);
+ buf = xzalloc(backend_raw->size_full);
header = buf;
data = buf + sizeof(*header);
@@ -1100,13 +1242,20 @@ static int state_backend_raw_save(struct state_backend *backend,
if (fd < 0)
goto out_free;
- ret = backend_raw_write_one(backend_raw, state, fd,
- !backend_raw->num_copy_read, buf, size);
- if (ret)
- goto out_close;
+ /* save other slots first */
+ for (i = 0; i < RAW_BACKEND_COPIES; i++) {
+ if (i == backend_raw->num_copy_read)
+ continue;
- ret = backend_raw_write_one(backend_raw, state, fd,
- backend_raw->num_copy_read, buf, size);
+ ret = backend_raw_save_one(backend_raw, state, fd,
+ i, buf, backend_raw->size_full);
+ if (ret)
+ goto out_close;
+
+ }
+
+ ret = backend_raw_save_one(backend_raw, state, fd,
+ backend_raw->num_copy_read, buf, backend_raw->size_full);
if (ret)
goto out_close;
@@ -1119,6 +1268,60 @@ out_free:
return ret;
}
+#ifdef __BAREBOX__
+#define STAT_GIVES_SIZE(s) (S_ISREG(s.st_mode) || S_ISCHR(s.st_mode))
+#define BLKGET_GIVES_SIZE(s) 0
+#ifndef BLKGETSIZE64
+#define BLKGETSIZE64 -1
+#endif
+#else
+#define STAT_GIVES_SIZE(s) (S_ISREG(s.st_mode))
+#define BLKGET_GIVES_SIZE(s) (S_ISBLK(s.st_mode))
+#endif
+
+static int state_backend_raw_file_get_size(const char *path, size_t *out_size)
+{
+ struct mtd_info_user meminfo;
+ struct stat s;
+ int ret;
+
+ ret = stat(path, &s);
+ if (ret)
+ return -errno;
+
+ /*
+ * under Linux, stat() gives the size only on regular files
+ * under barebox, it works on char dev, too
+ */
+ if (STAT_GIVES_SIZE(s)) {
+ *out_size = s.st_size;
+ return 0;
+ }
+
+ /* this works under Linux on block devs */
+ if (BLKGET_GIVES_SIZE(s)) {
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ ret = ioctl(fd, BLKGETSIZE64, out_size);
+ close(fd);
+ if (!ret)
+ return 0;
+ }
+
+ /* try mtd next */
+ ret = mtd_get_meminfo(path, &meminfo);
+ if (!ret) {
+ *out_size = meminfo.size;
+ return 0;
+ }
+
+ return ret;
+}
+
/*
* state_backend_raw_file - create a raw file backend store for a state instance
*
@@ -1136,32 +1339,34 @@ out_free:
* device @size may be 0. The two copies are spread to different
* eraseblocks if approriate for this device.
*/
-int state_backend_raw_file(struct state *state, const char *path, off_t offset,
- size_t size)
+int state_backend_raw_file(struct state *state, const char *of_path,
+ const char *path, off_t offset, size_t size)
{
struct state_backend_raw *backend_raw;
struct state_backend *backend;
struct state_variable *sv;
- int ret;
- struct stat s;
struct mtd_info_user meminfo;
+ size_t path_size = 0;
+ int ret;
if (state->backend)
return -EBUSY;
- ret = stat(path, &s);
- if (!ret && S_ISCHR(s.st_mode)) {
- if (size == 0)
- size = s.st_size;
- else if (offset + size > s.st_size)
- return -EINVAL;
- }
+ ret = state_backend_raw_file_get_size(path, &path_size);
+ if (ret)
+ return ret;
+
+ if (size == 0)
+ size = path_size;
+ else if (offset + size > path_size)
+ return -EINVAL;
backend_raw = xzalloc(sizeof(*backend_raw));
backend = &backend_raw->backend;
backend->load = state_backend_raw_load;
backend->save = state_backend_raw_save;
+ backend->of_path = xstrdup(of_path);
backend->path = xstrdup(path);
backend->name = "raw";
@@ -1175,18 +1380,21 @@ int state_backend_raw_file(struct state *state, const char *path, off_t offset,
state->backend = backend;
ret = mtd_get_meminfo(backend->path, &meminfo);
- if (!ret && !(meminfo.mtd->flags & MTD_NO_ERASE)) {
+ if (!ret && !(meminfo.flags & MTD_NO_ERASE)) {
backend_raw->need_erase = true;
- backend_raw->step = ALIGN(backend_raw->size_full,
- meminfo.erasesize);
+ backend_raw->size_full = ALIGN(backend_raw->size_full,
+ meminfo.writesize);
+ backend_raw->stride = ALIGN(backend_raw->size_full,
+ meminfo.erasesize);
dev_dbg(&state->dev, "is a mtd, adjust stepsize to %ld\n",
- backend_raw->step);
+ backend_raw->stride);
} else {
- backend_raw->step = backend_raw->size_full;
+ backend_raw->stride = backend_raw->size_full;
}
- if (backend_raw->size / backend_raw->step < RAW_BACKEND_COPIES) {
- dev_err(&state->dev, "not enough space for two copies\n");
+ if (backend_raw->size / backend_raw->stride < RAW_BACKEND_COPIES) {
+ dev_err(&state->dev, "not enough space for two copies (%lu each)\n",
+ backend_raw->stride);
ret = -ENOSPC;
goto err;
}
diff --git a/common/tlsfbits.h b/common/tlsfbits.h
index 93466e46a8..edbac80636 100644
--- a/common/tlsfbits.h
+++ b/common/tlsfbits.h
@@ -3,6 +3,10 @@
#include <linux/bitops.h>
+#ifdef CONFIG_64BIT
+#define TLSF_64BIT
+#endif
+
/*
** Architecture-specific bit manipulation routines.
**
@@ -33,7 +37,7 @@ static int tlsf_fls(unsigned int word)
/* Possibly 64-bit version of tlsf_fls. */
#if defined (TLSF_64BIT)
-tlsf_decl int tlsf_fls_sizet(size_t size)
+static int tlsf_fls_sizet(size_t size)
{
int high = (int)(size >> 32);
int bits = 0;
diff --git a/crypto/crc16.c b/crypto/crc16.c
index d22b656379..0b08e9ccde 100644
--- a/crypto/crc16.c
+++ b/crypto/crc16.c
@@ -90,7 +90,7 @@ static const uint16_t crc16_tab[] = {
};
uint16_t
-cyg_crc16(unsigned char *buf, int len)
+cyg_crc16(const unsigned char *buf, int len)
{
int i;
uint16_t cksum;
diff --git a/crypto/digest.c b/crypto/digest.c
index b3f514c8ad..a90e4ff79f 100644
--- a/crypto/digest.c
+++ b/crypto/digest.c
@@ -172,7 +172,7 @@ EXPORT_SYMBOL_GPL(digest_free);
int digest_file_window(struct digest *d, const char *filename,
unsigned char *hash,
- unsigned char *sig,
+ const unsigned char *sig,
ulong start, ulong size)
{
ulong len = 0;
@@ -249,8 +249,8 @@ out:
EXPORT_SYMBOL_GPL(digest_file_window);
int digest_file(struct digest *d, const char *filename,
- unsigned char *hash,
- unsigned char *sig)
+ unsigned char *hash,
+ const unsigned char *sig)
{
struct stat st;
int ret;
@@ -265,8 +265,8 @@ int digest_file(struct digest *d, const char *filename,
EXPORT_SYMBOL_GPL(digest_file);
int digest_file_by_name(const char *algo, const char *filename,
- unsigned char *hash,
- unsigned char *sig)
+ unsigned char *hash,
+ const unsigned char *sig)
{
struct digest *d;
int ret;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 24cb5bc62b..338bea1280 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -113,14 +113,29 @@ int device_detect(struct device_d *dev)
return dev->detect(dev);
}
-int device_detect_by_name(const char *devname)
+int device_detect_by_name(const char *__devname)
{
- struct device_d *dev = get_device_by_name(devname);
+ char *devname = xstrdup(__devname);
+ char *str = devname;
+ struct device_d *dev;
+ int ret = -ENODEV;
+
+ while (1) {
+ strsep(&str, ".");
+
+ dev = get_device_by_name(devname);
+ if (dev)
+ ret = device_detect(dev);
- if (!dev)
- return -ENODEV;
+ if (!str)
+ break;
+ else
+ *(str - 1) = '.';
+ }
- return device_detect(dev);
+ free(devname);
+
+ return ret;
}
static int match(struct driver_d *drv, struct device_d *dev)
diff --git a/drivers/bus/omap-gpmc.c b/drivers/bus/omap-gpmc.c
index 6752c42a35..8ae909a1b6 100644
--- a/drivers/bus/omap-gpmc.c
+++ b/drivers/bus/omap-gpmc.c
@@ -24,6 +24,14 @@
#define GPMC_CS_NUM 8
#define GPMC_NR_WAITPINS 4
+#define GPMC_BURST_4 4 /* 4 word burst */
+#define GPMC_BURST_8 8 /* 8 word burst */
+#define GPMC_BURST_16 16 /* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
+#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
+
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29)
@@ -55,6 +63,9 @@
#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN (1 << 7)
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
static unsigned int gpmc_nr_waitpins;
static unsigned long gpmc_l3_clk = 100000000; /* This should be a proper clock */
@@ -149,7 +160,7 @@ static void gpmc_cs_bool_timings(struct gpmc_config *gpmc_config, const struct g
if (p->oe_extra_delay)
gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
if (p->we_extra_delay)
- gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
+ gpmc_config->cfg[3] |= GPMC_CONFIG4_WEEXTRADELAY;
if (p->cycle2cyclesamecsen)
gpmc_config->cfg[5] |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
if (p->cycle2cyclediffcsen)
@@ -220,6 +231,8 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
if (div < 0)
return div;
+ gpmc_config->cfg[0] |= div - 1;
+
ret |= set_cfg(gpmc_config, 0, 18, 19, t->wait_monitoring);
ret |= set_cfg(gpmc_config, 0, 25, 26, t->clk_activation);
@@ -255,6 +268,60 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
return 0;
}
+static int gpmc_settings_to_config(struct gpmc_config *gpmc_config,
+ struct gpmc_settings *p)
+{
+ u32 config1 = gpmc_config->cfg[0];
+
+ /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+ if (p->burst_read || p->burst_write) {
+ switch (p->burst_len) {
+ case GPMC_BURST_4:
+ case GPMC_BURST_8:
+ case GPMC_BURST_16:
+ break;
+ default:
+ pr_err("%s: invalid page/burst-length (%d)\n",
+ __func__, p->burst_len);
+ return -EINVAL;
+ }
+ }
+
+ if (p->wait_pin > gpmc_nr_waitpins) {
+ pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+ return -EINVAL;
+ }
+
+ config1 |= GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+ if (p->sync_read)
+ config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+ if (p->sync_write)
+ config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+ if (p->wait_on_read)
+ config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+ if (p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+ if (p->wait_on_read || p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+ if (p->device_nand)
+ config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+ if (p->mux_add_data)
+ config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+ if (p->burst_read)
+ config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+ if (p->burst_write)
+ config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+ if (p->burst_read || p->burst_write) {
+ config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+ config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+ }
+
+ gpmc_config->cfg[0] = config1;
+
+ return 0;
+}
+
/**
* gpmc_read_settings_dt - read gpmc settings from device-tree
* @np: pointer to device-tree node for a gpmc child device
@@ -464,6 +531,77 @@ static int gpmc_probe_nand_child(struct device_d *dev,
return 0;
}
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev: pointer to gpmc platform device
+ * @child: pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct device_d *dev,
+ struct device_node *child)
+{
+ struct gpmc_settings gpmc_s = {};
+ struct gpmc_timings gpmc_t = {};
+ struct resource res;
+ int ret, cs;
+ struct gpmc_config cfg = {};
+ resource_size_t size;
+
+ if (of_property_read_u32(child, "reg", &cs) < 0) {
+ dev_err(dev, "%s has no 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(child, 0, &res) < 0) {
+ dev_err(dev, "%s has malformed 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ gpmc_read_settings_dt(child, &gpmc_s);
+ gpmc_read_timings_dt(child, &gpmc_t);
+
+ ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+ if (ret < 0)
+ goto err;
+
+ gpmc_timings_to_config(&cfg, &gpmc_t);
+
+ cfg.base = res.start;
+
+ size = resource_size(&res);
+ if (size > SZ_64M)
+ cfg.size = GPMC_SIZE_128M;
+ else if (size > SZ_32M)
+ cfg.size = GPMC_SIZE_64M;
+ else if (size > SZ_16M)
+ cfg.size = GPMC_SIZE_32M;
+ else
+ cfg.size = GPMC_SIZE_16M;
+
+ gpmc_settings_to_config(&cfg, &gpmc_s);
+
+ gpmc_cs_config(cs, &cfg);
+
+ /* create platform device, NULL on error or when disabled */
+ if (of_get_property(child, "compatible", NULL) && !of_platform_device_create(child, dev))
+ goto err_child_fail;
+
+ return 0;
+
+err_child_fail:
+
+ dev_err(dev, "failed to create gpmc child %s\n", child->name);
+ ret = -ENODEV;
+
+err:
+
+ return ret;
+}
+
static int gpmc_probe(struct device_d *dev)
{
struct device_node *child, *node = dev->device_node;
@@ -488,6 +626,10 @@ static int gpmc_probe(struct device_d *dev)
if (!strncmp(child->name, "nand", 4))
ret = gpmc_probe_nand_child(dev, child);
+ else if (strncmp(child->name, "ethernet", 8) == 0 ||
+ strncmp(child->name, "nor", 3) == 0 ||
+ strncmp(child->name, "uart", 4) == 0)
+ ret = gpmc_probe_generic_child(dev, child);
else
dev_warn(dev, "unhandled child %s\n", child->name);
diff --git a/drivers/i2c/i2c.c b/drivers/i2c/i2c.c
index 7a6bde0f67..5d0fa06bb5 100644
--- a/drivers/i2c/i2c.c
+++ b/drivers/i2c/i2c.c
@@ -183,7 +183,7 @@ int i2c_read_reg(struct i2c_client *client, u32 addr, u8 *buf, u16 count)
msg->len = i;
status = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
- dev_dbg(&client->dev, "%s: %zu@%u --> %d\n", __func__,
+ dev_dbg(&client->dev, "%s: %u@%u --> %d\n", __func__,
count, addr, status);
if (status == ARRAY_SIZE(msg))
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 31f7d2d4ea..ebd8da9591 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -95,7 +95,7 @@ config MCI_OMAP_HSMMC
config MCI_PXA
bool "PXA"
- depends on ARCH_PXA
+ depends on ARCH_PXA2XX
help
Enable this entry to add support to read and write SD cards on a
XScale PXA25x / PXA27x based system.
diff --git a/drivers/mci/imx-esdhc.c b/drivers/mci/imx-esdhc.c
index 8b45500a09..6caf165616 100644
--- a/drivers/mci/imx-esdhc.c
+++ b/drivers/mci/imx-esdhc.c
@@ -60,9 +60,10 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
if (data) {
xfertyp |= COMMAND_DPSEL;
-#ifndef CONFIG_MCI_IMX_ESDHC_PIO
- xfertyp |= TRANSFER_MODE_DMAEN;
-#endif
+
+ if (!IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO))
+ xfertyp |= TRANSFER_MODE_DMAEN;
+
if (data->blocks > 1) {
xfertyp |= TRANSFER_MODE_MSBSEL;
xfertyp |= TRANSFER_MODE_BCEN;
@@ -89,11 +90,10 @@ static u32 esdhc_xfertyp(struct mci_cmd *cmd, struct mci_data *data)
return COMMAND_CMD(cmd->cmdidx) | xfertyp;
}
-#ifdef CONFIG_MCI_IMX_ESDHC_PIO
/*
* PIO Read/Write Mode reduce the performace as DMA is not used in this mode.
*/
-static void
+static int
esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data)
{
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
@@ -115,8 +115,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data)
while (!(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_BREN)
&& --timeout);
if (timeout <= 0) {
- printf("\nData Read Failed in PIO Mode.");
- return;
+ dev_err(host->dev, "Data Read Failed\n");
+ return -ETIMEDOUT;
}
while (size && (!(irqstat & IRQSTAT_TC))) {
udelay(100); /* Wait before last byte transfer complete */
@@ -138,8 +138,8 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data)
while (!(esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_BWEN)
&& --timeout);
if (timeout <= 0) {
- printf("\nData Write Failed in PIO Mode.");
- return;
+ dev_err(host->dev, "Data Write Failed\n");
+ return -ETIMEDOUT;
}
while (size && (!(irqstat & IRQSTAT_TC))) {
udelay(100); /* Wait before last byte transfer complete */
@@ -152,53 +152,85 @@ esdhc_pio_read_write(struct mci_host *mci, struct mci_data *data)
blocks--;
}
}
+
+ return 0;
}
-#endif
static int esdhc_setup_data(struct mci_host *mci, struct mci_data *data)
{
struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
void __iomem *regs = host->regs;
-#ifndef CONFIG_MCI_IMX_ESDHC_PIO
u32 wml_value;
- wml_value = data->blocksize/4;
-
- if (data->flags & MMC_DATA_READ) {
- if (wml_value > 0x10)
- wml_value = 0x10;
-
- esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value);
- esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest);
+ if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO)) {
+ if (!(data->flags & MMC_DATA_READ)) {
+ if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0)
+ goto err_locked;
+ esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src);
+ } else {
+ esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest);
+ }
} else {
- if (wml_value > 0x80)
- wml_value = 0x80;
- if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) {
- printf("\nThe SD card is locked. Can not write to a locked card.\n\n");
- return -ETIMEDOUT;
+ wml_value = data->blocksize/4;
+
+ if (data->flags & MMC_DATA_READ) {
+ if (wml_value > 0x10)
+ wml_value = 0x10;
+
+ esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_RD_WML_MASK, wml_value);
+ esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest);
+ } else {
+ if (wml_value > 0x80)
+ wml_value = 0x80;
+ if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0)
+ goto err_locked;
+
+ esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_WR_WML_MASK,
+ wml_value << 16);
+ esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src);
}
-
- esdhc_clrsetbits32(regs + IMX_SDHCI_WML, WML_WR_WML_MASK,
- wml_value << 16);
- esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src);
}
-#else /* CONFIG_MCI_IMX_ESDHC_PIO */
- if (!(data->flags & MMC_DATA_READ)) {
- if ((esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_WPSPL) == 0) {
- printf("\nThe SD card is locked. "
- "Can not write to a locked card.\n\n");
- return -ETIMEDOUT;
- }
- esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->src);
- } else
- esdhc_write32(regs + SDHCI_DMA_ADDRESS, (u32)data->dest);
-#endif /* CONFIG_MCI_IMX_ESDHC_PIO */
esdhc_write32(regs + SDHCI_BLOCK_SIZE__BLOCK_COUNT, data->blocks << 16 | data->blocksize);
return 0;
+
+err_locked:
+ dev_err(host->dev, "Can not write to locked card.\n\n");
+
+ return -ETIMEDOUT;
}
+static int esdhc_do_data(struct mci_host *mci, struct mci_data *data)
+{
+ struct fsl_esdhc_host *host = to_fsl_esdhc(mci);
+ void __iomem *regs = host->regs;
+ unsigned int num_bytes = data->blocks * data->blocksize;
+ u32 irqstat;
+
+ if (IS_ENABLED(CONFIG_MCI_IMX_ESDHC_PIO))
+ return esdhc_pio_read_write(mci, data);
+
+ do {
+ irqstat = esdhc_read32(regs + SDHCI_INT_STATUS);
+
+ if (irqstat & DATA_ERR)
+ return -EIO;
+
+ if (irqstat & IRQSTAT_DTOE)
+ return -ETIMEDOUT;
+ } while (!(irqstat & IRQSTAT_TC) &&
+ (esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_DLA));
+
+ if (data->flags & MMC_DATA_WRITE)
+ dma_sync_single_for_cpu((unsigned long)data->src,
+ num_bytes, DMA_TO_DEVICE);
+ else
+ dma_sync_single_for_cpu((unsigned long)data->dest,
+ num_bytes, DMA_FROM_DEVICE);
+
+ return 0;
+}
/*
* Sends a command out on the bus. Takes the mci pointer,
@@ -303,27 +335,9 @@ esdhc_send_cmd(struct mci_host *mci, struct mci_cmd *cmd, struct mci_data *data)
/* Wait until all of the blocks are transferred */
if (data) {
-#ifdef CONFIG_MCI_IMX_ESDHC_PIO
- esdhc_pio_read_write(mci, data);
-#else
- do {
- irqstat = esdhc_read32(regs + SDHCI_INT_STATUS);
-
- if (irqstat & DATA_ERR)
- return -EIO;
-
- if (irqstat & IRQSTAT_DTOE)
- return -ETIMEDOUT;
- } while (!(irqstat & IRQSTAT_TC) &&
- (esdhc_read32(regs + SDHCI_PRESENT_STATE) & PRSSTAT_DLA));
-
- if (data->flags & MMC_DATA_WRITE)
- dma_sync_single_for_cpu((unsigned long)data->src,
- num_bytes, DMA_TO_DEVICE);
- else
- dma_sync_single_for_cpu((unsigned long)data->dest,
- num_bytes, DMA_FROM_DEVICE);
-#endif
+ ret = esdhc_do_data(mci, data);
+ if (ret)
+ return ret;
}
esdhc_write32(regs + SDHCI_INT_STATUS, -1);
@@ -498,8 +512,9 @@ static int esdhc_init(struct mci_host *mci, struct device_d *dev)
return ret;
}
-static int esdhc_reset(void __iomem *regs)
+static int esdhc_reset(struct fsl_esdhc_host *host)
{
+ void __iomem *regs = host->regs;
uint64_t start;
/* reset the controller */
@@ -513,7 +528,7 @@ static int esdhc_reset(void __iomem *regs)
& SYSCTL_RSTA))
break;
if (is_timeout(start, 100 * MSECOND)) {
- printf("MMC/SD: Reset never completed.\n");
+ dev_err(host->dev, "Reset never completed.\n");
return -EIO;
}
}
@@ -550,7 +565,7 @@ static int fsl_esdhc_probe(struct device_d *dev)
return PTR_ERR(host->regs);
/* First reset the eSDHC controller */
- ret = esdhc_reset(host->regs);
+ ret = esdhc_reset(host);
if (ret) {
free(host);
return ret;
diff --git a/drivers/misc/state.c b/drivers/misc/state.c
index 3b07bb93d7..f3e366480f 100644
--- a/drivers/misc/state.c
+++ b/drivers/misc/state.c
@@ -24,10 +24,12 @@
static int state_probe(struct device_d *dev)
{
struct device_node *np = dev->device_node;
+ struct device_node *partition_node;
struct state *state;
const char *alias;
const char *backend_type = NULL;
- int ret;
+ int len, ret;
+ const char *of_path;
char *path;
if (!np)
@@ -41,28 +43,70 @@ static int state_probe(struct device_d *dev)
if (IS_ERR(state))
return PTR_ERR(state);
- ret = of_find_path(np, "backend", &path, 0);
- if (ret)
- return ret;
+ of_path = of_get_property(np, "backend", &len);
+ if (!of_path) {
+ ret = -ENODEV;
+ goto out_release;
+ }
+
+ /* guess if of_path is a path, not a phandle */
+ if (of_path[0] == '/' && len > 1) {
+ ret = of_find_path(np, "backend", &path, 0);
+ if (ret)
+ goto out_release;
+ } else {
+ struct device_d *dev;
+ struct cdev *cdev;
+
+ partition_node = of_parse_phandle(np, "backend", 0);
+ if (!partition_node) {
+ ret = -ENODEV;
+ goto out_release;
+ }
+
+ dev = of_find_device_by_node(partition_node);
+ if (!list_is_singular(&dev->cdevs)) {
+ ret = -ENODEV;
+ goto out_release;
+ }
+
+ cdev = list_first_entry(&dev->cdevs, struct cdev, devices_list);
+ if (!cdev) {
+ ret = -ENODEV;
+ goto out_release;
+ }
- dev_info(dev, "outpath: %s\n", path);
+ path = asprintf("/dev/%s", cdev->name);
+ of_path = partition_node->full_name;
+ }
ret = of_property_read_string(np, "backend-type", &backend_type);
- if (ret)
- return ret;
- else if (!strcmp(backend_type, "raw"))
- ret = state_backend_raw_file(state, path, 0, 0);
- else if (!strcmp(backend_type, "dtb"))
- ret = state_backend_dtb_file(state, path);
- else
+ if (ret) {
+ goto out_free;
+ } else if (!strcmp(backend_type, "raw")) {
+ ret = state_backend_raw_file(state, of_path, path, 0, 0);
+ } else if (!strcmp(backend_type, "dtb")) {
+ ret = state_backend_dtb_file(state, of_path, path);
+ } else {
dev_warn(dev, "invalid backend type: %s\n", backend_type);
+ ret = -ENODEV;
+ goto out_free;
+ }
if (ret)
- return ret;
+ goto out_free;
- state_load(state);
+ dev_info(dev, "backend: %s, path: %s, of_path: %s\n", backend_type, path, of_path);
+ free(path);
+ state_load(state);
return 0;
+
+ out_free:
+ free(path);
+ out_release:
+ state_release(state);
+ return ret;
}
static __maybe_unused struct of_device_id state_ids[] = {
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index e94e6b1f63..ea1be556b4 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -20,9 +20,20 @@ config MTD_RAW_DEVICE
default n
prompt "mtdraw device to read/write both data+oob"
+config MTD_CONCAT
+ bool
+ prompt "MTD concatenating support"
+ help
+ Support for concatenating several MTD devices into a single
+ (virtual) one. This allows you to have -for example- a JFFS(2)
+ file system spanning multiple physical flash chips. This option
+ needs driver support, currently only the cfi-flash driver supports
+ concatenating MTD devices.
+
source "drivers/mtd/devices/Kconfig"
source "drivers/mtd/nor/Kconfig"
source "drivers/mtd/nand/Kconfig"
+source "drivers/mtd/spi-nor/Kconfig"
source "drivers/mtd/ubi/Kconfig"
endif
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 9c7725742e..d3ae7fca3e 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -1,7 +1,9 @@
obj-$(CONFIG_NAND) += nand/
obj-$(CONFIG_DRIVER_CFI) += nor/
+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor/
obj-$(CONFIG_MTD_UBI) += ubi/
obj-y += devices/
obj-$(CONFIG_MTD) += core.o partition.o
obj-$(CONFIG_MTD_OOB_DEVICE) += mtdoob.o
obj-$(CONFIG_MTD_RAW_DEVICE) += mtdraw.o
+obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 1755e7680f..fda903441c 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -18,7 +18,9 @@
#include <common.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/mtd.h>
+#include <mtd/ubi-user.h>
#include <cmdlinepart.h>
+#include <filetype.h>
#include <init.h>
#include <xfuncs.h>
#include <driver.h>
@@ -191,7 +193,7 @@ static int mtd_op_erase(struct cdev *cdev, size_t count, loff_t offset)
return 0;
}
-static ssize_t mtd_op_protect(struct cdev *cdev, size_t count, loff_t offset, int prot)
+static int mtd_op_protect(struct cdev *cdev, size_t count, loff_t offset, int prot)
{
struct mtd_info *mtd = cdev->priv;
@@ -542,7 +544,42 @@ static int of_mtd_fixup(struct device_node *root, void *ctx)
return 0;
}
-int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
+static int mtd_detect(struct device_d *dev)
+{
+ struct mtd_info *mtd = container_of(dev, struct mtd_info, class_dev);
+ int bufsize = 512;
+ void *buf;
+ int ret;
+ enum filetype filetype;
+ size_t retlen;
+
+ /*
+ * Do not try to attach an UBI device if this device has partitions
+ * as it's not a good idea to attach UBI on a raw device when the
+ * real UBI only spans the first partition.
+ */
+ if (!list_empty(&mtd->partitions))
+ return -EBUSY;
+
+ buf = xmalloc(bufsize);
+
+ ret = mtd_read(mtd, 0, bufsize, &retlen, buf);
+ if (ret)
+ goto out;
+
+ filetype = file_detect_type(buf, bufsize);
+ if (filetype == filetype_ubi) {
+ ret = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 20);
+ if (ret == -EEXIST)
+ ret = 0;
+ }
+out:
+ free(buf);
+
+ return ret;
+}
+
+int add_mtd_device(struct mtd_info *mtd, const char *devname, int device_id)
{
struct mtddev_hook *hook;
int ret;
@@ -554,6 +591,9 @@ int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
if (mtd->parent)
mtd->class_dev.parent = mtd->parent;
+ if (IS_ENABLED(CONFIG_MTD_UBI))
+ mtd->class_dev.detect = mtd_detect;
+
ret = register_device(&mtd->class_dev);
if (ret)
return ret;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 7f9c306258..9c3925bde1 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -22,6 +22,7 @@ config MTD_DATAFLASH_WRITE_VERIFY
config MTD_M25P80
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
depends on SPI
+ select MTD_SPI_NOR
help
This enables access to most modern SPI flash chips, used for
program and data storage. Series supported include Atmel AT26DF,
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index efef98490b..794c9dbd82 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -25,775 +25,202 @@
#include <errno.h>
#include <linux/err.h>
#include <clock.h>
-#include <linux/math64.h>
-#include <linux/mtd/cfi.h>
#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <linux/mod_devicetable.h>
-/* Flash opcodes. */
-#define OPCODE_WREN 0x06 /* Write enable */
-#define OPCODE_RDSR 0x05 /* Read status register */
-#define OPCODE_WRSR 0x01 /* Write status register 1 byte */
-#define OPCODE_NORM_READ 0x03 /* Read data bytes (low frequency) */
-#define OPCODE_FAST_READ 0x0b /* Read data bytes (high frequency) */
-#define OPCODE_PP 0x02 /* Page program (up to 256 bytes) */
-#define OPCODE_BE_4K 0x20 /* Erase 4KiB block */
-#define OPCODE_BE_32K 0x52 /* Erase 32KiB block */
-#define OPCODE_CHIP_ERASE 0xc7 /* Erase whole flash chip */
-#define OPCODE_SE 0xd8 /* Sector erase (usually 64KiB) */
-#define OPCODE_RDID 0x9f /* Read JEDEC ID */
-
-/* Used for SST flashes only. */
-#define OPCODE_BP 0x02 /* Byte program */
-#define OPCODE_WRDI 0x04 /* Write disable */
-#define OPCODE_AAI_WP 0xad /* Auto address increment word program */
-
-/* Used for Macronix flashes only. */
-#define OPCODE_EN4B 0xb7 /* Enter 4-byte mode */
-#define OPCODE_EX4B 0xe9 /* Exit 4-byte mode */
-
-/* Used for Spansion flashes only. */
-#define OPCODE_BRWR 0x17 /* Bank register write */
-
-/* Status Register bits. */
-#define SR_WIP 1 /* Write in progress */
-#define SR_WEL 2 /* Write enable latch */
-/* meaning of other SR_* bits may differ between vendors */
-#define SR_BP0 4 /* Block protect 0 */
-#define SR_BP1 8 /* Block protect 1 */
-#define SR_BP2 0x10 /* Block protect 2 */
-#define SR_SRWD 0x80 /* SR write protect */
-
-/* Define max times to check status register before we give up. */
-#define MAX_READY_WAIT 40 /* M25P16 specs 40s max chip erase */
#define MAX_CMD_SIZE 6
-#define JEDEC_MFR(_jedec_id) ((_jedec_id) >> 16)
-
-/****************************************************************************/
-
-#define SPI_NAME_SIZE 32
-
struct m25p {
struct spi_device *spi;
+ struct spi_nor spi_nor;
struct mtd_info mtd;
- u16 page_size;
- unsigned sector_size;
- u16 addr_width;
- u8 erase_opcode;
- u8 erase_opcode_4k;
- u8 *command;
+ u8 command[MAX_CMD_SIZE];
};
-static inline struct m25p *mtd_to_m25p(struct mtd_info *mtd)
-{
- return container_of(mtd, struct m25p, mtd);
-}
-
-/****************************************************************************/
-
-/*
- * Internal helper functions
- */
-
-/*
- * Read the status register, returning its value in the location
- * Return the status register value.
- * Returns negative if error occurred.
- */
-static int read_sr(struct m25p *flash)
-{
- ssize_t retval;
- u8 code = OPCODE_RDSR;
- u8 val;
-
- retval = spi_write_then_read(flash->spi, &code, 1, &val, 1);
-
- if (retval < 0) {
- dev_err(&flash->spi->dev, "error %d reading SR\n",
- (int) retval);
- return retval;
- }
-
- return val;
-}
-
-/*
- * Write status register 1 byte
- * Returns negative if error occurred.
- */
-static int write_sr(struct m25p *flash, u8 val)
-{
- flash->command[0] = OPCODE_WRSR;
- flash->command[1] = val;
-
- return spi_write(flash->spi, flash->command, 2);
-}
-
-/*
- * Set write enable latch with Write Enable command.
- * Returns negative if error occurred.
- */
-static inline int write_enable(struct m25p *flash)
-{
- u8 code = OPCODE_WREN;
-
- return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
-}
-
-/*
- * Send write disble instruction to the chip.
- */
-static inline int write_disable(struct m25p *flash)
-{
- u8 code = OPCODE_WRDI;
-
- return spi_write_then_read(flash->spi, &code, 1, NULL, 0);
-}
-
-/*
- * Enable/disable 4-byte addressing mode.
- */
-static inline int set_4byte(struct m25p *flash, u32 jedec_id, int enable)
-{
- switch (JEDEC_MFR(jedec_id)) {
- case CFI_MFR_MACRONIX:
- flash->command[0] = enable ? OPCODE_EN4B : OPCODE_EX4B;
- return spi_write(flash->spi, flash->command, 1);
- default:
- /* Spansion style */
- flash->command[0] = OPCODE_BRWR;
- flash->command[1] = enable << 7;
- return spi_write(flash->spi, flash->command, 2);
- }
-}
-
-/*
- * Service routine to read status register until ready, or timeout occurs.
- * Returns non-zero if error.
- */
-static int wait_till_ready(struct m25p *flash)
-{
- int sr;
- uint64_t timer_start;
-
- timer_start = get_time_ns();
-
- do {
- if ((sr = read_sr(flash)) < 0)
- break;
- else if (!(sr & SR_WIP))
- return 0;
-
- } while (!(is_timeout(timer_start, MAX_READY_WAIT * SECOND)));
-
- return -ETIMEDOUT;
-}
-
-/*
- * Erase the whole flash memory
- *
- * Returns 0 if successful, non-zero otherwise.
- */
-static int erase_chip(struct m25p *flash)
+static int m25p80_read_reg(struct spi_nor *nor, u8 code, u8 *val, int len)
{
- dev_dbg(&flash->spi->dev, "%s %lldKiB\n",
- __func__, (long long)(flash->mtd.size >> 10));
-
- /* Wait until finished previous write command. */
- if (wait_till_ready(flash))
- return -ETIMEDOUT;
-
- /* Send write enable, then erase commands. */
- write_enable(flash);
+ struct m25p *flash = nor->priv;
+ struct spi_device *spi = flash->spi;
+ int ret;
- /* Set up command buffer. */
- flash->command[0] = OPCODE_CHIP_ERASE;
-
- spi_write(flash->spi, flash->command, 1);
+ ret = spi_write_then_read(spi, &code, 1, val, len);
+ if (ret < 0)
+ dev_err(&spi->dev, "error %d reading %x\n", ret, code);
- return 0;
+ return ret;
}
-static void m25p_addr2cmd(struct m25p *flash, unsigned int addr, u8 *cmd)
+static void m25p_addr2cmd(struct spi_nor *nor, unsigned int addr, u8 *cmd)
{
/* opcode is in cmd[0] */
- cmd[1] = addr >> (flash->addr_width * 8 - 8);
- cmd[2] = addr >> (flash->addr_width * 8 - 16);
- cmd[3] = addr >> (flash->addr_width * 8 - 24);
- cmd[4] = addr >> (flash->addr_width * 8 - 32);
-}
-
-static int m25p_cmdsz(struct m25p *flash)
-{
- return 1 + flash->addr_width;
+ cmd[1] = addr >> (nor->addr_width * 8 - 8);
+ cmd[2] = addr >> (nor->addr_width * 8 - 16);
+ cmd[3] = addr >> (nor->addr_width * 8 - 24);
+ cmd[4] = addr >> (nor->addr_width * 8 - 32);
}
-/*
- * Erase one sector of flash memory at offset ``offset'' which is any
- * address within the sector which should be erased.
- *
- * Returns 0 if successful, non-zero otherwise.
- */
-static int erase_sector(struct m25p *flash, u32 offset, u32 command)
+static int m25p_cmdsz(struct spi_nor *nor)
{
- dev_dbg(&flash->spi->dev, "%s %dKiB at 0x%08x\n",
- __func__, flash->mtd.erasesize / 1024, offset);
-
- /* Wait until finished previous write command. */
- if (wait_till_ready(flash))
- return -ETIMEDOUT;
-
- /* Send write enable, then erase commands. */
- write_enable(flash);
-
- /* Set up command buffer. */
- flash->command[0] = command;
- m25p_addr2cmd(flash, offset, flash->command);
-
- spi_write(flash->spi, flash->command, m25p_cmdsz(flash));
-
- return 0;
+ return 1 + nor->addr_width;
}
-/****************************************************************************/
-
-/*
- * MTD implementation
- */
-
-/*
- * Erase an address range on the flash chip. The address range may extend
- * one or more erase sectors. Return an error is there is a problem erasing.
- */
-static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
+static int m25p80_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
+ int wr_en)
{
- struct m25p *flash = mtd_to_m25p(mtd);
- u32 addr;
- uint32_t rem;
- uint64_t len;
-
- dev_dbg(&flash->spi->dev, "%s at 0x%llx, len %lld\n",
- __func__, (long long)instr->addr,
- (long long)instr->len);
-
- div_u64_rem(instr->len, mtd->erasesize, &rem);
- if (rem)
- return -EINVAL;
-
- addr = instr->addr;
- len = instr->len;
-
- /* whole-chip erase? */
- if (len == flash->mtd.size) {
- if (erase_chip(flash)) {
- instr->state = MTD_ERASE_FAILED;
- return -EIO;
- }
- return 0;
- }
-
- if (flash->erase_opcode_4k) {
- while (len && (addr & (flash->sector_size - 1))) {
- if (ctrlc())
- return -EINTR;
- if (erase_sector(flash, addr, flash->erase_opcode_4k))
- return -EIO;
- addr += mtd->erasesize;
- len -= mtd->erasesize;
- }
-
- while (len >= flash->sector_size) {
- if (ctrlc())
- return -EINTR;
- if (erase_sector(flash, addr, flash->erase_opcode))
- return -EIO;
- addr += flash->sector_size;
- len -= flash->sector_size;
- }
-
- while (len) {
- if (ctrlc())
- return -EINTR;
- if (erase_sector(flash, addr, flash->erase_opcode_4k))
- return -EIO;
- addr += mtd->erasesize;
- len -= mtd->erasesize;
- }
- } else {
- while (len) {
- if (ctrlc())
- return -EINTR;
- if (erase_sector(flash, addr, flash->erase_opcode))
- return -EIO;
-
- if (len <= mtd->erasesize)
- break;
- addr += mtd->erasesize;
- len -= mtd->erasesize;
- }
- }
-
- if (wait_till_ready(flash))
- return -ETIMEDOUT;
+ struct m25p *flash = nor->priv;
+ struct spi_device *spi = flash->spi;
- instr->state = MTD_ERASE_DONE;
- mtd_erase_callback(instr);
+ flash->command[0] = opcode;
+ if (buf)
+ memcpy(&flash->command[1], buf, len);
- return 0;
+ return spi_write(spi, flash->command, len + 1);
}
-/*
- * Read an address range from the flash chip. The address range
- * may be any size provided it is within the physical boundaries.
- */
-static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+static void m25p80_write(struct spi_nor *nor, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
{
- struct m25p *flash = mtd_to_m25p(mtd);
- struct spi_transfer t[2];
+ struct m25p *flash = nor->priv;
+ struct spi_device *spi = flash->spi;
+ struct spi_transfer t[2] = {};
struct spi_message m;
- int fast_read = 0;
-
- if (flash->spi->max_speed_hz >= 25000000)
- fast_read = 1;
+ int cmd_sz = m25p_cmdsz(nor);
spi_message_init(&m);
- memset(t, 0, (sizeof t));
- /* NOTE:
- * OPCODE_FAST_READ (if available) is faster.
- * Should add 1 byte DUMMY_BYTE.
- */
+ if (nor->program_opcode == SPINOR_OP_AAI_WP && nor->sst_write_second)
+ cmd_sz = 1;
+
+ flash->command[0] = nor->program_opcode;
+ m25p_addr2cmd(nor, to, flash->command);
+
t[0].tx_buf = flash->command;
- t[0].len = m25p_cmdsz(flash) + fast_read;
+ t[0].len = cmd_sz;
spi_message_add_tail(&t[0], &m);
- t[1].rx_buf = buf;
+ t[1].tx_buf = buf;
t[1].len = len;
spi_message_add_tail(&t[1], &m);
- /* Wait till previous write/erase is done. */
- if (wait_till_ready(flash))
- return -ETIMEDOUT;
-
- /* FIXME switch to OPCODE_FAST_READ. It's required for higher
- * clocks; and at this writing, every chip this driver handles
- * supports that opcode.
- */
-
- /* Set up the write data buffer. */
- flash->command[0] = fast_read ? OPCODE_FAST_READ : OPCODE_NORM_READ;
- m25p_addr2cmd(flash, from, flash->command);
-
- spi_sync(flash->spi, &m);
-
- *retlen = m.actual_length - m25p_cmdsz(flash) - fast_read;
+ spi_sync(spi, &m);
- return 0;
+ *retlen += m.actual_length - cmd_sz;
}
/*
- * Write an address range to the flash chip. Data must be written in
- * FLASH_PAGESIZE chunks. The address range may be any size provided
- * it is within the physical boundaries.
+ * Read an address range from the nor chip. The address range
+ * may be any size provided it is within the physical boundaries.
*/
-static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int m25p80_read(struct spi_nor *nor, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
{
- struct m25p *flash = mtd_to_m25p(mtd);
- u32 page_offset, page_size;
+ struct m25p *flash = nor->priv;
+ struct spi_device *spi = flash->spi;
struct spi_transfer t[2];
struct spi_message m;
+ unsigned int dummy = nor->read_dummy;
- dev_dbg(&flash->spi->dev, "m25p80_write %ld bytes at 0x%08llx\n",
- (unsigned long)len, to);
+ /* convert the dummy cycles to the number of bytes */
+ dummy /= 8;
spi_message_init(&m);
memset(t, 0, (sizeof t));
+ flash->command[0] = nor->read_opcode;
+ m25p_addr2cmd(nor, from, flash->command);
+
t[0].tx_buf = flash->command;
- t[0].len = m25p_cmdsz(flash);
+ t[0].len = m25p_cmdsz(nor) + dummy;
spi_message_add_tail(&t[0], &m);
- t[1].tx_buf = buf;
+ t[1].rx_buf = buf;
+ t[1].len = len;
spi_message_add_tail(&t[1], &m);
- /* Wait until finished previous write command. */
- if (wait_till_ready(flash))
- return -ETIMEDOUT;
-
- write_enable(flash);
-
- /* Set up the opcode in the write buffer. */
- flash->command[0] = OPCODE_PP;
- m25p_addr2cmd(flash, to, flash->command);
-
- page_offset = to & (flash->page_size - 1);
-
- /* do all the bytes fit onto one page? */
- if (page_offset + len <= flash->page_size) {
- t[1].len = len;
-
- spi_sync(flash->spi, &m);
-
- *retlen = m.actual_length - m25p_cmdsz(flash);
- } else {
- u32 i;
-
- /* the size of data remaining on the first page */
- page_size = flash->page_size - page_offset;
-
- t[1].len = page_size;
- spi_sync(flash->spi, &m);
-
- *retlen = m.actual_length - m25p_cmdsz(flash);
-
- /* write everything in flash->page_size chunks */
- for (i = page_size; i < len; i += page_size) {
- page_size = len - i;
- if (page_size > flash->page_size)
- page_size = flash->page_size;
-
- /* write the next page to flash */
- m25p_addr2cmd(flash, to + i, flash->command);
-
- t[1].tx_buf = buf + i;
- t[1].len = page_size;
-
- wait_till_ready(flash);
-
- write_enable(flash);
-
- spi_sync(flash->spi, &m);
-
- *retlen += m.actual_length - m25p_cmdsz(flash);
- }
- }
+ spi_sync(spi, &m);
+ *retlen = m.actual_length - m25p_cmdsz(nor) - dummy;
return 0;
}
-static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+static int m25p80_erase(struct spi_nor *nor, loff_t offset)
{
- struct m25p *flash = mtd_to_m25p(mtd);
- struct spi_transfer t[2];
- struct spi_message m;
- size_t actual;
- int cmd_sz, ret;
-
- dev_dbg(&flash->spi->dev, "%s to 0x%08x, len %zd\n",
- __func__, (u32)to, len);
-
- spi_message_init(&m);
- memset(t, 0, (sizeof t));
+ struct m25p *flash = nor->priv;
- t[0].tx_buf = flash->command;
- t[0].len = m25p_cmdsz(flash);
- spi_message_add_tail(&t[0], &m);
+ dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
+ flash->mtd.erasesize / 1024, (u32)offset);
- t[1].tx_buf = buf;
- spi_message_add_tail(&t[1], &m);
+ /* Set up command buffer. */
+ flash->command[0] = nor->erase_opcode;
+ m25p_addr2cmd(nor, offset, flash->command);
- /* Wait until finished previous write command. */
- ret = wait_till_ready(flash);
- if (ret)
- goto time_out;
-
- write_enable(flash);
-
- actual = to % 2;
- /* Start write from odd address. */
- if (actual) {
- flash->command[0] = OPCODE_BP;
- m25p_addr2cmd(flash, to, flash->command);
-
- /* write one byte. */
- t[1].len = 1;
- spi_sync(flash->spi, &m);
- ret = wait_till_ready(flash);
- if (ret)
- goto time_out;
- *retlen += m.actual_length - m25p_cmdsz(flash);
- }
- to += actual;
-
- flash->command[0] = OPCODE_AAI_WP;
- m25p_addr2cmd(flash, to, flash->command);
-
- /* Write out most of the data here. */
- cmd_sz = m25p_cmdsz(flash);
- for (; actual < len - 1; actual += 2) {
- t[0].len = cmd_sz;
- /* write two bytes. */
- t[1].len = 2;
- t[1].tx_buf = buf + actual;
-
- spi_sync(flash->spi, &m);
- ret = wait_till_ready(flash);
- if (ret)
- goto time_out;
- *retlen += m.actual_length - cmd_sz;
- cmd_sz = 1;
- to += 2;
- }
- write_disable(flash);
- ret = wait_till_ready(flash);
- if (ret)
- goto time_out;
-
- /* Write out trailing byte if it exists. */
- if (actual != len) {
- write_enable(flash);
- flash->command[0] = OPCODE_BP;
- m25p_addr2cmd(flash, to, flash->command);
- t[0].len = m25p_cmdsz(flash);
- t[1].len = 1;
- t[1].tx_buf = buf + actual;
-
- spi_sync(flash->spi, &m);
- ret = wait_till_ready(flash);
- if (ret)
- goto time_out;
- *retlen += m.actual_length - m25p_cmdsz(flash);
- write_disable(flash);
- }
+ spi_write(flash->spi, flash->command, m25p_cmdsz(nor));
-time_out:
- return ret;
+ return 0;
}
-/****************************************************************************/
-
/*
- * SPI device driver setup and teardown
- */
-
-struct flash_info {
- /* JEDEC id zero means "no ID" (most older chips); otherwise it has
- * a high byte of zero plus three data bytes: the manufacturer id,
- * then a two byte device id.
- */
- u32 jedec_id;
- u16 ext_id;
-
- /* The size listed here is what works with OPCODE_SE, which isn't
- * necessarily called a "sector" by the vendor.
- */
- unsigned sector_size;
- u16 n_sectors;
-
- u16 page_size;
- u16 addr_width;
-
- u16 flags;
-#define SECT_4K 0x01 /* OPCODE_BE_4K works uniformly */
-#define M25P_NO_ERASE 0x02 /* No erase command needed */
-};
-
-#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
- ((unsigned long)&(struct flash_info) { \
- .jedec_id = (_jedec_id), \
- .ext_id = (_ext_id), \
- .sector_size = (_sector_size), \
- .n_sectors = (_n_sectors), \
- .page_size = 256, \
- .flags = (_flags), \
- })
-
-#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width) \
- ((unsigned long)&(struct flash_info) { \
- .sector_size = (_sector_size), \
- .n_sectors = (_n_sectors), \
- .page_size = (_page_size), \
- .addr_width = (_addr_width), \
- .flags = M25P_NO_ERASE, \
- })
-
-/* NOTE: double check command sets and memory organization when you add
- * more flash chips. This current list focusses on newer chips, which
- * have been converging on command sets which including JEDEC ID.
+ * Do NOT add to this array without reading the following:
+ *
+ * Historically, many flash devices are bound to this driver by their name. But
+ * since most of these flash are compatible to some extent, and their
+ * differences can often be differentiated by the JEDEC read-ID command, we
+ * encourage new users to add support to the spi-nor library, and simply bind
+ * against a generic string here (e.g., "nor-jedec").
+ *
+ * Many flash names are kept here in this list (as well as in spi-nor.c) to
+ * keep them available as module aliases for existing platforms.
*/
static const struct platform_device_id m25p_ids[] = {
- /* Atmel -- some are (confusingly) marketed as "DataFlash" */
- { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
- { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
-
- { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
- { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
- { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
-
- { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
- { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
- { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
- { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
-
- { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
-
- /* EON -- en25xxx */
- { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
- { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
- { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
- { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
- { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
-
- /* Everspin */
- { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2) },
-
- /* Intel/Numonyx -- xxxs33b */
- { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
- { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
- { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
-
- /* Macronix */
- { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
- { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
- { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
- { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
- { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
- { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
- { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
- { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
- { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
- { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
-
- /* Micron */
- { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
- { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
- { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
- { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K) },
-
- /* Spansion -- single (large) sector size only, at least
- * for the chips listed here (without boot sectors).
+ {"at25fs010"}, {"at25fs040"}, {"at25df041a"}, {"at25df321a"},
+ {"at25df641"}, {"at26f004"}, {"at26df081a"}, {"at26df161a"},
+ {"at26df321"}, {"at45db081d"},
+ {"en25f32"}, {"en25p32"}, {"en25q32b"}, {"en25p64"},
+ {"en25q64"}, {"en25qh128"}, {"en25qh256"},
+ {"f25l32pa"},
+ {"mr25h256"}, {"mr25h10"},
+ {"gd25q32"}, {"gd25q64"},
+ {"160s33b"}, {"320s33b"}, {"640s33b"},
+ {"mx25l2005a"}, {"mx25l4005a"}, {"mx25l8005"}, {"mx25l1606e"},
+ {"mx25l3205d"}, {"mx25l3255e"}, {"mx25l6405d"}, {"mx25l12805d"},
+ {"mx25l12855e"},{"mx25l25635e"},{"mx25l25655e"},{"mx66l51235l"},
+ {"mx66l1g55g"},
+ {"n25q064"}, {"n25q128a11"}, {"n25q128a13"}, {"n25q256a"},
+ {"n25q512a"}, {"n25q512ax3"}, {"n25q00"},
+ {"pm25lv512"}, {"pm25lv010"}, {"pm25lq032"},
+ {"s25sl032p"}, {"s25sl064p"}, {"s25fl256s0"}, {"s25fl256s1"},
+ {"s25fl512s"}, {"s70fl01gs"}, {"s25sl12800"}, {"s25sl12801"},
+ {"s25fl129p0"}, {"s25fl129p1"}, {"s25sl004a"}, {"s25sl008a"},
+ {"s25sl016a"}, {"s25sl032a"}, {"s25sl064a"}, {"s25fl008k"},
+ {"s25fl016k"}, {"s25fl064k"}, {"s25fl132k"},
+ {"sst25vf040b"},{"sst25vf080b"},{"sst25vf016b"},{"sst25vf032b"},
+ {"sst25vf064c"},{"sst25wf512"}, {"sst25wf010"}, {"sst25wf020"},
+ {"sst25wf040"},
+ {"m25p05"}, {"m25p10"}, {"m25p20"}, {"m25p40"},
+ {"m25p80"}, {"m25p16"}, {"m25p32"}, {"m25p64"},
+ {"m25p128"}, {"n25q032"},
+ {"m25p05-nonjedec"}, {"m25p10-nonjedec"}, {"m25p20-nonjedec"},
+ {"m25p40-nonjedec"}, {"m25p80-nonjedec"}, {"m25p16-nonjedec"},
+ {"m25p32-nonjedec"}, {"m25p64-nonjedec"}, {"m25p128-nonjedec"},
+ {"m45pe10"}, {"m45pe80"}, {"m45pe16"},
+ {"m25pe20"}, {"m25pe80"}, {"m25pe16"},
+ {"m25px16"}, {"m25px32"}, {"m25px32-s0"}, {"m25px32-s1"},
+ {"m25px64"}, {"m25px80"},
+ {"w25x10"}, {"w25x20"}, {"w25x40"}, {"w25x80"},
+ {"w25x16"}, {"w25x32"}, {"w25q32"}, {"w25q32dw"},
+ {"w25x64"}, {"w25q64"}, {"w25q80"}, {"w25q80bl"},
+ {"w25q128"}, {"w25q256"}, {"cat25c11"},
+ {"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"},
+
+ /*
+ * Generic support for SPI NOR that can be identified by the JEDEC READ
+ * ID opcode (0x9F). Use this, if possible.
*/
- { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, 0) },
- { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) },
- { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
- { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, 0) },
- { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, 0) },
- { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
- { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
- { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
- { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) },
- { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) },
- { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
- { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
- { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
- { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
- { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
- { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) },
- { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
-
- /* SST -- large erase sizes are "overlays", "sectors" are 4K */
- { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K) },
- { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K) },
- { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K) },
- { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K) },
- { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K) },
- { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K) },
- { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K) },
- { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K) },
-
- /* ST Microelectronics -- newer production may have feature updates */
- { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
- { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
- { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
- { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
- { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
- { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
- { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
- { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
- { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
- { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) },
-
- { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
- { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
- { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
- { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
- { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
- { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
- { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
- { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
- { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
-
- { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
- { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
- { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
-
- { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) },
- { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
- { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
-
- { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) },
- { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
-
- /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
- { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
- { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
- { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
- { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
- { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) },
- { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
- { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
- { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-
- /* Catalyst / On Semiconductor -- non-JEDEC */
- { "cat25c11", CAT25_INFO( 16, 8, 16, 1) },
- { "cat25c03", CAT25_INFO( 32, 8, 16, 2) },
- { "cat25c09", CAT25_INFO( 128, 8, 32, 2) },
- { "cat25c17", CAT25_INFO( 256, 8, 32, 2) },
- { "cat25128", CAT25_INFO(2048, 8, 64, 2) },
+ {"nor-jedec"},
{ },
};
-static const struct platform_device_id *jedec_probe(struct spi_device *spi)
-{
- int tmp;
- u8 code = OPCODE_RDID;
- u8 id[5];
- u32 jedec;
- u16 ext_jedec;
- struct flash_info *info;
-
- /* JEDEC also defines an optional "extended device information"
- * string for after vendor-specific data, after the three bytes
- * we use here. Supporting some chips might require using it.
- */
- tmp = spi_write_then_read(spi, &code, 1, id, 5);
- if (tmp < 0) {
- dev_dbg(&spi->dev, "%s: error %d reading JEDEC ID\n",
- dev_name(&spi->dev), tmp);
- return ERR_PTR(tmp);
- }
- jedec = id[0];
- jedec = jedec << 8;
- jedec |= id[1];
- jedec = jedec << 8;
- jedec |= id[2];
-
- ext_jedec = id[3] << 8 | id[4];
-
- for (tmp = 0; tmp < ARRAY_SIZE(m25p_ids) - 1; tmp++) {
- info = (void *)m25p_ids[tmp].driver_data;
- if (info->jedec_id == jedec) {
- if (info->ext_id != 0 && info->ext_id != ext_jedec)
- continue;
- return &m25p_ids[tmp];
- }
- }
- dev_err(&spi->dev, "unrecognized JEDEC id %06x\n", jedec);
- return ERR_PTR(-ENODEV);
-}
-
-
/*
* board specific setup should have ensured the SPI clock used here
* matches what the READ command supports, at least until this driver
@@ -802,164 +229,65 @@ static const struct platform_device_id *jedec_probe(struct spi_device *spi)
static int m25p_probe(struct device_d *dev)
{
struct spi_device *spi = (struct spi_device *)dev->type_data;
- const struct platform_device_id *id = NULL;
struct flash_platform_data *data;
struct m25p *flash;
- struct flash_info *info = NULL;
- unsigned i;
- unsigned do_jdec_probe = 1;
- char *flashname = NULL;
- const char *typename = NULL;
+ struct spi_nor *nor;
+ enum read_mode mode = SPI_NOR_NORMAL;
+ const char *flash_name = NULL;
int device_id;
+ int ret;
- /* Platform data helps sort out which chip type we have, as
- * well as how this board partitions it. If we don't have
- * a chip ID, try the JEDEC id commands; they'll work for most
- * newer chips, even if we don't recognize the particular chip.
- */
data = dev->platform_data;
- if (data && data->type)
- typename = data->type;
- else if (dev->id_entry)
- typename = dev->id_entry->name;
-
- if (typename) {
- const struct platform_device_id *plat_id;
-
- for (i = 0; i < ARRAY_SIZE(m25p_ids) - 1; i++) {
- plat_id = &m25p_ids[i];
- if (strcmp(typename, plat_id->name))
- continue;
- break;
- }
-
- if (i < ARRAY_SIZE(m25p_ids) - 1) {
- id = plat_id;
- info = (void *)id->driver_data;
- /* If flash type is provided but the memory is not
- * JEDEC compliant, don't try to probe the JEDEC id */
- if (!info->jedec_id)
- do_jdec_probe = 0;
- } else
- dev_warn(&spi->dev, "unrecognized id %s\n", typename);
- }
-
- if (do_jdec_probe) {
- const struct platform_device_id *jid;
-
- jid = jedec_probe(spi);
- if (IS_ERR(jid)) {
- return PTR_ERR(jid);
- } else if (jid != id) {
- /*
- * JEDEC knows better, so overwrite platform ID. We
- * can't trust partitions any longer, but we'll let
- * mtd apply them anyway, since some partitions may be
- * marked read-only, and we don't want to lose that
- * information, even if it's not 100% accurate.
- */
- if (id)
- dev_warn(dev, "found %s, expected %s\n",
- jid->name, id->name);
-
- id = jid;
- info = (void *)jid->driver_data;
- }
- }
flash = xzalloc(sizeof *flash);
- flash->command = xmalloc(MAX_CMD_SIZE);
- flash->spi = spi;
- dev->priv = (void *)flash;
- /*
- * Atmel, SST and Intel/Numonyx serial flash tend to power
- * up with the software protection bits set
- */
+ nor = &flash->spi_nor;
- if (JEDEC_MFR(info->jedec_id) == CFI_MFR_ATMEL ||
- JEDEC_MFR(info->jedec_id) == CFI_MFR_INTEL ||
- JEDEC_MFR(info->jedec_id) == CFI_MFR_SST) {
- write_enable(flash);
- write_sr(flash, 0);
- }
+ /* install the hooks */
+ nor->read = m25p80_read;
+ nor->write = m25p80_write;
+ nor->erase = m25p80_erase;
+ nor->write_reg = m25p80_write_reg;
+ nor->read_reg = m25p80_read_reg;
- device_id = DEVICE_ID_SINGLE;
- if (dev->device_node) {
- const char *alias = of_alias_get(dev->device_node);
- if (alias)
- flashname = xstrdup(alias);
- } else if (data && data->name) {
- flashname = data->name;
- }
+ nor->dev = dev;
+ nor->mtd = &flash->mtd;
+ nor->priv = flash;
- if (!flashname) {
- device_id = DEVICE_ID_DYNAMIC;
- flashname = "m25p";
- }
+ flash->mtd.priv = nor;
+ flash->mtd.parent = &spi->dev;
+ flash->spi = spi;
+
+ dev->priv = (void *)flash;
- flash->mtd.type = MTD_NORFLASH;
- flash->mtd.writesize = 1;
- flash->mtd.flags = MTD_CAP_NORFLASH;
- flash->mtd.size = (uint64_t)info->sector_size * info->n_sectors;
- flash->mtd.erase = m25p80_erase;
- flash->mtd.read = m25p80_read;
+ if (data && data->name)
+ flash->mtd.name = data->name;
- /* sst flash chips use AAI word program */
- if (IS_ENABLED(CONFIG_MTD_SST25L) && JEDEC_MFR(info->jedec_id) == CFI_MFR_SST)
- flash->mtd.write = sst_write;
+ if (data && data->type)
+ flash_name = data->type;
+ else if (data && data->name)
+ flash_name = data->name;
+ else if (dev->id_entry)
+ flash_name = dev->id_entry->name;
else
- flash->mtd.write = m25p80_write;
-
- /* prefer "small sector" erase if possible */
- if (info->flags & SECT_4K) {
- flash->erase_opcode_4k = OPCODE_BE_4K;
- flash->erase_opcode = OPCODE_SE;
- flash->mtd.erasesize = 4096;
- } else {
- flash->erase_opcode = OPCODE_SE;
- flash->mtd.erasesize = info->sector_size;
- }
+ flash_name = NULL; /* auto-detect */
- if (info->flags & M25P_NO_ERASE)
- flash->mtd.flags |= MTD_NO_ERASE;
+ ret = spi_nor_scan(nor, flash_name, mode);
+ if (ret)
+ return ret;
- flash->mtd.parent = &spi->dev;
- flash->page_size = info->page_size;
- flash->sector_size = info->sector_size;
-
- if (info->addr_width)
- flash->addr_width = info->addr_width;
- else {
- /* enable 4-byte addressing if the device exceeds 16MiB */
- if (flash->mtd.size > 0x1000000) {
- flash->addr_width = 4;
- set_4byte(flash, info->jedec_id, 1);
- } else
- flash->addr_width = 3;
+ device_id = DEVICE_ID_SINGLE;
+ if (dev->device_node)
+ flash_name = of_alias_get(dev->device_node);
+ else if (data && data->name)
+ flash_name = data->name;
+
+ if (!flash_name) {
+ device_id = DEVICE_ID_DYNAMIC;
+ flash_name = "m25p";
}
- dev_info(dev, "%s (%lld Kbytes)\n", id->name,
- (long long)flash->mtd.size >> 10);
-
- dev_dbg(dev, "mtd .name = %s, .size = 0x%llx (%lldMiB) "
- ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
- flash->mtd.name,
- (long long)flash->mtd.size, (long long)(flash->mtd.size >> 20),
- flash->mtd.erasesize, flash->mtd.erasesize / 1024,
- flash->mtd.numeraseregions);
-
- if (flash->mtd.numeraseregions)
- for (i = 0; i < flash->mtd.numeraseregions; i++)
- dev_dbg(dev, "mtd.eraseregions[%d] = { .offset = 0x%llx, "
- ".erasesize = 0x%.8x (%uKiB), "
- ".numblocks = %d }\n",
- i, (long long)flash->mtd.eraseregions[i].offset,
- flash->mtd.eraseregions[i].erasesize,
- flash->mtd.eraseregions[i].erasesize / 1024,
- flash->mtd.eraseregions[i].numblocks);
-
- return add_mtd_device(&flash->mtd, flashname, device_id);
+ return add_mtd_device(&flash->mtd, flash_name, device_id);
}
static __maybe_unused struct of_device_id m25p80_dt_ids[] = {
diff --git a/drivers/mtd/mtd.h b/drivers/mtd/mtd.h
index 414bd6cdb5..2a85265f98 100644
--- a/drivers/mtd/mtd.h
+++ b/drivers/mtd/mtd.h
@@ -25,7 +25,7 @@
*/
struct mtddev_hook {
struct list_head hook;
- int (*add_mtd_device)(struct mtd_info *mtd, char *devname, void **priv);
+ int (*add_mtd_device)(struct mtd_info *mtd, const char *devname, void **priv);
int (*del_mtd_device)(struct mtd_info *mtd, void **priv);
void *priv;
};
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
new file mode 100644
index 0000000000..10d3dc4c36
--- /dev/null
+++ b/drivers/mtd/mtdconcat.c
@@ -0,0 +1,765 @@
+/*
+ * MTD device concatenation layer
+ *
+ * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
+ * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * NAND support by Christian Gan <cgan@iders.ca>
+ *
+ * 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <common.h>
+#include <malloc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/concat.h>
+
+#include <asm-generic/div64.h>
+
+/*
+ * Our storage structure:
+ * Subdev points to an array of pointers to struct mtd_info objects
+ * which is allocated along with this structure
+ *
+ */
+struct mtd_concat {
+ struct mtd_info mtd;
+ int num_subdev;
+ struct mtd_info **subdev;
+};
+
+/*
+ * how to calculate the size required for the above structure,
+ * including the pointer array subdev points to:
+ */
+#define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \
+ ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
+
+/*
+ * Given a pointer to the MTD object in the mtd_concat structure,
+ * we can retrieve the pointer to that structure with this macro.
+ */
+#define CONCAT(x) ((struct mtd_concat *)(x))
+
+/*
+ * MTD methods which look up the relevant subdevice, translate the
+ * effective address and pass through to the subdevice.
+ */
+
+static int
+concat_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int ret = 0, err;
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (from >= subdev->size) {
+ /* Not destined for this subdev */
+ size = 0;
+ from -= subdev->size;
+ continue;
+ }
+ if (from + len > subdev->size)
+ /* First part goes into this subdev */
+ size = subdev->size - from;
+ else
+ /* Entire transaction goes into this subdev */
+ size = len;
+
+ err = mtd_read(subdev, from, size, &retsize, buf);
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (mtd_is_eccerr(err)) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (mtd_is_bitflip(err)) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ return ret;
+
+ buf += size;
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int err = -EINVAL;
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (to >= subdev->size) {
+ size = 0;
+ to -= subdev->size;
+ continue;
+ }
+ if (to + len > subdev->size)
+ size = subdev->size - to;
+ else
+ size = len;
+
+ err = mtd_write(subdev, to, size, &retsize, buf);
+ if (err)
+ break;
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ buf += size;
+ to = 0;
+ }
+ return err;
+}
+
+static int
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err, ret = 0;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (from >= subdev->size) {
+ from -= subdev->size;
+ continue;
+ }
+
+ /* partial read ? */
+ if (from + devops.len > subdev->size)
+ devops.len = subdev->size - from;
+
+ err = mtd_read_oob(subdev, from, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (mtd_is_eccerr(err)) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (mtd_is_bitflip(err)) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return ret;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return ret;
+ devops.oobbuf += ops->oobretlen;
+ }
+
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (to >= subdev->size) {
+ to -= subdev->size;
+ continue;
+ }
+
+ /* partial write ? */
+ if (to + devops.len > subdev->size)
+ devops.len = subdev->size - to;
+
+ err = mtd_write_oob(subdev, to, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+ if (err)
+ return err;
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return 0;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return 0;
+ devops.oobbuf += devops.oobretlen;
+ }
+ to = 0;
+ }
+ return -EINVAL;
+}
+
+static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ int err;
+ wait_queue_head_t waitq;
+
+ erase->mtd = mtd;
+ erase->priv = (unsigned long) &waitq;
+
+ err = mtd_erase(mtd, erase);
+
+ return err;
+}
+
+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_info *subdev;
+ int i, err;
+ uint64_t length, offset = 0;
+ struct erase_info *erase;
+
+ /*
+ * Check for proper erase block alignment of the to-be-erased area.
+ * It is easier to do this based on the super device's erase
+ * region info rather than looking at each particular sub-device
+ * in turn.
+ */
+ if (!concat->mtd.numeraseregions) {
+ /* the easy case: device has uniform erase block size */
+ if (instr->addr & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ if (instr->len & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ } else {
+ /* device has variable erase size */
+ struct mtd_erase_region_info *erase_regions =
+ concat->mtd.eraseregions;
+
+ /*
+ * Find the erase region where the to-be-erased area begins:
+ */
+ for (i = 0; i < concat->mtd.numeraseregions &&
+ instr->addr >= erase_regions[i].offset; i++) ;
+ --i;
+
+ /*
+ * Now erase_regions[i] is the region in which the
+ * to-be-erased area begins. Verify that the starting
+ * offset is aligned to this region's erase size:
+ */
+ if (i < 0 || instr->addr & (erase_regions[i].erasesize - 1))
+ return -EINVAL;
+
+ /*
+ * now find the erase region where the to-be-erased area ends:
+ */
+ for (; i < concat->mtd.numeraseregions &&
+ (instr->addr + instr->len) >= erase_regions[i].offset;
+ ++i) ;
+ --i;
+ /*
+ * check if the ending offset is aligned to this region's erase size
+ */
+ if (i < 0 || ((instr->addr + instr->len) &
+ (erase_regions[i].erasesize - 1)))
+ return -EINVAL;
+ }
+
+ /* make a local copy of instr to avoid modifying the caller's struct */
+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
+
+ if (!erase)
+ return -ENOMEM;
+
+ *erase = *instr;
+ length = instr->len;
+
+ /*
+ * find the subdevice where the to-be-erased area begins, adjust
+ * starting offset to be relative to the subdevice start
+ */
+ for (i = 0; i < concat->num_subdev; i++) {
+ subdev = concat->subdev[i];
+ if (subdev->size <= erase->addr) {
+ erase->addr -= subdev->size;
+ offset += subdev->size;
+ } else {
+ break;
+ }
+ }
+
+ /* must never happen since size limit has been verified above */
+ BUG_ON(i >= concat->num_subdev);
+
+ /* now do the erase: */
+ err = 0;
+ for (; length > 0; i++) {
+ /* loop for all subdevices affected by this request */
+ subdev = concat->subdev[i]; /* get current subdevice */
+
+ /* limit length to subdevice's size: */
+ if (erase->addr + length > subdev->size)
+ erase->len = subdev->size - erase->addr;
+ else
+ erase->len = length;
+
+ length -= erase->len;
+ if ((err = concat_dev_erase(subdev, erase))) {
+ /* sanity check: should never happen since
+ * block alignment has been checked above */
+ BUG_ON(err == -EINVAL);
+ if (erase->fail_addr != 0xffffffff)
+ instr->fail_addr = erase->fail_addr + offset;
+ break;
+ }
+ /*
+ * erase->addr specifies the offset of the area to be
+ * erased *within the current subdevice*. It can be
+ * non-zero only the first time through this loop, i.e.
+ * for the first subdevice where blocks need to be erased.
+ * All the following erases must begin at the start of the
+ * current subdevice, i.e. at offset zero.
+ */
+ erase->addr = 0;
+ offset += subdev->size;
+ }
+ instr->state = erase->state;
+ kfree(erase);
+ if (err)
+ return err;
+
+ if (instr->callback)
+ instr->callback(instr);
+ return 0;
+}
+
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = mtd_lock(subdev, ofs, size);
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = mtd_unlock(subdev, ofs, size);
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, res = 0;
+
+ if (!mtd_can_have_bb(concat->subdev[0]))
+ return res;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ res = mtd_block_isbad(subdev, ofs);
+ break;
+ }
+
+ return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ err = mtd_block_markbad(subdev, ofs);
+ if (!err)
+ mtd->ecc_stats.badblocks++;
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * This function constructs a virtual MTD device by concatenating
+ * num_devs MTD devices. A pointer to the new device object is
+ * stored to *new_dev upon success. This function does _not_
+ * register any devices: this is the caller's responsibility.
+ */
+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name)
+{ /* name for the new device */
+ int i;
+ size_t size;
+ struct mtd_concat *concat;
+ uint32_t max_erasesize, curr_erasesize;
+ int num_erase_region;
+ int max_writebufsize = 0;
+
+ printk(KERN_NOTICE "Concatenating MTD devices:\n");
+ for (i = 0; i < num_devs; i++)
+ printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name);
+ printk(KERN_NOTICE "into device \"%s\"\n", name);
+
+ /* allocate the device structure */
+ size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
+ concat = kzalloc(size, GFP_KERNEL);
+ if (!concat) {
+ printk
+ ("memory allocation error while creating concatenated device \"%s\"\n",
+ name);
+ return NULL;
+ }
+ concat->subdev = (struct mtd_info **) (concat + 1);
+
+ /*
+ * Set up the new "super" device's MTD object structure, check for
+ * incompatibilities between the subdevices.
+ */
+ concat->mtd.type = subdev[0]->type;
+ concat->mtd.flags = subdev[0]->flags;
+ concat->mtd.size = subdev[0]->size;
+ concat->mtd.erasesize = subdev[0]->erasesize;
+ concat->mtd.writesize = subdev[0]->writesize;
+
+ for (i = 0; i < num_devs; i++)
+ if (max_writebufsize < subdev[i]->writebufsize)
+ max_writebufsize = subdev[i]->writebufsize;
+ concat->mtd.writebufsize = max_writebufsize;
+
+ concat->mtd.subpage_sft = subdev[0]->subpage_sft;
+ concat->mtd.oobsize = subdev[0]->oobsize;
+ concat->mtd.oobavail = subdev[0]->oobavail;
+ if (subdev[0]->read_oob)
+ concat->mtd.read_oob = concat_read_oob;
+ if (subdev[0]->write_oob)
+ concat->mtd.write_oob = concat_write_oob;
+ if (subdev[0]->block_isbad)
+ concat->mtd.block_isbad = concat_block_isbad;
+ if (subdev[0]->block_markbad)
+ concat->mtd.block_markbad = concat_block_markbad;
+
+ concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
+
+ concat->subdev[0] = subdev[0];
+
+ for (i = 1; i < num_devs; i++) {
+ if (concat->mtd.type != subdev[i]->type) {
+ kfree(concat);
+ printk("Incompatible device type on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ if (concat->mtd.flags != subdev[i]->flags) {
+ /*
+ * Expect all flags except MTD_WRITEABLE to be
+ * equal on all subdevices.
+ */
+ if ((concat->mtd.flags ^ subdev[i]->
+ flags) & ~MTD_WRITEABLE) {
+ kfree(concat);
+ printk("Incompatible device flags on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ } else
+ /* if writeable attribute differs,
+ make super device writeable */
+ concat->mtd.flags |=
+ subdev[i]->flags & MTD_WRITEABLE;
+ }
+
+ concat->mtd.size += subdev[i]->size;
+ concat->mtd.ecc_stats.badblocks +=
+ subdev[i]->ecc_stats.badblocks;
+ if (concat->mtd.writesize != subdev[i]->writesize ||
+ concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
+ concat->mtd.oobsize != subdev[i]->oobsize ||
+ !concat->mtd.read_oob != !subdev[i]->read_oob ||
+ !concat->mtd.write_oob != !subdev[i]->write_oob) {
+ kfree(concat);
+ printk("Incompatible OOB or ECC data on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ concat->subdev[i] = subdev[i];
+
+ }
+
+ concat->mtd.ecclayout = subdev[0]->ecclayout;
+
+ concat->num_subdev = num_devs;
+ concat->mtd.name = xstrdup(name);
+
+ concat->mtd.erase = concat_erase;
+ concat->mtd.read = concat_read;
+ concat->mtd.write = concat_write;
+ concat->mtd.lock = concat_lock;
+ concat->mtd.unlock = concat_unlock;
+
+ /*
+ * Combine the erase block size info of the subdevices:
+ *
+ * first, walk the map of the new device and see how
+ * many changes in erase size we have
+ */
+ max_erasesize = curr_erasesize = subdev[0]->erasesize;
+ num_erase_region = 1;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /* if it differs from the last subdevice's erase size, count it */
+ ++num_erase_region;
+ curr_erasesize = subdev[i]->erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].erasesize !=
+ curr_erasesize) {
+ ++num_erase_region;
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ }
+ }
+ }
+
+ if (num_erase_region == 1) {
+ /*
+ * All subdevices have the same uniform erase size.
+ * This is easy:
+ */
+ concat->mtd.erasesize = curr_erasesize;
+ concat->mtd.numeraseregions = 0;
+ } else {
+ uint64_t tmp64;
+
+ /*
+ * erase block size varies across the subdevices: allocate
+ * space to store the data describing the variable erase regions
+ */
+ struct mtd_erase_region_info *erase_region_p;
+ uint64_t begin, position;
+
+ concat->mtd.erasesize = max_erasesize;
+ concat->mtd.numeraseregions = num_erase_region;
+ concat->mtd.eraseregions = erase_region_p =
+ kmalloc(num_erase_region *
+ sizeof (struct mtd_erase_region_info), GFP_KERNEL);
+ if (!erase_region_p) {
+ kfree(concat);
+ printk
+ ("memory allocation error while creating erase region list"
+ " for device \"%s\"\n", name);
+ return NULL;
+ }
+
+ /*
+ * walk the map of the new device once more and fill in
+ * in erase region info:
+ */
+ curr_erasesize = subdev[0]->erasesize;
+ begin = position = 0;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /*
+ * fill in an mtd_erase_region_info structure for the area
+ * we have walked so far:
+ */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize = subdev[i]->erasesize;
+ ++erase_region_p;
+ }
+ position += subdev[i]->size;
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].
+ erasesize != curr_erasesize) {
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ ++erase_region_p;
+ }
+ position +=
+ subdev[i]->eraseregions[j].
+ numblocks * (uint64_t)curr_erasesize;
+ }
+ }
+ }
+ /* Now write the final entry */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize = curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ }
+
+ return &concat->mtd;
+}
+
+/*
+ * This function destroys an MTD object obtained from concat_mtd_devs()
+ */
+
+void mtd_concat_destroy(struct mtd_info *mtd)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ if (concat->mtd.numeraseregions)
+ kfree(concat->mtd.eraseregions);
+ kfree(concat);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Kaiser <rkaiser@sysgo.de>");
+MODULE_DESCRIPTION("Generic support for concatenating of MTD devices");
diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c
index 10d17e90d2..6160ddba08 100644
--- a/drivers/mtd/mtdoob.c
+++ b/drivers/mtd/mtdoob.c
@@ -69,7 +69,7 @@ static struct file_operations mtd_ops_oob = {
.lseek = dev_lseek_default,
};
-static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv)
+static int add_mtdoob_device(struct mtd_info *mtd, const char *devname, void **priv)
{
struct mtdoob *mtdoob;
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
index c25e4062ee..ae4bec2a4c 100644
--- a/drivers/mtd/mtdraw.c
+++ b/drivers/mtd/mtdraw.c
@@ -281,7 +281,7 @@ static const struct file_operations mtd_raw_fops = {
.lseek = dev_lseek_default,
};
-static int add_mtdraw_device(struct mtd_info *mtd, char *devname, void **priv)
+static int add_mtdraw_device(struct mtd_info *mtd, const char *devname, void **priv)
{
struct mtdraw *mtdraw;
diff --git a/drivers/mtd/nand/nand-bb.c b/drivers/mtd/nand/nand-bb.c
index 539c685482..8e4600ab03 100644
--- a/drivers/mtd/nand/nand-bb.c
+++ b/drivers/mtd/nand/nand-bb.c
@@ -54,7 +54,7 @@ static ssize_t nand_bb_read(struct cdev *cdev, void *buf, size_t count,
size_t retlen;
int ret, bytes = 0, now;
- debug("%s offset: 0x%08llx (raw: 0x%08llx) count: 0x%08x\n",
+ debug("%s offset: 0x%08llx (raw: 0x%08llx) count: 0x%08zx\n",
__func__, offset, bb->offset, count);
while (count) {
@@ -132,7 +132,7 @@ static ssize_t nand_bb_write(struct cdev *cdev, const void *buf, size_t count,
struct nand_bb *bb = cdev->priv;
int bytes = count, now, wroffs, ret;
- debug("%s offset: 0x%08llx (raw: 0x%08llx) count: 0x%08x\n",
+ debug("%s offset: 0x%08llx (raw: 0x%08llx) count: 0x%08zx\n",
__func__, offset, bb->offset, count);
while (count) {
diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c
index 0fa41bf67b..f2268dfde7 100644
--- a/drivers/mtd/nor/cfi_flash.c
+++ b/drivers/mtd/nor/cfi_flash.c
@@ -40,6 +40,8 @@
#include <errno.h>
#include <progress.h>
#include <linux/err.h>
+#include <asm/unaligned.h>
+#include <linux/mtd/concat.h>
#include "cfi_flash.h"
/*
@@ -58,7 +60,9 @@
*
*/
-static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
+static unsigned int flash_offset_cfi[2] = {
+ FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT
+};
/*
* Check if chip width is defined. If not, start detecting with 8bit.
@@ -72,7 +76,7 @@ static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
* Functions
*/
-static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
+static void flash_add_byte(struct flash_info *info, cfiword_t *cword, u8 c)
{
if (bankwidth_is_1(info)) {
*cword = c;
@@ -94,7 +98,7 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
#endif
}
-static int flash_write_cfiword (struct flash_info *info, ulong dest,
+static int flash_write_cfiword(struct flash_info *info, unsigned long dest,
cfiword_t cword)
{
void *dstaddr = (void *)dest;
@@ -110,34 +114,21 @@ static int flash_write_cfiword (struct flash_info *info, ulong dest,
else if (bankwidth_is_8(info))
flag = ((flash_read64(dstaddr) & cword) == cword);
else
- return 2;
+ return -EIO;
if (!flag)
- return 2;
+ return -EIO;
info->cfi_cmd_set->flash_prepare_write(info);
flash_write_word(info, cword, (void *)dest);
- return flash_status_check (info, find_sector (info, dest),
+ return flash_status_check(info, find_sector (info, dest),
info->write_tout, "write");
}
#ifdef DEBUG
-/*
- * Debug support
- */
-void print_longlong (char *str, unsigned long long data)
-{
- int i;
- char *cp;
-
- cp = (unsigned char *) &data;
- for (i = 0; i < 8; i++)
- sprintf (&str[i * 2], "%2.2x", *cp++);
-}
-
-static void flash_printqry (struct cfi_qry *qry)
+static void flash_printqry(struct cfi_qry *qry)
{
u8 *p = (u8 *)qry;
int x, y;
@@ -163,9 +154,9 @@ static void flash_printqry (struct cfi_qry *qry)
/*
* read a character at a port width address
*/
-uchar flash_read_uchar (struct flash_info *info, uint offset)
+u8 flash_read_uchar(struct flash_info *info, unsigned int offset)
{
- uchar *cp = flash_make_addr(info, 0, offset);
+ u8 *cp = flash_make_addr(info, 0, offset);
#if defined __LITTLE_ENDIAN
return flash_read8(cp);
#else
@@ -177,23 +168,20 @@ uchar flash_read_uchar (struct flash_info *info, uint offset)
* read a long word by picking the least significant byte of each maximum
* port size word. Swap for ppc format.
*/
-static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint offset)
+static unsigned long flash_read_long(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset)
{
- uchar *addr;
- ulong retval;
-
-#ifdef DEBUG
+ u8 *addr;
+ unsigned long retval;
int x;
-#endif
+
addr = flash_make_addr (info, sect, offset);
-#ifdef DEBUG
dev_dbg(info->dev, "long addr is at %p info->portwidth = %d\n", addr,
info->portwidth);
- for (x = 0; x < 4 * info->portwidth; x++) {
+ for (x = 0; x < 4 * info->portwidth; x++)
dev_dbg(info->dev, "addr[%x] = 0x%x\n", x, flash_read8(addr + x));
- }
-#endif
+
#if defined __LITTLE_ENDIAN
retval = ((flash_read8(addr) << 16) |
(flash_read8(addr + info->portwidth) << 24) |
@@ -216,14 +204,14 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o
u32 jedec_read_mfr(struct flash_info *info)
{
int bank = 0;
- uchar mfr;
+ u8 mfr;
/* According to JEDEC "Standard Manufacturer's Identification Code"
* (http://www.jedec.org/download/search/jep106W.pdf)
* several first banks can contain 0x7f instead of actual ID
*/
do {
- mfr = flash_read_uchar (info,
+ mfr = flash_read_uchar(info,
(bank << 8) | FLASH_OFFSET_MANUFACTURER_ID);
bank++;
} while (mfr == FLASH_ID_CONTINUATION);
@@ -231,7 +219,7 @@ u32 jedec_read_mfr(struct flash_info *info)
return mfr;
}
-static void flash_read_cfi (struct flash_info *info, void *buf,
+static void flash_read_cfi(struct flash_info *info, void *buf,
unsigned int start, size_t len)
{
u8 *p = buf;
@@ -241,45 +229,53 @@ static void flash_read_cfi (struct flash_info *info, void *buf,
p[i] = flash_read_uchar(info, start + i);
}
-static int flash_detect_width (struct flash_info *info, struct cfi_qry *qry)
+static int flash_detect_width(struct flash_info *info, struct cfi_qry *qry)
{
int cfi_offset;
+ int pw, cw;
+
+ for (pw = CFG_FLASH_CFI_WIDTH; pw <= FLASH_CFI_64BIT; pw <<= 1) {
+ for (cw = FLASH_CFI_BY8; cw <= pw; cw <<= 1) {
+ info->chipwidth = cw;
+ info->portwidth = pw;
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ for (cfi_offset = 0;
+ cfi_offset < sizeof(flash_offset_cfi) / sizeof(unsigned int);
+ cfi_offset++) {
- for (info->portwidth = CFG_FLASH_CFI_WIDTH;
- info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
- for (info->chipwidth = FLASH_CFI_BY8;
- info->chipwidth <= info->portwidth;
- info->chipwidth <<= 1) {
- flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
- for (cfi_offset=0; cfi_offset < sizeof(flash_offset_cfi)/sizeof(uint); cfi_offset++) {
- flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
- if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
- flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
- sizeof(struct cfi_qry));
- info->interface = le16_to_cpu(qry->interface_desc);
-
- info->cfi_offset=flash_offset_cfi[cfi_offset];
- dev_dbg(info->dev, "device interface is %d\n",
- info->interface);
- dev_dbg(info->dev, "found port %d chip %d chip_lsb %d ",
- info->portwidth, info->chipwidth, info->chip_lsb);
- dev_dbg(info->dev, "port %d bits chip %d bits\n",
- info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- return 1;
- }
+ flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
+
+ if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') &&
+ flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') &&
+ flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y'))
+ goto found;
}
}
}
- dev_dbg(info->dev, "not found\n");
+
+ dev_dbg(info->dev, "no flash found\n");
+
+ return -ENODEV;
+
+found:
+ flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+ sizeof(struct cfi_qry));
+ info->interface = get_unaligned_le16(&qry->interface_desc);
+ info->cfi_offset = flash_offset_cfi[cfi_offset];
+ dev_dbg(info->dev, "device interface is %d\n", info->interface);
+ dev_dbg(info->dev, "found port %d chip %d chip_lsb %d ",
+ info->portwidth, info->chipwidth, info->chip_lsb);
+ dev_dbg(info->dev, "port %d bits chip %d bits\n",
+ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
return 0;
}
-static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry)
+static int flash_detect_cfi(struct flash_info *info, struct cfi_qry *qry)
{
int ret;
@@ -287,180 +283,184 @@ static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry)
info->chip_lsb = 0;
ret = flash_detect_width (info, qry);
- if (!ret) {
- info->chip_lsb = 1;
- ret = flash_detect_width (info, qry);
- }
- return ret;
+ if (!ret)
+ return 0;
+
+ info->chip_lsb = 1;
+ return flash_detect_width (info, qry);
}
/*
* The following code cannot be run from FLASH!
*/
-static ulong flash_get_size (struct flash_info *info)
+static int flash_detect_size(struct flash_info *info)
{
- int i, j;
+ int i, j, ret;
flash_sect_t sect_cnt;
unsigned long sector;
unsigned long tmp;
int size_ratio;
- uchar num_erase_regions;
+ int num_erase_regions;
int erase_region_size;
int erase_region_count;
int cur_offset = 0;
- struct cfi_qry qry;
+ struct cfi_qry qry = {};
unsigned long base = (unsigned long)info->base;
- memset(&qry, 0, sizeof(qry));
-
info->ext_addr = 0;
info->cfi_version = 0;
-#ifdef CFG_FLASH_PROTECTION
- info->legacy_unlock = 0;
-#endif
/* first only malloc space for the first sector */
- info->start = xmalloc(sizeof(ulong));
+ info->start = xmalloc(sizeof(*info->eraseregions));
info->start[0] = base;
info->protect = 0;
- if (flash_detect_cfi (info, &qry)) {
- info->vendor = le16_to_cpu(qry.p_id);
- info->ext_addr = le16_to_cpu(qry.p_adr);
- num_erase_regions = qry.num_erase_regions;
+ ret = flash_detect_cfi(info, &qry);
+ if (ret)
+ return ret;
- if (info->ext_addr) {
- info->cfi_version = (ushort) flash_read_uchar (info,
- info->ext_addr + 3) << 8;
- info->cfi_version |= (ushort) flash_read_uchar (info,
- info->ext_addr + 4);
- }
+ info->vendor = get_unaligned_le16(&qry.p_id);
+ info->ext_addr = get_unaligned_le16(&qry.p_adr);
+ num_erase_regions = qry.num_erase_regions;
+
+ if (info->ext_addr) {
+ info->cfi_version = (u16)flash_read_uchar (info,
+ info->ext_addr + 3) << 8;
+ info->cfi_version |= (u16)flash_read_uchar (info,
+ info->ext_addr + 4);
+ }
#ifdef DEBUG
- flash_printqry (&qry);
+ flash_printqry(&qry);
#endif
- switch (info->vendor) {
-#ifdef CONFIG_DRIVER_CFI_INTEL
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ if (IS_ENABLED(CONFIG_DRIVER_CFI_INTEL))
info->cfi_cmd_set = &cfi_cmd_set_intel;
- break;
-#endif
-#ifdef CONFIG_DRIVER_CFI_AMD
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ if (IS_ENABLED(CONFIG_DRIVER_CFI_AMD))
info->cfi_cmd_set = &cfi_cmd_set_amd;
+ break;
+ }
+
+ if (!info->cfi_cmd_set) {
+ dev_err(info->dev, "unsupported vendor 0x%04x\n", info->vendor);
+ return -ENOSYS;
+ }
+
+ info->cfi_cmd_set->flash_read_jedec_ids (info);
+ flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+ info->cfi_cmd_set->flash_fixup (info, &qry);
+
+ dev_dbg(info->dev, "manufacturer is %d\n", info->vendor);
+ dev_dbg(info->dev, "manufacturer id is 0x%x\n", info->manufacturer_id);
+ dev_dbg(info->dev, "device id is 0x%x\n", info->device_id);
+ dev_dbg(info->dev, "device id2 is 0x%x\n", info->device_id2);
+ dev_dbg(info->dev, "cfi version is 0x%04x\n", info->cfi_version);
+
+ size_ratio = info->portwidth / info->chipwidth;
+
+ /* if the chip is x8/x16 reduce the ratio by half */
+ if ((info->interface == FLASH_CFI_X8X16)
+ && (info->chipwidth == FLASH_CFI_BY8)
+ && (size_ratio != 1)) {
+ size_ratio >>= 1;
+ }
+
+ dev_dbg(info->dev, "size_ratio %d port %d bits chip %d bits\n",
+ size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ dev_dbg(info->dev, "found %d erase regions\n", num_erase_regions);
+
+ info->eraseregions = xzalloc(sizeof(*info->eraseregions) * num_erase_regions);
+ info->numeraseregions = num_erase_regions;
+ sect_cnt = 0;
+ sector = base;
+
+ for (i = 0; i < num_erase_regions; i++) {
+ struct mtd_erase_region_info *region = &info->eraseregions[i];
+
+ if (i > NUM_ERASE_REGIONS) {
+ dev_info(info->dev, "%d erase regions found, only %d used\n",
+ num_erase_regions, NUM_ERASE_REGIONS);
break;
-#endif
- default:
- dev_err(info->dev, "unsupported vendor\n");
- return 0;
}
- info->cfi_cmd_set->flash_read_jedec_ids (info);
- flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
-
- info->cfi_cmd_set->flash_fixup (info, &qry);
-
- dev_dbg(info->dev, "manufacturer is %d\n", info->vendor);
- dev_dbg(info->dev, "manufacturer id is 0x%x\n", info->manufacturer_id);
- dev_dbg(info->dev, "device id is 0x%x\n", info->device_id);
- dev_dbg(info->dev, "device id2 is 0x%x\n", info->device_id2);
- dev_dbg(info->dev, "cfi version is 0x%04x\n", info->cfi_version);
-
- size_ratio = info->portwidth / info->chipwidth;
- /* if the chip is x8/x16 reduce the ratio by half */
- if ((info->interface == FLASH_CFI_X8X16)
- && (info->chipwidth == FLASH_CFI_BY8)
- && (size_ratio != 1)) {
- size_ratio >>= 1;
- }
- dev_dbg(info->dev, "size_ratio %d port %d bits chip %d bits\n",
- size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- dev_dbg(info->dev, "found %d erase regions\n", num_erase_regions);
- info->eraseregions = xzalloc(sizeof(*(info->eraseregions)) * num_erase_regions);
- info->numeraseregions = num_erase_regions;
- sect_cnt = 0;
- sector = base;
-
- for (i = 0; i < num_erase_regions; i++) {
- struct mtd_erase_region_info *region = &info->eraseregions[i];
-
- if (i > NUM_ERASE_REGIONS) {
- dev_info(info->dev, "%d erase regions found, only %d used\n",
- num_erase_regions, NUM_ERASE_REGIONS);
- break;
- }
- tmp = le32_to_cpu(qry.erase_region_info[i]);
- dev_dbg(info->dev, "erase region %u: 0x%08lx\n", i, tmp);
-
- erase_region_count = (tmp & 0xffff) + 1;
- tmp >>= 16;
- erase_region_size =
- (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
- dev_dbg(info->dev, "erase_region_count = %d erase_region_size = %d\n",
- erase_region_count, erase_region_size);
-
- region->offset = cur_offset;
- region->erasesize = erase_region_size * size_ratio;
- region->numblocks = erase_region_count;
- cur_offset += erase_region_size * size_ratio * erase_region_count;
-
- /* increase the space malloced for the sector start addresses */
- info->start = xrealloc(info->start, sizeof(ulong) * (erase_region_count + sect_cnt));
- info->protect = xrealloc(info->protect, sizeof(uchar) * (erase_region_count + sect_cnt));
-
- for (j = 0; j < erase_region_count; j++) {
- info->start[sect_cnt] = sector;
- sector += (erase_region_size * size_ratio);
-
- /*
- * Only read protection status from supported devices (intel...)
- */
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- info->protect[sect_cnt] =
- flash_isset (info, sect_cnt,
- FLASH_OFFSET_PROTECT,
- FLASH_STATUS_PROTECT);
- break;
- default:
- info->protect[sect_cnt] = 0; /* default: not protected */
- }
-
- sect_cnt++;
+ tmp = get_unaligned_le32(&qry.erase_region_info[i]);
+ dev_dbg(info->dev, "erase region %u: 0x%08lx\n", i, tmp);
+
+ erase_region_count = (tmp & 0xffff) + 1;
+ tmp >>= 16;
+ erase_region_size =
+ (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
+ dev_dbg(info->dev, "erase_region_count = %d erase_region_size = %d\n",
+ erase_region_count, erase_region_size);
+
+ region->offset = cur_offset;
+ region->erasesize = erase_region_size * size_ratio;
+ region->numblocks = erase_region_count;
+ cur_offset += erase_region_size * size_ratio * erase_region_count;
+
+ /* increase the space malloced for the sector start addresses */
+ info->start = xrealloc(info->start, sizeof(*info->eraseregions) *
+ (erase_region_count + sect_cnt));
+ info->protect = xrealloc(info->protect, sizeof(*info->eraseregions) *
+ (erase_region_count + sect_cnt));
+
+ for (j = 0; j < erase_region_count; j++) {
+ info->start[sect_cnt] = sector;
+ sector += (erase_region_size * size_ratio);
+
+ /*
+ * Only read protection status from supported devices (intel...)
+ */
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ info->protect[sect_cnt] =
+ flash_isset (info, sect_cnt,
+ FLASH_OFFSET_PROTECT,
+ FLASH_STATUS_PROTECT);
+ break;
+ default:
+ info->protect[sect_cnt] = 0; /* default: not protected */
}
- }
- info->sector_count = sect_cnt;
- /* multiply the size by the number of chips */
- info->size = (1 << qry.dev_size) * size_ratio;
- info->buffer_size = (1 << le16_to_cpu(qry.max_buf_write_size));
- info->erase_blk_tout = 1 << (qry.block_erase_timeout_typ +
- qry.block_erase_timeout_max);
- info->buffer_write_tout = 1 << (qry.buf_write_timeout_typ +
- qry.buf_write_timeout_max);
- info->write_tout = 1 << (qry.word_write_timeout_typ +
- qry.word_write_timeout_max);
- info->flash_id = FLASH_MAN_CFI;
- if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
- info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
+ sect_cnt++;
}
- flash_write_cmd (info, 0, 0, info->cmd_reset);
}
- return info->size;
+ info->sector_count = sect_cnt;
+ /* multiply the size by the number of chips */
+ info->size = (1 << qry.dev_size) * size_ratio;
+ info->buffer_size = (1 << get_unaligned_le16(&qry.max_buf_write_size));
+ info->erase_blk_tout = 1 << (qry.block_erase_timeout_typ +
+ qry.block_erase_timeout_max);
+ info->buffer_write_tout = 1 << (qry.buf_write_timeout_typ +
+ qry.buf_write_timeout_max);
+ info->write_tout = 1 << (qry.word_write_timeout_typ +
+ qry.word_write_timeout_max);
+ info->flash_id = FLASH_MAN_CFI;
+
+ if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8))
+ info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
+
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
+
+ return 0;
}
/* loop through the sectors from the highest address
* when the passed address is greater or equal to the sector address
* we have a match
*/
-flash_sect_t find_sector (struct flash_info *info, ulong addr)
+flash_sect_t find_sector(struct flash_info *info, unsigned long addr)
{
flash_sect_t sector;
@@ -468,6 +468,7 @@ flash_sect_t find_sector (struct flash_info *info, ulong addr)
if (addr >= info->start[sector])
break;
}
+
return sector;
}
@@ -496,43 +497,40 @@ out:
return ret;
}
-/*
- * Copy memory to flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-static int write_buff (struct flash_info *info, const uchar * src, ulong addr, ulong cnt)
+static int write_buff(struct flash_info *info, const u8 *src,
+ unsigned long addr, unsigned long cnt)
{
- ulong wp;
- uchar *p;
+ unsigned long wp;
+ u8 *p;
int aln;
cfiword_t cword;
- int i, rc;
+ int i, ret;
#ifdef CONFIG_CFI_BUFFER_WRITE
int buffered_size;
#endif
/* get lower aligned address */
- wp = (addr & ~(info->portwidth - 1));
+ wp = addr & ~(info->portwidth - 1);
/* handle unaligned start */
- if ((aln = addr - wp) != 0) {
+ aln = addr - wp;
+ if (aln) {
cword = 0;
- p = (uchar*)wp;
+ p = (u8 *)wp;
for (i = 0; i < aln; ++i)
- flash_add_byte (info, &cword, flash_read8(p + i));
+ flash_add_byte(info, &cword, flash_read8(p + i));
for (; (i < info->portwidth) && (cnt > 0); i++) {
- flash_add_byte (info, &cword, *src++);
+ flash_add_byte(info, &cword, *src++);
cnt--;
}
+
for (; (cnt == 0) && (i < info->portwidth); ++i)
- flash_add_byte (info, &cword, flash_read8(p + i));
+ flash_add_byte(info, &cword, flash_read8(p + i));
- rc = flash_write_cfiword (info, wp, cword);
- if (rc != 0)
- return rc;
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
wp += i;
}
@@ -545,12 +543,17 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
/* prohibit buffer write when buffer_size is 1 */
if (info->buffer_size == 1) {
cword = 0;
+
for (i = 0; i < info->portwidth; i++)
- flash_add_byte (info, &cword, *src++);
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
+ flash_add_byte(info, &cword, *src++);
+
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
+
wp += info->portwidth;
cnt -= info->portwidth;
+
continue;
}
@@ -558,8 +561,11 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
i = buffered_size - (wp % buffered_size);
if (i > cnt)
i = cnt;
- if ((rc = info->cfi_cmd_set->flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
- return rc;
+
+ ret = info->cfi_cmd_set->flash_write_cfibuffer(info, wp, src, i);
+ if (ret)
+ return ret;
+
i -= i & (info->portwidth - 1);
wp += i;
src += i;
@@ -568,64 +574,67 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
#else
while (cnt >= info->portwidth) {
cword = 0;
- for (i = 0; i < info->portwidth; i++) {
- flash_add_byte (info, &cword, *src++);
- }
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
+
+ for (i = 0; i < info->portwidth; i++)
+ flash_add_byte(info, &cword, *src++);
+
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
+
wp += info->portwidth;
cnt -= info->portwidth;
}
#endif /* CONFIG_CFI_BUFFER_WRITE */
- if (cnt == 0) {
+ if (cnt == 0)
return 0;
- }
/*
* handle unaligned tail bytes
*/
cword = 0;
- p = (uchar*)wp;
+ p = (u8 *)wp;
+
for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
- flash_add_byte (info, &cword, *src++);
+ flash_add_byte(info, &cword, *src++);
--cnt;
}
- for (; i < info->portwidth; ++i) {
- flash_add_byte (info, &cword, flash_read8(p + i));
- }
- return flash_write_cfiword (info, wp, cword);
+ for (; i < info->portwidth; ++i)
+ flash_add_byte(info, &cword, flash_read8(p + i));
+
+ return flash_write_cfiword(info, wp, cword);
}
-static int flash_real_protect (struct flash_info *info, long sector, int prot)
+static int flash_real_protect(struct flash_info *info, long sector, int prot)
{
- int retcode = 0;
-
- retcode = info->cfi_cmd_set->flash_real_protect(info, sector, prot);
+ int ret;
- if (retcode)
- return retcode;
+ ret = info->cfi_cmd_set->flash_real_protect(info, sector, prot);
+ if (ret)
+ return ret;
- if ((retcode =
- flash_status_check (info, sector, info->erase_blk_tout,
- prot ? "protect" : "unprotect")) == 0) {
+ ret = flash_status_check(info, sector, info->erase_blk_tout,
+ prot ? "protect" : "unprotect");
+ if (ret)
+ return ret;
- info->protect[sector] = prot;
+ info->protect[sector] = prot;
- /*
- * On some of Intel's flash chips (marked via legacy_unlock)
- * unprotect unprotects all locking.
- */
- if ((prot == 0) && (info->legacy_unlock)) {
- flash_sect_t i;
+ /*
+ * On some of Intel's flash chips (marked via legacy_unlock)
+ * unprotect unprotects all locking.
+ */
+ if (prot == 0 && info->legacy_unlock) {
+ flash_sect_t i;
- for (i = 0; i < info->sector_count; i++) {
- if (info->protect[i])
- flash_real_protect (info, i, 1);
- }
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->protect[i])
+ flash_real_protect (info, i, 1);
}
}
- return retcode;
+
+ return 0;
}
static int cfi_mtd_protect(struct flash_info *finfo, loff_t offset, size_t len, int prot)
@@ -637,12 +646,12 @@ static int cfi_mtd_protect(struct flash_info *finfo, loff_t offset, size_t len,
end = find_sector(finfo, (unsigned long)finfo->base + offset + len - 1);
for (i = start; i <= end; i++) {
- ret = flash_real_protect (finfo, i, prot);
+ ret = flash_real_protect(finfo, i, prot);
if (ret)
- goto out;
+ return ret;
}
-out:
- return ret;
+
+ return 0;
}
static int cfi_mtd_lock(struct mtd_info *mtd, loff_t offset, size_t len)
@@ -665,50 +674,53 @@ static void cfi_info (struct device_d* dev)
int i;
if (info->flash_id != FLASH_MAN_CFI) {
- puts ("missing or unknown FLASH type\n");
+ printf("missing or unknown FLASH type\n");
return;
}
- printf ("CFI conformant FLASH (%d x %d)",
+ printf("CFI conformant FLASH (%d x %d)",
(info->portwidth << 3), (info->chipwidth << 3));
- printf (" Size: %ld MB in %d Sectors\n",
+ printf(" Size: %ld MB in %d Sectors\n ",
info->size >> 20, info->sector_count);
- printf (" ");
+
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
- printf ("Intel Standard");
+ printf("Intel Standard");
break;
case CFI_CMDSET_INTEL_EXTENDED:
- printf ("Intel Extended");
+ printf("Intel Extended");
break;
case CFI_CMDSET_AMD_STANDARD:
- printf ("AMD Standard");
+ printf("AMD Standard");
break;
case CFI_CMDSET_AMD_EXTENDED:
- printf ("AMD Extended");
+ printf("AMD Extended");
break;
default:
- printf ("Unknown (%d)", info->vendor);
+ printf("Unknown (%d)", info->vendor);
break;
}
- printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
+ printf(" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
info->manufacturer_id, info->device_id);
- if (info->device_id == 0x7E) {
+
+ if (info->device_id == 0x7E)
printf("%04X", info->device_id2);
- }
- printf ("\n Erase timeout: %ld ms, write timeout: %ld us\n",
+
+ printf("\n Erase timeout: %ld ms, write timeout: %ld us\n",
info->erase_blk_tout,
info->write_tout);
+
if (info->buffer_size > 1) {
- printf (" Buffer write timeout: %ld us, buffer size: %d bytes\n",
+ printf(" Buffer write timeout: %ld us, buffer size: %d bytes\n",
info->buffer_write_tout,
info->buffer_size);
}
- puts ("\n Sector Start Addresses:");
+ printf("\n Sector Start Addresses:");
+
for (i = 0; i < info->sector_count; ++i) {
if ((i % 5) == 0)
- printf ("\n");
+ printf("\n");
#ifdef CFG_FLASH_EMPTY_INFO
{
int k;
@@ -724,7 +736,7 @@ static void cfi_info (struct device_d* dev)
else
size = info->start[0] + info->size - info->start[i];
erased = 1;
- flash = (volatile unsigned long *) info->start[i];
+ flash = (volatile unsigned long *)info->start[i];
size = size >> 2; /* divide by 4 for longword access */
for (k = 0; k < size; k++) {
if (*flash++ != 0xffffffff) {
@@ -734,13 +746,13 @@ static void cfi_info (struct device_d* dev)
}
/* print empty and read-only info */
- printf (" %08lX %c %s ",
+ printf(" %08lX %c %s ",
info->start[i],
erased ? 'E' : ' ',
info->protect[i] ? "RO" : " ");
}
#else /* ! CFG_FLASH_EMPTY_INFO */
- printf (" %08lX %s ",
+ printf(" %08lX %s ",
info->start[i],
info->protect[i] ? "RO" : " ");
#endif
@@ -749,41 +761,8 @@ static void cfi_info (struct device_d* dev)
return;
}
-#if 0
-/*
- * flash_read_user_serial - read the OneTimeProgramming cells
- */
-static void flash_read_user_serial (struct flash_info *info, void *buffer, int offset,
- int len)
-{
- uchar *src;
- uchar *dst;
-
- dst = buffer;
- src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (dst, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-/*
- * flash_read_factory_serial - read the device Id from the protection area
- */
-static void flash_read_factory_serial (struct flash_info *info, void *buffer, int offset,
- int len)
-{
- uchar *src;
-
- src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (buffer, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-#endif
-
-int flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+int flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
return info->cfi_cmd_set->flash_status_check(info, sector, tout, prompt);
}
@@ -792,10 +771,10 @@ int flash_status_check (struct flash_info *info, flash_sect_t sector,
* wait for XSR.7 to be set. Time out with an error if it does not.
* This routine does not set the flash to read-array mode.
*/
-int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+int flash_generic_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
- uint64_t start;
+ u64 start;
tout *= 1000000;
@@ -806,12 +785,15 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
dev_err(info->dev, "Flash %s timeout at address %lx data %lx\n",
prompt, info->start[sector],
flash_read_long (info, sector, 0));
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return ERR_TIMOUT;
+
+ flash_write_cmd(info, sector, 0, info->cmd_reset);
+
+ return -ETIMEDOUT;
}
- udelay (1); /* also triggers watchdog */
+ udelay(1); /* also triggers watchdog */
}
- return ERR_OK;
+
+ return 0;
}
/*
@@ -831,23 +813,22 @@ void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf)
* Write a proper sized command to the correct address
*/
void flash_write_cmd(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
-
- uchar *addr;
+ u8 *addr;
cfiword_t cword;
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
- dev_dbg(info->dev, "%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__,
+ dev_vdbg(info->dev, "%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__,
info, sect, offset, addr, cword);
flash_write_word(info, cword, addr);
}
int flash_isequal(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
void *addr;
cfiword_t cword;
@@ -856,36 +837,29 @@ int flash_isequal(struct flash_info *info, flash_sect_t sect,
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
- dev_dbg(info->dev, "is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+ dev_vdbg(info->dev, "is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+
if (bankwidth_is_1(info)) {
- dev_dbg(info->dev, "is= %x %x\n", flash_read8(addr), (u8)cword);
+ dev_vdbg(info->dev, "is= %x %x\n", flash_read8(addr), (u8)cword);
retval = (flash_read8(addr) == cword);
} else if (bankwidth_is_2(info)) {
- dev_dbg(info->dev, "is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword);
+ dev_vdbg(info->dev, "is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword);
retval = (flash_read16(addr) == cword);
} else if (bankwidth_is_4(info)) {
- dev_dbg(info->dev, "is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword);
+ dev_vdbg(info->dev, "is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword);
retval = (flash_read32(addr) == cword);
} else if (bankwidth_is_8(info)) {
-#ifdef DEBUG
- {
- char str1[20];
- char str2[20];
-
- print_longlong (str1, flash_read32(addr));
- print_longlong (str2, cword);
- dev_dbg(info->dev, "is= %s %s\n", str1, str2);
- }
-#endif
+ dev_vdbg(info->dev, "is= %16.16llx %16.16llx\n", flash_read64(addr), (u64)cword);
retval = (flash_read64(addr) == cword);
- } else
+ } else {
retval = 0;
+ }
return retval;
}
int flash_isset(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
void *addr = flash_make_addr (info, sect, offset);
cfiword_t cword;
@@ -900,14 +874,15 @@ int flash_isset(struct flash_info *info, flash_sect_t sect,
retval = ((flash_read32(addr) & cword) == cword);
} else if (bankwidth_is_8(info)) {
retval = ((flash_read64(addr) & cword) == cword);
- } else
+ } else {
retval = 0;
+ }
return retval;
}
static int cfi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+ size_t *retlen, u8 *buf)
{
struct flash_info *info = container_of(mtd, struct flash_info, mtd);
@@ -918,7 +893,7 @@ static int cfi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
}
static int cfi_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+ size_t *retlen, const u8 *buf)
{
struct flash_info *info = container_of(mtd, struct flash_info, mtd);
int ret;
@@ -935,7 +910,6 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
int ret;
ret = cfi_erase(info, instr->len, instr->addr);
-
if (ret) {
instr->state = MTD_ERASE_FAILED;
return -EIO;
@@ -947,10 +921,16 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
return 0;
}
+struct cfi_priv {
+ struct flash_info *infos;
+ int num_devs;
+ struct mtd_info **mtds;
+};
+
static void cfi_init_mtd(struct flash_info *info)
{
struct mtd_info *mtd = &info->mtd;
- u_int32_t erasesize;
+ u32 erasesize;
int i;
mtd->read = cfi_mtd_read;
@@ -961,10 +941,11 @@ static void cfi_init_mtd(struct flash_info *info)
mtd->size = info->size;
erasesize = 0;
- for (i=0; i < info->numeraseregions; i++) {
+ for (i = 0; i < info->numeraseregions; i++) {
if (erasesize < info->eraseregions[i].erasesize)
erasesize = info->eraseregions[i].erasesize;
}
+
mtd->erasesize = erasesize;
mtd->writesize = 1;
@@ -974,38 +955,84 @@ static void cfi_init_mtd(struct flash_info *info)
mtd->flags = MTD_CAP_NORFLASH;
mtd->type = MTD_NORFLASH;
mtd->parent = info->dev;
-
- add_mtd_device(mtd, "nor", DEVICE_ID_DYNAMIC);
}
-static int cfi_probe (struct device_d *dev)
+static int cfi_probe_one(struct flash_info *info, int num)
{
- struct flash_info *info = xzalloc(sizeof(*info));
-
- dev->priv = (void *)info;
+ int ret;
- /* Init: no FLASHes known */
info->flash_id = FLASH_UNKNOWN;
info->cmd_reset = FLASH_CMD_RESET;
- info->base = dev_request_mem_region(dev, 0);
+ info->base = dev_request_mem_region(info->dev, num);
if (IS_ERR(info->base))
return PTR_ERR(info->base);
- info->dev = dev;
- info->size = flash_get_size(info);
-
- if (info->flash_id == FLASH_UNKNOWN) {
- dev_warn(dev, "## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n",
- dev->resource[0].start, info->size, info->size << 20);
+ ret = flash_detect_size(info);
+ if (ret) {
+ dev_warn(info->dev, "## Unknown FLASH on Bank at 0x%p - Size = 0x%08lx = %ld MB\n",
+ info->base, info->size, info->size << 20);
return -ENODEV;
}
- dev_info(dev, "found cfi flash at 0x%p, size %s\n",
+ dev_info(info->dev, "found cfi flash at 0x%p, size %s\n",
info->base, size_human_readable(info->size));
+ cfi_init_mtd(info);
+
+ return 0;
+}
+
+static int cfi_probe(struct device_d *dev)
+{
+ struct cfi_priv *priv;
+ int i, ret;
+ struct mtd_info *mtd;
+ const char *mtd_name = NULL;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->num_devs = dev->num_resources;
+ priv->infos = xzalloc(sizeof(*priv->infos) * priv->num_devs);
+ priv->mtds = xzalloc(sizeof(*priv->mtds) * priv->num_devs);
+
+ of_property_read_string(dev->device_node, "linux,mtd-name", &mtd_name);
+
+ if (!mtd_name)
+ mtd_name = dev_name(dev);
+
+ dev->priv = priv;
+
+ for (i = 0; i < priv->num_devs; i++) {
+ struct flash_info *info = &priv->infos[i];
+
+ info->dev = dev;
+ info->mtd.name = xstrdup(mtd_name);
+
+ ret = cfi_probe_one(info, i);
+ if (ret)
+ return ret;
+ priv->mtds[i] = &priv->infos[i].mtd;
+ }
+
dev->info = cfi_info;
- cfi_init_mtd(info);
+ if (priv->num_devs > 1 && IS_ENABLED(CONFIG_MTD_CONCAT)) {
+ mtd = mtd_concat_create(priv->mtds, priv->num_devs, "nor");
+ if (!mtd) {
+ dev_err(dev, "failed to create concat mtd device\n");
+ return -ENODEV;
+ }
+ } else {
+ if (priv->num_devs > 1)
+ dev_warn(dev, "mtd concat disabled. using first chip only\n");
+ mtd = &priv->infos[0].mtd;
+ }
+
+ mtd->parent = dev;
+
+ ret = add_mtd_device(mtd, "nor", DEVICE_ID_DYNAMIC);
+ if (ret)
+ return ret;
return 0;
}
diff --git a/drivers/mtd/nor/cfi_flash.h b/drivers/mtd/nor/cfi_flash.h
index 9aad5c41f6..e82eb28abe 100644
--- a/drivers/mtd/nor/cfi_flash.h
+++ b/drivers/mtd/nor/cfi_flash.h
@@ -49,32 +49,32 @@ struct cfi_cmd_set;
struct flash_info {
struct device_d *dev;
- ulong size; /* total bank size in bytes */
- ushort sector_count; /* number of erase units */
- ulong flash_id; /* combined device & manufacturer code */
- ulong *start; /* physical sector start addresses */
- uchar *protect; /* sector protection status */
-
- uchar portwidth; /* the width of the port */
- uchar chipwidth; /* the width of the chip */
- uchar chip_lsb; /* extra Least Significant Bit in the */
+ unsigned long size; /* total bank size in bytes */
+ unsigned int sector_count; /* number of erase units */
+ unsigned long flash_id; /* combined device & manufacturer code */
+ unsigned long *start; /* physical sector start addresses */
+ unsigned char *protect; /* sector protection status */
+
+ unsigned int portwidth; /* the width of the port */
+ unsigned int chipwidth; /* the width of the chip */
+ unsigned int chip_lsb; /* extra Least Significant Bit in the */
/* address of chip. */
- ushort buffer_size; /* # of bytes in write buffer */
- ulong erase_blk_tout; /* maximum block erase timeout */
- ulong write_tout; /* maximum write timeout */
- ulong buffer_write_tout; /* maximum buffer write timeout */
- ushort vendor; /* the primary vendor id */
- ushort cmd_reset; /* vendor specific reset command */
- ushort interface; /* used for x8/x16 adjustments */
- ushort legacy_unlock; /* support Intel legacy (un)locking */
- uchar manufacturer_id; /* manufacturer id */
- ushort device_id; /* device id */
- ushort device_id2; /* extended device id */
- ushort ext_addr; /* extended query table address */
- ushort cfi_version; /* cfi version */
- ushort cfi_offset; /* offset for cfi query */
- ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
- ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
+ unsigned int buffer_size; /* # of bytes in write buffer */
+ unsigned long erase_blk_tout; /* maximum block erase timeout */
+ unsigned long write_tout; /* maximum write timeout */
+ unsigned long buffer_write_tout;/* maximum buffer write timeout */
+ unsigned int vendor; /* the primary vendor id */
+ unsigned int cmd_reset; /* vendor specific reset command */
+ unsigned int interface; /* used for x8/x16 adjustments */
+ unsigned int legacy_unlock; /* support Intel legacy (un)locking */
+ unsigned int manufacturer_id; /* manufacturer id */
+ unsigned int device_id; /* device id */
+ unsigned int device_id2; /* extended device id */
+ unsigned int ext_addr; /* extended query table address */
+ unsigned int cfi_version; /* cfi version */
+ unsigned int cfi_offset; /* offset for cfi query */
+ unsigned long addr_unlock1; /* unlock address 1 for AMD flash roms */
+ unsigned long addr_unlock2; /* unlock address 2 for AMD flash roms */
struct cfi_cmd_set *cfi_cmd_set;
struct mtd_info mtd;
int numeraseregions;
@@ -118,14 +118,16 @@ struct cfi_pri_hdr {
struct cfi_cmd_set {
- int (*flash_write_cfibuffer) (struct flash_info *info, ulong dest, const uchar * cp, int len);
- int (*flash_erase_one) (struct flash_info *info, long sect);
- int (*flash_is_busy) (struct flash_info *info, flash_sect_t sect);
- void (*flash_read_jedec_ids) (struct flash_info *info);
- void (*flash_prepare_write) (struct flash_info *info);
- int (*flash_status_check) (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt);
- int (*flash_real_protect) (struct flash_info *info, long sector, int prot);
- void (*flash_fixup) (struct flash_info *info, struct cfi_qry *qry);
+ int (*flash_write_cfibuffer)(struct flash_info *info, unsigned long dest,
+ const u8 *cp, int len);
+ int (*flash_erase_one)(struct flash_info *info, long sect);
+ int (*flash_is_busy)(struct flash_info *info, flash_sect_t sect);
+ void (*flash_read_jedec_ids)(struct flash_info *info);
+ void (*flash_prepare_write)(struct flash_info *info);
+ int (*flash_status_check)(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
+ int (*flash_real_protect)(struct flash_info *info, long sector, int prot);
+ void (*flash_fixup)(struct flash_info *info, struct cfi_qry *qry);
};
extern struct cfi_cmd_set cfi_cmd_set_intel;
@@ -241,32 +243,32 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
/* Prototypes */
int flash_isset(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
+ unsigned int offset, u32 cmd);
void flash_write_cmd(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
-flash_sect_t find_sector (struct flash_info *info, ulong addr);
-int flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt);
-int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt);
+ unsigned int offset, u32 cmd);
+flash_sect_t find_sector(struct flash_info *info, unsigned long addr);
+int flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
+int flash_generic_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
int flash_isequal(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
+ unsigned int offset, u32 cmd);
void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf);
static inline void flash_write8(u8 value, void *addr)
{
- cpu_writeb(value, addr);
+ __raw_writeb(value, addr);
}
static inline void flash_write16(u16 value, void *addr)
{
- cpu_writew(value, addr);
+ __raw_writew(value, addr);
}
static inline void flash_write32(u32 value, void *addr)
{
- cpu_writel(value, addr);
+ __raw_writel(value, addr);
}
static inline void flash_write64(u64 value, void *addr)
@@ -276,17 +278,17 @@ static inline void flash_write64(u64 value, void *addr)
static inline u8 flash_read8(void *addr)
{
- return cpu_readb(addr);
+ return __raw_readb(addr);
}
static inline u16 flash_read16(void *addr)
{
- return cpu_readw(addr);
+ return __raw_readw(addr);
}
static inline u32 flash_read32(void *addr)
{
- return cpu_readl(addr);
+ return __raw_readl(addr);
}
static inline u64 flash_read64(void *addr)
@@ -298,12 +300,13 @@ static inline u64 flash_read64(void *addr)
/*
* create an address based on the offset and the port width
*/
-static inline uchar *flash_make_addr (struct flash_info *info, flash_sect_t sect, uint offset)
+static inline u8 *flash_make_addr(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset)
{
- return ((uchar *) (info->start[sect] + ((offset * info->portwidth) << info->chip_lsb)));
+ return ((u8 *)(info->start[sect] + ((offset * info->portwidth) << info->chip_lsb)));
}
-uchar flash_read_uchar (struct flash_info *info, uint offset);
+u8 flash_read_uchar(struct flash_info *info, unsigned int offset);
u32 jedec_read_mfr(struct flash_info *info);
#ifdef CONFIG_DRIVER_CFI_BANK_WIDTH_1
@@ -332,49 +335,25 @@ u32 jedec_read_mfr(struct flash_info *info);
static inline void flash_write_word(struct flash_info *info, cfiword_t datum, void *addr)
{
- if (bankwidth_is_1(info)) {
- debug("fw addr %p val %02x\n", addr, (u8)datum);
+ if (bankwidth_is_1(info))
flash_write8(datum, addr);
- } else if (bankwidth_is_2(info)) {
- debug("fw addr %p val %04x\n", addr, (u16)datum);
+ else if (bankwidth_is_2(info))
flash_write16(datum, addr);
- } else if (bankwidth_is_4(info)) {
- debug("fw addr %p val %08x\n", addr, (u32)datum);
+ else if (bankwidth_is_4(info))
flash_write32(datum, addr);
- } else if (bankwidth_is_8(info)) {
+ else if (bankwidth_is_8(info))
flash_write64(datum, addr);
- }
}
-extern void flash_print_info (struct flash_info *);
-extern int flash_sect_erase (ulong addr_first, ulong addr_last);
-extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
+extern void flash_print_info(struct flash_info *);
+extern int flash_sect_erase(unsigned long addr_first, unsigned long addr_last);
+extern int flash_sect_protect(int flag, unsigned long addr_first,
+ unsigned long addr_last);
/* common/flash.c */
-extern void flash_protect (int flag, ulong from, ulong to, struct flash_info *info);
-extern int flash_write (char *, ulong, ulong);
-extern struct flash_info *addr2info (ulong);
-//extern int write_buff (flash_info_t *info, const uchar *src, ulong addr, ulong cnt);
-
-/* board/?/flash.c */
-#if defined(CFG_FLASH_PROTECTION)
-extern int flash_real_protect(struct flash_info *info, long sector, int prot);
-extern void flash_read_user_serial(struct flash_info *info, void * buffer, int offset, int len);
-extern void flash_read_factory_serial(struct flash_info *info, void * buffer, int offset, int len);
-#endif /* CFG_FLASH_PROTECTION */
-
-/*-----------------------------------------------------------------------
- * return codes from flash_write():
- */
-#define ERR_OK 0
-#define ERR_TIMOUT 1
-#define ERR_NOT_ERASED 2
-#define ERR_PROTECTED 4
-#define ERR_INVAL 8
-#define ERR_ALIGN 16
-#define ERR_UNKNOWN_FLASH_VENDOR 32
-#define ERR_UNKNOWN_FLASH_TYPE 64
-#define ERR_PROG_ERROR 128
+extern void flash_protect(int flag, unsigned long from, unsigned long to,
+ struct flash_info *info);
+extern int flash_write(char *, unsigned long, unsigned long);
/*-----------------------------------------------------------------------
* Protection Flags for flash_protect():
@@ -729,4 +708,3 @@ extern void flash_read_factory_serial(struct flash_info *info, void * buffer, in
#define FLASH_WRITE_TIMEOUT 500 /* timeout for writes in ms */
#endif /* __CFI_FLASH_H */
-
diff --git a/drivers/mtd/nor/cfi_flash_amd.c b/drivers/mtd/nor/cfi_flash_amd.c
index 45c59b9d01..9c44561d45 100644
--- a/drivers/mtd/nor/cfi_flash_amd.c
+++ b/drivers/mtd/nor/cfi_flash_amd.c
@@ -19,7 +19,7 @@ static void cfi_reverse_geometry(struct cfi_qry *qry)
}
}
-static void flash_unlock_seq (struct flash_info *info)
+static void flash_unlock_seq(struct flash_info *info)
{
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_UNLOCK_START);
flash_write_cmd (info, 0, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
@@ -31,7 +31,7 @@ static void flash_unlock_seq (struct flash_info *info)
* Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
*
*/
-static void amd_read_jedec_ids (struct flash_info *info)
+static void amd_read_jedec_ids(struct flash_info *info)
{
info->cmd_reset = AMD_CMD_RESET;
info->manufacturer_id = 0;
@@ -62,20 +62,21 @@ static void amd_read_jedec_ids (struct flash_info *info)
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = jedec_read_mfr(info);
- info->device_id = flash_read_uchar (info,
+ info->device_id = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID);
if (info->device_id == 0x7E) {
/* AMD 3-byte (expanded) device ids */
- info->device_id2 = flash_read_uchar (info,
+ info->device_id2 = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID2);
info->device_id2 <<= 8;
- info->device_id2 |= flash_read_uchar (info,
+ info->device_id2 |= flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID3);
}
flash_write_cmd(info, 0, 0, info->cmd_reset);
}
-static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
+static int flash_toggle(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset, u8 cmd)
{
void *addr;
cfiword_t cword;
@@ -83,6 +84,7 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
+
if (bankwidth_is_1(info)) {
retval = flash_read8(addr) != flash_read8(addr);
} else if (bankwidth_is_2(info)) {
@@ -92,8 +94,9 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
} else if (bankwidth_is_8(info)) {
retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
(flash_read32(addr+4) != flash_read32(addr+4)) );
- } else
+ } else {
retval = 0;
+ }
return retval;
}
@@ -102,12 +105,12 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
* flash_is_busy - check to see if the flash is busy
* This routine checks the status of the chip and returns true if the chip is busy
*/
-static int amd_flash_is_busy (struct flash_info *info, flash_sect_t sect)
+static int amd_flash_is_busy(struct flash_info *info, flash_sect_t sect)
{
return flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
}
-static int amd_flash_erase_one (struct flash_info *info, long sect)
+static int amd_flash_erase_one(struct flash_info *info, long sect)
{
flash_unlock_seq(info);
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_ERASE_START);
@@ -124,13 +127,12 @@ static void amd_flash_prepare_write(struct flash_info *info)
}
#ifdef CONFIG_CFI_BUFFER_WRITE
-static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const uchar * cp,
- int len)
+static int amd_flash_write_cfibuffer(struct flash_info *info, unsigned long dest,
+ const u8 *cp, int len)
{
flash_sect_t sector;
int cnt;
- int retcode;
- void *src = (void*)cp;
+ void *src = (void *)cp;
void *dst = (void *)dest;
cfiword_t cword;
@@ -170,18 +172,18 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
}
}
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_status_check (info, sector, info->buffer_write_tout,
+ flash_write_cmd(info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+
+ return flash_status_check(info, sector, info->buffer_write_tout,
"buffer write");
- return retcode;
}
#else
#define amd_flash_write_cfibuffer NULL
#endif /* CONFIG_CFI_BUFFER_WRITE */
-static int amd_flash_real_protect (struct flash_info *info, long sector, int prot)
+static int amd_flash_real_protect(struct flash_info *info, long sector, int prot)
{
- if (info->manufacturer_id != (uchar)ATM_MANUFACT)
+ if (info->manufacturer_id != (u8)ATM_MANUFACT)
return 0;
if (prot) {
@@ -205,7 +207,7 @@ static int amd_flash_real_protect (struct flash_info *info, long sector, int pro
* Manufacturer-specific quirks. Add workarounds for geometry
* reversal, etc. here.
*/
-static void flash_fixup_amd (struct flash_info *info, struct cfi_qry *qry)
+static void flash_fixup_amd(struct flash_info *info, struct cfi_qry *qry)
{
/* check if flash geometry needs reversal */
if (qry->num_erase_regions > 1) {
@@ -265,4 +267,3 @@ struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_real_protect = amd_flash_real_protect,
.flash_fixup = amd_flash_fixup,
};
-
diff --git a/drivers/mtd/nor/cfi_flash_intel.c b/drivers/mtd/nor/cfi_flash_intel.c
index 32e581a395..6108d7cc62 100644
--- a/drivers/mtd/nor/cfi_flash_intel.c
+++ b/drivers/mtd/nor/cfi_flash_intel.c
@@ -6,8 +6,8 @@
*
* Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
*
-*/
-static void intel_read_jedec_ids (struct flash_info *info)
+ */
+static void intel_read_jedec_ids(struct flash_info *info)
{
info->cmd_reset = FLASH_CMD_RESET;
info->manufacturer_id = 0;
@@ -19,7 +19,7 @@ static void intel_read_jedec_ids (struct flash_info *info)
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = jedec_read_mfr(info);
- info->device_id = flash_read_uchar (info,
+ info->device_id = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID);
flash_write_cmd(info, 0, 0, info->cmd_reset);
}
@@ -28,16 +28,16 @@ static void intel_read_jedec_ids (struct flash_info *info)
* flash_is_busy - check to see if the flash is busy
* This routine checks the status of the chip and returns true if the chip is busy
*/
-static int intel_flash_is_busy (struct flash_info *info, flash_sect_t sect)
+static int intel_flash_is_busy(struct flash_info *info, flash_sect_t sect)
{
return !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
}
-static int intel_flash_erase_one (struct flash_info *info, long sect)
+static int intel_flash_erase_one(struct flash_info *info, long sect)
{
- flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
- flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
return flash_status_check(info, sect, info->erase_blk_tout, "erase");
}
@@ -49,26 +49,26 @@ static void intel_flash_prepare_write(struct flash_info *info)
}
#ifdef CONFIG_CFI_BUFFER_WRITE
-static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, const uchar * cp,
- int len)
+static int intel_flash_write_cfibuffer(struct flash_info *info,
+ unsigned long dest, const u8 *cp, int len)
{
flash_sect_t sector;
int cnt;
- int retcode;
+ int ret;
void *src = (void*)cp;
void *dst = (void *)dest;
/* reduce width due to possible alignment problems */
const unsigned long ptr = (unsigned long)dest | (unsigned long)cp | info->portwidth;
const int width = ptr & -ptr;
- sector = find_sector (info, dest);
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
+ sector = find_sector(info, dest);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
- retcode = flash_generic_status_check (info, sector, info->buffer_write_tout,
+ ret = flash_generic_status_check(info, sector, info->buffer_write_tout,
"write to buffer");
- if (retcode != ERR_OK)
- return retcode;
+ if (ret)
+ return ret;
/* reduce the number of loops by the width of the port */
cnt = len / width;
@@ -95,69 +95,65 @@ static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, con
}
}
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_status_check (info, sector,
+ flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM);
+ ret = flash_status_check(info, sector,
info->buffer_write_tout,
"buffer write");
- return retcode;
+ return ret;
}
#else
#define intel_flash_write_cfibuffer NULL
#endif /* CONFIG_CFI_BUFFER_WRITE */
-static int intel_flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+static int intel_flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
- int retcode;
-
- retcode = flash_generic_status_check (info, sector, tout, prompt);
+ int ret;
- if ((retcode == ERR_OK)
- && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
- retcode = ERR_INVAL;
- printf ("Flash %s error at address %lx\n", prompt,
+ ret = flash_generic_status_check(info, sector, tout, prompt);
+ if (!ret && !flash_isequal(info, sector, 0, FLASH_STATUS_DONE)) {
+ ret = -EINVAL;
+ printf("Flash %s error at address %lx\n", prompt,
info->start[sector]);
- if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
- puts ("Command Sequence Error.\n");
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
+ printf("Command Sequence Error.\n");
} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
- puts ("Block Erase Error.\n");
- retcode = ERR_NOT_ERASED;
- } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
- puts ("Locking Error\n");
+ printf("Block Erase Error.\n");
+ ret = -EIO;
+ } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) {
+ printf("Locking Error\n");
}
- if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
- puts ("Block locked.\n");
- retcode = ERR_PROTECTED;
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
+ printf("Block locked.\n");
+ ret = -EROFS;
}
- if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
- puts ("Vpp Low Error.\n");
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
+ printf("Vpp Low Error.\n");
}
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return retcode;
+ flash_write_cmd(info, sector, 0, info->cmd_reset);
+
+ return ret;
}
-static int intel_flash_real_protect (struct flash_info *info, long sector, int prot)
+static int intel_flash_real_protect(struct flash_info *info, long sector, int prot)
{
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
+
if (prot)
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
else
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
return 0;
}
-static void intel_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
+static void intel_flash_fixup(struct flash_info *info, struct cfi_qry *qry)
{
-#ifdef CFG_FLASH_PROTECTION
- /* read legacy lock/unlock bit from intel flash */
- if (info->ext_addr) {
- info->legacy_unlock = flash_read_uchar (info,
- info->ext_addr + 5) & 0x08;
- }
-#endif
}
struct cfi_cmd_set cfi_cmd_set_intel = {
@@ -170,4 +166,3 @@ struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_real_protect = intel_flash_real_protect,
.flash_fixup = intel_flash_fixup,
};
-
diff --git a/drivers/mtd/partition.c b/drivers/mtd/partition.c
index 98b90819bd..c11a3db1c5 100644
--- a/drivers/mtd/partition.c
+++ b/drivers/mtd/partition.c
@@ -31,6 +31,16 @@ static int mtd_part_write(struct mtd_info *mtd, loff_t to, size_t len,
len, retlen, buf);
}
+static int mtd_part_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ if (to >= mtd->size)
+ return -EINVAL;
+ if (ops->datbuf && to + ops->len > mtd->size)
+ return -EINVAL;
+ return mtd->master->write_oob(mtd->master, to + mtd->master_offset, ops);
+}
+
static int mtd_part_erase(struct mtd_info *mtd, struct erase_info *instr)
{
int ret;
@@ -160,6 +170,9 @@ struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
part->block_markbad = mtd->block_markbad ? mtd_part_block_markbad : NULL;
}
+ if (mtd->write_oob)
+ part->write_oob = mtd_part_write_oob;
+
part->block_isbad = mtd->block_isbad ? mtd_part_block_isbad : NULL;
part->size = size;
part->name = xstrdup(name);
diff --git a/drivers/mtd/spi-nor/Kconfig b/drivers/mtd/spi-nor/Kconfig
new file mode 100644
index 0000000000..a84591fdd1
--- /dev/null
+++ b/drivers/mtd/spi-nor/Kconfig
@@ -0,0 +1,15 @@
+menuconfig MTD_SPI_NOR
+ tristate "SPI-NOR device support"
+ depends on MTD
+ help
+ This is the framework for the SPI NOR which can be used by the SPI
+ device drivers and the SPI-NOR device driver.
+
+if MTD_SPI_NOR
+
+config SPI_CADENCE_QUADSPI
+ tristate "Cadence Quad SPI controller"
+ help
+ This enables support for the Cadence Quad SPI controller and NOR flash.
+
+endif
diff --git a/drivers/mtd/spi-nor/Makefile b/drivers/mtd/spi-nor/Makefile
new file mode 100644
index 0000000000..4e00f38a7d
--- /dev/null
+++ b/drivers/mtd/spi-nor/Makefile
@@ -0,0 +1,2 @@
+obj-$(CONFIG_MTD_SPI_NOR) += spi-nor.o
+obj-$(CONFIG_SPI_CADENCE_QUADSPI) += cadence-quadspi.o
diff --git a/drivers/mtd/spi-nor/cadence-quadspi.c b/drivers/mtd/spi-nor/cadence-quadspi.c
new file mode 100644
index 0000000000..dce29ca0ea
--- /dev/null
+++ b/drivers/mtd/spi-nor/cadence-quadspi.c
@@ -0,0 +1,1211 @@
+/*
+ * Copyright (C) 2015 Pengutronix, Steffen Trumtrar <s.trumtrar@pengutronix.de>
+ *
+ * derived from Linux kernel driver by
+ *
+ * Driver for Cadence QSPI Controller
+ *
+ * Copyright Altera Corporation (C) 2012-2014. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <clock.h>
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/spi-nor.h>
+#include <of.h>
+#include <platform_data/cadence_qspi.h>
+#include <spi/spi.h>
+
+#define CQSPI_MAX_CHIPSELECT 16
+
+struct cqspi_flash_pdata {
+ struct mtd_info mtd;
+ struct spi_nor nor;
+ u32 clk_rate;
+ unsigned int block_size;
+ unsigned int read_delay;
+ unsigned int tshsl_ns;
+ unsigned int tsd2d_ns;
+ unsigned int tchsh_ns;
+ unsigned int tslch_ns;
+};
+
+struct cqspi_st {
+ struct device_d *dev;
+ struct clk *l4_mp_clk;
+ struct clk *qspi_clk;
+ unsigned int sclk;
+
+ void __iomem *iobase;
+ void __iomem *ahb_base;
+ unsigned int irq_mask;
+ int current_cs;
+ unsigned int master_ref_clk_hz;
+ unsigned int ext_decoder;
+ unsigned int fifo_depth;
+ struct cqspi_flash_pdata f_pdata[CQSPI_MAX_CHIPSELECT];
+ bool no_reconfig;
+};
+
+/* Operation timeout value */
+#define CQSPI_TIMEOUT_MS 800 * MSECOND
+#define CQSPI_READ_TIMEOUT_MS 100 * MSECOND
+#define CQSPI_POLL_IDLE_RETRY 3
+
+#define CQSPI_FIFO_WIDTH 4
+
+#define CQSPI_REG_SRAM_THRESHOLD_BYTES 50
+
+/* Instruction type */
+#define CQSPI_INST_TYPE_SINGLE 0
+#define CQSPI_INST_TYPE_DUAL 1
+#define CQSPI_INST_TYPE_QUAD 2
+
+#define CQSPI_DUMMY_CLKS_PER_BYTE 8
+#define CQSPI_DUMMY_BYTES_MAX 4
+
+#define CQSPI_STIG_DATA_LEN_MAX 8
+
+#define CQSPI_INDIRECTTRIGGER_ADDR_MASK 0xFFFFF
+
+/* Register map */
+#define CQSPI_REG_CONFIG 0x00
+#define CQSPI_REG_CONFIG_ENABLE_MASK BIT(0)
+#define CQSPI_REG_CONFIG_DECODE_MASK BIT(9)
+#define CQSPI_REG_CONFIG_CHIPSELECT_LSB 10
+#define CQSPI_REG_CONFIG_DMA_MASK BIT(15)
+#define CQSPI_REG_CONFIG_BAUD_LSB 19
+#define CQSPI_REG_CONFIG_IDLE_LSB 31
+#define CQSPI_REG_CONFIG_CHIPSELECT_MASK 0xF
+#define CQSPI_REG_CONFIG_BAUD_MASK 0xF
+
+#define CQSPI_REG_RD_INSTR 0x04
+#define CQSPI_REG_RD_INSTR_OPCODE_LSB 0
+#define CQSPI_REG_RD_INSTR_TYPE_INSTR_LSB 8
+#define CQSPI_REG_RD_INSTR_TYPE_ADDR_LSB 12
+#define CQSPI_REG_RD_INSTR_TYPE_DATA_LSB 16
+#define CQSPI_REG_RD_INSTR_MODE_EN_LSB 20
+#define CQSPI_REG_RD_INSTR_DUMMY_LSB 24
+#define CQSPI_REG_RD_INSTR_TYPE_INSTR_MASK 0x3
+#define CQSPI_REG_RD_INSTR_TYPE_ADDR_MASK 0x3
+#define CQSPI_REG_RD_INSTR_TYPE_DATA_MASK 0x3
+#define CQSPI_REG_RD_INSTR_DUMMY_MASK 0x1F
+
+#define CQSPI_REG_WR_INSTR 0x08
+#define CQSPI_REG_WR_INSTR_OPCODE_LSB 0
+#define CQSPI_REG_WR_INSTR_TYPE_ADDR_LSB 12
+#define CQSPI_REG_WR_INSTR_TYPE_DATA_LSB 16
+
+#define CQSPI_REG_DELAY 0x0C
+#define CQSPI_REG_DELAY_TSLCH_LSB 0
+#define CQSPI_REG_DELAY_TCHSH_LSB 8
+#define CQSPI_REG_DELAY_TSD2D_LSB 16
+#define CQSPI_REG_DELAY_TSHSL_LSB 24
+#define CQSPI_REG_DELAY_TSLCH_MASK 0xFF
+#define CQSPI_REG_DELAY_TCHSH_MASK 0xFF
+#define CQSPI_REG_DELAY_TSD2D_MASK 0xFF
+#define CQSPI_REG_DELAY_TSHSL_MASK 0xFF
+
+#define CQSPI_REG_READCAPTURE 0x10
+#define CQSPI_REG_READCAPTURE_BYPASS_LSB 0
+#define CQSPI_REG_READCAPTURE_DELAY_LSB 1
+#define CQSPI_REG_READCAPTURE_DELAY_MASK 0xF
+
+#define CQSPI_REG_SIZE 0x14
+#define CQSPI_REG_SIZE_ADDRESS_LSB 0
+#define CQSPI_REG_SIZE_PAGE_LSB 4
+#define CQSPI_REG_SIZE_BLOCK_LSB 16
+#define CQSPI_REG_SIZE_ADDRESS_MASK 0xF
+#define CQSPI_REG_SIZE_PAGE_MASK 0xFFF
+#define CQSPI_REG_SIZE_BLOCK_MASK 0x3F
+
+#define CQSPI_REG_SRAMPARTITION 0x18
+#define CQSPI_REG_INDIRECTTRIGGER 0x1C
+
+#define CQSPI_REG_DMA 0x20
+#define CQSPI_REG_DMA_SINGLE_LSB 0
+#define CQSPI_REG_DMA_BURST_LSB 8
+#define CQSPI_REG_DMA_SINGLE_MASK 0xFF
+#define CQSPI_REG_DMA_BURST_MASK 0xFF
+
+#define CQSPI_REG_REMAP 0x24
+#define CQSPI_REG_MODE_BIT 0x28
+
+#define CQSPI_REG_SRAMLEVEL 0x2C
+#define CQSPI_REG_SRAMLEVEL_RD_LSB 0
+#define CQSPI_REG_SRAMLEVEL_WR_LSB 16
+#define CQSPI_REG_SRAMLEVEL_RD_MASK 0xFFFF
+#define CQSPI_REG_SRAMLEVEL_WR_MASK 0xFFFF
+
+#define CQSPI_REG_IRQSTATUS 0x40
+#define CQSPI_REG_IRQMASK 0x44
+
+#define CQSPI_REG_INDIRECTRD 0x60
+#define CQSPI_REG_INDIRECTRD_START_MASK BIT(0)
+#define CQSPI_REG_INDIRECTRD_CANCEL_MASK BIT(1)
+#define CQSPI_REG_INDIRECTRD_DONE_MASK BIT(5)
+
+#define CQSPI_REG_INDIRECTRDWATERMARK 0x64
+#define CQSPI_REG_INDIRECTRDSTARTADDR 0x68
+#define CQSPI_REG_INDIRECTRDBYTES 0x6C
+
+#define CQSPI_REG_CMDCTRL 0x90
+#define CQSPI_REG_CMDCTRL_EXECUTE_MASK BIT(0)
+#define CQSPI_REG_CMDCTRL_INPROGRESS_MASK BIT(1)
+#define CQSPI_REG_CMDCTRL_WR_BYTES_LSB 12
+#define CQSPI_REG_CMDCTRL_WR_EN_LSB 15
+#define CQSPI_REG_CMDCTRL_ADD_BYTES_LSB 16
+#define CQSPI_REG_CMDCTRL_ADDR_EN_LSB 19
+#define CQSPI_REG_CMDCTRL_RD_BYTES_LSB 20
+#define CQSPI_REG_CMDCTRL_RD_EN_LSB 23
+#define CQSPI_REG_CMDCTRL_OPCODE_LSB 24
+#define CQSPI_REG_CMDCTRL_WR_BYTES_MASK 0x7
+#define CQSPI_REG_CMDCTRL_ADD_BYTES_MASK 0x3
+#define CQSPI_REG_CMDCTRL_RD_BYTES_MASK 0x7
+
+#define CQSPI_REG_INDIRECTWR 0x70
+#define CQSPI_REG_INDIRECTWR_START_MASK BIT(0)
+#define CQSPI_REG_INDIRECTWR_CANCEL_MASK BIT(1)
+#define CQSPI_REG_INDIRECTWR_DONE_MASK BIT(5)
+
+#define CQSPI_REG_INDIRECTWRWATERMARK 0x74
+#define CQSPI_REG_INDIRECTWRSTARTADDR 0x78
+#define CQSPI_REG_INDIRECTWRBYTES 0x7C
+
+#define CQSPI_REG_CMDADDRESS 0x94
+#define CQSPI_REG_CMDREADDATALOWER 0xA0
+#define CQSPI_REG_CMDREADDATAUPPER 0xA4
+#define CQSPI_REG_CMDWRITEDATALOWER 0xA8
+#define CQSPI_REG_CMDWRITEDATAUPPER 0xAC
+
+/* Interrupt status bits */
+#define CQSPI_REG_IRQ_MODE_ERR BIT(0)
+#define CQSPI_REG_IRQ_UNDERFLOW BIT(1)
+#define CQSPI_REG_IRQ_IND_COMP BIT(2)
+#define CQSPI_REG_IRQ_IND_RD_REJECT BIT(3)
+#define CQSPI_REG_IRQ_WR_PROTECTED_ERR BIT(4)
+#define CQSPI_REG_IRQ_ILLEGAL_AHB_ERR BIT(5)
+#define CQSPI_REG_IRQ_WATERMARK BIT(6)
+#define CQSPI_REG_IRQ_IND_RD_OVERFLOW BIT(12)
+
+#define CQSPI_IRQ_STATUS_ERR (CQSPI_REG_IRQ_MODE_ERR | \
+ CQSPI_REG_IRQ_IND_RD_REJECT | \
+ CQSPI_REG_IRQ_WR_PROTECTED_ERR | \
+ CQSPI_REG_IRQ_ILLEGAL_AHB_ERR)
+
+#define CQSPI_IRQ_MASK_RD (CQSPI_REG_IRQ_WATERMARK | \
+ CQSPI_REG_IRQ_IND_RD_OVERFLOW | \
+ CQSPI_REG_IRQ_IND_COMP)
+
+#define CQSPI_IRQ_MASK_WR (CQSPI_REG_IRQ_IND_COMP | \
+ CQSPI_REG_IRQ_WATERMARK | \
+ CQSPI_REG_IRQ_UNDERFLOW)
+
+#define CQSPI_IRQ_STATUS_MASK 0x1FFFE
+
+#define CQSPI_REG_IS_IDLE(base) \
+ ((readl(base + CQSPI_REG_CONFIG) >> \
+ CQSPI_REG_CONFIG_IDLE_LSB) & 0x1)
+
+#define CQSPI_GET_RD_SRAM_LEVEL(reg_base) \
+ (((readl(reg_base + CQSPI_REG_SRAMLEVEL)) >> \
+ CQSPI_REG_SRAMLEVEL_RD_LSB) & CQSPI_REG_SRAMLEVEL_RD_MASK)
+
+static void cqspi_fifo_read(void *dest, const void *src_ahb_addr,
+ unsigned int bytes)
+{
+ unsigned int temp;
+ int remaining = bytes;
+ unsigned int *dest_ptr = (unsigned int *)dest;
+ unsigned int *src_ptr = (unsigned int *)src_ahb_addr;
+
+ while (remaining > CQSPI_FIFO_WIDTH) {
+ *dest_ptr = readl(src_ptr);
+ dest_ptr++;
+ remaining -= CQSPI_FIFO_WIDTH;
+ }
+ if (remaining > 0) {
+ /* dangling bytes */
+ temp = readl(src_ptr);
+ memcpy(dest_ptr, &temp, remaining);
+ }
+}
+
+static void cqspi_fifo_write(void *dest_ahb_addr,
+ const void *src, unsigned int bytes)
+{
+ unsigned int temp;
+ int remaining = bytes;
+ unsigned int *dest_ptr = (unsigned int *)dest_ahb_addr;
+ unsigned int *src_ptr = (unsigned int *)src;
+
+ while (remaining > CQSPI_FIFO_WIDTH) {
+ writel(*src_ptr, dest_ptr);
+ src_ptr++;
+ remaining -= CQSPI_FIFO_WIDTH;
+ }
+ if (remaining > 0) {
+ /* dangling bytes */
+ memcpy(&temp, src_ptr, remaining);
+ writel(temp, dest_ptr);
+ }
+}
+
+static int cqspi_find_chipselect(struct spi_nor *nor)
+{
+ int cs = -1;
+ struct cqspi_st *cqspi = nor->priv;
+
+ for (cs = 0; cs < CQSPI_MAX_CHIPSELECT; cs++)
+ if (nor == &cqspi->f_pdata[cs].nor)
+ break;
+ return cs;
+}
+
+static unsigned int cqspi_calc_rdreg(struct spi_nor *nor, u8 opcode)
+{
+ unsigned int rdreg = 0;
+ struct cqspi_st *cqspi = nor->priv;
+ struct cqspi_flash_pdata *f_pdata;
+
+ f_pdata = &cqspi->f_pdata[cqspi->current_cs];
+
+ if (nor->flash_read == SPI_NOR_QUAD)
+ rdreg |= (CQSPI_INST_TYPE_QUAD
+ << CQSPI_REG_RD_INSTR_TYPE_DATA_LSB);
+ return rdreg;
+}
+
+static unsigned int cqspi_wait_idle(struct cqspi_st *cqspi)
+{
+ void __iomem *reg_base = cqspi->iobase;
+
+ if (wait_on_timeout(CQSPI_TIMEOUT_MS,
+ CQSPI_REG_IS_IDLE(reg_base))) {
+ /* Timeout, in busy mode. */
+ dev_err(cqspi->dev, "QSPI is still busy after %llums timeout.\n",
+ CQSPI_TIMEOUT_MS);
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int cqspi_exec_flash_cmd(struct cqspi_st *cqspi, unsigned int reg)
+{
+ void __iomem *reg_base = cqspi->iobase;
+
+ /* Write the CMDCTRL without start execution. */
+ writel(reg, reg_base + CQSPI_REG_CMDCTRL);
+ /* Start execute */
+ reg |= CQSPI_REG_CMDCTRL_EXECUTE_MASK;
+ writel(reg, reg_base + CQSPI_REG_CMDCTRL);
+
+ if (wait_on_timeout(CQSPI_TIMEOUT_MS,
+ (readl(reg_base + CQSPI_REG_CMDCTRL) &
+ CQSPI_REG_CMDCTRL_INPROGRESS_MASK) == 0)) {
+ dev_err(cqspi->dev, "flash cmd execute time out (0x%08x)\n",
+ readl(reg_base + CQSPI_REG_CMDCTRL));
+ return -EIO;
+ }
+
+ /* Polling QSPI idle status. */
+ return cqspi_wait_idle(cqspi);
+}
+
+static int cqspi_command_read(struct spi_nor *nor,
+ const u8 *txbuf, unsigned n_tx,
+ u8 *rxbuf, unsigned n_rx)
+{
+ unsigned int reg;
+ unsigned int read_len;
+ int status;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int rdreg;
+
+ if (!n_rx || n_rx > CQSPI_STIG_DATA_LEN_MAX || rxbuf == NULL) {
+ dev_err(nor->dev,
+ "Invalid input argument, len %d rxbuf 0x%08x\n", n_rx,
+ (unsigned int)rxbuf);
+ return -EINVAL;
+ }
+
+ reg = txbuf[0] << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+
+ rdreg = cqspi_calc_rdreg(nor, txbuf[0]);
+ writel(rdreg, reg_base + CQSPI_REG_RD_INSTR);
+
+ reg |= (0x1 << CQSPI_REG_CMDCTRL_RD_EN_LSB);
+
+ /* 0 means 1 byte. */
+ reg |= (((n_rx - 1) & CQSPI_REG_CMDCTRL_RD_BYTES_MASK)
+ << CQSPI_REG_CMDCTRL_RD_BYTES_LSB);
+ status = cqspi_exec_flash_cmd(cqspi, reg);
+ if (status != 0)
+ return status;
+
+ reg = readl(reg_base + CQSPI_REG_CMDREADDATALOWER);
+
+ /* Put the read value into rx_buf */
+ read_len = (n_rx > 4) ? 4 : n_rx;
+ memcpy(rxbuf, &reg, read_len);
+ rxbuf += read_len;
+
+ if (n_rx > 4) {
+ reg = readl(reg_base + CQSPI_REG_CMDREADDATAUPPER);
+
+ read_len = n_rx - read_len;
+ memcpy(rxbuf, &reg, read_len);
+ }
+
+ return 0;
+}
+
+static __maybe_unused int cqspi_command_write(struct spi_nor *nor,
+ u8 opcode, const u8 *txbuf, unsigned n_tx)
+{
+ unsigned int reg;
+ unsigned int data;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+
+ if (n_tx > 4 || (n_tx && txbuf == NULL)) {
+ dev_err(nor->dev,
+ "Invalid input argument, cmdlen %d txbuf 0x%08x\n",
+ n_tx, (unsigned int)txbuf);
+ return -EINVAL;
+ }
+
+ reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ if (n_tx) {
+ reg |= (0x1 << CQSPI_REG_CMDCTRL_WR_EN_LSB);
+ reg |= ((n_tx - 1) & CQSPI_REG_CMDCTRL_WR_BYTES_MASK)
+ << CQSPI_REG_CMDCTRL_WR_BYTES_LSB;
+ data = 0;
+ memcpy(&data, txbuf, n_tx);
+ writel(data, reg_base + CQSPI_REG_CMDWRITEDATALOWER);
+ }
+
+ return cqspi_exec_flash_cmd(cqspi, reg);
+}
+
+static int cqspi_command_write_addr(struct spi_nor *nor,
+ u8 opcode, unsigned int addr)
+{
+ unsigned int reg;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+
+ reg = opcode << CQSPI_REG_CMDCTRL_OPCODE_LSB;
+ reg |= (0x1 << CQSPI_REG_CMDCTRL_ADDR_EN_LSB);
+ reg |= ((nor->addr_width - 1) & CQSPI_REG_CMDCTRL_ADD_BYTES_MASK)
+ << CQSPI_REG_CMDCTRL_ADD_BYTES_LSB;
+
+ writel(addr, reg_base + CQSPI_REG_CMDADDRESS);
+
+ return cqspi_exec_flash_cmd(cqspi, reg);
+}
+
+static int cqspi_indirect_read_setup(struct spi_nor *nor,
+ unsigned int from_addr)
+{
+ struct cqspi_st *cqspi = nor->priv;
+ unsigned int ahb_base = (unsigned int) cqspi->ahb_base;
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int dummy_clk = 0;
+ unsigned int dummy_bytes;
+ unsigned int reg = 0;
+
+ writel(ahb_base & CQSPI_INDIRECTTRIGGER_ADDR_MASK,
+ reg_base + CQSPI_REG_INDIRECTTRIGGER);
+ writel(from_addr, reg_base + CQSPI_REG_INDIRECTRDSTARTADDR);
+
+ reg = nor->read_opcode << CQSPI_REG_RD_INSTR_OPCODE_LSB;
+ reg |= cqspi_calc_rdreg(nor, nor->read_opcode);
+
+ /* Setup dummy clock cycles */
+ dummy_bytes = nor->read_dummy / 8;
+
+ if (dummy_bytes) {
+ struct cqspi_flash_pdata *f_pdata;
+
+ f_pdata = &cqspi->f_pdata[cqspi->current_cs];
+
+ if (dummy_bytes > CQSPI_DUMMY_BYTES_MAX)
+ dummy_bytes = CQSPI_DUMMY_BYTES_MAX;
+
+ reg |= (1 << CQSPI_REG_RD_INSTR_MODE_EN_LSB);
+ /* Set mode bits high to ensure chip doesn't enter XIP */
+ writel(0xFF, reg_base + CQSPI_REG_MODE_BIT);
+
+ /* Convert to clock cycles. */
+ dummy_clk = dummy_bytes * CQSPI_DUMMY_CLKS_PER_BYTE;
+ /* Need to subtract the mode byte (8 clocks). */
+ dummy_clk -= CQSPI_DUMMY_CLKS_PER_BYTE;
+
+ if (dummy_clk)
+ reg |= (dummy_clk & CQSPI_REG_RD_INSTR_DUMMY_MASK)
+ << CQSPI_REG_RD_INSTR_DUMMY_LSB;
+ }
+
+ writel(reg, reg_base + CQSPI_REG_RD_INSTR);
+
+ /* Set address width */
+ reg = readl(reg_base + CQSPI_REG_SIZE);
+ reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
+ reg |= (nor->addr_width) - 1;
+ writel(reg, reg_base + CQSPI_REG_SIZE);
+ return 0;
+}
+
+static int cqspi_indirect_read_execute(struct spi_nor *nor,
+ u8 *rxbuf, unsigned n_rx)
+{
+ int ret = 0;
+ unsigned int reg = 0;
+ unsigned int bytes_to_read = 0;
+ unsigned int watermark;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+ void __iomem *ahb_base = cqspi->ahb_base;
+ int remaining = (int)n_rx;
+
+ watermark = cqspi->fifo_depth * CQSPI_FIFO_WIDTH / 2;
+ writel(watermark, reg_base + CQSPI_REG_INDIRECTRDWATERMARK);
+ writel(remaining, reg_base + CQSPI_REG_INDIRECTRDBYTES);
+
+ /* Clear all interrupts. */
+ writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
+
+ cqspi->irq_mask = CQSPI_IRQ_MASK_RD;
+ writel(cqspi->irq_mask, reg_base + CQSPI_REG_IRQMASK);
+
+ writel(CQSPI_REG_INDIRECTRD_START_MASK,
+ reg_base + CQSPI_REG_INDIRECTRD);
+
+ while (remaining > 0) {
+ unsigned int irq_status;
+
+ ret = wait_on_timeout(CQSPI_READ_TIMEOUT_MS,
+ readl(reg_base + CQSPI_REG_IRQSTATUS) & cqspi->irq_mask);
+
+ irq_status = readl(reg_base + CQSPI_REG_IRQSTATUS);
+ bytes_to_read = CQSPI_GET_RD_SRAM_LEVEL(reg_base);
+
+ /* Clear all interrupts. */
+ writel(irq_status, reg_base + CQSPI_REG_IRQSTATUS);
+
+ if (!ret && bytes_to_read == 0) {
+ dev_err(nor->dev, "Indirect read timeout, no bytes\n");
+ ret = -ETIMEDOUT;
+ goto failrd;
+ }
+
+ while (bytes_to_read != 0) {
+ bytes_to_read *= CQSPI_FIFO_WIDTH;
+ bytes_to_read = bytes_to_read > remaining
+ ? remaining : bytes_to_read;
+ cqspi_fifo_read(rxbuf, ahb_base, bytes_to_read);
+ rxbuf += bytes_to_read;
+ remaining -= bytes_to_read;
+ bytes_to_read = CQSPI_GET_RD_SRAM_LEVEL(reg_base);
+ }
+ }
+
+ /* Check indirect done status */
+ if (wait_on_timeout(CQSPI_TIMEOUT_MS,
+ readl(reg_base + CQSPI_REG_INDIRECTRD) &
+ CQSPI_REG_INDIRECTRD_DONE_MASK)) {
+ dev_err(nor->dev,
+ "Indirect read completion error 0x%08x\n", reg);
+ ret = -ETIMEDOUT;
+ goto failrd;
+ }
+
+ /* Disable interrupt */
+ writel(0, reg_base + CQSPI_REG_IRQMASK);
+
+ /* Clear indirect completion status */
+ writel(CQSPI_REG_INDIRECTRD_DONE_MASK, reg_base + CQSPI_REG_INDIRECTRD);
+
+ return 0;
+
+ failrd:
+ /* Disable interrupt */
+ writel(0, reg_base + CQSPI_REG_IRQMASK);
+
+ /* Cancel the indirect read */
+ writel(CQSPI_REG_INDIRECTWR_CANCEL_MASK,
+ reg_base + CQSPI_REG_INDIRECTRD);
+ return ret;
+}
+
+static __maybe_unused int cqspi_indirect_write_setup(struct spi_nor *nor,
+ unsigned int to_addr)
+{
+ unsigned int reg;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+
+ /* Set opcode. */
+ reg = nor->program_opcode << CQSPI_REG_WR_INSTR_OPCODE_LSB;
+ writel(reg, reg_base + CQSPI_REG_WR_INSTR);
+ reg = cqspi_calc_rdreg(nor, nor->program_opcode);
+ writel(reg, reg_base + CQSPI_REG_RD_INSTR);
+
+ writel(to_addr, reg_base + CQSPI_REG_INDIRECTWRSTARTADDR);
+
+ reg = readl(reg_base + CQSPI_REG_SIZE);
+ reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
+ reg |= (nor->addr_width - 1);
+ writel(reg, reg_base + CQSPI_REG_SIZE);
+ return 0;
+}
+
+static __maybe_unused int cqspi_indirect_write_execute(struct spi_nor *nor,
+ const u8 *txbuf, unsigned n_tx)
+{
+ int ret;
+ unsigned int reg = 0;
+ struct cqspi_st *cqspi = nor->priv;
+ void __iomem *reg_base = cqspi->iobase;
+ void __iomem *ahb_base = cqspi->ahb_base;
+ int remaining = (int)n_tx;
+ unsigned int page_size;
+ unsigned int write_bytes;
+
+ page_size = nor->page_size;
+
+ writel(remaining, reg_base + CQSPI_REG_INDIRECTWRBYTES);
+
+ writel(CQSPI_REG_SRAM_THRESHOLD_BYTES, reg_base +
+ CQSPI_REG_INDIRECTWRWATERMARK);
+
+ /* Clear all interrupts. */
+ writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
+
+ cqspi->irq_mask = CQSPI_IRQ_MASK_WR;
+ writel(cqspi->irq_mask, reg_base + CQSPI_REG_IRQMASK);
+
+ writel(CQSPI_REG_INDIRECTWR_START_MASK,
+ reg_base + CQSPI_REG_INDIRECTWR);
+
+ /* Write a page or remaining bytes. */
+ write_bytes = remaining > page_size ? page_size : remaining;
+ /* Fill up the data at the beginning */
+ cqspi_fifo_write(ahb_base, txbuf, write_bytes);
+ txbuf += write_bytes;
+ remaining -= write_bytes;
+
+ while (remaining > 0) {
+ ret = wait_on_timeout(CQSPI_READ_TIMEOUT_MS,
+ readl(reg_base + CQSPI_REG_IRQSTATUS) & cqspi->irq_mask);
+
+ /* Clear all interrupts. */
+ writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
+
+ if (ret < 0) {
+ dev_err(nor->dev, "Indirect write timeout\n");
+ ret = -ETIMEDOUT;
+ goto failwr;
+ }
+
+ write_bytes = remaining > page_size ? page_size : remaining;
+ cqspi_fifo_write(ahb_base, txbuf, write_bytes);
+ txbuf += write_bytes;
+ remaining -= write_bytes;
+
+ writel(cqspi->irq_mask, reg_base + CQSPI_REG_IRQMASK);
+ }
+ ret = wait_on_timeout(CQSPI_READ_TIMEOUT_MS,
+ readl(reg_base + CQSPI_REG_IRQSTATUS) & cqspi->irq_mask);
+
+ /* Clear all interrupts. */
+ writel(CQSPI_IRQ_STATUS_MASK, reg_base + CQSPI_REG_IRQSTATUS);
+ if (ret < 0) {
+ dev_err(nor->dev, "Indirect write timeout\n");
+ ret = -ETIMEDOUT;
+ goto failwr;
+ }
+
+ /* Check indirect done status */
+ if (wait_on_timeout(CQSPI_TIMEOUT_MS,
+ readl(reg_base + CQSPI_REG_INDIRECTWR)
+ & CQSPI_REG_INDIRECTWR_DONE_MASK)) {
+ dev_err(nor->dev,
+ "Indirect write completion error 0x%08x\n", reg);
+ ret = -ETIMEDOUT;
+ goto failwr;
+ }
+
+ /* Disable interrupt. */
+ writel(0, reg_base + CQSPI_REG_IRQMASK);
+
+ /* Clear indirect completion status */
+ writel(CQSPI_REG_INDIRECTWR_DONE_MASK, reg_base + CQSPI_REG_INDIRECTWR);
+
+ cqspi_wait_idle(cqspi);
+
+ return 0;
+
+failwr:
+ /* Disable interrupt. */
+ writel(0, reg_base + CQSPI_REG_IRQMASK);
+
+ /* Cancel the indirect write */
+ writel(CQSPI_REG_INDIRECTWR_CANCEL_MASK,
+ reg_base + CQSPI_REG_INDIRECTWR);
+ return ret;
+}
+
+static void cqspi_write(struct spi_nor *nor, loff_t to,
+ size_t len, size_t *retlen, const u_char *buf)
+{
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_MTD_WRITE))
+ return;
+
+ ret = cqspi_indirect_write_setup(nor, to);
+ if (ret == 0) {
+ ret = cqspi_indirect_write_execute(nor, buf, len);
+ if (ret == 0)
+ *retlen += len;
+ }
+}
+
+static int cqspi_read(struct spi_nor *nor, loff_t from,
+ size_t len, size_t *retlen, u_char *buf)
+{
+ int ret;
+
+ ret = cqspi_indirect_read_setup(nor, from);
+ if (ret == 0) {
+ ret = cqspi_indirect_read_execute(nor, buf, len);
+ if (ret == 0)
+ *retlen += len;
+ }
+ return ret;
+}
+
+static int cqspi_erase(struct spi_nor *nor, loff_t offs)
+{
+ int ret;
+
+ /* Send write enable, then erase commands. */
+ ret = nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0);
+ if (ret)
+ return ret;
+
+ /* Set up command buffer. */
+ ret = cqspi_command_write_addr(nor, nor->erase_opcode, offs);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static unsigned int calculate_ticks_for_ns(unsigned int ref_clk_hz,
+ unsigned int ns_val)
+{
+ unsigned int ticks;
+
+ ticks = ref_clk_hz;
+ ticks /= 1000;
+ ticks *= ns_val;
+ ticks += 999999;
+ ticks /= 1000000;
+ return ticks;
+}
+
+static void cqspi_delay(struct cqspi_st *cqspi,
+ unsigned int ref_clk_hz, unsigned int sclk_hz)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ struct cqspi_flash_pdata *f_pdata;
+ unsigned int ref_clk_ns;
+ unsigned int sclk_ns;
+ unsigned int tshsl, tchsh, tslch, tsd2d;
+ unsigned int reg;
+ unsigned int tsclk;
+
+ if (cqspi->no_reconfig)
+ return;
+
+ f_pdata = &cqspi->f_pdata[cqspi->current_cs];
+
+ /* Convert to ns. */
+ ref_clk_ns = NSEC_PER_SEC / ref_clk_hz;
+
+ /* Convert to ns. */
+ sclk_ns = NSEC_PER_SEC / sclk_hz;
+
+ /* calculate the number of ref ticks for one sclk tick */
+ tsclk = (ref_clk_hz + sclk_hz - 1) / sclk_hz;
+
+ tshsl = calculate_ticks_for_ns(ref_clk_hz, f_pdata->tshsl_ns);
+ /* this particular value must be at least one sclk */
+ if (tshsl < tsclk)
+ tshsl = tsclk;
+
+ tchsh = calculate_ticks_for_ns(ref_clk_hz, f_pdata->tchsh_ns);
+ tslch = calculate_ticks_for_ns(ref_clk_hz, f_pdata->tslch_ns);
+ tsd2d = calculate_ticks_for_ns(ref_clk_hz, f_pdata->tsd2d_ns);
+
+ reg = ((tshsl & CQSPI_REG_DELAY_TSHSL_MASK)
+ << CQSPI_REG_DELAY_TSHSL_LSB);
+ reg |= ((tchsh & CQSPI_REG_DELAY_TCHSH_MASK)
+ << CQSPI_REG_DELAY_TCHSH_LSB);
+ reg |= ((tslch & CQSPI_REG_DELAY_TSLCH_MASK)
+ << CQSPI_REG_DELAY_TSLCH_LSB);
+ reg |= ((tsd2d & CQSPI_REG_DELAY_TSD2D_MASK)
+ << CQSPI_REG_DELAY_TSD2D_LSB);
+ writel(reg, reg_base + CQSPI_REG_DELAY);
+}
+
+static void cqspi_config_baudrate_div(struct cqspi_st *cqspi,
+ unsigned int ref_clk_hz,
+ unsigned int sclk_hz)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int reg;
+ unsigned int div;
+
+ reg = readl(reg_base + CQSPI_REG_CONFIG);
+ reg &= ~(CQSPI_REG_CONFIG_BAUD_MASK << CQSPI_REG_CONFIG_BAUD_LSB);
+
+ div = ref_clk_hz / sclk_hz;
+
+ /* Recalculate the baudrate divisor based on QSPI specification. */
+ if (div > 32)
+ div = 32;
+
+ /* Check if even number. */
+ if (div & 1)
+ div = (div / 2);
+ else
+ div = (div / 2) - 1;
+
+ div = (div & CQSPI_REG_CONFIG_BAUD_MASK) << CQSPI_REG_CONFIG_BAUD_LSB;
+ reg |= div;
+ writel(reg, reg_base + CQSPI_REG_CONFIG);
+}
+
+static void cqspi_readdata_capture(struct cqspi_st *cqspi,
+ unsigned int bypass, unsigned int delay)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int reg;
+
+ if (cqspi->no_reconfig)
+ return;
+
+ reg = readl(reg_base + CQSPI_REG_READCAPTURE);
+
+ if (bypass)
+ reg |= (1 << CQSPI_REG_READCAPTURE_BYPASS_LSB);
+ else
+ reg &= ~(1 << CQSPI_REG_READCAPTURE_BYPASS_LSB);
+
+ reg &= ~(CQSPI_REG_READCAPTURE_DELAY_MASK
+ << CQSPI_REG_READCAPTURE_DELAY_LSB);
+
+ reg |= ((delay & CQSPI_REG_READCAPTURE_DELAY_MASK)
+ << CQSPI_REG_READCAPTURE_DELAY_LSB);
+
+ writel(reg, reg_base + CQSPI_REG_READCAPTURE);
+}
+
+static void cqspi_chipselect(struct cqspi_st *cqspi,
+ unsigned int chip_select,
+ unsigned int decoder_enable)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int reg;
+
+ reg = readl(reg_base + CQSPI_REG_CONFIG);
+ if (decoder_enable) {
+ reg |= CQSPI_REG_CONFIG_DECODE_MASK;
+ } else {
+ reg &= ~CQSPI_REG_CONFIG_DECODE_MASK;
+
+ /* Convert CS if without decoder.
+ * CS0 to 4b'1110
+ * CS1 to 4b'1101
+ * CS2 to 4b'1011
+ * CS3 to 4b'0111
+ */
+ chip_select = 0xF & ~(1 << chip_select);
+ }
+
+ reg &= ~(CQSPI_REG_CONFIG_CHIPSELECT_MASK
+ << CQSPI_REG_CONFIG_CHIPSELECT_LSB);
+ reg |= (chip_select & CQSPI_REG_CONFIG_CHIPSELECT_MASK)
+ << CQSPI_REG_CONFIG_CHIPSELECT_LSB;
+ writel(reg, reg_base + CQSPI_REG_CONFIG);
+}
+
+static void cqspi_controller_enable(struct cqspi_st *cqspi)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int reg;
+
+ reg = readl(reg_base + CQSPI_REG_CONFIG);
+ reg |= CQSPI_REG_CONFIG_ENABLE_MASK;
+ writel(reg, reg_base + CQSPI_REG_CONFIG);
+}
+
+static void cqspi_controller_disable(struct cqspi_st *cqspi)
+{
+ void __iomem *reg_base = cqspi->iobase;
+ unsigned int reg;
+
+ reg = readl(reg_base + CQSPI_REG_CONFIG);
+ reg &= ~CQSPI_REG_CONFIG_ENABLE_MASK;
+ writel(reg, reg_base + CQSPI_REG_CONFIG);
+}
+
+static void cqspi_switch_cs(struct cqspi_st *cqspi, unsigned int cs)
+{
+ unsigned int reg;
+ struct cqspi_flash_pdata *f_pdata = &cqspi->f_pdata[cs];
+ void __iomem *reg_base = cqspi->iobase;
+ struct spi_nor *nor = &f_pdata->nor;
+
+ cqspi_controller_disable(cqspi);
+
+ /* configure page size and block size. */
+ reg = readl(reg_base + CQSPI_REG_SIZE);
+ reg &= ~(CQSPI_REG_SIZE_PAGE_MASK << CQSPI_REG_SIZE_PAGE_LSB);
+ reg &= ~(CQSPI_REG_SIZE_BLOCK_MASK << CQSPI_REG_SIZE_BLOCK_LSB);
+ reg |= (nor->page_size << CQSPI_REG_SIZE_PAGE_LSB);
+ reg |= (f_pdata->block_size << CQSPI_REG_SIZE_BLOCK_LSB);
+ reg &= ~CQSPI_REG_SIZE_ADDRESS_MASK;
+ reg |= (nor->addr_width - 1);
+ writel(reg, reg_base + CQSPI_REG_SIZE);
+
+ /* configure the chip select */
+ cqspi_chipselect(cqspi, cs, cqspi->ext_decoder);
+
+ cqspi_controller_enable(cqspi);
+}
+
+static int cqspi_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ struct cqspi_st *cqspi = nor->priv;
+ int cs = cqspi_find_chipselect(nor);
+ struct cqspi_flash_pdata *f_pdata;
+ unsigned int sclk;
+
+ /* Switch chip select. */
+ if (cqspi->current_cs != cs) {
+ cqspi->current_cs = cs;
+ cqspi_switch_cs(cqspi, cs);
+ }
+
+ /* Setup baudrate divisor and delays */
+ f_pdata = &cqspi->f_pdata[cqspi->current_cs];
+ sclk = f_pdata->clk_rate;
+ if (cqspi->sclk != sclk) {
+ cqspi->sclk = sclk;
+ cqspi_controller_disable(cqspi);
+ cqspi_config_baudrate_div(cqspi,
+ cqspi->master_ref_clk_hz, sclk);
+ cqspi_delay(cqspi, cqspi->master_ref_clk_hz, sclk);
+ cqspi_readdata_capture(cqspi, 1, f_pdata->read_delay);
+ cqspi_controller_enable(cqspi);
+ }
+ return 0;
+}
+
+static int cqspi_read_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len)
+{
+ int ret;
+
+ cqspi_prep(nor, SPI_NOR_OPS_READ);
+
+ ret = cqspi_command_read(nor, &opcode, 1, buf, len);
+ return ret;
+}
+
+static int cqspi_write_reg(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
+ int write_enable)
+{
+ int ret = 0;
+
+ if (!IS_ENABLED(CONFIG_MTD_WRITE))
+ return -ENOTSUPP;
+
+ cqspi_prep(nor, SPI_NOR_OPS_WRITE);
+
+ ret = cqspi_command_write(nor, opcode, buf, len);
+ return ret;
+}
+
+static int cqspi_of_get_flash_pdata(struct device_d *dev,
+ struct cqspi_flash_pdata *f_pdata,
+ struct device_node *np)
+{
+ struct cqspi_st *cqspi = dev->priv;
+ void __iomem *reg_base = cqspi->iobase;
+
+ if (!np) {
+ f_pdata->block_size = (readl(reg_base + CQSPI_REG_SIZE) >>
+ CQSPI_REG_SIZE_BLOCK_LSB) &
+ CQSPI_REG_SIZE_BLOCK_MASK;
+
+ cqspi->no_reconfig = true;
+
+ return 0;
+ }
+
+ if (of_property_read_u32(np, "cdns,block-size", &f_pdata->block_size)) {
+ dev_err(dev, "couldn't determine block-size\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "cdns,read-delay", &f_pdata->read_delay)) {
+ dev_err(dev, "couldn't determine read-delay\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "cdns,tshsl-ns", &f_pdata->tshsl_ns)) {
+ dev_err(dev, "couldn't determine tshsl-ns\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "cdns,tsd2d-ns", &f_pdata->tsd2d_ns)) {
+ dev_err(dev, "couldn't determine tsd2d-ns\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "cdns,tchsh-ns", &f_pdata->tchsh_ns)) {
+ dev_err(dev, "couldn't determine tchsh-ns\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "cdns,tslch-ns", &f_pdata->tslch_ns)) {
+ dev_err(dev, "couldn't determine tslch-ns\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "spi-max-frequency", &f_pdata->clk_rate)) {
+ dev_err(dev, "couldn't determine spi-max-frequency\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int cqspi_parse_dt(struct cqspi_st *cqspi)
+{
+ struct device_node *np = cqspi->dev->device_node;
+ struct device_d *dev = cqspi->dev;
+
+ if (of_property_read_u32(np, "ext-decoder", &cqspi->ext_decoder)) {
+ dev_err(dev, "couldn't determine ext-decoder\n");
+ return -ENXIO;
+ }
+
+ if (of_property_read_u32(np, "fifo-depth", &cqspi->fifo_depth)) {
+ dev_err(dev, "couldn't determine fifo-depth\n");
+ return -ENXIO;
+ }
+
+ return 0;
+}
+
+static int cqspi_setup_flash(struct device_d *dev,
+ struct cqspi_flash_pdata *f_pdata,
+ struct device_node *np)
+{
+ struct cqspi_st *cqspi = dev->priv;
+ struct mtd_info *mtd;
+ struct spi_nor *nor;
+ int ret;
+
+ ret = cqspi_of_get_flash_pdata(dev, f_pdata, np);
+ if (ret)
+ goto probe_failed;
+
+ nor = &f_pdata->nor;
+ mtd = &f_pdata->mtd;
+
+ nor->mtd = mtd;
+
+ if (np) {
+ nor->dev = xzalloc(sizeof(*nor->dev));
+
+ strcpy(nor->dev->name, np->name);
+
+ nor->dev->device_node = np;
+ nor->dev->id = DEVICE_ID_SINGLE;
+ nor->dev->parent = dev;
+ ret = register_device(nor->dev);
+
+ if (ret)
+ return ret;
+
+ mtd->parent = nor->dev;
+ } else {
+ nor->dev = dev;
+ }
+
+ nor->priv = cqspi;
+ mtd->priv = nor;
+
+ nor->read_reg = cqspi_read_reg;
+ nor->write_reg = cqspi_write_reg;
+ nor->read = cqspi_read;
+ nor->write = cqspi_write;
+ nor->erase = cqspi_erase;
+
+ ret = spi_nor_scan(nor, NULL, SPI_NOR_QUAD);
+ if (ret)
+ goto probe_failed;
+
+ ret = add_mtd_device(mtd, NULL, DEVICE_ID_DYNAMIC);
+ if (ret)
+ goto probe_failed;
+
+ return 0;
+
+probe_failed:
+ dev_err(dev, "probing for flashchip failed\n");
+ return ret;
+
+}
+
+static void cqspi_controller_init(struct cqspi_st *cqspi)
+{
+ cqspi_controller_disable(cqspi);
+
+ /* Configure the remap address register, no remap */
+ writel(0, cqspi->iobase + CQSPI_REG_REMAP);
+
+ /* Disable all interrupts */
+ writel(0, cqspi->iobase + CQSPI_REG_IRQMASK);
+
+ cqspi_controller_enable(cqspi);
+}
+
+static int cqspi_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct cqspi_st *cqspi;
+ struct cadence_qspi_platform_data *pdata = dev->platform_data;
+ int ret;
+
+ cqspi = kzalloc(sizeof(*cqspi), GFP_KERNEL);
+ if (!cqspi)
+ return -ENOMEM;
+
+ cqspi->dev = dev;
+ dev->priv = cqspi;
+
+ if (pdata) {
+ cqspi->ext_decoder = pdata->ext_decoder;
+ cqspi->fifo_depth = pdata->fifo_depth;
+ } else {
+ ret = cqspi_parse_dt(cqspi);
+ if (ret) {
+ dev_err(dev, "Get platform data failed.\n");
+ return -ENODEV;
+ }
+ }
+
+ cqspi->qspi_clk = clk_get(dev, "qspi_clk");
+ if (IS_ERR(cqspi->qspi_clk)) {
+ dev_err(dev, "cannot get qspi clk\n");
+ ret = PTR_ERR(cqspi->qspi_clk);
+ goto probe_failed;
+ }
+ cqspi->master_ref_clk_hz = clk_get_rate(cqspi->qspi_clk);
+
+ clk_enable(cqspi->qspi_clk);
+
+ cqspi->iobase = dev_request_mem_region(dev, 0);
+ if (IS_ERR(cqspi->iobase)) {
+ dev_err(dev, "dev_request_mem_region 0 failed\n");
+ ret = PTR_ERR(cqspi->iobase);
+ goto probe_failed;
+ }
+
+ cqspi->ahb_base = dev_request_mem_region(dev, 1);
+ if (IS_ERR(cqspi->ahb_base)) {
+ dev_err(dev, "dev_request_mem_region 0 failed\n");
+ ret = PTR_ERR(cqspi->ahb_base);
+ goto probe_failed;
+ }
+
+ cqspi_wait_idle(cqspi);
+ cqspi_controller_init(cqspi);
+ cqspi->current_cs = -1;
+ cqspi->sclk = 0;
+
+ if (!dev->device_node) {
+ struct cqspi_flash_pdata *f_pdata;
+
+ f_pdata = &cqspi->f_pdata[0];
+
+ ret = cqspi_setup_flash(dev, f_pdata, NULL);
+ if (ret)
+ goto probe_failed;
+ } else {
+ /* Get flash device data */
+ for_each_available_child_of_node(dev->device_node, np) {
+ struct cqspi_flash_pdata *f_pdata;
+ unsigned int cs;
+ if (of_property_read_u32(np, "reg", &cs)) {
+ dev_err(dev, "couldn't determine chip select\n");
+ return -ENXIO;
+ }
+ if (cs > CQSPI_MAX_CHIPSELECT) {
+ dev_err(dev, "chip select %d out of range\n", cs);
+ return -ENXIO;
+ }
+ f_pdata = &cqspi->f_pdata[cs];
+
+ ret = cqspi_setup_flash(dev, f_pdata, np);
+ if (ret)
+ goto probe_failed;
+ }
+ }
+
+ dev_info(dev, "Cadence QSPI NOR flash driver\n");
+ return 0;
+
+probe_failed:
+ dev_err(dev, "Cadence QSPI NOR probe failed\n");
+ return ret;
+}
+
+static __maybe_unused struct of_device_id cqspi_dt_ids[] = {
+ {.compatible = "cdns,qspi-nor",},
+ { /* end of table */ }
+};
+
+static struct driver_d cqspi_driver = {
+ .name = "cadence_qspi",
+ .probe = cqspi_probe,
+ .of_compatible = DRV_OF_COMPAT(cqspi_dt_ids),
+};
+device_platform_driver(cqspi_driver);
diff --git a/drivers/mtd/spi-nor/spi-nor.c b/drivers/mtd/spi-nor/spi-nor.c
new file mode 100644
index 0000000000..c85ed34e06
--- /dev/null
+++ b/drivers/mtd/spi-nor/spi-nor.c
@@ -0,0 +1,1148 @@
+/*
+ * Based on m25p80.c, by Mike Lavender (mike@steroidmicros.com), with
+ * influence from lart.c (Abraham Van Der Merwe) and mtd_dataflash.c
+ *
+ * Copyright (C) 2005, Intec Automation Inc.
+ * Copyright (C) 2014, Freescale Semiconductor, Inc.
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <clock.h>
+#include <common.h>
+#include <driver.h>
+#include <errno.h>
+#include <linux/err.h>
+#include <linux/math64.h>
+#include <linux/mod_devicetable.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/cfi.h>
+#include <linux/mtd/spi-nor.h>
+#include <of.h>
+#include <spi/flash.h>
+
+#define SPI_NOR_MAX_ID_LEN 6
+
+struct flash_info {
+ /*
+ * This array stores the ID bytes.
+ * The first three bytes are the JEDIC ID.
+ * JEDEC ID zero means "no ID" (mostly older chips).
+ */
+ u8 id[SPI_NOR_MAX_ID_LEN];
+ u8 id_len;
+
+ /* The size listed here is what works with SPINOR_OP_SE, which isn't
+ * necessarily called a "sector" by the vendor.
+ */
+ unsigned sector_size;
+ u16 n_sectors;
+
+ u16 page_size;
+ u16 addr_width;
+
+ u16 flags;
+#define SECT_4K 0x01 /* SPINOR_OP_BE_4K works uniformly */
+#define SPI_NOR_NO_ERASE 0x02 /* No erase command needed */
+#define SST_WRITE 0x04 /* use SST byte programming */
+#define SPI_NOR_NO_FR 0x08 /* Can't do fastread */
+#define SECT_4K_PMC 0x10 /* SPINOR_OP_BE_4K_PMC works uniformly */
+#define SPI_NOR_DUAL_READ 0x20 /* Flash supports Dual Read */
+#define SPI_NOR_QUAD_READ 0x40 /* Flash supports Quad Read */
+#define USE_FSR 0x80 /* use flag status register */
+};
+
+#define JEDEC_MFR(info) ((info)->id[0])
+
+static const struct spi_device_id *spi_nor_match_id(const char *name);
+
+/*
+ * Read the status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_sr(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDSR, &val, 1);
+ if (ret < 0) {
+ pr_err("error %d reading SR\n", (int) ret);
+ return ret;
+ }
+
+ return val;
+}
+
+/*
+ * Read the flag status register, returning its value in the location
+ * Return the status register value.
+ * Returns negative if error occurred.
+ */
+static int read_fsr(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDFSR, &val, 1);
+ if (ret < 0) {
+ pr_err("error %d reading FSR\n", ret);
+ return ret;
+ }
+
+ return val;
+}
+
+/*
+ * Read configuration register, returning its value in the
+ * location. Return the configuration register value.
+ * Returns negative if error occured.
+ */
+static int read_cr(struct spi_nor *nor)
+{
+ int ret;
+ u8 val;
+
+ ret = nor->read_reg(nor, SPINOR_OP_RDCR, &val, 1);
+ if (ret < 0) {
+ dev_err(nor->dev, "error %d reading CR\n", ret);
+ return ret;
+ }
+
+ return val;
+}
+
+/*
+ * Dummy Cycle calculation for different type of read.
+ * It can be used to support more commands with
+ * different dummy cycle requirements.
+ */
+static inline int spi_nor_read_dummy_cycles(struct spi_nor *nor)
+{
+ switch (nor->flash_read) {
+ case SPI_NOR_FAST:
+ case SPI_NOR_DUAL:
+ case SPI_NOR_QUAD:
+ return 8;
+ case SPI_NOR_NORMAL:
+ return 0;
+ }
+ return 0;
+}
+
+/*
+ * Write status register 1 byte
+ * Returns negative if error occurred.
+ */
+static inline int write_sr(struct spi_nor *nor, u8 val)
+{
+ nor->cmd_buf[0] = val;
+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);
+}
+
+/*
+ * Set write enable latch with Write Enable command.
+ * Returns negative if error occurred.
+ */
+static inline int write_enable(struct spi_nor *nor)
+{
+ return nor->write_reg(nor, SPINOR_OP_WREN, NULL, 0, 0);
+}
+
+/*
+ * Send write disble instruction to the chip.
+ */
+static inline int write_disable(struct spi_nor *nor)
+{
+ return nor->write_reg(nor, SPINOR_OP_WRDI, NULL, 0, 0);
+}
+
+static inline struct spi_nor *mtd_to_spi_nor(struct mtd_info *mtd)
+{
+ return mtd->priv;
+}
+
+/* Enable/disable 4-byte addressing mode. */
+static inline int set_4byte(struct spi_nor *nor, struct flash_info *info,
+ int enable)
+{
+ int status;
+ bool need_wren = false;
+ u8 cmd;
+
+ switch (JEDEC_MFR(info)) {
+ case CFI_MFR_ST: /* Micron, actually */
+ /* Some Micron need WREN command; all will accept it */
+ need_wren = true;
+ case CFI_MFR_MACRONIX:
+ case 0xEF /* winbond */:
+ if (need_wren)
+ write_enable(nor);
+
+ cmd = enable ? SPINOR_OP_EN4B : SPINOR_OP_EX4B;
+ status = nor->write_reg(nor, cmd, NULL, 0, 0);
+ if (need_wren)
+ write_disable(nor);
+
+ return status;
+ default:
+ /* Spansion style */
+ nor->cmd_buf[0] = enable << 7;
+ return nor->write_reg(nor, SPINOR_OP_BRWR, nor->cmd_buf, 1, 0);
+ }
+}
+static inline int spi_nor_sr_ready(struct spi_nor *nor)
+{
+ int sr = read_sr(nor);
+ if (sr < 0)
+ return sr;
+ else
+ return !(sr & SR_WIP);
+}
+
+static inline int spi_nor_fsr_ready(struct spi_nor *nor)
+{
+ int fsr = read_fsr(nor);
+ if (fsr < 0)
+ return fsr;
+ else
+ return fsr & FSR_READY;
+}
+
+static int spi_nor_ready(struct spi_nor *nor)
+{
+ int sr, fsr;
+ sr = spi_nor_sr_ready(nor);
+ if (sr < 0)
+ return sr;
+ fsr = nor->flags & SNOR_F_USE_FSR ? spi_nor_fsr_ready(nor) : 1;
+ if (fsr < 0)
+ return fsr;
+ return sr && fsr;
+}
+
+/*
+ * Service routine to read status register until ready, or timeout occurs.
+ * Returns non-zero if error.
+ */
+static int spi_nor_wait_till_ready(struct spi_nor *nor)
+{
+ uint64_t start = get_time_ns();
+ int timeout = 0;
+ int ret;
+
+ while (!timeout) {
+ if (is_timeout(start, 40 * SECOND))
+ timeout = 1;
+
+ ret = spi_nor_ready(nor);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ return 0;
+ }
+
+ dev_err(nor->dev, "flash operation timed out\n");
+
+ return -ETIMEDOUT;
+}
+
+/*
+ * Erase the whole flash memory
+ *
+ * Returns 0 if successful, non-zero otherwise.
+ */
+static int erase_chip(struct spi_nor *nor)
+{
+ dev_dbg(nor->dev, " %lldKiB\n", (long long)(nor->mtd->size >> 10));
+
+ return nor->write_reg(nor, SPINOR_OP_CHIP_ERASE, NULL, 0, 0);
+}
+
+static int spi_nor_lock_and_prep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ int ret = 0;
+
+ mutex_lock(&nor->lock);
+
+ if (nor->prepare) {
+ ret = nor->prepare(nor, ops);
+ if (ret) {
+ dev_err(nor->dev, "failed in the preparation.\n");
+ mutex_unlock(&nor->lock);
+ return ret;
+ }
+ }
+ return ret;
+}
+
+static void spi_nor_unlock_and_unprep(struct spi_nor *nor, enum spi_nor_ops ops)
+{
+ if (nor->unprepare)
+ nor->unprepare(nor, ops);
+ mutex_unlock(&nor->lock);
+}
+
+/*
+ * Erase an address range on the nor chip. The address range may extend
+ * one or more erase sectors. Return an error is there is a problem erasing.
+ */
+static int spi_nor_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ u32 addr, len;
+ uint32_t rem;
+ int ret;
+
+ dev_dbg(nor->dev, "at 0x%llx, len %lld\n", (long long)instr->addr,
+ (long long)instr->len);
+
+ div_u64_rem(instr->len, mtd->erasesize, &rem);
+ if (rem)
+ return -EINVAL;
+
+ addr = instr->addr;
+ len = instr->len;
+
+ /* Assure previous operations are completed */
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto erase_err;
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_ERASE);
+ if (ret)
+ return ret;
+
+ /* whole-chip erase? */
+ if (len == mtd->size) {
+ write_enable(nor);
+
+ if (erase_chip(nor)) {
+ ret = -EIO;
+ goto erase_err;
+ }
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto erase_err;
+
+ /* REVISIT in some cases we could speed up erasing large regions
+ * by using SPINOR_OP_SE instead of SPINOR_OP_BE_4K. We may have set up
+ * to use "small sector erase", but that's not always optimal.
+ */
+
+ /* "sector"-at-a-time erase */
+ } else {
+ while (len) {
+ write_enable(nor);
+
+ if (nor->erase(nor, addr)) {
+ ret = -EIO;
+ goto erase_err;
+ }
+
+ addr += mtd->erasesize;
+ len -= mtd->erasesize;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto erase_err;
+ }
+ }
+
+ write_disable(nor);
+
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
+
+ instr->state = MTD_ERASE_DONE;
+ mtd_erase_callback(instr);
+
+ return ret;
+
+erase_err:
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_ERASE);
+ instr->state = MTD_ERASE_FAILED;
+ return ret;
+}
+
+static int spi_nor_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ uint32_t offset = ofs;
+ uint8_t status_old, status_new;
+ int ret = 0;
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_LOCK);
+ if (ret)
+ return ret;
+
+ status_old = read_sr(nor);
+
+ if (offset < mtd->size - (mtd->size / 2))
+ status_new = status_old | SR_BP2 | SR_BP1 | SR_BP0;
+ else if (offset < mtd->size - (mtd->size / 4))
+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
+ else if (offset < mtd->size - (mtd->size / 8))
+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
+ else if (offset < mtd->size - (mtd->size / 16))
+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
+ else if (offset < mtd->size - (mtd->size / 32))
+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
+ else if (offset < mtd->size - (mtd->size / 64))
+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
+ else
+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
+
+ /* Only modify protection if it will not unlock other areas */
+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) >
+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
+ write_enable(nor);
+ ret = write_sr(nor, status_new);
+ if (ret)
+ goto err;
+ }
+
+err:
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_LOCK);
+ return ret;
+}
+
+static int spi_nor_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ uint32_t offset = ofs;
+ uint8_t status_old, status_new;
+ int ret = 0;
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_UNLOCK);
+ if (ret)
+ return ret;
+
+ status_old = read_sr(nor);
+
+ if (offset+len > mtd->size - (mtd->size / 64))
+ status_new = status_old & ~(SR_BP2 | SR_BP1 | SR_BP0);
+ else if (offset+len > mtd->size - (mtd->size / 32))
+ status_new = (status_old & ~(SR_BP2 | SR_BP1)) | SR_BP0;
+ else if (offset+len > mtd->size - (mtd->size / 16))
+ status_new = (status_old & ~(SR_BP2 | SR_BP0)) | SR_BP1;
+ else if (offset+len > mtd->size - (mtd->size / 8))
+ status_new = (status_old & ~SR_BP2) | SR_BP1 | SR_BP0;
+ else if (offset+len > mtd->size - (mtd->size / 4))
+ status_new = (status_old & ~(SR_BP0 | SR_BP1)) | SR_BP2;
+ else if (offset+len > mtd->size - (mtd->size / 2))
+ status_new = (status_old & ~SR_BP1) | SR_BP2 | SR_BP0;
+ else
+ status_new = (status_old & ~SR_BP0) | SR_BP2 | SR_BP1;
+
+ /* Only modify protection if it will not lock other areas */
+ if ((status_new & (SR_BP2 | SR_BP1 | SR_BP0)) <
+ (status_old & (SR_BP2 | SR_BP1 | SR_BP0))) {
+ write_enable(nor);
+ ret = write_sr(nor, status_new);
+ if (ret)
+ goto err;
+ }
+
+err:
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_UNLOCK);
+ return ret;
+}
+
+/* Used when the "_ext_id" is two bytes at most */
+#define INFO(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+ ((unsigned long)&(struct flash_info) { \
+ .id = { \
+ ((_jedec_id) >> 16) & 0xff, \
+ ((_jedec_id) >> 8) & 0xff, \
+ (_jedec_id) & 0xff, \
+ ((_ext_id) >> 8) & 0xff, \
+ (_ext_id) & 0xff, \
+ }, \
+ .id_len = (!(_jedec_id) ? 0 : (3 + ((_ext_id) ? 2 : 0))), \
+ .sector_size = (_sector_size), \
+ .n_sectors = (_n_sectors), \
+ .page_size = 256, \
+ .flags = (_flags), \
+ })
+
+#define INFO6(_jedec_id, _ext_id, _sector_size, _n_sectors, _flags) \
+ ((unsigned long)&(struct flash_info) { \
+ .id = { \
+ ((_jedec_id) >> 16) & 0xff, \
+ ((_jedec_id) >> 8) & 0xff, \
+ (_jedec_id) & 0xff, \
+ ((_ext_id) >> 16) & 0xff, \
+ ((_ext_id) >> 8) & 0xff, \
+ (_ext_id) & 0xff, \
+ }, \
+ .id_len = 6, \
+ .sector_size = (_sector_size), \
+ .n_sectors = (_n_sectors), \
+ .page_size = 256, \
+ .flags = (_flags), \
+ })
+
+#define CAT25_INFO(_sector_size, _n_sectors, _page_size, _addr_width, _flags) \
+ ((unsigned long)&(struct flash_info) { \
+ .sector_size = (_sector_size), \
+ .n_sectors = (_n_sectors), \
+ .page_size = (_page_size), \
+ .addr_width = (_addr_width), \
+ .flags = (_flags), \
+ })
+
+/* NOTE: double check command sets and memory organization when you add
+ * more nor chips. This current list focusses on newer chips, which
+ * have been converging on command sets which including JEDEC ID.
+ */
+static const struct spi_device_id spi_nor_ids[] = {
+ /* Atmel -- some are (confusingly) marketed as "DataFlash" */
+ { "at25fs010", INFO(0x1f6601, 0, 32 * 1024, 4, SECT_4K) },
+ { "at25fs040", INFO(0x1f6604, 0, 64 * 1024, 8, SECT_4K) },
+
+ { "at25df041a", INFO(0x1f4401, 0, 64 * 1024, 8, SECT_4K) },
+ { "at25df321a", INFO(0x1f4701, 0, 64 * 1024, 64, SECT_4K) },
+ { "at25df641", INFO(0x1f4800, 0, 64 * 1024, 128, SECT_4K) },
+
+ { "at26f004", INFO(0x1f0400, 0, 64 * 1024, 8, SECT_4K) },
+ { "at26df081a", INFO(0x1f4501, 0, 64 * 1024, 16, SECT_4K) },
+ { "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
+ { "at26df321", INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
+
+ { "at45db081d", INFO(0x1f2500, 0, 64 * 1024, 16, SECT_4K) },
+
+ /* EON -- en25xxx */
+ { "en25f32", INFO(0x1c3116, 0, 64 * 1024, 64, SECT_4K) },
+ { "en25p32", INFO(0x1c2016, 0, 64 * 1024, 64, 0) },
+ { "en25q32b", INFO(0x1c3016, 0, 64 * 1024, 64, 0) },
+ { "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
+ { "en25q64", INFO(0x1c3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "en25qh128", INFO(0x1c7018, 0, 64 * 1024, 256, 0) },
+ { "en25qh256", INFO(0x1c7019, 0, 64 * 1024, 512, 0) },
+
+ /* ESMT */
+ { "f25l32pa", INFO(0x8c2016, 0, 64 * 1024, 64, SECT_4K) },
+
+ /* Everspin */
+ { "mr25h256", CAT25_INFO( 32 * 1024, 1, 256, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "mr25h10", CAT25_INFO(128 * 1024, 1, 256, 3, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+
+ /* Fujitsu */
+ { "mb85rs1mt", INFO(0x047f27, 0, 128 * 1024, 1, SPI_NOR_NO_ERASE) },
+
+ /* GigaDevice */
+ { "gd25q32", INFO(0xc84016, 0, 64 * 1024, 64, SECT_4K) },
+ { "gd25q64", INFO(0xc84017, 0, 64 * 1024, 128, SECT_4K) },
+
+ /* Intel/Numonyx -- xxxs33b */
+ { "160s33b", INFO(0x898911, 0, 64 * 1024, 32, 0) },
+ { "320s33b", INFO(0x898912, 0, 64 * 1024, 64, 0) },
+ { "640s33b", INFO(0x898913, 0, 64 * 1024, 128, 0) },
+
+ /* Macronix */
+ { "mx25l2005a", INFO(0xc22012, 0, 64 * 1024, 4, SECT_4K) },
+ { "mx25l4005a", INFO(0xc22013, 0, 64 * 1024, 8, SECT_4K) },
+ { "mx25l8005", INFO(0xc22014, 0, 64 * 1024, 16, 0) },
+ { "mx25l1606e", INFO(0xc22015, 0, 64 * 1024, 32, SECT_4K) },
+ { "mx25l3205d", INFO(0xc22016, 0, 64 * 1024, 64, 0) },
+ { "mx25l3255e", INFO(0xc29e16, 0, 64 * 1024, 64, SECT_4K) },
+ { "mx25l6405d", INFO(0xc22017, 0, 64 * 1024, 128, 0) },
+ { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
+ { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
+ { "mx25l25635e", INFO(0xc22019, 0, 64 * 1024, 512, 0) },
+ { "mx25l25655e", INFO(0xc22619, 0, 64 * 1024, 512, 0) },
+ { "mx66l51235l", INFO(0xc2201a, 0, 64 * 1024, 1024, SPI_NOR_QUAD_READ) },
+ { "mx66l1g55g", INFO(0xc2261b, 0, 64 * 1024, 2048, SPI_NOR_QUAD_READ) },
+
+ /* Micron */
+ { "n25q032", INFO(0x20ba16, 0, 64 * 1024, 64, 0) },
+ { "n25q064", INFO(0x20ba17, 0, 64 * 1024, 128, 0) },
+ { "n25q128a11", INFO(0x20bb18, 0, 64 * 1024, 256, 0) },
+ { "n25q128a13", INFO(0x20ba18, 0, 64 * 1024, 256, 0) },
+ { "n25q256a", INFO(0x20ba19, 0, 64 * 1024, 512, SECT_4K | SPI_NOR_QUAD_READ) },
+ { "n25q512a", INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K) },
+ { "n25q512ax3", INFO(0x20ba20, 0, 64 * 1024, 1024, USE_FSR) },
+ { "n25q00", INFO(0x20ba21, 0, 64 * 1024, 2048, USE_FSR | SPI_NOR_QUAD_READ) },
+
+ /* PMC */
+ { "pm25lv512", INFO(0, 0, 32 * 1024, 2, SECT_4K_PMC) },
+ { "pm25lv010", INFO(0, 0, 32 * 1024, 4, SECT_4K_PMC) },
+ { "pm25lq032", INFO(0x7f9d46, 0, 64 * 1024, 64, SECT_4K) },
+
+ /* Spansion -- single (large) sector size only, at least
+ * for the chips listed here (without boot sectors).
+ */
+ { "s25sl032p", INFO(0x010215, 0x4d00, 64 * 1024, 64, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25sl064p", INFO(0x010216, 0x4d00, 64 * 1024, 128, 0) },
+ { "s25fl256s0", INFO(0x010219, 0x4d00, 256 * 1024, 128, 0) },
+ { "s25fl256s1", INFO(0x010219, 0x4d01, 64 * 1024, 512, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s25fl512s", INFO(0x010220, 0x4d00, 256 * 1024, 256, SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
+ { "s70fl01gs", INFO(0x010221, 0x4d00, 256 * 1024, 256, 0) },
+ { "s25sl12800", INFO(0x012018, 0x0300, 256 * 1024, 64, 0) },
+ { "s25sl12801", INFO(0x012018, 0x0301, 64 * 1024, 256, 0) },
+ { "s25fl128s", INFO6(0x012018, 0x4d0180, 64 * 1024, 256, SPI_NOR_QUAD_READ) },
+ { "s25fl129p0", INFO(0x012018, 0x4d00, 256 * 1024, 64, 0) },
+ { "s25fl129p1", INFO(0x012018, 0x4d01, 64 * 1024, 256, 0) },
+ { "s25sl004a", INFO(0x010212, 0, 64 * 1024, 8, 0) },
+ { "s25sl008a", INFO(0x010213, 0, 64 * 1024, 16, 0) },
+ { "s25sl016a", INFO(0x010214, 0, 64 * 1024, 32, 0) },
+ { "s25sl032a", INFO(0x010215, 0, 64 * 1024, 64, 0) },
+ { "s25sl064a", INFO(0x010216, 0, 64 * 1024, 128, 0) },
+ { "s25fl008k", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
+ { "s25fl016k", INFO(0xef4015, 0, 64 * 1024, 32, SECT_4K) },
+ { "s25fl064k", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+ { "s25fl132k", INFO(0x014016, 0, 64 * 1024, 64, 0) },
+
+ /* SST -- large erase sizes are "overlays", "sectors" are 4K */
+ { "sst25vf040b", INFO(0xbf258d, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
+ { "sst25vf080b", INFO(0xbf258e, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+ { "sst25vf016b", INFO(0xbf2541, 0, 64 * 1024, 32, SECT_4K | SST_WRITE) },
+ { "sst25vf032b", INFO(0xbf254a, 0, 64 * 1024, 64, SECT_4K | SST_WRITE) },
+ { "sst25vf064c", INFO(0xbf254b, 0, 64 * 1024, 128, SECT_4K) },
+ { "sst25wf512", INFO(0xbf2501, 0, 64 * 1024, 1, SECT_4K | SST_WRITE) },
+ { "sst25wf010", INFO(0xbf2502, 0, 64 * 1024, 2, SECT_4K | SST_WRITE) },
+ { "sst25wf020", INFO(0xbf2503, 0, 64 * 1024, 4, SECT_4K | SST_WRITE) },
+ { "sst25wf040", INFO(0xbf2504, 0, 64 * 1024, 8, SECT_4K | SST_WRITE) },
+ { "sst25wf080", INFO(0xbf2505, 0, 64 * 1024, 16, SECT_4K | SST_WRITE) },
+
+ /* ST Microelectronics -- newer production may have feature updates */
+ { "m25p05", INFO(0x202010, 0, 32 * 1024, 2, 0) },
+ { "m25p10", INFO(0x202011, 0, 32 * 1024, 4, 0) },
+ { "m25p20", INFO(0x202012, 0, 64 * 1024, 4, 0) },
+ { "m25p40", INFO(0x202013, 0, 64 * 1024, 8, 0) },
+ { "m25p80", INFO(0x202014, 0, 64 * 1024, 16, 0) },
+ { "m25p16", INFO(0x202015, 0, 64 * 1024, 32, 0) },
+ { "m25p32", INFO(0x202016, 0, 64 * 1024, 64, 0) },
+ { "m25p64", INFO(0x202017, 0, 64 * 1024, 128, 0) },
+ { "m25p128", INFO(0x202018, 0, 256 * 1024, 64, 0) },
+
+ { "m25p05-nonjedec", INFO(0, 0, 32 * 1024, 2, 0) },
+ { "m25p10-nonjedec", INFO(0, 0, 32 * 1024, 4, 0) },
+ { "m25p20-nonjedec", INFO(0, 0, 64 * 1024, 4, 0) },
+ { "m25p40-nonjedec", INFO(0, 0, 64 * 1024, 8, 0) },
+ { "m25p80-nonjedec", INFO(0, 0, 64 * 1024, 16, 0) },
+ { "m25p16-nonjedec", INFO(0, 0, 64 * 1024, 32, 0) },
+ { "m25p32-nonjedec", INFO(0, 0, 64 * 1024, 64, 0) },
+ { "m25p64-nonjedec", INFO(0, 0, 64 * 1024, 128, 0) },
+ { "m25p128-nonjedec", INFO(0, 0, 256 * 1024, 64, 0) },
+
+ { "m45pe10", INFO(0x204011, 0, 64 * 1024, 2, 0) },
+ { "m45pe80", INFO(0x204014, 0, 64 * 1024, 16, 0) },
+ { "m45pe16", INFO(0x204015, 0, 64 * 1024, 32, 0) },
+
+ { "m25pe20", INFO(0x208012, 0, 64 * 1024, 4, 0) },
+ { "m25pe80", INFO(0x208014, 0, 64 * 1024, 16, 0) },
+ { "m25pe16", INFO(0x208015, 0, 64 * 1024, 32, SECT_4K) },
+
+ { "m25px16", INFO(0x207115, 0, 64 * 1024, 32, SECT_4K) },
+ { "m25px32", INFO(0x207116, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px32-s0", INFO(0x207316, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px32-s1", INFO(0x206316, 0, 64 * 1024, 64, SECT_4K) },
+ { "m25px64", INFO(0x207117, 0, 64 * 1024, 128, 0) },
+ { "m25px80", INFO(0x207114, 0, 64 * 1024, 16, 0) },
+
+ /* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
+ { "w25x10", INFO(0xef3011, 0, 64 * 1024, 2, SECT_4K) },
+ { "w25x20", INFO(0xef3012, 0, 64 * 1024, 4, SECT_4K) },
+ { "w25x40", INFO(0xef3013, 0, 64 * 1024, 8, SECT_4K) },
+ { "w25x80", INFO(0xef3014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25x16", INFO(0xef3015, 0, 64 * 1024, 32, SECT_4K) },
+ { "w25x32", INFO(0xef3016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25q32", INFO(0xef4016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25q32dw", INFO(0xef6016, 0, 64 * 1024, 64, SECT_4K) },
+ { "w25x64", INFO(0xef3017, 0, 64 * 1024, 128, SECT_4K) },
+ { "w25q64", INFO(0xef4017, 0, 64 * 1024, 128, SECT_4K) },
+ { "w25q80", INFO(0xef5014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25q80bl", INFO(0xef4014, 0, 64 * 1024, 16, SECT_4K) },
+ { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
+ { "w25q256", INFO(0xef4019, 0, 64 * 1024, 512, SECT_4K) },
+
+ /* Catalyst / On Semiconductor -- non-JEDEC */
+ { "cat25c11", CAT25_INFO( 16, 8, 16, 1, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c03", CAT25_INFO( 32, 8, 16, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c09", CAT25_INFO( 128, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25c17", CAT25_INFO( 256, 8, 32, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { "cat25128", CAT25_INFO(2048, 8, 64, 2, SPI_NOR_NO_ERASE | SPI_NOR_NO_FR) },
+ { },
+};
+
+static const struct spi_device_id *spi_nor_read_id(struct spi_nor *nor)
+{
+ int tmp;
+ u8 id[SPI_NOR_MAX_ID_LEN];
+ struct flash_info *info;
+
+ tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
+ if (tmp < 0) {
+ dev_dbg(nor->dev, " error %d reading JEDEC ID\n", tmp);
+ return ERR_PTR(tmp);
+ }
+
+ for (tmp = 0; tmp < ARRAY_SIZE(spi_nor_ids) - 1; tmp++) {
+ info = (void *)spi_nor_ids[tmp].driver_data;
+ if (info->id_len) {
+ if (!memcmp(info->id, id, info->id_len))
+ return &spi_nor_ids[tmp];
+ }
+ }
+ dev_err(nor->dev, "unrecognized JEDEC id bytes: %02x, %2x, %2x\n",
+ id[0], id[1], id[2]);
+ return ERR_PTR(-ENODEV);
+}
+
+static int spi_nor_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t *retlen, u_char *buf)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ int ret;
+
+ dev_dbg(nor->dev, "from 0x%08x, len %zd\n", (u32)from, len);
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_READ);
+ if (ret)
+ return ret;
+
+ ret = nor->read(nor, from, len, retlen, buf);
+
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_READ);
+ return ret;
+}
+
+static int sst_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ size_t actual;
+ int ret;
+
+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
+ if (ret)
+ return ret;
+
+ write_enable(nor);
+
+ nor->sst_write_second = false;
+
+ actual = to % 2;
+ /* Start write from odd address. */
+ if (actual) {
+ nor->program_opcode = SPINOR_OP_BP;
+
+ /* write one byte. */
+ nor->write(nor, to, 1, retlen, buf);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto time_out;
+ }
+ to += actual;
+
+ /* Write out most of the data here. */
+ for (; actual < len - 1; actual += 2) {
+ nor->program_opcode = SPINOR_OP_AAI_WP;
+
+ /* write two bytes. */
+ nor->write(nor, to, 2, retlen, buf + actual);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto time_out;
+ to += 2;
+ nor->sst_write_second = true;
+ }
+ nor->sst_write_second = false;
+
+ write_disable(nor);
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto time_out;
+
+ /* Write out trailing byte if it exists. */
+ if (actual != len) {
+ write_enable(nor);
+
+ nor->program_opcode = SPINOR_OP_BP;
+ nor->write(nor, to, 1, retlen, buf + actual);
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto time_out;
+ write_disable(nor);
+ }
+time_out:
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
+ return ret;
+}
+
+/*
+ * Write an address range to the nor chip. Data must be written in
+ * FLASH_PAGESIZE chunks. The address range may be any size provided
+ * it is within the physical boundaries.
+ */
+static int spi_nor_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t *retlen, const u_char *buf)
+{
+ struct spi_nor *nor = mtd_to_spi_nor(mtd);
+ u32 page_offset, page_size, i;
+ int ret;
+
+ dev_dbg(nor->dev, "to 0x%08x, len %zd\n", (u32)to, len);
+
+ ret = spi_nor_lock_and_prep(nor, SPI_NOR_OPS_WRITE);
+ if (ret)
+ return ret;
+
+ write_enable(nor);
+
+ page_offset = to & (nor->page_size - 1);
+
+ /* do all the bytes fit onto one page? */
+ if (page_offset + len <= nor->page_size) {
+ nor->write(nor, to, len, retlen, buf);
+ } else {
+ /* the size of data remaining on the first page */
+ page_size = nor->page_size - page_offset;
+ nor->write(nor, to, page_size, retlen, buf);
+
+ /* write everything in nor->page_size chunks */
+ for (i = page_size; i < len; i += page_size) {
+ page_size = len - i;
+ if (page_size > nor->page_size)
+ page_size = nor->page_size;
+
+ ret = spi_nor_wait_till_ready(nor);
+ if (ret)
+ goto write_err;
+
+ write_enable(nor);
+
+ nor->write(nor, to + i, page_size, retlen, buf + i);
+ }
+ }
+
+ ret = spi_nor_wait_till_ready(nor);
+write_err:
+ spi_nor_unlock_and_unprep(nor, SPI_NOR_OPS_WRITE);
+ return ret;
+}
+
+static int macronix_quad_enable(struct spi_nor *nor)
+{
+ int ret, val;
+
+ val = read_sr(nor);
+ write_enable(nor);
+
+ nor->cmd_buf[0] = val | SR_QUAD_EN_MX;
+ nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 1, 0);
+
+ if (spi_nor_wait_till_ready(nor))
+ return 1;
+
+ ret = read_sr(nor);
+ if (!(ret > 0 && (ret & SR_QUAD_EN_MX))) {
+ dev_err(nor->dev, "Macronix Quad bit not set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Write status Register and configuration register with 2 bytes
+ * The first byte will be written to the status register, while the
+ * second byte will be written to the configuration register.
+ * Return negative if error occured.
+ */
+static int write_sr_cr(struct spi_nor *nor, u16 val)
+{
+ nor->cmd_buf[0] = val & 0xff;
+ nor->cmd_buf[1] = (val >> 8);
+
+ return nor->write_reg(nor, SPINOR_OP_WRSR, nor->cmd_buf, 2, 0);
+}
+
+static int spansion_quad_enable(struct spi_nor *nor)
+{
+ int ret;
+ int quad_en = CR_QUAD_EN_SPAN << 8;
+
+ write_enable(nor);
+
+ ret = write_sr_cr(nor, quad_en);
+ if (ret < 0) {
+ dev_err(nor->dev,
+ "error while writing configuration register\n");
+ return -EINVAL;
+ }
+
+ /* read back and check it */
+ ret = read_cr(nor);
+ if (!(ret > 0 && (ret & CR_QUAD_EN_SPAN))) {
+ dev_err(nor->dev, "Spansion Quad bit not set\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int set_quad_mode(struct spi_nor *nor, struct flash_info *info)
+{
+ int status;
+
+ switch (JEDEC_MFR(info)) {
+ case CFI_MFR_MACRONIX:
+ status = macronix_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "Macronix quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ default:
+ status = spansion_quad_enable(nor);
+ if (status) {
+ dev_err(nor->dev, "Spansion quad-read not enabled\n");
+ return -EINVAL;
+ }
+ return status;
+ }
+}
+
+static int spi_nor_check(struct spi_nor *nor)
+{
+ if (!nor->dev || !nor->read || !nor->write ||
+ !nor->read_reg || !nor->write_reg || !nor->erase) {
+ pr_err("spi-nor: please fill all the necessary fields!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode)
+{
+ const struct spi_device_id *id = NULL;
+ struct flash_info *info;
+ struct device_d *dev = nor->dev;
+ struct mtd_info *mtd = nor->mtd;
+ struct device_node *np = dev->device_node;
+ int ret;
+ int i;
+
+ ret = spi_nor_check(nor);
+ if (ret)
+ return ret;
+
+ /* Try to auto-detect if chip name wasn't specified */
+ if (!name)
+ id = spi_nor_read_id(nor);
+ else
+ id = spi_nor_match_id(name);
+ if (IS_ERR_OR_NULL(id))
+ return -ENOENT;
+
+ info = (void *)id->driver_data;
+
+ /*
+ * If caller has specified name of flash model that can normally be
+ * detected using JEDEC, let's verify it.
+ */
+ if (name && info->id_len) {
+ const struct spi_device_id *jid;
+
+ jid = spi_nor_read_id(nor);
+ if (IS_ERR(jid)) {
+ return PTR_ERR(jid);
+ } else if (jid != id) {
+ /*
+ * JEDEC knows better, so overwrite platform ID. We
+ * can't trust partitions any longer, but we'll let
+ * mtd apply them anyway, since some partitions may be
+ * marked read-only, and we don't want to lose that
+ * information, even if it's not 100% accurate.
+ */
+ dev_warn(dev, "found %s, expected %s\n",
+ jid->name, id->name);
+ id = jid;
+ info = (void *)jid->driver_data;
+ }
+ }
+
+ mutex_init(&nor->lock);
+
+ /*
+ * Atmel, SST and Intel/Numonyx serial nor tend to power
+ * up with the software protection bits set
+ */
+
+ if (JEDEC_MFR(info) == CFI_MFR_ATMEL ||
+ JEDEC_MFR(info) == CFI_MFR_INTEL ||
+ JEDEC_MFR(info) == CFI_MFR_SST) {
+ write_enable(nor);
+ write_sr(nor, 0);
+ }
+
+ if (!mtd->name)
+ mtd->name = (char *) dev_name(dev);
+ mtd->type = MTD_NORFLASH;
+ mtd->writesize = 1;
+ mtd->flags = MTD_CAP_NORFLASH;
+ mtd->size = info->sector_size * info->n_sectors;
+ mtd->erase = spi_nor_erase;
+ mtd->read = spi_nor_read;
+
+ /* nor protection support for STmicro chips */
+ if (JEDEC_MFR(info) == CFI_MFR_ST) {
+ mtd->lock = spi_nor_lock;
+ mtd->unlock = spi_nor_unlock;
+ }
+
+ /* sst nor chips use AAI word program */
+ if (info->flags & SST_WRITE)
+ mtd->write = sst_write;
+ else
+ mtd->write = spi_nor_write;
+
+ if (info->flags & USE_FSR)
+ nor->flags |= SNOR_F_USE_FSR;
+
+#ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
+ /* prefer "small sector" erase if possible */
+ if (info->flags & SECT_4K) {
+ nor->erase_opcode = SPINOR_OP_BE_4K;
+ mtd->erasesize = 4096;
+ } else if (info->flags & SECT_4K_PMC) {
+ nor->erase_opcode = SPINOR_OP_BE_4K_PMC;
+ mtd->erasesize = 4096;
+ } else
+#endif
+ {
+ nor->erase_opcode = SPINOR_OP_SE;
+ mtd->erasesize = info->sector_size;
+ }
+
+ if (info->flags & SPI_NOR_NO_ERASE)
+ mtd->flags |= MTD_NO_ERASE;
+
+ nor->page_size = info->page_size;
+ mtd->writebufsize = nor->page_size;
+
+ if (np) {
+ /* If we were instantiated by DT, use it */
+ if (of_property_read_bool(np, "m25p,fast-read"))
+ nor->flash_read = SPI_NOR_FAST;
+ else
+ nor->flash_read = SPI_NOR_NORMAL;
+ } else {
+ /* If we weren't instantiated by DT, default to fast-read */
+ nor->flash_read = SPI_NOR_FAST;
+ }
+
+ /* Some devices cannot do fast-read, no matter what DT tells us */
+ if (info->flags & SPI_NOR_NO_FR)
+ nor->flash_read = SPI_NOR_NORMAL;
+
+ /* Quad/Dual-read mode takes precedence over fast/normal */
+ if (mode == SPI_NOR_QUAD && info->flags & SPI_NOR_QUAD_READ) {
+ ret = set_quad_mode(nor, info);
+ if (ret) {
+ dev_err(dev, "quad mode not supported\n");
+ return ret;
+ }
+ nor->flash_read = SPI_NOR_QUAD;
+ } else if (mode == SPI_NOR_DUAL && info->flags & SPI_NOR_DUAL_READ) {
+ nor->flash_read = SPI_NOR_DUAL;
+ }
+
+ /* Default commands */
+ switch (nor->flash_read) {
+ case SPI_NOR_QUAD:
+ nor->read_opcode = SPINOR_OP_READ_1_1_4;
+ break;
+ case SPI_NOR_DUAL:
+ nor->read_opcode = SPINOR_OP_READ_1_1_2;
+ break;
+ case SPI_NOR_FAST:
+ nor->read_opcode = SPINOR_OP_READ_FAST;
+ break;
+ case SPI_NOR_NORMAL:
+ nor->read_opcode = SPINOR_OP_READ;
+ break;
+ default:
+ dev_err(dev, "No Read opcode defined\n");
+ return -EINVAL;
+ }
+
+ nor->program_opcode = SPINOR_OP_PP;
+
+ if (info->addr_width)
+ nor->addr_width = info->addr_width;
+ else if (mtd->size > 0x1000000) {
+ /* enable 4-byte addressing if the device exceeds 16MiB */
+ nor->addr_width = 4;
+ if (JEDEC_MFR(info) == CFI_MFR_AMD) {
+ /* Dedicated 4-byte command set */
+ switch (nor->flash_read) {
+ case SPI_NOR_QUAD:
+ nor->read_opcode = SPINOR_OP_READ4_1_1_4;
+ break;
+ case SPI_NOR_DUAL:
+ nor->read_opcode = SPINOR_OP_READ4_1_1_2;
+ break;
+ case SPI_NOR_FAST:
+ nor->read_opcode = SPINOR_OP_READ4_FAST;
+ break;
+ case SPI_NOR_NORMAL:
+ nor->read_opcode = SPINOR_OP_READ4;
+ break;
+ }
+ nor->program_opcode = SPINOR_OP_PP_4B;
+ /* No small sector erase for 4-byte command set */
+ nor->erase_opcode = SPINOR_OP_SE_4B;
+ mtd->erasesize = info->sector_size;
+ } else
+ set_4byte(nor, info, 1);
+ } else {
+ nor->addr_width = 3;
+ }
+
+ nor->read_dummy = spi_nor_read_dummy_cycles(nor);
+
+ dev_info(dev, "%s (%lld Kbytes)\n", id->name,
+ (long long)mtd->size >> 10);
+
+ dev_dbg(dev,
+ "mtd .name = %s, .size = 0x%llx (%lldMiB), "
+ ".erasesize = 0x%.8x (%uKiB) .numeraseregions = %d\n",
+ mtd->name, (long long)mtd->size, (long long)(mtd->size >> 20),
+ mtd->erasesize, mtd->erasesize / 1024, mtd->numeraseregions);
+
+ if (mtd->numeraseregions)
+ for (i = 0; i < mtd->numeraseregions; i++)
+ dev_dbg(dev,
+ "mtd.eraseregions[%d] = { .offset = 0x%llx, "
+ ".erasesize = 0x%.8x (%uKiB), "
+ ".numblocks = %d }\n",
+ i, (long long)mtd->eraseregions[i].offset,
+ mtd->eraseregions[i].erasesize,
+ mtd->eraseregions[i].erasesize / 1024,
+ mtd->eraseregions[i].numblocks);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(spi_nor_scan);
+
+static const struct spi_device_id *spi_nor_match_id(const char *name)
+{
+ const struct spi_device_id *id = spi_nor_ids;
+
+ while (id->name[0]) {
+ if (!strcmp(name, id->name))
+ return id;
+ id++;
+ }
+ return NULL;
+}
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index b02880eb79..797022636d 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -155,8 +155,8 @@ static int uif_init(struct ubi_device *ubi, int *ref)
*ref = 0;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
- sprintf(ubi->dev.name, "ubi");
- ubi->dev.id = DEVICE_ID_DYNAMIC;
+ sprintf(ubi->dev.name, "%s.ubi", ubi->mtd->cdev.name);
+ ubi->dev.id = DEVICE_ID_SINGLE;
ubi->dev.parent = &ubi->mtd->class_dev;
err = register_device(&ubi->dev);
@@ -518,7 +518,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && mtd == ubi->mtd) {
- ubi_err("mtd%d is already attached to ubi%d",
+ ubi_debug("mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
}
@@ -596,9 +596,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
#else
ubi->fm_disabled = 1;
#endif
-
- ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
-
err = io_init(ubi, max_beb_per1024);
if (err)
goto out_free;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 90d5b2dd66..fe71a8d609 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -176,7 +176,7 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
priv->ubi = ubi;
cdev->ops = &ubi_volume_fops;
- cdev->name = asprintf("ubi%d.%s", ubi->ubi_num, vol->name);
+ cdev->name = asprintf("%s.%s", ubi->cdev.name, vol->name);
cdev->priv = priv;
cdev->size = vol->used_bytes;
cdev->dev = &vol->dev;
@@ -239,7 +239,7 @@ int ubi_cdev_add(struct ubi_device *ubi)
int ret;
cdev->ops = &ubi_fops;
- cdev->name = asprintf("ubi%d", ubi->ubi_num);
+ cdev->name = asprintf("%s.ubi", ubi->mtd->cdev.name);
cdev->priv = ubi;
cdev->size = 0;
diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
index 385a7150ba..a1863655fa 100644
--- a/drivers/net/altera_tse.c
+++ b/drivers/net/altera_tse.c
@@ -231,7 +231,7 @@ static int tse_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int tse_set_ethaddr(struct eth_device *edev, unsigned char *m)
+static int tse_set_ethaddr(struct eth_device *edev, const unsigned char *m)
{
struct altera_tse_priv *priv = edev->priv;
struct alt_tse_mac *mac_dev = priv->tse_regs;
diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c
index 48e4b30fd6..7447c4484d 100644
--- a/drivers/net/ar231x.c
+++ b/drivers/net/ar231x.c
@@ -70,7 +70,7 @@ static void ar231x_reset_bit_(struct ar231x_eth_priv *priv,
(*priv->reset_bit)(val, state);
}
-static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr);
+static int ar231x_set_ethaddr(struct eth_device *edev, const unsigned char *addr);
static void ar231x_reset_regs(struct eth_device *edev)
{
struct ar231x_eth_priv *priv = edev->priv;
diff --git a/drivers/net/arc_emac.c b/drivers/net/arc_emac.c
index 84e2c75c5e..3dc54cd22b 100644
--- a/drivers/net/arc_emac.c
+++ b/drivers/net/arc_emac.c
@@ -332,7 +332,7 @@ static int arc_emac_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return -1;
}
-static int arc_emac_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int arc_emac_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct arc_emac_priv *priv = edev->priv;
unsigned int addr_low, addr_hi;
diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c
index 5a74837f65..523e35590b 100644
--- a/drivers/net/at91_ether.c
+++ b/drivers/net/at91_ether.c
@@ -261,7 +261,7 @@ static int at91_ether_get_ethaddr(struct eth_device *eth, unsigned char *adr)
return -1;
}
-static int at91_ether_set_ethaddr(struct eth_device *eth, unsigned char *adr)
+static int at91_ether_set_ethaddr(struct eth_device *eth, const unsigned char *adr)
{
int i;
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index c0db96bb53..4d6b7b2e78 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -547,7 +547,7 @@ static int cpsw_get_hwaddr(struct eth_device *edev, unsigned char *mac)
return -1;
}
-static int cpsw_set_hwaddr(struct eth_device *edev, unsigned char *mac)
+static int cpsw_set_hwaddr(struct eth_device *edev, const unsigned char *mac)
{
struct cpsw_slave *slave = edev->priv;
struct cpsw_priv *priv = slave->cpsw;
diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index dccb808f95..a4a5dcaf7f 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -341,7 +341,7 @@ static int cs8900_get_ethaddr(struct eth_device *dev, unsigned char *mac)
return 0;
}
-static int cs8900_set_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int cs8900_set_ethaddr(struct eth_device *dev, const unsigned char *mac)
{
struct cs8900_priv *priv = (struct cs8900_priv *)dev->priv;
int i;
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 056ffe28bc..9f8f0e1fa7 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -178,7 +178,7 @@ static int davinci_emac_get_ethaddr(struct eth_device *edev, unsigned char *adr)
* This function must be called before emac_open() if you want to override
* the default mac address.
*/
-static int davinci_emac_set_ethaddr(struct eth_device *edev, unsigned char *addr)
+static int davinci_emac_set_ethaddr(struct eth_device *edev, const unsigned char *addr)
{
struct davinci_emac_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 213fe41359..800652760a 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -384,7 +384,7 @@ static int dwc_ether_get_ethaddr(struct eth_device *dev, u8 adr[6])
return -1;
}
-static int dwc_ether_set_ethaddr(struct eth_device *dev, u8 adr[6])
+static int dwc_ether_set_ethaddr(struct eth_device *dev, const unsigned char *adr)
{
struct dw_eth_dev *priv = dev->priv;
struct eth_mac_regs *mac_p = priv->mac_regs_p;
diff --git a/drivers/net/dm9k.c b/drivers/net/dm9k.c
index abcb7ee65f..1f1938d977 100644
--- a/drivers/net/dm9k.c
+++ b/drivers/net/dm9k.c
@@ -48,6 +48,7 @@
# define NCR_FCOL (1 << 4)
# define NCR_FDX (1 << 3)
# define NCR_LBK (3 << 1)
+# define NCR_MAC_LBK (1 << 1)
# define NCR_RST (1 << 0)
#define DM9K_NSR 0x01
@@ -359,6 +360,11 @@ static int dm9k_phy_read(struct mii_bus *bus, int addr, int reg)
struct dm9k *priv = bus->priv;
struct device_d *dev = &bus->dev;
+ /* only internal phy supported by now, so show only one phy on miibus */
+ if (addr != 0) {
+ return 0xffff;
+ }
+
/* 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 */
@@ -378,6 +384,11 @@ static int dm9k_phy_write(struct mii_bus *bus, int addr, int reg, u16 val)
struct dm9k *priv = bus->priv;
struct device_d *dev = &bus->dev;
+ /* only internal phy supported by now, so show only one phy on miibus */
+ if (addr != 0) {
+ return 0;
+ }
+
/* Fill the phyxcer register into REG_0C */
dm9k_iow(priv, DM9K_EPAR, DM9K_PHY | reg);
@@ -462,8 +473,28 @@ static void dm9k_reset(struct dm9k *priv)
struct device_d *dev = priv->miibus.parent;
dev_dbg(dev, "%s\n", __func__);
- dm9k_iow(priv, DM9K_NCR, NCR_RST);
- udelay(1000); /* delay 1ms */
+
+ /* Reset DM9000, see DM9000 Application Notes V1.22 Jun 11, 2004 page 29
+ * The essential point is that we have to do a double reset, and the
+ * instruction is to set LBK into MAC internal loopback mode.
+ */
+
+ /* Make all GPIO pins outputs */
+ dm9k_iow(priv, DM9K_GPCR, 0x0F);
+ /* Power internal PHY by writing 0 to GPIO0 pin */
+ dm9k_iow(priv, DM9K_GPR, 0);
+
+ dm9k_iow(priv, DM9K_NCR, NCR_RST | NCR_MAC_LBK);
+ udelay(100); /* Application note says at least 20 us */
+ if (dm9k_ior(priv, DM9K_NCR) & NCR_RST)
+ dev_err(dev, "dm9000 did not respond to first reset\n");
+
+ dm9k_iow(priv, DM9K_NCR, 0);
+ dm9k_iow(priv, DM9K_NCR, NCR_RST | NCR_MAC_LBK);
+ udelay(100);
+
+ if (dm9k_ior(priv, DM9K_NCR) & NCR_RST)
+ dev_err(dev, "dm9000 did not respond to second reset\n");
}
static int dm9k_eth_open(struct eth_device *edev)
@@ -680,7 +711,7 @@ static int dm9k_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int dm9k_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int dm9k_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct dm9k *priv = (struct dm9k *)edev->priv;
int i, oft;
@@ -698,17 +729,66 @@ static int dm9k_init_dev(struct eth_device *edev)
return 0;
}
+static int dm9000_setup_buswidth(struct device_d *dev, struct dm9k *priv, uint32_t width)
+{
+ switch (width) {
+ case 1:
+ priv->buswidth = IORESOURCE_MEM_8BIT;
+ break;
+ case 2:
+ priv->buswidth = IORESOURCE_MEM_16BIT;
+ break;
+ case 4:
+ priv->buswidth = IORESOURCE_MEM_32BIT;
+ break;
+ default:
+ dev_err(dev, "Wrong io resource size\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int dm9000_parse_dt(struct device_d *dev, struct dm9k *priv)
+{
+ struct device_node *np = dev->device_node;
+ uint32_t prop;
+
+ if (!IS_ENABLED(CONFIG_OFDEVICE) || !np)
+ return -ENODEV;
+
+ if (of_find_property(np, "davicom,no-eeprom", NULL)) {
+ priv->srom = 0;
+ } else {
+ priv->srom = 1;
+ }
+
+ if (of_property_read_u32(np, "reg-io-width", &prop)) {
+ /* Use 8-bit registers by default */
+ prop = 1;
+ }
+
+ return dm9000_setup_buswidth(dev, priv, prop);
+}
+
+static int dm9000_parse_pdata(struct device_d *dev, struct dm9k *priv)
+{
+ struct dm9000_platform_data *pdata = dev->platform_data;
+ uint32_t width;
+
+ priv->srom = pdata->srom;
+
+ width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
+
+ return dm9000_setup_buswidth(dev, priv, width);
+}
+
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;
- }
+ int ret;
if (dev->num_resources < 2) {
dev_err(dev, "Need 2 resources base and data");
@@ -717,19 +797,28 @@ static int dm9k_probe(struct device_d *dev)
edev = xzalloc(sizeof(struct eth_device) + sizeof(struct dm9k));
edev->priv = (struct dm9k *)(edev + 1);
+ priv = edev->priv;
- pdata = dev->platform_data;
+ if (dev->platform_data) {
+ ret = dm9000_parse_pdata(dev, priv);
+ } else {
+ ret = dm9000_parse_dt(dev, priv);
+ }
- priv = edev->priv;
+ if (ret)
+ goto err;
- priv->buswidth = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
priv->iodata = dev_request_mem_region(dev, 1);
- if (!priv->iodata)
- return -EBUSY;
+ if (!priv->iodata) {
+ ret = -EBUSY;
+ goto err;
+ }
+
priv->iobase = dev_request_mem_region(dev, 0);
- if (!priv->iobase)
- return -EBUSY;
- priv->srom = pdata->srom;
+ if (!priv->iobase) {
+ ret = -EBUSY;
+ goto err;
+ }
edev->init = dm9k_init_dev;
edev->open = dm9k_eth_open;
@@ -747,8 +836,10 @@ static int dm9k_probe(struct device_d *dev)
/* RESET device */
dm9k_reset(priv);
- if(dm9k_check_id(priv))
- return -ENODEV;
+ if (dm9k_check_id(priv)) {
+ ret = -ENODEV;
+ goto err;
+ }
io_mode = dm9k_ior(priv, DM9K_ISR) >> 6;
switch (io_mode) {
@@ -780,10 +871,21 @@ static int dm9k_probe(struct device_d *dev)
eth_register(edev);
return 0;
+
+err:
+ free(edev);
+
+ return ret;
}
+static struct of_device_id dm9000_of_matches[] = {
+ { .compatible = "davicom,dm9000", },
+ { /* sentinel */ }
+};
+
static struct driver_d dm9k_driver = {
.name = "dm9000",
.probe = dm9k_probe,
+ .of_compatible = DRV_OF_COMPAT(dm9000_of_matches),
};
device_platform_driver(dm9k_driver);
diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c
index 4b73abff37..90c12fce75 100644
--- a/drivers/net/ep93xx.c
+++ b/drivers/net/ep93xx.c
@@ -466,7 +466,7 @@ static int ep93xx_eth_get_ethaddr(struct eth_device *edev,
}
static int ep93xx_eth_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct mac_regs *regs = ep93xx_get_regs(edev);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 7c52a09eaa..6bae7d68a6 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -435,7 +435,7 @@ static int ethoc_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return 0;
}
-static int ethoc_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int ethoc_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct ethoc *dev = edev->priv;
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 9a10c9f2e4..78ccb85376 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -249,7 +249,7 @@ static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
return -1;
}
-static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+static int fec_set_hwaddr(struct eth_device *dev, const unsigned char *mac)
{
struct fec_priv *fec = (struct fec_priv *)dev->priv;
diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c
index f431d79d1d..14ef872927 100644
--- a/drivers/net/fec_mpc5200.c
+++ b/drivers/net/fec_mpc5200.c
@@ -211,7 +211,7 @@ static int mpc5xxx_fec_get_ethaddr(struct eth_device *dev, unsigned char *mac)
return -1;
}
-static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, const unsigned char *mac)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
uint8_t currByte; /* byte for which to compute the CRC */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 5e47c64e0f..ac698332cf 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -233,7 +233,7 @@ static int gfar_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return -ENODEV;
}
-static int gfar_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int gfar_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct gfar_private *priv = edev->priv;
void __iomem *regs = priv->regs;
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index a8974cfcb9..854a666bfc 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -571,7 +571,7 @@ static int ks8851_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int ks8851_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int ks8851_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct ks_net *priv = (struct ks_net *)edev->priv;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 2ac00f3460..6d4973fa2f 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -493,7 +493,7 @@ static int macb_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int macb_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int macb_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct macb_device *macb = edev->priv;
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 3be2ec531f..aab52c45de 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -486,7 +486,7 @@ recv_err:
return ret;
}
-static int mvneta_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int mvneta_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct mvneta_port *priv = edev->priv;
u32 mac_h = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c
index 96dbc7c5df..64e9886d61 100644
--- a/drivers/net/netx_eth.c
+++ b/drivers/net/netx_eth.c
@@ -210,7 +210,7 @@ static int netx_eth_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int netx_eth_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int netx_eth_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv;
int xcno = priv->xcno;
diff --git a/drivers/net/orion-gbe.c b/drivers/net/orion-gbe.c
index 97ffff2b26..e6bd757689 100644
--- a/drivers/net/orion-gbe.c
+++ b/drivers/net/orion-gbe.c
@@ -322,7 +322,7 @@ recv_err:
return ret;
}
-static int port_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int port_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct port_priv *port = edev->priv;
u32 mac_h = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index d57c706e52..a9eb865358 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -352,7 +352,7 @@ static int rtl8139_get_ethaddr(struct eth_device *edev, unsigned char *m)
}
static int rtl8139_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct rtl8139_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index d6a761087c..47d5e4a893 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -456,7 +456,7 @@ static int rtl8169_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int rtl8169_set_ethaddr(struct eth_device *edev, unsigned char *mac_addr)
+static int rtl8169_set_ethaddr(struct eth_device *edev, const unsigned char *mac_addr)
{
struct rtl8169_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index c0cf42ad82..5ea1bc3259 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -1378,7 +1378,7 @@ static int smc91c111_get_ethaddr(struct eth_device *edev, unsigned char *m)
}
static int smc91c111_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct smc91c111_priv *priv = (struct smc91c111_priv *)edev->priv;
unsigned address;
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 9977ae3f32..60cf36ea4a 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -182,7 +182,7 @@ static int smc911x_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int smc911x_set_ethaddr(struct eth_device *edev, unsigned char *m)
+static int smc911x_set_ethaddr(struct eth_device *edev, const unsigned char *m)
{
unsigned long addrh, addrl;
@@ -630,8 +630,14 @@ static int smc911x_probe(struct device_d *dev)
return 0;
}
+static const struct of_device_id smsc911x_dt_ids[] = {
+ { .compatible = "smsc,lan9115", },
+ { /* sentinel */ }
+};
+
static struct driver_d smc911x_driver = {
.name = "smc911x",
.probe = smc911x_probe,
+ .of_compatible = DRV_OF_COMPAT(smsc911x_dt_ids),
};
device_platform_driver(smc911x_driver);
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 2458fb52c7..ca53f12d92 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -65,7 +65,7 @@ static int tap_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int tap_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int tap_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
return 0;
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 7cce5b929e..4c53a142f1 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -403,7 +403,7 @@ static int asix_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int asix_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int asix_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
/* not possible? */
return 0;
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 053da1822a..6360e480fe 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -363,7 +363,7 @@ static int smsc95xx_set_csums(struct usbnet *dev)
return 0;
}
-static int smsc95xx_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int smsc95xx_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct usbnet *udev = container_of(edev, struct usbnet, edev);
diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c
index 3b2273fd79..7cc4d4888f 100644
--- a/drivers/net/xgmac.c
+++ b/drivers/net/xgmac.c
@@ -674,7 +674,7 @@ static int xgmac_get_ethaddr(struct eth_device *edev, unsigned char *addr)
return 0;
}
-static int xgmac_set_ethaddr(struct eth_device *dev, unsigned char *addr)
+static int xgmac_set_ethaddr(struct eth_device *dev, const unsigned char *addr)
{
struct xgmac_priv *priv = dev->priv;
u32 data;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index dfa95c38c8..88f0523260 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -48,7 +48,6 @@ static inline char *dt_string(struct fdt_header *f, char *strstart, uint32_t ofs
/**
* of_unflatten_dtb - unflatten a dtb binary blob
- * @root - node in which the fdt blob should be merged into or NULL
* @infdt - the fdt blob to unflatten
*
* Parse a flat device tree binary blob and return a pointer to the
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index ab3ccab3b6..2c075dbae3 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -118,7 +118,7 @@ static void of_device_make_bus_id(struct device_d *dev)
* Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
-static struct device_d *of_platform_device_create(struct device_node *np,
+struct device_d *of_platform_device_create(struct device_node *np,
struct device_d *parent)
{
struct device_d *dev;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3a0e7a5f4e..191561da03 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -129,10 +129,24 @@ static struct pci_dev *alloc_pci_dev(void)
return dev;
}
+static u32 pci_size(u32 base, u32 maxbase, u32 mask)
+{
+ u32 size = maxbase & mask;
+ if (!size)
+ return 0;
+
+ size = (size & ~(size-1)) - 1;
+
+ if (base == maxbase && ((base | size) & mask) != mask)
+ return 0;
+
+ return size + 1;
+}
+
+
static void setup_device(struct pci_dev *dev, int max_bar)
{
- int bar, size;
- u32 mask;
+ int bar;
u8 cmd;
pci_read_config_byte(dev, PCI_COMMAND, &cmd);
@@ -141,9 +155,12 @@ static void setup_device(struct pci_dev *dev, int max_bar)
for (bar = 0; bar < max_bar; bar++) {
resource_size_t last_addr;
+ u32 orig, mask, size;
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &orig);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, orig);
if (mask == 0 || mask == 0xffffffff) {
pr_debug("pbar%d set bad mask\n", bar);
@@ -151,7 +168,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
}
if (mask & 0x01) { /* IO */
- size = ((~(mask & 0xfffffffe)) & 0xffff) + 1;
+ size = pci_size(orig, mask, 0xfffffffe);
+ if (!size) {
+ pr_debug("pbar%d bad IO mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
if (last_io + size >
dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
@@ -164,7 +185,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
last_io += size;
} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
last_mem_pref) /* prefetchable MEM */ {
- size = (~(mask & 0xfffffff0)) + 1;
+ size = pci_size(orig, mask, 0xfffffff0);
+ if (!size) {
+ pr_debug("pbar%d bad P-MEM mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x P memory %d bytes\n",
bar, mask, size);
if (last_mem_pref + size >
@@ -178,7 +203,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
last_addr = last_mem_pref;
last_mem_pref += size;
} else { /* non-prefetch MEM */
- size = (~(mask & 0xfffffff0)) + 1;
+ size = pci_size(orig, mask, 0xfffffff0);
+ if (!size) {
+ pr_debug("pbar%d bad NP-MEM mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x NP memory %d bytes\n",
bar, mask, size);
if (last_mem + size >
@@ -391,11 +420,6 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
continue;
}
-
- if (class == PCI_CLASS_BRIDGE_HOST) {
- pr_debug("skip pci host bridge\n");
- continue;
- }
}
/*
diff --git a/drivers/serial/serial_ar933x.c b/drivers/serial/serial_ar933x.c
index 51184aaae5..59bb5b2ecf 100644
--- a/drivers/serial/serial_ar933x.c
+++ b/drivers/serial/serial_ar933x.c
@@ -40,7 +40,7 @@ static inline void ar933x_serial_writel(struct console_device *cdev,
{
struct ar933x_uart_priv *priv = cdev->dev->priv;
- cpu_writel(b, priv->base + offset);
+ __raw_writel(b, priv->base + offset);
}
static inline u32 ar933x_serial_readl(struct console_device *cdev,
@@ -48,7 +48,7 @@ static inline u32 ar933x_serial_readl(struct console_device *cdev,
{
struct ar933x_uart_priv *priv = cdev->dev->priv;
- return cpu_readl(priv->base + offset);
+ return __raw_readl(priv->base + offset);
}
/*
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index f075c50fc2..68b438b0bb 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -23,113 +23,7 @@
#include <of.h>
#include <linux/err.h>
#include <linux/clk.h>
-
-#define URXD0 0x0 /* Receiver Register */
-#define URTX0 0x40 /* Transmitter Register */
-#define UCR1 0x80 /* Control Register 1 */
-#define UCR2 0x84 /* Control Register 2 */
-#define UCR3 0x88 /* Control Register 3 */
-#define UCR4 0x8c /* Control Register 4 */
-#define UFCR 0x90 /* FIFO Control Register */
-#define USR1 0x94 /* Status Register 1 */
-#define USR2 0x98 /* Status Register 2 */
-#define UESC 0x9c /* Escape Character Register */
-#define UTIM 0xa0 /* Escape Timer Register */
-#define UBIR 0xa4 /* BRM Incremental Register */
-#define UBMR 0xa8 /* BRM Modulator Register */
-#define UBRC 0xac /* Baud Rate Count Register */
-
-/* UART Control Register Bit Fields.*/
-#define URXD_CHARRDY (1<<15)
-#define URXD_ERR (1<<14)
-#define URXD_OVRRUN (1<<13)
-#define URXD_FRMERR (1<<12)
-#define URXD_BRK (1<<11)
-#define URXD_PRERR (1<<10)
-#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
-#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
-#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
-#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
-#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
-#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
-#define UCR1_IREN (1<<7) /* Infrared interface enable */
-#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
-#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
-#define UCR1_SNDBRK (1<<4) /* Send break */
-#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
-#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
-#define UCR1_DOZE (1<<1) /* Doze */
-#define UCR1_UARTEN (1<<0) /* UART enabled */
-#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
-#define UCR2_IRTS (1<<14) /* Ignore RTS pin */
-#define UCR2_CTSC (1<<13) /* CTS pin control */
-#define UCR2_CTS (1<<12) /* Clear to send */
-#define UCR2_ESCEN (1<<11) /* Escape enable */
-#define UCR2_PREN (1<<8) /* Parity enable */
-#define UCR2_PROE (1<<7) /* Parity odd/even */
-#define UCR2_STPB (1<<6) /* Stop */
-#define UCR2_WS (1<<5) /* Word size */
-#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
-#define UCR2_TXEN (1<<2) /* Transmitter enabled */
-#define UCR2_RXEN (1<<1) /* Receiver enabled */
-#define UCR2_SRST (1<<0) /* SW reset */
-#define UCR3_DTREN (1<<13) /* DTR interrupt enable */
-#define UCR3_PARERREN (1<<12) /* Parity enable */
-#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
-#define UCR3_DSR (1<<10) /* Data set ready */
-#define UCR3_DCD (1<<9) /* Data carrier detect */
-#define UCR3_RI (1<<8) /* Ring indicator */
-#define UCR3_ADNIMP (1<<7) /* Autobaud Detection Not Improved */
-#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
-#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
-#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
-#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz (i.MXL / i.MX1) */
-#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz (i.MXL / i.MX1) */
-#define UCR3_RXDMUXSEL (1<<2) /* RXD Muxed input select (i.MX27) */
-#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
-#define UCR3_BPEN (1<<0) /* Preset registers enable */
-#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
-#define UCR4_INVR (1<<9) /* Inverted infrared reception */
-#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
-#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
-#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
-#define UCR4_IRSC (1<<5) /* IR special case */
-#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
-#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
-#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
-#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
-#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
-#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
-#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
-#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
-#define USR1_RTSS (1<<14) /* RTS pin status */
-#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
-#define USR1_RTSD (1<<12) /* RTS delta */
-#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
-#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
-#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
-#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
-#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
-#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
-#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
-#define USR2_ADET (1<<15) /* Auto baud rate detect complete */
-#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
-#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
-#define USR2_IDLE (1<<12) /* Idle condition */
-#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
-#define USR2_WAKE (1<<7) /* Wake */
-#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
-#define USR2_TXDC (1<<3) /* Transmitter complete */
-#define USR2_BRCD (1<<2) /* Break condition */
-#define USR2_ORE (1<<1) /* Overrun error */
-#define USR2_RDR (1<<0) /* Recv data ready */
-#define UTS_FRCPERR (1<<13) /* Force parity error */
-#define UTS_LOOP (1<<12) /* Loop tx and rx */
-#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
-#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
-#define UTS_TXFULL (1<<4) /* TxFIFO full */
-#define UTS_RXFULL (1<<3) /* RxFIFO full */
-#define UTS_SOFTRST (1<<0) /* Software reset */
+#include <serial/imx-uart.h>
/*
* create default values for different platforms
@@ -219,10 +113,10 @@ static int imx_serial_init_port(struct console_device *cdev)
writel(val, regs + USR2);
/* Clear status flags */
- val = readl(regs + USR2);
+ val = readl(regs + USR1);
val |= USR1_PARITYERR | USR1_RTSD | USR1_ESCF | USR1_FRAMERR | USR1_AIRINT |
USR1_AWAKE;
- writel(val, regs + USR2);
+ writel(val, regs + USR1);
return 0;
}
@@ -284,9 +178,9 @@ static int imx_serial_setbaudrate(struct console_device *cdev, int baudrate)
writel(val, regs + UCR1);
/* Set the numerator value minus one of the BRM ratio */
- writel((baudrate / 100) - 1, regs + UBIR);
+ writel(baudrate_to_ubir(baudrate), regs + UBIR);
/* Set the denominator value minus one of the BRM ratio */
- writel((imx_serial_reffreq(priv) / 1600) - 1, regs + UBMR);
+ writel(refclock_to_ubmr(imx_serial_reffreq(priv)), regs + UBMR);
writel(ucr1, regs + UCR1);
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 4d636c14ca..c186ad4d39 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -291,6 +291,7 @@ static void ns16550_probe_dt(struct device_d *dev, struct ns16550_priv *priv)
if (!IS_ENABLED(CONFIG_OFDEVICE))
return;
+ of_property_read_u32(np, "clock-frequency", &priv->plat.clock);
of_property_read_u32(np, "reg-shift", &priv->plat.shift);
}
@@ -417,7 +418,7 @@ static int ns16550_probe(struct device_d *dev)
else
ns16550_probe_dt(dev, priv);
- if (!plat || !plat->clock) {
+ if (!priv->plat.clock) {
priv->clk = clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
ret = PTR_ERR(priv->clk);
@@ -427,12 +428,6 @@ static int ns16550_probe(struct device_d *dev)
priv->plat.clock = clk_get_rate(priv->clk);
}
- if (priv->plat.clock == 0 && IS_ENABLED(CONFIG_OFDEVICE)) {
- struct device_node *np = dev->device_node;
-
- of_property_read_u32(np, "clock-frequency", &priv->plat.clock);
- }
-
if (priv->plat.clock == 0) {
dev_err(dev, "no valid clockrate\n");
ret = -EINVAL;
diff --git a/drivers/spi/ath79_spi.c b/drivers/spi/ath79_spi.c
index 4d71eba695..bdb39ef0cb 100644
--- a/drivers/spi/ath79_spi.c
+++ b/drivers/spi/ath79_spi.c
@@ -48,12 +48,12 @@ struct ath79_spi {
static inline u32 ath79_spi_rr(struct ath79_spi *sp, int reg)
{
- return cpu_readl(sp->regs + reg);
+ return __raw_readl(sp->regs + reg);
}
static inline void ath79_spi_wr(struct ath79_spi *sp, u32 val, int reg)
{
- cpu_writel(val, sp->regs + reg);
+ __raw_writel(val, sp->regs + reg);
}
static inline void setbits(struct ath79_spi *sp, int bits, int on)
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 5d9158ffae..13a3e7062a 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -25,7 +25,7 @@ config USB_GADGET_DRIVER_AT91
config USB_GADGET_DRIVER_PXA27X
bool
prompt "PXA27x gadget driver"
- depends on ARCH_PXA
+ depends on ARCH_PXA27X
default y
select USB_GADGET_DUALSPEED
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 1e5e8093c0..2b0faf3303 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -536,7 +536,8 @@ int gserial_connect(struct gserial *gser, u8 port_num)
if (status)
goto fail_out;
- dev_set_param(&cdev->class_dev, "active", "ioe");
+ console_set_active(cdev, CONSOLE_STDIN | CONSOLE_STDOUT |
+ CONSOLE_STDERR);
/* REVISIT if waiting on "carrier detect", signal. */
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ccb702980f..84a05c4f96 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -119,8 +119,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
-#define MUSB_HOST_TIMEOUT 0x5fffff
-
/*-------------------------------------------------------------------------*/
#ifndef CONFIG_BLACKFIN
@@ -1025,17 +1023,18 @@ int musb_init(struct usb_host *host)
{
struct musb *musb = to_musb(host);
void *mbase;
- int timeout = MUSB_HOST_TIMEOUT;
+ u64 start;
u8 power;
musb_start(musb);
mbase = musb->mregs;
- do {
+ start = get_time_ns();
+ while (1) {
if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
break;
- } while (--timeout);
- if (!timeout)
- return -ENODEV;
+ if (is_timeout(start, 4 * SECOND))
+ return -ENODEV;
+ }
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
diff --git a/dts/Bindings/arm/omap/l3-noc.txt b/dts/Bindings/arm/omap/l3-noc.txt
index 974624ea68..161448da95 100644
--- a/dts/Bindings/arm/omap/l3-noc.txt
+++ b/dts/Bindings/arm/omap/l3-noc.txt
@@ -6,6 +6,7 @@ provided by Arteris.
Required properties:
- compatible : Should be "ti,omap3-l3-smx" for OMAP3 family
Should be "ti,omap4-l3-noc" for OMAP4 family
+ Should be "ti,omap5-l3-noc" for OMAP5 family
Should be "ti,dra7-l3-noc" for DRA7 family
Should be "ti,am4372-l3-noc" for AM43 family
- reg: Contains L3 register address range for each noc domain.
diff --git a/dts/Bindings/clock/silabs,si5351.txt b/dts/Bindings/clock/silabs,si5351.txt
index c40711e8e8..28b28309f5 100644
--- a/dts/Bindings/clock/silabs,si5351.txt
+++ b/dts/Bindings/clock/silabs,si5351.txt
@@ -17,7 +17,8 @@ Required properties:
- #clock-cells: from common clock binding; shall be set to 1.
- clocks: from common clock binding; list of parent clock
handles, shall be xtal reference clock or xtal and clkin for
- si5351c only.
+ si5351c only. Corresponding clock input names are "xtal" and
+ "clkin" respectively.
- #address-cells: shall be set to 1.
- #size-cells: shall be set to 0.
@@ -71,6 +72,7 @@ i2c-master-node {
/* connect xtal input to 25MHz reference */
clocks = <&ref25>;
+ clock-names = "xtal";
/* connect xtal input as source of pll0 and pll1 */
silabs,pll-source = <0 0>, <1 0>;
diff --git a/dts/Bindings/dma/fsl-mxs-dma.txt b/dts/Bindings/dma/fsl-mxs-dma.txt
index a4873e5e3e..e30e184f50 100644
--- a/dts/Bindings/dma/fsl-mxs-dma.txt
+++ b/dts/Bindings/dma/fsl-mxs-dma.txt
@@ -38,7 +38,7 @@ dma_apbx: dma-apbx@80024000 {
80 81 68 69
70 71 72 73
74 75 76 77>;
- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
"saif0", "saif1", "i2c0", "i2c1",
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
diff --git a/dts/Bindings/input/touchscreen/tsc2005.txt b/dts/Bindings/input/touchscreen/tsc2005.txt
index 4b641c7bf1..09089a6d69 100644
--- a/dts/Bindings/input/touchscreen/tsc2005.txt
+++ b/dts/Bindings/input/touchscreen/tsc2005.txt
@@ -32,8 +32,8 @@ Example:
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
- touchscreen-max-x = <4096>;
- touchscreen-max-y = <4096>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
diff --git a/dts/Bindings/mtd/m25p80.txt b/dts/Bindings/mtd/jedec,spi-nor.txt
index f20b111b50..2bee68103b 100644
--- a/dts/Bindings/mtd/m25p80.txt
+++ b/dts/Bindings/mtd/jedec,spi-nor.txt
@@ -8,8 +8,8 @@ Required properties:
is not Linux-only, but in case of Linux, see the "m25p_ids"
table in drivers/mtd/devices/m25p80.c for the list of supported
chips.
- Must also include "nor-jedec" for any SPI NOR flash that can be
- identified by the JEDEC READ ID opcode (0x9F).
+ Must also include "jedec,spi-nor" for any SPI NOR flash that can
+ be identified by the JEDEC READ ID opcode (0x9F).
- reg : Chip-Select number
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
@@ -25,7 +25,7 @@ Example:
flash: m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "spansion,m25p80", "nor-jedec";
+ compatible = "spansion,m25p80", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
m25p,fast-read;
diff --git a/dts/Bindings/net/cdns-emac.txt b/dts/Bindings/net/cdns-emac.txt
index abd67c13d3..4451ee9732 100644
--- a/dts/Bindings/net/cdns-emac.txt
+++ b/dts/Bindings/net/cdns-emac.txt
@@ -3,7 +3,8 @@
Required properties:
- compatible: Should be "cdns,[<chip>-]{emac}"
Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
- or the generic form: "cdns,emac".
+ Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
+ Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
- interrupts: Should contain macb interrupt
- phy-mode: see ethernet.txt file in the same directory.
diff --git a/dts/Bindings/rtc/abracon,abx80x.txt b/dts/Bindings/rtc/abracon,abx80x.txt
new file mode 100644
index 0000000000..be789685a1
--- /dev/null
+++ b/dts/Bindings/rtc/abracon,abx80x.txt
@@ -0,0 +1,30 @@
+Abracon ABX80X I2C ultra low power RTC/Alarm chip
+
+The Abracon ABX80X family consist of the ab0801, ab0803, ab0804, ab0805, ab1801,
+ab1803, ab1804 and ab1805. The ab0805 is the superset of ab080x and the ab1805
+is the superset of ab180x.
+
+Required properties:
+
+ - "compatible": should one of:
+ "abracon,abx80x"
+ "abracon,ab0801"
+ "abracon,ab0803"
+ "abracon,ab0804"
+ "abracon,ab0805"
+ "abracon,ab1801"
+ "abracon,ab1803"
+ "abracon,ab1804"
+ "abracon,ab1805"
+ Using "abracon,abx80x" will enable chip autodetection.
+ - "reg": I2C bus address of the device
+
+Optional properties:
+
+The abx804 and abx805 have a trickle charger that is able to charge the
+connected battery or supercap. Both the following properties have to be defined
+and valid to enable charging:
+
+ - "abracon,tc-diode": should be "standard" (0.6V) or "schottky" (0.3V)
+ - "abracon,tc-resistor": should be <0>, <3>, <6> or <11>. 0 disables the output
+ resistor, the other values are in ohm.
diff --git a/dts/Bindings/usb/renesas_usbhs.txt b/dts/Bindings/usb/renesas_usbhs.txt
index dc2a18f0b3..ddbe304beb 100644
--- a/dts/Bindings/usb/renesas_usbhs.txt
+++ b/dts/Bindings/usb/renesas_usbhs.txt
@@ -15,10 +15,8 @@ Optional properties:
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
- dmas: Must contain a list of references to DMA specifiers.
- - dma-names : Must contain a list of DMA names:
- - tx0 ... tx<n>
- - rx0 ... rx<n>
- - This <n> means DnFIFO in USBHS module.
+ - dma-names : named "ch%d", where %d is the channel number ranging from zero
+ to the number of channels (DnFIFOs) minus one.
Example:
usbhs: usb@e6590000 {
diff --git a/dts/src/arm/am335x-bone-common.dtsi b/dts/src/arm/am335x-bone-common.dtsi
index c3255e0c90..dbb3f4d2bf 100644
--- a/dts/src/arm/am335x-bone-common.dtsi
+++ b/dts/src/arm/am335x-bone-common.dtsi
@@ -223,6 +223,25 @@
/include/ "tps65217.dtsi"
&tps {
+ /*
+ * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
+ * mode") at poweroff. Most BeagleBone versions do not support RTC-only
+ * mode and risk hardware damage if this mode is entered.
+ *
+ * For details, see linux-omap mailing list May 2015 thread
+ * [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
+ * In particular, messages:
+ * http://www.spinics.net/lists/linux-omap/msg118585.html
+ * http://www.spinics.net/lists/linux-omap/msg118615.html
+ *
+ * You can override this later with
+ * &tps { /delete-property/ ti,pmic-shutdown-controller; }
+ * if you want to use RTC-only mode and made sure you are not affected
+ * by the hardware problems. (Tip: double-check by performing a current
+ * measurement after shutdown: it should be less than 1 mA.)
+ */
+ ti,pmic-shutdown-controller;
+
regulators {
dcdc1_reg: regulator@0 {
regulator-name = "vdds_dpr";
diff --git a/dts/src/arm/am335x-boneblack.dts b/dts/src/arm/am335x-boneblack.dts
index 5c42d259fa..901739fcb8 100644
--- a/dts/src/arm/am335x-boneblack.dts
+++ b/dts/src/arm/am335x-boneblack.dts
@@ -80,7 +80,3 @@
status = "okay";
};
};
-
-&rtc {
- system-power-controller;
-};
diff --git a/dts/src/arm/am335x-evmsk.dts b/dts/src/arm/am335x-evmsk.dts
index 87fc7a35e8..156d05efcb 100644
--- a/dts/src/arm/am335x-evmsk.dts
+++ b/dts/src/arm/am335x-evmsk.dts
@@ -654,7 +654,7 @@
wlcore: wlcore@2 {
compatible = "ti,wl1271";
reg = <2>;
- interrupt-parent = <&gpio1>;
+ interrupt-parent = <&gpio0>;
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
ref-clock-frequency = <38400000>;
};
diff --git a/dts/src/arm/am35xx-clocks.dtsi b/dts/src/arm/am35xx-clocks.dtsi
index 518b8fde88..18cc826e9d 100644
--- a/dts/src/arm/am35xx-clocks.dtsi
+++ b/dts/src/arm/am35xx-clocks.dtsi
@@ -12,7 +12,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <1>;
};
@@ -20,7 +20,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&rmii_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <9>;
};
@@ -28,7 +28,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <2>;
};
@@ -36,7 +36,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&pclk_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <10>;
};
@@ -44,7 +44,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <0>;
};
@@ -52,7 +52,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&sys_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <8>;
};
@@ -60,7 +60,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&sys_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <3>;
};
};
diff --git a/dts/src/arm/am437x-sk-evm.dts b/dts/src/arm/am437x-sk-evm.dts
index 8ae29c955c..c17097d2c1 100644
--- a/dts/src/arm/am437x-sk-evm.dts
+++ b/dts/src/arm/am437x-sk-evm.dts
@@ -49,7 +49,7 @@
pinctrl-0 = <&matrix_keypad_pins>;
debounce-delay-ms = <5>;
- col-scan-delay-us = <1500>;
+ col-scan-delay-us = <5>;
row-gpios = <&gpio5 5 GPIO_ACTIVE_HIGH /* Bank5, pin5 */
&gpio5 6 GPIO_ACTIVE_HIGH>; /* Bank5, pin6 */
@@ -473,7 +473,7 @@
interrupt-parent = <&gpio0>;
interrupts = <31 0>;
- wake-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
touchscreen-size-x = <480>;
touchscreen-size-y = <272>;
diff --git a/dts/src/arm/am57xx-beagle-x15.dts b/dts/src/arm/am57xx-beagle-x15.dts
index 15f198e486..7128fad991 100644
--- a/dts/src/arm/am57xx-beagle-x15.dts
+++ b/dts/src/arm/am57xx-beagle-x15.dts
@@ -18,6 +18,7 @@
aliases {
rtc0 = &mcp_rtc;
rtc1 = &tps659038_rtc;
+ rtc2 = &rtc;
};
memory {
@@ -83,7 +84,7 @@
gpio_fan: gpio_fan {
/* Based on 5v 500mA AFB02505HHB */
compatible = "gpio-fan";
- gpios = <&tps659038_gpio 1 GPIO_ACTIVE_HIGH>;
+ gpios = <&tps659038_gpio 2 GPIO_ACTIVE_HIGH>;
gpio-fan,speed-map = <0 0>,
<13000 1>;
#cooling-cells = <2>;
@@ -130,8 +131,8 @@
uart3_pins_default: uart3_pins_default {
pinctrl-single,pins = <
- 0x248 (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_rxd.rxd */
- 0x24c (PIN_INPUT_SLEW | MUX_MODE0) /* uart3_txd.txd */
+ 0x3f8 (PIN_INPUT_SLEW | MUX_MODE2) /* uart2_ctsn.uart3_rxd */
+ 0x3fc (PIN_INPUT_SLEW | MUX_MODE1) /* uart2_rtsn.uart3_txd */
>;
};
@@ -455,7 +456,7 @@
mcp_rtc: rtc@6f {
compatible = "microchip,mcp7941x";
reg = <0x6f>;
- interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_LOW>; /* IRQ_SYS_1N */
+ interrupts = <GIC_SPI 2 IRQ_TYPE_EDGE_RISING>; /* IRQ_SYS_1N */
pinctrl-names = "default";
pinctrl-0 = <&mcp79410_pins_default>;
@@ -478,7 +479,7 @@
&uart3 {
status = "okay";
interrupts-extended = <&crossbar_mpu GIC_SPI 69 IRQ_TYPE_LEVEL_HIGH>,
- <&dra7_pmx_core 0x248>;
+ <&dra7_pmx_core 0x3f8>;
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins_default>;
diff --git a/dts/src/arm/armada-375.dtsi b/dts/src/arm/armada-375.dtsi
index c675257f23..f076ff856d 100644
--- a/dts/src/arm/armada-375.dtsi
+++ b/dts/src/arm/armada-375.dtsi
@@ -69,7 +69,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
refclk: oscillator {
diff --git a/dts/src/arm/armada-38x.dtsi b/dts/src/arm/armada-38x.dtsi
index ed2dd8ba40..218a2acd36 100644
--- a/dts/src/arm/armada-38x.dtsi
+++ b/dts/src/arm/armada-38x.dtsi
@@ -585,7 +585,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
diff --git a/dts/src/arm/armada-39x.dtsi b/dts/src/arm/armada-39x.dtsi
index 0e85fc15ce..ecd1318109 100644
--- a/dts/src/arm/armada-39x.dtsi
+++ b/dts/src/arm/armada-39x.dtsi
@@ -502,7 +502,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
};
};
diff --git a/dts/src/arm/armada-xp-linksys-mamba.dts b/dts/src/arm/armada-xp-linksys-mamba.dts
index a2cf2154dc..fdd187c55a 100644
--- a/dts/src/arm/armada-xp-linksys-mamba.dts
+++ b/dts/src/arm/armada-xp-linksys-mamba.dts
@@ -95,6 +95,11 @@
internal-regs {
+ rtc@10300 {
+ /* No crystal connected to the internal RTC */
+ status = "disabled";
+ };
+
/* J10: VCC, NC, RX, NC, TX, GND */
serial@12000 {
status = "okay";
diff --git a/dts/src/arm/armada-xp-openblocks-ax3-4.dts b/dts/src/arm/armada-xp-openblocks-ax3-4.dts
index e3b08fb959..990e8a2100 100644
--- a/dts/src/arm/armada-xp-openblocks-ax3-4.dts
+++ b/dts/src/arm/armada-xp-openblocks-ax3-4.dts
@@ -105,6 +105,10 @@
};
internal-regs {
+ rtc@10300 {
+ /* No crystal connected to the internal RTC */
+ status = "disabled";
+ };
serial@12000 {
status = "okay";
};
diff --git a/dts/src/arm/dm816x.dtsi b/dts/src/arm/dm816x.dtsi
index de8427be83..289806adb3 100644
--- a/dts/src/arm/dm816x.dtsi
+++ b/dts/src/arm/dm816x.dtsi
@@ -382,7 +382,7 @@
ti,hwmods = "usb_otg_hs";
usb0: usb@47401000 {
- compatible = "ti,musb-am33xx";
+ compatible = "ti,musb-dm816";
reg = <0x47401400 0x400
0x47401000 0x200>;
reg-names = "mc", "control";
@@ -422,7 +422,7 @@
};
usb1: usb@47401800 {
- compatible = "ti,musb-am33xx";
+ compatible = "ti,musb-dm816";
reg = <0x47401c00 0x400
0x47401800 0x200>;
reg-names = "mc", "control";
diff --git a/dts/src/arm/dove-cubox.dts b/dts/src/arm/dove-cubox.dts
index aae7efc09b..e6fa251e17 100644
--- a/dts/src/arm/dove-cubox.dts
+++ b/dts/src/arm/dove-cubox.dts
@@ -87,6 +87,7 @@
/* connect xtal input to 25MHz reference */
clocks = <&ref25>;
+ clock-names = "xtal";
/* connect xtal input as source of pll0 and pll1 */
silabs,pll-source = <0 0>, <1 0>;
diff --git a/dts/src/arm/dra7.dtsi b/dts/src/arm/dra7.dtsi
index 5332b57b49..f03a091cd0 100644
--- a/dts/src/arm/dra7.dtsi
+++ b/dts/src/arm/dra7.dtsi
@@ -911,7 +911,7 @@
ti,clock-cycles = <16>;
reg = <0x4ae07ddc 0x4>, <0x4ae07de0 0x4>,
- <0x4ae06014 0x4>, <0x4a003b20 0x8>,
+ <0x4ae06014 0x4>, <0x4a003b20 0xc>,
<0x4ae0c158 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
@@ -944,7 +944,7 @@
ti,clock-cycles = <16>;
reg = <0x4ae07e34 0x4>, <0x4ae07e24 0x4>,
- <0x4ae06010 0x4>, <0x4a0025cc 0x8>,
+ <0x4ae06010 0x4>, <0x4a0025cc 0xc>,
<0x4a002470 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
@@ -977,7 +977,7 @@
ti,clock-cycles = <16>;
reg = <0x4ae07e30 0x4>, <0x4ae07e20 0x4>,
- <0x4ae06010 0x4>, <0x4a0025e0 0x8>,
+ <0x4ae06010 0x4>, <0x4a0025e0 0xc>,
<0x4a00246c 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
@@ -1010,7 +1010,7 @@
ti,clock-cycles = <16>;
reg = <0x4ae07de4 0x4>, <0x4ae07de8 0x4>,
- <0x4ae06010 0x4>, <0x4a003b08 0x8>,
+ <0x4ae06010 0x4>, <0x4a003b08 0xc>,
<0x4ae0c154 0x4>;
reg-names = "setup-address", "control-address",
"int-address", "efuse-address",
@@ -1203,7 +1203,7 @@
status = "disabled";
};
- rtc@48838000 {
+ rtc: rtc@48838000 {
compatible = "ti,am3352-rtc";
reg = <0x48838000 0x100>;
interrupts = <GIC_SPI 217 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/dts/src/arm/exynos4412-odroid-common.dtsi b/dts/src/arm/exynos4412-odroid-common.dtsi
index 8de12af7c2..d6b49e5b32 100644
--- a/dts/src/arm/exynos4412-odroid-common.dtsi
+++ b/dts/src/arm/exynos4412-odroid-common.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/sound/samsung-i2s.h>
#include <dt-bindings/input/input.h>
+#include <dt-bindings/clock/maxim,max77686.h>
#include "exynos4412.dtsi"
/ {
@@ -105,6 +106,8 @@
rtc@10070000 {
status = "okay";
+ clocks = <&clock CLK_RTC>, <&max77686 MAX77686_CLK_AP>;
+ clock-names = "rtc", "rtc_src";
};
g2d@10800000 {
diff --git a/dts/src/arm/exynos4412-trats2.dts b/dts/src/arm/exynos4412-trats2.dts
index 173ffa479a..792394dd0f 100644
--- a/dts/src/arm/exynos4412-trats2.dts
+++ b/dts/src/arm/exynos4412-trats2.dts
@@ -736,7 +736,7 @@
display-timings {
timing-0 {
- clock-frequency = <0>;
+ clock-frequency = <57153600>;
hactive = <720>;
vactive = <1280>;
hfront-porch = <5>;
diff --git a/dts/src/arm/exynos5250-snow.dts b/dts/src/arm/exynos5250-snow.dts
index 2657e842e5..1eca97ee4b 100644
--- a/dts/src/arm/exynos5250-snow.dts
+++ b/dts/src/arm/exynos5250-snow.dts
@@ -567,6 +567,7 @@
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
samsung,dw-mshc-ciu-div = <3>;
samsung,dw-mshc-sdr-timing = <2 3>;
diff --git a/dts/src/arm/exynos5420-peach-pit.dts b/dts/src/arm/exynos5420-peach-pit.dts
index 0788d08fb4..146e71118a 100644
--- a/dts/src/arm/exynos5420-peach-pit.dts
+++ b/dts/src/arm/exynos5420-peach-pit.dts
@@ -711,6 +711,7 @@
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
diff --git a/dts/src/arm/exynos5420-trip-points.dtsi b/dts/src/arm/exynos5420-trip-points.dtsi
index 5d31fc1408..2180a0152c 100644
--- a/dts/src/arm/exynos5420-trip-points.dtsi
+++ b/dts/src/arm/exynos5420-trip-points.dtsi
@@ -28,7 +28,7 @@ trips {
type = "active";
};
cpu-crit-0 {
- temperature = <1200000>; /* millicelsius */
+ temperature = <120000>; /* millicelsius */
hysteresis = <0>; /* millicelsius */
type = "critical";
};
diff --git a/dts/src/arm/exynos5420.dtsi b/dts/src/arm/exynos5420.dtsi
index f67b23f303..45317538bb 100644
--- a/dts/src/arm/exynos5420.dtsi
+++ b/dts/src/arm/exynos5420.dtsi
@@ -536,6 +536,7 @@
clock-names = "dp";
phys = <&dp_phy>;
phy-names = "dp";
+ power-domains = <&disp_pd>;
};
mipi_phy: video-phy@10040714 {
diff --git a/dts/src/arm/exynos5440-trip-points.dtsi b/dts/src/arm/exynos5440-trip-points.dtsi
index 48adfa8f43..356e963edf 100644
--- a/dts/src/arm/exynos5440-trip-points.dtsi
+++ b/dts/src/arm/exynos5440-trip-points.dtsi
@@ -18,7 +18,7 @@ trips {
type = "active";
};
cpu-crit-0 {
- temperature = <1050000>; /* millicelsius */
+ temperature = <105000>; /* millicelsius */
hysteresis = <0>; /* millicelsius */
type = "critical";
};
diff --git a/dts/src/arm/exynos5800-peach-pi.dts b/dts/src/arm/exynos5800-peach-pi.dts
index 412f41d626..02eb8b1537 100644
--- a/dts/src/arm/exynos5800-peach-pi.dts
+++ b/dts/src/arm/exynos5800-peach-pi.dts
@@ -674,6 +674,7 @@
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
diff --git a/dts/src/arm/imx23-olinuxino.dts b/dts/src/arm/imx23-olinuxino.dts
index 7e6eef2488..82045398bf 100644
--- a/dts/src/arm/imx23-olinuxino.dts
+++ b/dts/src/arm/imx23-olinuxino.dts
@@ -12,6 +12,7 @@
*/
/dts-v1/;
+#include <dt-bindings/gpio/gpio.h>
#include "imx23.dtsi"
/ {
@@ -93,6 +94,7 @@
ahb@80080000 {
usb0: usb@80080000 {
+ dr_mode = "host";
vbus-supply = <&reg_usb0_vbus>;
status = "okay";
};
@@ -122,7 +124,7 @@
user {
label = "green";
- gpios = <&gpio2 1 1>;
+ gpios = <&gpio2 1 GPIO_ACTIVE_HIGH>;
};
};
};
diff --git a/dts/src/arm/imx25.dtsi b/dts/src/arm/imx25.dtsi
index e4d3aecc4e..677f81d9dc 100644
--- a/dts/src/arm/imx25.dtsi
+++ b/dts/src/arm/imx25.dtsi
@@ -428,6 +428,7 @@
pwm4: pwm@53fc8000 {
compatible = "fsl,imx25-pwm", "fsl,imx27-pwm";
+ #pwm-cells = <2>;
reg = <0x53fc8000 0x4000>;
clocks = <&clks 108>, <&clks 52>;
clock-names = "ipg", "per";
diff --git a/dts/src/arm/imx27.dtsi b/dts/src/arm/imx27.dtsi
index 6951b66d1a..bc215e4b75 100644
--- a/dts/src/arm/imx27.dtsi
+++ b/dts/src/arm/imx27.dtsi
@@ -533,7 +533,7 @@
fec: ethernet@1002b000 {
compatible = "fsl,imx27-fec";
- reg = <0x1002b000 0x4000>;
+ reg = <0x1002b000 0x1000>;
interrupts = <50>;
clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
<&clks IMX27_CLK_FEC_AHB_GATE>;
diff --git a/dts/src/arm/imx28.dtsi b/dts/src/arm/imx28.dtsi
index 25e25f82fb..4e073e8547 100644
--- a/dts/src/arm/imx28.dtsi
+++ b/dts/src/arm/imx28.dtsi
@@ -913,7 +913,7 @@
80 81 68 69
70 71 72 73
74 75 76 77>;
- interrupt-names = "auart4-rx", "aurat4-tx", "spdif-tx", "empty",
+ interrupt-names = "auart4-rx", "auart4-tx", "spdif-tx", "empty",
"saif0", "saif1", "i2c0", "i2c1",
"auart0-rx", "auart0-tx", "auart1-rx", "auart1-tx",
"auart2-rx", "auart2-tx", "auart3-rx", "auart3-tx";
diff --git a/dts/src/arm/imx6qdl-phytec-pfla02.dtsi b/dts/src/arm/imx6qdl-phytec-pfla02.dtsi
index 19cc269a08..1ce6133b67 100644
--- a/dts/src/arm/imx6qdl-phytec-pfla02.dtsi
+++ b/dts/src/arm/imx6qdl-phytec-pfla02.dtsi
@@ -31,6 +31,7 @@
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio4 15 0>;
+ enable-active-high;
};
reg_usb_h1_vbus: regulator@1 {
@@ -40,6 +41,7 @@
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
gpio = <&gpio1 0 0>;
+ enable-active-high;
};
};
diff --git a/dts/src/arm/imx6qdl-sabreauto.dtsi b/dts/src/arm/imx6qdl-sabreauto.dtsi
index 46b2fed7c3..3b24b12651 100644
--- a/dts/src/arm/imx6qdl-sabreauto.dtsi
+++ b/dts/src/arm/imx6qdl-sabreauto.dtsi
@@ -185,7 +185,6 @@
&i2c3 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c3>;
- pinctrl-assert-gpios = <&gpio5 4 GPIO_ACTIVE_HIGH>;
status = "okay";
max7310_a: gpio@30 {
diff --git a/dts/src/arm/omap3-devkit8000.dts b/dts/src/arm/omap3-devkit8000.dts
index 134d3f27a8..921de6605f 100644
--- a/dts/src/arm/omap3-devkit8000.dts
+++ b/dts/src/arm/omap3-devkit8000.dts
@@ -110,6 +110,8 @@
nand@0,0 {
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
nand-bus-width = <16>;
+ gpmc,device-width = <2>;
+ ti,nand-ecc-opt = "sw";
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
diff --git a/dts/src/arm/omap3-n900.dts b/dts/src/arm/omap3-n900.dts
index a29315833e..5f5e0f3d5b 100644
--- a/dts/src/arm/omap3-n900.dts
+++ b/dts/src/arm/omap3-n900.dts
@@ -498,6 +498,8 @@
DRVDD-supply = <&vmmc2>;
IOVDD-supply = <&vio>;
DVDD-supply = <&vio>;
+
+ ai3x-micbias-vg = <1>;
};
tlv320aic3x_aux: tlv320aic3x@19 {
@@ -509,6 +511,8 @@
DRVDD-supply = <&vmmc2>;
IOVDD-supply = <&vio>;
DVDD-supply = <&vio>;
+
+ ai3x-micbias-vg = <2>;
};
tsl2563: tsl2563@29 {
@@ -828,8 +832,8 @@
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
- touchscreen-max-x = <4096>;
- touchscreen-max-y = <4096>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
diff --git a/dts/src/arm/omap3.dtsi b/dts/src/arm/omap3.dtsi
index d18a90f5ec..69a40cfc1f 100644
--- a/dts/src/arm/omap3.dtsi
+++ b/dts/src/arm/omap3.dtsi
@@ -456,6 +456,7 @@
};
mmu_isp: mmu@480bd400 {
+ #iommu-cells = <0>;
compatible = "ti,omap2-iommu";
reg = <0x480bd400 0x80>;
interrupts = <24>;
@@ -464,6 +465,7 @@
};
mmu_iva: mmu@5d000000 {
+ #iommu-cells = <0>;
compatible = "ti,omap2-iommu";
reg = <0x5d000000 0x80>;
interrupts = <28>;
diff --git a/dts/src/arm/omap5.dtsi b/dts/src/arm/omap5.dtsi
index efe5f737f3..7d24ae0306 100644
--- a/dts/src/arm/omap5.dtsi
+++ b/dts/src/arm/omap5.dtsi
@@ -128,7 +128,7 @@
* hierarchy.
*/
ocp {
- compatible = "ti,omap4-l3-noc", "simple-bus";
+ compatible = "ti,omap5-l3-noc", "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges;
diff --git a/dts/src/arm/r8a7791-koelsch.dts b/dts/src/arm/r8a7791-koelsch.dts
index 74c3212f1f..824ddab9c3 100644
--- a/dts/src/arm/r8a7791-koelsch.dts
+++ b/dts/src/arm/r8a7791-koelsch.dts
@@ -545,7 +545,7 @@
compatible = "adi,adv7511w";
reg = <0x39>;
interrupt-parent = <&gpio3>;
- interrupts = <29 IRQ_TYPE_EDGE_FALLING>;
+ interrupts = <29 IRQ_TYPE_LEVEL_LOW>;
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
diff --git a/dts/src/arm/ste-dbx5x0.dtsi b/dts/src/arm/ste-dbx5x0.dtsi
index bfd3f1c734..2201cd5da3 100644
--- a/dts/src/arm/ste-dbx5x0.dtsi
+++ b/dts/src/arm/ste-dbx5x0.dtsi
@@ -1017,23 +1017,6 @@
status = "disabled";
};
- vmmci: regulator-gpio {
- compatible = "regulator-gpio";
-
- regulator-min-microvolt = <1800000>;
- regulator-max-microvolt = <2900000>;
- regulator-name = "mmci-reg";
- regulator-type = "voltage";
-
- startup-delay-us = <100>;
- enable-active-high;
-
- states = <1800000 0x1
- 2900000 0x0>;
-
- status = "disabled";
- };
-
mcde@a0350000 {
compatible = "stericsson,mcde";
reg = <0xa0350000 0x1000>, /* MCDE */
diff --git a/dts/src/arm/ste-href.dtsi b/dts/src/arm/ste-href.dtsi
index bf8f0eddc2..744c1e3a74 100644
--- a/dts/src/arm/ste-href.dtsi
+++ b/dts/src/arm/ste-href.dtsi
@@ -111,6 +111,21 @@
pinctrl-1 = <&i2c3_sleep_mode>;
};
+ vmmci: regulator-gpio {
+ compatible = "regulator-gpio";
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-name = "mmci-reg";
+ regulator-type = "voltage";
+
+ startup-delay-us = <100>;
+ enable-active-high;
+
+ states = <1800000 0x1
+ 2900000 0x0>;
+ };
+
// External Micro SD slot
sdi0_per1@80126000 {
arm,primecell-periphid = <0x10480180>;
diff --git a/dts/src/arm/ste-snowball.dts b/dts/src/arm/ste-snowball.dts
index 206826a855..1bc84ebdcc 100644
--- a/dts/src/arm/ste-snowball.dts
+++ b/dts/src/arm/ste-snowball.dts
@@ -146,8 +146,21 @@
};
vmmci: regulator-gpio {
+ compatible = "regulator-gpio";
+
gpios = <&gpio7 4 0x4>;
enable-gpio = <&gpio6 25 0x4>;
+
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <2900000>;
+ regulator-name = "mmci-reg";
+ regulator-type = "voltage";
+
+ startup-delay-us = <100>;
+ enable-active-high;
+
+ states = <1800000 0x1
+ 2900000 0x0>;
};
// External Micro SD slot
diff --git a/dts/src/arm/tegra124.dtsi b/dts/src/arm/tegra124.dtsi
index cf01c818b8..13cc7ca5e0 100644
--- a/dts/src/arm/tegra124.dtsi
+++ b/dts/src/arm/tegra124.dtsi
@@ -826,7 +826,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 59>, <&tegra_car 22>;
+ resets = <&tegra_car 22>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
@@ -838,6 +838,7 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -862,7 +863,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 22>, <&tegra_car 22>;
+ resets = <&tegra_car 58>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
@@ -874,7 +875,6 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
- nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -899,7 +899,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 58>, <&tegra_car 22>;
+ resets = <&tegra_car 59>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
diff --git a/dts/src/arm/vexpress-v2p-ca15_a7.dts b/dts/src/arm/vexpress-v2p-ca15_a7.dts
index 7a2aeacd62..107395c32d 100644
--- a/dts/src/arm/vexpress-v2p-ca15_a7.dts
+++ b/dts/src/arm/vexpress-v2p-ca15_a7.dts
@@ -191,6 +191,7 @@
compatible = "arm,cortex-a15-pmu";
interrupts = <0 68 4>,
<0 69 4>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
};
oscclk6a: oscclk6a {
diff --git a/dts/src/arm/vexpress-v2p-ca9.dts b/dts/src/arm/vexpress-v2p-ca9.dts
index 23662b5a5e..d949facba3 100644
--- a/dts/src/arm/vexpress-v2p-ca9.dts
+++ b/dts/src/arm/vexpress-v2p-ca9.dts
@@ -33,28 +33,28 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ A9_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
};
- cpu@1 {
+ A9_1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
next-level-cache = <&L2>;
};
- cpu@2 {
+ A9_2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
next-level-cache = <&L2>;
};
- cpu@3 {
+ A9_3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
@@ -170,6 +170,7 @@
compatible = "arm,pl310-cache";
reg = <0x1e00a000 0x1000>;
interrupts = <0 43 4>;
+ cache-unified;
cache-level = <2>;
arm,data-latency = <1 1 1>;
arm,tag-latency = <1 1 1>;
@@ -181,6 +182,8 @@
<0 61 4>,
<0 62 4>,
<0 63 4>;
+ interrupt-affinity = <&A9_0>, <&A9_1>, <&A9_2>, <&A9_3>;
+
};
dcc {
diff --git a/dts/src/arm/zynq-7000.dtsi b/dts/src/arm/zynq-7000.dtsi
index a5cd2eda3e..9ea54b3dba 100644
--- a/dts/src/arm/zynq-7000.dtsi
+++ b/dts/src/arm/zynq-7000.dtsi
@@ -193,7 +193,7 @@
};
gem0: ethernet@e000b000 {
- compatible = "cdns,gem";
+ compatible = "cdns,zynq-gem";
reg = <0xe000b000 0x1000>;
status = "disabled";
interrupts = <0 22 4>;
@@ -204,7 +204,7 @@
};
gem1: ethernet@e000c000 {
- compatible = "cdns,gem";
+ compatible = "cdns,zynq-gem";
reg = <0xe000c000 0x1000>;
status = "disabled";
interrupts = <0 45 4>;
diff --git a/dts/src/arm64/arm/juno-motherboard.dtsi b/dts/src/arm64/arm/juno-motherboard.dtsi
index c138b95a83..351c95bda8 100644
--- a/dts/src/arm64/arm/juno-motherboard.dtsi
+++ b/dts/src/arm64/arm/juno-motherboard.dtsi
@@ -21,6 +21,20 @@
clock-output-names = "juno_mb:clk25mhz";
};
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "juno_mb:refclk1mhz";
+ };
+
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "juno_mb:refclk32khz";
+ };
+
motherboard {
compatible = "arm,vexpress,v2p-p1", "simple-bus";
#address-cells = <2>; /* SMB chipselect number and offset */
@@ -66,6 +80,15 @@
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
+ v2m_sysctl: sysctl@020000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&mb_clk24mhz>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ };
+
mmci@050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
@@ -106,16 +129,16 @@
compatible = "arm,sp804", "arm,primecell";
reg = <0x110000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
v2m_timer23: timer@120000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x120000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
rtc@170000 {
diff --git a/dts/src/arm64/mediatek/mt8173-evb.dts b/dts/src/arm64/mediatek/mt8173-evb.dts
index 43d54017b7..d0ab012fa3 100644
--- a/dts/src/arm64/mediatek/mt8173-evb.dts
+++ b/dts/src/arm64/mediatek/mt8173-evb.dts
@@ -16,7 +16,8 @@
#include "mt8173.dtsi"
/ {
- model = "mediatek,mt8173-evb";
+ model = "MediaTek MT8173 evaluation board";
+ compatible = "mediatek,mt8173-evb", "mediatek,mt8173";
aliases {
serial0 = &uart0;
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index fb927149e7..97f028a3ec 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -481,4 +481,3 @@ static int cramfs_init(void)
}
device_initcall(cramfs_init);
-
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 6d7d262f32..ece937d443 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -434,4 +434,3 @@ static int fat_init(void)
}
coredevice_initcall(fat_init);
-
diff --git a/fs/fs.c b/fs/fs.c
index 779f2641b2..c249f843bf 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -1564,14 +1564,11 @@ out:
}
EXPORT_SYMBOL(rmdir);
-static void memcpy_sz(void *_dst, const void *_src, ulong count, ulong rwsize)
+static void memcpy_sz(void *dst, const void *src, size_t count, int rwsize)
{
- ulong dst = (ulong)_dst;
- ulong src = (ulong)_src;
-
/* no rwsize specification given. Do whatever memcpy likes best */
if (!rwsize) {
- memcpy(_dst, _src, count);
+ memcpy(dst, src, count);
return;
}
@@ -1582,13 +1579,16 @@ static void memcpy_sz(void *_dst, const void *_src, ulong count, ulong rwsize)
while (count-- > 0) {
switch (rwsize) {
case 1:
- *((u_char *)dst) = *((u_char *)src);
+ *((u8 *)dst) = *((u8 *)src);
break;
case 2:
- *((ushort *)dst) = *((ushort *)src);
+ *((u16 *)dst) = *((u16 *)src);
break;
case 4:
- *((ulong *)dst) = *((ulong *)src);
+ *((u32 *)dst) = *((u32 *)src);
+ break;
+ case 8:
+ *((u64 *)dst) = *((u64 *)src);
break;
}
dst += rwsize;
diff --git a/fs/ramfs.c b/fs/ramfs.c
index fe5eb89824..716f40f5ba 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -644,4 +644,3 @@ static int ramfs_init(void)
}
coredevice_initcall(ramfs_init);
-
diff --git a/fs/tftp.c b/fs/tftp.c
index 72e4983a01..0de215e5e9 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -253,27 +253,24 @@ static void tftp_timer_reset(struct file_priv *priv)
priv->progress_timeout = priv->resend_timeout = get_time_ns();
}
-static void tftp_handler(void *ctx, char *packet, unsigned len)
+static void tftp_recv(struct file_priv *priv,
+ uint8_t *pkt, unsigned len, uint16_t uh_sport)
{
- struct file_priv *priv = ctx;
- uint16_t proto;
- uint16_t *s;
- char *pkt = net_eth_to_udp_payload(packet);
- struct udphdr *udp = net_eth_to_udphdr(packet);
+ uint16_t opcode;
- len = net_eth_to_udplen(packet);
- if (len < 2)
+ /* according to RFC1350 minimal tftp packet length is 4 bytes */
+ if (len < 4)
return;
- len -= 2;
+ opcode = ntohs(*(uint16_t *)pkt);
- s = (uint16_t *)pkt;
- proto = *s++;
- pkt = (unsigned char *)s;
+ /* skip tftp opcode 2-byte field */
+ len -= 2;
+ pkt += 2;
- debug("%s: proto 0x%04x\n", __func__, proto);
+ debug("%s: opcode 0x%04x\n", __func__, opcode);
- switch (ntohs(proto)) {
+ switch (opcode) {
case TFTP_RRQ:
case TFTP_WRQ:
default:
@@ -296,14 +293,14 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
priv->state = STATE_DONE;
break;
}
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
+ priv->tftp_con->udp->uh_dport = uh_sport;
priv->state = STATE_WDATA;
break;
case TFTP_OACK:
tftp_parse_oack(priv, pkt, len);
- priv->server_port = ntohs(udp->uh_sport);
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
+ priv->server_port = ntohs(uh_sport);
+ priv->tftp_con->udp->uh_dport = uh_sport;
if (priv->push) {
/* send first block */
@@ -318,16 +315,14 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
break;
case TFTP_DATA:
- if (len < 2)
- return;
len -= 2;
priv->block = ntohs(*(uint16_t *)pkt);
if (priv->state == STATE_RRQ || priv->state == STATE_OACK) {
/* first block received */
priv->state = STATE_RDATA;
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
- priv->server_port = ntohs(udp->uh_sport);
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ priv->server_port = ntohs(uh_sport);
priv->last_block = 0;
if (priv->block != 1) { /* Assertion */
@@ -376,6 +371,16 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
}
}
+static void tftp_handler(void *ctx, char *packet, unsigned len)
+{
+ struct file_priv *priv = ctx;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+
+ (void)len;
+ tftp_recv(priv, pkt, net_eth_to_udplen(packet), udp->uh_sport);
+}
+
static struct file_priv *tftp_do_open(struct device_d *dev,
int accmode, const char *filename)
{
diff --git a/images/Makefile b/images/Makefile
index 587cb2651f..a5f589b303 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -75,6 +75,8 @@ quiet_cmd_pblx ?= PBLX $@
$(obj)/%.pblx: $(obj)/%.pblb $(obj)/barebox.z FORCE
$(call if_changed,pblx,$(@F))
+ $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_PBLX_SIZE))
+
$(obj)/%.s: $(obj)/% FORCE
$(call if_changed,disasm)
@@ -105,6 +107,7 @@ include $(srctree)/images/Makefile.imx
include $(srctree)/images/Makefile.imxhabv4
include $(srctree)/images/Makefile.mvebu
include $(srctree)/images/Makefile.mxs
+include $(srctree)/images/Makefile.omap3
include $(srctree)/images/Makefile.rockchip
include $(srctree)/images/Makefile.socfpga
include $(srctree)/images/Makefile.tegra
diff --git a/images/Makefile.am33xx b/images/Makefile.am33xx
index eae2a6a6e1..657aeb0e28 100644
--- a/images/Makefile.am33xx
+++ b/images/Makefile.am33xx
@@ -7,13 +7,23 @@ quiet_cmd_mlo_image = MLO $@
$(obj)/%.mlo: $(obj)/% FORCE
$(call if_changed,mlo_image)
+# %.mlospi - convert MLO image for SPI loading
+# ----------------------------------------------------------------
+quiet_cmd_mlo_spi_image = SPI-IMG $@
+ cmd_mlo_spi_image = scripts/mk-omap-image -s -a 0x402f0400 $<.mlo > $@
+
+$(obj)/%.mlospi: $(obj)/% $(obj)/%.mlo FORCE
+ $(call if_changed,mlo_spi_image)
+
pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sdram
FILE_barebox-am33xx-afi-gf.img = start_am33xx_afi_gf_sdram.pblx
am33xx-barebox-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf.img
pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sram
FILE_barebox-am33xx-afi-gf-mlo.img = start_am33xx_afi_gf_sram.pblx.mlo
+FILE_barebox-am33xx-afi-gf-mlo.spi.img = start_am33xx_afi_gf_sram.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf-mlo.img
+am33xx-mlospi-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf-mlo.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sdram
FILE_barebox-am33xx-phytec-phycore.img = start_am33xx_phytec_phycore_sdram.pblx
@@ -25,19 +35,27 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_256mb
FILE_barebox-am33xx-phytec-phycore-mlo-256mb.img = start_am33xx_phytec_phycore_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-256mb.spi.img = start_am33xx_phytec_phycore_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_128mb
FILE_barebox-am33xx-phytec-phycore-mlo-128mb.img = start_am33xx_phytec_phycore_sram_128mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-128mb.spi.img = start_am33xx_phytec_phycore_sram_128mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-128mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-128mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_512mb
FILE_barebox-am33xx-phytec-phycore-mlo-512mb.img = start_am33xx_phytec_phycore_sram_512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-512mb.spi.img = start_am33xx_phytec_phycore_sram_512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_2x512mb
FILE_barebox-am33xx-phytec-phycore-mlo-2x512mb.img = start_am33xx_phytec_phycore_sram_2x512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-2x512mb.spi.img = start_am33xx_phytec_phycore_sram_2x512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-2x512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-2x512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sdram
FILE_barebox-am33xx-phytec-phyflex.img = start_am33xx_phytec_phyflex_sdram.pblx
@@ -45,11 +63,15 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sram_256mb
FILE_barebox-am33xx-phytec-phyflex-mlo-256mb.img = start_am33xx_phytec_phyflex_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phyflex-mlo-256mb.spi.img = start_am33xx_phytec_phyflex_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sram_512mb
FILE_barebox-am33xx-phytec-phyflex-mlo-512mb.img = start_am33xx_phytec_phyflex_sram_512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phyflex-mlo-512mb.spi.img = start_am33xx_phytec_phyflex_sram_512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycard_sdram
FILE_barebox-am33xx-phytec-phycard.img = start_am33xx_phytec_phycard_sdram.pblx
@@ -57,7 +79,9 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycard_sram_256mb
FILE_barebox-am33xx-phytec-phycard-mlo-256mb.img = start_am33xx_phytec_phycard_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycard-mlo-256mb.spi.img = start_am33xx_phytec_phycard_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_BEAGLEBONE) += start_am33xx_beaglebone_sdram
FILE_barebox-am33xx-beaglebone.img = start_am33xx_beaglebone_sdram.pblx
@@ -72,3 +96,7 @@ image-y += $(am33xx-mlo-y)
else
image-y += $(am33xx-barebox-y)
endif
+
+ifdef CONFIG_OMAP_BUILD_SPI
+image-y += $(am33xx-mlospi-y)
+endif
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 415b294e85..6b44958157 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -4,8 +4,15 @@
# %.imximg - convert into i.MX image
# ----------------------------------------------------------------
+
+ifdef CONFIG_ARCH_IMX_XLOAD
+$(obj)/%.imximg: $(obj)/% FORCE
+ $(call cmd,check_file_size,$<,$(CONFIG_ARCH_IMX_UNUSED_IRAM_SIZE))
+ $(call if_changed,imx_image)
+else
$(obj)/%.imximg: $(obj)/% FORCE
$(call if_changed,imx_image)
+endif
# ----------------------- i.MX25 based boards ---------------------------
pblx-$(CONFIG_MACH_TX25) += start_imx25_karo_tx25
@@ -29,7 +36,18 @@ image-$(CONFIG_MACH_PCM038) += barebox-phytec-phycore-imx27.img
pblx-$(CONFIG_MACH_FREESCALE_MX51_PDK) += start_imx51_babbage
CFG_start_imx51_babbage.pblx.imximg = $(board)/freescale-mx51-babbage/flash-header-imx51-babbage.imxcfg
FILE_barebox-freescale-imx51-babbage.img = start_imx51_babbage.pblx.imximg
-image-$(CONFIG_MACH_FREESCALE_MX51_PDK) += barebox-freescale-imx51-babbage.img
+imx-barebox-$(CONFIG_MACH_FREESCALE_MX51_PDK) += barebox-freescale-imx51-babbage.img
+
+pblx-$(CONFIG_MACH_FREESCALE_MX51_PDK) += start_imx51_babbage_xload
+CFG_start_imx51_babbage_xload.pblx.imximg = $(board)/freescale-mx51-babbage/flash-header-imx51-babbage-xload.imxcfg
+FILE_barebox-freescale-imx51-babbage-xload.img = start_imx51_babbage_xload.pblx.imximg
+imx-xload-$(CONFIG_MACH_FREESCALE_MX51_PDK) += barebox-freescale-imx51-babbage-xload.img
+
+ifdef CONFIG_ARCH_IMX_XLOAD
+image-y += $(imx-xload-y)
+else
+image-y += $(imx-barebox-y)
+endif
pblx-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += start_imx51_genesi_efikasb
CFG_start_imx51_genesi_efikasb.pblx.imximg = $(board)/efika-mx-smartbook/flash-header-imx51-genesi-efikasb.imxcfg
diff --git a/images/Makefile.omap3 b/images/Makefile.omap3
new file mode 100644
index 0000000000..694ec30836
--- /dev/null
+++ b/images/Makefile.omap3
@@ -0,0 +1,19 @@
+# %.mlo - convert into mlo image
+# ----------------------------------------------------------------
+quiet_cmd_omap3_mlo_image = MLO $@
+ cmd_omap3_mlo_image = scripts/omap_signGP -o $@ -l 0x40200000 -c $<
+
+$(obj)/%.omap3_mlo: $(obj)/% FORCE
+ $(call if_changed,omap3_mlo_image)
+
+pblx-$(CONFIG_MACH_BEAGLE) += start_omap3_beagleboard_sdram start_omap3_beagleboard_sram
+FILE_barebox-beagleboard.img = start_omap3_beagleboard_sdram.pblx
+omap3-barebox-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard.img
+FILE_barebox-beagleboard-mlo.img = start_omap3_beagleboard_sram.pblx.omap3_mlo
+omap3-mlo-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard-mlo.img
+
+ifdef CONFIG_OMAP_BUILD_IFT
+image-y += $(omap3-mlo-y)
+else
+image-y += $(omap3-barebox-y)
+endif
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index e359187d7f..00d6ecaf54 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -34,7 +34,9 @@
KEEP(*(.initcall.9)) \
KEEP(*(.initcall.10)) \
KEEP(*(.initcall.11)) \
- KEEP(*(.initcall.12))
+ KEEP(*(.initcall.12)) \
+ KEEP(*(.initcall.13)) \
+ KEEP(*(.initcall.14))
#define BAREBOX_CMDS KEEP(*(SORT_BY_NAME(.barebox_cmd*)))
@@ -45,7 +47,8 @@
#define BAREBOX_CLK_TABLE() \
. = ALIGN(8); \
__clk_of_table_start = .; \
- KEEP(*(.__clk_of_table_*)); \
+ KEEP(*(.__clk_of_table)); \
+ KEEP(*(.__clk_of_table_end)); \
__clk_of_table_end = .;
#define BAREBOX_DTB() \
diff --git a/include/asm-generic/bitsperlong.h b/include/asm-generic/bitsperlong.h
index 4ae54e07de..bb98650298 100644
--- a/include/asm-generic/bitsperlong.h
+++ b/include/asm-generic/bitsperlong.h
@@ -1,32 +1,10 @@
#ifndef __ASM_GENERIC_BITS_PER_LONG
#define __ASM_GENERIC_BITS_PER_LONG
-/*
- * There seems to be no way of detecting this automatically from user
- * space, so 64 bit architectures should override this in their
- * bitsperlong.h. In particular, an architecture that supports
- * both 32 and 64 bit user space must not rely on CONFIG_64BIT
- * to decide it, but rather check a compiler provided macro.
- */
-#ifndef __BITS_PER_LONG
-#define __BITS_PER_LONG 32
-#endif
-
-#ifdef __KERNEL__
-
#ifdef CONFIG_64BIT
#define BITS_PER_LONG 64
#else
#define BITS_PER_LONG 32
#endif /* CONFIG_64BIT */
-/*
- * FIXME: The check currently breaks x86-64 build, so it's
- * temporarily disabled. Please fix x86-64 and reenable
- */
-#if 0 && BITS_PER_LONG != __BITS_PER_LONG
-#error Inconsistent word size. Check asm/bitsperlong.h
-#endif
-
-#endif /* __KERNEL__ */
#endif /* __ASM_GENERIC_BITS_PER_LONG */
diff --git a/include/asm-generic/posix_types.h b/include/asm-generic/posix_types.h
new file mode 100644
index 0000000000..136f161e15
--- /dev/null
+++ b/include/asm-generic/posix_types.h
@@ -0,0 +1,90 @@
+#ifndef __ASM_GENERIC_POSIX_TYPES_H
+#define __ASM_GENERIC_POSIX_TYPES_H
+
+#include <asm/bitsperlong.h>
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc.
+ *
+ * First the types that are often defined in different ways across
+ * architectures, so that you can override them.
+ */
+
+#ifndef __kernel_long_t
+typedef long __kernel_long_t;
+typedef unsigned long __kernel_ulong_t;
+#endif
+
+#ifndef __kernel_ino_t
+typedef __kernel_ulong_t __kernel_ino_t;
+#endif
+
+#ifndef __kernel_mode_t
+typedef unsigned int __kernel_mode_t;
+#endif
+
+#ifndef __kernel_pid_t
+typedef int __kernel_pid_t;
+#endif
+
+#ifndef __kernel_ipc_pid_t
+typedef int __kernel_ipc_pid_t;
+#endif
+
+#ifndef __kernel_uid_t
+typedef unsigned int __kernel_uid_t;
+typedef unsigned int __kernel_gid_t;
+#endif
+
+#ifndef __kernel_suseconds_t
+typedef __kernel_long_t __kernel_suseconds_t;
+#endif
+
+#ifndef __kernel_daddr_t
+typedef int __kernel_daddr_t;
+#endif
+
+#ifndef __kernel_uid32_t
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+#endif
+
+#ifndef __kernel_old_uid_t
+typedef __kernel_uid_t __kernel_old_uid_t;
+typedef __kernel_gid_t __kernel_old_gid_t;
+#endif
+
+#ifndef __kernel_old_dev_t
+typedef unsigned int __kernel_old_dev_t;
+#endif
+
+/*
+ * Most 32 bit architectures use "unsigned int" size_t,
+ * and all 64 bit architectures use "unsigned long" size_t.
+ */
+#ifndef __kernel_size_t
+#if BITS_PER_LONG != 64
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+#else
+typedef __kernel_ulong_t __kernel_size_t;
+typedef __kernel_long_t __kernel_ssize_t;
+typedef __kernel_long_t __kernel_ptrdiff_t;
+#endif
+#endif
+
+/*
+ * anything below here should be completely generic
+ */
+typedef __kernel_long_t __kernel_off_t;
+typedef long long __kernel_loff_t;
+typedef __kernel_long_t __kernel_time_t;
+typedef __kernel_long_t __kernel_clock_t;
+typedef int __kernel_timer_t;
+typedef int __kernel_clockid_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+
+#endif /* __ASM_GENERIC_POSIX_TYPES_H */
diff --git a/include/asm-generic/swab.h b/include/asm-generic/swab.h
index a8e9029d9e..3ab5add54f 100644
--- a/include/asm-generic/swab.h
+++ b/include/asm-generic/swab.h
@@ -9,7 +9,7 @@
* valid if the compiler supports 64 bit data types.
*/
-#if __BITS_PER_LONG == 32
+#if BITS_PER_LONG == 32
#if defined(__GNUC__) && !defined(__STRICT_ANSI__) || defined(__KERNEL__)
#define __SWAB_64_THRU_32__
#endif
diff --git a/include/bbu.h b/include/bbu.h
index 4a3d35e7ce..7277911718 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -4,6 +4,7 @@
#include <asm-generic/errno.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <filetype.h>
struct bbu_data {
#define BBU_FLAG_FORCE (1 << 0)
@@ -41,6 +42,9 @@ void bbu_handlers_list(void);
int bbu_register_handler(struct bbu_handler *);
+int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype);
+
#else
static inline int bbu_register_handler(struct bbu_handler *unused)
@@ -48,6 +52,25 @@ static inline int bbu_register_handler(struct bbu_handler *unused)
return -EINVAL;
}
+static inline int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype)
+{
+ return -ENOSYS;
+}
+#endif
+
+#if defined(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB)
+int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
+int imx28_bbu_nand_register_handler(const char *name, unsigned long flags);
+#else
+static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ return -ENOSYS;
+}
+static inline int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ return -ENOSYS;
+}
#endif
#endif /* __INCLUDE_BBU_H */
diff --git a/include/blspec.h b/include/blspec.h
index afac5ed7ba..e22e9be11d 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -35,6 +35,7 @@ int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
int blspec_scan_devices(struct blspec *blspec);
+int blspec_scan_device(struct blspec *blspec, struct device_d *dev);
int blspec_scan_devicename(struct blspec *blspec, const char *devname);
int blspec_scan_directory(struct blspec *blspec, const char *root);
diff --git a/include/bootsource.h b/include/bootsource.h
index 4bca9b99ad..c6d3b3a98b 100644
--- a/include/bootsource.h
+++ b/include/bootsource.h
@@ -15,6 +15,7 @@ enum bootsource {
BOOTSOURCE_ONENAND,
BOOTSOURCE_HD,
BOOTSOURCE_USB,
+ BOOTSOURCE_NET,
};
#define BOOTSOURCE_INSTANCE_UNKNOWN -1
diff --git a/include/console.h b/include/console.h
index 72b4a440e7..839ec17e50 100644
--- a/include/console.h
+++ b/include/console.h
@@ -52,8 +52,10 @@ struct console_device {
struct list_head list;
unsigned char f_active;
+ char active[4];
unsigned int baudrate;
+ unsigned int baudrate_param;
const char *linux_console_name;
};
@@ -62,6 +64,7 @@ int console_register(struct console_device *cdev);
int console_unregister(struct console_device *cdev);
struct console_device *console_get_by_dev(struct device_d *dev);
+struct console_device *console_get_by_name(const char *name);
extern struct list_head console_list;
#define for_each_console(console) list_for_each_entry(console, &console_list, list)
@@ -75,4 +78,9 @@ extern int barebox_loglevel;
struct console_device *console_get_first_active(void);
+int console_set_active(struct console_device *cdev, unsigned active);
+unsigned console_get_active(struct console_device *cdev);
+int console_set_baudrate(struct console_device *cdev, unsigned baudrate);
+unsigned console_get_baudrate(struct console_device *cdev);
+
#endif
diff --git a/include/crc.h b/include/crc.h
index 10560c9fa9..4290f41c57 100644
--- a/include/crc.h
+++ b/include/crc.h
@@ -95,6 +95,6 @@ cyg_ether_crc32_accumulate(uint32_t crc, unsigned char *s, int len);
/* 16 bit CRC with polynomial x^16+x^12+x^5+1 */
-extern uint16_t cyg_crc16(unsigned char *s, int len);
+extern uint16_t cyg_crc16(const unsigned char *s, int len);
#endif /* _SERVICES_CRC_CRC_H_ */
diff --git a/include/dhcp.h b/include/dhcp.h
new file mode 100644
index 0000000000..0796b30cf1
--- /dev/null
+++ b/include/dhcp.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2015 PHYTEC Messtechnik GmbH,
+ * Author: Wadim Egorov <w.egorov@phytec.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __DHCP_H__
+#define __DHCP_H__
+
+#define DHCP_DEFAULT_RETRY 20
+
+struct dhcp_req_param {
+ char *hostname;
+ char *vendor_id;
+ char *client_id;
+ char *user_class;
+ char *client_uuid;
+};
+
+int dhcp(int retries, struct dhcp_req_param *param);
+
+#endif
diff --git a/include/digest.h b/include/digest.h
index 7f8d696eb6..3a9d305963 100644
--- a/include/digest.h
+++ b/include/digest.h
@@ -59,6 +59,7 @@ struct digest {
/*
* digest functions
*/
+#ifdef CONFIG_DIGEST
int digest_algo_register(struct digest_algo *d);
void digest_algo_unregister(struct digest_algo *d);
void digest_algo_prints(const char *prefix);
@@ -68,14 +69,24 @@ void digest_free(struct digest *d);
int digest_file_window(struct digest *d, const char *filename,
unsigned char *hash,
- unsigned char *sig,
+ const unsigned char *sig,
ulong start, ulong size);
int digest_file(struct digest *d, const char *filename,
- unsigned char *hash,
- unsigned char *sig);
+ unsigned char *hash,
+ const unsigned char *sig);
int digest_file_by_name(const char *algo, const char *filename,
- unsigned char *hash,
- unsigned char *sig);
+ unsigned char *hash,
+ const unsigned char *sig);
+#else
+static inline struct digest *digest_alloc(const char *name)
+{
+ return NULL;
+}
+
+static inline void digest_free(struct digest *d)
+{
+}
+#endif
static inline int digest_init(struct digest *d)
{
diff --git a/include/fcntl.h b/include/fcntl.h
index aed741e584..501b415035 100644
--- a/include/fcntl.h
+++ b/include/fcntl.h
@@ -17,11 +17,12 @@
#define O_NOFOLLOW 00400000 /* don't follow links */
/* barebox additional flags */
-#define O_RWSIZE_MASK 00000070
+#define O_RWSIZE_MASK 00000170
#define O_RWSIZE_SHIFT 3
#define O_RWSIZE_1 00000010
#define O_RWSIZE_2 00000020
#define O_RWSIZE_4 00000040
+#define O_RWSIZE_8 00000100
#define F_DUPFD 0 /* dup */
#define F_GETFD 1 /* get close_on_exec */
diff --git a/include/filetype.h b/include/filetype.h
index cca4dad7f3..e452b7ac9d 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -34,6 +34,7 @@ enum filetype {
filetype_ch_image_be,
filetype_exe,
filetype_xz_compressed,
+ filetype_mxs_bootstream,
filetype_max,
};
diff --git a/include/habv4.h b/include/habv4.h
index fb6ed99d82..f9bf74f3b9 100644
--- a/include/habv4.h
+++ b/include/habv4.h
@@ -21,7 +21,7 @@
#ifdef CONFIG_HABV4
int habv4_get_status(void);
#else
-static inline int habv4_get_status()
+static inline int habv4_get_status(void)
{
return -EPERM;
}
diff --git a/include/init.h b/include/init.h
index 37c7eedf67..f619c951d3 100644
--- a/include/init.h
+++ b/include/init.h
@@ -39,6 +39,8 @@ typedef int (*initcall_t)(void);
#define device_initcall(fn) __define_initcall("10",fn,10)
#define crypto_initcall(fn) __define_initcall("11",fn,11)
#define late_initcall(fn) __define_initcall("12",fn,12)
+#define environment_initcall(fn) __define_initcall("13",fn,13)
+#define postenvironment_initcall(fn) __define_initcall("14",fn,14)
/* section for code used very early when
* - we're not running from where we linked at
diff --git a/include/io.h b/include/io.h
index 8d885de68f..8eb56b061f 100644
--- a/include/io.h
+++ b/include/io.h
@@ -3,12 +3,4 @@
#include <asm/io.h>
-/* cpu_read/cpu_write: cpu native io accessors */
-#define cpu_readb(a) __raw_readb(a)
-#define cpu_readw(a) __raw_readw(a)
-#define cpu_readl(a) __raw_readl(a)
-#define cpu_writeb(v, a) __raw_writeb((v), (a))
-#define cpu_writew(v, a) __raw_writew((v), (a))
-#define cpu_writel(v, a) __raw_writel((v), (a))
-
#endif /* __IO_H */
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index be5fd38bd5..f3a740c461 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -54,7 +54,7 @@ extern unsigned long __sw_hweight64(__u64 w);
(bit) < (size); \
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
-static __inline__ int get_bitmask_order(unsigned int count)
+static inline int get_bitmask_order(unsigned int count)
{
int order;
@@ -62,7 +62,7 @@ static __inline__ int get_bitmask_order(unsigned int count)
return order; /* We could be slightly more clever with -1 here... */
}
-static __inline__ int get_count_order(unsigned int count)
+static inline int get_count_order(unsigned int count)
{
int order;
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4aeec63a84..7a0ee110e4 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -321,7 +321,7 @@ struct of_phandle_args;
#define CLK_OF_DECLARE(name, compat, fn) \
const struct of_device_id __clk_of_table_##name \
-__attribute__ ((unused,section (".__clk_of_table_" __stringify(name)))) \
+__attribute__ ((unused,section (".__clk_of_table"))) \
= { .compatible = compat, .data = fn }
#if defined(CONFIG_OFTREE) && defined(CONFIG_COMMON_CLK_OF_PROVIDER)
diff --git a/include/linux/mod_devicetable.h b/include/linux/mod_devicetable.h
index c822075688..d8125214a0 100644
--- a/include/linux/mod_devicetable.h
+++ b/include/linux/mod_devicetable.h
@@ -17,4 +17,11 @@ struct pci_device_id {
__u32 class, class_mask; /* (class,subclass,prog-if) triplet */
};
+#define SPI_NAME_SIZE 32
+
+struct spi_device_id {
+ char name[SPI_NAME_SIZE];
+ unsigned long driver_data;
+};
+
#endif /* LINUX_MOD_DEVICETABLE_H */
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
new file mode 100644
index 0000000000..ccdbe93a90
--- /dev/null
+++ b/include/linux/mtd/concat.h
@@ -0,0 +1,34 @@
+/*
+ * MTD device concatenation layer definitions
+ *
+ * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef MTD_CONCAT_H
+#define MTD_CONCAT_H
+
+
+struct mtd_info *mtd_concat_create(
+ struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name); /* name for the new device */
+
+void mtd_concat_destroy(struct mtd_info *mtd);
+
+#endif
+
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 33f1fd512d..7e828bc98f 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -270,7 +270,7 @@ static inline uint32_t mtd_div_by_wb(uint64_t sz, struct mtd_info *mtd)
/* Kernel-side ioctl definitions */
-extern int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id);
+extern int add_mtd_device(struct mtd_info *mtd, const char *devname, int device_id);
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/linux/mtd/spi-nor.h b/include/linux/mtd/spi-nor.h
new file mode 100644
index 0000000000..f099406c53
--- /dev/null
+++ b/include/linux/mtd/spi-nor.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ *
+ * 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 __LINUX_MTD_SPI_NOR_H
+#define __LINUX_MTD_SPI_NOR_H
+
+/*
+ * Note on opcode nomenclature: some opcodes have a format like
+ * SPINOR_OP_FUNCTION{4,}_x_y_z. The numbers x, y, and z stand for the number
+ * of I/O lines used for the opcode, address, and data (respectively). The
+ * FUNCTION has an optional suffix of '4', to represent an opcode which
+ * requires a 4-byte (32-bit) address.
+ */
+
+/* Flash opcodes. */
+#define SPINOR_OP_WREN 0x06 /* Write enable */
+#define SPINOR_OP_RDSR 0x05 /* Read status register */
+#define SPINOR_OP_WRSR 0x01 /* Write status register 1 byte */
+#define SPINOR_OP_READ 0x03 /* Read data bytes (low frequency) */
+#define SPINOR_OP_READ_FAST 0x0b /* Read data bytes (high frequency) */
+#define SPINOR_OP_READ_1_1_2 0x3b /* Read data bytes (Dual SPI) */
+#define SPINOR_OP_READ_1_1_4 0x6b /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_PP 0x02 /* Page program (up to 256 bytes) */
+#define SPINOR_OP_BE_4K 0x20 /* Erase 4KiB block */
+#define SPINOR_OP_BE_4K_PMC 0xd7 /* Erase 4KiB block on PMC chips */
+#define SPINOR_OP_BE_32K 0x52 /* Erase 32KiB block */
+#define SPINOR_OP_CHIP_ERASE 0xc7 /* Erase whole flash chip */
+#define SPINOR_OP_SE 0xd8 /* Sector erase (usually 64KiB) */
+#define SPINOR_OP_RDID 0x9f /* Read JEDEC ID */
+#define SPINOR_OP_RDCR 0x35 /* Read configuration register */
+#define SPINOR_OP_RDFSR 0x70 /* Read flag status register */
+
+/* 4-byte address opcodes - used on Spansion and some Macronix flashes. */
+#define SPINOR_OP_READ4 0x13 /* Read data bytes (low frequency) */
+#define SPINOR_OP_READ4_FAST 0x0c /* Read data bytes (high frequency) */
+#define SPINOR_OP_READ4_1_1_2 0x3c /* Read data bytes (Dual SPI) */
+#define SPINOR_OP_READ4_1_1_4 0x6c /* Read data bytes (Quad SPI) */
+#define SPINOR_OP_PP_4B 0x12 /* Page program (up to 256 bytes) */
+#define SPINOR_OP_SE_4B 0xdc /* Sector erase (usually 64KiB) */
+
+/* Used for SST flashes only. */
+#define SPINOR_OP_BP 0x02 /* Byte program */
+#define SPINOR_OP_WRDI 0x04 /* Write disable */
+#define SPINOR_OP_AAI_WP 0xad /* Auto address increment word program */
+
+/* Used for Macronix and Winbond flashes. */
+#define SPINOR_OP_EN4B 0xb7 /* Enter 4-byte mode */
+#define SPINOR_OP_EX4B 0xe9 /* Exit 4-byte mode */
+
+/* Used for Spansion flashes only. */
+#define SPINOR_OP_BRWR 0x17 /* Bank register write */
+
+/* Status Register bits. */
+#define SR_WIP 1 /* Write in progress */
+#define SR_WEL 2 /* Write enable latch */
+/* meaning of other SR_* bits may differ between vendors */
+#define SR_BP0 4 /* Block protect 0 */
+#define SR_BP1 8 /* Block protect 1 */
+#define SR_BP2 0x10 /* Block protect 2 */
+#define SR_SRWD 0x80 /* SR write protect */
+
+#define SR_QUAD_EN_MX 0x40 /* Macronix Quad I/O */
+
+/* Flag Status Register bits */
+#define FSR_READY 0x80
+
+/* Configuration Register bits. */
+#define CR_QUAD_EN_SPAN 0x2 /* Spansion Quad I/O */
+
+enum read_mode {
+ SPI_NOR_NORMAL = 0,
+ SPI_NOR_FAST,
+ SPI_NOR_DUAL,
+ SPI_NOR_QUAD,
+};
+
+/**
+ * struct spi_nor_xfer_cfg - Structure for defining a Serial Flash transfer
+ * @wren: command for "Write Enable", or 0x00 for not required
+ * @cmd: command for operation
+ * @cmd_pins: number of pins to send @cmd (1, 2, 4)
+ * @addr: address for operation
+ * @addr_pins: number of pins to send @addr (1, 2, 4)
+ * @addr_width: number of address bytes
+ * (3,4, or 0 for address not required)
+ * @mode: mode data
+ * @mode_pins: number of pins to send @mode (1, 2, 4)
+ * @mode_cycles: number of mode cycles (0 for mode not required)
+ * @dummy_cycles: number of dummy cycles (0 for dummy not required)
+ */
+struct spi_nor_xfer_cfg {
+ u8 wren;
+ u8 cmd;
+ u8 cmd_pins;
+ u32 addr;
+ u8 addr_pins;
+ u8 addr_width;
+ u8 mode;
+ u8 mode_pins;
+ u8 mode_cycles;
+ u8 dummy_cycles;
+};
+
+#define SPI_NOR_MAX_CMD_SIZE 8
+enum spi_nor_ops {
+ SPI_NOR_OPS_READ = 0,
+ SPI_NOR_OPS_WRITE,
+ SPI_NOR_OPS_ERASE,
+ SPI_NOR_OPS_LOCK,
+ SPI_NOR_OPS_UNLOCK,
+};
+
+enum spi_nor_option_flags {
+ SNOR_F_USE_FSR = BIT(0),
+};
+
+/**
+ * struct spi_nor - Structure for defining a the SPI NOR layer
+ * @mtd: point to a mtd_info structure
+ * @lock: the lock for the read/write/erase/lock/unlock operations
+ * @dev: point to a spi device, or a spi nor controller device.
+ * @page_size: the page size of the SPI NOR
+ * @addr_width: number of address bytes
+ * @erase_opcode: the opcode for erasing a sector
+ * @read_opcode: the read opcode
+ * @read_dummy: the dummy needed by the read operation
+ * @program_opcode: the program opcode
+ * @flash_read: the mode of the read
+ * @sst_write_second: used by the SST write operation
+ * @flags: flag options for the current SPI-NOR (SNOR_F_*)
+ * @cfg: used by the read_xfer/write_xfer
+ * @cmd_buf: used by the write_reg
+ * @prepare: [OPTIONAL] do some preparations for the
+ * read/write/erase/lock/unlock operations
+ * @unprepare: [OPTIONAL] do some post work after the
+ * read/write/erase/lock/unlock operations
+ * @read_xfer: [OPTIONAL] the read fundamental primitive
+ * @write_xfer: [OPTIONAL] the writefundamental primitive
+ * @read_reg: [DRIVER-SPECIFIC] read out the register
+ * @write_reg: [DRIVER-SPECIFIC] write data to the register
+ * @read: [DRIVER-SPECIFIC] read data from the SPI NOR
+ * @write: [DRIVER-SPECIFIC] write data to the SPI NOR
+ * @erase: [DRIVER-SPECIFIC] erase a sector of the SPI NOR
+ * at the offset @offs
+ * @priv: the private data
+ */
+struct spi_nor {
+ struct mtd_info *mtd;
+ struct mutex lock;
+ struct device_d *dev;
+ u32 page_size;
+ u8 addr_width;
+ u8 erase_opcode;
+ u8 read_opcode;
+ u8 read_dummy;
+ u8 program_opcode;
+ enum read_mode flash_read;
+ bool sst_write_second;
+ u32 flags;
+ struct spi_nor_xfer_cfg cfg;
+ u8 cmd_buf[SPI_NOR_MAX_CMD_SIZE];
+
+ int (*prepare)(struct spi_nor *nor, enum spi_nor_ops ops);
+ void (*unprepare)(struct spi_nor *nor, enum spi_nor_ops ops);
+ int (*read_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
+ u8 *buf, size_t len);
+ int (*write_xfer)(struct spi_nor *nor, struct spi_nor_xfer_cfg *cfg,
+ u8 *buf, size_t len);
+ int (*read_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len);
+ int (*write_reg)(struct spi_nor *nor, u8 opcode, u8 *buf, int len,
+ int write_enable);
+
+ int (*read)(struct spi_nor *nor, loff_t from,
+ size_t len, size_t *retlen, u_char *read_buf);
+ void (*write)(struct spi_nor *nor, loff_t to,
+ size_t len, size_t *retlen, const u_char *write_buf);
+ int (*erase)(struct spi_nor *nor, loff_t offs);
+
+ void *priv;
+};
+
+/**
+ * spi_nor_scan() - scan the SPI NOR
+ * @nor: the spi_nor structure
+ * @name: the chip type name
+ * @mode: the read mode supported by the driver
+ *
+ * The drivers can use this fuction to scan the SPI NOR.
+ * In the scanning, it will try to get all the necessary information to
+ * fill the mtd_info{} and the spi_nor{}.
+ *
+ * The chip type name can be provided through the @name parameter.
+ *
+ * Return: 0 for success, others for failure.
+ */
+int spi_nor_scan(struct spi_nor *nor, const char *name, enum read_mode mode);
+
+#endif
diff --git a/include/linux/types.h b/include/linux/types.h
index c11e148c90..ce1a0ec84c 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -15,7 +15,6 @@ typedef __kernel_fd_set fd_set;
typedef __kernel_dev_t dev_t;
typedef __kernel_ino_t ino_t;
typedef __kernel_mode_t mode_t;
-typedef __kernel_nlink_t nlink_t;
typedef __kernel_off_t off_t;
typedef __kernel_pid_t pid_t;
typedef __kernel_daddr_t daddr_t;
@@ -158,6 +157,13 @@ typedef __u32 __bitwise __wsum;
#define __aligned_be64 __be64 __attribute__((aligned(8)))
#define __aligned_le64 __le64 __attribute__((aligned(8)))
+/* A dma_addr_t can hold any valid DMA or bus address for the platform */
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
+typedef u64 dma_addr_t;
+#else
+typedef u32 dma_addr_t;
+#endif /* dma_addr_t */
+
#ifdef CONFIG_PHYS_ADDR_T_64BIT
typedef u64 phys_addr_t;
typedef u64 phys_size_t;
diff --git a/include/net.h b/include/net.h
index 364011b20f..b93e264f54 100644
--- a/include/net.h
+++ b/include/net.h
@@ -42,7 +42,7 @@ struct eth_device {
int (*recv) (struct eth_device*);
void (*halt) (struct eth_device*);
int (*get_ethaddr) (struct eth_device*, u8 adr[6]);
- int (*set_ethaddr) (struct eth_device*, u8 adr[6]);
+ int (*set_ethaddr) (struct eth_device*, const unsigned char *adr);
struct eth_device *next;
void *priv;
@@ -60,6 +60,7 @@ struct eth_device {
IPaddr_t serverip;
IPaddr_t netmask;
IPaddr_t gateway;
+ char ethaddr_param[6];
char ethaddr[6];
};
@@ -67,6 +68,7 @@ struct eth_device {
int eth_register(struct eth_device* dev); /* Register network device */
void eth_unregister(struct eth_device* dev); /* Unregister network device */
+int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr);
int eth_send(struct eth_device *edev, void *packet, int length); /* Send a packet */
int eth_rx(void); /* Check for received packets */
diff --git a/include/of.h b/include/of.h
index e73cd7a446..1db210b38a 100644
--- a/include/of.h
+++ b/include/of.h
@@ -224,6 +224,8 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
extern struct device_node *of_get_root_node(void);
extern int of_set_root_node(struct device_node *node);
+extern struct device_d *of_platform_device_create(struct device_node *np,
+ struct device_d *parent);
extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
struct device_d *parent);
@@ -243,6 +245,7 @@ struct device_d *of_find_device_by_node_path(const char *path);
#define OF_FIND_PATH_FLAGS_BB 1 /* return .bb device if available */
int of_find_path(struct device_node *node, const char *propname, char **outpath, unsigned flags);
int of_register_fixup(int (*fixup)(struct device_node *, void *), void *context);
+int of_unregister_fixup(int (*fixup)(struct device_node *, void *), void *context);
struct device_node *of_find_node_by_alias(struct device_node *root,
const char *alias);
struct device_node *of_find_node_by_path_or_alias(struct device_node *root,
diff --git a/include/platform_data/cadence_qspi.h b/include/platform_data/cadence_qspi.h
new file mode 100644
index 0000000000..4930edce50
--- /dev/null
+++ b/include/platform_data/cadence_qspi.h
@@ -0,0 +1,9 @@
+#ifndef __INCLUDE_PLATFORM_DATA_CADENCE_QSPI_H
+#define __INCLUDE_PLATFORM_DATA_CADENCE_QSPI_H
+
+struct cadence_qspi_platform_data {
+ unsigned int ext_decoder;
+ unsigned int fifo_depth;
+};
+
+#endif /* __INCLUDE_PLATFORM_DATA_CADENCE_QSPI_H */
diff --git a/include/serial/imx-uart.h b/include/serial/imx-uart.h
new file mode 100644
index 0000000000..7275e6ac38
--- /dev/null
+++ b/include/serial/imx-uart.h
@@ -0,0 +1,128 @@
+#ifndef __IMX_UART_H__
+#define __IMX_UART_H__
+
+#define URXD0 0x0 /* Receiver Register */
+#define URTX0 0x40 /* Transmitter Register */
+#define UCR1 0x80 /* Control Register 1 */
+#define UCR2 0x84 /* Control Register 2 */
+#define UCR3 0x88 /* Control Register 3 */
+#define UCR4 0x8c /* Control Register 4 */
+#define UFCR 0x90 /* FIFO Control Register */
+#define USR1 0x94 /* Status Register 1 */
+#define USR2 0x98 /* Status Register 2 */
+#define UESC 0x9c /* Escape Character Register */
+#define UTIM 0xa0 /* Escape Timer Register */
+#define UBIR 0xa4 /* BRM Incremental Register */
+#define UBMR 0xa8 /* BRM Modulator Register */
+#define UBRC 0xac /* Baud Rate Count Register */
+
+/* UART Control Register Bit Fields.*/
+#define URXD_CHARRDY (1<<15)
+#define URXD_ERR (1<<14)
+#define URXD_OVRRUN (1<<13)
+#define URXD_FRMERR (1<<12)
+#define URXD_BRK (1<<11)
+#define URXD_PRERR (1<<10)
+#define UCR1_ADEN (1<<15) /* Auto dectect interrupt */
+#define UCR1_ADBR (1<<14) /* Auto detect baud rate */
+#define UCR1_TRDYEN (1<<13) /* Transmitter ready interrupt enable */
+#define UCR1_IDEN (1<<12) /* Idle condition interrupt */
+#define UCR1_RRDYEN (1<<9) /* Recv ready interrupt enable */
+#define UCR1_RDMAEN (1<<8) /* Recv ready DMA enable */
+#define UCR1_IREN (1<<7) /* Infrared interface enable */
+#define UCR1_TXMPTYEN (1<<6) /* Transimitter empty interrupt enable */
+#define UCR1_RTSDEN (1<<5) /* RTS delta interrupt enable */
+#define UCR1_SNDBRK (1<<4) /* Send break */
+#define UCR1_TDMAEN (1<<3) /* Transmitter ready DMA enable */
+#define UCR1_UARTCLKEN (1<<2) /* UART clock enabled */
+#define UCR1_DOZE (1<<1) /* Doze */
+#define UCR1_UARTEN (1<<0) /* UART enabled */
+#define UCR2_ESCI (1<<15) /* Escape seq interrupt enable */
+#define UCR2_IRTS (1<<14) /* Ignore RTS pin */
+#define UCR2_CTSC (1<<13) /* CTS pin control */
+#define UCR2_CTS (1<<12) /* Clear to send */
+#define UCR2_ESCEN (1<<11) /* Escape enable */
+#define UCR2_PREN (1<<8) /* Parity enable */
+#define UCR2_PROE (1<<7) /* Parity odd/even */
+#define UCR2_STPB (1<<6) /* Stop */
+#define UCR2_WS (1<<5) /* Word size */
+#define UCR2_RTSEN (1<<4) /* Request to send interrupt enable */
+#define UCR2_TXEN (1<<2) /* Transmitter enabled */
+#define UCR2_RXEN (1<<1) /* Receiver enabled */
+#define UCR2_SRST (1<<0) /* SW reset */
+#define UCR3_DTREN (1<<13) /* DTR interrupt enable */
+#define UCR3_PARERREN (1<<12) /* Parity enable */
+#define UCR3_FRAERREN (1<<11) /* Frame error interrupt enable */
+#define UCR3_DSR (1<<10) /* Data set ready */
+#define UCR3_DCD (1<<9) /* Data carrier detect */
+#define UCR3_RI (1<<8) /* Ring indicator */
+#define UCR3_ADNIMP (1<<7) /* Autobaud Detection Not Improved */
+#define UCR3_RXDSEN (1<<6) /* Receive status interrupt enable */
+#define UCR3_AIRINTEN (1<<5) /* Async IR wake interrupt enable */
+#define UCR3_AWAKEN (1<<4) /* Async wake interrupt enable */
+#define UCR3_REF25 (1<<3) /* Ref freq 25 MHz (i.MXL / i.MX1) */
+#define UCR3_REF30 (1<<2) /* Ref Freq 30 MHz (i.MXL / i.MX1) */
+#define UCR3_RXDMUXSEL (1<<2) /* RXD Muxed input select (i.MX27) */
+#define UCR3_INVT (1<<1) /* Inverted Infrared transmission */
+#define UCR3_BPEN (1<<0) /* Preset registers enable */
+#define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */
+#define UCR4_INVR (1<<9) /* Inverted infrared reception */
+#define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */
+#define UCR4_WKEN (1<<7) /* Wake interrupt enable */
+#define UCR4_REF16 (1<<6) /* Ref freq 16 MHz */
+#define UCR4_IRSC (1<<5) /* IR special case */
+#define UCR4_TCEN (1<<3) /* Transmit complete interrupt enable */
+#define UCR4_BKEN (1<<2) /* Break condition interrupt enable */
+#define UCR4_OREN (1<<1) /* Receiver overrun interrupt enable */
+#define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */
+#define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */
+#define UFCR_RFDIV (7<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV6 (0b000<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV5 (0b001<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV4 (0b010<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV3 (0b011<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV2 (0b100<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV1 (0b101<<7) /* Reference freq divider mask */
+#define UFCR_RFDIV7 (0b110<<7) /* Reference freq divider mask */
+#define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */
+#define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */
+#define USR1_RTSS (1<<14) /* RTS pin status */
+#define USR1_TRDY (1<<13) /* Transmitter ready interrupt/dma flag */
+#define USR1_RTSD (1<<12) /* RTS delta */
+#define USR1_ESCF (1<<11) /* Escape seq interrupt flag */
+#define USR1_FRAMERR (1<<10) /* Frame error interrupt flag */
+#define USR1_RRDY (1<<9) /* Receiver ready interrupt/dma flag */
+#define USR1_TIMEOUT (1<<7) /* Receive timeout interrupt status */
+#define USR1_RXDS (1<<6) /* Receiver idle interrupt flag */
+#define USR1_AIRINT (1<<5) /* Async IR wake interrupt flag */
+#define USR1_AWAKE (1<<4) /* Aysnc wake interrupt flag */
+#define USR2_ADET (1<<15) /* Auto baud rate detect complete */
+#define USR2_TXFE (1<<14) /* Transmit buffer FIFO empty */
+#define USR2_DTRF (1<<13) /* DTR edge interrupt flag */
+#define USR2_IDLE (1<<12) /* Idle condition */
+#define USR2_IRINT (1<<8) /* Serial infrared interrupt flag */
+#define USR2_WAKE (1<<7) /* Wake */
+#define USR2_RTSF (1<<4) /* RTS edge interrupt flag */
+#define USR2_TXDC (1<<3) /* Transmitter complete */
+#define USR2_BRCD (1<<2) /* Break condition */
+#define USR2_ORE (1<<1) /* Overrun error */
+#define USR2_RDR (1<<0) /* Recv data ready */
+#define UTS_FRCPERR (1<<13) /* Force parity error */
+#define UTS_LOOP (1<<12) /* Loop tx and rx */
+#define UTS_TXEMPTY (1<<6) /* TxFIFO empty */
+#define UTS_RXEMPTY (1<<5) /* RxFIFO empty */
+#define UTS_TXFULL (1<<4) /* TxFIFO full */
+#define UTS_RXFULL (1<<3) /* RxFIFO full */
+#define UTS_SOFTRST (1<<0) /* Software reset */
+
+static inline int baudrate_to_ubir(int baudrate)
+{
+ return baudrate / 100 - 1;
+}
+
+static inline int refclock_to_ubmr(int clock_hz)
+{
+ return clock_hz / 1600 - 1;
+}
+
+#endif /* __IMX_UART_H__ */
diff --git a/include/state.h b/include/state.h
index e96d3bfb2e..08c4e8654b 100644
--- a/include/state.h
+++ b/include/state.h
@@ -5,12 +5,13 @@
struct state;
-int state_backend_dtb_file(struct state *state, const char *path);
-int state_backend_raw_file(struct state *state, const char *path,
- off_t offset, size_t size);
+int state_backend_dtb_file(struct state *state, const char *of_path,
+ const char *path);
+int state_backend_raw_file(struct state *state, const char *of_path,
+ const char *path, off_t offset, size_t size);
-struct state *state_new_from_fdt(const char *name, void *fdt);
struct state *state_new_from_node(const char *name, struct device_node *node);
+void state_release(struct state *state);
struct state *state_by_name(const char *name);
struct state *state_by_node(const struct device_node *node);
diff --git a/include/watchdog.h b/include/watchdog.h
index 3e2d08e876..7e37b7c22a 100644
--- a/include/watchdog.h
+++ b/include/watchdog.h
@@ -17,8 +17,25 @@ struct watchdog {
int (*set_timeout)(struct watchdog *, unsigned);
};
+#ifdef CONFIG_WATCHDOG
int watchdog_register(struct watchdog *);
int watchdog_deregister(struct watchdog *);
int watchdog_set_timeout(unsigned);
+#else
+static inline int watchdog_register(struct watchdog *w)
+{
+ return 0;
+}
+
+int watchdog_deregister(struct watchdog *w)
+{
+ return 0;
+}
+
+int watchdog_set_timeout(unsigned t)
+{
+ return 0;
+}
+#endif
#endif /* INCLUDE_WATCHDOG_H */
diff --git a/lib/bootstrap/devfs.c b/lib/bootstrap/devfs.c
index 704680a4c9..5a64477eed 100644
--- a/lib/bootstrap/devfs.c
+++ b/lib/bootstrap/devfs.c
@@ -35,7 +35,7 @@ static void *read_image_head(const char *name)
cdev = cdev_open(name, O_RDONLY);
if (!cdev) {
bootstrap_err("failed to open partition\n");
- return NULL;
+ goto free_header;
}
ret = cdev_read(cdev, header, BAREBOX_HEAD_SIZE, 0, 0);
@@ -43,10 +43,14 @@ static void *read_image_head(const char *name)
if (ret != BAREBOX_HEAD_SIZE) {
bootstrap_err("failed to read from partition\n");
- return NULL;
+ goto free_header;
}
return header;
+
+free_header:
+ free(header);
+ return NULL;
}
static unsigned int get_image_size(void *head)
@@ -54,8 +58,12 @@ static unsigned int get_image_size(void *head)
unsigned int ret = 0;
unsigned int *psize = head + BAREBOX_HEAD_SIZE_OFFSET;
- if (is_barebox_head(head))
+ if (is_barebox_head(head)) {
ret = *psize;
+ if (!ret)
+ bootstrap_err(
+ "image has correct magic, but the length is zero\n");
+ }
debug("Detected barebox image size %u\n", ret);
return ret;
@@ -77,13 +85,27 @@ void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
{
int ret;
int size = 0;
- void *to, *header;
- struct cdev *cdev;
+ void *to, *header, *result = NULL;
+ struct cdev *cdev, *partition;
char *partname = "x";
- devfs_add_partition(devname, offset, max_size, DEVFS_PARTITION_FIXED, partname);
+ partition = devfs_add_partition(devname, offset, max_size,
+ DEVFS_PARTITION_FIXED, partname);
+ if (IS_ERR(partition)) {
+ bootstrap_err("%s: failed to add partition (%ld)\n",
+ devname, PTR_ERR(partition));
+ return NULL;
+ }
+
if (use_bb) {
- dev_add_bb_dev(partname, "bbx");
+ ret = dev_add_bb_dev(partname, "bbx");
+ if (ret) {
+ bootstrap_err(
+ "%s: failed to add bad block aware partition (%d)\n",
+ devname, ret);
+ goto delete_devfs_partition;
+ }
+
partname = "bbx";
}
@@ -105,14 +127,29 @@ void* bootstrap_read_devfs(char *devname, bool use_bb, int offset,
cdev = cdev_open(partname, O_RDONLY);
if (!cdev) {
bootstrap_err("%s: failed to open %s\n", devname, partname);
- return NULL;
+ goto free_memory;
}
ret = cdev_read(cdev, to, size, 0, 0);
- if (ret != size) {
+ cdev_close(cdev);
+
+ if (ret != size)
bootstrap_err("%s: failed to read from %s\n", devname, partname);
- return NULL;
+ else
+ result = to;
+
+free_memory:
+ free(header);
+ if (!result)
+ free(to);
+
+ if (use_bb) {
+ dev_remove_bb_dev(partname);
+ partname = "x";
}
- return to;
+delete_devfs_partition:
+ devfs_del_partition(partname);
+
+ return result;
}
diff --git a/lib/fnmatch.c b/lib/fnmatch.c
index 1a5e8d0d3d..0ab530d3b1 100644
--- a/lib/fnmatch.c
+++ b/lib/fnmatch.c
@@ -218,4 +218,3 @@ int fnmatch(const char *pattern, const char *string, int flags)
# undef FOLD
}
-
diff --git a/lib/gui/bmp.c b/lib/gui/bmp.c
index 6943a1c8e0..d457c01d84 100644
--- a/lib/gui/bmp.c
+++ b/lib/gui/bmp.c
@@ -7,6 +7,7 @@
#include <gui/graphic_utils.h>
#include <init.h>
#include <gui/image_renderer.h>
+#include <asm/unaligned.h>
struct image *bmp_open(char *inbuf, int insize)
{
@@ -19,9 +20,9 @@ struct image *bmp_open(char *inbuf, int insize)
}
img->data = inbuf;
- img->height = le32_to_cpu(bmp->header.height);
- img->width = le32_to_cpu(bmp->header.width);
- img->bits_per_pixel = le16_to_cpu(bmp->header.bit_count);
+ img->height = get_unaligned_le32(&bmp->header.height);
+ img->width = get_unaligned_le32(&bmp->header.width);
+ img->bits_per_pixel = get_unaligned_le16(&bmp->header.bit_count);
pr_debug("bmp: %d x %d x %d data@0x%p\n", img->width, img->height,
img->bits_per_pixel, img->data);
@@ -76,7 +77,7 @@ static int bmp_renderer(struct screen *sc, struct surface *s, struct image *img)
for (y = 0; y < height; y++) {
image = (char *)bmp +
- le32_to_cpu(bmp->header.data_offset);
+ get_unaligned_le32(&bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + (y + starty) * sc->info.line_length +
startx * (sc->info.bits_per_pixel >> 3);
@@ -98,7 +99,7 @@ static int bmp_renderer(struct screen *sc, struct surface *s, struct image *img)
for (y = 0; y < height; y++) {
image = (char *)bmp +
- le32_to_cpu(bmp->header.data_offset);
+ get_unaligned_le32(&bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + (y + starty) * sc->info.line_length +
startx * (sc->info.bits_per_pixel >> 3);
diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c
index dd29389baa..9bef99a7b0 100644
--- a/lib/gui/image_renderer.c
+++ b/lib/gui/image_renderer.c
@@ -37,10 +37,10 @@ struct image *image_renderer_open(const char* file)
struct image *img;
int ret;
- data = read_file(file, &size);
- if (!data) {
- printf("unable to read %s\n", file);
- return ERR_PTR(-ENOMEM);
+ ret = read_file_2(file, &size, &data, FILESIZE_MAX);
+ if (ret) {
+ printf("unable to read %s: %s\n", file, strerror(-ret));
+ return ERR_PTR(ret);
}
ir = get_renderer(data, size);
diff --git a/lib/libfile.c b/lib/libfile.c
index 8acff042c8..ba03700aba 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -184,8 +184,8 @@ again:
if (read_size < s.st_size)
return -EFBIG;
- else
- return 0;
+
+ return 0;
err_out1:
close(fd);
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 3c0f512634..6e8c822b3a 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -258,4 +258,3 @@ lookbehind_overrun:
}
EXPORT_SYMBOL(lzo1x_decompress_safe);
-
diff --git a/lib/parameter.c b/lib/parameter.c
index 865ad9f431..60642f001b 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -122,6 +122,14 @@ static const char *param_get_generic(struct device_d *dev, struct param_d *p)
return p->value ? p->value : "";
}
+static int compare(struct list_head *a, struct list_head *b)
+{
+ char *na = (char*)list_entry(a, struct param_d, list)->name;
+ char *nb = (char*)list_entry(b, struct param_d, list)->name;
+
+ return strcmp(na, nb);
+}
+
static int __dev_add_param(struct param_d *param, struct device_d *dev, const char *name,
int (*set)(struct device_d *dev, struct param_d *p, const char *val),
const char *(*get)(struct device_d *dev, struct param_d *p),
@@ -145,7 +153,7 @@ static int __dev_add_param(struct param_d *param, struct device_d *dev, const ch
param->flags = flags;
param->dev = dev;
- list_add_tail(&param->list, &dev->parameters);
+ list_add_sort(&param->list, &dev->parameters, compare);
return 0;
}
@@ -575,7 +583,6 @@ struct param_d *dev_add_param_llint_ro(struct device_d *dev, const char *name,
return &piro->param;
}
-#ifdef CONFIG_NET
struct param_ip {
struct param_d param;
IPaddr_t *ip;
@@ -739,7 +746,6 @@ struct param_d *dev_add_param_mac(struct device_d *dev, const char *name,
return &pm->param;
}
-#endif
/**
* dev_remove_param - remove a parameter from a device and free its
diff --git a/lib/random.c b/lib/random.c
index 14c7da119d..210fea9946 100644
--- a/lib/random.c
+++ b/lib/random.c
@@ -25,4 +25,3 @@ void get_random_bytes(void *_buf, int len)
while (len--)
*buf++ = rand() % 256;
}
-
diff --git a/lib/strtox.c b/lib/strtox.c
index 882865b45d..cfe61240cc 100644
--- a/lib/strtox.c
+++ b/lib/strtox.c
@@ -65,4 +65,3 @@ unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int ba
return result;
}
EXPORT_SYMBOL(simple_strtoull);
-
diff --git a/lib/xfuncs.c b/lib/xfuncs.c
index 86d0013787..0e78b670a5 100644
--- a/lib/xfuncs.c
+++ b/lib/xfuncs.c
@@ -30,8 +30,6 @@ void *xmalloc(size_t size)
if (!(p = malloc(size)))
panic("ERROR: out of memory\n");
- debug("xmalloc %p (size %zu)\n", p, size);
-
return p;
}
EXPORT_SYMBOL(xmalloc);
@@ -43,8 +41,6 @@ void *xrealloc(void *ptr, size_t size)
if (!(p = realloc(ptr, size)))
panic("ERROR: out of memory\n");
- debug("xrealloc %p -> %p (size %zu)\n", ptr, p, size);
-
return p;
}
EXPORT_SYMBOL(xrealloc);
diff --git a/net/Kconfig b/net/Kconfig
index 918d77653e..a89049201d 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -22,4 +22,8 @@ config NET_IFUP
default y
bool
+config NET_DHCP
+ bool
+ prompt "dhcp support"
+
endif
diff --git a/net/Makefile b/net/Makefile
index 907dc28b99..8d564e7299 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -1,7 +1,8 @@
+obj-y += lib.o
obj-$(CONFIG_NET) += eth.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_NET_NFS) += nfs.o
-obj-$(CONFIG_CMD_DHCP) += dhcp.o
+obj-$(CONFIG_NET_DHCP) += dhcp.o
obj-$(CONFIG_CMD_PING) += ping.o
obj-$(CONFIG_NET_RESOLV)+= dns.o
obj-$(CONFIG_NET_NETCONSOLE) += netconsole.o
diff --git a/net/dhcp.c b/net/dhcp.c
index 19a846270e..e1625ec9cd 100644
--- a/net/dhcp.c
+++ b/net/dhcp.c
@@ -21,8 +21,7 @@
#include <getopt.h>
#include <globalvar.h>
#include <init.h>
-
-#define DHCP_DEFAULT_RETRY 20
+#include <dhcp.h>
#define OPT_SIZE 312 /* Minimum DHCP Options size per RFC2131 - results in 576 byte pkt */
@@ -142,7 +141,8 @@ static void env_ip_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
IPaddr_t ip;
ip = net_read_ip(popt);
- setenv_ip(opt->barebox_var_name, ip);
+ if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
+ setenv_ip(opt->barebox_var_name, ip);
}
static void env_str_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen)
@@ -158,10 +158,9 @@ static void env_str_handle(struct dhcp_opt *opt, unsigned char *popt, int optlen
if (opt->copy_only_if_valid && !strlen(tmp))
return;
-
- if (opt->barebox_var_name)
+ if (opt->barebox_var_name && IS_ENABLED(EVIRONMENT_VARIABLES))
setenv(opt->barebox_var_name, tmp);
- if (opt->barebox_dhcp_global)
+ if (opt->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
dhcp_set_barebox_global(opt->barebox_dhcp_global, tmp);
}
@@ -263,10 +262,10 @@ static int dhcp_set_string_options(struct dhcp_param *param, u8 *e)
int str_len;
char* str = param->data;
- if (!str && param->barebox_var_name)
+ if (!str && param->barebox_var_name && IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
str = (char*)getenv(param->barebox_var_name);
- if (!str && param->barebox_dhcp_global)
+ if (!str && param->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
str = (char*)dhcp_get_barebox_global(param->barebox_dhcp_global);
if (!str)
@@ -391,8 +390,10 @@ static void bootp_copy_net_params(struct bootp *bp)
net_set_serverip(tmp_ip);
if (strlen(bp->bp_file) > 0) {
- setenv("bootfile", bp->bp_file);
- dhcp_set_barebox_global("bootfile", bp->bp_file);
+ if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
+ setenv("bootfile", bp->bp_file);
+ if (IS_ENABLED(CONFIG_GLOBALVAR))
+ dhcp_set_barebox_global("bootfile", bp->bp_file);
}
debug("bootfile: %s\n", bp->bp_file);
@@ -651,87 +652,27 @@ static void dhcp_reset_env(void)
if (!opt->barebox_var_name || opt->copy_only_if_valid)
continue;
- setenv(opt->barebox_var_name,"");
- if (opt->barebox_dhcp_global)
- dhcp_set_barebox_global(opt->barebox_dhcp_global,"");
- }
-}
-
-static void dhcp_global_add(const char *var)
-{
- char * var_global = asprintf("dhcp.%s", var);
-
- if (!var_global)
- return;
-
- globalvar_add_simple(var_global, NULL);
- free(var_global);
-}
-
-static int dhcp_global_init(void)
-{
- struct dhcp_opt *opt;
- struct dhcp_param *param;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
- opt = &dhcp_options[i];
-
- if (!opt->barebox_dhcp_global)
- continue;
-
- dhcp_global_add(opt->barebox_dhcp_global);
- }
-
- for (i = 0; i < ARRAY_SIZE(dhcp_params); i++) {
- param = &dhcp_params[i];
-
- if (!param->barebox_dhcp_global)
- continue;
-
- dhcp_global_add(param->barebox_dhcp_global);
+ if (IS_ENABLED(CONFIG_ENVIRONMENT_VARIABLES))
+ setenv(opt->barebox_var_name, "");
+ if (opt->barebox_dhcp_global && IS_ENABLED(CONFIG_GLOBALVAR))
+ dhcp_set_barebox_global(opt->barebox_dhcp_global, "");
}
-
- return 0;
}
-late_initcall(dhcp_global_init);
-static int do_dhcp(int argc, char *argv[])
+int dhcp(int retries, struct dhcp_req_param *param)
{
- int ret, opt;
- int retries = DHCP_DEFAULT_RETRY;
+ int ret = 0;
dhcp_reset_env();
- getenv_uint("global.dhcp.retries", &retries);
-
- while((opt = getopt(argc, argv, "H:v:c:u:U:r:")) > 0) {
- switch(opt) {
- case 'H':
- dhcp_set_param_data(DHCP_HOSTNAME, optarg);
- break;
- case 'v':
- dhcp_set_param_data(DHCP_VENDOR_ID, optarg);
- break;
- case 'c':
- dhcp_set_param_data(DHCP_CLIENT_ID, optarg);
- break;
- case 'u':
- dhcp_set_param_data(DHCP_CLIENT_UUID, optarg);
- break;
- case 'U':
- dhcp_set_param_data(DHCP_USER_CLASS, optarg);
- break;
- case 'r':
- retries = simple_strtoul(optarg, NULL, 10);
- break;
- }
- }
+ dhcp_set_param_data(DHCP_HOSTNAME, param->hostname);
+ dhcp_set_param_data(DHCP_VENDOR_ID, param->vendor_id);
+ dhcp_set_param_data(DHCP_CLIENT_ID, param->client_id);
+ dhcp_set_param_data(DHCP_USER_CLASS, param->user_class);
+ dhcp_set_param_data(DHCP_CLIENT_UUID, param->client_uuid);
- if (!retries) {
- printf("retries is set to zero, set it to %d\n", DHCP_DEFAULT_RETRY);
+ if (!retries)
retries = DHCP_DEFAULT_RETRY;
- }
dhcp_con = net_udp_new(0xffffffff, PORT_BOOTPS, dhcp_handler, NULL);
if (IS_ERR(dhcp_con)) {
@@ -781,29 +722,50 @@ out1:
net_unregister(dhcp_con);
out:
if (ret)
- printf("dhcp failed: %s\n", strerror(-ret));
+ debug("dhcp failed: %s\n", strerror(-ret));
return ret;
}
-BAREBOX_CMD_HELP_START(dhcp)
-BAREBOX_CMD_HELP_TEXT("Options:")
-BAREBOX_CMD_HELP_OPT ("-H HOSTNAME", "hostname to send to the DHCP server")
-BAREBOX_CMD_HELP_OPT ("-v ID\t", "DHCP Vendor ID (code 60) submitted in DHCP requests")
-BAREBOX_CMD_HELP_OPT ("-c ID\t", "DHCP Client ID (code 61) submitted in DHCP requests")
-BAREBOX_CMD_HELP_OPT ("-u UUID\t", "DHCP Client UUID (code 97) submitted in DHCP requests")
-BAREBOX_CMD_HELP_OPT ("-U CLASS", "DHCP User class (code 77) submitted in DHCP requests")
-BAREBOX_CMD_HELP_OPT ("-r RETRY", "retry limit (default 20)");
-BAREBOX_CMD_HELP_END
-
-BAREBOX_CMD_START(dhcp)
- .cmd = do_dhcp,
- BAREBOX_CMD_DESC("DHCP client to obtain IP or boot params")
- BAREBOX_CMD_OPTS("[-HvcuUr]")
- BAREBOX_CMD_GROUP(CMD_GRP_NET)
- BAREBOX_CMD_HELP(cmd_dhcp_help)
- BAREBOX_CMD_COMPLETE(empty_complete)
-BAREBOX_CMD_END
+#ifdef CONFIG_GLOBALVAR
+static void dhcp_global_add(const char *var)
+{
+ char *var_global = asprintf("dhcp.%s", var);
+
+ if (!var_global)
+ return;
+
+ globalvar_add_simple(var_global, NULL);
+ free(var_global);
+}
+
+static int dhcp_global_init(void)
+{
+ struct dhcp_opt *opt;
+ struct dhcp_param *param;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(dhcp_options); i++) {
+ opt = &dhcp_options[i];
+
+ if (!opt->barebox_dhcp_global)
+ continue;
+
+ dhcp_global_add(opt->barebox_dhcp_global);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(dhcp_params); i++) {
+ param = &dhcp_params[i];
+
+ if (!param->barebox_dhcp_global)
+ continue;
+
+ dhcp_global_add(param->barebox_dhcp_global);
+ }
+
+ return 0;
+}
+late_initcall(dhcp_global_init);
BAREBOX_MAGICVAR_NAMED(global_dhcp_bootfile, global.dhcp.bootfile, "bootfile returned from DHCP request");
BAREBOX_MAGICVAR_NAMED(global_dhcp_rootpath, global.dhcp.rootpath, "rootpath returned from DHCP request");
@@ -814,3 +776,4 @@ BAREBOX_MAGICVAR_NAMED(global_dhcp_user_class, global.dhcp.user_class, "user cla
BAREBOX_MAGICVAR_NAMED(global_dhcp_tftp_server_name, global.dhcp.tftp_server_name, "TFTP server Name returned from DHCP request");
BAREBOX_MAGICVAR_NAMED(global_dhcp_oftree_file, global.dhcp.oftree_file, "OF tree returned from DHCP request (option 224)");
BAREBOX_MAGICVAR_NAMED(global_dhcp_retries, global.dhcp.retries, "retry limit");
+#endif
diff --git a/net/dns.c b/net/dns.c
index 0a8ce8b244..0e16ea2c9d 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -116,9 +116,8 @@ static int dns_send(char *name)
return ret;
}
-static void dns_handler(void *ctx, char *packet, unsigned len)
+static void dns_recv(struct header *header, unsigned len)
{
- struct header *header;
unsigned char *p, *e, *s;
u16 type;
int found, stop, dlen;
@@ -127,7 +126,6 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
debug("%s\n", __func__);
/* We sent 1 query. We want to see more that 1 answer. */
- header = (struct header *)net_eth_to_udp_payload(packet);
if (ntohs(header->nqueries) != 1)
return;
@@ -140,7 +138,7 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
/* Skip host name */
s = &header->data[0];
- e = packet + len;
+ e = ((uint8_t *)header) + len;
for (p = s; p < e && *p != '\0'; p++)
continue;
@@ -194,6 +192,13 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
}
}
+static void dns_handler(void *ctx, char *packet, unsigned len)
+{
+ (void)ctx;
+ dns_recv((struct header *)net_eth_to_udp_payload(packet),
+ net_eth_to_udplen(packet));
+}
+
IPaddr_t resolv(char *host)
{
IPaddr_t ip;
diff --git a/net/eth.c b/net/eth.c
index 0c1ff73e4c..a090961bca 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -42,15 +42,27 @@ struct eth_ethaddr {
static LIST_HEAD(ethaddr_list);
+int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr)
+{
+ int ret;
+
+ ret = edev->set_ethaddr(edev, ethaddr);
+ if (ret)
+ return ret;
+
+ memcpy(edev->ethaddr, ethaddr, ETH_ALEN);
+
+ return 0;
+}
+
static void register_preset_mac_address(struct eth_device *edev, const char *ethaddr)
{
unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")];
- ethaddr_to_string(ethaddr, ethaddr_str);
-
if (is_valid_ether_addr(ethaddr)) {
+ ethaddr_to_string(ethaddr, ethaddr_str);
dev_info(&edev->dev, "got preset MAC address: %s\n", ethaddr_str);
- dev_set_param(&edev->dev, "ethaddr", ethaddr_str);
+ eth_set_ethaddr(edev, ethaddr);
}
}
@@ -261,13 +273,11 @@ int eth_rx(void)
return 0;
}
-static int eth_set_ethaddr(struct param_d *param, void *priv)
+static int eth_param_set_ethaddr(struct param_d *param, void *priv)
{
struct eth_device *edev = priv;
- edev->set_ethaddr(edev, edev->ethaddr);
-
- return 0;
+ return eth_set_ethaddr(edev, edev->ethaddr_param);
}
#ifdef CONFIG_OFTREE
@@ -350,7 +360,8 @@ int eth_register(struct eth_device *edev)
dev_add_param_ip(dev, "serverip", NULL, NULL, &edev->serverip, edev);
dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, edev);
dev_add_param_ip(dev, "netmask", NULL, NULL, &edev->netmask, edev);
- dev_add_param_mac(dev, "ethaddr", eth_set_ethaddr, NULL, edev->ethaddr, edev);
+ dev_add_param_mac(dev, "ethaddr", eth_param_set_ethaddr, NULL,
+ edev->ethaddr_param, edev);
if (edev->init)
edev->init(edev);
diff --git a/net/lib.c b/net/lib.c
new file mode 100644
index 0000000000..f1c60c9a74
--- /dev/null
+++ b/net/lib.c
@@ -0,0 +1,109 @@
+/*
+ * net.c - barebox networking support
+ *
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * based on U-Boot (LiMon) code
+ *
+ * Copyright 1994 - 2000 Neil Russell.
+ * Copyright 2000 Roland Borde
+ * Copyright 2000 Paolo Scaffardi
+ * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License 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 <net.h>
+#include <linux/ctype.h>
+
+int string_to_ethaddr(const char *str, u8 enetaddr[6])
+{
+ int reg;
+ char *e;
+
+ if (!str || strlen(str) != 17) {
+ memset(enetaddr, 0, 6);
+ return -EINVAL;
+ }
+
+ if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
+ str[11] != ':' || str[14] != ':')
+ return -EINVAL;
+
+ for (reg = 0; reg < 6; ++reg) {
+ enetaddr[reg] = simple_strtoul(str, &e, 16);
+ str = e + 1;
+ }
+
+ return 0;
+}
+
+void ethaddr_to_string(const u8 enetaddr[6], char *str)
+{
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
+ enetaddr[4], enetaddr[5]);
+}
+
+void print_IPaddr(IPaddr_t x)
+{
+ puts(ip_to_string(x));
+}
+
+char *ip_to_string(IPaddr_t x)
+{
+ static char s[sizeof("xxx.xxx.xxx.xxx")];
+
+ x = ntohl(x);
+ sprintf(s, "%d.%d.%d.%d",
+ (int) ((x >> 24) & 0xff),
+ (int) ((x >> 16) & 0xff),
+ (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
+ );
+
+ return s;
+}
+
+int string_to_ip(const char *s, IPaddr_t *ip)
+{
+ IPaddr_t addr = 0;
+ char *e;
+ int i;
+
+ if (!s)
+ return -EINVAL;
+
+ for (i = 0; i < 4; i++) {
+ unsigned long val;
+
+ if (!isdigit(*s))
+ return -EINVAL;
+
+ val = simple_strtoul(s, &e, 10);
+ if (val > 255)
+ return -EINVAL;
+
+ addr = (addr << 8) | val;
+
+ if (*e != '.' && i != 3)
+ return -EINVAL;
+
+ s = e + 1;
+ }
+
+ *ip = htonl(addr);
+
+ return 0;
+}
diff --git a/net/net.c b/net/net.c
index 07350ad8fb..e5bd9bbc78 100644
--- a/net/net.c
+++ b/net/net.c
@@ -62,50 +62,6 @@ uint16_t net_checksum(unsigned char *ptr, int len)
return xsum & 0xffff;
}
-char *ip_to_string (IPaddr_t x)
-{
- static char s[sizeof("xxx.xxx.xxx.xxx")];
-
- x = ntohl (x);
- sprintf (s, "%d.%d.%d.%d",
- (int) ((x >> 24) & 0xff),
- (int) ((x >> 16) & 0xff),
- (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
- );
- return s;
-}
-
-int string_to_ip(const char *s, IPaddr_t *ip)
-{
- IPaddr_t addr = 0;
- char *e;
- int i;
-
- if (!s)
- return -EINVAL;
-
- for (i = 0; i < 4; i++) {
- unsigned long val;
-
- if (!isdigit(*s))
- return -EINVAL;
-
- val = simple_strtoul(s, &e, 10);
- if (val > 255)
- return -EINVAL;
-
- addr = (addr << 8) | val;
-
- if (*e != '.' && i != 3)
- return -EINVAL;
-
- s = e + 1;
- }
-
- *ip = htonl(addr);
- return 0;
-}
-
IPaddr_t getenv_ip(const char *name)
{
IPaddr_t ip;
@@ -131,40 +87,6 @@ int setenv_ip(const char *name, IPaddr_t ip)
return 0;
}
-void print_IPaddr (IPaddr_t x)
-{
- puts(ip_to_string(x));
-}
-
-int string_to_ethaddr(const char *str, u8 enetaddr[6])
-{
- int reg;
- char *e;
-
- if (!str || strlen(str) != 17) {
- memset(enetaddr, 0, 6);
- return -EINVAL;
- }
-
- if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
- str[11] != ':' || str[14] != ':')
- return -EINVAL;
-
- for (reg = 0; reg < 6; ++reg) {
- enetaddr[reg] = simple_strtoul (str, &e, 16);
- str = e + 1;
- }
-
- return 0;
-}
-
-void ethaddr_to_string(const u8 enetaddr[6], char *str)
-{
- sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
- enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
- enetaddr[4], enetaddr[5]);
-}
-
static unsigned char *arp_ether;
static IPaddr_t arp_wait_ip;
@@ -348,7 +270,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler,
random_ether_addr(edev->ethaddr);
ethaddr_to_string(edev->ethaddr, str);
printf("warning: No MAC address set. Using random address %s\n", str);
- dev_set_param(&edev->dev, "ethaddr", str);
+ eth_set_ethaddr(edev, edev->ethaddr);
}
/* If we don't have an ip only broadcast is allowed */
@@ -667,4 +589,3 @@ static int net_init(void)
}
postcore_initcall(net_init);
-
diff --git a/net/nfs.c b/net/nfs.c
index 27533304ea..0a3021994a 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -731,4 +731,3 @@ BAREBOX_CMD_START(nfs)
BAREBOX_CMD_OPTS("FILE [LOCALFILE]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_END
-
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 6203589fe3..533bffd97d 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -24,3 +24,4 @@ bareboxstate-target
mk-am35xx-spi-image
mxsimage
mxsboot
+mxs-usb-loader
diff --git a/scripts/Makefile b/scripts/Makefile
index 74c22136db..a3f6222d08 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -24,6 +24,9 @@ HOSTLOADLIBES_mxsimage = `pkg-config --libs openssl`
HOSTCFLAGS_mxs-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_mxs-usb-loader = `pkg-config --libs libusb-1.0`
hostprogs-$(CONFIG_ARCH_MXS_USBLOADER) += mxs-usb-loader
+HOSTCFLAGS_omap3-usb-loader.o = `pkg-config --cflags libusb-1.0`
+HOSTLOADLIBES_omap3-usb-loader = `pkg-config --libs libusb-1.0`
+hostprogs-$(CONFIG_OMAP3_USB_LOADER) += omap3-usb-loader
subdir-y += mod
subdir-$(CONFIG_OMAP4_USBBOOT) += omap4_usbboot
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 57426d0302..e991f33691 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -388,10 +388,10 @@ quiet_cmd_ln = LN $@
cmd_ln = ln -sf $< $@
# Check size of a file
-quiet_cmd_check_file_size = CHKSIZE $@
+quiet_cmd_check_file_size = CHKSIZE $2
cmd_check_file_size = set -e; \
- size=`stat -c%s $@`; \
- max_size=`printf "%d" $2`; \
+ size=`stat -c%s $2`; \
+ max_size=`printf "%d" $3`; \
if [ $$size -gt $$max_size ] ; \
then \
echo "$@ size $$size > of the maximum size $$max_size" >&2; \
diff --git a/scripts/coccinelle/misc/altera_sequencer.cocci b/scripts/coccinelle/misc/altera_sequencer.cocci
index 9fea239c0c..2350e841c0 100644
--- a/scripts/coccinelle/misc/altera_sequencer.cocci
+++ b/scripts/coccinelle/misc/altera_sequencer.cocci
@@ -1,7 +1,8 @@
@r_shadow@
+type T;
@@
-- ...curr_shadow_reg = 0;
+- static T curr_shadow_reg = 0;
@r_out2_delay@
type T;
diff --git a/scripts/imx/Makefile b/scripts/imx/Makefile
index be0b490108..ee0acc1514 100644
--- a/scripts/imx/Makefile
+++ b/scripts/imx/Makefile
@@ -6,5 +6,7 @@ always := $(hostprogs-y)
HOSTCFLAGS_imx-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_imx-usb-loader = `pkg-config --libs libusb-1.0`
+HOSTCFLAGS_imx-image.o = -I$(srctree)
+
imx-usb-loader-objs := imx-usb-loader.o
imx-image-objs := imx-image.o
diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c
index 25ea4d8d1b..e765c1d3d6 100644
--- a/scripts/imx/imx-image.c
+++ b/scripts/imx/imx-image.c
@@ -27,6 +27,8 @@
#include <fcntl.h>
#include <endian.h>
+#include <include/filetype.h>
+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
#define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER)
#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y))
@@ -91,9 +93,12 @@ static int add_header_v1(void *buf, int offset, uint32_t loadaddr, uint32_t imag
{
struct imx_flash_header *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
+ uint32_t *psize = buf + ARM_HEAD_SIZE_OFFSET;
- if (add_barebox_header)
+ if (add_barebox_header) {
memcpy(buf, bb_header, sizeof(bb_header));
+ *psize = imagesize;
+ }
buf += offset;
hdr = buf;
@@ -177,6 +182,7 @@ static int add_header_v2(void *buf, int offset, uint32_t loadaddr, uint32_t imag
{
struct imx_flash_header_v2 *hdr;
int dcdsize = curdcd * sizeof(uint32_t);
+ uint32_t *psize = buf + ARM_HEAD_SIZE_OFFSET;
if (add_barebox_header)
memcpy(buf, bb_header, sizeof(bb_header));
@@ -201,6 +207,9 @@ static int add_header_v2(void *buf, int offset, uint32_t loadaddr, uint32_t imag
hdr->boot_data.size += CSF_LEN;
}
+ if (add_barebox_header)
+ *psize = hdr->boot_data.size;
+
hdr->dcd_header.tag = TAG_DCD_HEADER;
hdr->dcd_header.length = htobe16(sizeof(uint32_t) + dcdsize);
hdr->dcd_header.version = DCD_VERSION;
diff --git a/scripts/omap3-usb-loader.c b/scripts/omap3-usb-loader.c
new file mode 100644
index 0000000000..edf6043edf
--- /dev/null
+++ b/scripts/omap3-usb-loader.c
@@ -0,0 +1,921 @@
+/*
+ * OMAP Loader, a USB uploader application targeted at OMAP3 processors
+ * Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>
+ * Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*
+ * Reasons for the name change: this is a complete rewrite of
+ * the unversioned omap3_usbload so to lower ambiguity the name was changed.
+ * The GPLv2 license specifies rewrites as derived work.
+ */
+#define PROG_NAME "OMAP Loader"
+#define VERSION "1.0.0"
+
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define OMAP_IS_BIG_ENDIAN
+#endif
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#include <arpa/inet.h>
+#endif
+
+#include <unistd.h> /* for usleep and friends */
+#include <getopt.h>
+#include <errno.h>
+#include <libgen.h> /* for basename */
+
+#include <libusb-1.0/libusb.h> /* the main event */
+
+/* Device specific defines (OMAP)
+ * Primary source: http://www.ti.com/lit/pdf/sprugn4
+ * Section 26.4.5 "Peripheral Booting"
+ */
+#define OMAP_BASE_ADDRESS 0x40200000
+#define OMAP_PERIPH_BOOT 0xF0030002
+#define OMAP_VENDOR_ID 0x0451
+#define OMAP_PRODUCT_ID 0xD00E
+/* TODO: dynamically discover these endpoints */
+#define OMAP_USB_BULK_IN 0x81
+#define OMAP_USB_BULK_OUT 0x01
+#define OMAP_ASIC_ID_LEN 69
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#define cpu_to_le32(v) (((v & 0xff) << 24) | ((v & 0xff00) << 8) | \
+ ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24))
+#define le32_to_cpu(v) cpu_to_le32(v)
+#else
+#define cpu_to_le32(v) (v)
+#define le32_to_cpu(v) (v)
+#endif
+
+/*
+ * taken from x-loader/drivers/usb/usb.c
+ * All credit to Martin Mueller
+ */
+#define PACK4(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U','S','B','s') /* file size request */
+#define USBLOAD_CMD_FILE_REQ PACK4('U','S','B','f') /* file size resp */
+#define USBLOAD_CMD_JUMP PACK4('U','S','B','j') /* execute code here */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U','S','B','n') /* file size confirm to */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U','S','B','o') /* confirm full file */
+#define USBLOAD_CMD_MESSAGE PACK4('U','S','B','m') /* debug message */
+
+/* USB transfer characteristics */
+#define USB_MAX_WAIT 5000
+#define USB_TIMEOUT 1000
+#define USB_MAX_TIMEOUTS (USB_MAX_WAIT/USB_TIMEOUT)
+
+/* stores the data and attributes of a file to upload in to memory */
+struct file_upload {
+ size_t size;
+ void *data;
+ uint32_t addr;
+ char *path;
+ char *basename;
+};
+
+/* stores all of the arguments read in by getopt in main() */
+struct arg_state {
+ struct file_upload **files;
+ int numfiles;
+ uint32_t jumptarget;
+ uint16_t vendor, product;
+};
+
+static int g_verbose = 0;
+
+static void log_error(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[-] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static void log_info(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[+] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static bool omap_usb_read(libusb_device_handle *handle, unsigned char *data,
+ int length, int *actuallength)
+{
+ int ret = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ if (!actuallength)
+ return false;
+
+ while (sizeleft > 0) {
+ int actualread = 0;
+ int readamt = sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_IN, data + iter,
+ readamt, &actualread, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* we got some data, lets cut our losses and stop here */
+ if (iter > 0)
+ break;
+
+ log_error("device timed out while transfering in %d bytes (got %d)\n",
+ length, iter);
+
+ return false;
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualRead on anything but a timeout or success */
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* stop at the first sign of data */
+ if (iter > 0)
+ break;
+ } else {
+ log_error("fatal transfer error (BULK_IN) for %d bytes (got %d): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ *actuallength = iter;
+
+ return true;
+}
+
+static bool omap_usb_write(libusb_device_handle *handle, void *data, int length)
+{
+ int ret = 0;
+ int numtimeouts = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ while (sizeleft > 0) {
+ int actualwrite = 0;
+ int writeamt = sizeleft > 512 ? 512 : sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_OUT, data + iter,
+ writeamt, &actualwrite, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ numtimeouts++;
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+
+ /* build in some reliablity */
+ if (numtimeouts > USB_MAX_TIMEOUTS) {
+ log_error("device timed out while transfering out %d bytes (%d made it)\n",
+ length, iter);
+ return false;
+ }
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualWrite on anything but a timeout or success */
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+ } else {
+ log_error("fatal transfer error (BULK_OUT) for %d bytes (%d made it): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static unsigned char *omap_usb_get_string(libusb_device_handle *handle, uint8_t idx)
+{
+ unsigned char *data = NULL;
+ int len = 0;
+ int ret = 0;
+
+ if (!handle)
+ return NULL;
+
+ while (true) {
+ if (!len || ret < 0) {
+ len += 256;
+ data = realloc(data, len);
+
+ if (!data)
+ return NULL;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, idx, data, len);
+
+ /* we can still recover... */
+ if (ret < 0) {
+ if (ret == LIBUSB_ERROR_INVALID_PARAM)
+ continue; /* try again with an increased size */
+
+ log_error("failed to lookup string index %hhu: %s\n",
+ idx, libusb_error_name(ret));
+
+ /* unrecoverable */
+ free(data);
+ return NULL;
+ } else {
+ /* we got something! */
+ break;
+ }
+ }
+
+ return data;
+}
+
+uint16_t omap_products[] = {
+ 0xd009,
+ 0xd00f,
+};
+
+static libusb_device_handle *omap_usb_open(libusb_context *ctx, uint16_t vendor, uint16_t product)
+{
+ libusb_device **devlist;
+ libusb_device_handle *handle;
+ struct libusb_device_descriptor desc;
+ ssize_t count, i;
+ int ret;
+
+ log_info("scanning for USB device matching %04hx:%04hx...\n",
+ vendor, product);
+
+ while (1) {
+ if ((count = libusb_get_device_list(ctx, &devlist)) < 0) {
+ log_error("failed to gather USB device list: %s\n",
+ libusb_error_name(count));
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = libusb_get_device_descriptor(devlist[i], &desc);
+ if (ret < 0) {
+ log_error("failed to get USB device descriptor: %s\n",
+ libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ if (desc.idVendor != vendor)
+ continue;
+
+ if (product) {
+ if (desc.idProduct != product)
+ continue;
+ goto found;
+ }
+
+ for (i = 0; i < sizeof(omap_products) / sizeof(uint16_t); i++)
+ if (desc.idProduct == omap_products[i]) {
+ product = desc.idProduct;
+ goto found;
+ }
+ }
+
+ libusb_free_device_list(devlist, 1);
+
+ /* nothing found yet. have a 10ms nap */
+ usleep(10000);
+ }
+found:
+ ret = libusb_open(devlist[i], &handle);
+ if (ret < 0) {
+ log_error("failed to open USB device %04hx:%04hx: %s\n",
+ vendor, product, libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ ret = libusb_claim_interface(handle, 0);
+ if (ret) {
+ printf("Claim failed\n");
+ return NULL;
+ }
+
+ /* grab the manufacturer and product strings for printing */
+ unsigned char *mfgstr = omap_usb_get_string(handle, desc.iManufacturer);
+ unsigned char *prodstr = omap_usb_get_string(handle, desc.iProduct);
+
+ log_info("successfully opened %04hx:%04hx (", vendor, product);
+
+ if (mfgstr) {
+ fprintf(stdout, prodstr ? "%s " : "%s", mfgstr);
+ free(mfgstr);
+ }
+
+ if (prodstr) {
+ fprintf(stdout, "%s", prodstr);
+ free(prodstr);
+ }
+
+ fprintf(stdout, ")\n");
+
+ return handle;
+}
+
+static unsigned char *read_file(char *path, size_t *readamt)
+{
+ FILE *fp = fopen(path, "rb");
+
+ if (!fp) {
+ log_error("failed to open file \'%s\': %s\n", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ unsigned char *data = NULL;
+ size_t allocsize = 0;
+ size_t iter = 0;
+
+ while (1) {
+ if (iter >= iter) {
+ allocsize += 1024;
+ data = realloc(data, allocsize);
+ if (!data)
+ return NULL;
+ }
+
+ size_t readsize = allocsize - iter;
+ size_t ret = fread(data + iter, sizeof (unsigned char), readsize, fp);
+
+ iter += ret;
+
+ if (ret != readsize) {
+ if (feof(fp)) {
+ break;
+ } else if (ferror(fp)) {
+ log_error("error file reading file \'%s\': %s\n",
+ path, strerror(errno));
+ free(data);
+ return NULL;
+ }
+ }
+ }
+
+ /* trim the allocation down to size */
+ data = realloc(data, iter);
+ *readamt = iter;
+
+ return data;
+}
+
+static int transfer_first_stage(libusb_device_handle * handle, struct arg_state *args)
+{
+ unsigned char *buffer = NULL;
+ uint32_t cmd = 0;
+ uint32_t filelen = 0;
+ int bufsize = 0x200;
+ int transLen = 0;
+ int i;
+ void *data;
+ uint32_t *dbuf;
+
+ struct file_upload *file = args->files[0];
+
+ /* TODO determine buffer size based on endpoint */
+ buffer = calloc(bufsize, sizeof (unsigned char));
+ filelen = cpu_to_le32(file->size);
+
+ data = file->data;
+ dbuf = data;
+
+ if (le32toh(dbuf[5]) == 0x45534843) {
+ int chsettingssize = 512 + 2 * sizeof(uint32_t);
+
+ log_info("CHSETTINGS image detected. Skipping header\n");
+
+ data += chsettingssize;
+ filelen -= chsettingssize;
+ }
+
+ /* read the ASIC ID */
+ if (!omap_usb_read(handle, buffer, bufsize, &transLen)) {
+ log_error("failed to read ASIC ID from USB connection. "
+ "Check your USB device!\n");
+ goto fail;
+ }
+
+ if (transLen != OMAP_ASIC_ID_LEN) {
+ log_error("got some ASIC ID, but it's not the right length, %d "
+ "(expected %d)\n", transLen, OMAP_ASIC_ID_LEN);
+ goto fail;
+ }
+
+ /* optionally, print some ASIC ID info */
+ if (g_verbose) {
+ char *fields[] =
+ { "Num Subblocks", "Device ID Info", "Reserved",
+ "Ident Data", "Reserved", "CRC (4 bytes)"
+ };
+ int fieldLen[] = { 1, 7, 4, 23, 23, 11 };
+ int field = 0;
+ int nextSep = 0;
+
+ log_info("got ASIC ID - ");
+
+ for (i = 0; i < transLen; i++) {
+ if (i == nextSep) {
+ fprintf(stdout, "%s%s ",
+ (field > 0) ? ", " : "", fields[field]);
+ nextSep += fieldLen[field];
+ field++;
+
+ fprintf(stdout, "[");
+ }
+
+ fprintf(stdout, "%02x", buffer[i]);
+
+ if (i + 1 == nextSep)
+ fprintf(stdout, "]");
+ }
+
+ fprintf(stdout, "\n");
+ }
+
+ /* send the peripheral boot command */
+ cmd = cpu_to_le32(OMAP_PERIPH_BOOT);
+
+ if (!omap_usb_write(handle, (unsigned char *) &cmd, sizeof (cmd))) {
+ log_error("failed to send the peripheral boot command 0x%08x\n",
+ OMAP_PERIPH_BOOT);
+ goto fail;
+ }
+
+ /* send the length of the first file (little endian) */
+ if (!omap_usb_write
+ (handle, (unsigned char *) &filelen, sizeof (filelen))) {
+ log_error("failed to length specifier of %u to OMAP BootROM\n",
+ filelen);
+ goto fail;
+ }
+
+ /* send the file! */
+ if (!omap_usb_write(handle, data, filelen)) {
+ log_error("failed to send file \'%s\' (size %u)\n",
+ file->basename, filelen);
+ goto fail;
+ }
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int transfer_other_files(libusb_device_handle *handle, struct arg_state *args)
+{
+ uint32_t *buffer = NULL;
+ int bufsize = 128 * sizeof (*buffer);
+ int numfailures = 0; /* build in some reliablity */
+ int maxfailures = 3;
+ int transLen = 0;
+ int curfile = 1; /* skip the first file */
+ size_t len;
+
+ buffer = calloc(bufsize, sizeof(unsigned char));
+
+ /* handle the state machine for the X-Loader */
+ while (curfile < args->numfiles) {
+ uint32_t opcode = 0;
+ uint8_t *extra = NULL;
+ struct file_upload *f = args->files[curfile];
+
+ /* read the opcode from xloader ID */
+ if (!omap_usb_read
+ (handle, (unsigned char *) buffer, bufsize, &transLen)) {
+ numfailures++;
+
+ if (numfailures >= maxfailures) {
+ log_error("failed to read command from X-Loader\n");
+ goto fail;
+ }
+
+ /* sleep a bit */
+ usleep(2000 * 1000); /* 2s */
+ continue; /* try the opcode read again */
+ }
+
+ if (transLen < 8) {
+ log_error("failed to recieve enough data for the opcode\n");
+ goto fail;
+ }
+
+ /* extract the opcode and extra data pointer */
+ opcode = le32_to_cpu(buffer[0]);
+ extra = (uint8_t *)buffer;
+
+ switch (opcode) {
+ case USBLOAD_CMD_FILE_REQ:
+ /* X-loader is requesting a file to be sent */
+ /* send the opcode, size, and addr */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_FILE);
+ buffer[1] = cpu_to_le32(f->size);
+ buffer[2] = cpu_to_le32(f->addr);
+
+ if (!omap_usb_write(handle, (unsigned char *)buffer, sizeof(*buffer) * 3)) {
+ log_error("failed to send load file command to the X-loader\n");
+ goto fail;
+ }
+
+ if (g_verbose) {
+ log_info("uploading \'%s\' (size %zu) to 0x%08x\n",
+ f->basename, f->size, f->addr);
+ }
+
+ break;
+ case USBLOAD_CMD_ECHO_SZ:
+ /* X-loader confirms the size to recieve */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right file size for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ /* upload the raw file data */
+ if (!omap_usb_write(handle, f->data, f->size)) {
+ log_error
+ ("failed to send file \'%s\' to the X-loader\n",
+ f->basename);
+ goto fail;
+ }
+
+ break;
+ case USBLOAD_CMD_REPORT_SZ:
+ /* X-loader confirms the amount of data it recieved */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right amount of data for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ curfile++; /* move on to the next file */
+ break;
+ case USBLOAD_CMD_MESSAGE:
+ /* X-loader debug message */
+ len = strlen((char *)extra);
+
+ if (len > (bufsize - sizeof (opcode) - 1))
+ log_error("X-loader debug message not NUL terminated (size %zu)\n",
+ len);
+ else
+ fprintf(stdout, "X-loader Debug: %s\n", extra);
+ break;
+ default:
+ log_error("unknown X-Loader opcode 0x%08X (%c%c%c%c)\n",
+ opcode, extra[0], extra[1], extra[2],
+ extra[3]);
+ goto fail;
+ }
+ }
+
+ /* we're done uploading files to X-loader send the jump command */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_JUMP);
+ buffer[1] = cpu_to_le32(args->jumptarget);
+
+ if (!omap_usb_write
+ (handle, (unsigned char *) buffer, sizeof (*buffer) * 2)) {
+ log_error
+ ("failed to send the final jump command to the X-loader. "
+ "Target was 0x%08x\n", args->jumptarget);
+ goto fail;
+ }
+
+ if (g_verbose)
+ log_info("jumping to address 0x%08x\n", args->jumptarget);
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int process_args(struct arg_state *args)
+{
+ int i;
+
+ /* For each file, load it in to memory
+ * TODO: defer this until transfer time (save memory and pipeline IO)
+ */
+
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ f->data = read_file(f->path, &f->size);
+
+ if (!f->data) {
+ return 1;
+ }
+ }
+
+ if (g_verbose > 0) {
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ printf("File \'%s\' at 0x%08x, size %zu\n",
+ f->basename, f->addr, f->size);
+ }
+ }
+
+ libusb_context *ctx;
+ libusb_device_handle *dev;
+ int ret;
+
+ if ((ret = libusb_init(&ctx)) < 0) {
+ log_error("failed to initialize libusb context: %s\n",
+ libusb_error_name(ret));
+ return ret;
+ }
+
+ dev = omap_usb_open(ctx, args->vendor, args->product);
+
+ if (!dev) {
+ libusb_exit(ctx);
+ return 1;
+ }
+
+ /* Communicate with the TI BootROM directly
+ * - retrieve ASIC ID
+ * - start peripheral boot
+ * - upload first file
+ * - execute first file
+ */
+ if (!transfer_first_stage(dev, args)) {
+ log_error("failed to transfer the first stage file \'%s\'\n",
+ args->files[0]->basename);
+ goto fail;
+ }
+
+ /* Note: this is a race between the target's processor getting X-loader
+ * running and our processor. If we fail to communicate with the X-loader,
+ * it's possible that it hasn't been fully initialized. I'm not going to put
+ * some stupid, arbitrary sleep value here. The transfer_other_files function
+ * should be robust enough to handle some errors.
+ */
+
+ /* If we are passed one file, assume that the user just wants to
+ * upload some initial code with no X-loader chaining
+ */
+ if (args->numfiles > 1) {
+ if (!transfer_other_files(dev, args)) {
+ log_error
+ ("failed to transfer the additional files in to memory\n");
+ goto fail;
+ }
+ }
+
+ log_info("successfully transfered %d %s\n", args->numfiles,
+ (args->numfiles > 1) ? "files" : "file");
+
+ /* safely close our USB handle and context */
+ libusb_close(dev);
+ libusb_exit(ctx);
+ return 0;
+
+fail:
+ libusb_close(dev);
+ libusb_exit(ctx);
+
+ return 1;
+}
+
+/* getopt configuration */
+static int do_version = 0;
+static const char *const short_opt = "f:a:j:i:p:vh";
+static const struct option long_opt[] = {
+ {"file", 1, NULL, 'f'},
+ {"addr", 1, NULL, 'a'},
+ {"jump", 1, NULL, 'j'},
+ {"vendor", 1, NULL, 'i'},
+ {"product", 1, NULL, 'p'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"version", 0, &do_version, 1},
+ {NULL, 0, NULL, 0}
+};
+
+static void usage(char *exe)
+{
+ printf(
+"Usage: %s [options] -f first-stage [-f file -a addr]...\n"
+"Options:\n"
+" -f, --file Provide the filename of a binary file to be\n"
+" uploaded. The first file specified is uploaded to\n"
+" the fixed address 0x%08x as defined by the manual.\n"
+" Additional files must be followed by an address\n"
+" argument (-a).\n"
+" -a, --addr The address to load the prior file at.\n"
+" -j, --jump Specify the address to jump to after loading all\n"
+" of the files in to memory.\n"
+" -i, --vendor Override the default vendor ID to poll for\n"
+" (default 0x%04x).\n"
+" -p, --product Poll for specific product id. Default: All known OMAP chips\n"
+" -h, --help Display this message.\n"
+" -v, --verbose Enable verbose output.\n"
+"\n"
+"Description:\n"
+" %s's basic usage is to upload an arbitrary file in to the memory\n"
+" of a TI OMAP3 compatible processor. This program directly\n"
+" communicates with the TI BootROM in order to upload a first stage\n"
+" payload, in most cases, TI's X-Loader. Using a compatible X-Loader\n"
+" will enable the upload of any file to any part in device memory.\n"
+"\n"
+"Examples:\n"
+" Uploading a compatible X-Loader, U-Boot, Kernel, and RAMDisk, then jumping\n"
+" to the U-Boot image for further bootloading:\n"
+" %s -f x-load.bin -f u-boot.bin -a 0x80200000 -f uImage -a 0x80800000 \\\n"
+" -f uRamdisk -a 0x81000000 -j 0x80200000\n"
+" Uploading arbitrary code to be executed (doesn't have to be X-loader):\n"
+" %s -f exec_me.bin\n"
+" Trying to debug an upload issue using verbose output:\n"
+" %s -v -f exec_me.bin -f file1.bin -a 0xdeadbeef -j 0xabad1dea\n"
+"\n"
+"Authors:\n"
+" Grant Hernandez <grant.h.hernandez@gmail.com> - rewrite of omap3_usbload to\n"
+" use the newer libusb 1.0\n"
+" Martin Mueller <martinmm@pfump.org> - initial code (omap3_usbload)\n"
+" and X-Loader patch\n",
+ exe, OMAP_BASE_ADDRESS, OMAP_VENDOR_ID, PROG_NAME, exe, exe, exe
+ );
+}
+
+static void license(void)
+{
+ printf(
+"Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>\n"
+"Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.com>\n"
+"License GPLv2: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ bool gotfile = false;
+ bool gotjump = false;
+ int filecount = 0;
+ char *exe = NULL;
+
+ /* temporary local file object */
+ struct file_upload file;
+ /* total arg state */
+ struct arg_state *args = calloc(1, sizeof (*args));
+
+ if (argc < 1) {
+ log_error("invalid arguments (no argv[0])\n");
+ return 1;
+ }
+
+ exe = argv[0];
+
+ fprintf(stdout, "%s %s\n", PROG_NAME, VERSION);
+
+ /* set the default vendor and product */
+ args->vendor = OMAP_VENDOR_ID;
+ args->product = 0;
+
+ while ((opt = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
+ switch (opt) {
+ case 0:
+ if (do_version) {
+ license();
+ return 0;
+ }
+ break;
+ case 'f':
+ if (gotfile) {
+ log_error("missing address argument (-a) for file \'%s\'\n",
+ file.path);
+ usage(exe);
+ return 1;
+ }
+
+ file.path = strdup(optarg);
+
+ /* necessary to be sure that we own all the memory
+ and that the path input can be modified */
+ char *tmpPath = strdup(file.path);
+ file.basename = strdup(basename(tmpPath));
+ free(tmpPath);
+
+ filecount++;
+
+ /* the first file gets uploaded to a fixed address
+ as specified by the technical reference manual */
+ if (filecount == 1) {
+ file.addr = OMAP_BASE_ADDRESS;
+
+ /* commit the file object with the processor specified base address */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof (file));
+ memcpy(args->files[filecount - 1], &file, sizeof (file));
+ } else {
+ /* commit only after an address is specified */
+ gotfile = true;
+ }
+ break;
+ case 'a':
+ if (!gotfile) {
+ log_error
+ ("missing file argument (-f) before address \'%s\'\n",
+ optarg);
+ usage(exe);
+ return 1;
+ }
+
+ /* passing 0 to strtoul enables detection of the 0x prefix with
+ base-10 fallback if missing */
+ file.addr = strtoul(optarg, NULL, 0);
+
+ /* commit the file object */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof(file));
+ memcpy(args->files[filecount - 1], &file, sizeof(file));
+
+ gotfile = false;
+ break;
+ case 'j':
+ args->jumptarget = strtoul(optarg, NULL, 0);
+ gotjump = true;
+ break;
+ case 'i':
+ args->vendor = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ args->product = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ g_verbose++;
+ break;
+ case 'h':
+ usage(exe);
+ return 0;
+ default:
+ usage(exe);
+ return 1;
+ }
+ }
+
+ if (gotfile) {
+ log_error("got file \'%s\', but no address!\n", file.path);
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles <= 0) {
+ log_error("at least one file needs to be specified\n");
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles == 1 && gotjump) {
+ log_info
+ ("WARNING: jump target 0x%08x specified, but will never be taken "
+ "(more than one file required)\n", args->jumptarget);
+ } else if (args->numfiles > 1 && !gotjump) {
+ log_info
+ ("WARNING: no jump target specified. Defaulting to the first "
+ "file's (\'%s\') address 0x%08x\n",
+ args->files[1]->basename, args->files[1]->addr);
+ args->jumptarget = args->files[1]->addr;
+ }
+
+ return process_args(args);
+}
diff --git a/scripts/omap_signGP.c b/scripts/omap_signGP.c
index 482cfac925..ac47fdf089 100644
--- a/scripts/omap_signGP.c
+++ b/scripts/omap_signGP.c
@@ -317,8 +317,15 @@ int main(int argc, char *argv[])
if (fwrite(&config_header, 1, 512, ofile) <= 0)
pdie("fwrite");
+ /* The size field in the header needs to include the
+ * size of the gp_header */
+ len += sizeof(struct gp_header);
+
if (fwrite(&len, 1, 4, ofile) <= 0)
pdie("fwrite");
+
+ len -= sizeof(struct gp_header);
+
if (fwrite(&loadaddr, 1, 4, ofile) <= 0)
pdie("fwrite");
for (i = 0; i < len; i++) {
diff --git a/scripts/socfpga_get_sequencer b/scripts/socfpga_get_sequencer
index 5e4eb2d0c4..fb0ea6628b 100755
--- a/scripts/socfpga_get_sequencer
+++ b/scripts/socfpga_get_sequencer
@@ -49,6 +49,14 @@ copy_source() {
echo " Running coccinelle cleanups..."
spatch -sp_file scripts/coccinelle/misc/altera_sequencer.cocci -in_place arch/arm/mach-socfpga/include/mach
+
+ echo " Cleanup header..."
+ sed -i 's/^static void rw_mgr_mem_calibrate_eye_diag_aid(void);$//g' $tgt
+ sed -i 's/^static void rw_mgr_load_mrs_calib(void);$//g' $tgt
+ sed -i 's/^static void rw_mgr_load_mrs_exec(void);$//g' $tgt
+ sed -i 's/^static void scc_mgr_set_group_dqs_io_and_oct_out2_gradual(uint32_t write_group, uint32_t delay);$//g' $tgt
+ sed -i 's/^static void rw_mgr_incr_vfifo_auto(uint32_t grp);$//g' $tgt
+ sed -i 's/^static void rw_mgr_decr_vfifo_auto(uint32_t grp);$//g' $tgt
}
copy_source ${ubootsrc}/board/altera/socfpga/sdram/sequencer.c arch/arm/mach-socfpga/include/mach/sequencer.c
diff --git a/scripts/socfpga_sequencer_defines_defaults b/scripts/socfpga_sequencer_defines_defaults
index 19b12b1142..3ad1f588f6 100755
--- a/scripts/socfpga_sequencer_defines_defaults
+++ b/scripts/socfpga_sequencer_defines_defaults
@@ -33,6 +33,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define DYNAMIC_CALIBRATION_MODE 0
#define DISABLE_GUARANTEED_READ 0
+#define AP_MODE 0
+#define ADVANCED_ODT_CONTROL 0
#define ARRIAVGZ 0
#define ARRIAV 0
#define AVL_CLK_FREQ 67
@@ -56,6 +58,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define ENABLE_INST_ROM_WRITE 1
#define ENABLE_MARGIN_REPORT_GEN 0
#define ENABLE_NON_DESTRUCTIVE_CALIB 0
+#define ENABLE_NON_DES_CAL 0
+#define ENABLE_NON_DES_CAL_TEST 0
#define ENABLE_SUPER_QUICK_CALIBRATION 0
#define ENABLE_TCL_DEBUG 0
#define FAKE_CAL_FAIL 0