summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--Documentation/boards/davinci.rst51
-rw-r--r--Documentation/boards/digic.rst16
-rw-r--r--Documentation/boards/efi.rst298
-rw-r--r--Documentation/commands.rst86
-rwxr-xr-xDocumentation/gen_commands.py29
-rw-r--r--Documentation/glossary.rst3
-rw-r--r--Documentation/user/imd.rst54
-rw-r--r--Documentation/user/updating.rst3
-rw-r--r--Documentation/user/user-manual.rst1
-rw-r--r--Makefile11
-rw-r--r--README2
-rw-r--r--arch/arm/Kconfig11
-rw-r--r--arch/arm/Makefile11
-rw-r--r--arch/arm/boards/Makefile2
-rw-r--r--arch/arm/boards/at91sam9m10ihd/hw_version.c1
-rw-r--r--arch/arm/boards/at91sam9x5ek/hw_version.c1
-rw-r--r--arch/arm/boards/canon-a1100/Makefile1
-rw-r--r--arch/arm/boards/canon-a1100/lowlevel.c23
-rw-r--r--arch/arm/boards/crystalfontz-cfa10036/hwdetect.c1
-rw-r--r--arch/arm/boards/embedsky-e9/Makefile4
-rw-r--r--arch/arm/boards/embedsky-e9/board.c87
-rw-r--r--arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc16
-rw-r--r--arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc36
-rw-r--r--arch/arm/boards/embedsky-e9/defaultenv-e9/config-board7
-rw-r--r--arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg87
-rw-r--r--arch/arm/boards/embedsky-e9/lowlevel.c18
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/lowlevel.c1
-rw-r--r--arch/arm/boards/phytec-phycore-am335x/lowlevel.c115
-rw-r--r--arch/arm/boards/phytec-phyflex-imx6/lowlevel.c16
-rw-r--r--arch/arm/boards/sama5d3_xplained/init.c29
-rw-r--r--arch/arm/boards/sama5d3xek/hw_version.c1
-rw-r--r--arch/arm/boards/sama5d3xek/init.c29
-rw-r--r--arch/arm/boards/tqma53/lowlevel.c9
-rw-r--r--arch/arm/configs/am335x_defconfig83
-rw-r--r--arch/arm/configs/am335x_mlo_defconfig1
-rw-r--r--arch/arm/configs/canon-a1100_defconfig56
-rw-r--r--arch/arm/configs/imx_v7_defconfig1
-rw-r--r--arch/arm/cpu/Kconfig13
-rw-r--r--arch/arm/cpu/dtb.c1
-rw-r--r--arch/arm/cpu/mmu.c1
-rw-r--r--arch/arm/cpu/start.c6
-rw-r--r--arch/arm/dts/Makefile130
-rw-r--r--arch/arm/dts/am335x-bone-common.dtsi3
-rw-r--r--arch/arm/dts/am335x-phytec-phycore.dts7
-rw-r--r--arch/arm/dts/armada-370-mirabox-bb.dts3
-rw-r--r--arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts4
-rw-r--r--arch/arm/dts/canon-a1100.dts35
-rw-r--r--arch/arm/dts/digic4.dtsi42
-rw-r--r--arch/arm/dts/empty.c3
-rw-r--r--arch/arm/dts/imx6q-embedsky-e9.dts42
-rw-r--r--arch/arm/lib/barebox.lds.S2
-rw-r--r--arch/arm/lib/bootm.c21
-rw-r--r--arch/arm/lib/pbl.lds.S2
-rw-r--r--arch/arm/mach-at91/at91sam926x_lowlevel_init.c2
-rw-r--r--arch/arm/mach-at91/boot_test_cmd.c1
-rw-r--r--arch/arm/mach-at91/clock.c2
-rw-r--r--arch/arm/mach-at91/include/mach/at91sam9_smc.h33
-rw-r--r--arch/arm/mach-at91/sam9_smc.c38
-rw-r--r--arch/arm/mach-digic/Kconfig15
-rw-r--r--arch/arm/mach-digic/Makefile1
-rw-r--r--arch/arm/mach-digic/core.c25
-rw-r--r--arch/arm/mach-digic/include/mach/debug_ll.h40
-rw-r--r--arch/arm/mach-digic/include/mach/digic4.h23
-rw-r--r--arch/arm/mach-digic/include/mach/uart.h28
-rw-r--r--arch/arm/mach-imx/Kconfig6
-rw-r--r--arch/arm/mach-imx/esdctl.c4
-rw-r--r--arch/arm/mach-imx/imx-bbu-internal.c63
-rw-r--r--arch/arm/mach-mvebu/Kconfig2
-rw-r--r--arch/arm/mach-mvebu/armada-370-xp.c11
-rw-r--r--arch/arm/mach-mvebu/common.c59
-rw-r--r--arch/arm/mach-mvebu/dove.c6
-rw-r--r--arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h2
-rw-r--r--arch/arm/mach-mvebu/include/mach/common.h2
-rw-r--r--arch/arm/mach-mvebu/kirkwood.c5
-rw-r--r--arch/arm/mach-omap/Kconfig2
-rw-r--r--arch/arm/mach-omap/Makefile1
-rw-r--r--arch/arm/mach-omap/am33xx_generic.c56
-rw-r--r--arch/arm/mach-omap/am33xx_scrm.c51
-rw-r--r--arch/arm/mach-omap/include/mach/am33xx-silicon.h2
-rw-r--r--arch/arm/mach-omap/omap_generic.c1
-rw-r--r--arch/arm/mach-omap/xload.c1
-rw-r--r--arch/blackfin/boards/ipe337/cmd_alternate.c1
-rw-r--r--arch/efi/Kconfig52
-rw-r--r--arch/efi/Makefile41
-rw-r--r--arch/efi/configs/efi_defconfig78
-rw-r--r--arch/efi/efi/Makefile2
-rw-r--r--arch/efi/efi/clocksource.c60
-rw-r--r--arch/efi/efi/efi-block-io.c174
-rw-r--r--arch/efi/efi/efi-device.c349
-rw-r--r--arch/efi/efi/efi-image.c105
-rw-r--r--arch/efi/efi/efi.c343
-rw-r--r--arch/efi/efi/env-efi/network/eth0-discover5
-rw-r--r--arch/efi/include/asm/barebox.h1
-rw-r--r--arch/efi/include/asm/bitops.h22
-rw-r--r--arch/efi/include/asm/byteorder.h8
-rw-r--r--arch/efi/include/asm/common.h4
-rw-r--r--arch/efi/include/asm/dma.h13
-rw-r--r--arch/efi/include/asm/elf.h60
-rw-r--r--arch/efi/include/asm/io.h55
-rw-r--r--arch/efi/include/asm/posix_types.h93
-rw-r--r--arch/efi/include/asm/sections.h1
-rw-r--r--arch/efi/include/asm/string.h1
-rw-r--r--arch/efi/include/asm/swab.h6
-rw-r--r--arch/efi/include/asm/types.h73
-rw-r--r--arch/efi/include/asm/unaligned.h19
-rw-r--r--arch/efi/include/mach/debug_ll.h20
-rw-r--r--arch/efi/include/mach/efi-device.h45
-rw-r--r--arch/efi/include/mach/efi.h24
-rw-r--r--arch/efi/lib/.gitignore2
-rw-r--r--arch/efi/lib/Makefile4
-rw-r--r--arch/efi/lib/crt0-efi-ia32.S76
-rw-r--r--arch/efi/lib/crt0-efi-x86_64.S75
-rw-r--r--arch/efi/lib/elf_ia32_efi.lds.S102
-rw-r--r--arch/efi/lib/elf_x86_64_efi.lds.S93
-rw-r--r--arch/efi/lib/reloc_ia32.c97
-rw-r--r--arch/efi/lib/reloc_x86_64.c96
-rw-r--r--arch/mips/configs/qemu-malta_defconfig1
-rw-r--r--arch/mips/configs/ritmix-rzx50_defconfig6
-rw-r--r--arch/mips/dts/Makefile10
-rw-r--r--arch/mips/dts/rzx50.dts10
-rw-r--r--arch/mips/lib/barebox.lds.S2
-rw-r--r--arch/mips/lib/bootm.c1
-rw-r--r--arch/mips/pbl/zbarebox.lds.S2
-rw-r--r--commands/Kconfig13
-rw-r--r--commands/Makefile1
-rw-r--r--commands/barebox-update.c1
-rw-r--r--commands/cp.c1
-rw-r--r--commands/crc.c1
-rw-r--r--commands/dfu.c15
-rw-r--r--commands/edit.c12
-rw-r--r--commands/exec.c1
-rw-r--r--commands/help.c2
-rw-r--r--commands/i2c.c18
-rw-r--r--commands/imd.c60
-rw-r--r--commands/insmod.c1
-rw-r--r--commands/linux16.c1
-rw-r--r--commands/lspci.c2
-rw-r--r--commands/of_dump.c1
-rw-r--r--commands/oftree.c3
-rw-r--r--commands/readf.c1
-rw-r--r--commands/saveenv.c33
-rw-r--r--commands/tftp.c4
-rw-r--r--commands/trigger.c5
-rw-r--r--commands/ubiformat.c1
-rw-r--r--commands/uimage.c1
-rw-r--r--common/Kconfig15
-rw-r--r--common/Makefile6
-rw-r--r--common/block.c3
-rw-r--r--common/blspec.c1
-rw-r--r--common/bootm.c1
-rw-r--r--common/console.c39
-rw-r--r--common/efi-devicepath.c1370
-rw-r--r--common/efi-guid.c84
-rw-r--r--common/environment.c33
-rw-r--r--common/filetype.c17
-rw-r--r--common/hush.c1
-rw-r--r--common/imd-barebox.c25
-rw-r--r--common/imd.c322
-rw-r--r--common/memory.c2
-rw-r--r--common/menutree.c1
-rw-r--r--common/partitions/efi.c2
-rw-r--r--common/partitions/efi.h2
-rw-r--r--common/uimage.c1
-rw-r--r--drivers/bus/mvebu-mbus.c97
-rw-r--r--drivers/bus/omap-gpmc.c3
-rw-r--r--drivers/clocksource/Kconfig4
-rw-r--r--drivers/clocksource/Makefile1
-rw-r--r--drivers/clocksource/digic.c93
-rw-r--r--drivers/gpio/Kconfig24
-rw-r--r--drivers/gpio/Makefile2
-rw-r--r--drivers/gpio/gpio-digic.c180
-rw-r--r--drivers/gpio/gpio-pca953x.c481
-rw-r--r--drivers/i2c/Makefile2
-rw-r--r--drivers/i2c/busses/Kconfig12
-rw-r--r--drivers/i2c/busses/Makefile6
-rw-r--r--drivers/i2c/busses/i2c-at91.c437
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c647
-rw-r--r--drivers/i2c/i2c-smbus.c371
-rw-r--r--drivers/led/led-triggers.c4
-rw-r--r--drivers/mtd/nand/nand_omap_gpmc.c20
-rw-r--r--drivers/net/Kconfig4
-rw-r--r--drivers/net/Makefile1
-rw-r--r--drivers/net/efi-snp.c296
-rw-r--r--drivers/of/Kconfig8
-rw-r--r--drivers/of/Makefile1
-rw-r--r--drivers/of/of_pci.c27
-rw-r--r--drivers/of/partition.c4
-rw-r--r--drivers/of/platform.c3
-rw-r--r--drivers/pci/Kconfig6
-rw-r--r--drivers/pci/Makefile2
-rw-r--r--drivers/pci/pci-mvebu-phy.c208
-rw-r--r--drivers/pci/pci-mvebu.c446
-rw-r--r--drivers/pci/pci-mvebu.h37
-rw-r--r--drivers/pci/pci.c28
-rw-r--r--drivers/pinctrl/mvebu/Kconfig8
-rw-r--r--drivers/pinctrl/mvebu/Makefile2
-rw-r--r--drivers/pinctrl/mvebu/armada-370.c416
-rw-r--r--drivers/pinctrl/mvebu/armada-xp.c403
-rw-r--r--drivers/serial/Kconfig8
-rw-r--r--drivers/serial/Makefile2
-rw-r--r--drivers/serial/efi-stdio.c367
-rw-r--r--drivers/serial/serial_digic.c132
-rw-r--r--drivers/serial/serial_imx.c4
-rw-r--r--drivers/serial/serial_ns16550.c237
-rw-r--r--drivers/usb/gadget/dfu.c1
-rw-r--r--drivers/usb/gadget/u_serial.c7
-rw-r--r--dts/Bindings/arm/armada-38x.txt14
-rw-r--r--dts/Bindings/arm/exynos/power_domain.txt20
-rw-r--r--dts/Bindings/arm/l2cc.txt3
-rw-r--r--dts/Bindings/arm/samsung/exynos-adc.txt2
-rw-r--r--dts/Bindings/cpufreq/cpufreq-cpu0.txt6
-rw-r--r--dts/Bindings/hwmon/ntc_thermistor.txt20
-rw-r--r--dts/Bindings/serial/renesas,sci-serial.txt7
-rw-r--r--dts/Bindings/spi/qcom,spi-qup.txt6
-rw-r--r--dts/Bindings/vendor-prefixes.txt1
-rw-r--r--dts/include/dt-bindings/clock/exynos5420.h3
-rw-r--r--dts/include/dt-bindings/clock/imx6sl-clock.h3
-rw-r--r--dts/include/dt-bindings/clock/stih415-clks.h1
-rw-r--r--dts/include/dt-bindings/clock/stih416-clks.h1
-rw-r--r--dts/include/dt-bindings/pinctrl/dra.h7
-rw-r--r--dts/src/arm/am335x-evm.dts4
-rw-r--r--dts/src/arm/am335x-evmsk.dts4
-rw-r--r--dts/src/arm/am335x-igep0033.dtsi6
-rw-r--r--dts/src/arm/am43x-epos-evm.dts4
-rw-r--r--dts/src/arm/armada-380.dtsi2
-rw-r--r--dts/src/arm/armada-385-db.dts2
-rw-r--r--dts/src/arm/armada-385-rd.dts2
-rw-r--r--dts/src/arm/armada-385.dtsi2
-rw-r--r--dts/src/arm/armada-38x.dtsi2
-rw-r--r--dts/src/arm/at91sam9261.dtsi21
-rw-r--r--dts/src/arm/at91sam9261ek.dts4
-rw-r--r--dts/src/arm/at91sam9n12.dtsi6
-rw-r--r--dts/src/arm/at91sam9x5.dtsi10
-rw-r--r--dts/src/arm/dra7-evm.dts1
-rw-r--r--dts/src/arm/dra7.dtsi12
-rw-r--r--dts/src/arm/dra7xx-clocks.dtsi26
-rw-r--r--dts/src/arm/exynos4.dtsi4
-rw-r--r--dts/src/arm/exynos5420.dtsi5
-rw-r--r--dts/src/arm/hi3620.dtsi2
-rw-r--r--dts/src/arm/imx51-babbage.dts10
-rw-r--r--dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts4
-rw-r--r--dts/src/arm/imx53-m53evk.dts40
-rw-r--r--dts/src/arm/imx6dl-hummingboard.dts10
-rw-r--r--dts/src/arm/imx6q-embedsky-e9.dtsi395
-rw-r--r--dts/src/arm/imx6q-gw51xx.dts2
-rw-r--r--dts/src/arm/imx6qdl-cubox-i.dtsi27
-rw-r--r--dts/src/arm/imx6qdl-gw51xx.dtsi2
-rw-r--r--dts/src/arm/imx6qdl-gw52xx.dtsi4
-rw-r--r--dts/src/arm/imx6qdl-gw53xx.dtsi2
-rw-r--r--dts/src/arm/imx6qdl-microsom.dtsi13
-rw-r--r--dts/src/arm/imx6sl.dtsi2
-rw-r--r--dts/src/arm/kirkwood-guruplug-server-plus.dts4
-rw-r--r--dts/src/arm/omap3-beagle-xm.dts6
-rw-r--r--dts/src/arm/omap3-evm-common.dtsi7
-rw-r--r--dts/src/arm/omap3-n900.dts5
-rw-r--r--dts/src/arm/omap5.dtsi1
-rw-r--r--dts/src/arm/r8a7791.dtsi4
-rw-r--r--dts/src/arm/ste-nomadik-s8815.dts2
-rw-r--r--dts/src/arm/ste-nomadik-stn8815.dtsi7
-rw-r--r--dts/src/arm/stih415.dtsi8
-rw-r--r--dts/src/arm/stih416-b2020e.dts (renamed from dts/src/arm/stih416-b2020-revE.dts)0
-rw-r--r--dts/src/arm/stih416.dtsi8
-rw-r--r--fs/Kconfig15
-rw-r--r--fs/Makefile2
-rw-r--r--fs/efi.c563
-rw-r--r--fs/efivarfs.c340
-rw-r--r--fs/ext4/ext4_common.c17
-rw-r--r--fs/fat/fat.c4
-rw-r--r--fs/fs.c72
-rw-r--r--fs/uimagefs.c1
-rw-r--r--images/.gitignore2
-rw-r--r--images/Makefile2
-rw-r--r--images/Makefile.am33xx14
-rw-r--r--images/Makefile.imx10
-rw-r--r--include/asm-generic/barebox.lds.h6
-rw-r--r--include/block.h1
-rw-r--r--include/console.h3
-rw-r--r--include/efi.h621
-rw-r--r--include/envfs.h3
-rw-r--r--include/filetype.h3
-rw-r--r--include/fs.h14
-rw-r--r--include/i2c/i2c.h57
-rw-r--r--include/image-metadata.h117
-rw-r--r--include/libbb.h7
-rw-r--r--include/libfile.h18
-rw-r--r--include/linux/efi.h547
-rw-r--r--include/linux/kernel.h23
-rw-r--r--include/linux/mbus.h2
-rw-r--r--include/linux/pci.h12
-rw-r--r--include/of_pci.h17
-rw-r--r--include/param.h2
-rw-r--r--include/platform_data/pca953x.h27
-rw-r--r--include/wchar.h18
-rw-r--r--lib/Kconfig3
-rw-r--r--lib/Makefile3
-rw-r--r--lib/bootstrap/disk.c1
-rw-r--r--lib/copy_file.c86
-rw-r--r--lib/gui/image_renderer.c1
-rw-r--r--lib/libbb.c93
-rw-r--r--lib/libfile.c331
-rw-r--r--lib/misc.c3
-rw-r--r--lib/readkey.c2
-rw-r--r--lib/vsprintf.c62
-rw-r--r--lib/wchar.c80
-rw-r--r--net/netconsole.c1
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.lib25
-rw-r--r--scripts/bareboxenv.c10
-rw-r--r--scripts/bareboximd.c161
-rwxr-xr-xscripts/canon-a1100-image10
-rwxr-xr-xscripts/checkpatch.pl2
-rw-r--r--scripts/dtc/.gitignore1
-rw-r--r--scripts/dtc/Makefile18
-rw-r--r--scripts/dtc/fdt.c (renamed from scripts/dtc/libfdt/fdt.c)0
-rw-r--r--scripts/dtc/fdt.h (renamed from scripts/dtc/libfdt/fdt.h)0
-rw-r--r--scripts/dtc/fdt_empty_tree.c (renamed from scripts/dtc/libfdt/fdt_empty_tree.c)0
-rw-r--r--scripts/dtc/fdt_ro.c (renamed from scripts/dtc/libfdt/fdt_ro.c)0
-rw-r--r--scripts/dtc/fdt_rw.c (renamed from scripts/dtc/libfdt/fdt_rw.c)0
-rw-r--r--scripts/dtc/fdt_strerror.c (renamed from scripts/dtc/libfdt/fdt_strerror.c)0
-rw-r--r--scripts/dtc/fdt_sw.c (renamed from scripts/dtc/libfdt/fdt_sw.c)0
-rw-r--r--scripts/dtc/fdt_wip.c (renamed from scripts/dtc/libfdt/fdt_wip.c)0
-rw-r--r--scripts/dtc/libfdt.h (renamed from scripts/dtc/libfdt/libfdt.h)0
-rw-r--r--scripts/dtc/libfdt_env.h (renamed from scripts/dtc/libfdt/libfdt_env.h)0
-rw-r--r--scripts/dtc/libfdt_internal.h (renamed from scripts/dtc/libfdt/libfdt_internal.h)0
-rwxr-xr-xscripts/gen-dtb-s56
326 files changed, 14148 insertions, 1457 deletions
diff --git a/.gitignore b/.gitignore
index 135fdeb630..a62e08c730 100644
--- a/.gitignore
+++ b/.gitignore
@@ -46,6 +46,8 @@ barebox.uimage
barebox.map
barebox.kwb
barebox.kwbuart
+barebox.efi
+barebox.canon-a1100.bin
barebox-flash-image
System.map
Module.symvers
@@ -66,7 +68,6 @@ include/linux/compile.h
include/generated
# Generated files
-Doxyfile.version
Documentation/commands/*.rst
doctrees/
diff --git a/Documentation/boards/davinci.rst b/Documentation/boards/davinci.rst
new file mode 100644
index 0000000000..a2ddc3c41f
--- /dev/null
+++ b/Documentation/boards/davinci.rst
@@ -0,0 +1,51 @@
+TI Davinci
+==========
+
+virt2real
+---------
+
+virt2real is a miniature board for creation of WiFi
+or Internet controllable smart devices.
+
+The board has
+
+ * TI DaVinchi DM365 running at 300 MHz;
+ * 128 MiB DDR2 SDRAM;
+ * 256 MiB NAND Flash Memory;
+ * 2 x UART serial interfaces;
+ * 1 x Ethernet interface (Micrel KS8851);
+ * 1 x USB interface;
+ * microSD card slot.
+
+The board uses U-Boot as bootloader.
+
+
+Running barebox
+^^^^^^^^^^^^^^^
+
+ 1. Connect to the boards's UART0 (115200 8N1);
+ Use J2.2 (GND), J2.4 (UART0_TXD), J2.6 (UART0_RXD) pins.
+
+ 2. Turn board's power on;
+
+ 3. Wait for ``Hit any key to stop autoboot`` prompt and press the space key.
+
+ 4. Upload ``barebox.bin`` via Ymodem
+
+.. code-block:: none
+ virt2real ># loady
+..
+
+ 5. Run barebox
+
+.. code-block:: none
+ virt2real ># go 0x82000000
+..
+
+
+Links
+^^^^^
+
+ * http://virt2real.com/
+ * http://wiki.virt2real.ru/
+ * https://github.com/virt2real
diff --git a/Documentation/boards/digic.rst b/Documentation/boards/digic.rst
new file mode 100644
index 0000000000..e2c49b6514
--- /dev/null
+++ b/Documentation/boards/digic.rst
@@ -0,0 +1,16 @@
+Canon DIGIC
+===========
+
+Canon PowerShot A1100 IS
+------------------------
+
+Running barebox on QEMU
+^^^^^^^^^^^^^^^^^^^^^^^
+
+QEMU supports Canon A1100 camera emulation since version 2.0.
+
+Usage::
+
+ $ qemu-system-arm -M canon-a1100 \
+ -nographic -monitor null -serial stdio \
+ -bios barebox.canon-a1100.bin
diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst
new file mode 100644
index 0000000000..2147cb63db
--- /dev/null
+++ b/Documentation/boards/efi.rst
@@ -0,0 +1,298 @@
+barebox on (U)EFI
+=================
+
+barebox can be built as an EFI application for X86 PCs. This makes
+barebox a bootloader running on PC type hardware. In EFI jargon barebox
+would be a EFI shell. Due to the barebox :ref:`bootloader_spec` support
+it can act as a replacement for gummiboot.
+
+For accessing hardware the EFI drivers and abstractions are used. barebox
+has several drivers which merely map to the underlying EFI layers. A plain
+barebox binary provides access to the screen and keyboard. The EFI System
+partition (:term:`ESP`) is available under ``/boot``, additional partitions may
+be available as ``/efi*``. Networking may be available if the BIOS provides
+the necessary drivers, but most likely you'll have to download/compile
+network drivers yourself, see below.
+
+Depending on the ``CONFIG_64BIT`` option either a ia32 binary or a x86_64
+binary is built. Due to the lack of 32bit UEFI testing hardware only the
+x86_64 binary currently is tested.
+
+Building barebox for EFI
+------------------------
+
+Use the following to build barebox for EFI:
+
+.. code-block:: sh
+
+ export ARCH=efi
+ make efi_defconfig
+ make
+
+The resulting EFI image is ``barebox.efi`` (or the barebox-flash-image link).
+
+Running barebox on EFI systems
+------------------------------
+
+The simplest way to run barebox on a USB memory stick. (U)EFI only supports
+FAT filesystems, so make sure you either have a FAT16 or FAT32 filesystem on
+the memory stick. Put ``barebox.efi`` into the ``EFI/BOOT/`` directory and
+name it ``BOOTx64.EFI`` on 64bit architectures and ``BOOTIA32.EFI`` on 32bit
+architectures. Switching to USB boot in the BIOS should then be enough to
+start barebox via USB. Some BIOSes allow to specify a path to a binary to
+be executed, others have a "start UEFI shell" entry which executes
+EFI/Shellx64.efi on the :term:`ESP`. This can be a barebox binary aswell.
+
+Running EFI barebox on qemu
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+barebox can be started in qemu with OVMF http://www.linux-kvm.org/page/OVMF.
+
+OVMF is part of several distributions and can be installed with the package
+management system. qemu needs the OVMF.fd from the OVMF package file as
+argument to the -pflash option. As qemu needs write access to that file it's
+necessary to make a copy first.
+
+To start it create a USB memory stick like above and execute:
+
+.. code-block:: sh
+
+ qemu-system-x86_64 -pflash OVMF.fd -nographic /dev/sdx
+
+A plain VFAT image will work aswell, but in this case the UEFI BIOS won't
+recognize it as ESP and ``/boot`` won't be mounted.
+
+Loading EFI applications
+------------------------
+
+EFI supports loading applications aswell as drivers. barebox does not differentiate
+between both. Both types can be simply executed by typing the path on the command
+line. When an application/driver returns barebox iterates over the handle database
+and will initialize all new devices.
+
+Applications
+^^^^^^^^^^^^
+
+barebox itself and also the Linux Kernel are EFI applications. This means both
+can be directly executed. On other architectures when barebox is executed from
+another barebox it means the barebox binary will be replaced. EFI behaves
+differently, here different barebox instances will be nested, so exiting barebox
+means passing control to the calling instance. Note that currently the :ref:`command_reset`
+command will pass the control to the calling instance rather than resetting
+the CPU. This may change in the future.
+
+Although the Linux Kernel can be directly executed one should use the :ref:`command_bootm`
+command. Only the bootm command passes the Kernel commandline to the Kernel.
+
+Drivers
+^^^^^^^
+
+EFI is modular and drivers can be loaded during runtime. Many drivers are
+included in the BIOS already, but some have to be loaded during runtime,
+for example it's common that network drivers are not included in the BIOS.
+
+Drivers can be loaded under barebox simply by executing them:
+
+.. code-block:: sh
+
+ barebox:/ /boot/network-drivers/0001-SnpDxe.efi
+
+Should the drivers instanciate new devices these are automatically registered
+after the driver has been loaded.
+
+Simple Network Protocol (SNP)
+-----------------------------
+
+The Simple Network Protocol provides a raw packet interface to the EFI
+network drivers. Each device which supports SNP shows up as a regular
+network device under barebox. To use SNP the BIOS must have the SNP
+protocol and the network driver installed. For getting the SNP protocol
+follow the instruction in :ref:`efi_building_edk2`. Network drivers for
+the common Intel Network devices can be found here:
+
+https://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=19186
+
+Once instantiated the EFI drivers take some time to bring up the link, so
+it's best to only load the network drivers when needed. This can be
+archieved with the following script to put under ``/env/network/eth0-discover``:
+
+.. code-block:: sh
+
+ #!/bin/sh
+
+ for i in /boot/network-drivers/*; do
+ $i;
+ done
+
+This script will load the drivers in ``/boot/network-drivers/`` in alphabetical
+order.
+
+**NOTE** Loading the network drivers only works when loaded in the
+correct order. First the SNP driver must be loaded and then the network device
+driver. Otherwise the drivers will load without errors, but no devices will be
+instantiated. For making the order sure the driver names can be prepended with
+a number:
+
+.. code-block:: sh
+
+ /boot/network-drivers/0001-SnpDxe.efi
+ /boot/network-drivers/0002-E6208X3.EFI
+
+It is currently not known whether this is a limitation in EFI or a bug in
+barebox.
+
+EFI File IO Interface
+---------------------
+
+EFI itself has filesystem support. At least the :term:`ESP` will be mounted by the
+EFI core already. The :term:`ESP` is mounted to ``/boot`` under barebox, other devices
+are mounted to ``/efi<no>`` in no particular order.
+
+Block IO Protocol
+-----------------
+
+EFI provides access to block devices with the Block IO Protocol. This can
+be used to access raw block devices under barebox and also to access filesystems
+not supported by EFI. The block devices will show up as ``/dev/disk<diskno>.<partno>``
+under barebox and can be accessed like any other device:
+
+.. code-block:: sh
+
+ mount /dev/disk0.1 -text4 /mnt
+
+Care must be taken that a partition is only accessed either via the Block IO Protocol *or*
+the File IO Interface. Doing both at the same time will most likely result in data
+corruption on the partition
+
+EFI device pathes
+-----------------
+
+In EFI each device can be pointed to using a device path. Device pathes have multiple
+components. The toplevel component on X86 systems will be the PCI root complex, on
+other systems this can be the physical memory space. Each component will now descrive
+how to find the child component on the parent bus. Additional device path nodes can
+describe network addresses or filenames on partitions. Device pathes have a binary
+representation and a clearly defined string representation. These characteristics make
+device pathes suitable for describing boot entries. barebox could use device pathes
+to store the reference to kernels on boot media. Also device pathes could be used to
+pass a root filesystem to the Kernel.
+
+Currently device pathes are only integrated into barebox in a way that each EFI device
+has a device parameter ``devpath`` which contains its device path:
+
+.. code-block:: sh
+
+ barebox:/ echo ${handle-00000000d0012198.devpath}
+ pci_root(0)/Pci(0x1d,0x0)/Usb(0x1,0x0)/Usb(0x2,0x0)
+
+
+EFI variables
+-------------
+
+EFI has support for variables which are exported via the EFI Variable Services. EFI variables
+are identified by a 64bit GUID and a name. EFI variables can have arbitrary binary values, so
+they are not compatible with barebox shell variables which can only have printable content.
+Support for these variables is not yet complete in barebox. barebox contains the efivarfs which
+has the same format as the Linux Kernels efivarfs. It can be mounted with:
+
+.. code-block:: sh
+
+ mkdir efivarfs
+ mount -tefivarfs none /efivarfs
+
+In efivarfs each variable is represented by a file named <varname>-<guid>. Access to EFI variables
+is currently readonly. Since the variables have binary content using :ref:`command_md` is often
+more suitable than :ref:`command_cat`.
+
+EFI driver model and barebox
+----------------------------
+
+The EFI driver model is based around handles and protocols. A handle is an opaque
+cookie that represents a hardware device or a software object. Each handle can have
+multiple protocols attached to it. A protocol is a callable interface and is defined
+by a C struct containing function pointers. A protocol is identified by a 64bit GUID.
+Common examples for protocols are DEVICE_PATH, DEVICE_IO, BLOCK_IO, DISK_IO,
+FILE_SYSTEM, SIMPLE_INPUT or SIMPLE_TEXT_OUTPUT. Every handle that implements the
+DEVICE_PATH protocol is registered as device in barebox. The structure can be best
+seen in the ``devinfo`` output of such a device:
+
+.. code-block:: sh
+
+ barebox:/ devinfo handle-00000000cfaed198
+ Driver: efi-snp
+ Bus: efi
+ Protocols:
+ 0: a19832b9-ac25-11d3-9a2d-0090273fc14d
+ 1: 330d4706-f2a0-4e4f-a369-b66fa8d54385
+ 2: e5dd1403-d622-c24e-8488-c71b17f5e802
+ 3: 34d59603-1428-4429-a414-e6b3b5fd7dc1
+ 4: 0e1ad94a-dcf4-11db-9705-00e08161165f
+ 5: 1aced566-76ed-4218-bc81-767f1f977a89
+ 6: e3161450-ad0f-11d9-9669-0800200c9a66
+ 7: 09576e91-6d3f-11d2-8e39-00a0c969723b
+ 8: 51dd8b21-ad8d-48e9-bc3f-24f46722c748
+ Parameters:
+ devpath: pci_root(0)/Pci(0x1c,0x3)/Pci(0x0,0x0)/Mac(e03f4914f157)
+
+The protocols section in the output shows the different protocols this
+handle implements. One of this Protocols (here the first) is the Simple
+Network Protocol GUID:
+
+.. code-block:: c
+
+ #define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
+ EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D )
+
+Matching between EFI devices and drivers is done based on the Protocol GUIDs, so
+whenever a driver GUID matches one of the GUIDs a device imeplements the drivers
+probe function is called.
+
+.. _efi_building_edk2:
+
+Building EDK2
+-------------
+
+Additional drivers may be needed from the EDK2 package. For example to
+use Networking in barebox not only the network device drivers are needed,
+but also the Simple Network Protocol driver, SnpDxe.efi. This is often
+not included in the BIOS, but can be compiled from the EDK2 package.
+
+Here is only a quick walkthrough for building edk2, there are more elaborated
+HOWTOs in the net, for example on http://tianocore.sourceforge.net/wiki/Using_EDK_II_with_Native_GCC.
+
+.. code-block:: sh
+
+ git clone git://github.com/tianocore/edk2.git
+ cd edk2
+ make -C BaseTools
+ . edksetup.sh
+
+At least the following lines in ``Conf/target.txt`` should be edited::
+
+ ACTIVE_PLATFORM = MdeModulePkg/MdeModulePkg.dsc
+ TARGET_ARCH = X64
+ TOOL_CHAIN_TAG = GCC48
+ MAX_CONCURRENT_THREAD_NUMBER = 4
+
+The actual build is started with invoking ``build``. After building
+``Build/MdeModule/DEBUG_GCC48/X64/SnpDxe.efi`` should exist.
+
+**NOTE** As of this writing (July 2014) the following patch was needed to
+compile EDK2.
+
+.. code-block:: diff
+
+ diff --git a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ index 9783ec6..13fc06c 100644
+ --- a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ +++ b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S
+ @@ -280,7 +280,7 @@ ExtraPushDone:
+
+ mov %ds, %rax
+ pushq %rax
+ - movw %es, %rax
+ + mov %es, %rax^M
+ pushq %rax
+ mov %fs, %rax
+ pushq %rax
+
diff --git a/Documentation/commands.rst b/Documentation/commands.rst
index 55b04f6e56..261af2a078 100644
--- a/Documentation/commands.rst
+++ b/Documentation/commands.rst
@@ -1,9 +1,91 @@
Command reference
=================
+Information
+-----------
.. toctree::
+ :titlesonly:
:glob:
- :maxdepth: 1
- commands/*
+ commands/info/*
+
+Booting
+-------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/boot/*
+
+Partitions and Filesystems
+--------------------------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/part/*
+
+Environment
+-----------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/env/*
+
+Files
+-----
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/file/*
+
+Shell Scripting
+---------------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/script/*
+
+Console and Framebuffer
+-----------------------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/console/*
+
+Memory
+------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/mem/*
+
+Hardware Manipulation
+---------------------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/hwmanip/*
+
+Miscellaneous
+-------------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/misc/*
+
+Networking
+----------
+.. toctree::
+ :titlesonly:
+ :glob:
+
+ commands/net/*
diff --git a/Documentation/gen_commands.py b/Documentation/gen_commands.py
index 4e33ccaea6..b85e2e3eab 100755
--- a/Documentation/gen_commands.py
+++ b/Documentation/gen_commands.py
@@ -1,8 +1,10 @@
#!/usr/bin/python
+import errno
import os
import re
import sys
+import hashlib
from collections import defaultdict
from pprint import pprint
@@ -76,7 +78,7 @@ def parse_c(name):
x = CMD_GROUP.match(line)
if x:
last = cmd['c_group']
- last.append(x.group(1).decode("string_escape"))
+ last.append(x.group(1).split('_')[-1].lower())
continue
x = CONT.match(line)
if x:
@@ -101,7 +103,7 @@ def gen_rst(name, cmd):
out.append('.. _command_%s:' % name)
out.append('')
if 'c_desc' in cmd:
- out.append("%s (%s)" % (name, ''.join(cmd['c_desc']).strip()))
+ out.append("%s - %s" % (name, ''.join(cmd['c_desc']).strip()))
else:
out.append("%s" % (name,))
out.append('='*len(out[-1]))
@@ -159,6 +161,27 @@ for name in CMDS.keys():
for name, cmd in CMDS.items():
#pprint({name: cmd})
rst = gen_rst(name, cmd)
- target = os.path.join(sys.argv[2], name+'.rst')
+ subdir = os.path.join(sys.argv[2], cmd['c_group'][0])
+ try:
+ os.makedirs(subdir)
+ except OSError as e:
+ if e.errno == errno.EEXIST and os.path.isdir(subdir):
+ pass
+ else:
+ raise
+ target = os.path.join(subdir, name+'.rst')
+
+ # Only write the new rst if it differs from the old one. Wroto
+ hash_old = hashlib.sha1()
+ try:
+ f = open(target, 'rb')
+ hash_old.update(f.read())
+ except:
+ pass
+ hash_new = hashlib.sha1()
+ hash_new.update(rst)
+ if hash_old.hexdigest() == hash_new.hexdigest():
+ continue
+
file(target, 'w').write(rst)
diff --git a/Documentation/glossary.rst b/Documentation/glossary.rst
index 8bad7dc6e8..106dce98a9 100644
--- a/Documentation/glossary.rst
+++ b/Documentation/glossary.rst
@@ -16,3 +16,6 @@ Glossary
PBL
Pre BootLoader image
+
+ ESP
+ EFI System Partition
diff --git a/Documentation/user/imd.rst b/Documentation/user/imd.rst
new file mode 100644
index 0000000000..e0251d644e
--- /dev/null
+++ b/Documentation/user/imd.rst
@@ -0,0 +1,54 @@
+
+.. _imd:
+
+Image MetaData (IMD)
+====================
+
+barebox images can be enriched with metadata. This is useful to get information
+the board an image is compiled for and which barebox version an image contains.
+
+There are predefined tags for:
+
+- The build timestamp
+- The barebox release version
+- The model (board) the image is compiled for
+- The toplevel device tree compatible properties the image can handle
+
+Additionally there is a generic key/value tag to add information which does not
+fit into the above categories, for example the memory size for boards which come
+with different memory sizes which can't be automatically detected.
+
+The informations can be extracted with the ``bareboximd`` tool which lives under
+``scripts/`` in the barebox sourcecode. If enabled it is compiled for the compile
+host and also for the target architecture. barebox itself has the :ref:`command_imd`
+command to extract the informations. Here is an example output of the tool called
+without additional options::
+
+ # imd barebox-phytec-pbab01dl-1gib.img
+ build: #890 Wed Jul 30 16:15:24 CEST 2014
+ release: 2014.07.0-00167-ge6632a9-dirty
+ parameter: memsize=1024
+ of_compatible: phytec,imx6x-pbab01 phytec,imx6dl-pfla02 fsl,imx6dl
+ model: Phytec phyFLEX-i.MX6 Duallite Carrier-Board
+
+Single informations can be extracted with the ``-t <type>`` option::
+
+ # imd barebox-phytec-pbab01dl-1gib.img -t release
+ 2014.07.0-00167-ge6632a9-dirty
+
+Since the barebox hush does not have output redirection the barebox too has the
+``-s <var>`` option to assign the output to a variable for later evaluation.
+
+Limitations
+-----------
+
+The IMD tags are generated in the barebox binary before a SoC specific image is
+generated. Some SoCs encrypt or otherwise manipulate the images in a way that the
+IMD information is lost. The IMD mechanism does not work on these SoCs. A known
+example is the Freescale i.MX28.
+
+IMD and barebox_update
+----------------------
+
+The IMD informations could well be used to check if an image is suitable for updating
+barebox for a particular board. Support for such a check is planned but not yet implemented.
diff --git a/Documentation/user/updating.rst b/Documentation/user/updating.rst
index 2a963b6200..6a1a73348c 100644
--- a/Documentation/user/updating.rst
+++ b/Documentation/user/updating.rst
@@ -27,3 +27,6 @@ barebox has been started from is registered as default (marked with a ``*``)::
available for your board. It is recommended to implement it, but you can also
update barebox manually using :ref:`command_erase` and :ref:`command_cp`
commands. The exact commands are board specific.
+
+**NOTE** barebox images can be enriched with metadata which can be used to check
+if a given image is suitable for updating barebox, see :ref:`imd`.
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 0eac0aadc7..3d68bbb9ae 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -19,6 +19,7 @@ Contents:
hush
defaultenv-2
updating
+ imd
devicetree
pbl
multi-image
diff --git a/Makefile b/Makefile
index 63139c2512..4c40929343 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2014
-PATCHLEVEL = 07
+PATCHLEVEL = 08
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
@@ -774,10 +774,6 @@ include/config/kernel.release: include/config/auto.conf FORCE
$(Q)rm -f $@
$(Q)echo $(KERNELVERSION)$(localversion) > $@
-Doxyfile.version: include/config/auto.conf FORCE
- $(Q)rm -f $@
- $(Q)echo "PROJECT_NUMBER = $(KERNELRELEASE)" > $@
-
# Things we need to do before we recursively start building the kernel
# or the modules are listed in "prepare".
# A multi level approach is used. prepareN is processed before prepareN-1.
@@ -996,8 +992,9 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \
.tmp_version .tmp_barebox* barebox.bin barebox.map barebox.S \
.tmp_kallsyms* common/barebox_default_env* barebox.ldr \
scripts/bareboxenv-target barebox-flash-image \
- Doxyfile.version barebox.srec barebox.s5p barebox.ubl \
- barebox.uimage barebox.spi barebox.kwb barebox.kwbuart
+ barebox.srec barebox.s5p barebox.ubl barebox.zynq \
+ barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \
+ barebox.efi barebox.canon-a1100.bin
# Directories & files removed with 'make mrproper'
MRPROPER_DIRS += include/config include2 usr/include
diff --git a/README b/README
index cec9ccbaf5..3862f6091e 100644
--- a/README
+++ b/README
@@ -179,7 +179,7 @@ net/ -> Networking stuff
scripts/ -> Kconfig system
-Documentation/ -> Doxygen generated documentation
+Documentation/ -> Sphinx generated documentation
Release Strategy
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3af01970e3..9f34e1089b 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -62,6 +62,15 @@ config ARCH_DAVINCI
select HAS_DEBUG_LL
select GPIOLIB
+config ARCH_DIGIC
+ bool "Canon DIGIC-based cameras"
+ select CPU_ARM946E
+ select HAS_DEBUG_LL
+ select CLOCKSOURCE_DIGIC
+ select GPIOLIB
+ help
+ Support for Canon's digital cameras that use the DIGIC4 chip.
+
config ARCH_EP93XX
bool "Cirrus Logic EP93xx"
select CPU_ARM920T
@@ -95,6 +104,7 @@ config ARCH_MVEBU
select GPIOLIB
select HAS_DEBUG_LL
select HAVE_PBL_MULTI_IMAGES
+ select HW_HAS_PCI
select MVEBU_MBUS
select OFTREE
select OF_ADDRESS_PCI
@@ -220,6 +230,7 @@ source arch/arm/mach-at91/Kconfig
source arch/arm/mach-bcm2835/Kconfig
source arch/arm/mach-clps711x/Kconfig
source arch/arm/mach-davinci/Kconfig
+source arch/arm/mach-digic/Kconfig
source arch/arm/mach-ep93xx/Kconfig
source arch/arm/mach-highbank/Kconfig
source arch/arm/mach-imx/Kconfig
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 983f7f57cd..337aef175b 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -55,6 +55,7 @@ machine-$(CONFIG_ARCH_AT91) := at91
machine-$(CONFIG_ARCH_BCM2835) := bcm2835
machine-$(CONFIG_ARCH_CLPS711X) := clps711x
machine-$(CONFIG_ARCH_DAVINCI) := davinci
+machine-$(CONFIG_ARCH_DIGIC) := digic
machine-$(CONFIG_ARCH_EP93XX) := ep93xx
machine-$(CONFIG_ARCH_HIGHBANK) := highbank
machine-$(CONFIG_ARCH_IMX) := imx
@@ -184,6 +185,16 @@ ifeq ($(machine-y),zynq)
KBUILD_IMAGE := barebox.zynq
endif
+quiet_cmd_canon_a1100_image = DD $@
+ cmd_canon_a1100_image = scripts/canon-a1100-image $< $@ || \
+ echo "WARNING: Couldn't create Canon A1100 image due to previous errors."
+barebox.canon-a1100.bin: $(KBUILD_BINARY) FORCE
+ $(call if_changed,canon_a1100_image)
+
+ifeq ($(CONFIG_MACH_CANON_A1100),y)
+KBUILD_IMAGE := barebox.canon-a1100.bin
+endif
+
KWBIMAGE_OPTS = \
-c -i $(srctree)/$(BOARD)/kwbimage.cfg -d $(TEXT_BASE) -e $(TEXT_BASE)
diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile
index d200512758..c60da81261 100644
--- a/arch/arm/boards/Makefile
+++ b/arch/arm/boards/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MACH_AT91SAM9N12EK) += at91sam9n12ek/
obj-$(CONFIG_MACH_AT91SAM9X5EK) += at91sam9x5ek/
obj-$(CONFIG_MACH_BEAGLE) += beagle/
obj-$(CONFIG_MACH_BEAGLEBONE) += beaglebone/
+obj-$(CONFIG_MACH_CANON_A1100) += canon-a1100/
obj-$(CONFIG_MACH_NITROGEN6X) += boundarydevices-nitrogen6x/
obj-$(CONFIG_MACH_CCMX51) += ccxmx51/
obj-$(CONFIG_MACH_CFA10036) += crystalfontz-cfa10036/
@@ -28,6 +29,7 @@ obj-$(CONFIG_MACH_EDB9307) += edb93xx/
obj-$(CONFIG_MACH_EDB9315A) += edb93xx/
obj-$(CONFIG_MACH_EDB9315) += edb93xx/
obj-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += efika-mx-smartbook/
+obj-$(CONFIG_MACH_EMBEDSKY_E9) += embedsky-e9/
obj-$(CONFIG_MACH_EMBEST_RIOTBOARD) += embest-riotboard/
obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += eukrea_cpuimx25/
obj-$(CONFIG_MACH_EUKREA_CPUIMX27) += eukrea_cpuimx27/
diff --git a/arch/arm/boards/at91sam9m10ihd/hw_version.c b/arch/arm/boards/at91sam9m10ihd/hw_version.c
index 8e729013c7..96fb02d801 100644
--- a/arch/arm/boards/at91sam9m10ihd/hw_version.c
+++ b/arch/arm/boards/at91sam9m10ihd/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c
index 2da4e5ed8c..37eb1f80c5 100644
--- a/arch/arm/boards/at91sam9x5ek/hw_version.c
+++ b/arch/arm/boards/at91sam9x5ek/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/canon-a1100/Makefile b/arch/arm/boards/canon-a1100/Makefile
new file mode 100644
index 0000000000..b08c4a93ca
--- /dev/null
+++ b/arch/arm/boards/canon-a1100/Makefile
@@ -0,0 +1 @@
+lwl-y += lowlevel.o
diff --git a/arch/arm/boards/canon-a1100/lowlevel.c b/arch/arm/boards/canon-a1100/lowlevel.c
new file mode 100644
index 0000000000..bbae825661
--- /dev/null
+++ b/arch/arm/boards/canon-a1100/lowlevel.c
@@ -0,0 +1,23 @@
+#include <common.h>
+#include <sizes.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+
+void __naked barebox_arm_reset_vector(void)
+{
+ arm_cpu_lowlevel_init();
+
+ /* FIXME: can we determine RAM size using CP15 register?
+ *
+ * see http://chdk.setepontos.com/index.php?topic=5980.90
+ *
+ * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0363e/Bgbcdeca.html
+ * 4.2.19. c6, MPU memory region programming registers
+ *
+ * But the 'cpuinfo' command says that the Protection
+ * unit is disabled.
+ * The Control Register value (mrc p15, 0, %0, c0, c1, 4)
+ * is 0x00051078.
+ */
+ barebox_arm_entry(0x0, SZ_64M, 0);
+}
diff --git a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
index e28dd49fad..c94cb355e2 100644
--- a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
+++ b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c
@@ -21,6 +21,7 @@
#include <fs.h>
#include <globalvar.h>
#include <libbb.h>
+#include <libfile.h>
#include <magicvar.h>
#include <asm/armlinux.h>
diff --git a/arch/arm/boards/embedsky-e9/Makefile b/arch/arm/boards/embedsky-e9/Makefile
new file mode 100644
index 0000000000..db2dba7769
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/Makefile
@@ -0,0 +1,4 @@
+obj-y += board.o flash-header-e9.dcd.o
+extra-y += flash-header-e9.dcd.S flash-header-e9.dcd
+lwl-y += lowlevel.o
+bbenv-y += defaultenv-e9
diff --git a/arch/arm/boards/embedsky-e9/board.c b/arch/arm/boards/embedsky-e9/board.c
new file mode 100644
index 0000000000..55b4320219
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/board.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 Andrey Panov <rockford@yandex.ru>
+ *
+ * based on arch/arm/boards/freescale-mx6-sabresd/board.c
+ * Copyright (C) 2013 Hubert Feurstein <h.feurstein@gmail.com>
+ *
+ * based on arch/arm/boards/freescale-mx6-sabrelite/board.c
+ * Copyright (C) 2012 Steffen Trumtrar, Pengutronix
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <environment.h>
+#include <mach/imx6-regs.h>
+#include <fec.h>
+#include <gpio.h>
+#include <asm/armlinux.h>
+#include <generated/mach-types.h>
+#include <partition.h>
+#include <linux/phy.h>
+#include <asm/io.h>
+#include <asm/mmu.h>
+#include <mach/generic.h>
+#include <sizes.h>
+#include <net.h>
+#include <mach/imx6.h>
+#include <mach/devices-imx6.h>
+#include <mach/iomux-mx6.h>
+#include <spi/spi.h>
+#include <mach/spi.h>
+#include <mach/usb.h>
+#include <envfs.h>
+
+#define PHY_ID_RTL8211E 0x001cc915
+#define PHY_ID_MASK 0xffffffff
+
+/*
+ * This should reset a PHY. Taken from E9 U-Boot/Linux source.
+ */
+static int rtl8211e_phy_fixup(struct phy_device *dev)
+{
+ phy_write(dev, 0x00, 0x3140);
+ mdelay(10);
+ phy_write(dev, 0x00, 0x3340);
+ mdelay(10);
+
+ return 0;
+}
+
+static int e9_devices_init(void)
+{
+ if (!of_machine_is_compatible("embedsky,e9"))
+ return 0;
+
+ armlinux_set_architecture(3980);
+ barebox_set_hostname("e9");
+ defaultenv_append_directory(defaultenv_e9);
+
+ return 0;
+}
+device_initcall(e9_devices_init);
+
+static int e9_coredevices_init(void)
+{
+ if (!of_machine_is_compatible("embedsky,e9"))
+ return 0;
+
+ phy_register_fixup_for_uid(PHY_ID_RTL8211E, PHY_ID_MASK,
+ rtl8211e_phy_fixup);
+
+ return 0;
+}
+/*
+ * Do this before the fec initializes but after our
+ * gpios are available.
+ */
+coredevice_initcall(e9_coredevices_init);
diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1 b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1
new file mode 100644
index 0000000000..0177e6c6b8
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+mount /dev/mmc1.0
+
+global.bootm.image=/mnt/mmc1.0/zImage
+global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait"
diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3 b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3
new file mode 100644
index 0000000000..374eb1cfe6
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+mount /dev/mmc3.0
+
+global.bootm.image=/mnt/mmc3.0/boot/zImage
+global.linux.bootargs.dyn.root="root=/dev/mmcblk1p1 rootwait"
diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board b/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board
new file mode 100644
index 0000000000..6cba769921
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+# board defaults, do not change in running system. Change /env/config
+# instead
+
+global.hostname=e9
+global.boot.default=$bootsource$bootsource_instance
diff --git a/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg b/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg
new file mode 100644
index 0000000000..52edefd77a
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg
@@ -0,0 +1,87 @@
+loadaddr 0x27800000
+soc imx6
+dcdofs 0x400
+
+wm 32 0x020e0798 0x000c0000
+wm 32 0x020e0758 0x00000000
+wm 32 0x020e0588 0x00000030
+wm 32 0x020e0594 0x00000030
+wm 32 0x020e056c 0x00000030
+wm 32 0x020e0578 0x00000030
+wm 32 0x020e074c 0x00000030
+wm 32 0x020e057c 0x00000030
+wm 32 0x020e058c 0x00000000
+wm 32 0x020e059c 0x00000030
+wm 32 0x020e05a0 0x00000030
+wm 32 0x020e078c 0x00000030
+wm 32 0x020e0750 0x00020000
+wm 32 0x020e05a8 0x00000018
+wm 32 0x020e05b0 0x00000018
+wm 32 0x020e0524 0x00000018
+wm 32 0x020e051c 0x00000018
+wm 32 0x020e0518 0x00000018
+wm 32 0x020e050c 0x00000018
+wm 32 0x020e05b8 0x00000018
+wm 32 0x020e05c0 0x00000018
+wm 32 0x020e0774 0x00020000
+wm 32 0x020e0784 0x00000018
+wm 32 0x020e0788 0x00000018
+wm 32 0x020e0794 0x00000018
+wm 32 0x020e079c 0x00000018
+wm 32 0x020e07a0 0x00000018
+wm 32 0x020e07a4 0x00000018
+wm 32 0x020e07a8 0x00000018
+wm 32 0x020e0748 0x00000018
+wm 32 0x020e05ac 0x00000018
+wm 32 0x020e05b4 0x00000018
+wm 32 0x020e0528 0x00000018
+wm 32 0x020e0520 0x00000018
+wm 32 0x020e0514 0x00000018
+wm 32 0x020e0510 0x00000018
+wm 32 0x020e05bc 0x00000018
+wm 32 0x020e05c4 0x00000018
+wm 32 0x021b0800 0xa1390003
+wm 32 0x021b080c 0x001f001f
+wm 32 0x021b0810 0x001f001f
+wm 32 0x021b480c 0x001f001f
+wm 32 0x021b4810 0x001f001f
+wm 32 0x021b083c 0x4333033f
+wm 32 0x021b0840 0x032c031d
+wm 32 0x021b483c 0x43200332
+wm 32 0x021b4840 0x031a026a
+wm 32 0x021b0848 0x4d464746
+wm 32 0x021b4848 0x47453f4d
+wm 32 0x021b0850 0x3e434440
+wm 32 0x021b4850 0x47384839
+wm 32 0x021b081c 0x33333333
+wm 32 0x021b0820 0x33333333
+wm 32 0x021b0824 0x33333333
+wm 32 0x021b0828 0x33333333
+wm 32 0x021b481c 0x33333333
+wm 32 0x021b4820 0x33333333
+wm 32 0x021b4824 0x33333333
+wm 32 0x021b4828 0x33333333
+wm 32 0x021b08b8 0x00000800
+wm 32 0x021b48b8 0x00000800
+wm 32 0x021b0004 0x00020036
+wm 32 0x021b0008 0x09444040
+wm 32 0x021b000c 0x8a8f7955
+wm 32 0x021b0010 0xff328f64
+wm 32 0x021b0014 0x01ff00db
+wm 32 0x021b0018 0x00001740
+wm 32 0x021b001c 0x00008000
+wm 32 0x021b002c 0x000026d2
+wm 32 0x021b0030 0x008f1023
+wm 32 0x021b0040 0x00000047
+wm 32 0x021b0000 0x841a0000
+wm 32 0x021b001c 0x04088032
+wm 32 0x021b001c 0x00008033
+wm 32 0x021b001c 0x00048031
+wm 32 0x021b001c 0x09408030
+wm 32 0x021b001c 0x04008040
+wm 32 0x021b0020 0x00005800
+wm 32 0x021b0818 0x00011117
+wm 32 0x021b4818 0x00011117
+wm 32 0x021b0004 0x00025576
+wm 32 0x021b0404 0x00011006
+wm 32 0x021b001c 0x00000000
diff --git a/arch/arm/boards/embedsky-e9/lowlevel.c b/arch/arm/boards/embedsky-e9/lowlevel.c
new file mode 100644
index 0000000000..fee1011700
--- /dev/null
+++ b/arch/arm/boards/embedsky-e9/lowlevel.c
@@ -0,0 +1,18 @@
+#include <common.h>
+#include <sizes.h>
+#include <mach/generic.h>
+#include <asm/barebox-arm-head.h>
+#include <asm/barebox-arm.h>
+
+extern char __dtb_imx6q_embedsky_e9_start[];
+
+ENTRY_FUNCTION(start_imx6q_embedsky_e9, r0, r1, r2)
+{
+ void *fdt;
+
+ imx6_cpu_lowlevel_init();
+
+ fdt = __dtb_imx6q_embedsky_e9_start - get_runtime_offset();
+
+ barebox_arm_entry(0x10000000, SZ_2G, fdt);
+}
diff --git a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
index 51b9ef8db7..7d1c1d5b2a 100644
--- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
+++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c
@@ -2,6 +2,7 @@
#include <mach/esdctl.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
+#include <image-metadata.h>
extern char __dtb_imx53_qsb_start[];
diff --git a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
index a0ba86a6ec..ff1f04e87f 100644
--- a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
+++ b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c
@@ -15,7 +15,7 @@
#include <mach/wdt.h>
#include <debug_ll.h>
-static const struct am33xx_cmd_control MT41J256M8HX15E_2x256M8_cmd = {
+static const struct am33xx_cmd_control pcm051_cmd = {
.slave_ratio0 = 0x40,
.dll_lock_diff0 = 0x0,
.invert_clkout0 = 0x1,
@@ -27,23 +27,74 @@ static const struct am33xx_cmd_control MT41J256M8HX15E_2x256M8_cmd = {
.invert_clkout2 = 0x1,
};
-static const struct am33xx_emif_regs MT41J256M8HX15E_2x256M8_regs = {
- .emif_read_latency = 0x6,
- .emif_tim1 = 0x0668A39B,
- .emif_tim2 = 0x26337FDA,
- .emif_tim3 = 0x501F830F,
- .sdram_config = 0x61C04832,
- .zq_config = 0x50074BE4,
- .sdram_ref_ctrl = 0x0000093B,
+struct pcm051_sdram_timings {
+ struct am33xx_emif_regs regs;
+ struct am33xx_ddr_data data;
};
-static const struct am33xx_ddr_data MT41J256M8HX15E_2x256M8_data = {
- .rd_slave_ratio0 = 0x3B,
- .wr_dqs_slave_ratio0 = 0x85,
- .fifo_we_slave_ratio0 = 0x100,
- .wr_slave_ratio0 = 0xC1,
- .use_rank0_delay = 0x01,
- .dll_lock_diff0 = 0x0,
+enum {
+ MT41J128M16125IT_1x256M16,
+ MT41J64M1615IT_1x128M16,
+ MT41J256M16HA15EIT_1x512M16,
+};
+
+struct pcm051_sdram_timings timings[] = {
+ /* 1x256M16 */
+ [MT41J128M16125IT_1x256M16] = {
+ .regs = {
+ .emif_read_latency = 0x6,
+ .emif_tim1 = 0x0888A39B,
+ .emif_tim2 = 0x26337FDA,
+ .emif_tim3 = 0x501F830F,
+ .sdram_config = 0x61C04AB2,
+ .zq_config = 0x50074BE4,
+ .sdram_ref_ctrl = 0x0000093B,
+ },
+ .data = {
+ .rd_slave_ratio0 = 0x3B,
+ .wr_dqs_slave_ratio0 = 0x3B,
+ .fifo_we_slave_ratio0 = 0x97,
+ .wr_slave_ratio0 = 0x76,
+ },
+ },
+
+ /* 1x128M16 */
+ [MT41J64M1615IT_1x128M16] = {
+ .regs = {
+ .emif_read_latency = 0x6,
+ .emif_tim1 = 0x0888A39B,
+ .emif_tim2 = 0x26247FDA,
+ .emif_tim3 = 0x501F821F,
+ .sdram_config = 0x61C04A32,
+ .zq_config = 0x50074BE4,
+ .sdram_ref_ctrl = 0x0000093B,
+ },
+ .data = {
+ .rd_slave_ratio0 = 0x3A,
+ .wr_dqs_slave_ratio0 = 0x36,
+ .fifo_we_slave_ratio0 = 0xA2,
+ .wr_slave_ratio0 = 0x74,
+ },
+ },
+
+ /* 1x512MB */
+ [MT41J256M16HA15EIT_1x512M16] = {
+ .regs = {
+ .emif_read_latency = 0x6,
+ .emif_tim1 = 0x0888A39B,
+ .emif_tim2 = 0x26517FDA,
+ .emif_tim3 = 0x501F84EF,
+ .sdram_config = 0x61C04B32,
+ .zq_config = 0x50074BE4,
+ .sdram_ref_ctrl = 0x0000093B,
+ },
+ .data = {
+ .rd_slave_ratio0 = 0x3B,
+ .wr_dqs_slave_ratio0 = 0x3B,
+ .fifo_we_slave_ratio0 = 0x96,
+ .wr_slave_ratio0 = 0x76,
+ },
+ },
};
extern char __dtb_am335x_phytec_phycore_start[];
@@ -57,9 +108,10 @@ extern char __dtb_am335x_phytec_phycore_start[];
*
* @return void
*/
-static noinline void pcm051_board_init(void)
+static noinline void pcm051_board_init(int sdram)
{
void *fdt;
+ struct pcm051_sdram_timings *timing = &timings[sdram];
/* WDT1 is already running when the bootloader gets control
* Disable it to avoid "random" resets
@@ -72,9 +124,9 @@ static noinline void pcm051_board_init(void)
am33xx_pll_init(MPUPLL_M_600, 25, DDRPLL_M_303);
- am335x_sdram_init(0x18B, &MT41J256M8HX15E_2x256M8_cmd,
- &MT41J256M8HX15E_2x256M8_regs,
- &MT41J256M8HX15E_2x256M8_data);
+ am335x_sdram_init(0x18B, &pcm051_cmd,
+ &timing->regs,
+ &timing->data);
am33xx_uart_soft_reset((void *)AM33XX_UART0_BASE);
am33xx_enable_uart0_pin_mux();
@@ -83,10 +135,10 @@ static noinline void pcm051_board_init(void)
fdt = __dtb_am335x_phytec_phycore_start - get_runtime_offset();
- barebox_arm_entry(0x80000000, SZ_512M, fdt);
+ am335x_barebox_entry(fdt);
}
-ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram, bootinfo, r1, r2)
+static noinline void pcm051_board_entry(unsigned long bootinfo, int sdram)
{
am33xx_save_bootinfo((void *)bootinfo);
@@ -99,7 +151,22 @@ ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram, bootinfo, r1, r2)
relocate_to_current_adr();
setup_c();
- pcm051_board_init();
+ pcm051_board_init(sdram);
+}
+
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x256m16, bootinfo, r1, r2)
+{
+ pcm051_board_entry(bootinfo, MT41J128M16125IT_1x256M16);
+}
+
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x128m16, bootinfo, r1, r2)
+{
+ pcm051_board_entry(bootinfo, MT41J64M1615IT_1x128M16);
+}
+
+ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x512m16, bootinfo, r1, r2)
+{
+ pcm051_board_entry(bootinfo, MT41J256M16HA15EIT_1x512M16);
}
ENTRY_FUNCTION(start_am33xx_phytec_phycore_sdram, r0, r1, r2)
@@ -108,5 +175,5 @@ ENTRY_FUNCTION(start_am33xx_phytec_phycore_sdram, r0, r1, r2)
fdt = __dtb_am335x_phytec_phycore_start - get_runtime_offset();
- barebox_arm_entry(0x80000000, SZ_512M, fdt);
+ am335x_barebox_entry(fdt);
}
diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
index 55aae00954..1d08f0561a 100644
--- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
+++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c
@@ -16,6 +16,7 @@
#include <common.h>
#include <sizes.h>
#include <io.h>
+#include <image-metadata.h>
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
#include <asm/sections.h>
@@ -57,6 +58,11 @@ extern char __dtb_imx6q_phytec_pbab01_start[];
extern char __dtb_imx6dl_phytec_pbab01_start[];
extern char __dtb_imx6s_phytec_pbab01_start[];
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0);
+BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0);
+
ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
{
void *fdt;
@@ -65,6 +71,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_1G);
+
if (IS_ENABLED(CONFIG_DEBUG_LL))
setup_uart();
@@ -81,6 +89,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_2G);
+
if (IS_ENABLED(CONFIG_DEBUG_LL))
setup_uart();
@@ -97,6 +107,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_4G);
+
fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, 0xEFFFFFF8, fdt);
@@ -110,6 +122,8 @@ ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_1G);
+
fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, SZ_1G, fdt);
@@ -123,6 +137,8 @@ ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2)
arm_setup_stack(0x00920000 - 8);
+ IMD_USED(phyflex_mx6_memsize_512M);
+
fdt = __dtb_imx6s_phytec_pbab01_start - get_runtime_offset();
barebox_arm_entry(0x10000000, SZ_512M, fdt);
diff --git a/arch/arm/boards/sama5d3_xplained/init.c b/arch/arm/boards/sama5d3_xplained/init.c
index ae18863acd..ae84209cbb 100644
--- a/arch/arm/boards/sama5d3_xplained/init.c
+++ b/arch/arm/boards/sama5d3_xplained/init.c
@@ -57,21 +57,30 @@ static struct atmel_nand_data nand_pdata = {
};
static struct sam9_smc_config sama5d3_xplained_nand_smc_config = {
- .ncs_read_setup = 0,
- .nrd_setup = 1,
- .ncs_write_setup = 0,
- .nwe_setup = 1,
+ .ncs_read_setup = 1,
+ .nrd_setup = 2,
+ .ncs_write_setup = 1,
+ .nwe_setup = 2,
- .ncs_read_pulse = 6,
- .nrd_pulse = 4,
+ .ncs_read_pulse = 5,
+ .nrd_pulse = 3,
.ncs_write_pulse = 5,
.nwe_pulse = 3,
- .read_cycle = 6,
- .write_cycle = 5,
+ .read_cycle = 8,
+ .write_cycle = 8,
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
- .tdf_cycles = 1,
+ .tdf_cycles = 3,
+
+ .tclr = 3,
+ .tadl = 10,
+ .tar = 3,
+ .ocms = 0,
+ .trr = 4,
+ .twb = 5,
+ .rbnsel = 3,
+ .nfsel = 1
};
static void ek_add_device_nand(void)
@@ -87,7 +96,7 @@ static void ek_add_device_nand(void)
sama5d3_xplained_nand_smc_config.mode |= AT91_SMC_DBW_8;
/* configure chip-select 3 (NAND) */
- sam9_smc_configure(0, 3, &sama5d3_xplained_nand_smc_config);
+ sama5_smc_configure(0, 3, &sama5d3_xplained_nand_smc_config);
at91_add_device_nand(&nand_pdata);
}
diff --git a/arch/arm/boards/sama5d3xek/hw_version.c b/arch/arm/boards/sama5d3xek/hw_version.c
index 450eb9f8a1..c809c37742 100644
--- a/arch/arm/boards/sama5d3xek/hw_version.c
+++ b/arch/arm/boards/sama5d3xek/hw_version.c
@@ -18,6 +18,7 @@
#include <fs.h>
#include <fcntl.h>
#include <libbb.h>
+#include <libfile.h>
#include <asm/armlinux.h>
#include <of.h>
diff --git a/arch/arm/boards/sama5d3xek/init.c b/arch/arm/boards/sama5d3xek/init.c
index e078642242..743197fe47 100644
--- a/arch/arm/boards/sama5d3xek/init.c
+++ b/arch/arm/boards/sama5d3xek/init.c
@@ -72,21 +72,30 @@ static struct atmel_nand_data nand_pdata = {
};
static struct sam9_smc_config cm_nand_smc_config = {
- .ncs_read_setup = 0,
- .nrd_setup = 1,
- .ncs_write_setup = 0,
- .nwe_setup = 1,
+ .ncs_read_setup = 1,
+ .nrd_setup = 2,
+ .ncs_write_setup = 1,
+ .nwe_setup = 2,
- .ncs_read_pulse = 6,
- .nrd_pulse = 4,
+ .ncs_read_pulse = 5,
+ .nrd_pulse = 3,
.ncs_write_pulse = 5,
.nwe_pulse = 3,
- .read_cycle = 6,
- .write_cycle = 5,
+ .read_cycle = 8,
+ .write_cycle = 8,
.mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE,
- .tdf_cycles = 1,
+ .tdf_cycles = 3,
+
+ .tclr = 3,
+ .tadl = 10,
+ .tar = 3,
+ .ocms = 0,
+ .trr = 4,
+ .twb = 5,
+ .rbnsel = 3,
+ .nfsel = 1
};
static void ek_add_device_nand(void)
@@ -102,7 +111,7 @@ static void ek_add_device_nand(void)
cm_nand_smc_config.mode |= AT91_SMC_DBW_8;
/* configure chip-select 3 (NAND) */
- sam9_smc_configure(0, 3, &cm_nand_smc_config);
+ sama5_smc_configure(0, 3, &cm_nand_smc_config);
at91_add_device_nand(&nand_pdata);
}
diff --git a/arch/arm/boards/tqma53/lowlevel.c b/arch/arm/boards/tqma53/lowlevel.c
index 0a67228008..cd87212555 100644
--- a/arch/arm/boards/tqma53/lowlevel.c
+++ b/arch/arm/boards/tqma53/lowlevel.c
@@ -5,6 +5,7 @@
#include <asm/barebox-arm-head.h>
#include <asm/barebox-arm.h>
#include <mach/imx5.h>
+#include <image-metadata.h>
extern char __dtb_imx53_mba53_start[];
@@ -34,6 +35,8 @@ static void __noreturn start_imx53_tqma53_common(void *fdt)
imx53_barebox_entry(fdt);
}
+BAREBOX_IMD_TAG_STRING(tqma53_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0);
+
ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
{
void *fdt;
@@ -42,6 +45,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
arm_setup_stack(0xf8020000 - 8);
+ IMD_USED(tqma53_memsize_512M);
+
imx53_init_lowlevel_early(800);
fdt = __dtb_imx53_mba53_start - get_runtime_offset();
@@ -49,6 +54,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2)
start_imx53_tqma53_common(fdt);
}
+BAREBOX_IMD_TAG_STRING(tqma53_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0);
+
ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2)
{
void *fdt;
@@ -57,6 +64,8 @@ ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2)
arm_setup_stack(0xf8020000 - 8);
+ IMD_USED(tqma53_memsize_1G);
+
imx53_init_lowlevel_early(800);
fdt = __dtb_imx53_mba53_start - get_runtime_offset();
diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig
index 0c92c96e45..d3feb108a1 100644
--- a/arch/arm/configs/am335x_defconfig
+++ b/arch/arm/configs/am335x_defconfig
@@ -1,11 +1,11 @@
CONFIG_ARCH_OMAP=y
CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO=y
+CONFIG_BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS=y
CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLEBONE=y
CONFIG_MACH_PCM051=y
CONFIG_THUMB2_BAREBOX=y
CONFIG_ARM_BOARD_APPEND_ATAG=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
@@ -15,7 +15,6 @@ 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
@@ -25,61 +24,63 @@ CONFIG_BLSPEC=y
CONFIG_CONSOLE_ACTIVATE_NONE=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
CONFIG_DEBUG_INFO=y
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_LOADENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_READF=y
-CONFIG_CMD_LET=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENUTREE=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_TFTP=y
-CONFIG_CMD_FILETYPE=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADB=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_FLASH=y
-CONFIG_CMD_UBIFORMAT=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_UIMAGE=y
-CONFIG_CMD_BOOTZ=y
# CONFIG_CMD_BOOTU is not set
-CONFIG_CMD_RESET=y
+CONFIG_CMD_BOOTZ=y
CONFIG_CMD_GO=y
-CONFIG_CMD_OFTREE=y
-CONFIG_CMD_OF_PROPERTY=y
-CONFIG_CMD_OF_NODE=y
-CONFIG_CMD_BAREBOX_UPDATE=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_UBIFORMAT=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=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_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=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_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
CONFIG_CMD_I2C=y
-CONFIG_CMD_SPI=y
CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
CONFIG_CMD_LED_TRIGGER=y
-CONFIG_CMD_MIITOOL=y
-CONFIG_CMD_DETECT=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_NET_NFS=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
diff --git a/arch/arm/configs/am335x_mlo_defconfig b/arch/arm/configs/am335x_mlo_defconfig
index b8dc4e04ec..19f78d0ae8 100644
--- a/arch/arm/configs/am335x_mlo_defconfig
+++ b/arch/arm/configs/am335x_mlo_defconfig
@@ -1,4 +1,5 @@
CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_BUILD_IFT=y
CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLEBONE=y
CONFIG_MACH_PCM051=y
diff --git a/arch/arm/configs/canon-a1100_defconfig b/arch/arm/configs/canon-a1100_defconfig
new file mode 100644
index 0000000000..5c1e195a2d
--- /dev/null
+++ b/arch/arm/configs/canon-a1100_defconfig
@@ -0,0 +1,56 @@
+CONFIG_BUILTIN_DTB=y
+CONFIG_BUILTIN_DTB_NAME="canon-a1100"
+CONFIG_ARCH_DIGIC=y
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_PBL_IMAGE=y
+CONFIG_IMAGE_COMPRESSION_LZ4=y
+CONFIG_TEXT_BASE=0x00300000
+CONFIG_MALLOC_SIZE=0x200000
+CONFIG_PROMPT="canon-a1100 > "
+CONFIG_GLOB=y
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_DEBUG_LL=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+# CONFIG_CMD_BOOTM is not set
+# CONFIG_CMD_BOOTU is not set
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADY=y
+# CONFIG_CMD_MOUNT is not set
+# CONFIG_CMD_UMOUNT is not set
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_GLOBAL=y
+CONFIG_CMD_MD5SUM=y
+# CONFIG_CMD_PWD is not set
+CONFIG_CMD_SHA1SUM=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+# CONFIG_CMD_CLEAR is not set
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_OFDEVICE=y
+CONFIG_DRIVER_SERIAL_DIGIC=y
+# CONFIG_SPI is not set
+CONFIG_MTD=y
+# CONFIG_MTD_WRITE is not set
+CONFIG_DRIVER_CFI=y
+# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set
+CONFIG_CLOCKSOURCE_DUMMY=y
+CONFIG_CLOCKSOURCE_DUMMY_RATE=2000
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_GPIO_DIGIC=y
+CONFIG_ZLIB=y
diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig
index 66fc123223..0a4f2fe129 100644
--- a/arch/arm/configs/imx_v7_defconfig
+++ b/arch/arm/configs/imx_v7_defconfig
@@ -16,6 +16,7 @@ CONFIG_MACH_SABRELITE=y
CONFIG_MACH_SABRESD=y
CONFIG_MACH_NITROGEN6X=y
CONFIG_MACH_SOLIDRUN_MICROSOM=y
+CONFIG_MACH_EMBEDSKY_E9=y
CONFIG_MACH_EMBEST_RIOTBOARD=y
CONFIG_MACH_UDOO=y
CONFIG_MACH_VARISCITE_MX6=y
diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig
index aed4cb7c63..fb1a9998b0 100644
--- a/arch/arm/cpu/Kconfig
+++ b/arch/arm/cpu/Kconfig
@@ -39,6 +39,19 @@ config CPU_ARM926T
Say Y if you want support for the ARM926T processor.
Otherwise, say N.
+# ARM946E-S
+config CPU_ARM946E
+ bool
+ depends on !MMU
+ select CPU_32v4T
+ help
+ ARM946E-S is a member of the ARM9E-S family of high-
+ performance, 32-bit system-on-chip processor solutions.
+ The TCM and ARMv5TE 32-bit instruction set is supported.
+
+ Say Y if you want support for the ARM946E-S processor.
+ Otherwise, say N.
+
# Feroceon
config CPU_FEROCEON
bool
diff --git a/arch/arm/cpu/dtb.c b/arch/arm/cpu/dtb.c
index abc3ccb4c0..ae4ff2a9ad 100644
--- a/arch/arm/cpu/dtb.c
+++ b/arch/arm/cpu/dtb.c
@@ -50,6 +50,7 @@ static int of_arm_init(void)
root = of_unflatten_dtb(fdt);
if (root) {
of_set_root_node(root);
+ of_fix_tree(root);
if (IS_ENABLED(CONFIG_OFDEVICE))
of_probe();
}
diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c
index bf0141b946..e4afcc8411 100644
--- a/arch/arm/cpu/mmu.c
+++ b/arch/arm/cpu/mmu.c
@@ -188,6 +188,7 @@ void *map_io_sections(unsigned long phys, void *_start, size_t size)
for (sec = start; sec < start + size; sec += (1 << 20))
ttb[sec >> 20] = (phys++ << 20) | PMD_SECT_DEF_UNCACHED;
+ dma_flush_range((unsigned long)ttb, (unsigned long)ttb + 0x4000);
tlb_invalidate();
return _start;
}
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 961873d6bb..264420d084 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -103,7 +103,7 @@ static noinline __noreturn void __start(unsigned long membase,
/*
* Maximum malloc space is the Kconfig value if given
- * or 64MB.
+ * or 1GB.
*/
if (MALLOC_SIZE > 0) {
malloc_start = malloc_end - MALLOC_SIZE;
@@ -111,8 +111,8 @@ static noinline __noreturn void __start(unsigned long membase,
malloc_start = membase;
} else {
malloc_start = malloc_end - (malloc_end - membase) / 2;
- if (malloc_end - malloc_start > SZ_64M)
- malloc_start = malloc_end - SZ_64M;
+ if (malloc_end - malloc_start > SZ_1G)
+ malloc_start = malloc_end - SZ_1G;
}
mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1);
diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile
index 72ad5e6a6f..fac2b273cb 100644
--- a/arch/arm/dts/Makefile
+++ b/arch/arm/dts/Makefile
@@ -1,93 +1,47 @@
-dtb-$(CONFIG_ARCH_AM33XX) += \
- am335x-bone.dtb \
- am335x-boneblack.dtb \
- am335x-bone-common.dtb \
- am335x-phytec-phycore.dtb
-dtb-$(CONFIG_ARCH_IMX25) += imx25-karo-tx25.dtb
-dtb-$(CONFIG_ARCH_IMX27) += imx27-phytec-phycard-s-rdk-bb.dtb \
- imx27-phytec-phycore-rdk.dtb
-dtb-$(CONFIG_ARCH_IMX51) += imx51-babbage.dtb \
- imx51-genesi-efika-sb.dtb
-dtb-$(CONFIG_ARCH_IMX53) += imx53-mba53.dtb \
- imx53-qsb.dtb \
- imx53-qsrb.dtb \
- imx53-voipac-bsb.dtb
-dtb-$(CONFIG_ARCH_IMX6) += imx6q-gk802.dtb \
- imx6dl-dfi-fs700-m60-6s.dtb \
- imx6q-dfi-fs700-m60-6q.dtb \
- imx6q-dmo-edmqmx6.dtb \
- imx6q-sabrelite.dtb \
- imx6dl-sabrelite.dtb \
- imx6q-sabresd.dtb \
- imx6dl-mba6x.dtb \
- imx6q-mba6x.dtb \
- imx6dl-phytec-pbab01.dtb \
- imx6q-phytec-pbab01.dtb \
- imx6s-phytec-pbab01.dtb \
- imx6dl-hummingboard.dtb \
- imx6q-guf-santaro.dtb \
- imx6q-nitrogen6x.dtb \
- imx6dl-nitrogen6x.dtb \
- imx6q-udoo.dtb \
- imx6q-var-custom.dtb \
- imx6s-riotboard.dtb \
- imx6q-phytec-pbaa03.dtb
-dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3188-radxarock.dtb
-dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5_sockit.dtb \
- socfpga_cyclone5_socrates.dtb
-dtb-$(CONFIG_ARCH_TEGRA) += \
- tegra20-colibri-iris.dtb \
- tegra20-paz00.dtb \
- tegra30-beaver.dtb \
- tegra124-jetson-tk1.dtb
-
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
-obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-
-pbl-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
-pbl-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
-pbl-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
-pbl-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o
-pbl-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o
-pbl-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
-pbl-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o
-pbl-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o
-pbl-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
-pbl-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o
-pbl-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
-pbl-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
-pbl-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o
-pbl-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o
-pbl-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o
-pbl-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o
-pbl-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o
-pbl-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o
-pbl-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o
-pbl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
-pbl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
-pbl-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o
-pbl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
-pbl-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o
-pbl-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o
-pbl-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
-pbl-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o
-pbl-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o
-pbl-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
-pbl-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
-pbl-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o
-pbl-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o
-pbl-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
-pbl-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
-pbl-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
-
-.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
-.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
+obj-dtb-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-targets += dtbs
-targets += $(dtb-y)
+# just to build a built-in.o. Otherwise compilation fails when no devicetree is
+# created.
+obj-y += empty.o
-extra-y += $(dtb-y)
+pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o
+pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o
+pbl-dtb-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o
+pbl-dtb-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o
+pbl-dtb-$(CONFIG_MACH_EMBEDSKY_E9) += imx6q-embedsky-e9.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o
+pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o
+pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o
+pbl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o
+pbl-dtb-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o
+pbl-dtb-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o
+pbl-dtb-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o
+pbl-dtb-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o
+pbl-dtb-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o
+pbl-dtb-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o
+pbl-dtb-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o
+pbl-dtb-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o
+pbl-dtb-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o
+pbl-dtb-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o
+pbl-dtb-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o
+pbl-dtb-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o
+pbl-dtb-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o
+pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o
+pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o
+pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o
clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts
diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi
index 4cf7fdbb48..e1effac323 100644
--- a/arch/arm/dts/am335x-bone-common.dtsi
+++ b/arch/arm/dts/am335x-bone-common.dtsi
@@ -276,13 +276,14 @@
pinctrl-names = "default", "sleep";
pinctrl-0 = <&cpsw_default>;
pinctrl-1 = <&cpsw_sleep>;
-
+ status = "okay";
};
&davinci_mdio {
pinctrl-names = "default", "sleep";
pinctrl-0 = <&davinci_mdio_default>;
pinctrl-1 = <&davinci_mdio_sleep>;
+ status = "okay";
};
&mmc1 {
diff --git a/arch/arm/dts/am335x-phytec-phycore.dts b/arch/arm/dts/am335x-phytec-phycore.dts
index 6196eb3244..5678138f66 100644
--- a/arch/arm/dts/am335x-phytec-phycore.dts
+++ b/arch/arm/dts/am335x-phytec-phycore.dts
@@ -22,11 +22,6 @@
};
};
- memory {
- device_type = "memory";
- reg = <0x80000000 0x20000000>; /* 512 MB */
- };
-
gpio-leds {
compatible = "gpio-leds";
pinctrl-names = "default";
@@ -214,6 +209,7 @@
&davinci_mdio {
pinctrl-names = "default";
pinctrl-0 = <&davinci_mdio_default>;
+ status = "okay";
};
&phy_sel {
@@ -236,6 +232,7 @@
pinctrl-names = "default";
pinctrl-0 = <&emac_rmii1_pins>;
dual_emac = <1>;
+ status = "okay";
};
&gpmc {
diff --git a/arch/arm/dts/armada-370-mirabox-bb.dts b/arch/arm/dts/armada-370-mirabox-bb.dts
index de37a75bb9..315678151a 100644
--- a/arch/arm/dts/armada-370-mirabox-bb.dts
+++ b/arch/arm/dts/armada-370-mirabox-bb.dts
@@ -11,9 +11,6 @@
};
soc {
- ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000
- MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>;
-
internal-regs {
gpio_leds {
green_pwr_led {
diff --git a/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts b/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts
index 611d72707f..e88f1dc781 100644
--- a/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts
+++ b/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts
@@ -11,10 +11,6 @@
};
soc {
- ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000
- MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000
- MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>;
-
internal-regs {
gpio_leds {
red_led {
diff --git a/arch/arm/dts/canon-a1100.dts b/arch/arm/dts/canon-a1100.dts
new file mode 100644
index 0000000000..a88eacf4d4
--- /dev/null
+++ b/arch/arm/dts/canon-a1100.dts
@@ -0,0 +1,35 @@
+/dts-v1/;
+
+/include/ "digic4.dtsi"
+
+/ {
+ model = "Canon PowerShot A1100 IS";
+ compatible = "canon,a1100";
+
+ memory {
+ reg = <0x00000000 0x04000000>;
+ };
+
+ flash@f8000000 {
+ compatible = "cfi-flash";
+ reg = <0xf8000000 0x08000000>;
+ };
+
+ leds {
+ compatible = "gpio-leds";
+
+ direct_print {
+ label = "direct-print (blue)";
+ gpios = <&gpio 51 0>;
+ };
+
+ auto_focus {
+ label = "auto-focus (red)";
+ gpios = <&gpio 55 0>;
+ };
+ };
+};
+
+&timer2 {
+ status = "okay";
+};
diff --git a/arch/arm/dts/digic4.dtsi b/arch/arm/dts/digic4.dtsi
new file mode 100644
index 0000000000..21b004d4a2
--- /dev/null
+++ b/arch/arm/dts/digic4.dtsi
@@ -0,0 +1,42 @@
+/include/ "skeleton.dtsi"
+
+/ {
+ compatible = "canon,digic4";
+
+ timer0: timer@c0210000 {
+ compatible = "canon,digic-timer";
+ reg = <0xc0210000 0x1c>;
+ status = "disabled";
+ };
+
+ timer1: timer@c0210100 {
+ compatible = "canon,digic-timer";
+ reg = <0xc0210100 0x1c>;
+ status = "disabled";
+ };
+
+ timer2: timer@c0210200 {
+ compatible = "canon,digic-timer";
+ reg = <0xc0210200 0x1c>;
+ status = "disabled";
+ };
+
+ /*
+ * I don't know real max GPIO number but this page
+ * http://magiclantern.wikia.com/wiki/Register_Map#GPIO_Ports
+ * says about 93 pins on 5DMkIII.
+ * Assume that DIGIC4 has at least 96 pins.
+ * So resource size is 96 * 4 = 0x180.
+ */
+ gpio: gpio {
+ compatible = "canon,digic-gpio";
+ reg = <0xc0220000 0x180>;
+ #gpio-cells = <2>;
+ gpio-controller;
+ };
+
+ uart: uart {
+ compatible = "canon,digic-uart";
+ reg = <0xc0800000 0x1c>;
+ };
+};
diff --git a/arch/arm/dts/empty.c b/arch/arm/dts/empty.c
new file mode 100644
index 0000000000..d141224cf8
--- /dev/null
+++ b/arch/arm/dts/empty.c
@@ -0,0 +1,3 @@
+static inline void empty(void)
+{
+}
diff --git a/arch/arm/dts/imx6q-embedsky-e9.dts b/arch/arm/dts/imx6q-embedsky-e9.dts
new file mode 100644
index 0000000000..14f6d5fe15
--- /dev/null
+++ b/arch/arm/dts/imx6q-embedsky-e9.dts
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+/dts-v1/;
+
+#include "imx6q.dtsi"
+#include <arm/imx6q-embedsky-e9.dtsi>
+
+/ {
+ chosen {
+ linux,stdout-path = &uart4;
+
+ environment@0 {
+ compatible = "barebox,environment";
+ device-path = &usdhc2, "partname:barebox-environment";
+ };
+
+ };
+};
+
+&usdhc2 {
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ partition@0 {
+ label = "barebox";
+ reg = <0x0 0x80000>;
+ };
+ partition@1 {
+ label = "barebox-environment";
+ reg = <0x80000 0x80000>;
+ };
+};
diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S
index d9588736f8..bb0354ae29 100644
--- a/arch/arm/lib/barebox.lds.S
+++ b/arch/arm/lib/barebox.lds.S
@@ -75,6 +75,8 @@ SECTIONS
. = ALIGN(4);
.data : { *(.data*) }
+ .barebox_imd : { BAREBOX_IMD }
+
. = .;
__barebox_cmd_start = .;
.barebox_cmd : { BAREBOX_CMDS }
diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c
index 4896d01976..baf0946a47 100644
--- a/arch/arm/lib/bootm.c
+++ b/arch/arm/lib/bootm.c
@@ -6,6 +6,7 @@
#include <image.h>
#include <init.h>
#include <fs.h>
+#include <libfile.h>
#include <linux/list.h>
#include <xfuncs.h>
#include <malloc.h>
@@ -314,7 +315,7 @@ static int do_bootz_linux(struct image_data *data)
image_size - sizeof(*header));
if (ret < 0)
goto err_out;
- if (ret < end - sizeof(*header)) {
+ if (ret < image_size - sizeof(*header)) {
printf("premature end of image\n");
ret = -EIO;
goto err_out;
@@ -414,6 +415,11 @@ static int do_bootm_aimage(struct image_data *data)
int to_read;
struct android_header_comp *cmp;
unsigned long mem_free;
+ unsigned long mem_start, mem_size;
+
+ ret = sdram_start_and_size(&mem_start, &mem_size);
+ if (ret)
+ return ret;
fd = open(data->os_file, O_RDONLY);
if (fd < 0) {
@@ -447,8 +453,17 @@ static int do_bootm_aimage(struct image_data *data)
cmp = &header->kernel;
data->os_res = request_sdram_region("akernel", cmp->load_addr, cmp->size);
if (!data->os_res) {
- ret = -ENOMEM;
- goto err_out;
+ pr_err("Cannot request region 0x%08x - 0x%08x, using default load address\n",
+ cmp->load_addr, cmp->size);
+
+ data->os_address = mem_start + PAGE_ALIGN(cmp->size * 4);
+ data->os_res = request_sdram_region("akernel", data->os_address, cmp->size);
+ if (!data->os_res) {
+ pr_err("Cannot request region 0x%08x - 0x%08x\n",
+ cmp->load_addr, cmp->size);
+ ret = -ENOMEM;
+ goto err_out;
+ }
}
ret = aimage_load_resource(fd, data->os_res, buf, header->page_size);
diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S
index 76184a0eec..9afee2964a 100644
--- a/arch/arm/lib/pbl.lds.S
+++ b/arch/arm/lib/pbl.lds.S
@@ -54,6 +54,8 @@ SECTIONS
. = ALIGN(4);
.rodata : { *(.rodata*) }
+ .barebox_imd : { BAREBOX_IMD }
+
_etext = .; /* End of text and rodata section */
. = ALIGN(4);
diff --git a/arch/arm/mach-at91/at91sam926x_lowlevel_init.c b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c
index 985203ae59..e69e4a86bf 100644
--- a/arch/arm/mach-at91/at91sam926x_lowlevel_init.c
+++ b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c
@@ -130,7 +130,7 @@ void __bare_init at91sam926x_lowlevel_init(struct at91sam926x_lowlevel_cfg *cfg)
at91_sys_write(cfg->matrix_csa, cfg->ebi_csa);
/* flash */
- at91_smc_write(cfg->smc_cs, AT91_SMC_MODE, cfg->smc_mode);
+ at91_smc_write(cfg->smc_cs, AT91_SAM9_SMC_MODE, cfg->smc_mode);
at91_smc_write(cfg->smc_cs, AT91_SMC_CYCLE, cfg->smc_cycle);
diff --git a/arch/arm/mach-at91/boot_test_cmd.c b/arch/arm/mach-at91/boot_test_cmd.c
index 66c598b7ce..4fd1998ad0 100644
--- a/arch/arm/mach-at91/boot_test_cmd.c
+++ b/arch/arm/mach-at91/boot_test_cmd.c
@@ -7,6 +7,7 @@
#include <common.h>
#include <command.h>
#include <libbb.h>
+#include <libfile.h>
#include <getopt.h>
#include <fs.h>
#include <fcntl.h>
diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c
index 59c4d1111f..9d2a846447 100644
--- a/arch/arm/mach-at91/clock.c
+++ b/arch/arm/mach-at91/clock.c
@@ -65,7 +65,7 @@
#define cpu_has_pllb() (!(cpu_is_at91sam9rl() \
|| cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
- || cpu_is_at91sam9n12()))
+ || cpu_is_sama5d3()))
#define cpu_has_upll() (cpu_is_at91sam9g45() \
|| cpu_is_at91sam9x5() \
diff --git a/arch/arm/mach-at91/include/mach/at91sam9_smc.h b/arch/arm/mach-at91/include/mach/at91sam9_smc.h
index d5cf5f762d..d19cf82eca 100644
--- a/arch/arm/mach-at91/include/mach/at91sam9_smc.h
+++ b/arch/arm/mach-at91/include/mach/at91sam9_smc.h
@@ -43,12 +43,24 @@ struct sam9_smc_config {
/* Mode register */
u32 mode;
u8 tdf_cycles:4;
+
+ /* Timings register */
+ u8 tclr;
+ u8 tadl;
+ u8 tar;
+ u8 ocms;
+ u8 trr;
+ u8 twb;
+ u8 rbnsel;
+ u8 nfsel;
};
extern void sam9_smc_configure(int id, int cs, struct sam9_smc_config *config);
extern void sam9_smc_read(int id, int cs, struct sam9_smc_config *config);
extern void sam9_smc_read_mode(int id, int cs, struct sam9_smc_config *config);
extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config);
+
+extern void sama5_smc_configure(int id, int cs, struct sam9_smc_config *config);
#endif
#define AT91_SMC_SETUP 0x00 /* Setup Register for CS n */
@@ -77,7 +89,26 @@ extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config);
#define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */
#define AT91_SMC_NRDCYCLE_(x) ((x) << 16)
-#define AT91_SMC_MODE 0x0c /* Mode Register for CS n */
+#define AT91_SAMA5_SMC_TIMINGS 0x0c /* Timings register for CS n */
+#define AT91_SMC_TCLR (0x0f << 0) /* CLE to REN Low Delay */
+#define AT91_SMC_TCLR_(x) ((x) << 0)
+#define AT91_SMC_TADL (0x0f << 4) /* ALE to Data Start */
+#define AT91_SMC_TADL_(x) ((x) << 4)
+#define AT91_SMC_TAR (0x0f << 8) /* ALE to REN Low Delay */
+#define AT91_SMC_TAR_(x) ((x) << 8)
+#define AT91_SMC_OCMS (0x1 << 12) /* Off Chip Memory Scrambling Enable */
+#define AT91_SMC_OCMS_(x) ((x) << 12)
+#define AT91_SMC_TRR (0x0f << 16) /* Ready to REN Low Delay */
+#define AT91_SMC_TRR_(x) ((x) << 16)
+#define AT91_SMC_TWB (0x0f << 24) /* WEN High to REN to Busy */
+#define AT91_SMC_TWB_(x) ((x) << 24)
+#define AT91_SMC_RBNSEL (0x07 << 28) /* Ready/Busy Line Selection */
+#define AT91_SMC_RBNSEL_(x) ((x) << 28)
+#define AT91_SMC_NFSEL (0x01 << 31) /* Nand Flash Selection */
+#define AT91_SMC_NFSEL_(x) ((x) << 31)
+
+#define AT91_SAM9_SMC_MODE 0xc
+#define AT91_SAMA5_SMC_MODE 0x10
#define AT91_SMC_READMODE (1 << 0) /* Read Mode */
#define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */
#define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */
diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c
index c7bfdfda63..9f028079c2 100644
--- a/arch/arm/mach-at91/sam9_smc.c
+++ b/arch/arm/mach-at91/sam9_smc.c
@@ -17,7 +17,9 @@
#include <mach/at91sam9_smc.h>
-#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? 0x14 : 0x10)
+#define AT91_SAM9_SMC_CS_STRIDE 0x10
+#define AT91_SAMA5_SMC_CS_STRIDE 0x14
+#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_CS_STRIDE : AT91_SAM9_SMC_CS_STRIDE)
#define AT91_SMC_CS(id, n) (smc_base_addr[id] + ((n) * AT91_SMC_CS_STRIDE))
static void __iomem *smc_base_addr[2];
@@ -25,9 +27,27 @@ static void __iomem *smc_base_addr[2];
static void sam9_smc_cs_write_mode(void __iomem *base,
struct sam9_smc_config *config)
{
+ void __iomem *mode_reg;
+
+ mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE);
+
__raw_writel(config->mode
| AT91_SMC_TDF_(config->tdf_cycles),
- base + AT91_SMC_MODE);
+ mode_reg);
+}
+
+static void sam9_smc_cs_write_timings(void __iomem *base,
+ struct sam9_smc_config *config)
+{
+ __raw_writel(AT91_SMC_TCLR_(config->tclr)
+ | AT91_SMC_TADL_(config->tadl)
+ | AT91_SMC_TAR_(config->tar)
+ | AT91_SMC_OCMS_(config->ocms)
+ | AT91_SMC_TRR_(config->trr)
+ | AT91_SMC_TWB_(config->twb)
+ | AT91_SMC_RBNSEL_(config->rbnsel)
+ | AT91_SMC_NFSEL_(config->nfsel),
+ base + AT91_SAMA5_SMC_TIMINGS);
}
void sam9_smc_write_mode(int id, int cs,
@@ -72,7 +92,12 @@ void sam9_smc_configure(int id, int cs,
static void sam9_smc_cs_read_mode(void __iomem *base,
struct sam9_smc_config *config)
{
- u32 val = __raw_readl(base + AT91_SMC_MODE);
+ u32 val;
+ void __iomem *mode_reg;
+
+ mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE);
+
+ val = __raw_readl(mode_reg);
config->mode = (val & ~AT91_SMC_NWECYCLE);
config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ;
@@ -120,6 +145,13 @@ void sam9_smc_read(int id, int cs, struct sam9_smc_config *config)
sam9_smc_cs_read(AT91_SMC_CS(id, cs), config);
}
+void sama5_smc_configure(int id, int cs, struct sam9_smc_config *config)
+{
+ sam9_smc_configure(id, cs, config);
+
+ sam9_smc_cs_write_timings(AT91_SMC_CS(id, cs), config);
+}
+
static int at91sam9_smc_probe(struct device_d *dev)
{
int id = dev->id;
diff --git a/arch/arm/mach-digic/Kconfig b/arch/arm/mach-digic/Kconfig
new file mode 100644
index 0000000000..d25c3b3f51
--- /dev/null
+++ b/arch/arm/mach-digic/Kconfig
@@ -0,0 +1,15 @@
+if ARCH_DIGIC
+
+choice
+ prompt "camera type"
+
+config MACH_CANON_A1100
+ bool "Canon PowerShot A1100 IS"
+
+endchoice
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x00001900 if MACH_CANON_A1100
+
+endif
diff --git a/arch/arm/mach-digic/Makefile b/arch/arm/mach-digic/Makefile
new file mode 100644
index 0000000000..820eb10ac2
--- /dev/null
+++ b/arch/arm/mach-digic/Makefile
@@ -0,0 +1 @@
+obj-y += core.o
diff --git a/arch/arm/mach-digic/core.c b/arch/arm/mach-digic/core.c
new file mode 100644
index 0000000000..b1caec0bc8
--- /dev/null
+++ b/arch/arm/mach-digic/core.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+
+void __noreturn reset_cpu(unsigned long ignored)
+{
+ pr_err("%s: unimplemented\n", __func__);
+ hang();
+}
+EXPORT_SYMBOL(reset_cpu);
diff --git a/arch/arm/mach-digic/include/mach/debug_ll.h b/arch/arm/mach-digic/include/mach/debug_ll.h
new file mode 100644
index 0000000000..721fd444c2
--- /dev/null
+++ b/arch/arm/mach-digic/include/mach/debug_ll.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_DEBUG_LL_H__
+#define __MACH_DEBUG_LL_H__
+
+#include <io.h>
+#include <mach/digic4.h>
+#include <mach/uart.h>
+
+#define DEBUG_LL_UART DIGIC4_UART
+
+/* Serial interface registers */
+#define DEBUG_LL_UART_TX (DEBUG_LL_UART + DIGIC_UART_TX)
+#define DEBUG_LL_UART_ST (DEBUG_LL_UART + DIGIC_UART_ST)
+
+static inline void PUTC_LL(char ch)
+{
+ while (!(readl(DEBUG_LL_UART_ST) & DIGIC_UART_ST_TX_RDY))
+ ; /* noop */
+
+ writel(0x06, DEBUG_LL_UART_ST);
+ writel(ch, DEBUG_LL_UART_TX);
+}
+
+#endif /* __MACH_DEBUG_LL_H__ */
diff --git a/arch/arm/mach-digic/include/mach/digic4.h b/arch/arm/mach-digic/include/mach/digic4.h
new file mode 100644
index 0000000000..ffc7979a9c
--- /dev/null
+++ b/arch/arm/mach-digic/include/mach/digic4.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DIGIC4_H__
+#define __DIGIC4_H__
+
+#define DIGIC4_UART 0xc0800000
+
+#endif /* __DIGIC4_H__ */
diff --git a/arch/arm/mach-digic/include/mach/uart.h b/arch/arm/mach-digic/include/mach/uart.h
new file mode 100644
index 0000000000..043f7cd0e9
--- /dev/null
+++ b/arch/arm/mach-digic/include/mach/uart.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __DIGIC_UART_H__
+#define __DIGIC_UART_H__
+
+/* Serial interface registers offsets */
+#define DIGIC_UART_TX 0x0
+#define DIGIC_UART_RX 0x4
+#define DIGIC_UART_ST 0x14
+# define DIGIC_UART_ST_RX_RDY 1
+# define DIGIC_UART_ST_TX_RDY 2
+
+#endif /* __DIGIC_UART_H__ */
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 2d99f3eec5..53a44a06e9 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -208,6 +208,12 @@ config MACH_EFIKA_MX_SMARTBOOK
help
Choose this to compile barebox for the Efika MX Smartbook
+config MACH_EMBEDSKY_E9
+ bool "Embedsky E9 Mini-PC"
+ select ARCH_IMX6
+ help
+ Choose this to compile barebox for the Embedsky E9 Mini PC
+
config MACH_FREESCALE_MX51_PDK
bool "Freescale i.MX51 PDK"
select ARCH_IMX51
diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c
index bb8fec2d45..811592f7da 100644
--- a/arch/arm/mach-imx/esdctl.c
+++ b/arch/arm/mach-imx/esdctl.c
@@ -549,9 +549,9 @@ void __naked __noreturn imx53_barebox_entry(void *boarddata)
unsigned long base, size;
upper_or_coalesced_range(MX53_CSD0_BASE_ADDR,
- imx_v3_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 0),
+ imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 0),
MX53_CSD1_BASE_ADDR,
- imx_v3_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 1),
+ imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 1),
&base, &size);
barebox_arm_entry(base, size, boarddata);
diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c
index 125415ec8d..56369a0f94 100644
--- a/arch/arm/mach-imx/imx-bbu-internal.c
+++ b/arch/arm/mach-imx/imx-bbu-internal.c
@@ -168,7 +168,7 @@ static int imx_bbu_internal_v1_update(struct bbu_handler *handler, struct bbu_da
* layer.
*/
static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *imx_handler,
- struct bbu_data *data, void *image, int image_len)
+ struct bbu_data *data)
{
struct mtd_info_user meminfo;
int fd;
@@ -178,6 +178,11 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *
uint32_t *ptr, *num_bb, *bb;
uint64_t offset;
int block = 0, len, now, blocksize;
+ int dbbt_start_page = 4;
+ int firmware_start_page = 12;
+ void *dbbt_base;
+ void *image, *freep = NULL;
+ int pre_image_size;
ret = stat(data->devicefile, &s);
if (ret)
@@ -193,32 +198,40 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *
if (ret)
goto out;
+ pre_image_size = firmware_start_page * meminfo.writesize;
+ image = freep = xzalloc(data->len + pre_image_size);
+ memcpy(image + pre_image_size, data->image, data->len);
+
blocksize = meminfo.erasesize;
ptr = image + 0x4;
*ptr++ = FCB_MAGIC; /* FCB */
*ptr++ = 1; /* FCB version */
+ ptr = image + 0x68; /* Firmware start page */
+ *ptr = firmware_start_page;
+
ptr = image + 0x78; /* DBBT start page */
- *ptr = 4;
+ *ptr = dbbt_start_page;
- ptr = image + 4 * 2048 + 4;
+ dbbt_base = image + dbbt_start_page * meminfo.writesize;
+ ptr = dbbt_base + 4;
*ptr++ = DBBT_MAGIC; /* DBBT */
*ptr = 1; /* DBBT version */
- ptr = (u32*)(image + 0x2010);
+ ptr = (u32*)(dbbt_base + 0x10);
/*
* This is marked as reserved in the i.MX53 reference manual, but
* must be != 0. Otherwise the ROM ignores the DBBT
*/
*ptr = 1;
- ptr = (u32*)(image + 0x4004); /* start of DBBT */
+ ptr = (u32*)(dbbt_base + 4 * meminfo.writesize + 4); /* start of DBBT */
num_bb = ptr;
bb = ptr + 1;
offset = 0;
- size_need = data->len + 0x8000;
+ size_need = data->len + pre_image_size;
/*
* Collect bad blocks and construct DBBT
@@ -261,18 +274,18 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *
}
debug("total image size: 0x%08zx. Space needed including bad blocks: 0x%08zx\n",
- data->len + 0x8000,
- data->len + 0x8000 + *num_bb * blocksize);
+ data->len + pre_image_size,
+ data->len + pre_image_size + *num_bb * blocksize);
- if (data->len + 0x8000 + *num_bb * blocksize > imx_handler->device_size) {
+ if (data->len + pre_image_size + *num_bb * blocksize > imx_handler->device_size) {
printf("needed space (0x%08zx) exceeds partition space (0x%08zx)\n",
- data->len + 0x8000 + *num_bb * blocksize,
+ data->len + pre_image_size + *num_bb * blocksize,
imx_handler->device_size);
ret = -ENOSPC;
goto out;
}
- len = data->len + 0x8000;
+ len = data->len + pre_image_size;
offset = 0;
/*
@@ -312,6 +325,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *
out:
close(fd);
+ free(freep);
return ret;
}
@@ -329,10 +343,7 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da
{
struct imx_internal_bbu_handler *imx_handler =
container_of(handler, struct imx_internal_bbu_handler, handler);
- void *imx_pre_image = NULL;
- int imx_pre_image_size;
- int ret, image_len;
- void *buf;
+ int ret;
uint32_t *barker;
ret = imx_bbu_check_prereq(data);
@@ -346,26 +357,10 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da
return -EINVAL;
}
- imx_pre_image_size = 0;
-
- if (imx_handler->flags & IMX_INTERNAL_FLAG_NAND) {
- /* NAND needs additional space for the DBBT */
- imx_pre_image_size += 0x6000;
- imx_pre_image = xzalloc(imx_pre_image_size);
-
- /* Create a buffer containing header and image data */
- image_len = data->len + imx_pre_image_size;
- buf = xzalloc(image_len);
- memcpy(buf, imx_pre_image, imx_pre_image_size);
- memcpy(buf + imx_pre_image_size, data->image, data->len);
-
- ret = imx_bbu_internal_v2_write_nand_dbbt(imx_handler, data, buf,
- image_len);
- free(buf);
- free(imx_pre_image);
- } else {
+ if (imx_handler->flags & IMX_INTERNAL_FLAG_NAND)
+ ret = imx_bbu_internal_v2_write_nand_dbbt(imx_handler, data);
+ else
ret = imx_bbu_write_device(imx_handler, data, data->image, data->len);
- }
return ret;
}
diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig
index 18f61f74f9..131f3a67ea 100644
--- a/arch/arm/mach-mvebu/Kconfig
+++ b/arch/arm/mach-mvebu/Kconfig
@@ -14,11 +14,13 @@ config ARCH_ARMADA_370
bool "Armada 370"
select CPU_V7
select CLOCKSOURCE_MVEBU
+ select PINCTRL_ARMADA_370
config ARCH_ARMADA_XP
bool "Armada XP"
select CPU_V7
select CLOCKSOURCE_MVEBU
+ select PINCTRL_ARMADA_XP
config ARCH_DOVE
bool "Dove 88AP510"
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index e416a38765..f2b991e5a7 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -18,6 +18,7 @@
#include <init.h>
#include <io.h>
#include <asm/memory.h>
+#include <linux/mbus.h>
#include <mach/armada-370-xp-regs.h>
static inline void armada_370_xp_memory_find(unsigned long *phys_base,
@@ -46,12 +47,20 @@ static inline void armada_370_xp_memory_find(unsigned long *phys_base,
static int armada_370_xp_init_soc(void)
{
unsigned long phys_base, phys_size;
+ u32 reg;
barebox_set_model("Marvell Armada 370/XP");
barebox_set_hostname("armada");
+ /* Disable MBUS error propagation */
+ reg = readl(ARMADA_370_XP_FABRIC_BASE);
+ reg &= ~BIT(8);
+ writel(reg, ARMADA_370_XP_FABRIC_BASE);
+
armada_370_xp_memory_find(&phys_base, &phys_size);
- arm_add_mem_device("ram0", phys_base, phys_size);
+
+ mvebu_set_memory(phys_base, phys_size);
+ mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
return 0;
}
diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c
index b054bf5aff..ac4b332e01 100644
--- a/arch/arm/mach-mvebu/common.c
+++ b/arch/arm/mach-mvebu/common.c
@@ -79,3 +79,62 @@ static int mvebu_soc_id_init(void)
return 0;
}
postcore_initcall(mvebu_soc_id_init);
+
+static u64 mvebu_mem[2];
+
+void mvebu_set_memory(u64 phys_base, u64 phys_size)
+{
+ mvebu_mem[0] = phys_base;
+ mvebu_mem[1] = phys_size;
+}
+
+/*
+ * Memory size is set up by BootROM and can be read from SoC's ram controller
+ * registers. Fixup provided DTs to reflect accessible amount of directly
+ * attached RAM. Removable RAM, e.g. SODIMM, should be added by a per-board
+ * fixup.
+ */
+static int mvebu_memory_of_fixup(struct device_node *root, void *context)
+{
+ struct device_node *np;
+ __be32 reg[4];
+ int na, ns;
+
+ /* bail out on zero-sized mem */
+ if (!mvebu_mem[1])
+ return -ENODEV;
+
+ np = of_find_node_by_path("/memory");
+ if (!np)
+ np = of_create_node(root, "/memory");
+ if (!np)
+ return -EINVAL;
+
+ na = of_n_addr_cells(np);
+ ns = of_n_size_cells(np);
+
+ if (na == 2) {
+ reg[0] = cpu_to_be32(mvebu_mem[0] >> 32);
+ reg[1] = cpu_to_be32(mvebu_mem[0] & 0xffffffff);
+ } else {
+ reg[0] = cpu_to_be32(mvebu_mem[0] & 0xffffffff);
+ }
+
+ if (ns == 2) {
+ reg[2] = cpu_to_be32(mvebu_mem[1] >> 32);
+ reg[3] = cpu_to_be32(mvebu_mem[1] & 0xffffffff);
+ } else {
+ reg[1] = cpu_to_be32(mvebu_mem[1] & 0xffffffff);
+ }
+
+ if (of_set_property(np, "device_type", "memory", sizeof("memory"), 1) ||
+ of_set_property(np, "reg", reg, sizeof(u32) * (na + ns), 1))
+ pr_err("Unable to fixup memory node\n");
+
+ return 0;
+}
+
+static int mvebu_memory_fixup_register(void) {
+ return of_register_fixup(mvebu_memory_of_fixup, NULL);
+}
+pure_initcall(mvebu_memory_fixup_register);
diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c
index bcbf4b8ad7..69c6436b24 100644
--- a/arch/arm/mach-mvebu/dove.c
+++ b/arch/arm/mach-mvebu/dove.c
@@ -18,6 +18,7 @@
#include <init.h>
#include <io.h>
#include <asm/memory.h>
+#include <linux/mbus.h>
#include <mach/dove-regs.h>
static inline void dove_remap_mc_regs(void)
@@ -76,7 +77,10 @@ static int dove_init_soc(void)
dove_remap_mc_regs();
dove_memory_find(&phys_base, &phys_size);
- arm_add_mem_device("ram0", phys_base, phys_size);
+
+ mvebu_set_memory(phys_base, phys_size);
+ mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
+ mvebu_mbus_add_range(0xf0, 0x02, DOVE_REMAP_MC_REGS);
return 0;
}
diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h
index 5fd16e5733..ccc687c03b 100644
--- a/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h
+++ b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h
@@ -42,6 +42,8 @@
#define DDR_SIZE_CS_SHIFT 2
#define DDR_SIZE_MASK 0xff000000
+#define ARMADA_370_XP_FABRIC_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20200)
+
#define ARMADA_370_XP_TIMER_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20300)
#endif /* __MACH_MVEBU_DOVE_REGS_H */
diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h
index 3cc1bf71c0..9f6118e4ec 100644
--- a/arch/arm/mach-mvebu/include/mach/common.h
+++ b/arch/arm/mach-mvebu/include/mach/common.h
@@ -20,4 +20,6 @@
#define MVEBU_REMAP_INT_REG_BASE 0xf1000000
+void mvebu_set_memory(u64 phys_base, u64 phys_size);
+
#endif
diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c
index fe9ca9cbe4..c114bdb360 100644
--- a/arch/arm/mach-mvebu/kirkwood.c
+++ b/arch/arm/mach-mvebu/kirkwood.c
@@ -17,6 +17,7 @@
#include <init.h>
#include <io.h>
#include <asm/memory.h>
+#include <linux/mbus.h>
#include <mach/kirkwood-regs.h>
static inline void kirkwood_memory_find(unsigned long *phys_base,
@@ -50,7 +51,9 @@ static int kirkwood_init_soc(void)
barebox_set_hostname("kirkwood");
kirkwood_memory_find(&phys_base, &phys_size);
- arm_add_mem_device("ram0", phys_base, phys_size);
+
+ mvebu_set_memory(phys_base, phys_size);
+ mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE);
return 0;
}
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index 44585724fe..732de15fec 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -72,7 +72,6 @@ config OMAP_GPMC
config OMAP_BUILD_IFT
prompt "build ift binary (MLO)"
- depends on !OMAP_MULTI_BOARDS
bool
help
Say Y here if you want to build an MLO binary. On TI SoCs, this
@@ -81,7 +80,6 @@ config OMAP_BUILD_IFT
config OMAP_BUILD_SPI
prompt "build SPI binary"
- depends on !OMAP_MULTI_BOARDS
bool
help
Say Y here if you want to build an barebox.spi image as used
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index c9b6f4bb9f..0ebfae7437 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -24,6 +24,7 @@ pbl-$(CONFIG_ARCH_OMAP3) += omap3_generic.o auxcr.o
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_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c
index 606e3918b3..71c528ca8b 100644
--- a/arch/arm/mach-omap/am33xx_generic.c
+++ b/arch/arm/mach-omap/am33xx_generic.c
@@ -19,6 +19,7 @@
#include <init.h>
#include <io.h>
#include <net.h>
+#include <asm/barebox-arm.h>
#include <mach/am33xx-silicon.h>
#include <mach/am33xx-clock.h>
#include <mach/generic.h>
@@ -318,6 +319,61 @@ void am33xx_config_sdram(const struct am33xx_emif_regs *regs)
writel(regs->sdram_config, AM33XX_EMIF4_0_REG(SDRAM_CONFIG));
}
+/**
+ * am335x_sdram_size - read back SDRAM size from sdram_config register
+ *
+ * @return: The SDRAM size
+ */
+unsigned long am335x_sdram_size(void)
+{
+ int rows, cols, width, banks;
+ unsigned long size;
+ uint32_t sdram_config = readl(CM_EMIF_SDRAM_CONFIG);
+
+ rows = ((sdram_config >> 7) & 0x7) + 9;
+ cols = (sdram_config & 0x7) + 8;
+
+ switch ((sdram_config >> 14) & 0x3) {
+ case 0:
+ width = 4;
+ break;
+ case 1:
+ width = 2;
+ break;
+ default:
+ return 0;
+ }
+
+ switch ((sdram_config >> 4) & 0x7) {
+ case 0:
+ banks = 1;
+ break;
+ case 1:
+ banks = 2;
+ break;
+ case 2:
+ banks = 4;
+ break;
+ case 3:
+ banks = 8;
+ break;
+ default:
+ return 0;
+ }
+
+ size = (1 << rows) * (1 << cols) * banks * width;
+
+ debug("%s: sdram_config: 0x%08x cols: %2d rows: %2d width: %2d banks: %2d size: 0x%08lx\n",
+ __func__, sdram_config, cols, rows, width, banks, size);
+
+ return size;
+}
+
+void __noreturn am335x_barebox_entry(void *boarddata)
+{
+ barebox_arm_entry(0x80000000, am335x_sdram_size(), boarddata);
+}
+
void am33xx_config_io_ctrl(int ioctrl)
{
writel(ioctrl, AM33XX_DDR_CMD0_IOCTRL);
diff --git a/arch/arm/mach-omap/am33xx_scrm.c b/arch/arm/mach-omap/am33xx_scrm.c
new file mode 100644
index 0000000000..67529f8226
--- /dev/null
+++ b/arch/arm/mach-omap/am33xx_scrm.c
@@ -0,0 +1,51 @@
+/*
+ * (C) Copyright 2014 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 as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <io.h>
+#include <errno.h>
+#include <sizes.h>
+#include <init.h>
+#include <of.h>
+#include <asm/barebox-arm.h>
+#include <asm/memory.h>
+#include <mach/am33xx-silicon.h>
+
+static int am33xx_scrm_probe(struct device_d *dev)
+{
+ arm_add_mem_device("ram0", 0x80000000, am335x_sdram_size());
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id am33xx_scrm_dt_ids[] = {
+ {
+ .compatible = "ti,am3-scrm",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d am33xx_scrm_driver = {
+ .name = "am33xx-scrm",
+ .probe = am33xx_scrm_probe,
+ .of_compatible = DRV_OF_COMPAT(am33xx_scrm_dt_ids),
+};
+
+static int am33xx_scrm_init(void)
+{
+ return platform_driver_register(&am33xx_scrm_driver);
+}
+
+mem_initcall(am33xx_scrm_init);
diff --git a/arch/arm/mach-omap/include/mach/am33xx-silicon.h b/arch/arm/mach-omap/include/mach/am33xx-silicon.h
index 20b8e81c1c..ceca10a619 100644
--- a/arch/arm/mach-omap/include/mach/am33xx-silicon.h
+++ b/arch/arm/mach-omap/include/mach/am33xx-silicon.h
@@ -237,5 +237,7 @@ void am33xx_config_ddr_data(const struct am33xx_ddr_data *data, int macronr);
void am335x_sdram_init(int ioctrl, const struct am33xx_cmd_control *cmd_ctrl,
const struct am33xx_emif_regs *emif_regs,
const struct am33xx_ddr_data *ddr_data);
+unsigned long am335x_sdram_size(void);
+void am335x_barebox_entry(void *boarddata);
#endif
diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c
index 060c59277f..334cf8db56 100644
--- a/arch/arm/mach-omap/omap_generic.c
+++ b/arch/arm/mach-omap/omap_generic.c
@@ -20,6 +20,7 @@
#include <io.h>
#include <fs.h>
#include <malloc.h>
+#include <libfile.h>
#include <linux/stat.h>
#include <mach/gpmc.h>
#include <mach/generic.h>
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index a309450109..e9d7bbb2e9 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -5,6 +5,7 @@
#include <init.h>
#include <driver.h>
#include <linux/mtd/mtd.h>
+#include <libfile.h>
#include <fs.h>
#include <fcntl.h>
#include <sizes.h>
diff --git a/arch/blackfin/boards/ipe337/cmd_alternate.c b/arch/blackfin/boards/ipe337/cmd_alternate.c
index 992d274847..b332cfb059 100644
--- a/arch/blackfin/boards/ipe337/cmd_alternate.c
+++ b/arch/blackfin/boards/ipe337/cmd_alternate.c
@@ -1,5 +1,6 @@
#include <common.h>
#include <command.h>
+#include <libfile.h>
#include <linux/stat.h>
#include <malloc.h>
#include <fs.h>
diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig
new file mode 100644
index 0000000000..26fecaa392
--- /dev/null
+++ b/arch/efi/Kconfig
@@ -0,0 +1,52 @@
+config ARCH_EFI
+ bool
+ default y
+ select HAS_DEBUG_LL
+ select HAS_KALLSYMS
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select EFI_GUID
+ select EFI_DEVICEPATH
+ select PRINTF_UUID
+ select GENERIC_FIND_NEXT_BIT
+
+config ARCH_TEXT_BASE
+ hex
+ default 0x0
+
+menu "EFI specific settings"
+
+config 64BIT
+ def_bool y
+ help
+ Say yes to build a 64-bit binary - formerly known as x86_64
+ Say no to build a 32-bit binary - formerly known as i386.
+
+ 32-bit support currently does not compile and is not tested
+ due to the lack of hardware.
+
+config X86_32
+ def_bool y
+ depends on !64BIT
+
+config X86_64
+ def_bool y
+ depends on 64BIT
+
+config ARCH_EFI_REGISTER_COM1
+ bool "Register first serial port"
+ help
+ Say yes here to register the first serial port on ioport 0x3f8.
+ This is useful to control barebox over a serial port if the board
+ has one. Enabling this option may not work on boards which do not
+ have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable
+ the NS16550 driver.
+
+endmenu
+
+source common/Kconfig
+source commands/Kconfig
+source net/Kconfig
+source drivers/Kconfig
+source fs/Kconfig
+source lib/Kconfig
+source crypto/Kconfig
diff --git a/arch/efi/Makefile b/arch/efi/Makefile
new file mode 100644
index 0000000000..af280859f0
--- /dev/null
+++ b/arch/efi/Makefile
@@ -0,0 +1,41 @@
+CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx
+
+ifeq ($(CONFIG_X86_32),y)
+ UTS_MACHINE := i386
+ biarch := $(call cc-option,-m32)
+ AFLAGS += $(biarch)
+ CFLAGS += $(biarch)
+ TARGET = efi-app-ia32
+else
+ UTS_MACHINE := x86_64
+ AFLAGS += -m64
+ CFLAGS += -m64 -mno-red-zone
+ TARGET = efi-app-x86_64
+endif
+
+lds-$(CONFIG_X86_32) := arch/efi/lib/elf_ia32_efi.lds
+lds-$(CONFIG_X86_64) := arch/efi/lib/elf_x86_64_efi.lds
+
+cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \
+ -T $(lds-y) \
+ -shared -Bsymbolic -nostdlib -znocombreloc \
+ --start-group $(barebox-common) \
+ --end-group \
+ $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^)
+
+quiet_cmd_efi_image = EFI-IMG $@
+ cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \
+ -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \
+ -j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \
+ --target=$(TARGET) $< $@
+
+KBUILD_BINARY := barebox
+
+LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined
+
+barebox.efi: $(KBUILD_BINARY) FORCE
+ $(call if_changed,efi_image)
+
+KBUILD_IMAGE := barebox.efi
+
+common-y += arch/efi/efi/ arch/efi/lib/
diff --git a/arch/efi/configs/efi_defconfig b/arch/efi/configs/efi_defconfig
new file mode 100644
index 0000000000..456f70d32b
--- /dev/null
+++ b/arch/efi/configs/efi_defconfig
@@ -0,0 +1,78 @@
+CONFIG_MMU=y
+CONFIG_MALLOC_SIZE=0x0
+CONFIG_MALLOC_TLSF=y
+CONFIG_PROMPT="barebox> "
+CONFIG_HUSH_FANCY_PROMPT=y
+CONFIG_CMDLINE_EDITING=y
+CONFIG_AUTO_COMPLETE=y
+CONFIG_MENU=y
+# CONFIG_TIMESTAMP is not set
+CONFIG_CONSOLE_ACTIVATE_ALL=y
+CONFIG_PARTITION_DISK_EFI=y
+CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
+CONFIG_POLLER=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_LL=y
+CONFIG_LONGHELP=y
+CONFIG_CMD_IOMEM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_BOOTM_SHOW_TYPE=y
+CONFIG_CMD_BOOTM_VERBOSE=y
+CONFIG_CMD_BOOTM_INITRD=y
+CONFIG_CMD_BOOTM_OFTREE=y
+CONFIG_CMD_GO=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
+CONFIG_CMD_UIMAGE=y
+CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_LOADENV=y
+CONFIG_CMD_PRINTENV=y
+CONFIG_CMD_MAGICVAR=y
+CONFIG_CMD_MAGICVAR_HELP=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_UNCOMPRESS=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MM=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_2048=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_NET_NFS=y
+CONFIG_NET_NETCONSOLE=y
+CONFIG_DRIVER_SERIAL_EFI_STDIO=y
+CONFIG_DRIVER_SERIAL_NS16550=y
+CONFIG_DRIVER_NET_EFI_SNP=y
+# CONFIG_SPI is not set
+CONFIG_DISK=y
+CONFIG_FS_EXT4=y
+CONFIG_FS_TFTP=y
+CONFIG_FS_NFS=y
+CONFIG_FS_EFI=y
+CONFIG_FS_EFIVARFS=y
+CONFIG_FS_FAT=y
+CONFIG_FS_FAT_WRITE=y
+CONFIG_FS_FAT_LFN=y
diff --git a/arch/efi/efi/Makefile b/arch/efi/efi/Makefile
new file mode 100644
index 0000000000..a856e5907c
--- /dev/null
+++ b/arch/efi/efi/Makefile
@@ -0,0 +1,2 @@
+obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o
+bbenv-y += env-efi
diff --git a/arch/efi/efi/clocksource.c b/arch/efi/efi/clocksource.c
new file mode 100644
index 0000000000..2f33b43cce
--- /dev/null
+++ b/arch/efi/efi/clocksource.c
@@ -0,0 +1,60 @@
+#include <common.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <clock.h>
+
+#ifdef __x86_64__
+uint64_t ticks_read(void)
+{
+ uint64_t a, d;
+
+ __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
+
+ return (d << 32) | a;
+}
+#else
+uint64_t ticks_read(void)
+{
+ uint64_t val;
+
+ __asm__ volatile ("rdtsc" : "=A" (val));
+
+ return val;
+}
+#endif
+
+static uint64_t freq;
+
+/* count TSC ticks during a millisecond delay */
+static uint64_t ticks_freq(void)
+{
+ uint64_t ticks_start, ticks_end;
+
+ ticks_start = ticks_read();
+ BS->stall(1000);
+ ticks_end = ticks_read();
+
+ return (ticks_end - ticks_start) * 1000;
+}
+
+static uint64_t efi_clocksource_read(void)
+{
+ return 1000 * 1000 * ticks_read() / freq;
+}
+
+static struct clocksource cs = {
+ .read = efi_clocksource_read,
+ .mask = CLOCKSOURCE_MASK(64),
+ .shift = 0,
+};
+
+int efi_clocksource_init(void)
+{
+ cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift);
+
+ freq = ticks_freq();
+
+ init_clock(&cs);
+
+ return 0;
+}
diff --git a/arch/efi/efi/efi-block-io.c b/arch/efi/efi/efi-block-io.c
new file mode 100644
index 0000000000..00115317fc
--- /dev/null
+++ b/arch/efi/efi/efi-block-io.c
@@ -0,0 +1,174 @@
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <string.h>
+#include <command.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <efi.h>
+#include <block.h>
+#include <disks.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001
+#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31))
+
+struct efi_block_io_media{
+ u32 media_id;
+ bool removable_media;
+ bool media_present;
+ bool logical_partition;
+ bool read_only;
+ bool write_caching;
+ u32 block_size;
+ u32 io_align;
+ u64 last_block;
+ u64 lowest_aligned_lba; /* added in Revision 2 */
+ u32 logical_blocks_per_physical_block; /* added in Revision 2 */
+ u32 optimal_transfer_length_granularity; /* added in Revision 3 */
+};
+
+struct efi_block_io_protocol {
+ u64 revision;
+ struct efi_block_io_media *media;
+ efi_status_t(EFIAPI *reset)(struct efi_block_io_protocol *this,
+ bool ExtendedVerification);
+ efi_status_t(EFIAPI *read)(struct efi_block_io_protocol *this, u32 media_id,
+ u64 lba, unsigned long buffer_size, void *buf);
+ efi_status_t(EFIAPI *write)(struct efi_block_io_protocol *this, u32 media_id,
+ u64 lba, unsigned long buffer_size, void *buf);
+ efi_status_t(EFIAPI *flush)(struct efi_block_io_protocol *this);
+};
+
+struct efi_bio_priv {
+ struct efi_block_io_protocol *protocol;
+ struct device_d *dev;
+ struct block_device blk;
+ u32 media_id;
+};
+
+static int efi_bio_read(struct block_device *blk, void *buffer, int block,
+ int num_blocks)
+{
+ struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+ efi_status_t efiret;
+
+ efiret = priv->protocol->read(priv->protocol, priv->media_id,
+ block, num_blocks * 512, buffer);
+
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return 0;
+}
+
+static int efi_bio_write(struct block_device *blk,
+ const void *buffer, int block, int num_blocks)
+{
+ struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+ efi_status_t efiret;
+
+ efiret = priv->protocol->write(priv->protocol, priv->media_id,
+ block, num_blocks * 512, (void *)buffer);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return 0;
+}
+
+static int efi_bio_flush(struct block_device *blk)
+{
+ struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk);
+ efi_status_t efiret;
+
+ efiret = priv->protocol->flush(priv->protocol);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return 0;
+}
+
+static struct block_device_ops efi_bio_ops = {
+ .read = efi_bio_read,
+ .write = efi_bio_write,
+ .flush = efi_bio_flush,
+};
+
+static void efi_bio_print_info(struct efi_bio_priv *priv)
+{
+ struct efi_block_io_media *media = priv->protocol->media;
+ u64 revision = priv->protocol->revision;
+
+ dev_dbg(priv->dev, "revision: 0x%016llx\n", revision);
+ dev_dbg(priv->dev, "media_id: 0x%08x\n", media->media_id);
+ dev_dbg(priv->dev, "removable_media: %d\n", media->removable_media);
+ dev_dbg(priv->dev, "media_present: %d\n", media->media_present);
+ dev_dbg(priv->dev, "logical_partition: %d\n", media->logical_partition);
+ dev_dbg(priv->dev, "read_only: %d\n", media->read_only);
+ dev_dbg(priv->dev, "write_caching: %d\n", media->write_caching);
+ dev_dbg(priv->dev, "block_size: 0x%08x\n", media->block_size);
+ dev_dbg(priv->dev, "io_align: 0x%08x\n", media->io_align);
+ dev_dbg(priv->dev, "last_block: 0x%016llx\n", media->last_block);
+
+ if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION2)
+ return;
+
+ dev_dbg(priv->dev, "u64 lowest_aligned_lba: 0x%08llx\n",
+ media->lowest_aligned_lba);
+ dev_dbg(priv->dev, "logical_blocks_per_physical_block: 0x%08x\n",
+ media->logical_blocks_per_physical_block);
+
+ if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION3)
+ return;
+
+ dev_dbg(priv->dev, "optimal_transfer_length_granularity: 0x%08x\n",
+ media->optimal_transfer_length_granularity);
+}
+
+int efi_bio_probe(struct efi_device *efidev)
+{
+ int ret;
+ struct efi_bio_priv *priv;
+ struct efi_block_io_media *media;
+
+ priv = xzalloc(sizeof(*priv));
+
+ BS->handle_protocol(efidev->handle, &efi_block_io_protocol_guid,
+ (void **)&priv->protocol);
+ if (!priv->protocol)
+ return -ENODEV;
+
+ media = priv->protocol->media;
+ efi_bio_print_info(priv);
+ priv->dev = &efidev->dev;
+
+ priv->blk.cdev.name = asprintf("disk%d", cdev_find_free_index("disk"));
+ priv->blk.blockbits = ffs(media->block_size) - 1;
+ priv->blk.num_blocks = media->last_block;
+ priv->blk.ops = &efi_bio_ops;
+ priv->blk.dev = &efidev->dev;
+
+ priv->media_id = media->media_id;
+
+ ret = blockdevice_register(&priv->blk);
+ if (ret)
+ return ret;
+
+ parse_partition_table(&priv->blk);
+
+ return 0;
+}
+
+static struct efi_driver efi_fs_driver = {
+ .driver = {
+ .name = "efi-block-io",
+ },
+ .probe = efi_bio_probe,
+ .guid = EFI_BLOCK_IO_PROTOCOL_GUID,
+};
+device_efi_driver(efi_fs_driver);
diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c
new file mode 100644
index 0000000000..1c9553d906
--- /dev/null
+++ b/arch/efi/efi/efi-device.c
@@ -0,0 +1,349 @@
+/*
+ * efi-device.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <command.h>
+#include <common.h>
+#include <driver.h>
+#include <malloc.h>
+#include <memory.h>
+#include <string.h>
+#include <sizes.h>
+#include <wchar.h>
+#include <init.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+#include <linux/err.h>
+
+int efi_locate_handle(enum efi_locate_search_type search_type,
+ efi_guid_t *protocol,
+ void *search_key,
+ unsigned long *no_handles,
+ efi_handle_t **buffer)
+{
+ efi_status_t efiret;
+ unsigned long buffer_size = 0;
+ efi_handle_t *buf;
+
+ efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
+ NULL);
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL)
+ return -efi_errno(efiret);
+
+ buf = malloc(buffer_size);
+ if (!buf)
+ return -ENOMEM;
+
+ efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size,
+ buf);
+ if (EFI_ERROR(efiret)) {
+ free(buf);
+ return -efi_errno(efiret);
+ }
+
+ *no_handles = buffer_size / sizeof(efi_handle_t);
+ *buffer = buf;
+
+ return 0;
+}
+
+static struct efi_device *efi_find_device(efi_handle_t *handle)
+{
+ struct device_d *dev;
+ struct efi_device *efidev;
+
+ bus_for_each_device(&efi_bus, dev) {
+ efidev = container_of(dev, struct efi_device, dev);
+
+ if (efidev->handle == handle)
+ return efidev;
+ }
+
+ return NULL;
+}
+
+static void efi_devinfo(struct device_d *dev)
+{
+ struct efi_device *efidev = to_efi_device(dev);
+ int i;
+
+ printf("Protocols:\n");
+
+ for (i = 0; i < efidev->num_guids; i++)
+ printf(" %d: %pUl: %s\n", i, &efidev->guids[i],
+ efi_guid_string(&efidev->guids[i]));
+}
+
+static efi_handle_t *efi_find_parent(efi_handle_t *handle)
+{
+ unsigned long handle_count = 0;
+ efi_handle_t *handles = NULL, *parent;
+ unsigned long num_guids;
+ efi_guid_t **guids;
+ int ret, i, j, k;
+ efi_status_t efiret;
+ struct efi_open_protocol_information_entry *entry_buffer;
+ unsigned long entry_count;
+
+ ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
+ if (ret)
+ return NULL;
+
+ /*
+ * Normally one would expect a function/pointer to retrieve the parent.
+ * With EFI we have to:
+ * - get all handles
+ * - for each handle get the registered protocols
+ * - for each protocol get the users
+ * - the user which matches the input handle is the parent
+ */
+ for (i = 0; i < handle_count; i++) {
+ efiret = BS->open_protocol(handles[i], &efi_device_path_protocol_guid,
+ NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(efiret))
+ continue;
+
+ BS->protocols_per_handle(handles[i], &guids, &num_guids);
+ for (j = 0; j < num_guids; j++) {
+ efiret = BS->open_protocol_information(handles[i], guids[j],
+ &entry_buffer, &entry_count);
+ for (k = 0; k < entry_count; k++) {
+ if (entry_buffer[k].controller_handle == NULL)
+ continue;
+ if (entry_buffer[k].controller_handle == handles[i])
+ continue;
+ if (entry_buffer[k].controller_handle == handle) {
+ parent = handles[i];
+ goto out;
+ }
+ }
+ }
+ }
+
+ parent = NULL;
+
+ free(handles);
+out:
+ return parent;
+}
+
+static struct efi_device *efi_add_device(efi_handle_t *handle, efi_guid_t **guids,
+ int num_guids)
+{
+ struct efi_device *efidev;
+ int i;
+ efi_guid_t *guidarr;
+ efi_status_t efiret;
+ void *devpath;
+
+ efidev = efi_find_device(handle);
+ if (efidev)
+ return ERR_PTR(-EEXIST);
+
+ efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
+ NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(efiret))
+ return ERR_PTR(-EINVAL);
+
+ guidarr = malloc(sizeof(efi_guid_t) * num_guids);
+
+ for (i = 0; i < num_guids; i++)
+ memcpy(&guidarr[i], guids[i], sizeof(efi_guid_t));
+
+ efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid,
+ &devpath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(efiret))
+ return ERR_PTR(-EINVAL);
+
+ efidev = xzalloc(sizeof(*efidev));
+
+ efidev->guids = guidarr;
+ efidev->num_guids = num_guids;
+ efidev->handle = handle;
+ efidev->dev.bus = &efi_bus;
+ efidev->dev.id = DEVICE_ID_SINGLE;
+ efidev->dev.info = efi_devinfo;
+ efidev->devpath = devpath;
+
+ BS->handle_protocol(handle, &guidarr[0], &efidev->protocol);
+
+ sprintf(efidev->dev.name, "handle-%p", handle);
+
+ efidev->parent_handle = efi_find_parent(efidev->handle);
+
+ return efidev;
+}
+
+
+static int efi_register_device(struct efi_device *efidev)
+{
+ char *dev_path_str;
+ struct efi_device *parent;
+ int ret;
+
+ if (efi_find_device(efidev->handle))
+ return -EEXIST;
+
+ if (efidev->parent_handle) {
+ parent = efi_find_device(efidev->parent_handle);
+ if (!parent)
+ return -EINVAL;
+
+ efidev->dev.parent = &parent->dev;
+ }
+
+ ret = register_device(&efidev->dev);
+ if (ret)
+ return ret;
+
+ dev_path_str = device_path_to_str(efidev->devpath);
+ if (dev_path_str) {
+ dev_add_param_fixed(&efidev->dev, "devpath", dev_path_str);
+ free(dev_path_str);
+ }
+
+ debug("registered efi device %s\n", dev_name(&efidev->dev));
+
+ return 0;
+}
+
+/**
+ * efi_register_devices - iterate over all EFI handles and register
+ * the devices found
+ *
+ * in barebox we treat all EFI handles which support the device_path
+ * protocol as devices. This function iterates over all handles and
+ * registers the corresponding devices. efi_register_devices is safe
+ * to call multiple times. Already registered devices will be ignored.
+ *
+ */
+void efi_register_devices(void)
+{
+ unsigned long handle_count = 0;
+ efi_handle_t *handles = NULL;
+ unsigned long num_guids;
+ efi_guid_t **guids;
+ int ret, i;
+ struct efi_device **efidevs;
+ int registered;
+
+ ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles);
+ if (ret)
+ return;
+
+ efidevs = xzalloc(handle_count * sizeof(struct efi_device *));
+
+ for (i = 0; i < handle_count; i++) {
+ BS->protocols_per_handle(handles[i], &guids, &num_guids);
+
+ efidevs[i] = efi_add_device(handles[i], guids, num_guids);
+ }
+
+ /*
+ * We have a list of devices we want to register, but can only
+ * register a device when all parents are registered already.
+ * Do this by continiously iterating over the list until no
+ * further devices are registered.
+ */
+ do {
+ registered = 0;
+
+ for (i = 0; i < handle_count; i++) {
+ if (IS_ERR(efidevs[i]))
+ continue;
+
+ ret = efi_register_device(efidevs[i]);
+ if (!ret) {
+ efidevs[i] = ERR_PTR(-EEXIST);
+ registered = 1;
+ }
+ }
+ } while (registered);
+
+ free(efidevs);
+ free(handles);
+}
+
+int efi_connect_all(void)
+{
+ efi_status_t efiret;
+ unsigned long handle_count;
+ efi_handle_t *handle_buffer;
+ int i;
+
+ efiret = BS->locate_handle_buffer(all_handles, NULL, NULL, &handle_count,
+ &handle_buffer);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ for (i = 0; i < handle_count; i++)
+ efiret = BS->connect_controller(handle_buffer[i], NULL, NULL, true);
+
+ if (handle_buffer)
+ BS->free_pool(handle_buffer);
+
+ return 0;
+}
+
+static int efi_bus_match(struct device_d *dev, struct driver_d *drv)
+{
+ struct efi_driver *efidrv = to_efi_driver(drv);
+ struct efi_device *efidev = to_efi_device(dev);
+ int i;
+
+ for (i = 0; i < efidev->num_guids; i++) {
+ if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t)))
+ return 0;
+ }
+
+ return 1;
+}
+
+static int efi_bus_probe(struct device_d *dev)
+{
+ struct efi_driver *efidrv = to_efi_driver(dev->driver);
+ struct efi_device *efidev = to_efi_device(dev);
+
+ return efidrv->probe(efidev);
+}
+
+static void efi_bus_remove(struct device_d *dev)
+{
+ struct efi_driver *efidrv = to_efi_driver(dev->driver);
+ struct efi_device *efidev = to_efi_device(dev);
+
+ return efidrv->remove(efidev);
+}
+
+struct bus_type efi_bus = {
+ .name = "efi",
+ .match = efi_bus_match,
+ .probe = efi_bus_probe,
+ .remove = efi_bus_remove,
+};
+
+static int efi_init_devices(void)
+{
+ bus_register(&efi_bus);
+
+ efi_register_devices();
+
+ return 0;
+}
+core_initcall(efi_init_devices);
diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c
new file mode 100644
index 0000000000..18757d2697
--- /dev/null
+++ b/arch/efi/efi/efi-image.c
@@ -0,0 +1,105 @@
+/*
+ * efi-image.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY 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 <sizes.h>
+#include <memory.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <fs.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+static int efi_execute_image(const char *file)
+{
+ void *exe;
+ size_t size;
+ efi_handle_t handle;
+ efi_status_t efiret;
+ const char *options;
+ efi_loaded_image_t *loaded_image;
+
+ exe = read_file(file, &size);
+ if (!exe)
+ return -EINVAL;
+
+ efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size,
+ &handle);
+ if (EFI_ERROR(efiret)) {
+ pr_err("failed to LoadImage: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);;
+ };
+
+ efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid,
+ (void **)&loaded_image,
+ efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ options = linux_bootargs_get();
+ loaded_image->load_options = strdup_char_to_wchar(options);
+ loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t);
+
+ efiret = BS->start_image(handle, NULL, NULL);
+
+ efi_connect_all();
+ efi_register_devices();
+
+ return 0;
+}
+
+static int do_bootm_efi(struct image_data *data)
+{
+ return efi_execute_image(data->os_file);
+}
+
+static struct image_handler efi_handle_tr = {
+ .name = "EFI Application",
+ .bootm = do_bootm_efi,
+ .filetype = filetype_exe,
+};
+
+static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv)
+{
+ return efi_execute_image(file);
+}
+
+static struct binfmt_hook binfmt_efi_hook = {
+ .type = filetype_exe,
+ .hook = efi_execute,
+};
+
+static int efi_register_image_handler(void)
+{
+ register_image_handler(&efi_handle_tr);
+ binfmt_register(&binfmt_efi_hook);
+
+ return 0;
+}
+late_initcall(efi_register_image_handler);
diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c
new file mode 100644
index 0000000000..ff97783b13
--- /dev/null
+++ b/arch/efi/efi/efi.c
@@ -0,0 +1,343 @@
+/*
+ * efi.c - barebox EFI payload support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY 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 <sizes.h>
+#include <memory.h>
+#include <clock.h>
+#include <command.h>
+#include <magicvar.h>
+#include <init.h>
+#include <driver.h>
+#include <ns16550.h>
+#include <io.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <linux/err.h>
+#include <boot.h>
+#include <fs.h>
+#include <binfmt.h>
+#include <wchar.h>
+#include <envfs.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+efi_runtime_services_t *RT;
+efi_boot_services_t *BS;
+efi_system_table_t *efi_sys_table;
+efi_handle_t efi_parent_image;
+struct efi_device_path *efi_device_path;
+efi_loaded_image_t *efi_loaded_image;
+
+void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size)
+{
+ efi_status_t efiret;
+ void *buf;
+ unsigned long size = 0;
+ s16 *name16 = strdup_char_to_wchar(name);
+
+ efiret = RT->get_variable(name16, vendor, NULL, &size, NULL);
+
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) {
+ buf = ERR_PTR(-efi_errno(efiret));
+ goto out;
+ }
+
+ buf = malloc(size);
+ if (!buf) {
+ buf = ERR_PTR(-ENOMEM);
+ goto out;
+ }
+
+ efiret = RT->get_variable(name16, vendor, NULL, &size, buf);
+ if (EFI_ERROR(efiret)) {
+ free(buf);
+ buf = ERR_PTR(-efi_errno(efiret));
+ goto out;
+ }
+
+ if (var_size)
+ *var_size = size;
+
+out:
+ free(name16);
+
+ return buf;
+}
+
+struct efi_boot {
+ u32 attributes;
+ u16 file_path_len;
+ char *description;
+ struct efi_device_path *path;
+ void *binary;
+};
+
+struct efi_boot *efi_get_boot(int num)
+{
+ struct efi_boot *boot = xzalloc(sizeof(*boot));
+ void *buf, *ptr;
+ int size;
+ char *name;
+
+ name = asprintf("Boot%04X", num);
+
+ buf = efi_get_global_var(name, &size);
+
+ free(name);
+
+ if (!buf) {
+ free(boot);
+ return NULL;
+ }
+
+ ptr = buf;
+
+ boot->attributes = *(u32 *)ptr;
+
+ ptr += sizeof(u32);
+
+ boot->file_path_len = *(u16 *)ptr;
+
+ ptr += sizeof(u16);
+
+ boot->description = strdup_wchar_to_char(ptr);
+
+ ptr += (strlen(boot->description) + 1) * 2;
+
+ printf("description: %s\n", boot->description);
+
+ boot->path = memdup(ptr, boot->file_path_len);
+
+ printf("path: %s\n", device_path_to_str(boot->path));
+
+ return boot;
+}
+
+static int misc_init(void)
+{
+ efi_get_boot(1);
+ efi_get_boot(2);
+ efi_get_boot(3);
+
+ return 0;
+}
+late_initcall(misc_init);
+
+const char *efi_strerror(efi_status_t err)
+{
+ const char *str;
+
+ switch (err) {
+ case EFI_SUCCESS: str = "Success"; break;
+ case EFI_LOAD_ERROR: str = "Load Error"; break;
+ case EFI_INVALID_PARAMETER: str = "Invalid Parameter"; break;
+ case EFI_UNSUPPORTED: str = "Unsupported"; break;
+ case EFI_BAD_BUFFER_SIZE: str = "Bad Buffer Size"; break;
+ case EFI_BUFFER_TOO_SMALL: str = "Buffer Too Small"; break;
+ case EFI_NOT_READY: str = "Not Ready"; break;
+ case EFI_DEVICE_ERROR: str = "Device Error"; break;
+ case EFI_WRITE_PROTECTED: str = "Write Protected"; break;
+ case EFI_OUT_OF_RESOURCES: str = "Out of Resources"; break;
+ case EFI_VOLUME_CORRUPTED: str = "Volume Corrupt"; break;
+ case EFI_VOLUME_FULL: str = "Volume Full"; break;
+ case EFI_NO_MEDIA: str = "No Media"; break;
+ case EFI_MEDIA_CHANGED: str = "Media changed"; break;
+ case EFI_NOT_FOUND: str = "Not Found"; break;
+ case EFI_ACCESS_DENIED: str = "Access Denied"; break;
+ case EFI_NO_RESPONSE: str = "No Response"; break;
+ case EFI_NO_MAPPING: str = "No mapping"; break;
+ case EFI_TIMEOUT: str = "Time out"; break;
+ case EFI_NOT_STARTED: str = "Not started"; break;
+ case EFI_ALREADY_STARTED: str = "Already started"; break;
+ case EFI_ABORTED: str = "Aborted"; break;
+ case EFI_ICMP_ERROR: str = "ICMP Error"; break;
+ case EFI_TFTP_ERROR: str = "TFTP Error"; break;
+ case EFI_PROTOCOL_ERROR: str = "Protocol Error"; break;
+ case EFI_INCOMPATIBLE_VERSION: str = "Incompatible Version"; break;
+ case EFI_SECURITY_VIOLATION: str = "Security Violation"; break;
+ case EFI_CRC_ERROR: str = "CRC Error"; break;
+ case EFI_END_OF_MEDIA: str = "End of Media"; break;
+ case EFI_END_OF_FILE: str = "End of File"; break;
+ case EFI_INVALID_LANGUAGE: str = "Invalid Language"; break;
+ case EFI_COMPROMISED_DATA: str = "Compromised Data"; break;
+ default: str = "unknown error";
+ }
+
+ return str;
+}
+
+int efi_errno(efi_status_t err)
+{
+ int ret;
+
+ switch (err) {
+ case EFI_SUCCESS: ret = 0; break;
+ case EFI_LOAD_ERROR: ret = EIO; break;
+ case EFI_INVALID_PARAMETER: ret = EINVAL; break;
+ case EFI_UNSUPPORTED: ret = ENOTSUPP; break;
+ case EFI_BAD_BUFFER_SIZE: ret = EINVAL; break;
+ case EFI_BUFFER_TOO_SMALL: ret = EINVAL; break;
+ case EFI_NOT_READY: ret = EAGAIN; break;
+ case EFI_DEVICE_ERROR: ret = EIO; break;
+ case EFI_WRITE_PROTECTED: ret = EROFS; break;
+ case EFI_OUT_OF_RESOURCES: ret = ENOMEM; break;
+ case EFI_VOLUME_CORRUPTED: ret = EIO; break;
+ case EFI_VOLUME_FULL: ret = ENOSPC; break;
+ case EFI_NO_MEDIA: ret = ENOMEDIUM; break;
+ case EFI_MEDIA_CHANGED: ret = ENOMEDIUM; break;
+ case EFI_NOT_FOUND: ret = ENODEV; break;
+ case EFI_ACCESS_DENIED: ret = EACCES; break;
+ case EFI_NO_RESPONSE: ret = ETIMEDOUT; break;
+ case EFI_NO_MAPPING: ret = EINVAL; break;
+ case EFI_TIMEOUT: ret = ETIMEDOUT; break;
+ case EFI_NOT_STARTED: ret = EINVAL; break;
+ case EFI_ALREADY_STARTED: ret = EINVAL; break;
+ case EFI_ABORTED: ret = EINTR; break;
+ case EFI_ICMP_ERROR: ret = EINVAL; break;
+ case EFI_TFTP_ERROR: ret = EINVAL; break;
+ case EFI_PROTOCOL_ERROR: ret = EPROTO; break;
+ case EFI_INCOMPATIBLE_VERSION: ret = EINVAL; break;
+ case EFI_SECURITY_VIOLATION: ret = EINVAL; break;
+ case EFI_CRC_ERROR: ret = EINVAL; break;
+ case EFI_END_OF_MEDIA: ret = EINVAL; break;
+ case EFI_END_OF_FILE: ret = EINVAL; break;
+ case EFI_INVALID_LANGUAGE: ret = EINVAL; break;
+ case EFI_COMPROMISED_DATA: ret = EINVAL; break;
+ default: ret = EINVAL;
+ }
+
+ return ret;
+}
+
+static struct NS16550_plat ns16550_plat = {
+ .clock = 115200 * 16,
+};
+
+static int efi_console_init(void)
+{
+ barebox_set_model("barebox EFI payload");
+
+ add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL);
+
+ if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1))
+ add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT,
+ &ns16550_plat);
+
+ return 0;
+}
+console_initcall(efi_console_init);
+
+void reset_cpu(unsigned long addr)
+{
+ BS->exit(efi_parent_image, EFI_SUCCESS, 0, NULL);
+
+ while(1);
+}
+
+extern char image_base[];
+extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[],
+ __barebox_initcalls_end[];
+
+/*
+ * We have a position independent binary generated with -fpic. This function
+ * fixes the linker generated tables.
+ */
+static void fixup_tables(void)
+{
+ initcall_t *initcall;
+ unsigned long offset = (unsigned long)image_base;
+ struct command *cmdtp;
+ struct magicvar *m;
+
+ for (initcall = __barebox_initcalls_start;
+ initcall < __barebox_initcalls_end; initcall++)
+ *initcall += offset;
+
+ for (cmdtp = &__barebox_cmd_start;
+ cmdtp != &__barebox_cmd_end;
+ cmdtp++) {
+ cmdtp->name += offset;
+ cmdtp->cmd += offset;
+ if (cmdtp->complete)
+ cmdtp->complete += offset;
+ if (cmdtp->desc)
+ cmdtp->desc += offset;
+ if (cmdtp->help)
+ cmdtp->help += offset;
+ if (cmdtp->opts)
+ cmdtp->opts += offset;
+ if (cmdtp->aliases)
+ cmdtp->aliases = (void *)cmdtp->aliases + offset;
+ }
+
+ for (m = &__barebox_magicvar_start;
+ m != &__barebox_magicvar_end;
+ m++) {
+ m->name += offset;
+ m->description += offset;
+ }
+}
+
+static int efi_init(void)
+{
+ defaultenv_append_directory(env_efi);
+
+ return 0;
+}
+device_initcall(efi_init);
+
+/**
+ * efi-main - Entry point for EFI images
+ */
+efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table)
+{
+ void *mem;
+ efi_status_t efiret;
+
+#ifdef DEBUG
+ sys_table->con_out->output_string(sys_table->con_out, L"barebox\n");
+#endif
+
+ BS = sys_table->boottime;
+
+ efi_parent_image = image;
+ efi_sys_table = sys_table;
+ RT = sys_table->runtime;
+
+ efiret = BS->open_protocol(efi_parent_image, &efi_loaded_image_protocol_guid,
+ (void **)&efi_loaded_image,
+ efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(efiret))
+ BS->handle_protocol(efi_loaded_image->device_handle,
+ &efi_device_path_protocol_guid, (void **)&efi_device_path);
+
+ fixup_tables();
+
+ BS->allocate_pool(efi_loaded_image->image_data_type, SZ_16M, &mem);
+ mem_malloc_init(mem, mem + SZ_16M);
+
+ efi_clocksource_init();
+
+ start_barebox();
+
+ return EFI_SUCCESS;
+}
diff --git a/arch/efi/efi/env-efi/network/eth0-discover b/arch/efi/efi/env-efi/network/eth0-discover
new file mode 100644
index 0000000000..62c31a553c
--- /dev/null
+++ b/arch/efi/efi/env-efi/network/eth0-discover
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+for i in /boot/network-drivers/*; do
+ $i;
+done
diff --git a/arch/efi/include/asm/barebox.h b/arch/efi/include/asm/barebox.h
new file mode 100644
index 0000000000..2997587d82
--- /dev/null
+++ b/arch/efi/include/asm/barebox.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h
new file mode 100644
index 0000000000..447023da63
--- /dev/null
+++ b/arch/efi/include/asm/bitops.h
@@ -0,0 +1,22 @@
+#ifndef _SANDBOX_BITOPS_H
+#define _SANDBOX_BITOPS_H
+
+/* nothing but the defaults.. */
+#include <asm-generic/bitops/__ffs.h>
+#include <asm-generic/bitops/__fls.h>
+#include <asm-generic/bitops/ffs.h>
+#include <asm-generic/bitops/fls.h>
+#include <asm-generic/bitops/ffz.h>
+#include <asm-generic/bitops/find.h>
+#include <asm-generic/bitops/fls64.h>
+#include <asm-generic/bitops/hweight.h>
+#include <asm-generic/bitops/ops.h>
+
+#define set_bit(x, y) __set_bit(x, y)
+#define clear_bit(x, y) __clear_bit(x, y)
+#define change_bit(x, y) __change_bit(x, y)
+#define test_and_set_bit(x, y) __test_and_set_bit(x, y)
+#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y)
+#define test_and_change_bit(x, y) __test_and_change_bit(x, y)
+
+#endif
diff --git a/arch/efi/include/asm/byteorder.h b/arch/efi/include/asm/byteorder.h
new file mode 100644
index 0000000000..37316f2371
--- /dev/null
+++ b/arch/efi/include/asm/byteorder.h
@@ -0,0 +1,8 @@
+#ifndef _I386_BYTEORDER_H
+#define _I386_BYTEORDER_H
+
+#include <asm/types.h>
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _I386_BYTEORDER_H */
diff --git a/arch/efi/include/asm/common.h b/arch/efi/include/asm/common.h
new file mode 100644
index 0000000000..b0e6b7fb18
--- /dev/null
+++ b/arch/efi/include/asm/common.h
@@ -0,0 +1,4 @@
+#ifndef ASM_COMMON_H
+#define ASM_COMMON_H
+
+#endif /* ASM_COMMON_H */
diff --git a/arch/efi/include/asm/dma.h b/arch/efi/include/asm/dma.h
new file mode 100644
index 0000000000..459536779e
--- /dev/null
+++ b/arch/efi/include/asm/dma.h
@@ -0,0 +1,13 @@
+/*
+ * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de>
+ *
+ * This file is released under the GPLv2
+ *
+ */
+
+#ifndef __ASM_DMA_H
+#define __ASM_DMA_H
+
+/* empty*/
+
+#endif /* __ASM_DMA_H */
diff --git a/arch/efi/include/asm/elf.h b/arch/efi/include/asm/elf.h
new file mode 100644
index 0000000000..ddde035188
--- /dev/null
+++ b/arch/efi/include/asm/elf.h
@@ -0,0 +1,60 @@
+#ifndef __ASM_SANDBOX_ELF_H__
+#define __ASM_SANDBOX_ELF_H__
+
+#ifdef __i386__
+
+typedef struct user_fxsr_struct elf_fpxregset_t;
+
+#define R_386_NONE 0
+#define R_386_32 1
+#define R_386_PC32 2
+#define R_386_GOT32 3
+#define R_386_PLT32 4
+#define R_386_COPY 5
+#define R_386_GLOB_DAT 6
+#define R_386_JMP_SLOT 7
+#define R_386_RELATIVE 8
+#define R_386_GOTOFF 9
+#define R_386_GOTPC 10
+#define R_386_NUM 11
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_386
+
+#else
+
+/* x86-64 relocation types */
+#define R_X86_64_NONE 0 /* No reloc */
+#define R_X86_64_64 1 /* Direct 64 bit */
+#define R_X86_64_PC32 2 /* PC relative 32 bit signed */
+#define R_X86_64_GOT32 3 /* 32 bit GOT entry */
+#define R_X86_64_PLT32 4 /* 32 bit PLT address */
+#define R_X86_64_COPY 5 /* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */
+#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */
+#define R_X86_64_RELATIVE 8 /* Adjust by program base */
+#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative
+ offset to GOT */
+#define R_X86_64_32 10 /* Direct 32 bit zero extended */
+#define R_X86_64_32S 11 /* Direct 32 bit sign extended */
+#define R_X86_64_16 12 /* Direct 16 bit zero extended */
+#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */
+#define R_X86_64_8 14 /* Direct 8 bit sign extended */
+#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */
+
+#define R_X86_64_NUM 16
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS ELFCLASS64
+#define ELF_DATA ELFDATA2LSB
+#define ELF_ARCH EM_X86_64
+
+#endif
+
+#endif /* __ASM_SANDBOX_ELF_H__ */
diff --git a/arch/efi/include/asm/io.h b/arch/efi/include/asm/io.h
new file mode 100644
index 0000000000..ac8a9c1b35
--- /dev/null
+++ b/arch/efi/include/asm/io.h
@@ -0,0 +1,55 @@
+#ifndef __ASM_SANDBOX_IO_H
+#define __ASM_SANDBOX_IO_H
+
+#define build_mmio_read(name, size, type, reg, barrier) \
+ static inline type name(const volatile void *addr) \
+ { type ret; asm volatile("mov" size " %1,%0":reg (ret) \
+ :"m" (*(volatile type*)addr) barrier); return ret; }
+
+build_mmio_read(readb, "b", unsigned char, "=q", :"memory")
+build_mmio_read(readw, "w", unsigned short, "=r", :"memory")
+build_mmio_read(readl, "l", unsigned int, "=r", :"memory")
+
+#define build_mmio_write(name, size, type, reg, barrier) \
+ static inline void name(type val, volatile void *addr) \
+ { asm volatile("mov" size " %0,%1": :reg (val), \
+ "m" (*(volatile type*)addr) barrier); }
+
+build_mmio_write(writeb, "b", unsigned char, "q", :"memory")
+build_mmio_write(writew, "w", unsigned short, "r", :"memory")
+build_mmio_write(writel, "l", unsigned int, "r", :"memory")
+
+#define BUILDIO(bwl, bw, type) \
+static inline void out##bwl(unsigned type value, int port) \
+{ \
+ asm volatile("out" #bwl " %" #bw "0, %w1" \
+ : : "a"(value), "Nd"(port)); \
+} \
+ \
+static inline unsigned type in##bwl(int port) \
+{ \
+ unsigned type value; \
+ asm volatile("in" #bwl " %w1, %" #bw "0" \
+ : "=a"(value) : "Nd"(port)); \
+ return value; \
+} \
+ \
+static inline void outs##bwl(int port, const void *addr, unsigned long count) \
+{ \
+ asm volatile("rep; outs" #bwl \
+ : "+S"(addr), "+c"(count) : "d"(port)); \
+} \
+ \
+static inline void ins##bwl(int port, void *addr, unsigned long count) \
+{ \
+ asm volatile("rep; ins" #bwl \
+ : "+D"(addr), "+c"(count) : "d"(port)); \
+}
+
+BUILDIO(b, b, char)
+BUILDIO(w, w, short)
+BUILDIO(l, , int)
+
+#define IO_SPACE_LIMIT 0xffff
+
+#endif /* __ASM_SANDBOX_IO_H */
diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h
new file mode 100644
index 0000000000..6985b8eb4a
--- /dev/null
+++ b/arch/efi/include/asm/posix_types.h
@@ -0,0 +1,93 @@
+#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
diff --git a/arch/efi/include/asm/sections.h b/arch/efi/include/asm/sections.h
new file mode 100644
index 0000000000..2b8c516038
--- /dev/null
+++ b/arch/efi/include/asm/sections.h
@@ -0,0 +1 @@
+#include <asm-generic/sections.h>
diff --git a/arch/efi/include/asm/string.h b/arch/efi/include/asm/string.h
new file mode 100644
index 0000000000..2997587d82
--- /dev/null
+++ b/arch/efi/include/asm/string.h
@@ -0,0 +1 @@
+/* dummy */
diff --git a/arch/efi/include/asm/swab.h b/arch/efi/include/asm/swab.h
new file mode 100644
index 0000000000..60a90120b6
--- /dev/null
+++ b/arch/efi/include/asm/swab.h
@@ -0,0 +1,6 @@
+#ifndef _ASM_SWAB_H
+#define _ASM_SWAB_H
+
+/* nothing. use generic functions */
+
+#endif /* _ASM_SWAB_H */
diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h
new file mode 100644
index 0000000000..3204448dce
--- /dev/null
+++ b/arch/efi/include/asm/types.h
@@ -0,0 +1,73 @@
+#ifndef __ASM_I386_TYPES_H
+#define __ASM_I386_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef __x86_64__
+/*
+ * This is used in dlmalloc. On X86_64 we need it to be
+ * 64 bit
+ */
+#define INTERNAL_SIZE_T unsigned long
+
+/*
+ * This is a Kconfig variable in the Kernel, but we want to detect
+ * this during compile time, so we set it here.
+ */
+#define CONFIG_PHYS_ADDR_T_64BIT
+
+#endif
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+typedef __signed__ long long __s64;
+typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#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;
+
+#endif /* __KERNEL__ */
+
+#endif
+
+#endif
diff --git a/arch/efi/include/asm/unaligned.h b/arch/efi/include/asm/unaligned.h
new file mode 100644
index 0000000000..d02da6e60d
--- /dev/null
+++ b/arch/efi/include/asm/unaligned.h
@@ -0,0 +1,19 @@
+#ifndef _ASM_SANDBOX_UNALIGNED_H
+#define _ASM_SANDBOX_UNALIGNED_H
+
+/*
+ * The architecture sandbox is compiled on can do unaligned accesses itself.
+ */
+
+#include <linux/unaligned/access_ok.h>
+#include <linux/unaligned/generic.h>
+
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+#define get_unaligned __get_unaligned_le
+#define put_unaligned __put_unaligned_le
+#else
+#define get_unaligned __get_unaligned_be
+#define put_unaligned __put_unaligned_be
+#endif
+
+#endif /* _ASM_SANDBOX_UNALIGNED_H */
diff --git a/arch/efi/include/mach/debug_ll.h b/arch/efi/include/mach/debug_ll.h
new file mode 100644
index 0000000000..0fb2cb8c2a
--- /dev/null
+++ b/arch/efi/include/mach/debug_ll.h
@@ -0,0 +1,20 @@
+#ifndef __MACH_DEBUG_LL_H__
+#define __MACH_DEBUG_LL_H__
+
+#define EFI_DEBUG 0
+#define EFI_DEBUG_CLEAR_MEMORY 0
+
+#include <efi.h>
+#include <mach/efi.h>
+
+static inline void PUTC_LL(char c)
+{
+ uint16_t str[2] = {};
+ struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out;
+
+ str[0] = c;
+
+ con_out->output_string(con_out, str);
+}
+
+#endif
diff --git a/arch/efi/include/mach/efi-device.h b/arch/efi/include/mach/efi-device.h
new file mode 100644
index 0000000000..fe074a44bb
--- /dev/null
+++ b/arch/efi/include/mach/efi-device.h
@@ -0,0 +1,45 @@
+#ifndef __MACH_EFI_DEVICE_H
+#define __MACH_EFI_DEVICE_H
+
+struct efi_device {
+ struct device_d dev;
+ efi_guid_t *guids;
+ int num_guids;
+ efi_handle_t handle;
+ efi_handle_t parent_handle;
+ void *protocol;
+ struct efi_device_path *devpath;
+};
+
+struct efi_driver {
+ struct driver_d driver;
+ int (*probe)(struct efi_device *efidev);
+ void (*remove)(struct efi_device *efidev);
+ efi_guid_t guid;
+};
+
+extern struct bus_type efi_bus;
+
+static inline struct efi_device *to_efi_device(struct device_d *dev)
+{
+ return container_of(dev, struct efi_device, dev);
+}
+
+static inline struct efi_driver *to_efi_driver(struct driver_d *drv)
+{
+ return container_of(drv, struct efi_driver, driver);
+}
+
+#define device_efi_driver(drv) \
+ register_driver_macro(device, efi, drv)
+
+static inline int efi_driver_register(struct efi_driver *efidrv)
+{
+ efidrv->driver.bus = &efi_bus;
+ return register_driver(&efidrv->driver);
+}
+
+int efi_connect_all(void);
+void efi_register_devices(void);
+
+#endif /* __MACH_EFI_DEVICE_H */
diff --git a/arch/efi/include/mach/efi.h b/arch/efi/include/mach/efi.h
new file mode 100644
index 0000000000..1e9782a136
--- /dev/null
+++ b/arch/efi/include/mach/efi.h
@@ -0,0 +1,24 @@
+#ifndef __MACH_EFI_H
+#define __MACH_EFI_H
+
+#include <efi.h>
+
+const char *efi_strerror(efi_status_t err);
+
+extern efi_system_table_t *efi_sys_table;
+extern efi_handle_t efi_parent_image;
+extern struct efi_device_path *efi_device_path;
+extern efi_loaded_image_t *efi_loaded_image;
+
+int efi_errno(efi_status_t err);
+
+int efi_clocksource_init(void);
+
+void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size);
+
+static inline void *efi_get_global_var(char *name, int *var_size)
+{
+ return efi_get_variable(name, &efi_global_variable_guid, var_size);
+}
+
+#endif /* __MACH_EFI_H */
diff --git a/arch/efi/lib/.gitignore b/arch/efi/lib/.gitignore
new file mode 100644
index 0000000000..847e317701
--- /dev/null
+++ b/arch/efi/lib/.gitignore
@@ -0,0 +1,2 @@
+elf_x86_64_efi.lds
+elf_ia32_efi.lds
diff --git a/arch/efi/lib/Makefile b/arch/efi/lib/Makefile
new file mode 100644
index 0000000000..c8a97bae07
--- /dev/null
+++ b/arch/efi/lib/Makefile
@@ -0,0 +1,4 @@
+obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o
+obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o
+extra-$(CONFIG_X86_32) += elf_ia32_efi.lds
+extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds
diff --git a/arch/efi/lib/crt0-efi-ia32.S b/arch/efi/lib/crt0-efi-ia32.S
new file mode 100644
index 0000000000..6f0f2e872e
--- /dev/null
+++ b/arch/efi/lib/crt0-efi-ia32.S
@@ -0,0 +1,76 @@
+/* crt0-efi-ia32.S - x86 EFI startup code.
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+ .text
+ .align 4
+
+ .globl _start
+_start:
+ pushl %ebp
+ movl %esp,%ebp
+
+ pushl 12(%ebp) # copy "image" argument
+ pushl 8(%ebp) # copy "systab" argument
+
+ call 0f
+0: popl %eax
+ movl %eax,%ebx
+
+ addl $image_base-0b,%eax # %eax = ldbase
+ addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC
+
+ pushl %ebx # pass _DYNAMIC as second argument
+ pushl %eax # pass ldbase as first argument
+ call _relocate
+ popl %ebx
+ popl %ebx
+ testl %eax,%eax
+ jne .exit
+
+ call efi_main # call app with "image" and "systab" argument
+
+.exit: leave
+ ret
+
+ /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
+
+ .data
+dummy: .long 0
+
+#define IMAGE_REL_ABSOLUTE 0
+ .section .reloc
+ .long dummy /* Page RVA */
+ .long 10 /* Block Size (2*4+2) */
+ .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */
diff --git a/arch/efi/lib/crt0-efi-x86_64.S b/arch/efi/lib/crt0-efi-x86_64.S
new file mode 100644
index 0000000000..aa03106e9c
--- /dev/null
+++ b/arch/efi/lib/crt0-efi-x86_64.S
@@ -0,0 +1,75 @@
+/* crt0-efi-x86_64.S - x86_64 EFI startup code.
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+ Copyright (C) 2005 Intel Co.
+ Contributed by Fenghua Yu <fenghua.yu@intel.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+ .text
+ .align 4
+
+ .globl _start
+_start:
+ subq $8, %rsp
+ pushq %rcx
+ pushq %rdx
+
+0:
+ lea image_base(%rip), %rdi
+ lea _DYNAMIC(%rip), %rsi
+
+ popq %rcx
+ popq %rdx
+ pushq %rcx
+ pushq %rdx
+ call _relocate
+
+ popq %rdi
+ popq %rsi
+
+ call efi_main
+ addq $8, %rsp
+
+.exit:
+ ret
+
+ /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */
+
+ .data
+dummy: .long 0
+
+#define IMAGE_REL_ABSOLUTE 0
+ .section .reloc, "a"
+label1:
+ .long dummy-label1 /* Page RVA */
+ .long 10 /* Block Size (2*4+2) */
+ .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */
diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/efi/lib/elf_ia32_efi.lds.S
new file mode 100644
index 0000000000..a5f6287500
--- /dev/null
+++ b/arch/efi/lib/elf_ia32_efi.lds.S
@@ -0,0 +1,102 @@
+#include <asm-generic/barebox.lds.h>
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0;
+ image_base = .;
+ .hash : { *(.hash) } /* this MUST come first! */
+ . = ALIGN(4096);
+ .text :
+ {
+ _stext = .;
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ }
+
+ _etext = .;
+
+ . = ALIGN(4096);
+ .sdata : {
+ *(.got.plt)
+ *(.got)
+ *(.srodata)
+ *(.sdata)
+ *(.sbss)
+ *(.scommon)
+ }
+
+ . = ALIGN(4096);
+ _sdata = .;
+
+ .data : {
+ *(.rodata*)
+ *(.data)
+ *(.data1)
+ *(.data.*)
+ *(.sdata)
+ *(.got.plt)
+ *(.got)
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ * it all into .data: */
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+
+ . = ALIGN(64);
+
+ __barebox_initcalls_start = .;
+ __barebox_initcalls : { INITCALLS }
+ __barebox_initcalls_end = .;
+
+ . = ALIGN(64);
+ __barebox_magicvar_start = .;
+ .barebox_magicvar : { BAREBOX_MAGICVARS }
+ __barebox_magicvar_end = .;
+
+ . = ALIGN(64);
+ __barebox_cmd_start = .;
+ __barebox_cmd : { BAREBOX_CMDS }
+ __barebox_cmd_end = .;
+
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+ .rel : {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.got)
+ *(.rel.stab)
+ *(.data.rel.ro.local)
+ *(.data.rel.local)
+ *(.data.rel.ro)
+ *(.data.rel*)
+ }
+
+ . = ALIGN(4096);
+ .reloc : /* This is the PECOFF .reloc section! */
+ {
+ *(.reloc)
+ }
+
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ /DISCARD/ :
+ {
+ *(.rel.reloc)
+ *(.eh_frame)
+ *(.note.GNU-stack)
+ }
+
+ .comment 0 : { *(.comment) }
+}
diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/efi/lib/elf_x86_64_efi.lds.S
new file mode 100644
index 0000000000..d48432d21b
--- /dev/null
+++ b/arch/efi/lib/elf_x86_64_efi.lds.S
@@ -0,0 +1,93 @@
+#include <asm-generic/barebox.lds.h>
+
+/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */
+
+OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
+OUTPUT_ARCH(i386:x86-64)
+ENTRY(_start)
+SECTIONS
+{
+ . = 0;
+ image_base = .;
+ .hash : { *(.hash) } /* this MUST come first! */
+ . = ALIGN(4096);
+ .eh_frame : {
+ *(.eh_frame)
+ }
+
+ . = ALIGN(4096);
+
+ .text : {
+ _stext = .;
+ _text = .;
+ *(.text)
+ *(.text.*)
+ *(.gnu.linkonce.t.*)
+ }
+
+ _etext = .;
+
+ . = ALIGN(4096);
+
+ .reloc : {
+ *(.reloc)
+ }
+
+ . = ALIGN(4096);
+ _sdata = .;
+
+ .data : {
+ *(.rodata*)
+ *(.got.plt)
+ *(.got)
+ *(.data*)
+ *(.sdata)
+ /* the EFI loader doesn't seem to like a .bss section, so we stick
+ * it all into .data: */
+ *(.sbss)
+ *(.scommon)
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ *(.rel.local)
+ }
+
+ . = ALIGN(64);
+
+ __barebox_initcalls_start = .;
+ __barebox_initcalls : { INITCALLS }
+ __barebox_initcalls_end = .;
+
+ . = ALIGN(64);
+ __barebox_magicvar_start = .;
+ .barebox_magicvar : { BAREBOX_MAGICVARS }
+ __barebox_magicvar_end = .;
+
+ . = ALIGN(64);
+ __barebox_cmd_start = .;
+ __barebox_cmd : { BAREBOX_CMDS }
+ __barebox_cmd_end = .;
+
+ . = ALIGN(4096);
+ .dynamic : { *(.dynamic) }
+ . = ALIGN(4096);
+
+ .rela : {
+ *(.rela.data*)
+ *(.rela.got)
+ *(.rela.stab)
+ }
+
+ . = ALIGN(4096);
+ .dynsym : { *(.dynsym) }
+ . = ALIGN(4096);
+ .dynstr : { *(.dynstr) }
+ . = ALIGN(4096);
+ .ignored.reloc : {
+ *(.rela.reloc)
+ *(.eh_frame)
+ *(.note.GNU-stack)
+ }
+
+ .comment 0 : { *(.comment) }
+}
diff --git a/arch/efi/lib/reloc_ia32.c b/arch/efi/lib/reloc_ia32.c
new file mode 100644
index 0000000000..46929631ec
--- /dev/null
+++ b/arch/efi/lib/reloc_ia32.c
@@ -0,0 +1,97 @@
+/* reloc_ia32.c - position independent x86 ELF shared object relocator
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <common.h>
+#include <efi.h>
+
+#include <elf.h>
+
+efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
+{
+ long relsz = 0, relent = 0;
+ Elf32_Rel *rel = 0;
+ unsigned long *addr;
+ int i;
+
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_REL:
+ rel = (Elf32_Rel*)
+ ((unsigned long)dyn[i].d_un.d_ptr
+ + ldbase);
+ break;
+
+ case DT_RELSZ:
+ relsz = dyn[i].d_un.d_val;
+ break;
+
+ case DT_RELENT:
+ relent = dyn[i].d_un.d_val;
+ break;
+
+ case DT_RELA:
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!rel && relent == 0)
+ return EFI_SUCCESS;
+
+ if (!rel || relent == 0)
+ return EFI_LOAD_ERROR;
+
+ while (relsz > 0) {
+ /* apply the relocs */
+ switch (ELF32_R_TYPE (rel->r_info)) {
+ case R_386_NONE:
+ break;
+
+ case R_386_RELATIVE:
+ addr = (unsigned long *)
+ (ldbase + rel->r_offset);
+ *addr += ldbase;
+ break;
+
+ default:
+ break;
+ }
+ rel = (Elf32_Rel*) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/arch/efi/lib/reloc_x86_64.c b/arch/efi/lib/reloc_x86_64.c
new file mode 100644
index 0000000000..1db72f5dbc
--- /dev/null
+++ b/arch/efi/lib/reloc_x86_64.c
@@ -0,0 +1,96 @@
+/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator
+ Copyright (C) 1999 Hewlett-Packard Co.
+ Contributed by David Mosberger <davidm@hpl.hp.com>.
+ Copyright (C) 2005 Intel Co.
+ Contributed by Fenghua Yu <fenghua.yu@intel.com>.
+
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials
+ provided with the distribution.
+ * Neither the name of Hewlett-Packard Co. nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <common.h>
+#include <efi.h>
+
+#include <elf.h>
+
+efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab)
+{
+ long relsz = 0, relent = 0;
+ Elf64_Rel *rel = 0;
+ unsigned long *addr;
+ int i;
+
+ for (i = 0; dyn[i].d_tag != DT_NULL; ++i) {
+ switch (dyn[i].d_tag) {
+ case DT_RELA:
+ rel = (Elf64_Rel*)
+ ((unsigned long)dyn[i].d_un.d_ptr
+ + ldbase);
+ break;
+
+ case DT_RELASZ:
+ relsz = dyn[i].d_un.d_val;
+ break;
+
+ case DT_RELAENT:
+ relent = dyn[i].d_un.d_val;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!rel && relent == 0)
+ return EFI_SUCCESS;
+
+ if (!rel || relent == 0)
+ return EFI_LOAD_ERROR;
+
+ while (relsz > 0) {
+ /* apply the relocs */
+ switch (ELF64_R_TYPE (rel->r_info)) {
+ case R_X86_64_NONE:
+ break;
+
+ case R_X86_64_RELATIVE:
+ addr = (unsigned long *)
+ (ldbase + rel->r_offset);
+ *addr += ldbase;
+ break;
+
+ default:
+ break;
+ }
+ rel = (Elf64_Rel*) ((char *) rel + relent);
+ relsz -= relent;
+ }
+ return EFI_SUCCESS;
+}
diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig
index 6ee302df02..5a1ca36822 100644
--- a/arch/mips/configs/qemu-malta_defconfig
+++ b/arch/mips/configs/qemu-malta_defconfig
@@ -14,6 +14,7 @@ CONFIG_POLLER=y
CONFIG_DEBUG_INFO=y
CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
+CONFIG_CMD_IMD=y
CONFIG_CMD_MEMINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_GO=y
diff --git a/arch/mips/configs/ritmix-rzx50_defconfig b/arch/mips/configs/ritmix-rzx50_defconfig
index e6f10fb938..232faa2659 100644
--- a/arch/mips/configs/ritmix-rzx50_defconfig
+++ b/arch/mips/configs/ritmix-rzx50_defconfig
@@ -29,12 +29,18 @@ CONFIG_CMD_GETOPT=y
CONFIG_CMD_SLEEP=y
CONFIG_CMD_EDIT=y
CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
CONFIG_CMD_POWEROFF=y
+CONFIG_CMD_LED_TRIGGER=y
CONFIG_CMD_OF_NODE=y
CONFIG_CMD_OF_PROPERTY=y
CONFIG_CMD_OFTREE=y
CONFIG_OFDEVICE=y
# CONFIG_SPI is not set
+CONFIG_LED=y
+CONFIG_LED_GPIO=y
+CONFIG_LED_GPIO_OF=y
+CONFIG_LED_TRIGGERS=y
CONFIG_GPIO_JZ4740=y
CONFIG_SHA1=y
CONFIG_SHA224=y
diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile
index 7ccb2f811c..6d6c9a3ce0 100644
--- a/arch/mips/dts/Makefile
+++ b/arch/mips/dts/Makefile
@@ -2,14 +2,4 @@
BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME))
obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o
-dtb-y += ${BUILTIN_DTB}.dtb
-
-.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S
-.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y))
-
-targets += dtbs
-targets += $(dtb-y)
-
-extra-y += $(dtb-y)
-
clean-files := *.dtb *.dtb.S
diff --git a/arch/mips/dts/rzx50.dts b/arch/mips/dts/rzx50.dts
index 360c1bf5de..7ec3352666 100644
--- a/arch/mips/dts/rzx50.dts
+++ b/arch/mips/dts/rzx50.dts
@@ -9,6 +9,16 @@
memory {
reg = <0x00000000 0x4000000>;
};
+
+ gpio-leds {
+ compatible = "gpio-leds";
+
+ lcd-backlight-enable {
+ label = "lcd backlight";
+ gpios = <&gpio4 22 0>;
+ linux,default-trigger = "default-on";
+ };
+ };
};
&serial1 {
diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S
index 4ee4252b6d..c690e71976 100644
--- a/arch/mips/lib/barebox.lds.S
+++ b/arch/mips/lib/barebox.lds.S
@@ -49,6 +49,8 @@ SECTIONS
. = ALIGN(4);
.data : { *(.data*) }
+ .barebox_imd : { BAREBOX_IMD }
+
. = ALIGN(4);
.got : { *(.got*) }
diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c
index 3d6a4ce648..0e03aa9bcb 100644
--- a/arch/mips/lib/bootm.c
+++ b/arch/mips/lib/bootm.c
@@ -1,5 +1,6 @@
#include <boot.h>
#include <common.h>
+#include <libfile.h>
#include <init.h>
#include <fs.h>
#include <errno.h>
diff --git a/arch/mips/pbl/zbarebox.lds.S b/arch/mips/pbl/zbarebox.lds.S
index 3a26942b4c..a883fdb2db 100644
--- a/arch/mips/pbl/zbarebox.lds.S
+++ b/arch/mips/pbl/zbarebox.lds.S
@@ -44,6 +44,8 @@ SECTIONS
. = ALIGN(4);
.rodata : { *(.rodata*) }
+ .barebox_imd : { BAREBOX_IMD }
+
_etext = .; /* End of text and rodata section */
. = ALIGN(4);
diff --git a/commands/Kconfig b/commands/Kconfig
index 61816f5115..71cd1ee99e 100644
--- a/commands/Kconfig
+++ b/commands/Kconfig
@@ -148,6 +148,15 @@ config CMD_IOMEM
Show information about iomem/ioport usage. Pendant to
'cat /proc/iomem' and 'cat /proc/ioports' under Linux.
+config CMD_IMD
+ tristate
+ prompt "imd"
+ select IMD
+ help
+ barebox images can have metadata in them which contains information
+ like the barebox version and the build time. Say yes here to get the
+ imd command which can extract that information from images.
+
config CMD_MEMINFO
tristate
prompt "meminfo"
@@ -1859,7 +1868,7 @@ endmenu
-menu "Miscelleanous"
+menu "Miscellaneous"
config CMD_2048
tristate
@@ -1976,7 +1985,7 @@ config CMD_TIME
Note: This command depends on COMMAND being interruptible,
otherwise the timer may overrun resulting in incorrect results
-# end Miscelleanous commands
+# end Miscellaneous commands
endmenu
diff --git a/commands/Makefile b/commands/Makefile
index d42aca5c0c..44741360e2 100644
--- a/commands/Makefile
+++ b/commands/Makefile
@@ -100,3 +100,4 @@ obj-$(CONFIG_CMD_MENUTREE) += menutree.o
obj-$(CONFIG_CMD_2048) += 2048.o
obj-$(CONFIG_CMD_REGULATOR) += regulator.o
obj-$(CONFIG_CMD_LSPCI) += lspci.o
+obj-$(CONFIG_CMD_IMD) += imd.o
diff --git a/commands/barebox-update.c b/commands/barebox-update.c
index a24dc3ef4d..92e0efab6a 100644
--- a/commands/barebox-update.c
+++ b/commands/barebox-update.c
@@ -17,6 +17,7 @@
*/
#include <common.h>
#include <command.h>
+#include <libfile.h>
#include <getopt.h>
#include <malloc.h>
#include <errno.h>
diff --git a/commands/cp.c b/commands/cp.c
index 1a5675405e..af7a3d4dc0 100644
--- a/commands/cp.c
+++ b/commands/cp.c
@@ -26,6 +26,7 @@
#include <malloc.h>
#include <libgen.h>
#include <getopt.h>
+#include <libfile.h>
/**
* @param[in] argc Argument count from command line
diff --git a/commands/crc.c b/commands/crc.c
index 7c2936c23c..9b6a3e2a4b 100644
--- a/commands/crc.c
+++ b/commands/crc.c
@@ -22,6 +22,7 @@
#include <fs.h>
#include <getopt.h>
#include <malloc.h>
+#include <libfile.h>
#include <environment.h>
static int crc_from_file(const char* file, ulong *crc)
diff --git a/commands/dfu.c b/commands/dfu.c
index 354625260d..7f78f3bbc2 100644
--- a/commands/dfu.c
+++ b/commands/dfu.c
@@ -172,12 +172,15 @@ out:
BAREBOX_CMD_HELP_START(dfu)
BAREBOX_CMD_HELP_TEXT("Turn's the USB host into DFU mode (Device Firmware Mode) and accepts")
-BAREBOX_CMD_HELP_TEXT("a new firmware. The destination is described by DESC in the this format:")
-BAREBOX_CMD_HELP_TEXT(" DEVICE(NAME)[src]...")
-BAREBOX_CMD_HELP_TEXT("Specify the '(') and ')' literal, the [] however denote this optional modes:")
-BAREBOX_CMD_HELP_TEXT("- 's' safe mode (download the complete image before flashing)")
-BAREBOX_CMD_HELP_TEXT("- 'r' readback of the firmware is allowed")
-BAREBOX_CMD_HELP_TEXT("- 'c' the file will be created (for use with regular files)")
+BAREBOX_CMD_HELP_TEXT("a new firmware. The destination is described by DESC in the format")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("\tDEVICE(NAME)[src]...")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Here '(' and ')' are literal characters. The '[' and ']' however denote")
+BAREBOX_CMD_HELP_TEXT("one of the following optional modes:")
+BAREBOX_CMD_HELP_TEXT("'s': safe mode (download the complete image before flashing); ")
+BAREBOX_CMD_HELP_TEXT("'r': readback of the firmware is allowed; ")
+BAREBOX_CMD_HELP_TEXT("'c': the file will be created (for use with regular files).")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-m STR", "Manufacturer string (barebox)")
diff --git a/commands/edit.c b/commands/edit.c
index 5a2da7d034..b28e2b92a1 100644
--- a/commands/edit.c
+++ b/commands/edit.c
@@ -21,6 +21,7 @@
#include <fs.h>
#include <linux/ctype.h>
#include <fcntl.h>
+#include <libfile.h>
#include <readkey.h>
#include <errno.h>
#include <xfuncs.h>
@@ -379,7 +380,16 @@ static int do_edit(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
screenwidth = 80;
- screenheight = 25;
+
+ /*
+ * The EFI simple text output protocol wraps to the next line and scrolls
+ * down when we write to the right bottom screen position. Reduce the number
+ * of rows by one to work around this.
+ */
+ if (IS_ENABLED(CONFIG_ARCH_EFI))
+ screenheight = 24;
+ else
+ screenheight = 25;
/* check if we are called as "sedit" instead of "edit" */
if (*argv[0] == 's') {
diff --git a/commands/exec.c b/commands/exec.c
index 635f65eeb2..7c8934f137 100644
--- a/commands/exec.c
+++ b/commands/exec.c
@@ -23,6 +23,7 @@
#include <fcntl.h>
#include <linux/stat.h>
#include <errno.h>
+#include <libfile.h>
#include <malloc.h>
#include <xfuncs.h>
diff --git a/commands/help.c b/commands/help.c
index 9c33807fad..898533594f 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -128,7 +128,7 @@ static int do_help(int argc, char *argv[])
BAREBOX_CMD_HELP_START(help)
-BAREBOX_CMD_HELP_TEXT("Without arguments, lists all all commands. With an argument, print help")
+BAREBOX_CMD_HELP_TEXT("Without arguments, lists all commands. With an argument, print help")
BAREBOX_CMD_HELP_TEXT("about the specified command. If the argument is 'all', then output help")
BAREBOX_CMD_HELP_TEXT("for all commands.")
BAREBOX_CMD_HELP_TEXT("")
diff --git a/commands/i2c.c b/commands/i2c.c
index 2811f6abeb..d6c5412762 100644
--- a/commands/i2c.c
+++ b/commands/i2c.c
@@ -75,7 +75,7 @@ static int do_i2c_write(int argc, char *argv[])
int addr = -1, reg = -1, count = -1, verbose = 0, ret, opt, i, bus = 0, wide = 0;
u8 *buf;
- while ((opt = getopt(argc, argv, "a:b:r:v:w")) > 0) {
+ while ((opt = getopt(argc, argv, "a:b:r:vw")) > 0) {
switch (opt) {
case 'a':
addr = simple_strtol(optarg, NULL, 0);
@@ -90,7 +90,7 @@ static int do_i2c_write(int argc, char *argv[])
verbose = 1;
break;
case 'w':
- wide = 1;
+ wide = I2C_ADDR_16_BIT;
break;
}
}
@@ -113,9 +113,13 @@ static int do_i2c_write(int argc, char *argv[])
for (i = 0; i < count; i++)
*(buf + i) = (char) simple_strtol(argv[optind+i], NULL, 16);
- ret = i2c_write_reg(&client, reg | (wide ? I2C_ADDR_16_BIT : 0), buf, count);
- if (ret != count)
+ ret = i2c_write_reg(&client, reg | wide, buf, count);
+ if (ret != count) {
+ if (verbose)
+ printf("write aborted, count(%i) != writestatus(%i)\n",
+ count, ret);
goto out;
+ }
ret = 0;
if (verbose) {
@@ -155,7 +159,7 @@ static int do_i2c_read(int argc, char *argv[])
u8 *buf;
int count = -1, addr = -1, reg = -1, verbose = 0, ret, opt, bus = 0, wide = 0;
- while ((opt = getopt(argc, argv, "a:b:c:r:v:w")) > 0) {
+ while ((opt = getopt(argc, argv, "a:b:c:r:vw")) > 0) {
switch (opt) {
case 'a':
addr = simple_strtol(optarg, NULL, 0);
@@ -173,7 +177,7 @@ static int do_i2c_read(int argc, char *argv[])
verbose = 1;
break;
case 'w':
- wide = 1;
+ wide = I2C_ADDR_16_BIT;
break;
}
}
@@ -191,7 +195,7 @@ static int do_i2c_read(int argc, char *argv[])
client.addr = addr;
buf = xmalloc(count);
- ret = i2c_read_reg(&client, reg | (wide ? I2C_ADDR_16_BIT : 0), buf, count);
+ ret = i2c_read_reg(&client, reg | wide, buf, count);
if (ret == count) {
int i;
if (verbose)
diff --git a/commands/imd.c b/commands/imd.c
new file mode 100644
index 0000000000..f1a22cef96
--- /dev/null
+++ b/commands/imd.c
@@ -0,0 +1,60 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <command.h>
+#include <complete.h>
+#include <environment.h>
+#include <image-metadata.h>
+
+int imd_command_setenv(const char *variable_name, const char *value)
+{
+ return setenv(variable_name, value);
+}
+
+static int do_imd(int argc, char *argv[])
+{
+ int ret;
+
+ ret = imd_command(argc, argv);
+
+ if (ret == -ENOSYS)
+ return COMMAND_ERROR_USAGE;
+
+ return ret;
+}
+
+BAREBOX_CMD_HELP_START(imd)
+BAREBOX_CMD_HELP_TEXT("extract metadata from barebox binary")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_OPT ("-t <type>", "only show information of <type>")
+BAREBOX_CMD_HELP_OPT ("-n <no>", "for tags with multiple strings only show string <no>")
+BAREBOX_CMD_HELP_OPT ("-s VARNAME", "set variable VARNAME instead of showing information")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("Without options all information available is printed. Valid types are:")
+BAREBOX_CMD_HELP_TEXT("release, build, model, of_compatible")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(imd)
+ .cmd = do_imd,
+ BAREBOX_CMD_DESC("extract metadata from barebox binary")
+ BAREBOX_CMD_OPTS("[nst] FILE")
+ BAREBOX_CMD_GROUP(CMD_GRP_INFO)
+ BAREBOX_CMD_HELP(cmd_imd_help)
+BAREBOX_CMD_END
diff --git a/commands/insmod.c b/commands/insmod.c
index 176437ee70..735dde0222 100644
--- a/commands/insmod.c
+++ b/commands/insmod.c
@@ -3,6 +3,7 @@
#include <module.h>
#include <errno.h>
#include <fs.h>
+#include <libfile.h>
#include <malloc.h>
static int do_insmod(int argc, char *argv[])
diff --git a/commands/linux16.c b/commands/linux16.c
index 594efc7dc2..bb678bdb83 100644
--- a/commands/linux16.c
+++ b/commands/linux16.c
@@ -24,6 +24,7 @@
#include <environment.h>
#include <fs.h>
#include <errno.h>
+#include <libfile.h>
#include <getopt.h>
#include <malloc.h>
#include <boot.h>
diff --git a/commands/lspci.c b/commands/lspci.c
index c00b57f894..fdf02691b5 100644
--- a/commands/lspci.c
+++ b/commands/lspci.c
@@ -46,7 +46,7 @@ static int do_lspci(int argc, char *argv[])
BAREBOX_CMD_START(lspci)
.cmd = do_lspci,
- BAREBOX_CMD_DESC("Show PCI info")
+ BAREBOX_CMD_DESC("show PCI info")
BAREBOX_CMD_GROUP(CMD_GRP_INFO)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
diff --git a/commands/of_dump.c b/commands/of_dump.c
index cafde07b7c..315dbbae8c 100644
--- a/commands/of_dump.c
+++ b/commands/of_dump.c
@@ -18,6 +18,7 @@
*/
#include <common.h>
+#include <libfile.h>
#include <fdt.h>
#include <of.h>
#include <command.h>
diff --git a/commands/oftree.c b/commands/oftree.c
index 983a0a59ea..8a47c0be58 100644
--- a/commands/oftree.c
+++ b/commands/oftree.c
@@ -26,6 +26,7 @@
#include <common.h>
#include <environment.h>
#include <fdt.h>
+#include <libfile.h>
#include <of.h>
#include <command.h>
#include <fs.h>
@@ -42,7 +43,7 @@
static int do_oftree(int argc, char *argv[])
{
struct fdt_header *fdt = NULL;
- int size;
+ size_t size;
int opt;
int probe = 0;
char *load = NULL;
diff --git a/commands/readf.c b/commands/readf.c
index c8cc574f35..8dd5a2b55a 100644
--- a/commands/readf.c
+++ b/commands/readf.c
@@ -1,6 +1,7 @@
#include <common.h>
#include <command.h>
#include <fs.h>
+#include <libfile.h>
#include <malloc.h>
#include <linux/stat.h>
#include <linux/ctype.h>
diff --git a/commands/saveenv.c b/commands/saveenv.c
index 54b6fa1b7b..9da733e722 100644
--- a/commands/saveenv.c
+++ b/commands/saveenv.c
@@ -18,26 +18,39 @@
#include <common.h>
#include <command.h>
#include <errno.h>
+#include <getopt.h>
#include <fs.h>
#include <fcntl.h>
#include <envfs.h>
static int do_saveenv(int argc, char *argv[])
{
- int ret;
+ int ret, opt;
+ unsigned envfs_flags = 0;
char *filename, *dirname;
printf("saving environment\n");
- if (argc < 3)
+ while ((opt = getopt(argc, argv, "z")) > 0) {
+ switch (opt) {
+ case 'z':
+ envfs_flags |= ENVFS_FLAGS_FORCE_BUILT_IN;
+ break;
+ }
+ }
+
+ /* destination and source are given? */
+ if (argc == optind + 2)
+ dirname = argv[optind + 1];
+ else
dirname = "/env";
+
+ /* destination only given? */
+ if (argc == optind + 1)
+ filename = argv[optind];
else
- dirname = argv[2];
- if (argc < 2)
filename = default_environment_path_get();
- else
- filename = argv[1];
- ret = envfs_save(filename, dirname);
+ ret = envfs_save(filename, dirname, envfs_flags);
return ret;
}
@@ -47,15 +60,15 @@ BAREBOX_CMD_HELP_TEXT("Save the files in DIRECTORY to the persistent storage dev
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("ENVFS is usually a block in flash but can be any other file. If")
BAREBOX_CMD_HELP_TEXT("omitted, DIRECTORY defaults to /env and ENVFS defaults to")
-BAREBOX_CMD_HELP_TEXT("/dev/env0. Note that envfs can only handle files, directories are being")
-BAREBOX_CMD_HELP_TEXT("skipped silently.")
+BAREBOX_CMD_HELP_TEXT("/dev/env0.")
+BAREBOX_CMD_HELP_OPT ("-z", "force the built-in default environment at startup")
BAREBOX_CMD_HELP_END
BAREBOX_CMD_START(saveenv)
.cmd = do_saveenv,
BAREBOX_CMD_DESC("save environment to persistent storage")
- BAREBOX_CMD_OPTS("[ENVFS] [DIRECTORY]")
+ BAREBOX_CMD_OPTS("[-z] [ENVFS [DIRECTORY]]")
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_saveenv_help)
BAREBOX_CMD_END
diff --git a/commands/tftp.c b/commands/tftp.c
index c066631ad4..8a3b541382 100644
--- a/commands/tftp.c
+++ b/commands/tftp.c
@@ -24,6 +24,7 @@
#include <fs.h>
#include <net.h>
#include <libbb.h>
+#include <libfile.h>
#define TFTP_MOUNT_PATH "/.tftp_tmp_path"
@@ -92,7 +93,8 @@ err_free:
}
BAREBOX_CMD_HELP_START(tftp)
-BAREBOX_CMD_HELP_TEXT("Load (or save) a file via TFTP.")
+BAREBOX_CMD_HELP_TEXT("Load (or save) a file via TFTP. SOURCE is a path on server,")
+BAREBOX_CMD_HELP_TEXT("server address is taken from the environment (ethX.serverip).")
BAREBOX_CMD_HELP_TEXT("")
BAREBOX_CMD_HELP_TEXT("Options:")
BAREBOX_CMD_HELP_OPT ("-p", "push to TFTP server")
diff --git a/commands/trigger.c b/commands/trigger.c
index 17c8411501..b605448a91 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -68,8 +68,9 @@ static int do_trigger(int argc, char *argv[])
break;
case LED_COMMAND_DISABLE_TRIGGER:
- led_set_trigger(trigger, NULL);
- return 0;
+ ret = led_set_trigger(trigger, NULL);
+ break;
+
case LED_COMMAND_SET_TRIGGER:
if (argc - optind != 1)
return COMMAND_ERROR_USAGE;
diff --git a/commands/ubiformat.c b/commands/ubiformat.c
index 443d645a5a..df0b801da9 100644
--- a/commands/ubiformat.c
+++ b/commands/ubiformat.c
@@ -40,6 +40,7 @@
#include <malloc.h>
#include <ioctl.h>
#include <libbb.h>
+#include <libfile.h>
#include <linux/mtd/mtd.h>
#include <linux/kernel.h>
#include <linux/stat.h>
diff --git a/commands/uimage.c b/commands/uimage.c
index 33523d7e5c..7c2dca41ec 100644
--- a/commands/uimage.c
+++ b/commands/uimage.c
@@ -7,6 +7,7 @@
#include <malloc.h>
#include <errno.h>
#include <getopt.h>
+#include <libfile.h>
static int uimage_fd;
diff --git a/common/Kconfig b/common/Kconfig
index 6aa0aac991..d3d9b884cf 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -80,6 +80,14 @@ config MENUTREE
select GLOB
select GLOB_SORT
+config EFI_GUID
+ bool
+ help
+ With this option a table of EFI guids is compiled in.
+
+config EFI_DEVICEPATH
+ bool
+
menu "General Settings"
config LOCALVERSION
@@ -473,6 +481,13 @@ config BLSPEC
on a device and it allows the Operating System to install / update
kernels.
+config IMD
+ bool "barebox metadata support"
+
+config IMD_TARGET
+ bool "build bareboximd target tool"
+ depends on IMD
+
config KERNEL_INSTALL_TARGET
bool
depends on !SANDBOX
diff --git a/common/Makefile b/common/Makefile
index 204241c919..ddd7db2578 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -43,7 +43,11 @@ obj-$(CONFIG_RESET_SOURCE) += reset_source.o
obj-$(CONFIG_SHELL_HUSH) += hush.o
obj-$(CONFIG_SHELL_SIMPLE) += parser.o
obj-$(CONFIG_UIMAGE) += image.o uimage.o
-obj-$(CONFIG_MENUTREE) += menutree.o
+obj-$(CONFIG_MENUTREE) += menutree.o
+obj-$(CONFIG_EFI_GUID) += efi-guid.o
+obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o
+lwl-$(CONFIG_IMD) += imd-barebox.o
+obj-$(CONFIG_IMD) += imd.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/block.c b/common/block.c
index e522ee425a..0edc8619ef 100644
--- a/common/block.c
+++ b/common/block.c
@@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk)
}
}
+ if (blk->ops->flush)
+ return blk->ops->flush(blk);
+
return 0;
}
diff --git a/common/blspec.c b/common/blspec.c
index 9314eeab04..a4adc48da9 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -21,6 +21,7 @@
#include <malloc.h>
#include <block.h>
#include <fcntl.h>
+#include <libfile.h>
#include <libbb.h>
#include <init.h>
#include <boot.h>
diff --git a/common/bootm.c b/common/bootm.c
index 71390cb845..447c9b624c 100644
--- a/common/bootm.c
+++ b/common/bootm.c
@@ -16,6 +16,7 @@
#include <fs.h>
#include <malloc.h>
#include <memory.h>
+#include <libfile.h>
#include <globalvar.h>
#include <init.h>
diff --git a/common/console.c b/common/console.c
index aa9e3ce0f5..e5f4267cbd 100644
--- a/common/console.c
+++ b/common/console.c
@@ -162,6 +162,22 @@ static void console_set_stdoutpath(struct console_device *cdev)
free(str);
}
+static int __console_puts(struct console_device *cdev, const char *s)
+{
+ int n = 0;
+
+ while (*s) {
+ if (*s == '\n') {
+ cdev->putc(cdev, '\r');
+ n++;
+ }
+ cdev->putc(cdev, *s);
+ n++;
+ s++;
+ }
+ return n;
+}
+
int console_register(struct console_device *newcdev)
{
struct device_d *dev = &newcdev->class_dev;
@@ -170,8 +186,14 @@ int console_register(struct console_device *newcdev)
if (initialized == CONSOLE_UNINITIALIZED)
console_init_early();
- dev->id = DEVICE_ID_DYNAMIC;
- strcpy(dev->name, "cs");
+ if (newcdev->devname) {
+ dev->id = DEVICE_ID_SINGLE;
+ strcpy(dev->name, newcdev->devname);
+ } else {
+ dev->id = DEVICE_ID_DYNAMIC;
+ strcpy(dev->name, "cs");
+ }
+
if (newcdev->dev)
dev->parent = newcdev->dev;
platform_device_register(dev);
@@ -182,6 +204,9 @@ int console_register(struct console_device *newcdev)
NULL, &newcdev->baudrate, "%u", newcdev);
}
+ if (newcdev->putc && !newcdev->puts)
+ newcdev->puts = __console_puts;
+
dev_add_param(dev, "active", console_std_set, NULL, 0);
if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) {
@@ -342,9 +367,19 @@ EXPORT_SYMBOL(console_putc);
int console_puts(unsigned int ch, const char *str)
{
+ struct console_device *cdev;
const char *s = str;
int n = 0;
+ if (initialized == CONSOLE_INIT_FULL) {
+ for_each_console(cdev) {
+ if (cdev->f_active & ch) {
+ n = cdev->puts(cdev, str);
+ }
+ }
+ return n;
+ }
+
while (*s) {
if (*s == '\n') {
console_putc(ch, '\r');
diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c
new file mode 100644
index 0000000000..2b1d916768
--- /dev/null
+++ b/common/efi-devicepath.c
@@ -0,0 +1,1370 @@
+#include <common.h>
+#include <efi.h>
+#include <malloc.h>
+#include <string.h>
+#include <wchar.h>
+
+struct string {
+ char *str;
+ int len;
+};
+
+char *cprintf(struct string *str, const char *fmt, ...)
+ __attribute__ ((format(__printf__, 2, 3)));
+
+char *cprintf(struct string *str, const char *fmt, ...)
+{
+ va_list args;
+ int len;
+
+ va_start(args, fmt);
+ if (str->str)
+ len = vsprintf(str->str + str->len, fmt, args);
+ else
+ len = vsnprintf(NULL, 0, fmt, args);
+ va_end(args);
+
+ str->len += len;
+
+ return NULL;
+}
+
+#define MIN_ALIGNMENT_SIZE 8 /* FIXME: X86_64 specific */
+#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0)
+
+#define EFI_DP_TYPE_MASK 0x7f
+#define EFI_DP_TYPE_UNPACKED 0x80
+
+#define END_DEVICE_PATH_TYPE 0x7f
+
+#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff
+#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01
+#define END_DEVICE_PATH_LENGTH (sizeof(struct efi_device_path))
+
+#define DP_IS_END_TYPE(a)
+#define DP_IS_END_SUBTYPE(a) ( ((a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+
+#define device_path_type(a) ( ((a)->type) & EFI_DP_TYPE_MASK )
+#define next_device_path_node(a) ( (struct efi_device_path *) ( ((u8 *) (a)) + (a)->length))
+#define is_device_path_end_type(a) ( device_path_type(a) == END_DEVICE_PATH_TYPE )
+#define is_device_path_end_sub_type(a) ( (a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE )
+#define is_device_path_end(a) ( is_device_path_end_type(a) && is_device_path_end_sub_type(a) )
+#define is_device_path_unpacked(a) ( (a)->type & EFI_DP_TYPE_UNPACKED )
+
+#define set_device_path_end_node(a) { \
+ (a)->type = END_DEVICE_PATH_TYPE; \
+ (a)->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE; \
+ (a)->length = sizeof(struct efi_device_path); \
+ }
+
+/*
+ * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.)
+ */
+
+#define HARDWARE_DEVICE_PATH 0x01
+
+#define HW_PCI_DP 0x01
+struct pci_device_path {
+ struct efi_device_path header;
+ u8 Function;
+ u8 Device;
+};
+
+#define HW_PCCARD_DP 0x02
+struct pccard_device_path {
+ struct efi_device_path header;
+ u8 function_number;
+};
+
+#define HW_MEMMAP_DP 0x03
+struct memmap_device_path {
+ struct efi_device_path header;
+ u32 memory_type;
+ efi_physical_addr_t starting_address;
+ efi_physical_addr_t ending_address;
+};
+
+#define HW_VENDOR_DP 0x04
+struct vendor_device_path {
+ struct efi_device_path header;
+ efi_guid_t Guid;
+};
+
+struct unknown_device_vendor_device_path {
+ struct vendor_device_path device_path;
+ u8 legacy_drive_letter;
+};
+
+#define HW_CONTROLLER_DP 0x05
+struct controller_device_path {
+ struct efi_device_path header;
+ u32 Controller;
+};
+
+/*
+ * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.)
+ */
+#define ACPI_DEVICE_PATH 0x02
+
+#define ACPI_DP 0x01
+struct acpi_hid_device_path {
+ struct efi_device_path header;
+ u32 HID;
+ u32 UID;
+};
+
+#define EXPANDED_ACPI_DP 0x02
+struct expanded_acpi_hid_device_path {
+ struct efi_device_path header;
+ u32 HID;
+ u32 UID;
+ u32 CID;
+ u8 hid_str[1];
+};
+
+#define ACPI_ADR_DP 3
+struct acpi_adr_device_path {
+ struct efi_device_path header;
+ u32 ADR;
+};
+
+/*
+ * EISA ID Macro
+ * EISA ID Definition 32-bits
+ * bits[15:0] - three character compressed ASCII EISA ID.
+ * bits[31:16] - binary number
+ * Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z'
+ */
+#define PNP_EISA_ID_CONST 0x41d0
+#define EISA_ID(_Name, _Num) ((u32) ((_Name) | (_Num) << 16))
+#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId)))
+
+#define PNP_EISA_ID_MASK 0xffff
+#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16)
+
+/*
+ * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.)
+ */
+#define MESSAGING_DEVICE_PATH 0x03
+
+#define MSG_ATAPI_DP 0x01
+struct atapi_device_path {
+ struct efi_device_path header;
+ u8 primary_secondary;
+ u8 slave_master;
+ u16 Lun;
+};
+
+#define MSG_SCSI_DP 0x02
+struct scsi_device_path {
+ struct efi_device_path header;
+ u16 Pun;
+ u16 Lun;
+};
+
+#define MSG_FIBRECHANNEL_DP 0x03
+struct fibrechannel_device_path {
+ struct efi_device_path header;
+ u32 Reserved;
+ u64 WWN;
+ u64 Lun;
+};
+
+/**
+ * Fibre Channel Ex sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.6.
+ */
+#define MSG_FIBRECHANNELEX_DP 21
+struct fibrechannelex_device_path {
+ struct efi_device_path header;
+ u32 Reserved;
+ u8 WWN[8]; /* World Wide Name */
+ u8 Lun[8]; /* Logical unit, T-10 SCSI Architecture Model 4 specification */
+};
+
+#define MSG_1394_DP 0x04
+struct f1394_device_path {
+ struct efi_device_path header;
+ u32 Reserved;
+ u64 Guid;
+};
+
+#define MSG_USB_DP 0x05
+struct usb_device_path {
+ struct efi_device_path header;
+ u8 Port;
+ u8 Endpoint;
+};
+
+/**
+ * SATA Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.6.
+ */
+#define MSG_SATA_DP 18
+struct sata_device_path {
+ struct efi_device_path header;
+ u16 HBAPort_number;
+ u16 port_multiplier_port_number;
+ u16 Lun; /* Logical Unit Number */
+};
+
+/**
+ * USB WWID Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.7.
+ */
+#define MSG_USB_WWID_DP 16
+struct usb_wwid_device_path {
+ struct efi_device_path header;
+ u16 interface_number;
+ u16 vendor_id;
+ u16 product_id;
+ s16 serial_number[1]; /* UTF-16 characters of the USB serial number */
+};
+
+/**
+ * Device Logical Unit sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.8.
+ */
+#define MSG_DEVICE_LOGICAL_UNIT_DP 17
+struct device_logical_unit_device_path {
+ struct efi_device_path header;
+ u8 Lun; /* Logical Unit Number */
+};
+
+#define MSG_USB_CLASS_DP 0x0_f
+struct usb_class_device_path {
+ struct efi_device_path header;
+ u16 vendor_id;
+ u16 product_id;
+ u8 device_class;
+ u8 device_subclass;
+ u8 device_protocol;
+};
+
+#define MSG_I2_o_DP 0x06
+struct i2_o_device_path {
+ struct efi_device_path header;
+ u32 Tid;
+};
+
+#define MSG_MAC_ADDR_DP 0x0b
+struct mac_addr_device_path {
+ struct efi_device_path header;
+ efi_mac_address mac_address;
+ u8 if_type;
+};
+
+#define MSG_IPv4_DP 0x0c
+struct ipv4_device_path {
+ struct efi_device_path header;
+ efi_ipv4_address local_ip_address;
+ efi_ipv4_address remote_ip_address;
+ u16 local_port;
+ u16 remote_port;
+ u16 Protocol;
+ bool static_ip_address;
+ /* new from UEFI version 2, code must check length field in header */
+ efi_ipv4_address gateway_ip_address;
+ efi_ipv4_address subnet_mask;
+};
+
+#define MSG_IPv6_DP 0x0d
+struct ipv6_device_path {
+ struct efi_device_path header;
+ efi_ipv6_address local_ip_address;
+ efi_ipv6_address remote_ip_address;
+ u16 local_port;
+ u16 remote_port;
+ u16 Protocol;
+ bool IPAddress_origin;
+ /* new from UEFI version 2, code must check length field in header */
+ u8 prefix_length;
+ efi_ipv6_address gateway_ip_address;
+};
+
+/**
+ * Device Logical Unit sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.5.8.
+ */
+#define MSG_VLAN_DP 20
+struct vlan_device_path {
+ struct efi_device_path header;
+ u16 vlan_id;
+};
+
+#define MSG_INFINIBAND_DP 0x09
+struct infiniband_device_path {
+ struct efi_device_path header;
+ u32 resource_flags;
+ efi_guid_t port_gid;
+ u64 service_id;
+ u64 target_port_id;
+ u64 device_id;
+};
+
+#define MSG_UART_DP 0x0e
+struct uart_device_path {
+ struct efi_device_path header;
+ u32 Reserved;
+ u64 baud_rate;
+ u8 data_bits;
+ u8 Parity;
+ u8 stop_bits;
+};
+
+#define MSG_VENDOR_DP 0x0a
+/* Use VENDOR_DEVICE_PATH struct */
+
+#define DEVICE_PATH_MESSAGING_PC_ANSI \
+ { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+
+#define DEVICE_PATH_MESSAGING_VT_100 \
+ { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} }
+
+#define DEVICE_PATH_MESSAGING_VT_100_PLUS \
+ { 0x7baec70b , 0x57e0 , 0x4c76 , { 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } }
+
+#define DEVICE_PATH_MESSAGING_VT_UTF8 \
+ { 0xad15a0d6 , 0x8bec , 0x4acf , { 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } }
+
+#define EFI_PC_ANSI_GUID \
+ { 0xe0c14753 , 0xf9be , 0x11d2 , 0x9a , 0x0c , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d }
+
+#define EFI_VT_100_GUID \
+ { 0xdfa66065 , 0xb419 , 0x11d3 , 0x9a , 0x2d , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d }
+
+#define EFI_VT_100_PLUS_GUID \
+ { 0x7baec70b , 0x57e0 , 0x4c76 , 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 }
+
+#define EFI_VT_UTF8_GUID \
+ { 0xad15a0d6 , 0x8bec , 0x4acf , 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 }
+
+/*
+ * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.)
+ */
+#define MEDIA_DEVICE_PATH 0x04
+
+#define MEDIA_HARDDRIVE_DP 0x01
+struct harddrive_device_path {
+ struct efi_device_path header;
+ u32 partition_number;
+ u64 partition_start;
+ u64 partition_size;
+ u8 signature[16];
+ u8 mbr_type;
+ u8 signature_type;
+};
+
+#define MBR_TYPE_PCAT 0x01
+#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02
+
+#define SIGNATURE_TYPE_MBR 0x01
+#define SIGNATURE_TYPE_GUID 0x02
+
+#define MEDIA_CDROM_DP 0x02
+struct cdrom_device_path {
+ struct efi_device_path header;
+ u32 boot_entry;
+ u64 partition_start;
+ u64 partition_size;
+};
+
+#define MEDIA_VENDOR_DP 0x03
+/* Use VENDOR_DEVICE_PATH struct */
+
+#define MEDIA_FILEPATH_DP 0x04
+struct filepath_device_path {
+ struct efi_device_path header;
+ s16 path_name[1];
+};
+
+#define SIZE_OF_FILEPATH_DEVICE_PATH offsetof(FILEPATH_DEVICE_PATH,path_name)
+
+#define MEDIA_PROTOCOL_DP 0x05
+struct media_protocol_device_path {
+ struct efi_device_path header;
+ efi_guid_t Protocol;
+};
+
+/**
+ * PIWG Firmware File sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.6.
+ */
+#define MEDIA_PIWG_FW_FILE_DP 6
+struct media_fw_vol_filepath_device_path {
+ struct efi_device_path header;
+ efi_guid_t fv_file_name;
+};
+
+/**
+ * PIWG Firmware Volume Device Path sub_type.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.7.
+ */
+#define MEDIA_PIWG_FW_VOL_DP 7
+struct media_fw_vol_device_path {
+ struct efi_device_path header;
+ efi_guid_t fv_name;
+};
+
+/**
+ * Media relative offset range device path.
+ * UEFI 2.0 specification version 2.4 § 9.3.6.8.
+ */
+#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8
+struct media_relative_offset_range_device_path {
+ struct efi_device_path header;
+ u32 Reserved;
+ u64 starting_offset;
+ u64 ending_offset;
+};
+
+/*
+ * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.)
+ */
+#define BBS_DEVICE_PATH 0x05
+
+#define BBS_BBS_DP 0x01
+struct bbs_bbs_device_path {
+ struct efi_device_path header;
+ u16 device_type;
+ u16 status_flag;
+ s8 String[1];
+};
+
+/* device_type definitions - from BBS specification */
+#define BBS_TYPE_FLOPPY 0x01
+#define BBS_TYPE_HARDDRIVE 0x02
+#define BBS_TYPE_CDROM 0x03
+#define BBS_TYPE_PCMCIA 0x04
+#define BBS_TYPE_USB 0x05
+#define BBS_TYPE_EMBEDDED_NETWORK 0x06
+#define BBS_TYPE_DEV 0x80
+#define BBS_TYPE_UNKNOWN 0x_fF
+
+struct efi_device_path end_device_path = {
+ .type = END_DEVICE_PATH_TYPE,
+ .sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ .length = END_DEVICE_PATH_LENGTH,
+};
+
+struct efi_device_path end_instance_device_path = {
+ .type = END_DEVICE_PATH_TYPE,
+ .sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE,
+ .length = END_DEVICE_PATH_LENGTH,
+};
+
+unsigned long
+device_path_size(struct efi_device_path *dev_path)
+{
+ struct efi_device_path *Start;
+
+ Start = dev_path;
+ while (!is_device_path_end(dev_path))
+ dev_path = next_device_path_node(dev_path);
+
+ return ((unsigned long) dev_path - (unsigned long) Start) +
+ sizeof (struct efi_device_path);
+}
+
+struct efi_device_path *
+duplicate_device_path(struct efi_device_path *dev_path)
+{
+ struct efi_device_path *new_dev_path;
+ unsigned long Size;
+
+ Size = device_path_size(dev_path);
+
+ new_dev_path = malloc(Size);
+ if (new_dev_path)
+ memcpy(new_dev_path, dev_path, Size);
+
+ return new_dev_path;
+}
+
+struct efi_device_path *
+device_path_from_handle(efi_handle_t Handle)
+{
+ efi_status_t Status;
+ struct efi_device_path *device_path;
+
+ Status = BS->handle_protocol(Handle, &efi_device_path_protocol_guid,
+ (void *) &device_path);
+ if (EFI_ERROR(Status))
+ device_path = NULL;
+
+ return device_path;
+}
+
+struct efi_device_path *
+device_path_instance(struct efi_device_path **device_path, unsigned long *Size)
+{
+ struct efi_device_path *Start, *Next, *dev_path;
+ unsigned long Count;
+
+ dev_path = *device_path;
+ Start = dev_path;
+
+ if (!dev_path)
+ return NULL;
+
+ for (Count = 0;; Count++) {
+ Next = next_device_path_node(dev_path);
+
+ if (is_device_path_end_type(dev_path))
+ break;
+
+ dev_path = Next;
+ }
+
+ if (dev_path->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE)
+ Next = NULL;
+
+ *device_path = Next;
+
+ *Size = ((u8 *) dev_path) - ((u8 *) Start);
+
+ return Start;
+}
+
+unsigned long
+device_path_instance_count(struct efi_device_path *device_path)
+{
+ unsigned long Count, Size;
+
+ Count = 0;
+ while (device_path_instance(&device_path, &Size)) {
+ Count += 1;
+ }
+
+ return Count;
+}
+
+struct efi_device_path *
+append_device_path(struct efi_device_path *Src1, struct efi_device_path *Src2)
+/*
+ * Src1 may have multiple "instances" and each instance is appended
+ * Src2 is appended to each instance is Src1. (E.g., it's possible
+ * to append a new instance to the complete device path by passing
+ * it in Src2)
+ */
+{
+ unsigned long src1_size, src1_inst, src2_size, Size;
+ struct efi_device_path *Dst, *Inst;
+ u8 *dst_pos;
+
+ if (!Src1)
+ return duplicate_device_path(Src2);
+
+ if (!Src2) {
+ return duplicate_device_path(Src1);
+ }
+
+ src1_size = device_path_size(Src1);
+ src1_inst = device_path_instance_count(Src1);
+ src2_size = device_path_size(Src2);
+ Size = src1_size * src1_inst + src2_size;
+
+ Dst = malloc(Size);
+ if (Dst) {
+ dst_pos = (u8 *) Dst;
+
+ /* Copy all device path instances */
+
+ while ((Inst = device_path_instance(&Src1, &Size))) {
+
+ memcpy(dst_pos, Inst, Size);
+ dst_pos += Size;
+
+ memcpy(dst_pos, Src2, src2_size);
+ dst_pos += src2_size;
+
+ memcpy(dst_pos, &end_instance_device_path,
+ sizeof (struct efi_device_path));
+ dst_pos += sizeof (struct efi_device_path);
+ }
+
+ /* Change last end marker */
+ dst_pos -= sizeof (struct efi_device_path);
+ memcpy(dst_pos, &end_device_path,
+ sizeof (struct efi_device_path));
+ }
+
+ return Dst;
+}
+
+struct efi_device_path *
+append_device_path_node(struct efi_device_path *Src1,
+ struct efi_device_path *Src2)
+/*
+ * Src1 may have multiple "instances" and each instance is appended
+ * Src2 is a signal device path node (without a terminator) that is
+ * appended to each instance is Src1.
+ */
+{
+ struct efi_device_path *Temp, *Eop;
+ unsigned long length;
+
+ /* Build a Src2 that has a terminator on it */
+
+ length = Src2->length;
+ Temp = malloc(length + sizeof (struct efi_device_path));
+ if (!Temp)
+ return NULL;
+
+ memcpy(Temp, Src2, length);
+ Eop = next_device_path_node(Temp);
+ set_device_path_end_node(Eop);
+
+ /* Append device paths */
+
+ Src1 = append_device_path(Src1, Temp);
+ free(Temp);
+ return Src1;
+}
+
+struct efi_device_path *
+unpack_device_path(struct efi_device_path *dev_path)
+{
+ struct efi_device_path *Src, *Dest, *new_path;
+ unsigned long Size;
+
+ /* Walk device path and round sizes to valid boundries */
+
+ Src = dev_path;
+ Size = 0;
+ for (;;) {
+ Size += Src->length;
+ Size += ALIGN_SIZE(Size);
+
+ if (is_device_path_end(Src)) {
+ break;
+ }
+
+ Src = next_device_path_node(Src);
+ }
+
+ new_path = xzalloc(Size);
+
+ Src = dev_path;
+ Dest = new_path;
+ for (;;) {
+ Size = Src->length;
+ memcpy(Dest, Src, Size);
+ Size += ALIGN_SIZE(Size);
+ Dest->length = Size;
+ Dest->type |= EFI_DP_TYPE_UNPACKED;
+ Dest =
+ (struct efi_device_path *) (((u8 *) Dest) + Size);
+
+ if (is_device_path_end(Src))
+ break;
+
+ Src = next_device_path_node(Src);
+ }
+
+ return new_path;
+}
+
+struct efi_device_path *
+append_device_path_instance(struct efi_device_path *Src,
+ struct efi_device_path *Instance)
+{
+ u8 *Ptr;
+ struct efi_device_path *dev_path;
+ unsigned long src_size;
+ unsigned long instance_size;
+
+ if (Src == NULL)
+ return duplicate_device_path(Instance);
+
+ src_size = device_path_size(Src);
+ instance_size = device_path_size(Instance);
+ Ptr = malloc(src_size + instance_size);
+ dev_path = (struct efi_device_path *) Ptr;
+
+ memcpy(Ptr, Src, src_size);
+
+ while (!is_device_path_end(dev_path))
+ dev_path = next_device_path_node(dev_path);
+
+ /*
+ * Convert the End to an End Instance, since we are
+ * appending another instacne after this one its a good
+ * idea.
+ */
+ dev_path->sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+
+ dev_path = next_device_path_node(dev_path);
+ memcpy(dev_path, Instance, instance_size);
+
+ return (struct efi_device_path *) Ptr;
+}
+
+efi_status_t
+lib_device_path_to_interface(efi_guid_t * Protocol,
+ struct efi_device_path *file_path,
+ void **Interface)
+{
+ efi_status_t Status;
+ efi_handle_t Device;
+
+ Status = BS->locate_device_path(Protocol, &file_path, &Device);
+
+ if (!EFI_ERROR(Status)) {
+
+ /* If we didn't get a direct match return not found */
+ Status = EFI_NOT_FOUND;
+
+ if (is_device_path_end(file_path)) {
+
+ /* It was a direct match, lookup the protocol interface */
+
+ Status =
+ BS->handle_protocol(Device, Protocol, Interface);
+ }
+ }
+
+ if (EFI_ERROR(Status))
+ *Interface = NULL;
+
+ return Status;
+}
+
+static void
+dev_path_pci(struct string *str, void *dev_path)
+{
+ struct pci_device_path *Pci;
+
+ Pci = dev_path;
+ cprintf(str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function);
+}
+
+static void
+dev_path_pccard(struct string *str, void *dev_path)
+{
+ struct pccard_device_path *Pccard;
+
+ Pccard = dev_path;
+ cprintf(str, "Pccard(0x%x)", Pccard->function_number);
+}
+
+static void
+dev_path_mem_map(struct string *str, void *dev_path)
+{
+ struct memmap_device_path *mem_map;
+
+ mem_map = dev_path;
+ cprintf(str, "mem_map(%d,0x%llx,0x%llx)",
+ mem_map->memory_type,
+ mem_map->starting_address, mem_map->ending_address);
+}
+
+static void
+dev_path_controller(struct string *str, void *dev_path)
+{
+ struct controller_device_path *Controller;
+
+ Controller = dev_path;
+ cprintf(str, "Ctrl(%d)", Controller->Controller);
+}
+
+static void
+dev_path_vendor(struct string *str, void *dev_path)
+{
+ struct vendor_device_path *Vendor;
+ char *type;
+ struct unknown_device_vendor_device_path *unknown_dev_path;
+
+ Vendor = dev_path;
+ switch (device_path_type(&Vendor->header)) {
+ case HARDWARE_DEVICE_PATH:
+ type = "Hw";
+ break;
+ case MESSAGING_DEVICE_PATH:
+ type = "Msg";
+ break;
+ case MEDIA_DEVICE_PATH:
+ type = "Media";
+ break;
+ default:
+ type = "?";
+ break;
+ }
+
+ cprintf(str, "Ven%s(%pU", type, &Vendor->Guid);
+ if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) {
+ /* GUID used by EFI to enumerate an EDD 1.1 device */
+ unknown_dev_path =
+ (struct unknown_device_vendor_device_path *) Vendor;
+ cprintf(str, ":%02x)", unknown_dev_path->legacy_drive_letter);
+ } else {
+ cprintf(str, ")");
+ }
+}
+
+/*
+ type: 2 (ACPI Device Path) sub_type: 1 (ACPI Device Path)
+ */
+static void
+dev_path_acpi(struct string *str, void *dev_path)
+{
+ struct acpi_hid_device_path *Acpi;
+
+ Acpi = dev_path;
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ switch (EISA_ID_TO_NUM(Acpi->HID)) {
+ case 0x301:
+ cprintf(str, "Keyboard(%d)", Acpi->UID);
+ break;
+
+ case 0x401:
+ cprintf(str, "parallel_port(%d)", Acpi->UID);
+ break;
+ case 0x501:
+ cprintf(str, "Serial(%d)", Acpi->UID);
+ break;
+ case 0x604:
+ cprintf(str, "Floppy(%d)", Acpi->UID);
+ break;
+ case 0xa03:
+ cprintf(str, "pci_root(%d)", Acpi->UID);
+ break;
+ case 0xa08:
+ cprintf(str, "pcie_root(%d)", Acpi->UID);
+ break;
+ default:
+ cprintf(str, "Acpi(PNP%04x",
+ EISA_ID_TO_NUM(Acpi->HID));
+ if (Acpi->UID)
+ cprintf(str, ",%d", Acpi->UID);
+ cprintf(str, ")");
+ break;
+ }
+ } else {
+ cprintf(str, "Acpi(0x%X", Acpi->HID);
+ if (Acpi->UID)
+ cprintf(str, ",%d", Acpi->UID);
+ cprintf(str, ")");
+ }
+}
+
+static void
+dev_path_atapi(struct string *str, void *dev_path)
+{
+ struct atapi_device_path *Atapi;
+
+ Atapi = dev_path;
+ cprintf(str, "Ata(%s,%s)",
+ Atapi->primary_secondary ? "Secondary" : "Primary",
+ Atapi->slave_master ? "Slave" : "Master");
+}
+
+static void
+dev_path_scsi(struct string *str, void *dev_path)
+{
+ struct scsi_device_path *Scsi;
+
+ Scsi = dev_path;
+ cprintf(str, "Scsi(%d,%d)", Scsi->Pun, Scsi->Lun);
+}
+
+static void
+dev_path_fibre(struct string *str, void *dev_path)
+{
+ struct fibrechannel_device_path *Fibre;
+
+ Fibre = dev_path;
+ cprintf(str, "Fibre%s(0x%016llx,0x%016llx)",
+ device_path_type(&Fibre->header) ==
+ MSG_FIBRECHANNEL_DP ? "" : "Ex", Fibre->WWN, Fibre->Lun);
+}
+
+static void
+dev_path1394(struct string *str, void *dev_path)
+{
+ struct f1394_device_path *F1394;
+
+ F1394 = dev_path;
+ cprintf(str, "1394(%pU)", &F1394->Guid);
+}
+
+static void
+dev_path_usb(struct string *str, void *dev_path)
+{
+ struct usb_device_path *Usb;
+
+ Usb = dev_path;
+ cprintf(str, "Usb(0x%x,0x%x)", Usb->Port, Usb->Endpoint);
+}
+
+static void
+dev_path_i2_o(struct string *str, void *dev_path)
+{
+ struct i2_o_device_path *i2_o;
+
+ i2_o = dev_path;
+ cprintf(str, "i2_o(0x%X)", i2_o->Tid);
+}
+
+static void
+dev_path_mac_addr(struct string *str, void *dev_path)
+{
+ struct mac_addr_device_path *MAC;
+ unsigned long hw_address_size;
+ unsigned long Index;
+
+ MAC = dev_path;
+
+ /* hw_address_size = sizeof(EFI_MAC_ADDRESS); */
+ hw_address_size = MAC->header.length;
+ hw_address_size -= sizeof (MAC->header);
+ hw_address_size -= sizeof (MAC->if_type);
+ if (MAC->if_type == 0x01 || MAC->if_type == 0x00)
+ hw_address_size = 6;
+
+ cprintf(str, "Mac(");
+
+ for (Index = 0; Index < hw_address_size; Index++)
+ cprintf(str, "%02x", MAC->mac_address.Addr[Index]);
+
+ if (MAC->if_type != 0)
+ cprintf(str, ",%d", MAC->if_type);
+
+ cprintf(str, ")");
+}
+
+static void
+cat_print_iPv4(struct string *str, efi_ipv4_address * address)
+{
+ cprintf(str, "%d.%d.%d.%d", address->Addr[0], address->Addr[1],
+ address->Addr[2], address->Addr[3]);
+}
+
+static bool
+is_not_null_iPv4(efi_ipv4_address * address)
+{
+ u8 val;
+
+ val = address->Addr[0] | address->Addr[1];
+ val |= address->Addr[2] | address->Addr[3];
+
+ return val != 0;
+}
+
+static void
+cat_print_network_protocol(struct string *str, u16 Proto)
+{
+ if (Proto == 6)
+ cprintf(str, "TCP");
+ else if (Proto == 17)
+ cprintf(str, "UDP");
+ else
+ cprintf(str, "%d", Proto);
+}
+
+static void
+dev_path_iPv4(struct string *str, void *dev_path)
+{
+ struct ipv4_device_path *ip;
+ bool show;
+
+ ip = dev_path;
+ cprintf(str, "IPv4(");
+ cat_print_iPv4(str, &ip->remote_ip_address);
+ cprintf(str, ",");
+ cat_print_network_protocol(str, ip->Protocol);
+ cprintf(str, ",%s", ip->static_ip_address ? "Static" : "DHCP");
+ show = is_not_null_iPv4(&ip->local_ip_address);
+ if (!show
+ && ip->header.length ==
+ sizeof (struct ipv4_device_path)) {
+ /* only version 2 includes gateway and netmask */
+ show |= is_not_null_iPv4(&ip->gateway_ip_address);
+ show |= is_not_null_iPv4(&ip->subnet_mask);
+ }
+ if (show) {
+ cprintf(str, ",");
+ cat_print_iPv4(str, &ip->local_ip_address);
+ if (ip->header.length ==
+ sizeof (struct ipv4_device_path)) {
+ /* only version 2 includes gateway and netmask */
+ show = is_not_null_iPv4(&ip->gateway_ip_address);
+ show |= is_not_null_iPv4(&ip->subnet_mask);
+ if (show) {
+ cprintf(str, ",");
+ cat_print_iPv4(str, &ip->gateway_ip_address);
+ if (is_not_null_iPv4(&ip->subnet_mask)) {
+ cprintf(str, ",");
+ cat_print_iPv4(str, &ip->subnet_mask);
+ }
+ }
+ }
+ }
+ cprintf(str, ")");
+}
+
+#define cat_print_iPv6_ADD( x , y ) ( ( (u16) ( x ) ) << 8 | ( y ) )
+static void
+cat_print_ipv6(struct string *str, efi_ipv6_address * address)
+{
+ cprintf(str, "%x:%x:%x:%x:%x:%x:%x:%x",
+ cat_print_iPv6_ADD(address->Addr[0], address->Addr[1]),
+ cat_print_iPv6_ADD(address->Addr[2], address->Addr[3]),
+ cat_print_iPv6_ADD(address->Addr[4], address->Addr[5]),
+ cat_print_iPv6_ADD(address->Addr[6], address->Addr[7]),
+ cat_print_iPv6_ADD(address->Addr[8], address->Addr[9]),
+ cat_print_iPv6_ADD(address->Addr[10], address->Addr[11]),
+ cat_print_iPv6_ADD(address->Addr[12], address->Addr[13]),
+ cat_print_iPv6_ADD(address->Addr[14], address->Addr[15]));
+}
+
+static void
+dev_path_iPv6(struct string *str, void *dev_path)
+{
+ struct ipv6_device_path *ip;
+
+ ip = dev_path;
+ cprintf(str, "IPv6(");
+ cat_print_ipv6(str, &ip->remote_ip_address);
+ cprintf(str, ",");
+ cat_print_network_protocol(str, ip->Protocol);
+ cprintf(str, ",%s,", ip->IPAddress_origin ?
+ (ip->IPAddress_origin == 1 ? "stateless_auto_configure" :
+ "stateful_auto_configure") : "Static");
+ cat_print_ipv6(str, &ip->local_ip_address);
+ if (ip->header.length ==
+ sizeof (struct ipv6_device_path)) {
+ cprintf(str, ",");
+ cat_print_ipv6(str, &ip->gateway_ip_address);
+ cprintf(str, ",");
+ cprintf(str, "%d", ip->prefix_length);
+ }
+ cprintf(str, ")");
+}
+
+static void
+dev_path_infini_band(struct string *str, void *dev_path)
+{
+ struct infiniband_device_path *infini_band;
+
+ infini_band = dev_path;
+ cprintf(str, "Infiniband(0x%x,%pU,0x%llx,0x%llx,0x%llx)",
+ infini_band->resource_flags, &infini_band->port_gid,
+ infini_band->service_id, infini_band->target_port_id,
+ infini_band->device_id);
+}
+
+static void
+dev_path_uart(struct string *str, void *dev_path)
+{
+ struct uart_device_path *Uart;
+ s8 Parity;
+
+ Uart = dev_path;
+ switch (Uart->Parity) {
+ case 0:
+ Parity = 'D';
+ break;
+ case 1:
+ Parity = 'N';
+ break;
+ case 2:
+ Parity = 'E';
+ break;
+ case 3:
+ Parity = 'O';
+ break;
+ case 4:
+ Parity = 'M';
+ break;
+ case 5:
+ Parity = 'S';
+ break;
+ default:
+ Parity = 'x';
+ break;
+ }
+
+ if (Uart->baud_rate == 0)
+ cprintf(str, "Uart(DEFAULT %c", Parity);
+ else
+ cprintf(str, "Uart(%lld %c", Uart->baud_rate, Parity);
+
+ if (Uart->data_bits == 0)
+ cprintf(str, "D");
+ else
+ cprintf(str, "%d", Uart->data_bits);
+
+ switch (Uart->stop_bits) {
+ case 0:
+ cprintf(str, "D)");
+ break;
+ case 1:
+ cprintf(str, "1)");
+ break;
+ case 2:
+ cprintf(str, "1.5)");
+ break;
+ case 3:
+ cprintf(str, "2)");
+ break;
+ default:
+ cprintf(str, "x)");
+ break;
+ }
+}
+
+static void
+dev_path_sata(struct string *str, void *dev_path)
+{
+ struct sata_device_path *sata;
+
+ sata = dev_path;
+ cprintf(str, "Sata(0x%x,0x%x,0x%x)", sata->HBAPort_number,
+ sata->port_multiplier_port_number, sata->Lun);
+}
+
+static void
+dev_path_hard_drive(struct string *str, void *dev_path)
+{
+ struct harddrive_device_path *hd;
+
+ hd = dev_path;
+ switch (hd->signature_type) {
+ case SIGNATURE_TYPE_MBR:
+ cprintf(str, "HD(Part%d,Sig%08x)",
+ hd->partition_number, *((u32 *) (&(hd->signature[0])))
+ );
+ break;
+ case SIGNATURE_TYPE_GUID:
+ cprintf(str, "HD(Part%d,Sig%pU)",
+ hd->partition_number,
+ (efi_guid_t *) & (hd->signature[0])
+ );
+ break;
+ default:
+ cprintf(str, "HD(Part%d,mbr_type=%02x,sig_type=%02x)",
+ hd->partition_number, hd->mbr_type, hd->signature_type);
+ break;
+ }
+}
+
+static void
+dev_path_cdrom(struct string *str, void *dev_path)
+{
+ struct cdrom_device_path *cd;
+
+ cd = dev_path;
+ cprintf(str, "CDROM(0x%x)", cd->boot_entry);
+}
+
+static void
+dev_path_file_path(struct string *str, void *dev_path)
+{
+ struct filepath_device_path *Fp;
+ char *dst;
+
+ Fp = dev_path;
+
+ dst = strdup_wchar_to_char(Fp->path_name);
+
+ cprintf(str, "%s", dst);
+
+ free(dst);
+}
+
+static void
+dev_path_media_protocol(struct string *str, void *dev_path)
+{
+ struct media_protocol_device_path *media_prot;
+
+ media_prot = dev_path;
+ cprintf(str, "%pU", &media_prot->Protocol);
+}
+
+static void
+dev_path_bss_bss(struct string *str, void *dev_path)
+{
+ struct bbs_bbs_device_path *Bss;
+ char *type;
+
+ Bss = dev_path;
+ switch (Bss->device_type) {
+ case BBS_TYPE_FLOPPY:
+ type = "Floppy";
+ break;
+ case BBS_TYPE_HARDDRIVE:
+ type = "Harddrive";
+ break;
+ case BBS_TYPE_CDROM:
+ type = "CDROM";
+ break;
+ case BBS_TYPE_PCMCIA:
+ type = "PCMCIA";
+ break;
+ case BBS_TYPE_USB:
+ type = "Usb";
+ break;
+ case BBS_TYPE_EMBEDDED_NETWORK:
+ type = "Net";
+ break;
+ default:
+ type = "?";
+ break;
+ }
+
+ cprintf(str, "Bss-%s(%s)", type, Bss->String);
+}
+
+static void
+dev_path_end_instance(struct string *str, void *dev_path)
+{
+ cprintf(str, ",");
+}
+
+/**
+ * Print unknown device node.
+ * UEFI 2.4 § 9.6.1.6 table 89.
+ */
+
+static void
+dev_path_node_unknown(struct string *str, void *dev_path)
+{
+ struct efi_device_path *Path;
+ u8 *value;
+ int length, index;
+ Path = dev_path;
+ value = dev_path;
+ value += 4;
+ switch (Path->type) {
+ case HARDWARE_DEVICE_PATH:{
+ /* Unknown Hardware Device Path */
+ cprintf(str, "hardware_path(%d", Path->sub_type);
+ break;
+ }
+ case ACPI_DEVICE_PATH:{/* Unknown ACPI Device Path */
+ cprintf(str, "acpi_path(%d", Path->sub_type);
+ break;
+ }
+ case MESSAGING_DEVICE_PATH:{
+ /* Unknown Messaging Device Path */
+ cprintf(str, "Msg(%d", Path->sub_type);
+ break;
+ }
+ case MEDIA_DEVICE_PATH:{
+ /* Unknown Media Device Path */
+ cprintf(str, "media_path(%d", Path->sub_type);
+ break;
+ }
+ case BBS_DEVICE_PATH:{ /* Unknown BIOS Boot Specification Device Path */
+ cprintf(str, "bbs_path(%d", Path->sub_type);
+ break;
+ }
+ default:{ /* Unknown Device Path */
+ cprintf(str, "Path(%d,%d", Path->type, Path->sub_type);
+ break;
+ }
+ }
+ length = Path->length;
+ for (index = 0; index < length; index++) {
+ if (index == 0)
+ cprintf(str, ",0x");
+ cprintf(str, "%02x", *value);
+ value++;
+ }
+ cprintf(str, ")");
+}
+
+/*
+ * Table to convert "type" and "sub_type" to a "convert to text" function/
+ * Entries hold "type" and "sub_type" for know values.
+ * Special "sub_type" 0 is used as default for known type with unknown subtype.
+ */
+struct {
+ u8 type;
+ u8 sub_type;
+ void (*Function) (struct string *, void *);
+} dev_path_table[] = {
+ {
+ HARDWARE_DEVICE_PATH, HW_PCI_DP, dev_path_pci}, {
+ HARDWARE_DEVICE_PATH, HW_PCCARD_DP, dev_path_pccard}, {
+ HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, dev_path_mem_map}, {
+ HARDWARE_DEVICE_PATH, HW_VENDOR_DP, dev_path_vendor}, {
+ HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, dev_path_controller}, {
+ ACPI_DEVICE_PATH, ACPI_DP, dev_path_acpi}, {
+ MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, dev_path_atapi}, {
+ MESSAGING_DEVICE_PATH, MSG_SCSI_DP, dev_path_scsi}, {
+ MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, dev_path_fibre}, {
+ MESSAGING_DEVICE_PATH, MSG_1394_DP, dev_path1394}, {
+ MESSAGING_DEVICE_PATH, MSG_USB_DP, dev_path_usb}, {
+ MESSAGING_DEVICE_PATH, MSG_I2_o_DP, dev_path_i2_o}, {
+ MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, dev_path_mac_addr}, {
+ MESSAGING_DEVICE_PATH, MSG_IPv4_DP, dev_path_iPv4}, {
+ MESSAGING_DEVICE_PATH, MSG_IPv6_DP, dev_path_iPv6}, {
+ MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, dev_path_infini_band}, {
+ MESSAGING_DEVICE_PATH, MSG_UART_DP, dev_path_uart}, {
+ MESSAGING_DEVICE_PATH, MSG_SATA_DP, dev_path_sata}, {
+ MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, dev_path_vendor}, {
+ MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, dev_path_hard_drive}, {
+ MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, dev_path_cdrom}, {
+ MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, dev_path_vendor}, {
+ MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, dev_path_file_path}, {
+ MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, dev_path_media_protocol}, {
+ BBS_DEVICE_PATH, BBS_BBS_DP, dev_path_bss_bss}, {
+ END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE,
+ dev_path_end_instance}, {
+ 0, 0, NULL}
+};
+
+static int __device_path_to_str(struct string *str, struct efi_device_path *dev_path)
+{
+ struct efi_device_path *dev_path_node;
+ void (*dump_node) (struct string *, void *);
+ int i;
+
+ dev_path = unpack_device_path(dev_path);
+
+ dev_path_node = dev_path;
+ while (!is_device_path_end(dev_path_node)) {
+ dump_node = NULL;
+ for (i = 0; dev_path_table[i].Function; i += 1) {
+
+ if (device_path_type(dev_path_node) ==
+ dev_path_table[i].type
+ && dev_path_node->sub_type ==
+ dev_path_table[i].sub_type) {
+ dump_node = dev_path_table[i].Function;
+ break;
+ }
+ }
+
+ if (!dump_node)
+ dump_node = dev_path_node_unknown;
+
+ if (str->len && dump_node != dev_path_end_instance)
+ cprintf(str, "/");
+
+ dump_node(str, dev_path_node);
+
+ dev_path_node = next_device_path_node(dev_path_node);
+ }
+
+ return 0;
+}
+
+char *device_path_to_str(struct efi_device_path *dev_path)
+{
+ struct string str = {};
+
+ __device_path_to_str(&str, dev_path);
+
+ str.str = malloc(str.len + 1);
+ if (!str.str)
+ return NULL;
+
+ str.len = 0;
+
+ __device_path_to_str(&str, dev_path);
+
+ return str.str;
+}
diff --git a/common/efi-guid.c b/common/efi-guid.c
new file mode 100644
index 0000000000..f6b0404105
--- /dev/null
+++ b/common/efi-guid.c
@@ -0,0 +1,84 @@
+#include <common.h>
+#include <efi.h>
+
+efi_guid_t efi_file_info_id = EFI_FILE_INFO_GUID;
+efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_GUID;
+efi_guid_t efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID;
+efi_guid_t efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID;
+efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID;
+efi_guid_t efi_null_guid = EFI_NULL_GUID;
+efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID;
+efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID;
+
+#define EFI_GUID_STRING(guid, short, long) do { \
+ if (!efi_guidcmp(guid, *g)) \
+ return long; \
+ } while(0)
+
+const char *efi_guid_string(efi_guid_t *g)
+{
+ EFI_GUID_STRING(EFI_NULL_GUID, "NULL", "NULL GUID");
+ EFI_GUID_STRING(EFI_MPS_TABLE_GUID, "MPS Table", "MPS Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_ACPI_TABLE_GUID, "ACPI Table", "ACPI 1.0 Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_ACPI_20_TABLE_GUID, "ACPI 2.0 Table", "ACPI 2.0 Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_SMBIOS_TABLE_GUID, "SMBIOS Table", "SMBIOS Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_SAL_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_HCDP_TABLE_GUID, "HDCP Table", "HDCP Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol");
+ EFI_GUID_STRING(EFI_GLOBAL_VARIABLE_GUID, "Efi", "Efi Variable GUID");
+ EFI_GUID_STRING(EFI_UV_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table");
+ EFI_GUID_STRING(EFI_LINUX_EFI_CRASH_GUID, "Linux EFI Crash", "Linux EFI Crash GUID");
+ EFI_GUID_STRING(EFI_LOADED_IMAGE_PROTOCOL_GUID, "LoadedImage Protocol", "EFI 1.0 Loaded Image Protocol");
+ EFI_GUID_STRING(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "EFI Graphics Output Protocol", "UEFI Graphics Output Protocol");
+ EFI_GUID_STRING(EFI_UGA_PROTOCOL_GUID, "UGA Draw Protocol", "EFI 1.1 UGA Draw Protocol");
+ EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol");
+ EFI_GUID_STRING(EFI_PCI_IO_PROTOCOL_GUID, "PCI IO Protocol", "EFI 1.1 PCI IO Protocol");
+ EFI_GUID_STRING(EFI_FILE_INFO_GUID, "File Info", "EFI File Infom");
+ EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_GUID, "Filesystem", "EFI 1.0 Simple FileSystem");
+ EFI_GUID_STRING(EFI_DEVICE_TREE_GUID, "Device Tree", "EFI Device Tree GUID");
+ EFI_GUID_STRING(EFI_DEVICE_PATH_PROTOCOL_GUID, "Device Path Protocol", "EFI 1.0 Device Path protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_NETWORK_PROTOCOL_GUID, "Simple Network Protocol", "EFI 1.0 Simple Network Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "Filesystem Protocol", "EFI 1.0 Simple FileSystem Protocol");
+ EFI_GUID_STRING(EFI_UNKNOWN_DEVICE_GUID, "Efi Unknown Device", "Efi Unknown Device GUID");
+ EFI_GUID_STRING(EFI_BLOCK_IO_PROTOCOL_GUID, "BlockIo Protocol", "EFI 1.0 Block IO protocol");
+
+ EFI_GUID_STRING(EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "FirmwareVolume2Protocol", "Efi FirmwareVolume2Protocol");
+ EFI_GUID_STRING(EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "FirmwareVolumeBlock Protocol", "Firmware Volume Block protocol");
+ EFI_GUID_STRING(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID, "PciRootBridgeIo Protocol", "EFI 1.1 Pci Root Bridge IO Protocol");
+ EFI_GUID_STRING(EFI_ISA_ACPI_PROTOCOL_GUID, "ISA Acpi Protocol", "ISA Acpi Protocol");
+ EFI_GUID_STRING(EFI_ISA_IO_PROTOCOL_GUID, "ISA IO Protocol", "ISA IO Protocol");
+ EFI_GUID_STRING(EFI_STANDARD_ERROR_DEVICE_GUID, "Standard Error Device Guid", "EFI Standard Error Device Guid");
+ EFI_GUID_STRING(EFI_CONSOLE_OUT_DEVICE_GUID, "Console Out Device Guid", "EFI Console Out Device Guid");
+ EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Conosle In Device Guid");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID, "Simple Text Out Protocol", "EFI 1.0 Simple Text Out Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "Simple Text Input Ex Protocol", "UEFI 2.1 Simple Text Input Ex Protocol");
+ EFI_GUID_STRING(EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID, "Simple Text In Protocol", "EFI 1.0 Simple Text In Protocol");
+ EFI_GUID_STRING(EFI_DISK_IO_PROTOCOL_GUID, "DiskIo Protocol", "EFI 1.0 Disk IO Protocol");
+ EFI_GUID_STRING(EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE Controller Init Protocol", "Platform IDE Init Protocol");
+ EFI_GUID_STRING(EFI_DISK_INFO_PROTOCOL_GUID, "Disk Info Protocol", "Disk Info Protocol");
+ EFI_GUID_STRING(EFI_SERIAL_IO_PROTOCOL_GUID, "SerialIo Protocol", "EFI 1.0 Serial IO Protocol");
+ EFI_GUID_STRING(EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID, "Bus Specific Driver Override Protocol", "EFI 1.1 Bus Specific Driver Override Protocol");
+ EFI_GUID_STRING(EFI_LOAD_FILE2_PROTOCOL_GUID, "LoadFile2 Protocol", "EFI Load File 2 Protocol");
+ EFI_GUID_STRING(EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 Service Binding Protocol", "MTFTP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_DHCP4_PROTOCOL_GUID, "DHCP4 Protocol", "DHCP4 Protocol");
+ EFI_GUID_STRING(EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID, "UDP4 Service Binding Protocol", "UDP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID, "TCP4 Service Binding Protocol", "TCP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID, "IP4 Service Binding Protocol", "IP4 Service Binding Protocol");
+ EFI_GUID_STRING(EFI_IP4_CONFIG_PROTOCOL_GUID, "Ip4Config Protocol", "Ip4Config Protocol");
+ EFI_GUID_STRING(EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP Service Binding Protocol", "ARP Service Binding Protocol");
+ EFI_GUID_STRING(EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID, "Managed Network Service Binding Protocol", "Managed Network Service Binding Protocol");
+ EFI_GUID_STRING(EFI_VLAN_CONFIG_PROTOCOL_GUID, "VlanConfig Protocol", "VlanConfig Protocol");
+ EFI_GUID_STRING(EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID, "HII Config Access Protocol", "HII Config Access 2.1 protocol");
+ EFI_GUID_STRING(LOAD_FILE_PROTOCOL_GUID, "LoadFile Protocol", "EFI 1.0 Load File Protocol");
+ EFI_GUID_STRING(EFI_COMPONENT_NAME2_PROTOCOL_GUID, "Component Name2 Protocol", "UEFI 2.0 Component Name2 Protocol");
+ EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31, "Network Interface Identifier Protocol_31", "EFI1.1 Network Interface Identifier Protocol");
+ EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID, "Network Interface Identifier Protocol", "EFI Network Interface Identifier Protocol");
+
+ /* File */
+ EFI_GUID_STRING(EFI_IDEBUSDXE_INF_GUID, "IdeBusDxe.inf", "EFI IdeBusDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_TERMINALDXE_INF_GUID, "TerminalDxe.inf", "EFI TerminalDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_ISCSIDXE_INF_GUID, "IScsiDxe.inf", "EFI IScsiDxe.inf File GUID");
+ EFI_GUID_STRING(EFI_VLANCONFIGDXE_INF_GUID, "VlanConfigDxe.inf", "EFI VlanConfigDxe.inf File GUID");
+
+ return "unknown";
+}
diff --git a/common/environment.c b/common/environment.c
index 2d1edf8381..e55c7b7417 100644
--- a/common/environment.c
+++ b/common/environment.c
@@ -167,12 +167,13 @@ out:
* Make the current environment persistent
* @param[in] filename where to store
* @param[in] dirname what to store (all files in this dir)
+ * @param[in] flags superblock flags (refer ENVFS_FLAGS_* macros)
* @return 0 on success, anything else in case of failure
*
* Note: This function will also be used on the host! See note in the header
* of this file.
*/
-int envfs_save(const char *filename, const char *dirname)
+int envfs_save(const char *filename, const char *dirname, unsigned flags)
{
struct envfs_super *super;
int envfd, size, ret;
@@ -182,11 +183,15 @@ int envfs_save(const char *filename, const char *dirname)
data.writep = NULL;
data.base = dirname;
- /* first pass: calculate size */
- recursive_action(dirname, ACTION_RECURSE, file_size_action,
- NULL, &data, 0);
+ if (flags & ENVFS_FLAGS_FORCE_BUILT_IN) {
+ size = 0; /* force no content */
+ } else {
+ /* first pass: calculate size */
+ recursive_action(dirname, ACTION_RECURSE, file_size_action,
+ NULL, &data, 0);
- size = (unsigned long)data.writep;
+ size = (unsigned long)data.writep;
+ }
buf = xzalloc(size + sizeof(struct envfs_super));
data.writep = buf + sizeof(struct envfs_super);
@@ -196,10 +201,13 @@ int envfs_save(const char *filename, const char *dirname)
super->major = ENVFS_MAJOR;
super->minor = ENVFS_MINOR;
super->size = ENVFS_32(size);
+ super->flags = ENVFS_32(flags);
- /* second pass: copy files to buffer */
- recursive_action(dirname, ACTION_RECURSE, file_save_action,
- NULL, &data, 0);
+ if (!(flags & ENVFS_FLAGS_FORCE_BUILT_IN)) {
+ /* second pass: copy files to buffer */
+ recursive_action(dirname, ACTION_RECURSE, file_save_action,
+ NULL, &data, 0);
+ }
super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size));
super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4));
@@ -447,6 +455,15 @@ int envfs_load(const char *filename, const char *dir, unsigned flags)
if (ret)
goto out;
+ if (super.flags & ENVFS_FLAGS_FORCE_BUILT_IN) {
+ printf("found force-builtin environment, using defaultenv\n");
+ ret = defaultenv_load(dir, 0);
+ if (ret)
+ printf("failed to load default environment: %s\n",
+ strerror(-ret));
+ goto out;
+ }
+
buf = xmalloc(size);
rbuf = buf;
diff --git a/common/filetype.c b/common/filetype.c
index 508a2b56bf..c8f3582cd1 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -51,8 +51,13 @@ static const struct filetype_str filetype_str[] = {
[filetype_png] = { "PNG image", "png" },
[filetype_ext] = { "EXT filesystem", "ext" },
[filetype_gpt] = { "GUID Partition Table", "gpt" },
+ [filetype_ubifs] = { "UBIFS image", "ubifs" },
[filetype_bpk] = { "Binary PacKage", "bpk" },
[filetype_barebox_env] = { "barebox environment file", "bbenv" },
+ [filetype_ch_image] = { "TI OMAP CH boot image", "ch-image" },
+ [filetype_ch_image_be] = {
+ "TI OMAP CH boot image (big endian)", "ch-image-be" },
+ [filetype_exe] = { "MS-DOS executable", "exe" },
};
const char *file_type_to_string(enum filetype f)
@@ -177,6 +182,8 @@ enum filetype file_detect_partition_table(const void *_buf, size_t bufsize)
return filetype_unknown;
}
+#define CH_TOC_section_name 0x14
+
enum filetype file_detect_type(const void *_buf, size_t bufsize)
{
const u32 *buf = _buf;
@@ -231,6 +238,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (bufsize < 64)
return filetype_unknown;
+ if (buf8[0] == 'M' && buf8[1] == 'Z')
+ return filetype_exe;
+
if (is_barebox_arm_head(_buf))
return filetype_arm_barebox;
if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01)
@@ -246,6 +256,13 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (bufsize >= 1536 && buf16[512 + 28] == le16_to_cpu(0xef53))
return filetype_ext;
+ if (strncmp(buf8 + CH_TOC_section_name, "CHSETTINGS", 10) == 0)
+ return filetype_ch_image;
+
+ if (buf[5] == 0x43485345 && buf[6] == 0x5454494E &&
+ buf[7] == 0x47530000)
+ return filetype_ch_image_be;
+
return filetype_unknown;
}
diff --git a/common/hush.c b/common/hush.c
index f6aaa03514..b23b3f6633 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -118,6 +118,7 @@
#include <libbb.h>
#include <glob.h>
#include <getopt.h>
+#include <libfile.h>
#include <libbb.h>
#include <magicvar.h>
#include <linux/list.h>
diff --git a/common/imd-barebox.c b/common/imd-barebox.c
new file mode 100644
index 0000000000..e9cd37d83e
--- /dev/null
+++ b/common/imd-barebox.c
@@ -0,0 +1,25 @@
+#include <common.h>
+#include <image-metadata.h>
+#include <generated/compile.h>
+#include <generated/utsrelease.h>
+
+/*
+ * Mark a imd entry as used so that the linker cannot
+ * throw it away.
+ */
+void imd_used(const void *used)
+{
+}
+
+struct imd_header imd_start_header
+__BAREBOX_IMD_SECTION(.barebox_imd_start) = {
+ .type = cpu_to_le32(IMD_TYPE_START),
+};
+
+struct imd_header imd_end_header
+__BAREBOX_IMD_SECTION(.barebox_imd_end) = {
+ .type = cpu_to_le32(IMD_TYPE_END),
+};
+
+BAREBOX_IMD_TAG_STRING(imd_build_tag, IMD_TYPE_BUILD, UTS_VERSION, 1);
+BAREBOX_IMD_TAG_STRING(imd_release_tag, IMD_TYPE_RELEASE, UTS_RELEASE, 1);
diff --git a/common/imd.c b/common/imd.c
new file mode 100644
index 0000000000..2c837d6f25
--- /dev/null
+++ b/common/imd.c
@@ -0,0 +1,322 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 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.
+ *
+ */
+#ifdef __BAREBOX__
+#include <common.h>
+#include <image-metadata.h>
+#include <libfile.h>
+#include <getopt.h>
+#include <malloc.h>
+#include <fs.h>
+#endif
+
+/*
+ * imd_next - return a pointer to the next metadata field.
+ * @imd The current metadata field
+ */
+struct imd_header *imd_next(struct imd_header *imd)
+{
+ int length;
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ return (void *)imd + length;
+}
+
+struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type)
+{
+ imd_for_each(imd, imd)
+ if (imd_read_type(imd) == type)
+ return imd;
+
+ return NULL;
+}
+
+static int imd_next_validate(void *buf, int bufsize, int start_ofs)
+{
+ int length, size;
+ struct imd_header *imd = buf + start_ofs;
+
+ size = bufsize - start_ofs;
+
+ if (size < 8) {
+ debug("trunkated tag at offset %dd\n", start_ofs);
+ return -EINVAL;
+ }
+
+ length = imd_read_length(imd);
+ length = ALIGN(length, 4);
+ length += 8;
+
+ if (size < length) {
+ debug("tag at offset %d with size %d exceeds bufsize %d\n",
+ start_ofs, size, bufsize);
+ return -EINVAL;
+ }
+
+ debug("tag at offset %d has length %d\n", start_ofs, length);
+
+ return length;
+}
+
+static int imd_validate_tags(void *buf, int bufsize, int start_ofs)
+{
+ int ret;
+ struct imd_header *imd = buf + start_ofs;
+
+ while (1) {
+ uint32_t type;
+
+ ret = imd_next_validate(buf, bufsize, start_ofs);
+ if (ret < 0) {
+ debug("Invalid tag at offset %d\n", start_ofs);
+ return -EINVAL;
+ }
+
+ imd = (void *)imd + ret;
+ start_ofs += ret;
+
+ type = imd_read_type(imd);
+
+ if (!imd_type_valid(type)) {
+ debug("Invalid: tag: 0x%08x\n", type);
+ return -EINVAL;
+ }
+
+ if (type == IMD_TYPE_END)
+ return 0;
+ }
+}
+
+/*
+ * imd_search_validate - find valid metadata in a buffer
+ * @buf the buffer
+ * @size buffer size
+ * @start The returned pointer to the metadata
+ *
+ * This iterates over a buffer and searches for metadata. The metadata
+ * is checked for consistency (length fields not exceeding buffer and
+ * presence of end header) and returned in @start. The returned pointer
+ * is only valid when 0 is returned. The returned data may be unaligned.
+ */
+static int imd_search_validate(void *buf, int size, struct imd_header **start)
+{
+ int start_ofs = 0;
+ int i, ret;
+
+ for (i = start_ofs; i < size - 32; i++) {
+ uint32_t type;
+
+ type = imd_read_le32(buf + i);
+
+ if (type != IMD_TYPE_START)
+ continue;
+
+ debug("Start tag found at offset %d\n", i);
+
+ ret = imd_validate_tags(buf, size, i);
+ if (!ret) {
+ *start = buf + i;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+struct imd_type_names {
+ uint32_t type;
+ const char *name;
+};
+
+static struct imd_type_names imd_types[] = {
+ {
+ .type = IMD_TYPE_RELEASE,
+ .name = "release",
+ }, {
+ .type = IMD_TYPE_BUILD,
+ .name = "build",
+ }, {
+ .type = IMD_TYPE_MODEL,
+ .name = "model",
+ }, {
+ .type = IMD_TYPE_PARAMETER,
+ .name = "parameter",
+ }, {
+ .type = IMD_TYPE_OF_COMPATIBLE,
+ .name = "of_compatible",
+ },
+};
+
+static const char *imd_type_to_name(uint32_t type)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (imd_types[i].type == type)
+ return imd_types[i].name;
+
+ return "unknown";
+}
+
+static uint32_t imd_name_to_type(const char *name)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(imd_types); i++)
+ if (!strcmp(imd_types[i].name, name))
+ return imd_types[i].type;
+
+ return IMD_TYPE_INVALID;
+}
+
+static char *imd_string_data(struct imd_entry_string *imd_string, int index)
+{
+ int i, total = 0, l = 0;
+ int len = imd_read_length(&imd_string->header);
+ char *p = imd_string->data;
+
+ for (i = 0; total < len; total += l, p += l) {
+ l = strlen(p) + 1;
+ if (i++ == index)
+ return p;
+ }
+
+ return NULL;
+}
+
+static char *imd_concat_strings(struct imd_entry_string *imd_string)
+{
+ int i, len = imd_read_length(&imd_string->header);
+ char *str;
+
+ str = malloc(len);
+ if (!str)
+ return NULL;
+
+ memcpy(str, imd_string->data, len);
+
+ for (i = 0; i < len - 1; i++)
+ if (str[i] == 0)
+ str[i] = ' ';
+
+ return str;
+}
+
+int imd_command_verbose;
+
+int imd_command(int argc, char *argv[])
+{
+ int ret, opt, strno = -1;
+ void *buf;
+ size_t size;
+ uint32_t type = IMD_TYPE_INVALID;
+ struct imd_header *imd_start, *imd;
+ const char *filename;
+ const char *variable_name = NULL;
+ char *str;
+
+ imd_command_verbose = 0;
+
+ while ((opt = getopt(argc, argv, "vt:s:n:")) > 0) {
+ switch(opt) {
+ case 't':
+ type = imd_name_to_type(optarg);
+ if (type == IMD_TYPE_INVALID) {
+ fprintf(stderr, "no such type: %s\n", optarg);
+ return -ENOSYS;
+ }
+ break;
+ case 's':
+ variable_name = optarg;
+ break;
+ case 'v':
+ imd_command_verbose = 1;
+ break;
+ case 'n':
+ strno = simple_strtoul(optarg, NULL, 0);
+ break;
+ default:
+ return -ENOSYS;
+ }
+ }
+
+ if (optind == argc) {
+ fprintf(stderr, "No image given\n");
+ return -ENOSYS;
+ }
+
+ filename = argv[optind];
+
+ ret = read_file_2(filename, &size, &buf, 0x100000);
+ if (ret && ret != -EFBIG)
+ return -errno;
+
+ ret = imd_search_validate(buf, size, &imd_start);
+ if (ret)
+ return ret;
+
+ if (type == IMD_TYPE_INVALID) {
+ imd_for_each(imd_start, imd) {
+ uint32_t type = imd_read_type(imd);
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ str = imd_concat_strings(imd_string);
+
+ printf("%s: %s\n", imd_type_to_name(type), str);
+ } else {
+ debug("Unknown tag 0x%08x\n", type);
+ }
+ }
+ } else {
+ imd = imd_find_type(imd_start, type);
+ if (!imd) {
+ debug("No tag of type 0x%08x found\n", type);
+ return -ENODATA;
+ }
+
+ if (imd_is_string(type)) {
+ struct imd_entry_string *imd_string =
+ (struct imd_entry_string *)imd;
+
+ if (strno >= 0)
+ str = imd_string_data(imd_string, strno);
+ else
+ str = imd_concat_strings(imd_string);
+
+ if (!str)
+ return -ENODATA;
+
+ if (variable_name)
+ imd_command_setenv(variable_name, str);
+ else
+ printf("%s\n", str);
+
+ if (strno < 0)
+ free(str);
+ } else {
+ printf("tag 0x%08x present\n", type);
+ }
+ }
+
+ return 0;
+}
diff --git a/common/memory.c b/common/memory.c
index 7dbd7f4399..4a8fe283f2 100644
--- a/common/memory.c
+++ b/common/memory.c
@@ -58,7 +58,7 @@ void mem_malloc_init(void *start, void *end)
#endif
}
-#ifndef __SANDBOX__
+#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI
static int mem_malloc_resource(void)
{
/*
diff --git a/common/menutree.c b/common/menutree.c
index 814512d7b7..97e628de88 100644
--- a/common/menutree.c
+++ b/common/menutree.c
@@ -15,6 +15,7 @@
#include <glob.h>
#include <menu.h>
#include <fs.h>
+#include <libfile.h>
#include <linux/stat.h>
diff --git a/common/partitions/efi.c b/common/partitions/efi.c
index ee1326e622..dcb95414f6 100644
--- a/common/partitions/efi.c
+++ b/common/partitions/efi.c
@@ -232,7 +232,7 @@ static int is_gpt_valid(struct block_device *blk, u64 lba,
static inline int
is_pte_valid(const gpt_entry *pte, const u64 lastlba)
{
- if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) ||
+ if ((!efi_guidcmp(pte->partition_type_guid, EFI_NULL_GUID)) ||
le64_to_cpu(pte->starting_lba) > lastlba ||
le64_to_cpu(pte->ending_lba) > lastlba)
return 0;
diff --git a/common/partitions/efi.h b/common/partitions/efi.h
index 703ecca2f2..a9b10c1266 100644
--- a/common/partitions/efi.h
+++ b/common/partitions/efi.h
@@ -21,7 +21,7 @@
#ifndef FS_PART_EFI_H_INCLUDED
#define FS_PART_EFI_H_INCLUDED
-#include <linux/efi.h>
+#include <efi.h>
#define MSDOS_MBR_SIGNATURE 0xaa55
#define EFI_PMBR_OSTYPE_EFI 0xEF
diff --git a/common/uimage.c b/common/uimage.c
index 4ef09682c1..a7011a7623 100644
--- a/common/uimage.c
+++ b/common/uimage.c
@@ -22,6 +22,7 @@
#include <malloc.h>
#include <errno.h>
#include <libbb.h>
+#include <libfile.h>
#include <uncompress.h>
#include <fcntl.h>
#include <fs.h>
diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c
index 11e3777a60..b7f78367d4 100644
--- a/drivers/bus/mvebu-mbus.c
+++ b/drivers/bus/mvebu-mbus.c
@@ -53,6 +53,7 @@
#include <common.h>
#include <init.h>
#include <io.h>
+#include <malloc.h>
#include <of.h>
#include <of_address.h>
#include <linux/mbus.h>
@@ -187,7 +188,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
phys_addr_t base, size_t size,
u8 target, u8 attr)
{
- u64 end = (u64)base + size;
+ u64 end = (u64)base + size - 1;
int win;
for (win = 0; win < mbus->soc->num_wins; win++) {
@@ -203,7 +204,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus,
if (!enabled)
continue;
- wend = wbase + wsize;
+ wend = wbase + wsize - 1;
/*
* Check if the current window overlaps with the
@@ -546,7 +547,7 @@ void mvebu_mbus_get_pcie_io_aperture(struct resource *res)
* - bits 16 to 23: window attribute ID
* - bits 0 to 15: unused
*/
-#define CUSTOM(id) (((id) & 0xF0000000) >> 24)
+#define CUSTOM(id) (((id) & 0xF0000000) >> 28)
#define TARGET(id) (((id) & 0x0F000000) >> 24)
#define ATTR(id) (((id) & 0x00FF0000) >> 16)
@@ -661,7 +662,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
reg, ARRAY_SIZE(reg));
if (!ret) {
mem->start = reg[0];
- mem->end = mem->start + reg[1];
+ mem->end = mem->start + reg[1] - 1;
mem->flags = IORESOURCE_MEM;
}
@@ -669,7 +670,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np,
reg, ARRAY_SIZE(reg));
if (!ret) {
io->start = reg[0];
- io->end = io->start + reg[1];
+ io->end = io->start + reg[1] - 1;
io->flags = IORESOURCE_IO;
}
}
@@ -741,3 +742,89 @@ static int mvebu_mbus_init(void)
return platform_driver_register(&mvebu_mbus_driver);
}
postcore_initcall(mvebu_mbus_init);
+
+struct mbus_range {
+ u32 mbusid;
+ u32 remap;
+ struct list_head list;
+};
+
+#define MBUS_ID(t,a) (((t) << 24) | ((attr) << 16))
+static LIST_HEAD(mbus_ranges);
+
+void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap)
+{
+ struct mbus_range *r = xzalloc(sizeof(*r));
+
+ r->mbusid = MBUS_ID(target, attr);
+ r->remap = remap;
+ list_add_tail(&r->list, &mbus_ranges);
+}
+
+/*
+ * Barebox always remaps internal registers to 0xf1000000 on every SoC.
+ * As we (and Linux) need a working DT and there is no way to tell the current
+ * remap address, fixup any provided DT to ensure custom MBUS_IDs are correct.
+ */
+static int mvebu_mbus_of_fixup(struct device_node *root, void *context)
+{
+ struct device_node *np;
+
+ for_each_matching_node(np, mvebu_mbus_dt_ids) {
+ struct property *p;
+ int n, pa, na, ns, lenp, size;
+ u32 *ranges;
+
+ p = of_find_property(np, "ranges", &lenp);
+ if (!p)
+ return -EINVAL;
+
+ pa = of_n_addr_cells(np);
+ if (of_property_read_u32(np, "#address-cells", &na) ||
+ of_property_read_u32(np, "#size-cells", &ns))
+ return -EINVAL;
+
+ size = pa + na + ns;
+ ranges = xzalloc(lenp);
+ of_property_read_u32_array(np, "ranges", ranges, lenp/4);
+
+ /*
+ * Iterate through each ranges tuple and fixup the custom
+ * window ranges low base address. Because Armada XP supports
+ * LPAE, it has 2 cells for the parent address:
+ * <windowid child_base high_base low_base size>
+ *
+ * whereas for Armada 370, there's just one:
+ * <windowid child_base base size>
+ *
+ * For instance, the following tuple:
+ * <MBUS_ID(0xf0, 0x01) child_base {0} base 0x100000>
+ *
+ * would be fixed-up like:
+ * <MBUS_ID(0xf0, 0x01) child_base {0} remap 0x100000>
+ */
+ for (n = 0; n < lenp/4; n += size) {
+ struct mbus_range *r;
+ u32 mbusid = ranges[n];
+
+ if (!CUSTOM(mbusid))
+ continue;
+
+ list_for_each_entry(r, &mbus_ranges, list) {
+ if (r->mbusid == mbusid)
+ ranges[n + na + pa - 1] = r->remap;
+ }
+ }
+
+ if (of_property_write_u32_array(np, "ranges", ranges, lenp/4))
+ pr_err("Unable to fixup mbus ranges\n");
+ free(ranges);
+ }
+
+ return 0;
+}
+
+static int mvebu_mbus_fixup_register(void) {
+ return of_register_fixup(mvebu_mbus_of_fixup, NULL);
+}
+pure_initcall(mvebu_mbus_fixup_register);
diff --git a/drivers/bus/omap-gpmc.c b/drivers/bus/omap-gpmc.c
index ad21af2903..d7b02cf6ec 100644
--- a/drivers/bus/omap-gpmc.c
+++ b/drivers/bus/omap-gpmc.c
@@ -382,9 +382,6 @@ static struct dt_eccmode modes[] = {
.mode = OMAP_ECC_BCH4_CODE_HW,
}, {
.name = "bch8",
- .mode = OMAP_ECC_BCH8_CODE_HW,
- }, {
- .name = "bch8-romcode",
.mode = OMAP_ECC_BCH8_CODE_HW_ROMCODE,
},
};
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index c1480ceaaf..fc5a389b95 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -14,6 +14,10 @@ config CLOCKSOURCE_CLPS711X
bool
depends on ARCH_CLPS711X
+config CLOCKSOURCE_DIGIC
+ bool
+ depends on ARCH_DIGIC
+
config CLOCKSOURCE_DUMMY
bool "Enable dummy software-only clocksource"
help
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 97c0288aaa..b80df6b2c9 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -2,6 +2,7 @@ obj-$(CONFIG_AMBA_SP804) += amba-sp804.o
obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o
obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o
obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o
+obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o
obj-$(CONFIG_CLOCKSOURCE_DUMMY) += dummy.o
obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o
obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o
diff --git a/drivers/clocksource/digic.c b/drivers/clocksource/digic.c
new file mode 100644
index 0000000000..b80ef6f6fa
--- /dev/null
+++ b/drivers/clocksource/digic.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <init.h>
+#include <clock.h>
+
+#define DIGIC_TIMER_CLOCK 1000000
+
+#define DIGIC_TIMER_CONTROL 0x00
+#define DIGIC_TIMER_VALUE 0x0c
+
+static void __iomem *timer_base;
+
+static uint64_t digic_cs_read(void)
+{
+ return (uint64_t)(0xffff - readl(timer_base + DIGIC_TIMER_VALUE));
+}
+
+static struct clocksource digic_cs = {
+ .read = digic_cs_read,
+ .mask = CLOCKSOURCE_MASK(16),
+};
+
+static int digic_timer_probe(struct device_d *dev)
+{
+ /* use only one timer */
+ if (timer_base)
+ return -EBUSY;
+
+ timer_base = dev_request_mem_region(dev, 0);
+ if (!timer_base) {
+ dev_err(dev, "could not get memory region\n");
+ return -ENODEV;
+ }
+
+ clocks_calc_mult_shift(&digic_cs.mult, &digic_cs.shift,
+ DIGIC_TIMER_CLOCK, NSEC_PER_SEC, 1);
+
+ /* disable timer */
+ writel(0x80000000, timer_base + DIGIC_TIMER_CONTROL);
+
+ /* magic values... divider? */
+ writel(0x00000002, timer_base + 0x04);
+ writel(0x00000003, timer_base + 0x14);
+
+ /* max counter value */
+ writel(0x0000ffff, timer_base + 0x08);
+
+ init_clock(&digic_cs);
+
+ /* enable timer */
+ writel(0x00000001, timer_base + DIGIC_TIMER_CONTROL);
+ /* start timer */
+ writel(0x00000001, timer_base + 0x10);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id digic_timer_dt_ids[] = {
+ {
+ .compatible = "canon,digic-timer",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d digic_timer_driver = {
+ .probe = digic_timer_probe,
+ .name = "digic-timer",
+ .of_compatible = DRV_OF_COMPAT(digic_timer_dt_ids),
+};
+
+static int digic_timer_init(void)
+{
+ return platform_driver_register(&digic_timer_driver);
+}
+coredevice_initcall(digic_timer_init);
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index f98a9c00ef..0ca7df450a 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -9,6 +9,10 @@ menu "GPIO"
config GPIO_GENERIC
bool
+config GPIO_DIGIC
+ bool "GPIO support for Canon DIGIC"
+ depends on ARCH_DIGIC
+
config GPIO_BCM2835
bool "GPIO support for BCM2835"
depends on ARCH_BCM2835
@@ -64,6 +68,26 @@ config GPIO_ORION
found on Marvell Orion and MVEBU SoCs (Armada 370/XP,
Dove, Kirkwood, MV78x00, Orion5x).
+config GPIO_PCA953X
+ bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports"
+ depends on I2C
+ help
+ Say yes here to provide access to several register-oriented
+ SMBus I/O expanders, made mostly by NXP or TI. Compatible
+ models include:
+
+ 4 bits: pca9536, pca9537
+
+ 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554,
+ pca9556, pca9557, pca9574, tca6408, xra1202
+
+ 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575,
+ tca6416
+
+ 24 bits: tca6424
+
+ 40 bits: pca9505, pca9698
+
config GPIO_PL061
bool "PrimeCell PL061 GPIO support"
depends on ARM_AMBA
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile
index 22d2ac0706..510d146ff5 100644
--- a/drivers/gpio/Makefile
+++ b/drivers/gpio/Makefile
@@ -3,12 +3,14 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o
obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o
obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o
obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o
+obj-$(CONFIG_GPIO_DIGIC) += gpio-digic.o
obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o
obj-$(CONFIG_GPIO_IMX) += gpio-imx.o
obj-$(CONFIG_GPIO_JZ4740) += gpio-jz4740.o
obj-$(CONFIG_GPIO_MALTA_FPGA_I2C) += gpio-malta-fpga-i2c.o
obj-$(CONFIG_GPIO_ORION) += gpio-orion.o
obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o
+obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o
obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o
obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o
obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o
diff --git a/drivers/gpio/gpio-digic.c b/drivers/gpio/gpio-digic.c
new file mode 100644
index 0000000000..468aaa79ab
--- /dev/null
+++ b/drivers/gpio/gpio-digic.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <errno.h>
+#include <io.h>
+#include <gpio.h>
+#include <init.h>
+
+/*
+ * See http://magiclantern.wikia.com/wiki/Register_Map#GPIO_Ports
+ */
+
+#define DIGIC_GPIO_IN_LVL 1
+#define DIGIC_GPIO_OUT_LVL 2
+#define DIGIC_GPIO_DIR 4
+#define DIGIC_GPIO_TRISTATE 8
+
+struct digic_gpio_chip {
+ void __iomem *base;
+ struct gpio_chip gc;
+};
+
+#define to_digic_gpio_chip(c) container_of(c, struct digic_gpio_chip, gc)
+
+static inline uint32_t digic_gpio_readl(struct digic_gpio_chip *chip,
+ uint32_t offset)
+{
+ return readl(chip->base + 4 * offset);
+}
+
+static inline void digic_gpio_writel(struct digic_gpio_chip *chip,
+ uint32_t value, uint32_t offset)
+{
+ writel(value, chip->base + 4 * offset);
+}
+
+static int digic_gpio_get_value(struct gpio_chip *gc, unsigned offset)
+{
+ struct digic_gpio_chip *chip = to_digic_gpio_chip(gc);
+
+ if (offset >= gc->ngpio)
+ return -EINVAL;
+
+ return digic_gpio_readl(chip, offset) & DIGIC_GPIO_IN_LVL;
+}
+
+static void digic_gpio_set_value(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ struct digic_gpio_chip *chip = to_digic_gpio_chip(gc);
+ uint32_t t;
+
+ if (offset >= gc->ngpio)
+ return;
+
+ t = digic_gpio_readl(chip, offset);
+ /* Port direction (1 = OUT, 0 = IN) */
+ if (value)
+ t |= DIGIC_GPIO_OUT_LVL;
+ else
+ t &= ~(DIGIC_GPIO_OUT_LVL);
+ digic_gpio_writel(chip, t, offset);
+}
+
+static int digic_gpio_direction_input(struct gpio_chip *gc, unsigned offset)
+{
+ struct digic_gpio_chip *chip = to_digic_gpio_chip(gc);
+ uint32_t t;
+
+ if (offset >= gc->ngpio)
+ return -EINVAL;
+
+ t = digic_gpio_readl(chip, offset);
+ /* Port direction (1 = OUT, 0 = IN) */
+ t &= ~(DIGIC_GPIO_DIR);
+ digic_gpio_writel(chip, t, offset);
+
+ return 0;
+}
+
+static int digic_gpio_direction_output(struct gpio_chip *gc, unsigned offset,
+ int value)
+{
+ struct digic_gpio_chip *chip = to_digic_gpio_chip(gc);
+ uint32_t t;
+
+ if (offset >= gc->ngpio)
+ return -EINVAL;
+
+ t = digic_gpio_readl(chip, offset);
+ /* Port direction (1 = OUT, 0 = IN) */
+ t |= DIGIC_GPIO_DIR;
+ digic_gpio_writel(chip, t, offset);
+
+ digic_gpio_set_value(gc, offset, value);
+
+ return 0;
+}
+
+static struct gpio_ops digic_gpio_ops = {
+ .direction_input = digic_gpio_direction_input,
+ .direction_output = digic_gpio_direction_output,
+ .get = digic_gpio_get_value,
+ .set = digic_gpio_set_value,
+};
+
+static int digic_gpio_probe(struct device_d *dev)
+{
+ struct digic_gpio_chip *chip;
+ struct resource *res;
+ resource_size_t rsize;
+ int ret = -EINVAL;
+
+ chip = xzalloc(sizeof(*chip));
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ goto err;
+
+ rsize = resource_size(res);
+ chip->gc.ngpio = rsize / sizeof(int32_t);
+
+ chip->base = dev_request_mem_region(dev, 0);
+ chip->gc.ops = &digic_gpio_ops;
+ chip->gc.base = 0;
+
+ chip->gc.dev = dev;
+
+ ret = gpiochip_add(&chip->gc);
+ if (ret) {
+ dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret);
+ goto err;
+ }
+
+ dev_info(dev, "probed gpiochip%d with base %d\n",
+ dev->id, chip->gc.base);
+
+ return 0;
+
+err:
+ kfree(chip);
+
+ return ret;
+}
+
+static __maybe_unused struct of_device_id digic_gpio_dt_ids[] = {
+ {
+ .compatible = "canon,digic-gpio",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d digic_gpio_driver = {
+ .name = "digic-gpio",
+ .probe = digic_gpio_probe,
+ .of_compatible = DRV_OF_COMPAT(digic_gpio_dt_ids),
+};
+
+static int digic_gpio_init(void)
+{
+ return platform_driver_register(&digic_gpio_driver);
+}
+coredevice_initcall(digic_gpio_init);
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
new file mode 100644
index 0000000000..aabbb09eb8
--- /dev/null
+++ b/drivers/gpio/gpio-pca953x.c
@@ -0,0 +1,481 @@
+/*
+ * PCA953x 4/8/16/24/40 bit I/O ports
+ *
+ * This code was ported from linux-3.15 kernel by Antony Pavlov.
+ *
+ * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com>
+ * Copyright (C) 2007 Marvell International Ltd.
+ *
+ * Derived from drivers/i2c/chips/pca9539.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <i2c/i2c.h>
+
+#include <gpio.h>
+#include <platform_data/pca953x.h>
+
+#define PCA953X_INPUT 0
+#define PCA953X_OUTPUT 1
+#define PCA953X_INVERT 2
+#define PCA953X_DIRECTION 3
+
+#define REG_ADDR_AI 0x80
+
+#define PCA957X_IN 0
+#define PCA957X_INVRT 1
+#define PCA957X_BKEN 2
+#define PCA957X_PUPD 3
+#define PCA957X_CFG 4
+#define PCA957X_OUT 5
+#define PCA957X_MSK 6
+#define PCA957X_INTS 7
+
+#define PCA_GPIO_MASK 0x00FF
+#define PCA_INT 0x0100
+#define PCA953X_TYPE 0x1000
+#define PCA957X_TYPE 0x2000
+
+static struct platform_device_id pca953x_id[] = {
+ { "pca9505", 40 | PCA953X_TYPE | PCA_INT, },
+ { "pca9534", 8 | PCA953X_TYPE | PCA_INT, },
+ { "pca9535", 16 | PCA953X_TYPE | PCA_INT, },
+ { "pca9536", 4 | PCA953X_TYPE, },
+ { "pca9537", 4 | PCA953X_TYPE | PCA_INT, },
+ { "pca9538", 8 | PCA953X_TYPE | PCA_INT, },
+ { "pca9539", 16 | PCA953X_TYPE | PCA_INT, },
+ { "pca9554", 8 | PCA953X_TYPE | PCA_INT, },
+ { "pca9555", 16 | PCA953X_TYPE | PCA_INT, },
+ { "pca9556", 8 | PCA953X_TYPE, },
+ { "pca9557", 8 | PCA953X_TYPE, },
+ { "pca9574", 8 | PCA957X_TYPE | PCA_INT, },
+ { "pca9575", 16 | PCA957X_TYPE | PCA_INT, },
+ { "pca9698", 40 | PCA953X_TYPE, },
+
+ { "max7310", 8 | PCA953X_TYPE, },
+ { "max7312", 16 | PCA953X_TYPE | PCA_INT, },
+ { "max7313", 16 | PCA953X_TYPE | PCA_INT, },
+ { "max7315", 8 | PCA953X_TYPE | PCA_INT, },
+ { "pca6107", 8 | PCA953X_TYPE | PCA_INT, },
+ { "tca6408", 8 | PCA953X_TYPE | PCA_INT, },
+ { "tca6416", 16 | PCA953X_TYPE | PCA_INT, },
+ { "tca6424", 24 | PCA953X_TYPE | PCA_INT, },
+ { "xra1202", 8 | PCA953X_TYPE },
+ { }
+};
+
+#define MAX_BANK 5
+#define BANK_SZ 8
+
+#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ)
+
+struct pca953x_chip {
+ unsigned gpio_start;
+ u8 reg_output[MAX_BANK];
+ u8 reg_direction[MAX_BANK];
+ struct i2c_client *client;
+ struct gpio_chip gpio_chip;
+ const char *const *names;
+ int chip_type;
+};
+
+static inline struct pca953x_chip *to_pca(struct gpio_chip *gc)
+{
+ return container_of(gc, struct pca953x_chip, gpio_chip);
+}
+
+static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val,
+ int off)
+{
+ int ret;
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+ int offset = off / BANK_SZ;
+
+ ret = i2c_smbus_read_byte_data(chip->client,
+ (reg << bank_shift) + offset);
+ *val = ret;
+
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed reading register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val,
+ int off)
+{
+ int ret = 0;
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+ int offset = off / BANK_SZ;
+
+ ret = i2c_smbus_write_byte_data(chip->client,
+ (reg << bank_shift) + offset, val);
+
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed writing register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val)
+{
+ int ret = 0;
+
+ if (chip->gpio_chip.ngpio <= 8)
+ ret = i2c_smbus_write_byte_data(chip->client, reg, *val);
+ else if (chip->gpio_chip.ngpio >= 24) {
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+ ret = i2c_smbus_write_i2c_block_data(chip->client,
+ (reg << bank_shift) | REG_ADDR_AI,
+ NBANK(chip), val);
+ } else {
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ ret = i2c_smbus_write_word_data(chip->client,
+ reg << 1, (u16) *val);
+ break;
+ case PCA957X_TYPE:
+ ret = i2c_smbus_write_byte_data(chip->client, reg << 1,
+ val[0]);
+ if (ret < 0)
+ break;
+ ret = i2c_smbus_write_byte_data(chip->client,
+ (reg << 1) + 1,
+ val[1]);
+ break;
+ }
+ }
+
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed writing register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val)
+{
+ int ret;
+
+ if (chip->gpio_chip.ngpio <= 8) {
+ ret = i2c_smbus_read_byte_data(chip->client, reg);
+ *val = ret;
+ } else if (chip->gpio_chip.ngpio >= 24) {
+ int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ);
+
+ ret = i2c_smbus_read_i2c_block_data(chip->client,
+ (reg << bank_shift) | REG_ADDR_AI,
+ NBANK(chip), val);
+ } else {
+ ret = i2c_smbus_read_word_data(chip->client, reg << 1);
+ val[0] = (u16)ret & 0xFF;
+ val[1] = (u16)ret >> 8;
+ }
+ if (ret < 0) {
+ dev_err(&chip->client->dev, "failed reading register\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off)
+{
+ struct pca953x_chip *chip = to_pca(gc);
+ u8 reg_val;
+ int ret, offset = 0;
+
+ reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ));
+
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_DIRECTION;
+ break;
+ case PCA957X_TYPE:
+ offset = PCA957X_CFG;
+ break;
+ }
+ ret = pca953x_write_single(chip, offset, reg_val, off);
+ if (ret)
+ goto exit;
+
+ chip->reg_direction[off / BANK_SZ] = reg_val;
+ ret = 0;
+exit:
+ return ret;
+}
+
+static int pca953x_gpio_direction_output(struct gpio_chip *gc,
+ unsigned off, int val)
+{
+ struct pca953x_chip *chip = to_pca(gc);
+ u8 reg_val;
+ int ret, offset = 0;
+
+ /* set output level */
+ if (val)
+ reg_val = chip->reg_output[off / BANK_SZ]
+ | (1u << (off % BANK_SZ));
+ else
+ reg_val = chip->reg_output[off / BANK_SZ]
+ & ~(1u << (off % BANK_SZ));
+
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_OUTPUT;
+ break;
+ case PCA957X_TYPE:
+ offset = PCA957X_OUT;
+ break;
+ }
+ ret = pca953x_write_single(chip, offset, reg_val, off);
+ if (ret)
+ goto exit;
+
+ chip->reg_output[off / BANK_SZ] = reg_val;
+
+ /* then direction */
+ reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ));
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_DIRECTION;
+ break;
+ case PCA957X_TYPE:
+ offset = PCA957X_CFG;
+ break;
+ }
+ ret = pca953x_write_single(chip, offset, reg_val, off);
+ if (ret)
+ goto exit;
+
+ chip->reg_direction[off / BANK_SZ] = reg_val;
+ ret = 0;
+exit:
+ return ret;
+}
+
+static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off)
+{
+ struct pca953x_chip *chip = to_pca(gc);
+ u8 reg_val;
+
+ reg_val = chip->reg_direction[off / BANK_SZ] & (1u << (off % BANK_SZ));
+
+ if (reg_val)
+ return GPIOF_DIR_IN;
+
+ return GPIOF_DIR_OUT;
+}
+
+static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off)
+{
+ struct pca953x_chip *chip = to_pca(gc);
+ u32 reg_val;
+ int ret, offset = 0;
+
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_INPUT;
+ break;
+ case PCA957X_TYPE:
+ offset = PCA957X_IN;
+ break;
+ }
+ ret = pca953x_read_single(chip, offset, &reg_val, off);
+ if (ret < 0) {
+ /* NOTE: diagnostic already emitted; that's all we should
+ * do unless gpio_*_value_cansleep() calls become different
+ * from their nonsleeping siblings (and report faults).
+ */
+ return 0;
+ }
+
+ return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0;
+}
+
+static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val)
+{
+ struct pca953x_chip *chip = to_pca(gc);
+ u8 reg_val;
+ int ret, offset = 0;
+
+ if (val)
+ reg_val = chip->reg_output[off / BANK_SZ]
+ | (1u << (off % BANK_SZ));
+ else
+ reg_val = chip->reg_output[off / BANK_SZ]
+ & ~(1u << (off % BANK_SZ));
+
+ switch (chip->chip_type) {
+ case PCA953X_TYPE:
+ offset = PCA953X_OUTPUT;
+ break;
+ case PCA957X_TYPE:
+ offset = PCA957X_OUT;
+ break;
+ }
+ ret = pca953x_write_single(chip, offset, reg_val, off);
+ if (ret)
+ goto exit;
+
+ chip->reg_output[off / BANK_SZ] = reg_val;
+exit:
+ return;
+}
+
+static struct gpio_ops pca953x_gpio_ops = {
+ .direction_input = pca953x_gpio_direction_input,
+ .direction_output = pca953x_gpio_direction_output,
+ .get_direction = pca953x_gpio_get_direction,
+ .get = pca953x_gpio_get_value,
+ .set = pca953x_gpio_set_value,
+};
+
+static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios)
+{
+ struct gpio_chip *gc;
+
+ gc = &chip->gpio_chip;
+
+ gc->ops = &pca953x_gpio_ops;
+
+ gc->base = chip->gpio_start;
+ gc->ngpio = gpios;
+ gc->dev = &chip->client->dev;
+}
+
+static int device_pca953x_init(struct pca953x_chip *chip, u32 invert)
+{
+ int ret;
+ u8 val[MAX_BANK];
+
+ ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output);
+ if (ret)
+ goto out;
+
+ ret = pca953x_read_regs(chip, PCA953X_DIRECTION,
+ chip->reg_direction);
+ if (ret)
+ goto out;
+
+ /* set platform specific polarity inversion */
+ if (invert)
+ memset(val, 0xFF, NBANK(chip));
+ else
+ memset(val, 0, NBANK(chip));
+
+ ret = pca953x_write_regs(chip, PCA953X_INVERT, val);
+out:
+ return ret;
+}
+
+static int device_pca957x_init(struct pca953x_chip *chip, u32 invert)
+{
+ int ret;
+ u8 val[MAX_BANK];
+
+ ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output);
+ if (ret)
+ goto out;
+ ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction);
+ if (ret)
+ goto out;
+
+ /* set platform specific polarity inversion */
+ if (invert)
+ memset(val, 0xFF, NBANK(chip));
+ else
+ memset(val, 0, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_INVRT, val);
+
+ /* To enable register 6, 7 to controll pull up and pull down */
+ memset(val, 0x02, NBANK(chip));
+ pca953x_write_regs(chip, PCA957X_BKEN, val);
+
+ return 0;
+out:
+ return ret;
+}
+
+static int pca953x_probe(struct device_d *dev)
+{
+ struct i2c_client *client = to_i2c_client(dev);
+ unsigned long driver_data;
+ struct pca953x_platform_data *pdata;
+ struct pca953x_chip *chip;
+ int ret;
+ u32 invert = 0;
+
+ chip = xzalloc(sizeof(struct pca953x_chip));
+
+ driver_data = 0;
+ pdata = dev->platform_data;
+ if (pdata) {
+ chip->gpio_start = pdata->gpio_base;
+ invert = pdata->invert;
+ chip->names = pdata->names;
+ } else {
+ int err;
+
+ err = dev_get_drvdata(dev, &driver_data);
+ if (err)
+ return err;
+
+ chip->gpio_start = -1;
+ }
+
+ chip->client = client;
+
+ chip->chip_type = driver_data & (PCA953X_TYPE | PCA957X_TYPE);
+
+ /* initialize cached registers from their original values.
+ * we can't share this chip with another i2c master.
+ */
+ pca953x_setup_gpio(chip, driver_data & PCA_GPIO_MASK);
+
+ if (chip->chip_type == PCA953X_TYPE)
+ ret = device_pca953x_init(chip, invert);
+ else
+ ret = device_pca957x_init(chip, invert);
+ if (ret)
+ return ret;
+
+ ret = gpiochip_add(&chip->gpio_chip);
+ if (ret)
+ return ret;
+
+ if (pdata && pdata->setup) {
+ ret = pdata->setup(client, chip->gpio_chip.base,
+ chip->gpio_chip.ngpio, pdata->context);
+ if (ret < 0)
+ dev_warn(&client->dev, "setup failed, %d\n", ret);
+ }
+
+ return 0;
+}
+
+static struct driver_d pca953x_driver = {
+ .name = "pca953x",
+ .probe = pca953x_probe,
+ .id_table = pca953x_id,
+};
+
+static int __init pca953x_init(void)
+{
+ return i2c_driver_register(&pca953x_driver);
+}
+device_initcall(pca953x_init);
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 5ce0324714..648d844252 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_I2C) += i2c.o busses/ algos/
+obj-$(CONFIG_I2C) += i2c.o i2c-smbus.o busses/ algos/
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 370abb0c2e..39622863fb 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -12,10 +12,22 @@ config I2C_GPIO
This is a very simple bitbanging I2C driver utilizing the
arch-neutral GPIO API to control the SCL and SDA lines.
+config I2C_AT91
+ bool "AT91 I2C Master driver"
+ depends on ARCH_AT91
+
config I2C_IMX
bool "MPC85xx/i.MX I2C Master driver"
depends on (ARCH_IMX && !ARCH_IMX1) || ARCH_MPC85XX
+config I2C_MV64XXX
+ bool "Marvell mv64xxx I2C Controller"
+ depends on HAVE_CLK && OFDEVICE
+ help
+ If you say yes to this option, support will be included for the
+ built-in I2C interface on the Marvell 64xxx line of host bridges.
+ This driver is also used for Allwinner SoCs I2C controllers.
+
config I2C_OMAP
bool "OMAP I2C Master driver"
depends on ARCH_OMAP
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 9823d1bd36..1dbfbdf93b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -1,5 +1,7 @@
+obj-$(CONFIG_I2C_AT91) += i2c-at91.o
obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o
-obj-$(CONFIG_I2C_IMX) += i2c-imx.o
-obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
+obj-$(CONFIG_I2C_IMX) += i2c-imx.o
+obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
+obj-$(CONFIG_I2C_OMAP) += i2c-omap.o
obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o
obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o
diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c
new file mode 100644
index 0000000000..399f6a94be
--- /dev/null
+++ b/drivers/i2c/busses/i2c-at91.c
@@ -0,0 +1,437 @@
+/*
+ * i2c Support for Atmel's AT91 Two-Wire Interface (TWI)
+ *
+ * Copyright (C) 2011 Weinmann Medical GmbH
+ * Author: Nikolaus Voss <n.voss@weinmann.de>
+ *
+ * Evolved from original work by:
+ * Copyright (C) 2004 Rick Bronson
+ * Converted to 2.6 by Andrew Victor <andrew@sanpeople.com>
+ *
+ * Borrowed heavily from original work by:
+ * Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.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.
+ */
+
+#include <common.h>
+#include <clock.h>
+#include <i2c/i2c.h>
+#include <malloc.h>
+#include <of.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <driver.h>
+#include <init.h>
+
+#define DEFAULT_TWI_CLK_HZ 100000 /* max 400 Kbits/s */
+#define AT91_I2C_TIMEOUT (100 * MSECOND) /* transfer timeout */
+#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */
+
+/* AT91 TWI register definitions */
+#define AT91_TWI_CR 0x0000 /* Control Register */
+#define AT91_TWI_START 0x0001 /* Send a Start Condition */
+#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */
+#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */
+#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */
+#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */
+#define AT91_TWI_SWRST 0x0080 /* Software Reset */
+
+#define AT91_TWI_MMR 0x0004 /* Master Mode Register */
+#define AT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */
+#define AT91_TWI_MREAD 0x1000 /* Master Read Direction */
+
+#define AT91_TWI_IADR 0x000c /* Internal Address Register */
+
+#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */
+
+#define AT91_TWI_SR 0x0020 /* Status Register */
+#define AT91_TWI_TXCOMP 0x0001 /* Transmission Complete */
+#define AT91_TWI_RXRDY 0x0002 /* Receive Holding Register Ready */
+#define AT91_TWI_TXRDY 0x0004 /* Transmit Holding Register Ready */
+
+#define AT91_TWI_OVRE 0x0040 /* Overrun Error */
+#define AT91_TWI_UNRE 0x0080 /* Underrun Error */
+#define AT91_TWI_NACK 0x0100 /* Not Acknowledged */
+
+#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */
+#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */
+#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */
+#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */
+#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */
+
+struct at91_twi_pdata {
+ unsigned clk_max_div;
+ unsigned clk_offset;
+ bool has_unre_flag;
+};
+
+struct at91_twi_dev {
+ struct device *dev;
+ void __iomem *base;
+ struct clk *clk;
+ u8 *buf;
+ size_t buf_len;
+ struct i2c_msg *msg;
+ unsigned imr;
+ unsigned transfer_status;
+ struct i2c_adapter adapter;
+ unsigned twi_cwgr_reg;
+ struct at91_twi_pdata *pdata;
+};
+
+#define to_at91_twi_dev(a) container_of(a, struct at91_twi_dev, adapter)
+
+static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg)
+{
+ return __raw_readl(dev->base + reg);
+}
+
+static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val)
+{
+ __raw_writel(val, dev->base + reg);
+}
+
+static void at91_disable_twi_interrupts(struct at91_twi_dev *dev)
+{
+ at91_twi_write(dev, AT91_TWI_IDR,
+ AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY);
+}
+
+static void at91_init_twi_bus(struct at91_twi_dev *dev)
+{
+ at91_disable_twi_interrupts(dev);
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST);
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN);
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS);
+ at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg);
+}
+
+/*
+ * Calculate symmetric clock as stated in datasheet:
+ * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset))
+ */
+static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk)
+{
+ int ckdiv, cdiv, div;
+ struct at91_twi_pdata *pdata = dev->pdata;
+ int offset = pdata->clk_offset;
+ int max_ckdiv = pdata->clk_max_div;
+
+ div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk),
+ 2 * twi_clk) - offset);
+ ckdiv = fls(div >> 8);
+ cdiv = div >> ckdiv;
+
+ if (ckdiv > max_ckdiv) {
+ dev_warn(&dev->adapter.dev, "%d exceeds ckdiv max value which is %d.\n",
+ ckdiv, max_ckdiv);
+ ckdiv = max_ckdiv;
+ cdiv = 255;
+ }
+
+ dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv;
+ dev_dbg(&dev->adapter.dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv);
+}
+
+static void at91_twi_write_next_byte(struct at91_twi_dev *dev)
+{
+ if (dev->buf_len <= 0)
+ return;
+
+ at91_twi_write(dev, AT91_TWI_THR, *dev->buf);
+
+ /* send stop when last byte has been written */
+ if (--dev->buf_len == 0)
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+
+ dev_dbg(&dev->adapter.dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len);
+
+ ++dev->buf;
+}
+
+static void at91_twi_read_next_byte(struct at91_twi_dev *dev)
+{
+ if (dev->buf_len <= 0)
+ return;
+
+ *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff;
+ --dev->buf_len;
+
+ /* send stop if second but last byte has been read */
+ if (dev->buf_len == 1)
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP);
+
+ dev_dbg(&dev->adapter.dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len);
+
+ ++dev->buf;
+}
+
+static int at91_twi_wait_completion(struct at91_twi_dev *dev)
+{
+ uint64_t start = get_time_ns();
+ unsigned int status = at91_twi_read(dev, AT91_TWI_SR);
+ unsigned int irqstatus = at91_twi_read(dev, AT91_TWI_IMR);
+
+ if (irqstatus & AT91_TWI_RXRDY)
+ at91_twi_read_next_byte(dev);
+ else if (irqstatus & AT91_TWI_TXRDY)
+ at91_twi_write_next_byte(dev);
+ else
+ dev_warn(&dev->adapter.dev, "neither rx and tx are ready\n");
+
+ dev->transfer_status |= status;
+
+ while(!(at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_TXCOMP)) {
+ if(is_timeout(start, AT91_I2C_TIMEOUT)) {
+ dev_warn(&dev->adapter.dev, "timeout waiting for bus ready\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ at91_disable_twi_interrupts(dev);
+
+ return 0;
+}
+
+static int at91_do_twi_transfer(struct at91_twi_dev *dev)
+{
+ int ret;
+ bool has_unre_flag = dev->pdata->has_unre_flag;
+
+ dev_dbg(&dev->adapter.dev, "transfer: %s %d bytes.\n",
+ (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len);
+
+ dev->transfer_status = 0;
+
+ if (!dev->buf_len) {
+ at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK);
+ at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP);
+ } else if (dev->msg->flags & I2C_M_RD) {
+ unsigned start_flags = AT91_TWI_START;
+
+ if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) {
+ dev_err(&dev->adapter.dev, "RXRDY still set!");
+ at91_twi_read(dev, AT91_TWI_RHR);
+ }
+
+ /* if only one byte is to be read, immediately stop transfer */
+ if (dev->buf_len <= 1)
+ start_flags |= AT91_TWI_STOP;
+
+ at91_twi_write(dev, AT91_TWI_CR, start_flags);
+
+ at91_twi_write(dev, AT91_TWI_IER,
+ AT91_TWI_TXCOMP | AT91_TWI_RXRDY);
+ } else {
+ at91_twi_write_next_byte(dev);
+ at91_twi_write(dev, AT91_TWI_IER,
+ AT91_TWI_TXCOMP | AT91_TWI_TXRDY);
+ }
+
+ ret = at91_twi_wait_completion(dev);
+ if (ret < 0) {
+ dev_err(&dev->adapter.dev, "controller timed out\n");
+ at91_init_twi_bus(dev);
+ ret = -ETIMEDOUT;
+ goto error;
+ }
+ if (dev->transfer_status & AT91_TWI_NACK) {
+ dev_dbg(&dev->adapter.dev, "received nack\n");
+ ret = -EREMOTEIO;
+ goto error;
+ }
+ if (dev->transfer_status & AT91_TWI_OVRE) {
+ dev_err(&dev->adapter.dev, "overrun while reading\n");
+ ret = -EIO;
+ goto error;
+ }
+ if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) {
+ dev_err(&dev->adapter.dev, "underrun while writing\n");
+ ret = -EIO;
+ goto error;
+ }
+ dev_dbg(&dev->adapter.dev, "transfer complete\n");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num)
+{
+ struct at91_twi_dev *dev = to_at91_twi_dev(adap);
+ int ret;
+ unsigned int_addr_flag = 0;
+ struct i2c_msg *m_start = msg;
+
+ dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num);
+
+ /*
+ * The hardware can handle at most two messages concatenated by a
+ * repeated start via it's internal address feature.
+ */
+ if (num > 2) {
+ dev_err(&dev->adapter.dev,
+ "cannot handle more than two concatenated messages.\n");
+ return 0;
+ } else if (num == 2) {
+ int internal_address = 0;
+ int i;
+
+ if (msg->flags & I2C_M_RD) {
+ dev_err(&dev->adapter.dev, "first transfer must be write.\n");
+ return -EINVAL;
+ }
+ if (msg->len > 3) {
+ dev_err(&dev->adapter.dev, "first message size must be <= 3.\n");
+ return -EINVAL;
+ }
+
+ /* 1st msg is put into the internal address, start with 2nd */
+ m_start = &msg[1];
+ for (i = 0; i < msg->len; ++i) {
+ const unsigned addr = msg->buf[msg->len - 1 - i];
+
+ internal_address |= addr << (8 * i);
+ int_addr_flag += AT91_TWI_IADRSZ_1;
+ }
+ at91_twi_write(dev, AT91_TWI_IADR, internal_address);
+ }
+
+ at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag
+ | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0));
+
+ dev->buf_len = m_start->len;
+ dev->buf = m_start->buf;
+ dev->msg = m_start;
+
+ ret = at91_do_twi_transfer(dev);
+
+ return (ret < 0) ? ret : num;
+}
+
+static struct at91_twi_pdata at91rm9200_config = {
+ .clk_max_div = 5,
+ .clk_offset = 3,
+ .has_unre_flag = true,
+};
+
+static struct at91_twi_pdata at91sam9261_config = {
+ .clk_max_div = 5,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9260_config = {
+ .clk_max_div = 7,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g20_config = {
+ .clk_max_div = 7,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+};
+
+static struct at91_twi_pdata at91sam9g10_config = {
+ .clk_max_div = 7,
+ .clk_offset = 4,
+ .has_unre_flag = false,
+};
+
+static struct platform_device_id at91_twi_devtypes[] = {
+ {
+ .name = "i2c-at91rm9200",
+ .driver_data = (unsigned long) &at91rm9200_config,
+ }, {
+ .name = "i2c-at91sam9261",
+ .driver_data = (unsigned long) &at91sam9261_config,
+ }, {
+ .name = "i2c-at91sam9260",
+ .driver_data = (unsigned long) &at91sam9260_config,
+ }, {
+ .name = "i2c-at91sam9g20",
+ .driver_data = (unsigned long) &at91sam9g20_config,
+ }, {
+ .name = "i2c-at91sam9g10",
+ .driver_data = (unsigned long) &at91sam9g10_config,
+ }, {
+ /* sentinel */
+ }
+};
+
+static int at91_twi_probe(struct device_d *dev)
+{
+ struct at91_twi_dev *i2c_at91;
+ struct at91_twi_pdata *i2c_data;
+ int rc;
+ u32 bus_clk_rate;
+
+ i2c_at91 = xzalloc(sizeof(struct at91_twi_dev));
+
+ rc = dev_get_drvdata(dev, (unsigned long *)&i2c_data);
+ if (rc)
+ goto out_free;
+
+ i2c_at91->pdata = i2c_data;
+
+ i2c_at91->base = dev_request_mem_region(dev, 0);
+ if (!i2c_at91->base) {
+ dev_err(dev, "could not get memory region\n");
+ rc = -ENODEV;
+ goto out_free;
+ }
+
+ i2c_at91->clk = clk_get(dev, "twi_clk");
+ if (IS_ERR(i2c_at91->clk)) {
+ dev_err(dev, "no clock defined\n");
+ rc = -ENODEV;
+ goto out_free;
+ }
+
+ clk_enable(i2c_at91->clk);
+
+ bus_clk_rate = DEFAULT_TWI_CLK_HZ;
+
+ at91_calc_twi_clock(i2c_at91, bus_clk_rate);
+ at91_init_twi_bus(i2c_at91);
+
+ i2c_at91->adapter.master_xfer = at91_twi_xfer;
+ i2c_at91->adapter.dev.parent = dev;
+ i2c_at91->adapter.nr = dev->id;
+ i2c_at91->adapter.dev.device_node = dev->device_node;
+
+ rc = i2c_add_numbered_adapter(&i2c_at91->adapter);
+ if (rc) {
+ dev_err(dev, "Failed to add I2C adapter\n");
+ goto out_adap_fail;
+ }
+
+ dev_info(dev, "AT91 i2c bus driver.\n");
+ return 0;
+
+out_adap_fail:
+ clk_disable(i2c_at91->clk);
+ clk_put(i2c_at91->clk);
+out_free:
+ kfree(i2c_at91);
+ return rc;
+}
+
+static struct driver_d at91_twi_driver = {
+ .name = "at91-twi",
+ .probe = at91_twi_probe,
+ .id_table = at91_twi_devtypes,
+};
+device_platform_driver(at91_twi_driver);
+
+MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>");
+MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
new file mode 100644
index 0000000000..6d8c85b9d7
--- /dev/null
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -0,0 +1,647 @@
+/*
+ * Driver for the i2c controller on the Marvell line of host bridges
+ * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family).
+ *
+ * This code was ported from linux-3.15 kernel by Antony Pavlov.
+ *
+ * Author: Mark A. Greer <mgreer@mvista.com>
+ *
+ * 2005 (c) MontaVista, Software, Inc. This file is licensed under
+ * the terms of the GNU General Public License version 2. This program
+ * is licensed "as is" without any warranty of any kind, whether express
+ * or implied.
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <of.h>
+#include <malloc.h>
+#include <types.h>
+#include <xfuncs.h>
+#include <clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <io.h>
+#include <i2c/i2c.h>
+
+#define ADDR_ADDR(val) ((val & 0x7f) << 1)
+#define BAUD_DIV_N(val) (val & 0x7)
+#define BAUD_DIV_M(val) ((val & 0xf) << 3)
+
+#define REG_CONTROL_ACK 0x00000004
+#define REG_CONTROL_IFLG 0x00000008
+#define REG_CONTROL_STOP 0x00000010
+#define REG_CONTROL_START 0x00000020
+#define REG_CONTROL_TWSIEN 0x00000040
+#define REG_CONTROL_INTEN 0x00000080
+
+/* Ctlr status values */
+#define STATUS_MAST_START 0x08
+#define STATUS_MAST_REPEAT_START 0x10
+#define STATUS_MAST_WR_ADDR_ACK 0x18
+#define STATUS_MAST_WR_ADDR_NO_ACK 0x20
+#define STATUS_MAST_WR_ACK 0x28
+#define STATUS_MAST_WR_NO_ACK 0x30
+#define STATUS_MAST_RD_ADDR_ACK 0x40
+#define STATUS_MAST_RD_ADDR_NO_ACK 0x48
+#define STATUS_MAST_RD_DATA_ACK 0x50
+#define STATUS_MAST_RD_DATA_NO_ACK 0x58
+#define STATUS_MAST_WR_ADDR_2_ACK 0xd0
+#define STATUS_MAST_RD_ADDR_2_ACK 0xe0
+
+/* Driver states */
+enum mv64xxx_state {
+ STATE_INVALID,
+ STATE_IDLE,
+ STATE_WAITING_FOR_START_COND,
+ STATE_WAITING_FOR_RESTART,
+ STATE_WAITING_FOR_ADDR_1_ACK,
+ STATE_WAITING_FOR_ADDR_2_ACK,
+ STATE_WAITING_FOR_SLAVE_ACK,
+ STATE_WAITING_FOR_SLAVE_DATA,
+};
+
+/* Driver actions */
+enum mv64xxx_action {
+ ACTION_INVALID,
+ ACTION_CONTINUE,
+ ACTION_SEND_RESTART,
+ ACTION_OFFLOAD_RESTART,
+ ACTION_SEND_ADDR_1,
+ ACTION_SEND_ADDR_2,
+ ACTION_SEND_DATA,
+ ACTION_RCV_DATA,
+ ACTION_RCV_DATA_STOP,
+ ACTION_SEND_STOP,
+ ACTION_OFFLOAD_SEND_STOP,
+};
+
+struct mv64xxx_i2c_regs {
+ u8 addr;
+ u8 ext_addr;
+ u8 data;
+ u8 control;
+ u8 status;
+ u8 clock;
+ u8 soft_reset;
+};
+
+struct mv64xxx_i2c_data {
+ struct i2c_msg *msgs;
+ int num_msgs;
+ enum mv64xxx_state state;
+ enum mv64xxx_action action;
+ u8 cntl_bits;
+ void __iomem *reg_base;
+ struct mv64xxx_i2c_regs reg_offsets;
+ u8 addr1;
+ u8 addr2;
+ u8 bytes_left;
+ u8 byte_posn;
+ u8 send_stop;
+ bool block;
+ int rc;
+ u32 freq_m;
+ u32 freq_n;
+ struct clk *clk;
+ struct i2c_msg *msg;
+ struct i2c_adapter adapter;
+/* 5us delay in order to avoid repeated start timing violation */
+ bool errata_delay;
+ void (*write_reg)(struct mv64xxx_i2c_data *drv_data, u32 v, unsigned reg);
+ u32 (*read_reg)(struct mv64xxx_i2c_data *drv_data, unsigned reg);
+};
+
+static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = {
+ .addr = 0x00,
+ .ext_addr = 0x10,
+ .data = 0x04,
+ .control = 0x08,
+ .status = 0x0c,
+ .clock = 0x0c,
+ .soft_reset = 0x1c,
+};
+
+static void mv64xxx_writeb(struct mv64xxx_i2c_data *drv_data,
+ u32 v, unsigned reg)
+{
+ writeb(v, drv_data->reg_base + reg);
+}
+
+static void mv64xxx_writel(struct mv64xxx_i2c_data *drv_data,
+ u32 v, unsigned reg)
+{
+ writel(v, drv_data->reg_base + reg);
+}
+
+static inline void mv64xxx_write(struct mv64xxx_i2c_data *drv_data,
+ u32 v, unsigned reg)
+{
+ drv_data->write_reg(drv_data, v, reg);
+}
+
+static u32 mv64xxx_readb(struct mv64xxx_i2c_data *drv_data, unsigned reg)
+{
+ return readb(drv_data->reg_base + reg);
+}
+
+static u32 mv64xxx_readl(struct mv64xxx_i2c_data *drv_data, unsigned reg)
+{
+ return readl(drv_data->reg_base + reg);
+}
+
+static inline u32 mv64xxx_read(struct mv64xxx_i2c_data *drv_data, unsigned reg)
+{
+ return drv_data->read_reg(drv_data, reg);
+}
+
+static void
+mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
+ struct i2c_msg *msg)
+{
+ u32 dir = 0;
+
+ drv_data->cntl_bits = REG_CONTROL_ACK |
+ REG_CONTROL_INTEN | REG_CONTROL_TWSIEN;
+
+ if (msg->flags & I2C_M_RD)
+ dir = 1;
+
+ if (msg->flags & I2C_M_TEN) {
+ drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;
+ drv_data->addr2 = (u32)msg->addr & 0xff;
+ } else {
+ drv_data->addr1 = ADDR_ADDR((u32)msg->addr) | dir;
+ drv_data->addr2 = 0;
+ }
+}
+
+/*
+ *****************************************************************************
+ *
+ * Finite State Machine & Interrupt Routines
+ *
+ *****************************************************************************
+ */
+
+/* Reset hardware and initialize FSM */
+static void
+mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data)
+{
+ mv64xxx_write(drv_data, 0, drv_data->reg_offsets.soft_reset);
+ mv64xxx_write(drv_data, BAUD_DIV_M(drv_data->freq_m)
+ | BAUD_DIV_N(drv_data->freq_n),
+ drv_data->reg_offsets.clock);
+ mv64xxx_write(drv_data, 0, drv_data->reg_offsets.addr);
+ mv64xxx_write(drv_data, 0, drv_data->reg_offsets.ext_addr);
+ mv64xxx_write(drv_data, REG_CONTROL_TWSIEN
+ | REG_CONTROL_STOP,
+ drv_data->reg_offsets.control);
+ drv_data->state = STATE_IDLE;
+}
+
+static void
+mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status)
+{
+ /*
+ * If state is idle, then this is likely the remnants of an old
+ * operation that driver has given up on or the user has killed.
+ * If so, issue the stop condition and go to idle.
+ */
+ if (drv_data->state == STATE_IDLE) {
+ drv_data->action = ACTION_SEND_STOP;
+ return;
+ }
+
+ /* The status from the ctlr [mostly] tells us what to do next */
+ switch (status) {
+ /* Start condition interrupt */
+ case STATUS_MAST_START: /* 0x08 */
+ case STATUS_MAST_REPEAT_START: /* 0x10 */
+ drv_data->action = ACTION_SEND_ADDR_1;
+ drv_data->state = STATE_WAITING_FOR_ADDR_1_ACK;
+ break;
+
+ /* Performing a write */
+ case STATUS_MAST_WR_ADDR_ACK: /* 0x18 */
+ if (drv_data->msg->flags & I2C_M_TEN) {
+ drv_data->action = ACTION_SEND_ADDR_2;
+ drv_data->state =
+ STATE_WAITING_FOR_ADDR_2_ACK;
+ break;
+ }
+ /* FALLTHRU */
+ case STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */
+ case STATUS_MAST_WR_ACK: /* 0x28 */
+ if (drv_data->bytes_left == 0) {
+ if (drv_data->send_stop) {
+ drv_data->action = ACTION_SEND_STOP;
+ drv_data->state = STATE_IDLE;
+ } else {
+ drv_data->action =
+ ACTION_SEND_RESTART;
+ drv_data->state =
+ STATE_WAITING_FOR_RESTART;
+ }
+ } else {
+ drv_data->action = ACTION_SEND_DATA;
+ drv_data->state =
+ STATE_WAITING_FOR_SLAVE_ACK;
+ drv_data->bytes_left--;
+ }
+ break;
+
+ /* Performing a read */
+ case STATUS_MAST_RD_ADDR_ACK: /* 40 */
+ if (drv_data->msg->flags & I2C_M_TEN) {
+ drv_data->action = ACTION_SEND_ADDR_2;
+ drv_data->state =
+ STATE_WAITING_FOR_ADDR_2_ACK;
+ break;
+ }
+ /* FALLTHRU */
+ case STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */
+ if (drv_data->bytes_left == 0) {
+ drv_data->action = ACTION_SEND_STOP;
+ drv_data->state = STATE_IDLE;
+ break;
+ }
+ /* FALLTHRU */
+ case STATUS_MAST_RD_DATA_ACK: /* 0x50 */
+ if (status != STATUS_MAST_RD_DATA_ACK)
+ drv_data->action = ACTION_CONTINUE;
+ else {
+ drv_data->action = ACTION_RCV_DATA;
+ drv_data->bytes_left--;
+ }
+ drv_data->state = STATE_WAITING_FOR_SLAVE_DATA;
+
+ if (drv_data->bytes_left == 1)
+ drv_data->cntl_bits &= ~REG_CONTROL_ACK;
+ break;
+
+ case STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */
+ drv_data->action = ACTION_RCV_DATA_STOP;
+ drv_data->state = STATE_IDLE;
+ break;
+
+ case STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */
+ case STATUS_MAST_WR_NO_ACK: /* 30 */
+ case STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */
+ /* Doesn't seem to be a device at other end */
+ drv_data->action = ACTION_SEND_STOP;
+ drv_data->state = STATE_IDLE;
+ drv_data->rc = -ENXIO;
+ break;
+
+ default:
+ dev_err(&drv_data->adapter.dev,
+ "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, "
+ "status: 0x%x, addr: 0x%x, flags: 0x%x\n",
+ drv_data->state, status, drv_data->msg->addr,
+ drv_data->msg->flags);
+ drv_data->action = ACTION_SEND_STOP;
+ mv64xxx_i2c_hw_init(drv_data);
+ drv_data->rc = -EIO;
+ }
+}
+
+static void mv64xxx_i2c_send_start(struct mv64xxx_i2c_data *drv_data)
+{
+ drv_data->msg = drv_data->msgs;
+ drv_data->byte_posn = 0;
+ drv_data->bytes_left = drv_data->msg->len;
+ drv_data->rc = 0;
+
+ mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs);
+ mv64xxx_write(drv_data, drv_data->cntl_bits | REG_CONTROL_START,
+ drv_data->reg_offsets.control);
+}
+
+static void
+mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data)
+{
+ switch (drv_data->action) {
+ case ACTION_SEND_RESTART:
+ /* We should only get here if we have further messages */
+ BUG_ON(drv_data->num_msgs == 0);
+
+ drv_data->msgs++;
+ drv_data->num_msgs--;
+ mv64xxx_i2c_send_start(drv_data);
+
+ if (drv_data->errata_delay)
+ udelay(5);
+
+ /*
+ * We're never at the start of the message here, and by this
+ * time it's already too late to do any protocol mangling.
+ * Thankfully, do not advertise support for that feature.
+ */
+ drv_data->send_stop = drv_data->num_msgs == 1;
+ break;
+
+ case ACTION_CONTINUE:
+ mv64xxx_write(drv_data, drv_data->cntl_bits,
+ drv_data->reg_offsets.control);
+ break;
+
+ case ACTION_SEND_ADDR_1:
+ mv64xxx_write(drv_data, drv_data->addr1,
+ drv_data->reg_offsets.data);
+ mv64xxx_write(drv_data, drv_data->cntl_bits,
+ drv_data->reg_offsets.control);
+ break;
+
+ case ACTION_SEND_ADDR_2:
+ mv64xxx_write(drv_data, drv_data->addr2,
+ drv_data->reg_offsets.data);
+ mv64xxx_write(drv_data, drv_data->cntl_bits,
+ drv_data->reg_offsets.control);
+ break;
+
+ case ACTION_SEND_DATA:
+ mv64xxx_write(drv_data, drv_data->msg->buf[drv_data->byte_posn++],
+ drv_data->reg_offsets.data);
+ mv64xxx_write(drv_data, drv_data->cntl_bits,
+ drv_data->reg_offsets.control);
+ break;
+
+ case ACTION_RCV_DATA:
+ drv_data->msg->buf[drv_data->byte_posn++] =
+ mv64xxx_read(drv_data, drv_data->reg_offsets.data);
+ mv64xxx_write(drv_data, drv_data->cntl_bits,
+ drv_data->reg_offsets.control);
+ break;
+
+ case ACTION_RCV_DATA_STOP:
+ drv_data->msg->buf[drv_data->byte_posn++] =
+ mv64xxx_read(drv_data, drv_data->reg_offsets.data);
+ drv_data->cntl_bits &= ~REG_CONTROL_INTEN;
+ mv64xxx_write(drv_data, drv_data->cntl_bits | REG_CONTROL_STOP,
+ drv_data->reg_offsets.control);
+ drv_data->block = false;
+ if (drv_data->errata_delay)
+ udelay(5);
+
+ break;
+
+ case ACTION_INVALID:
+ default:
+ dev_err(&drv_data->adapter.dev,
+ "mv64xxx_i2c_do_action: Invalid action: %d\n",
+ drv_data->action);
+ drv_data->rc = -EIO;
+
+ /* FALLTHRU */
+ case ACTION_SEND_STOP:
+ drv_data->cntl_bits &= ~REG_CONTROL_INTEN;
+ mv64xxx_write(drv_data, drv_data->cntl_bits
+ | REG_CONTROL_STOP,
+ drv_data->reg_offsets.control);
+ drv_data->block = false;
+ break;
+ }
+}
+
+static void mv64xxx_i2c_intr(struct mv64xxx_i2c_data *drv_data)
+{
+ u32 status;
+ uint64_t start;
+
+ start = get_time_ns();
+
+ while (mv64xxx_read(drv_data, drv_data->reg_offsets.control) &
+ REG_CONTROL_IFLG) {
+ status = mv64xxx_read(drv_data, drv_data->reg_offsets.status);
+ mv64xxx_i2c_fsm(drv_data, status);
+ mv64xxx_i2c_do_action(drv_data);
+
+ if (is_timeout_non_interruptible(start, 3 * SECOND)) {
+ drv_data->rc = -EIO;
+ break;
+ }
+ }
+}
+
+/*
+ *****************************************************************************
+ *
+ * I2C Msg Execution Routines
+ *
+ *****************************************************************************
+ */
+static void
+mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data)
+{
+ do {
+ mv64xxx_i2c_intr(drv_data);
+ if (drv_data->rc) {
+ drv_data->state = STATE_IDLE;
+ dev_err(&drv_data->adapter.dev, "I2C bus error\n");
+ mv64xxx_i2c_hw_init(drv_data);
+ drv_data->block = false;
+ }
+ } while (drv_data->block);
+}
+
+/*
+ *****************************************************************************
+ *
+ * I2C Core Support Routines (Interface to higher level I2C code)
+ *
+ *****************************************************************************
+ */
+static int
+mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+ struct mv64xxx_i2c_data *drv_data = container_of(adap, struct mv64xxx_i2c_data, adapter);
+ int ret = num;
+
+ BUG_ON(drv_data->msgs != NULL);
+
+ drv_data->msgs = msgs;
+ drv_data->num_msgs = num;
+ drv_data->state = STATE_WAITING_FOR_START_COND;
+ drv_data->send_stop = (num == 1);
+ drv_data->block = true;
+ mv64xxx_i2c_send_start(drv_data);
+ mv64xxx_i2c_wait_for_completion(drv_data);
+
+ if (drv_data->rc < 0)
+ ret = drv_data->rc;
+
+ drv_data->num_msgs = 0;
+ drv_data->msgs = NULL;
+
+ return ret;
+}
+
+/*
+ *****************************************************************************
+ *
+ * Driver Interface & Early Init Routines
+ *
+ *****************************************************************************
+ */
+static struct of_device_id mv64xxx_i2c_of_match_table[] = {
+ { .compatible = "marvell,mv64xxx-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx},
+ { .compatible = "marvell,mv78230-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx},
+ { .compatible = "marvell,mv78230-a0-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx},
+ {}
+};
+
+static inline int
+mv64xxx_calc_freq(const int tclk, const int n, const int m)
+{
+ return tclk / (10 * (m + 1) * (2 << n));
+}
+
+static bool
+mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n,
+ u32 *best_m)
+{
+ int freq, delta, best_delta = INT_MAX;
+ int m, n;
+
+ for (n = 0; n <= 7; n++)
+ for (m = 0; m <= 15; m++) {
+ freq = mv64xxx_calc_freq(tclk, n, m);
+ delta = req_freq - freq;
+ if (delta >= 0 && delta < best_delta) {
+ *best_m = m;
+ *best_n = n;
+ best_delta = delta;
+ }
+ if (best_delta == 0)
+ return true;
+ }
+ if (best_delta == INT_MAX)
+ return false;
+ return true;
+}
+
+static int
+mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data,
+ struct device_d *pd)
+{
+ struct device_node *np = pd->device_node;
+ u32 bus_freq, tclk;
+ int rc = 0;
+ u32 prop;
+ struct mv64xxx_i2c_regs *mv64xxx_regs;
+ int freq;
+
+ if (IS_ERR(drv_data->clk)) {
+ rc = -ENODEV;
+ goto out;
+ }
+ tclk = clk_get_rate(drv_data->clk);
+
+ rc = of_property_read_u32(np, "clock-frequency", &bus_freq);
+ if (rc)
+ bus_freq = 100000; /* 100kHz by default */
+
+ if (!mv64xxx_find_baud_factors(bus_freq, tclk,
+ &drv_data->freq_n, &drv_data->freq_m)) {
+ rc = -EINVAL;
+ goto out;
+ }
+
+ freq = mv64xxx_calc_freq(tclk, drv_data->freq_n, drv_data->freq_m);
+ dev_dbg(pd, "tclk=%d freq_n=%d freq_m=%d freq=%d\n",
+ tclk, drv_data->freq_n, drv_data->freq_m, freq);
+
+ if (of_property_read_u32(np, "reg-io-width", &prop)) {
+ /* Use 32-bit registers by default */
+ prop = 4;
+ }
+
+ switch (prop) {
+ case 1:
+ drv_data->write_reg = mv64xxx_writeb;
+ drv_data->read_reg = mv64xxx_readb;
+ break;
+ case 4:
+ drv_data->write_reg = mv64xxx_writel;
+ drv_data->read_reg = mv64xxx_readl;
+ break;
+ default:
+ dev_err(pd, "unsupported reg-io-width (%d)\n", prop);
+ rc = -EINVAL;
+ goto out;
+ }
+
+ dev_get_drvdata(pd, (unsigned long *)&mv64xxx_regs);
+ memcpy(&drv_data->reg_offsets, mv64xxx_regs,
+ sizeof(drv_data->reg_offsets));
+
+ /*
+ * For controllers embedded in new SoCs activate the errata fix.
+ */
+ if (of_device_is_compatible(np, "marvell,mv78230-i2c")) {
+ drv_data->errata_delay = true;
+ }
+
+ if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) {
+ drv_data->errata_delay = true;
+ }
+
+out:
+ return rc;
+}
+
+static int
+mv64xxx_i2c_probe(struct device_d *pd)
+{
+ struct mv64xxx_i2c_data *drv_data;
+ int rc;
+
+ if (!pd->device_node)
+ return -ENODEV;
+
+ drv_data = xzalloc(sizeof(*drv_data));
+
+ drv_data->reg_base = dev_request_mem_region(pd, 0);
+ if (IS_ERR(drv_data->reg_base))
+ return PTR_ERR(drv_data->reg_base);
+
+ drv_data->clk = clk_get(pd, NULL);
+ if (IS_ERR(drv_data->clk))
+ return PTR_ERR(drv_data->clk);
+
+ clk_enable(drv_data->clk);
+
+ rc = mv64xxx_of_config(drv_data, pd);
+ if (rc)
+ goto exit_clk;
+
+ drv_data->adapter.master_xfer = mv64xxx_i2c_xfer;
+ drv_data->adapter.dev.parent = pd;
+ drv_data->adapter.nr = pd->id;
+ drv_data->adapter.dev.device_node = pd->device_node;
+
+ mv64xxx_i2c_hw_init(drv_data);
+
+ rc = i2c_add_numbered_adapter(&drv_data->adapter);
+ if (rc) {
+ dev_err(pd, "Failed to add I2C adapter\n");
+ goto exit_clk;
+ }
+
+ return 0;
+
+exit_clk:
+ clk_disable(drv_data->clk);
+
+ return rc;
+}
+
+static struct driver_d mv64xxx_i2c_driver = {
+ .probe = mv64xxx_i2c_probe,
+ .name = "mv64xxx_i2c",
+ .of_compatible = DRV_OF_COMPAT(mv64xxx_i2c_of_match_table),
+};
+device_platform_driver(mv64xxx_i2c_driver);
diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c
new file mode 100644
index 0000000000..e8aeaa7234
--- /dev/null
+++ b/drivers/i2c/i2c-smbus.c
@@ -0,0 +1,371 @@
+#include <common.h>
+#include <errno.h>
+#include <i2c/i2c.h>
+
+/* The SMBus parts */
+
+#define POLY (0x1070U << 3)
+static u8 crc8(u16 data)
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ if (data & 0x8000)
+ data = data ^ POLY;
+ data = data << 1;
+ }
+ return (u8)(data >> 8);
+}
+
+/* Incremental CRC8 over count bytes in the array pointed to by p */
+static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ crc = crc8((crc ^ p[i]) << 8);
+ return crc;
+}
+
+/* Assume a 7-bit address, which is reasonable for SMBus */
+static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg)
+{
+ /* The address will be sent first */
+ u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD);
+ pec = i2c_smbus_pec(pec, &addr, 1);
+
+ /* The data buffer follows */
+ return i2c_smbus_pec(pec, msg->buf, msg->len);
+}
+
+/* Used for write only transactions */
+static inline void i2c_smbus_add_pec(struct i2c_msg *msg)
+{
+ msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg);
+ msg->len++;
+}
+
+/* Return <0 on CRC error
+ If there was a write before this read (most cases) we need to take the
+ partial CRC from the write part into account.
+ Note that this function does modify the message (we need to decrease the
+ message length to hide the CRC byte from the caller). */
+static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
+{
+ u8 rpec = msg->buf[--msg->len];
+ cpec = i2c_smbus_msg_pec(cpec, msg);
+
+ if (rpec != cpec) {
+ pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
+ rpec, cpec);
+ return -EBADMSG;
+ }
+ return 0;
+}
+
+/**
+ * i2c_smbus_read_byte - SMBus "receive byte" protocol
+ * @client: Handle to slave device
+ *
+ * This executes the SMBus "receive byte" protocol, returning negative errno
+ * else the byte received from the device.
+ */
+s32 i2c_smbus_read_byte(const struct i2c_client *client)
+{
+ union i2c_smbus_data data;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_READ, 0,
+ I2C_SMBUS_BYTE, &data);
+ return (status < 0) ? status : data.byte;
+}
+EXPORT_SYMBOL(i2c_smbus_read_byte);
+
+/**
+ * i2c_smbus_write_byte - SMBus "send byte" protocol
+ * @client: Handle to slave device
+ * @value: Byte to be sent
+ *
+ * This executes the SMBus "send byte" protocol, returning negative errno
+ * else zero on success.
+ */
+s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
+{
+ return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+}
+EXPORT_SYMBOL(i2c_smbus_write_byte);
+
+/**
+ * i2c_smbus_read_byte_data - SMBus "read byte" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ *
+ * This executes the SMBus "read byte" protocol, returning negative errno
+ * else a data byte received from the device.
+ */
+s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
+{
+ union i2c_smbus_data data;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_BYTE_DATA, &data);
+ return (status < 0) ? status : data.byte;
+}
+EXPORT_SYMBOL(i2c_smbus_read_byte_data);
+
+/**
+ * i2c_smbus_write_byte_data - SMBus "write byte" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: Byte being written
+ *
+ * This executes the SMBus "write byte" protocol, returning negative errno
+ * else zero on success.
+ */
+s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command,
+ u8 value)
+{
+ union i2c_smbus_data data;
+ data.byte = value;
+ return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_BYTE_DATA, &data);
+}
+EXPORT_SYMBOL(i2c_smbus_write_byte_data);
+
+/**
+ * i2c_smbus_read_word_data - SMBus "read word" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ *
+ * This executes the SMBus "read word" protocol, returning negative errno
+ * else a 16-bit unsigned "word" received from the device.
+ */
+s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command)
+{
+ union i2c_smbus_data data;
+ int status;
+
+ status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_WORD_DATA, &data);
+ return (status < 0) ? status : data.word;
+}
+EXPORT_SYMBOL(i2c_smbus_read_word_data);
+
+/**
+ * i2c_smbus_write_word_data - SMBus "write word" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: 16-bit "word" being written
+ *
+ * This executes the SMBus "write word" protocol, returning negative errno
+ * else zero on success.
+ */
+s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command,
+ u16 value)
+{
+ union i2c_smbus_data data;
+ data.word = value;
+ return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_WORD_DATA, &data);
+}
+EXPORT_SYMBOL(i2c_smbus_write_word_data);
+
+/* Returns the number of read bytes */
+s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command,
+ u8 length, u8 *values)
+{
+ union i2c_smbus_data data;
+ int status;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = length;
+ status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_READ, command,
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+ if (status < 0)
+ return status;
+
+ memcpy(values, &data.block[1], data.block[0]);
+ return data.block[0];
+}
+EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data);
+
+s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command,
+ u8 length, const u8 *values)
+{
+ union i2c_smbus_data data;
+
+ if (length > I2C_SMBUS_BLOCK_MAX)
+ length = I2C_SMBUS_BLOCK_MAX;
+ data.block[0] = length;
+ memcpy(data.block + 1, values, length);
+ return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */,
+ I2C_SMBUS_WRITE, command,
+ I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data);
+
+/* Simulate a SMBus command using the i2c protocol
+ No checking of parameters is done! */
+static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags,
+ char read_write, u8 command, int size,
+ union i2c_smbus_data *data)
+{
+ /* So we need to generate a series of msgs. In the case of writing, we
+ need to use only one message; when reading, we need two. We initialize
+ most things with sane defaults, to keep the code below somewhat
+ simpler. */
+ unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3];
+ unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2];
+ int num = read_write == I2C_SMBUS_READ ? 2 : 1;
+ int i;
+ u8 partial_pec = 0;
+ int status;
+ struct i2c_msg msg[2] = {
+ {
+ .addr = addr,
+ .flags = flags,
+ .len = 1,
+ .buf = msgbuf0,
+ }, {
+ .addr = addr,
+ .flags = flags | I2C_M_RD,
+ .len = 0,
+ .buf = msgbuf1,
+ },
+ };
+
+ msgbuf0[0] = command;
+ switch (size) {
+ case I2C_SMBUS_QUICK:
+ msg[0].len = 0;
+ /* Special case: The read/write field is used as data */
+ msg[0].flags = flags | (read_write == I2C_SMBUS_READ ?
+ I2C_M_RD : 0);
+ num = 1;
+ break;
+ case I2C_SMBUS_BYTE:
+ if (read_write == I2C_SMBUS_READ) {
+ /* Special case: only a read! */
+ msg[0].flags = I2C_M_RD | flags;
+ num = 1;
+ }
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ if (read_write == I2C_SMBUS_READ)
+ msg[1].len = 1;
+ else {
+ msg[0].len = 2;
+ msgbuf0[1] = data->byte;
+ }
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ if (read_write == I2C_SMBUS_READ)
+ msg[1].len = 2;
+ else {
+ msg[0].len = 3;
+ msgbuf0[1] = data->word & 0xff;
+ msgbuf0[2] = data->word >> 8;
+ }
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ if (read_write == I2C_SMBUS_READ) {
+ msg[1].len = data->block[0];
+ } else {
+ msg[0].len = data->block[0] + 1;
+ if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
+ dev_err(&adapter->dev,
+ "Invalid block write size %d\n",
+ data->block[0]);
+ return -EINVAL;
+ }
+ for (i = 1; i <= data->block[0]; i++)
+ msgbuf0[i] = data->block[i];
+ }
+ break;
+ default:
+ dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
+ return -EOPNOTSUPP;
+ }
+
+ i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
+ && size != I2C_SMBUS_I2C_BLOCK_DATA);
+ if (i) {
+ /* Compute PEC if first message is a write */
+ if (!(msg[0].flags & I2C_M_RD)) {
+ if (num == 1) /* Write only */
+ i2c_smbus_add_pec(&msg[0]);
+ else /* Write followed by read */
+ partial_pec = i2c_smbus_msg_pec(0, &msg[0]);
+ }
+ /* Ask for PEC if last message is a read */
+ if (msg[num-1].flags & I2C_M_RD)
+ msg[num-1].len++;
+ }
+
+ status = i2c_transfer(adapter, msg, num);
+ if (status < 0)
+ return status;
+
+ /* Check PEC if last message is a read */
+ if (i && (msg[num-1].flags & I2C_M_RD)) {
+ status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
+ if (status < 0)
+ return status;
+ }
+
+ if (read_write == I2C_SMBUS_READ)
+ switch (size) {
+ case I2C_SMBUS_BYTE:
+ data->byte = msgbuf0[0];
+ break;
+ case I2C_SMBUS_BYTE_DATA:
+ data->byte = msgbuf1[0];
+ break;
+ case I2C_SMBUS_WORD_DATA:
+ data->word = msgbuf1[0] | (msgbuf1[1] << 8);
+ break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ for (i = 0; i < data->block[0]; i++)
+ data->block[i+1] = msgbuf1[i];
+ break;
+ }
+ return 0;
+}
+
+/**
+ * i2c_smbus_xfer - execute SMBus protocol operations
+ * @adapter: Handle to I2C bus
+ * @addr: Address of SMBus slave on that bus
+ * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)
+ * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE
+ * @command: Byte interpreted by slave, for protocols which use such bytes
+ * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL
+ * @data: Data to be read or written
+ *
+ * This executes an SMBus protocol operation, and returns a negative
+ * errno code else zero on success.
+ */
+s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
+ char read_write, u8 command, int protocol,
+ union i2c_smbus_data *data)
+{
+ s32 res;
+
+ flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB;
+
+ res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write,
+ command, protocol, data);
+
+ return res;
+}
+EXPORT_SYMBOL(i2c_smbus_xfer);
diff --git a/drivers/led/led-triggers.c b/drivers/led/led-triggers.c
index 5eaf732764..c5484d59a5 100644
--- a/drivers/led/led-triggers.c
+++ b/drivers/led/led-triggers.c
@@ -124,7 +124,7 @@ int led_set_trigger(enum led_trigger trigger, struct led *led)
triggers[trigger].led = led;
- if (trigger == LED_TRIGGER_DEFAULT_ON)
+ if (led && trigger == LED_TRIGGER_DEFAULT_ON)
led_set(triggers[trigger].led, triggers[trigger].led->max_value);
return 0;
@@ -145,7 +145,7 @@ int led_get_trigger(enum led_trigger trigger)
return led_get_number(triggers[trigger].led);
}
-int trigger_init(void)
+static int trigger_init(void)
{
return poller_register(&trigger_poller);
}
diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c
index 59712b8119..b1d266f4d6 100644
--- a/drivers/mtd/nand/nand_omap_gpmc.c
+++ b/drivers/mtd/nand/nand_omap_gpmc.c
@@ -804,8 +804,8 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo,
offset - omap_oobinfo.eccbytes;
break;
case OMAP_ECC_BCH4_CODE_HW:
- oinfo->nand.ecc.bytes = 4 * 7;
- oinfo->nand.ecc.size = 4 * 512;
+ oinfo->nand.ecc.bytes = 7;
+ oinfo->nand.ecc.size = 512;
oinfo->nand.ecc.strength = BCH4_MAX_ERROR;
omap_oobinfo.oobfree->offset = offset;
omap_oobinfo.oobfree->length = minfo->oobsize -
@@ -815,8 +815,8 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo,
omap_oobinfo.eccpos[i] = i + offset;
break;
case OMAP_ECC_BCH8_CODE_HW:
- oinfo->nand.ecc.bytes = 4 * 13;
- oinfo->nand.ecc.size = 4 * 512;
+ oinfo->nand.ecc.bytes = 13;
+ oinfo->nand.ecc.size = 512;
oinfo->nand.ecc.strength = BCH8_MAX_ERROR;
omap_oobinfo.oobfree->offset = offset;
omap_oobinfo.oobfree->length = minfo->oobsize -
@@ -826,19 +826,13 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo,
omap_oobinfo.eccpos[i] = i + offset;
break;
case OMAP_ECC_BCH8_CODE_HW_ROMCODE:
- oinfo->nand.ecc.bytes = 4 * 13;
- oinfo->nand.ecc.size = 4 * 512;
+ oinfo->nand.ecc.bytes = 13 + 1;
+ oinfo->nand.ecc.size = 512;
oinfo->nand.ecc.strength = BCH8_MAX_ERROR;
nand->ecc.read_page = omap_gpmc_read_page_bch_rom_mode;
omap_oobinfo.oobfree->length = 0;
j = 0;
- for (i = 2; i < 15; i++)
- omap_oobinfo.eccpos[j++] = i;
- for (i = 16; i < 29; i++)
- omap_oobinfo.eccpos[j++] = i;
- for (i = 30; i < 43; i++)
- omap_oobinfo.eccpos[j++] = i;
- for (i = 44; i < 57; i++)
+ for (i = 2; i < 58; i++)
omap_oobinfo.eccpos[j++] = i;
break;
case OMAP_ECC_SOFT:
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
index ffce40a506..c99fcc8316 100644
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -174,6 +174,10 @@ config DRIVER_NET_TAP
bool "tap Ethernet driver"
depends on LINUX
+config DRIVER_NET_EFI_SNP
+ bool "EFI SNP ethernet driver"
+ depends on ARCH_EFI
+
config DRIVER_NET_TSE
depends on NIOS2
bool "Altera TSE ethernet driver"
diff --git a/drivers/net/Makefile b/drivers/net/Makefile
index 33bb5c8fa0..1b85778f9f 100644
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -26,3 +26,4 @@ obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o
obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o
obj-$(CONFIG_DRIVER_NET_TAP) += tap.o
obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o
+obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o
diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c
new file mode 100644
index 0000000000..5b96fbf462
--- /dev/null
+++ b/drivers/net/efi-snp.c
@@ -0,0 +1,296 @@
+/*
+ * efi-snp.c - Simple Network Protocol driver for EFI
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHANY 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 <driver.h>
+#include <malloc.h>
+#include <net.h>
+#include <init.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+struct efi_network_statistics {
+ uint64_t RxTotalFrames;
+ uint64_t RxGoodFrames;
+ uint64_t RxUndersizeFrames;
+ uint64_t RxOversizeFrames;
+ uint64_t RxDroppedFrames;
+ uint64_t RxUnicastFrames;
+ uint64_t RxBroadcastFrames;
+ uint64_t RxMulticastFrames;
+ uint64_t RxCrcErrorFrames;
+ uint64_t RxTotalBytes;
+ uint64_t TxTotalFrames;
+ uint64_t TxGoodFrames;
+ uint64_t TxUndersizeFrames;
+ uint64_t TxOversizeFrames;
+ uint64_t TxDroppedFrames;
+ uint64_t TxUnicastFrames;
+ uint64_t TxBroadcastFrames;
+ uint64_t TxMulticastFrames;
+ uint64_t TxCrcErrorFrames;
+ uint64_t TxTotalBytes;
+ uint64_t Collisions;
+ uint64_t UnsupportedProtocol;
+};
+
+enum efi_simple_network_state {
+ EfiSimpleNetworkStopped,
+ EfiSimpleNetworkStarted,
+ EfiSimpleNetworkInitialized,
+ EfiSimpleNetworkMaxState
+};
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01
+#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02
+#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08
+#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10
+
+#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01
+#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02
+#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04
+#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08
+
+#define MAX_MCAST_FILTER_CNT 16
+struct efi_simple_network_mode {
+ uint32_t State;
+ uint32_t HwAddressSize;
+ uint32_t MediaHeaderSize;
+ uint32_t MaxPacketSize;
+ uint32_t NvRamSize;
+ uint32_t NvRamAccessSize;
+ uint32_t ReceiveFilterMask;
+ uint32_t ReceiveFilterSetting;
+ uint32_t MaxMCastFilterCount;
+ uint32_t MCastFilterCount;
+ efi_mac_address MCastFilter[MAX_MCAST_FILTER_CNT];
+ efi_mac_address CurrentAddress;
+ efi_mac_address BroadcastAddress;
+ efi_mac_address PermanentAddress;
+ uint8_t IfType;
+ bool MacAddressChangeable;
+ bool MultipleTxSupported;
+ bool MediaPresentSupported;
+ bool MediaPresent;
+};
+
+#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION 0x00010000
+
+struct efi_simple_network {
+ uint64_t Revision;
+ efi_status_t (EFIAPI *start) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *stop) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *initialize) (struct efi_simple_network *This,
+ unsigned long ExtraRxBufferSize, unsigned long ExtraTxBufferSize);
+ efi_status_t (EFIAPI *reset) (struct efi_simple_network *This, bool ExtendedVerification);
+ efi_status_t (EFIAPI *shutdown) (struct efi_simple_network *This);
+ efi_status_t (EFIAPI *receive_filters) (struct efi_simple_network *This,
+ uint32_t Enable, uint32_t Disable, bool ResetMCastFilter,
+ unsigned long MCastFilterCnt, efi_mac_address *MCastFilter);
+ efi_status_t (EFIAPI *station_address) (struct efi_simple_network *This,
+ bool Reset, efi_mac_address *New);
+ efi_status_t (EFIAPI *statistics) (struct efi_simple_network *This,
+ bool Reset, unsigned long *StatisticsSize,
+ struct efi_network_statistics *StatisticsTable);
+ efi_status_t (EFIAPI *mcast_ip_to_mac) (struct efi_simple_network *This,
+ bool IPv6, efi_ip_address *IP, efi_mac_address *MAC);
+ efi_status_t (EFIAPI *nvdata) (struct efi_simple_network *This,
+ bool ReadWrite, unsigned long Offset, unsigned long BufferSize,
+ void *Buffer);
+ efi_status_t (EFIAPI *get_status) (struct efi_simple_network *This,
+ uint32_t *InterruptStatus, void **TxBuf);
+ efi_status_t (EFIAPI *transmit) (struct efi_simple_network *This,
+ unsigned long HeaderSize, unsigned long BufferSize, void *Buffer,
+ efi_mac_address *SrcAddr, efi_mac_address *DestAddr,
+ uint16_t *Protocol);
+ efi_status_t (EFIAPI *receive) (struct efi_simple_network *This,
+ unsigned long *HeaderSize, unsigned long *BufferSize, void *Buffer,
+ efi_mac_address *SrcAddr, efi_mac_address *DestAddr, uint16_t *Protocol);
+ void *WaitForPacket;
+ struct efi_simple_network_mode *Mode;
+};
+
+struct efi_snp_priv {
+ struct device_d *dev;
+ struct eth_device edev;
+ struct efi_simple_network *snp;
+};
+
+static inline struct efi_snp_priv *to_priv(struct eth_device *edev)
+{
+ return container_of(edev, struct efi_snp_priv, edev);
+}
+
+static int efi_snp_eth_send(struct eth_device *edev, void *packet, int length)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ efi_status_t efiret;
+ void *txbuf;
+ uint64_t start;
+
+ efiret = priv->snp->transmit(priv->snp, 0, length, packet, NULL, NULL, NULL);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to send: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ start = get_time_ns();
+
+ while (!is_timeout(start, SECOND)) {
+ uint32_t irq;
+ priv->snp->get_status(priv->snp, &irq, &txbuf);
+ if (txbuf)
+ return 0;
+ }
+
+ dev_err(priv->dev, "tx time out\n");
+
+ return -ETIMEDOUT;
+}
+
+static int efi_snp_eth_rx(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ long bufsize = PKTSIZE;
+ efi_status_t efiret;
+
+ efiret = priv->snp->receive(priv->snp, NULL, &bufsize, NetRxPackets[0], NULL, NULL, NULL);
+ if (efiret == EFI_NOT_READY)
+ return 0;
+
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to receive: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ net_receive(edev, NetRxPackets[0], bufsize);
+
+ return 0;
+}
+
+static int efi_snp_eth_open(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+ uint32_t mask;
+ efi_status_t efiret;
+
+ priv->snp->shutdown(priv->snp);
+ priv->snp->stop(priv->snp);
+ priv->snp->start(priv->snp);
+ efiret = priv->snp->initialize(priv->snp, 0, 0);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "Initialize failed with: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ efiret = priv->snp->station_address(priv->snp, false,
+ (efi_mac_address *)priv->snp->Mode->PermanentAddress.Addr );
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to set MAC address: %s\n",
+ efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST |
+ EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
+ efiret = priv->snp->receive_filters(priv->snp, mask, 0, 0, 0, 0);
+ if (EFI_ERROR(efiret)) {
+ dev_err(priv->dev, "failed to set receive filters: %s\n",
+ efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ return 0;
+}
+
+static void efi_snp_eth_halt(struct eth_device *edev)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+
+ priv->snp->stop(priv->snp);
+}
+
+static int efi_snp_get_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ struct efi_snp_priv *priv = to_priv(edev);
+
+ memcpy(adr, priv->snp->Mode->PermanentAddress.Addr, 6);
+
+ return 0;
+}
+
+static int efi_snp_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+{
+ return 0;
+}
+
+int efi_snp_probe(struct efi_device *efidev)
+{
+ struct eth_device *edev;
+ struct efi_snp_priv *priv;
+ int ret;
+
+ dev_dbg(&efidev->dev, "efi_snp_probe\n");
+
+ priv = xzalloc(sizeof(struct efi_snp_priv));
+ priv->snp = efidev->protocol;
+ priv->dev = &efidev->dev;
+
+ dev_dbg(&efidev->dev, "perm: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ priv->snp->Mode->PermanentAddress.Addr[0],
+ priv->snp->Mode->PermanentAddress.Addr[1],
+ priv->snp->Mode->PermanentAddress.Addr[2],
+ priv->snp->Mode->PermanentAddress.Addr[3],
+ priv->snp->Mode->PermanentAddress.Addr[4],
+ priv->snp->Mode->PermanentAddress.Addr[5]);
+ dev_dbg(&efidev->dev, "curr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+ priv->snp->Mode->CurrentAddress.Addr[0],
+ priv->snp->Mode->CurrentAddress.Addr[1],
+ priv->snp->Mode->CurrentAddress.Addr[2],
+ priv->snp->Mode->CurrentAddress.Addr[3],
+ priv->snp->Mode->CurrentAddress.Addr[4],
+ priv->snp->Mode->CurrentAddress.Addr[5]);
+
+ edev = &priv->edev;
+ edev->priv = priv;
+ edev->parent = &efidev->dev;
+
+ edev->open = efi_snp_eth_open;
+ edev->send = efi_snp_eth_send;
+ edev->recv = efi_snp_eth_rx;
+ edev->halt = efi_snp_eth_halt;
+ edev->get_ethaddr = efi_snp_get_ethaddr;
+ edev->set_ethaddr = efi_snp_set_ethaddr;
+
+ ret = eth_register(edev);
+
+ return ret;
+}
+
+static struct efi_driver efi_snp_driver = {
+ .driver = {
+ .name = "efi-snp",
+ },
+ .probe = efi_snp_probe,
+ .guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID,
+};
+device_efi_driver(efi_snp_driver);
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index 45f77a759f..81955063d7 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -4,7 +4,7 @@ config OFTREE
config OFTREE_MEM_GENERIC
depends on OFTREE
- depends on PPC || ARM
+ depends on PPC || ARM || ARCH_EFI
def_bool y
config DTC
@@ -27,6 +27,12 @@ config OF_GPIO
depends on OFDEVICE
def_bool y
+config OF_PCI
+ bool
+ depends on PCI
+ help
+ OpenFirmware PCI bus accessors
+
config OF_BAREBOX_DRIVERS
depends on OFDEVICE
depends on ENV_HANDLING
diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index c883e516c8..0dc2f8d63e 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,6 +1,7 @@
obj-y += address.o base.o fdt.o platform.o
obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o
obj-$(CONFIG_OF_GPIO) += of_gpio.o
+obj-$(CONFIG_OF_PCI) += of_pci.o
obj-y += partition.o
obj-y += of_net.o
obj-$(CONFIG_MTD) += of_mtd.o
diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c
new file mode 100644
index 0000000000..2d0fbd2e5f
--- /dev/null
+++ b/drivers/of/of_pci.c
@@ -0,0 +1,27 @@
+#include <common.h>
+#include <errno.h>
+#include <of.h>
+#include <of_pci.h>
+
+/**
+ * of_pci_get_devfn() - Get device and function numbers for a device node
+ * @np: device node
+ *
+ * Parses a standard 5-cell PCI resource and returns an 8-bit value that can
+ * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device
+ * and function numbers respectively. On error a negative error code is
+ * returned.
+ */
+int of_pci_get_devfn(struct device_node *np)
+{
+ unsigned int size;
+ const __be32 *reg;
+
+ reg = of_get_property(np, "reg", &size);
+
+ if (!reg || size < 5 * sizeof(__be32))
+ return -EINVAL;
+
+ return (be32_to_cpup(reg) >> 8) & 0xff;
+}
+EXPORT_SYMBOL_GPL(of_pci_get_devfn);
diff --git a/drivers/of/partition.c b/drivers/of/partition.c
index e2ddec564e..3dce84404f 100644
--- a/drivers/of/partition.c
+++ b/drivers/of/partition.c
@@ -21,6 +21,7 @@
#include <of.h>
#include <malloc.h>
#include <linux/mtd/mtd.h>
+#include <linux/err.h>
#include <nand.h>
struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
@@ -60,6 +61,9 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node)
filename = asprintf("%s.%s", cdev->name, partname);
new = devfs_add_partition(cdev->name, offset, size, flags, filename);
+ if (IS_ERR(new))
+ new = NULL;
+
if (new && new->dev)
new->dev->device_node = node;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 72e75cc079..c417cfdcd9 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -183,7 +183,8 @@ static struct device_d *of_platform_device_create(struct device_node *np,
dev->num_resources = num_reg;
of_device_make_bus_id(dev);
- debug("%s: register device %s, io=0x%08x\n", __func__, dev_name(dev),
+ debug("%s: register device %s, io=" PRINTF_CONVERSION_RESOURCE "\n",
+ __func__, dev_name(dev),
(num_reg) ? dev->resource[0].start : (-1));
ret = platform_device_register(dev);
diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig
index 9e4659270d..d17a151082 100644
--- a/drivers/pci/Kconfig
+++ b/drivers/pci/Kconfig
@@ -24,6 +24,12 @@ config PCI_DEBUG
When in doubt, say N.
+config PCI_MVEBU
+ bool "Marvell EBU PCIe driver"
+ depends on ARCH_MVEBU
+ select OF_PCI
+ select PCI
+
endmenu
endif
diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile
index edac1a53de..442353173c 100644
--- a/drivers/pci/Makefile
+++ b/drivers/pci/Makefile
@@ -6,3 +6,5 @@ obj-y += pci.o bus.o pci_iomap.o
ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG
CPPFLAGS += $(ccflags-y)
+
+obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o
diff --git a/drivers/pci/pci-mvebu-phy.c b/drivers/pci/pci-mvebu-phy.c
new file mode 100644
index 0000000000..55a1d39f62
--- /dev/null
+++ b/drivers/pci/pci-mvebu-phy.c
@@ -0,0 +1,208 @@
+/*
+ * SoC specific PCIe PHY setup for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * based on Marvell BSP code (C) Marvell International Ltd.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <of.h>
+#include <of_address.h>
+
+#include "pci-mvebu.h"
+
+static u32 mvebu_pcie_phy_indirect(void __iomem *phybase, u8 lane,
+ u8 off, u16 val, bool is_read)
+{
+ u32 reg = (lane << 24) | (off << 16) | val;
+
+ if (is_read)
+ reg |= BIT(31);
+ writel(reg, phybase);
+
+ return (is_read) ? readl(phybase) & 0xffff : 0;
+}
+
+static inline u32 mvebu_pcie_phy_read(void __iomem *phybase, u8 lane,
+ u8 off)
+{
+ return mvebu_pcie_phy_indirect(phybase, lane, off, 0, true);
+}
+
+static inline void mvebu_pcie_phy_write(void __iomem *phybase, u8 lane,
+ u8 off, u16 val)
+{
+ mvebu_pcie_phy_indirect(phybase, lane, off, val, false);
+}
+
+/* PCIe registers */
+#define ARMADA_370_XP_PCIE_LINK_CAPS 0x6c
+#define MAX_LINK_WIDTH_MASK MAX_LINK_WIDTH(0x3f)
+#define MAX_LINK_WIDTH(x) ((x) << 4)
+#define MAX_LINK_SPEED_MASK 0xf
+#define MAX_LINK_SPEED_5G0 0x2
+#define MAX_LINK_SPEED_2G5 0x1
+#define ARMADA_370_XP_PHY_OFFSET 0x1b00
+/* System Control registers */
+#define ARMADA_370_XP_SOC_CTRL 0x04
+#define PCIE1_QUADX1_EN BIT(8) /* Armada XP */
+#define PCIE0_QUADX1_EN BIT(7) /* Armada XP */
+#define PCIE0_EN BIT(0)
+#define ARMADA_370_XP_SERDES03_SEL 0x70
+#define ARMADA_370_XP_SERDES47_SEL 0x74
+#define SERDES(x, v) ((v) << ((x) * 0x4))
+#define SERDES_MASK(x) SERDES((x), 0xf)
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie)
+{
+ struct device_node *np = of_find_compatible_node(NULL, NULL,
+ "marvell,armada-370-xp-system-controller");
+ void __iomem *sysctrl = of_iomap(np, 0);
+ void __iomem *phybase = pcie->base + ARMADA_370_XP_PHY_OFFSET;
+ u32 reg;
+
+ if (!sysctrl)
+ return -ENODEV;
+
+ /* Enable PEX */
+ reg = readl(sysctrl + ARMADA_370_XP_SOC_CTRL);
+ reg |= PCIE0_EN << pcie->port;
+ writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL);
+
+ /* Set SERDES selector */
+ reg = readl(sysctrl + ARMADA_370_XP_SERDES03_SEL);
+ reg &= ~SERDES_MASK(pcie->port);
+ reg |= SERDES(pcie->port, 0x1);
+ writel(reg, sysctrl + ARMADA_370_XP_SERDES03_SEL);
+
+ /* BTS #232 - PCIe clock (undocumented) */
+ writel(0x00000077, sysctrl + 0x2f0);
+
+ /* Set x1 Link Capability */
+ reg = readl(pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS);
+ reg &= ~(MAX_LINK_WIDTH_MASK | MAX_LINK_SPEED_MASK);
+ reg |= MAX_LINK_WIDTH(0x1) | MAX_LINK_SPEED_5G0;
+ writel(reg, pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS);
+
+ /* PEX pipe configuration */
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xd0, 0x0100);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xd1, 0x3014);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc5, 0x011f);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x80, 0x1000);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x81, 0x0011);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x0f, 0x2a21);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x45, 0x00df);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x4f, 0x6219);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000);
+
+ reg = mvebu_pcie_phy_read(phybase, pcie->lane, 0x48) & ~0x4;
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, reg & 0xffff);
+
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024);
+
+ mdelay(15);
+
+ return 0;
+}
+
+/*
+ * MV78230: 2 PCIe units Gen2.0, one unit 1x4 or 4x1, one unit 1x1
+ * MV78260: 3 PCIe units Gen2.0, two units 1x4 or 4x1, one unit 1x1/1x4
+ * MV78460: 4 PCIe units Gen2.0, two units 1x4 or 4x1, two units 1x1/1x4
+ */
+#define ARMADA_XP_COMM_PHY_REFCLK_ALIGN 0xf8
+#define REFCLK_ALIGN(x) (0xf << ((x) * 0x4))
+int armada_xp_phy_setup(struct mvebu_pcie *pcie)
+{
+ struct device_node *np = of_find_compatible_node(NULL, NULL,
+ "marvell,armada-370-xp-system-controller");
+ void __iomem *sysctrl = of_iomap(np, 0);
+ void __iomem *phybase = pcie->base + ARMADA_370_XP_PHY_OFFSET;
+ u32 serdes_off = (pcie->port < 2) ? ARMADA_370_XP_SERDES03_SEL :
+ ARMADA_370_XP_SERDES47_SEL;
+ bool single_x4 = (pcie->lane_mask == 0xf);
+ u32 reg, mask;
+
+ if (!sysctrl)
+ return -ENODEV;
+
+ /* Prepare PEX */
+ reg = readl(sysctrl + ARMADA_370_XP_SOC_CTRL);
+ reg &= ~(PCIE0_EN << pcie->port);
+ writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL);
+
+ if (pcie->port < 2) {
+ mask = PCIE0_QUADX1_EN << pcie->port;
+ if (single_x4)
+ reg &= ~mask;
+ else
+ reg |= mask;
+ }
+ reg |= PCIE0_EN << pcie->port;
+ writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL);
+
+ /* Set SERDES selector */
+ reg = readl(sysctrl + serdes_off);
+ for (mask = pcie->lane_mask; mask;) {
+ u32 l = ffs(mask)-1;
+ u32 off = 4 * (pcie->port % 2);
+ reg &= ~SERDES_MASK(off + l);
+ reg |= SERDES(off + l, 0x1);
+ mask &= ~BIT(l);
+ }
+ reg &= ~SERDES_MASK(pcie->port % 2);
+ reg |= SERDES(pcie->port % 2, 0x1);
+ writel(reg, sysctrl + serdes_off);
+
+ /* Reference Clock Alignment for 1x4 */
+ reg = readl(sysctrl + ARMADA_XP_COMM_PHY_REFCLK_ALIGN);
+ if (single_x4)
+ reg |= REFCLK_ALIGN(pcie->port);
+ else
+ reg &= ~REFCLK_ALIGN(pcie->port);
+ writel(reg, sysctrl + ARMADA_XP_COMM_PHY_REFCLK_ALIGN);
+
+ /* Set x1/x4 Link Capability */
+ reg = readl(pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS);
+ reg &= ~(MAX_LINK_WIDTH_MASK | MAX_LINK_SPEED_MASK);
+ if (single_x4)
+ reg |= MAX_LINK_WIDTH(0x4);
+ else
+ reg |= MAX_LINK_WIDTH(0x1);
+ reg |= MAX_LINK_SPEED_5G0;
+ writel(reg, pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS);
+
+ /* PEX pipe configuration */
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025);
+ if (single_x4) {
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc2, 0x0200);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x0001);
+ } else {
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc2, 0x0000);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f);
+ }
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000);
+
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040);
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024);
+ if (single_x4)
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, 0x1080);
+ else
+ mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, 0x9080);
+
+ mdelay(15);
+
+ return 0;
+}
diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c
new file mode 100644
index 0000000000..45befbba20
--- /dev/null
+++ b/drivers/pci/pci-mvebu.c
@@ -0,0 +1,446 @@
+/*
+ * PCIe driver for Marvell MVEBU SoCs
+ *
+ * Based on Linux drivers/pci/host/pci-mvebu.c
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#include <common.h>
+#include <gpio.h>
+#include <init.h>
+#include <io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/mbus.h>
+#include <linux/pci_regs.h>
+#include <malloc.h>
+#include <of_address.h>
+#include <of_gpio.h>
+#include <of_pci.h>
+#include <sizes.h>
+
+#include "pci-mvebu.h"
+
+/* PCIe unit register offsets */
+#define PCIE_DEV_ID_OFF 0x0000
+#define PCIE_CMD_OFF 0x0004
+#define PCIE_DEV_REV_OFF 0x0008
+#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3))
+#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3))
+#define PCIE_HEADER_LOG_4_OFF 0x0128
+#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4))
+#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4))
+#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4))
+#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4))
+#define PCIE_WIN5_CTRL_OFF 0x1880
+#define PCIE_WIN5_BASE_OFF 0x1884
+#define PCIE_WIN5_REMAP_OFF 0x188c
+#define PCIE_CONF_ADDR_OFF 0x18f8
+#define PCIE_CONF_ADDR_EN BIT(31)
+#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc))
+#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16)
+#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11)
+#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8)
+#define PCIE_CONF_ADDR(bus, devfn, where) \
+ (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | \
+ PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \
+ PCIE_CONF_ADDR_EN)
+#define PCIE_CONF_DATA_OFF 0x18fc
+#define PCIE_MASK_OFF 0x1910
+#define PCIE_MASK_ENABLE_INTS (0xf << 24)
+#define PCIE_CTRL_OFF 0x1a00
+#define PCIE_CTRL_X1_MODE BIT(0)
+#define PCIE_STAT_OFF 0x1a04
+#define PCIE_STAT_BUS (0xff << 8)
+#define PCIE_STAT_DEV (0x1f << 16)
+#define PCIE_STAT_LINK_DOWN BIT(0)
+#define PCIE_DEBUG_CTRL 0x1a60
+#define PCIE_DEBUG_SOFT_RESET BIT(20)
+
+#define to_pcie(_hc) container_of(_hc, struct mvebu_pcie, pci)
+
+/*
+ * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped
+ * into SoCs address space. Each controller will map 32M of MEM
+ * and 64K of I/O space when registered.
+ */
+static void __iomem *mvebu_pcie_membase = IOMEM(0xe0000000);
+static void __iomem *mvebu_pcie_iobase = IOMEM(0xffe00000);
+
+static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie)
+{
+ return !(readl(pcie->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN);
+}
+
+static void mvebu_pcie_set_local_bus_nr(struct pci_controller *host, int busno)
+{
+ struct mvebu_pcie *pcie = to_pcie(host);
+ u32 stat;
+
+ stat = readl(pcie->base + PCIE_STAT_OFF);
+ stat &= ~PCIE_STAT_BUS;
+ stat |= busno << 8;
+ writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno)
+{
+ u32 stat;
+
+ stat = readl(pcie->base + PCIE_STAT_OFF);
+ stat &= ~PCIE_STAT_DEV;
+ stat |= devno << 16;
+ writel(stat, pcie->base + PCIE_STAT_OFF);
+}
+
+static int mvebu_pcie_indirect_rd_conf(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val)
+{
+ struct mvebu_pcie *pcie = to_pcie(bus->host);
+
+ /* Skip all requests not directed to device behind bridge */
+ if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie)) {
+ *val = 0xffffffff;
+ return PCIBIOS_DEVICE_NOT_FOUND;
+ }
+
+ writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+ pcie->base + PCIE_CONF_ADDR_OFF);
+
+ *val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+ if (size == 1)
+ *val = (*val >> (8 * (where & 3))) & 0xff;
+ else if (size == 2)
+ *val = (*val >> (8 * (where & 3))) & 0xffff;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_indirect_wr_conf(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 val)
+{
+ struct mvebu_pcie *pcie = to_pcie(bus->host);
+ u32 _val, shift = 8 * (where & 3);
+
+ /* Skip all requests not directed to device behind bridge */
+ if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ writel(PCIE_CONF_ADDR(bus->number, devfn, where),
+ pcie->base + PCIE_CONF_ADDR_OFF);
+ _val = readl(pcie->base + PCIE_CONF_DATA_OFF);
+
+ if (size == 4)
+ _val = val;
+ else if (size == 2)
+ _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift);
+ else if (size == 1)
+ _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift);
+ else
+ return PCIBIOS_BAD_REGISTER_NUMBER;
+
+ writel(_val, pcie->base + PCIE_CONF_DATA_OFF);
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+static int mvebu_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr)
+{
+ struct mvebu_pcie *pcie = to_pcie(bus->host);
+
+ return (int)pcie->membase + (res_addr & (resource_size(&pcie->mem)-1));
+}
+
+static struct pci_ops mvebu_pcie_indirect_ops = {
+ .read = mvebu_pcie_indirect_rd_conf,
+ .write = mvebu_pcie_indirect_wr_conf,
+ .res_start = mvebu_pcie_res_start,
+};
+
+/*
+ * Setup PCIE BARs and Address Decode Wins:
+ * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks
+ * WIN[0-3] -> DRAM bank[0-3]
+ */
+static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie)
+{
+ const struct mbus_dram_target_info *dram = mvebu_mbus_dram_info();
+ u32 size;
+ int i;
+
+ /* First, disable and clear BARs and windows. */
+ for (i = 1; i < 3; i++) {
+ writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i));
+ writel(0, pcie->base + PCIE_BAR_LO_OFF(i));
+ writel(0, pcie->base + PCIE_BAR_HI_OFF(i));
+ }
+
+ for (i = 0; i < 5; i++) {
+ writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i));
+ writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i));
+ writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+ }
+
+ writel(0, pcie->base + PCIE_WIN5_CTRL_OFF);
+ writel(0, pcie->base + PCIE_WIN5_BASE_OFF);
+ writel(0, pcie->base + PCIE_WIN5_REMAP_OFF);
+
+ /* Setup windows for DDR banks. Count total DDR size on the fly. */
+ size = 0;
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ writel(cs->base & 0xffff0000,
+ pcie->base + PCIE_WIN04_BASE_OFF(i));
+ writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i));
+ writel(((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ pcie->base + PCIE_WIN04_CTRL_OFF(i));
+
+ size += cs->size;
+ }
+
+ /* Round up 'size' to the nearest power of two. */
+ if ((size & (size - 1)) != 0)
+ size = 1 << fls(size);
+
+ /* Setup BAR[1] to all DRAM banks. */
+ writel(dram->cs[0].base, pcie->base + PCIE_BAR_LO_OFF(1));
+ writel(0, pcie->base + PCIE_BAR_HI_OFF(1));
+ writel(((size - 1) & 0xffff0000) | 1,
+ pcie->base + PCIE_BAR_CTRL_OFF(1));
+}
+
+#define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03)
+#define DT_TYPE_IO 0x1
+#define DT_TYPE_MEM32 0x2
+#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF)
+#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF)
+
+static int mvebu_get_target_attr(struct device_node *np, int devfn,
+ unsigned long type, unsigned int *target, unsigned int *attr)
+{
+ const int na = 3, ns = 2;
+ const __be32 *range;
+ int rlen, nranges, rangesz, pna, i;
+
+ *target = -1;
+ *attr = -1;
+
+ range = of_get_property(np, "ranges", &rlen);
+ if (!range)
+ return -EINVAL;
+
+ pna = of_n_addr_cells(np);
+ rangesz = pna + na + ns;
+ nranges = rlen / sizeof(__be32) / rangesz;
+
+ for (i = 0; i < nranges; i++) {
+ u32 flags = of_read_number(range, 1);
+ u32 slot = of_read_number(range + 1, 1);
+ u64 cpuaddr = of_read_number(range + na, pna);
+ unsigned long rtype;
+
+ if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO)
+ rtype = IORESOURCE_IO;
+ else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32)
+ rtype = IORESOURCE_MEM;
+
+ if (slot == PCI_SLOT(devfn) && type == rtype) {
+ *target = DT_CPUADDR_TO_TARGET(cpuaddr);
+ *attr = DT_CPUADDR_TO_ATTR(cpuaddr);
+ return 0;
+ }
+
+ range += rangesz;
+ }
+
+ return -ENOENT;
+}
+
+static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev,
+ struct device_node *np)
+{
+ struct mvebu_pcie *pcie;
+ struct clk *clk;
+ enum of_gpio_flags flags;
+ struct property *prop;
+ const __be32 *p;
+ int reset_gpio;
+ u32 u, port, lane, lane_mask, devfn;
+ int mem_target, mem_attr;
+ int io_target, io_attr;
+ int ret;
+
+ if (of_property_read_u32(np, "marvell,pcie-port", &port)) {
+ dev_err(dev, "missing pcie-port property\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ lane_mask = 0;
+ of_property_for_each_u32(np, "marvell,pcie-lane", prop, p, u)
+ lane_mask |= BIT(u);
+ lane = ffs(lane_mask)-1;
+
+ devfn = of_pci_get_devfn(np);
+ if (devfn < 0) {
+ dev_err(dev, "unable to parse devfn\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ if (mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_MEM,
+ &mem_target, &mem_attr)) {
+ dev_err(dev, "unable to get target/attr for mem window\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ /* I/O windows are optional */
+ mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_IO,
+ &io_target, &io_attr);
+
+ reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags);
+ if (gpio_is_valid(reset_gpio)) {
+ int reset_active_low = flags & OF_GPIO_ACTIVE_LOW;
+ char *reset_name = asprintf("pcie%d.%d-reset", port, lane);
+ u32 reset_udelay = 20000;
+
+ of_property_read_u32(np, "reset-delay-us", &reset_udelay);
+
+ ret = gpio_request_one(reset_gpio, GPIOF_DIR_OUT, reset_name);
+ if (ret)
+ return ERR_PTR(ret);
+
+ /* Ensure a full reset cycle*/
+ gpio_set_value(reset_gpio, 1 ^ reset_active_low);
+ udelay(reset_udelay);
+ gpio_set_value(reset_gpio, 0 ^ reset_active_low);
+ udelay(reset_udelay);
+ }
+
+ pcie = xzalloc(sizeof(*pcie));
+ pcie->port = port;
+ pcie->lane = lane;
+ pcie->lane_mask = lane_mask;
+ pcie->name = asprintf("pcie%d.%d", port, lane);
+ pcie->devfn = devfn;
+
+ pcie->base = of_iomap(np, 0);
+ if (!pcie->base) {
+ dev_err(dev, "PCIe%d.%d unable to map registers\n", port, lane);
+ free(pcie);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pcie->membase = mvebu_pcie_membase;
+ pcie->mem.start = (u32)mvebu_pcie_membase;
+ pcie->mem.end = pcie->mem.start + SZ_32M - 1;
+ if (mvebu_mbus_add_window_remap_by_id(mem_target, mem_attr,
+ (resource_size_t)pcie->membase, resource_size(&pcie->mem),
+ (u32)pcie->mem.start)) {
+ dev_err(dev, "PCIe%d.%d unable to add mbus window for mem at %08x+%08x",
+ port, lane, (u32)pcie->mem.start, resource_size(&pcie->mem));
+
+ free(pcie);
+ return ERR_PTR(-EBUSY);
+ }
+ mvebu_pcie_membase += SZ_32M;
+
+ if (io_target >= 0 && io_attr >= 0) {
+ pcie->iobase = mvebu_pcie_iobase;
+ pcie->io.start = (u32)mvebu_pcie_iobase;
+ pcie->io.end = pcie->io.start + SZ_64K - 1;
+
+ mvebu_mbus_add_window_remap_by_id(io_target, io_attr,
+ (resource_size_t)pcie->iobase, resource_size(&pcie->io),
+ (u32)pcie->io.start);
+ mvebu_pcie_iobase += SZ_64K;
+ }
+
+ clk = of_clk_get(np, 0);
+ if (!IS_ERR(clk))
+ clk_enable(clk);
+
+ pcie->pci.set_busno = mvebu_pcie_set_local_bus_nr;
+ pcie->pci.pci_ops = &mvebu_pcie_indirect_ops;
+ pcie->pci.mem_resource = &pcie->mem;
+ pcie->pci.io_resource = &pcie->io;
+
+ return pcie;
+}
+
+static struct mvebu_pcie_ops __maybe_unused armada_370_ops = {
+ .phy_setup = armada_370_phy_setup,
+};
+
+static struct mvebu_pcie_ops __maybe_unused armada_xp_ops = {
+ .phy_setup = armada_xp_phy_setup,
+};
+
+static struct of_device_id mvebu_pcie_dt_ids[] = {
+#if defined(CONFIG_ARCH_ARMADA_XP)
+ { .compatible = "marvell,armada-xp-pcie", .data = (u32)&armada_xp_ops, },
+#endif
+#if defined(CONFIG_ARCH_ARMADA_370)
+ { .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, },
+#endif
+#if defined(CONFIG_ARCH_DOVE)
+ { .compatible = "marvell,dove-pcie", },
+#endif
+#if defined(CONFIG_ARCH_KIRKWOOD)
+ { .compatible = "marvell,kirkwood-pcie", },
+#endif
+ { },
+};
+
+static int mvebu_pcie_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ const struct of_device_id *match = of_match_node(mvebu_pcie_dt_ids, np);
+ struct mvebu_pcie_ops *ops = (struct mvebu_pcie_ops *)match->data;
+ struct device_node *pnp;
+
+ for_each_child_of_node(np, pnp) {
+ struct mvebu_pcie *pcie;
+ u32 reg;
+
+ if (!of_device_is_available(pnp))
+ continue;
+
+ pcie = mvebu_pcie_port_probe(dev, pnp);
+ if (IS_ERR(pcie))
+ continue;
+
+ if (ops && ops->phy_setup)
+ ops->phy_setup(pcie);
+
+ mvebu_pcie_set_local_dev_nr(pcie, 0);
+ mvebu_pcie_setup_wins(pcie);
+
+ /* Master + slave enable. */
+ reg = readl(pcie->base + PCIE_CMD_OFF);
+ reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+ reg |= PCI_COMMAND_MASTER;
+ writel(reg, pcie->base + PCIE_CMD_OFF);
+
+ /* Disable interrupts */
+ reg = readl(pcie->base + PCIE_MASK_OFF);
+ reg &= ~PCIE_MASK_ENABLE_INTS;
+ writel(reg, pcie->base + PCIE_MASK_OFF);
+
+ register_pci_controller(&pcie->pci);
+ }
+
+ return 0;
+}
+
+static struct driver_d mvebu_pcie_driver = {
+ .name = "mvebu-pcie",
+ .probe = mvebu_pcie_probe,
+ .of_compatible = mvebu_pcie_dt_ids,
+};
+device_platform_driver(mvebu_pcie_driver);
diff --git a/drivers/pci/pci-mvebu.h b/drivers/pci/pci-mvebu.h
new file mode 100644
index 0000000000..8ced9fefca
--- /dev/null
+++ b/drivers/pci/pci-mvebu.h
@@ -0,0 +1,37 @@
+/*
+ * PCIe include for Marvell MVEBU SoCs
+ *
+ * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __MVEBU_PCI_H
+#define __MVEBU_PCI_H
+
+#include <linux/pci.h>
+
+struct mvebu_pcie {
+ struct pci_controller pci;
+ char *name;
+ void __iomem *base;
+ void __iomem *membase;
+ struct resource mem;
+ void __iomem *iobase;
+ struct resource io;
+ u32 port;
+ u32 lane;
+ u32 lane_mask;
+ int devfn;
+};
+
+struct mvebu_pcie_ops {
+ int (*phy_setup)(struct mvebu_pcie *pcie);
+};
+
+int armada_370_phy_setup(struct mvebu_pcie *pcie);
+int armada_xp_phy_setup(struct mvebu_pcie *pcie);
+
+#endif
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3d88b0ff5f..a1b7680254 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -11,6 +11,7 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head;
LIST_HEAD(pci_root_buses);
EXPORT_SYMBOL(pci_root_buses);
+static u8 bus_index;
static struct pci_bus *pci_alloc_bus(void)
{
@@ -36,10 +37,14 @@ void register_pci_controller(struct pci_controller *hose)
bus = pci_alloc_bus();
hose->bus = bus;
+ bus->host = hose;
bus->ops = hose->pci_ops;
bus->resource[0] = hose->mem_resource;
bus->resource[1] = hose->io_resource;
+ bus->number = bus_index++;
+ if (hose->set_busno)
+ hose->set_busno(hose, bus->number);
pci_scan_bus(bus);
list_add_tail(&bus->node, &pci_root_buses);
@@ -186,14 +191,15 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device);
- list_add_tail(&dev->bus_list, &bus->devices);
- pci_register_device(dev);
-
if (class == PCI_CLASS_BRIDGE_HOST) {
DBG("PCI: skip pci host bridge\n");
continue;
}
+ pci_read_config_byte(dev, PCI_COMMAND, &cmd);
+ pci_write_config_byte(dev, PCI_COMMAND,
+ cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY));
+
for (bar = 0; bar < 6; bar++) {
resource_size_t last_addr;
@@ -211,20 +217,34 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
size = -(mask & 0xfffffffe);
DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io);
+ dev->resource[bar].flags = IORESOURCE_IO;
last_addr = last_io;
last_io += size;
-
} else { /* MEM */
size = -(mask & 0xfffffff0);
DBG(" PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem);
+ dev->resource[bar].flags = IORESOURCE_MEM;
last_addr = last_mem;
last_mem += size;
+
+ if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+ PCI_BASE_ADDRESS_MEM_TYPE_64) {
+ dev->resource[bar].flags |= IORESOURCE_MEM_64;
+ pci_write_config_dword(dev,
+ PCI_BASE_ADDRESS_1 + bar * 4, 0);
+ }
}
dev->resource[bar].start = last_addr;
dev->resource[bar].end = last_addr + size - 1;
+ if (dev->resource[bar].flags & IORESOURCE_MEM_64)
+ bar++;
}
+
+ pci_write_config_byte(dev, PCI_COMMAND, cmd);
+ list_add_tail(&dev->bus_list, &bus->devices);
+ pci_register_device(dev);
}
/*
diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig
index f5cf60804c..be154ed437 100644
--- a/drivers/pinctrl/mvebu/Kconfig
+++ b/drivers/pinctrl/mvebu/Kconfig
@@ -1,3 +1,11 @@
+config PINCTRL_ARMADA_370
+ bool
+ select PINCTRL
+
+config PINCTRL_ARMADA_XP
+ bool
+ select PINCTRL
+
config PINCTRL_DOVE
bool
select PINCTRL
diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile
index 05f320d5a3..6255a5f56d 100644
--- a/drivers/pinctrl/mvebu/Makefile
+++ b/drivers/pinctrl/mvebu/Makefile
@@ -1,3 +1,5 @@
obj-y += common.o
+obj-$(CONFIG_ARCH_ARMADA_370) += armada-370.o
+obj-$(CONFIG_ARCH_ARMADA_XP) += armada-xp.o
obj-$(CONFIG_ARCH_DOVE) += dove.o
obj-$(CONFIG_ARCH_KIRKWOOD) += kirkwood.o
diff --git a/drivers/pinctrl/mvebu/armada-370.c b/drivers/pinctrl/mvebu/armada-370.c
new file mode 100644
index 0000000000..4778358fad
--- /dev/null
+++ b/drivers/pinctrl/mvebu/armada-370.c
@@ -0,0 +1,416 @@
+/*
+ * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <malloc.h>
+#include <of.h>
+#include <of_address.h>
+#include <sizes.h>
+
+#include "common.h"
+
+static void __iomem *mpp_base;
+
+static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+ return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+ return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = {
+ MPP_MODE(0, "mpp0", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "uart0", "rxd")),
+ MPP_MODE(1, "mpp1", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "uart0", "txd")),
+ MPP_MODE(2, "mpp2", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "i2c0", "sck"),
+ MPP_FUNCTION(0x2, "uart0", "txd")),
+ MPP_MODE(3, "mpp3", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "i2c0", "sda"),
+ MPP_FUNCTION(0x2, "uart0", "rxd")),
+ MPP_MODE(4, "mpp4", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "cpu_pd", "vdd")),
+ MPP_MODE(5, "mpp5", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txclko"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x4, "spi1", "clk"),
+ MPP_FUNCTION(0x5, "audio", "mclk")),
+ MPP_MODE(6, "mpp6", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd0"),
+ MPP_FUNCTION(0x2, "sata0", "prsnt"),
+ MPP_FUNCTION(0x4, "tdm", "rst"),
+ MPP_FUNCTION(0x5, "audio", "sdo")),
+ MPP_MODE(7, "mpp7", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd1"),
+ MPP_FUNCTION(0x4, "tdm", "tdx"),
+ MPP_FUNCTION(0x5, "audio", "lrclk")),
+ MPP_MODE(8, "mpp8", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd2"),
+ MPP_FUNCTION(0x2, "uart0", "rts"),
+ MPP_FUNCTION(0x4, "tdm", "drx"),
+ MPP_FUNCTION(0x5, "audio", "bclk")),
+ MPP_MODE(9, "mpp9", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd3"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x3, "sd0", "clk"),
+ MPP_FUNCTION(0x5, "audio", "spdifo")),
+ MPP_MODE(10, "mpp10", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txctl"),
+ MPP_FUNCTION(0x2, "uart0", "cts"),
+ MPP_FUNCTION(0x4, "tdm", "fsync"),
+ MPP_FUNCTION(0x5, "audio", "sdi")),
+ MPP_MODE(11, "mpp11", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd0"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "sd0", "cmd"),
+ MPP_FUNCTION(0x4, "spi0", "cs1"),
+ MPP_FUNCTION(0x5, "sata1", "prsnt"),
+ MPP_FUNCTION(0x6, "spi1", "cs1")),
+ MPP_MODE(12, "mpp12", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd1"),
+ MPP_FUNCTION(0x2, "i2c1", "sda"),
+ MPP_FUNCTION(0x3, "sd0", "d0"),
+ MPP_FUNCTION(0x4, "spi1", "cs0"),
+ MPP_FUNCTION(0x5, "audio", "spdifi")),
+ MPP_MODE(13, "mpp13", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd2"),
+ MPP_FUNCTION(0x2, "i2c1", "sck"),
+ MPP_FUNCTION(0x3, "sd0", "d1"),
+ MPP_FUNCTION(0x4, "tdm", "pclk"),
+ MPP_FUNCTION(0x5, "audio", "rmclk")),
+ MPP_MODE(14, "mpp14", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd3"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x3, "sd0", "d2"),
+ MPP_FUNCTION(0x4, "spi1", "mosi"),
+ MPP_FUNCTION(0x5, "spi0", "cs2")),
+ MPP_MODE(15, "mpp15", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxctl"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+ MPP_FUNCTION(0x3, "sd0", "d3"),
+ MPP_FUNCTION(0x4, "spi1", "miso"),
+ MPP_FUNCTION(0x5, "spi0", "cs3")),
+ MPP_MODE(16, "mpp16", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxclk"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x4, "tdm", "int"),
+ MPP_FUNCTION(0x5, "audio", "extclk")),
+ MPP_MODE(17, "mpp17", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge", "mdc")),
+ MPP_MODE(18, "mpp18", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge", "mdio")),
+ MPP_MODE(19, "mpp19", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txclk"),
+ MPP_FUNCTION(0x2, "ge1", "txclkout"),
+ MPP_FUNCTION(0x4, "tdm", "pclk")),
+ MPP_MODE(20, "mpp20", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd4"),
+ MPP_FUNCTION(0x2, "ge1", "txd0")),
+ MPP_MODE(21, "mpp21", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd5"),
+ MPP_FUNCTION(0x2, "ge1", "txd1"),
+ MPP_FUNCTION(0x4, "uart1", "txd")),
+ MPP_MODE(22, "mpp22", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd6"),
+ MPP_FUNCTION(0x2, "ge1", "txd2"),
+ MPP_FUNCTION(0x4, "uart0", "rts")),
+ MPP_MODE(23, "mpp23", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "ge0", "txd7"),
+ MPP_FUNCTION(0x2, "ge1", "txd3"),
+ MPP_FUNCTION(0x4, "spi1", "mosi")),
+ MPP_MODE(24, "mpp24", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "col"),
+ MPP_FUNCTION(0x2, "ge1", "txctl"),
+ MPP_FUNCTION(0x4, "spi1", "cs0")),
+ MPP_MODE(25, "mpp25", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxerr"),
+ MPP_FUNCTION(0x2, "ge1", "rxd0"),
+ MPP_FUNCTION(0x4, "uart1", "rxd")),
+ MPP_MODE(26, "mpp26", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "crs"),
+ MPP_FUNCTION(0x2, "ge1", "rxd1"),
+ MPP_FUNCTION(0x4, "spi1", "miso")),
+ MPP_MODE(27, "mpp27", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd4"),
+ MPP_FUNCTION(0x2, "ge1", "rxd2"),
+ MPP_FUNCTION(0x4, "uart0", "cts")),
+ MPP_MODE(28, "mpp28", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd5"),
+ MPP_FUNCTION(0x2, "ge1", "rxd3")),
+ MPP_MODE(29, "mpp29", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd6"),
+ MPP_FUNCTION(0x2, "ge1", "rxctl"),
+ MPP_FUNCTION(0x4, "i2c1", "sda")),
+ MPP_MODE(30, "mpp30", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "ge0", "rxd7"),
+ MPP_FUNCTION(0x2, "ge1", "rxclk"),
+ MPP_FUNCTION(0x4, "i2c1", "sck")),
+ MPP_MODE(31, "mpp31", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x3, "tclk", NULL),
+ MPP_FUNCTION(0x4, "ge0", "txerr")),
+ MPP_MODE(32, "mpp32", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "cs0")),
+ MPP_MODE(33, "mpp33", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "bootcs"),
+ MPP_FUNCTION(0x2, "spi0", "cs0")),
+ MPP_MODE(34, "mpp34", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "wen0"),
+ MPP_FUNCTION(0x2, "spi0", "mosi")),
+ MPP_MODE(35, "mpp35", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "oen"),
+ MPP_FUNCTION(0x2, "spi0", "sck")),
+ MPP_MODE(36, "mpp36", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "a1"),
+ MPP_FUNCTION(0x2, "spi0", "miso")),
+ MPP_MODE(37, "mpp37", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "a0"),
+ MPP_FUNCTION(0x2, "sata0", "prsnt")),
+ MPP_MODE(38, "mpp38", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ready"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "uart0", "cts")),
+ MPP_MODE(39, "mpp39", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad0"),
+ MPP_FUNCTION(0x2, "audio", "spdifo")),
+ MPP_MODE(40, "mpp40", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad1"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "uart0", "rts")),
+ MPP_MODE(41, "mpp41", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad2"),
+ MPP_FUNCTION(0x2, "uart1", "rxd")),
+ MPP_MODE(42, "mpp42", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad3"),
+ MPP_FUNCTION(0x2, "uart1", "txd")),
+ MPP_MODE(43, "mpp43", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad4"),
+ MPP_FUNCTION(0x2, "audio", "bclk")),
+ MPP_MODE(44, "mpp44", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad5"),
+ MPP_FUNCTION(0x2, "audio", "mclk")),
+ MPP_MODE(45, "mpp45", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad6"),
+ MPP_FUNCTION(0x2, "audio", "lrclk")),
+ MPP_MODE(46, "mpp46", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad7"),
+ MPP_FUNCTION(0x2, "audio", "sdo")),
+ MPP_MODE(47, "mpp47", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad8"),
+ MPP_FUNCTION(0x3, "sd0", "clk"),
+ MPP_FUNCTION(0x5, "audio", "spdifo")),
+ MPP_MODE(48, "mpp48", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad9"),
+ MPP_FUNCTION(0x2, "uart0", "rts"),
+ MPP_FUNCTION(0x3, "sd0", "cmd"),
+ MPP_FUNCTION(0x4, "sata1", "prsnt"),
+ MPP_FUNCTION(0x5, "spi0", "cs1")),
+ MPP_MODE(49, "mpp49", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad10"),
+ MPP_FUNCTION(0x2, "pcie", "clkreq1"),
+ MPP_FUNCTION(0x3, "sd0", "d0"),
+ MPP_FUNCTION(0x4, "spi1", "cs0"),
+ MPP_FUNCTION(0x5, "audio", "spdifi")),
+ MPP_MODE(50, "mpp50", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad11"),
+ MPP_FUNCTION(0x2, "uart0", "cts"),
+ MPP_FUNCTION(0x3, "sd0", "d1"),
+ MPP_FUNCTION(0x4, "spi1", "miso"),
+ MPP_FUNCTION(0x5, "audio", "rmclk")),
+ MPP_MODE(51, "mpp51", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad12"),
+ MPP_FUNCTION(0x2, "i2c1", "sda"),
+ MPP_FUNCTION(0x3, "sd0", "d2"),
+ MPP_FUNCTION(0x4, "spi1", "mosi")),
+ MPP_MODE(52, "mpp52", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad13"),
+ MPP_FUNCTION(0x2, "i2c1", "sck"),
+ MPP_FUNCTION(0x3, "sd0", "d3"),
+ MPP_FUNCTION(0x4, "spi1", "sck")),
+ MPP_MODE(53, "mpp53", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad14"),
+ MPP_FUNCTION(0x2, "sd0", "clk"),
+ MPP_FUNCTION(0x3, "tdm", "pclk"),
+ MPP_FUNCTION(0x4, "spi0", "cs2"),
+ MPP_FUNCTION(0x5, "pcie", "clkreq1")),
+ MPP_MODE(54, "mpp54", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ad15"),
+ MPP_FUNCTION(0x3, "tdm", "dtx")),
+ MPP_MODE(55, "mpp55", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs1"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x3, "tdm", "rst"),
+ MPP_FUNCTION(0x4, "sata1", "prsnt"),
+ MPP_FUNCTION(0x5, "sata0", "prsnt")),
+ MPP_MODE(56, "mpp56", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs2"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "uart0", "cts"),
+ MPP_FUNCTION(0x4, "spi0", "cs3"),
+ MPP_FUNCTION(0x5, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x6, "spi1", "cs1")),
+ MPP_MODE(57, "mpp57", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs3"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "tdm", "fsync"),
+ MPP_FUNCTION(0x4, "sata0", "prsnt"),
+ MPP_FUNCTION(0x5, "audio", "sdo")),
+ MPP_MODE(58, "mpp58", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "cs0"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "tdm", "int"),
+ MPP_FUNCTION(0x5, "audio", "extclk"),
+ MPP_FUNCTION(0x6, "uart0", "rts")),
+ MPP_MODE(59, "mpp59", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "ale0"),
+ MPP_FUNCTION(0x2, "uart1", "rts"),
+ MPP_FUNCTION(0x3, "uart0", "rts"),
+ MPP_FUNCTION(0x5, "audio", "bclk")),
+ MPP_MODE(60, "mpp60", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "ale1"),
+ MPP_FUNCTION(0x2, "uart1", "rxd"),
+ MPP_FUNCTION(0x3, "sata0", "prsnt"),
+ MPP_FUNCTION(0x4, "pcie", "rst-out"),
+ MPP_FUNCTION(0x5, "audio", "sdi")),
+ MPP_MODE(61, "mpp61", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "dev", "wen1"),
+ MPP_FUNCTION(0x2, "uart1", "txd"),
+ MPP_FUNCTION(0x5, "audio", "rclk")),
+ MPP_MODE(62, "mpp62", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "dev", "a2"),
+ MPP_FUNCTION(0x2, "uart1", "cts"),
+ MPP_FUNCTION(0x3, "tdm", "drx"),
+ MPP_FUNCTION(0x4, "pcie", "clkreq0"),
+ MPP_FUNCTION(0x5, "audio", "mclk"),
+ MPP_FUNCTION(0x6, "uart0", "cts")),
+ MPP_MODE(63, "mpp63", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpo", NULL),
+ MPP_FUNCTION(0x1, "spi0", "sck"),
+ MPP_FUNCTION(0x2, "tclk", NULL)),
+ MPP_MODE(64, "mpp64", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "miso"),
+ MPP_FUNCTION(0x2, "spi0-1", "cs1")),
+ MPP_MODE(65, "mpp65", armada_370_mpp_ctrl,
+ MPP_FUNCTION(0x0, "gpio", NULL),
+ MPP_FUNCTION(0x1, "spi0", "mosi"),
+ MPP_FUNCTION(0x2, "spi0-1", "cs2")),
+};
+
+static struct mvebu_pinctrl_soc_info mv88f6710_pinctrl_info = {
+ .modes = mv88f6710_mpp_modes,
+ .nmodes = ARRAY_SIZE(mv88f6710_mpp_modes),
+ .variant = 0,
+};
+
+static struct of_device_id armada_370_pinctrl_of_match[] = {
+ {
+ .compatible = "marvell,mv88f6710-pinctrl",
+ .data = (u32)&mv88f6710_pinctrl_info,
+ },
+ { },
+};
+
+static int armada_370_pinctrl_probe(struct device_d *dev)
+{
+ const struct of_device_id *match =
+ of_match_node(armada_370_pinctrl_of_match, dev->device_node);
+ struct mvebu_pinctrl_soc_info *soc =
+ (struct mvebu_pinctrl_soc_info *)match->data;
+
+ mpp_base = dev_request_mem_region(dev, 0);
+ if (!mpp_base)
+ return -EBUSY;
+
+ return mvebu_pinctrl_probe(dev, soc);
+}
+
+static struct driver_d armada_370_pinctrl_driver = {
+ .name = "pinctrl-armada-370",
+ .probe = armada_370_pinctrl_probe,
+ .of_compatible = armada_370_pinctrl_of_match,
+};
+
+static int armada_370_pinctrl_init(void)
+{
+ return platform_driver_register(&armada_370_pinctrl_driver);
+}
+postcore_initcall(armada_370_pinctrl_init);
diff --git a/drivers/pinctrl/mvebu/armada-xp.c b/drivers/pinctrl/mvebu/armada-xp.c
new file mode 100644
index 0000000000..9f79d373e4
--- /dev/null
+++ b/drivers/pinctrl/mvebu/armada-xp.c
@@ -0,0 +1,403 @@
+/*
+ * Marvell Armada XP pinctrl driver based on mvebu pinctrl core
+ *
+ * Copyright (C) 2012 Marvell
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 file supports the three variants of Armada XP SoCs that are
+ * available: mv78230, mv78260 and mv78460. From a pin muxing
+ * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460
+ * both have 67 MPP pins (more GPIOs and address lines for the memory
+ * bus mainly). The only difference between the mv78260 and the
+ * mv78460 in terms of pin muxing is the addition of two functions on
+ * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two
+ * cores, mv78460 has four cores).
+ */
+
+#include <common.h>
+#include <init.h>
+#include <linux/clk.h>
+#include <malloc.h>
+#include <of.h>
+#include <of_address.h>
+#include <sizes.h>
+
+#include "common.h"
+
+static void __iomem *mpp_base;
+
+static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config)
+{
+ return default_mpp_ctrl_get(mpp_base, pid, config);
+}
+
+static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config)
+{
+ return default_mpp_ctrl_set(mpp_base, pid, config);
+}
+
+enum armada_xp_variant {
+ V_MV78230 = BIT(0),
+ V_MV78260 = BIT(1),
+ V_MV78460 = BIT(2),
+ V_MV78230_PLUS = (V_MV78230 | V_MV78260 | V_MV78460),
+ V_MV78260_PLUS = (V_MV78260 | V_MV78460),
+};
+
+static struct mvebu_mpp_mode armada_xp_mpp_modes[] = {
+ MPP_MODE(0, "mpp0", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txclko", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d0", V_MV78230_PLUS)),
+ MPP_MODE(1, "mpp1", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d1", V_MV78230_PLUS)),
+ MPP_MODE(2, "mpp2", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d2", V_MV78230_PLUS)),
+ MPP_MODE(3, "mpp3", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d3", V_MV78230_PLUS)),
+ MPP_MODE(4, "mpp4", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d4", V_MV78230_PLUS)),
+ MPP_MODE(5, "mpp5", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d5", V_MV78230_PLUS)),
+ MPP_MODE(6, "mpp6", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d6", V_MV78230_PLUS)),
+ MPP_MODE(7, "mpp7", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d7", V_MV78230_PLUS)),
+ MPP_MODE(8, "mpp8", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d8", V_MV78230_PLUS)),
+ MPP_MODE(9, "mpp9", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d9", V_MV78230_PLUS)),
+ MPP_MODE(10, "mpp10", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d10", V_MV78230_PLUS)),
+ MPP_MODE(11, "mpp11", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d11", V_MV78230_PLUS)),
+ MPP_MODE(12, "mpp12", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "clkout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d12", V_MV78230_PLUS)),
+ MPP_MODE(13, "mpp13", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d13", V_MV78230_PLUS)),
+ MPP_MODE(14, "mpp14", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d14", V_MV78230_PLUS)),
+ MPP_MODE(15, "mpp15", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txd7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d15", V_MV78230_PLUS)),
+ MPP_MODE(16, "mpp16", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "txclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d16", V_MV78230_PLUS)),
+ MPP_MODE(17, "mpp17", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "col", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "txctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d17", V_MV78230_PLUS)),
+ MPP_MODE(18, "mpp18", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxerr", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "trig", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d18", V_MV78230_PLUS)),
+ MPP_MODE(19, "mpp19", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "crs", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "evreq", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d19", V_MV78230_PLUS)),
+ MPP_MODE(20, "mpp20", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "ptp", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d20", V_MV78230_PLUS)),
+ MPP_MODE(21, "mpp21", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxd3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "mem", "bat", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d21", V_MV78230_PLUS)),
+ MPP_MODE(22, "mpp22", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxctl", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d22", V_MV78230_PLUS)),
+ MPP_MODE(23, "mpp23", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ge0", "rxd7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "ge1", "rxclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "d23", V_MV78230_PLUS)),
+ MPP_MODE(24, "mpp24", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)),
+ MPP_MODE(25, "mpp25", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)),
+ MPP_MODE(26, "mpp26", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)),
+ MPP_MODE(27, "mpp27", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "dtx", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "e", V_MV78230_PLUS)),
+ MPP_MODE(28, "mpp28", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "evreq", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "drx", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "pwm", V_MV78230_PLUS)),
+ MPP_MODE(29, "mpp29", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(30, "mpp30", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int1", V_MV78230_PLUS)),
+ MPP_MODE(31, "mpp31", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(32, "mpp32", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)),
+ MPP_MODE(33, "mpp33", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS)),
+ MPP_MODE(34, "mpp34", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "sata0", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int5", V_MV78230_PLUS)),
+ MPP_MODE(35, "mpp35", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "sd0", "d3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int6", V_MV78230_PLUS)),
+ MPP_MODE(36, "mpp36", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "mosi", V_MV78230_PLUS)),
+ MPP_MODE(37, "mpp37", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "miso", V_MV78230_PLUS)),
+ MPP_MODE(38, "mpp38", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "sck", V_MV78230_PLUS)),
+ MPP_MODE(39, "mpp39", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs0", V_MV78230_PLUS)),
+ MPP_MODE(40, "mpp40", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)),
+ MPP_MODE(41, "mpp41", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "spi", "cs2", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart2", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1", V_MV78230_PLUS)),
+ MPP_MODE(42, "mpp42", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)),
+ MPP_MODE(43, "mpp43", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)),
+ MPP_MODE(44, "mpp44", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart3", "rxd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs4", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2", V_MV78230_PLUS)),
+ MPP_MODE(45, "mpp45", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart2", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart3", "txd", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs5", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V_MV78230_PLUS)),
+ MPP_MODE(46, "mpp46", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart3", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart1", "rts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs6", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V_MV78230_PLUS)),
+ MPP_MODE(47, "mpp47", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "uart3", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "uart1", "cts", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x3, "spi", "cs7", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x4, "ref", "clkout", V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)),
+ MPP_MODE(48, "mpp48", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS),
+ MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)),
+ MPP_MODE(49, "mpp49", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "we3", V_MV78260_PLUS)),
+ MPP_MODE(50, "mpp50", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "we2", V_MV78260_PLUS)),
+ MPP_MODE(51, "mpp51", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad16", V_MV78260_PLUS)),
+ MPP_MODE(52, "mpp52", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad17", V_MV78260_PLUS)),
+ MPP_MODE(53, "mpp53", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad18", V_MV78260_PLUS)),
+ MPP_MODE(54, "mpp54", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)),
+ MPP_MODE(55, "mpp55", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)),
+ MPP_MODE(56, "mpp56", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)),
+ MPP_MODE(57, "mpp57", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)),
+ MPP_MODE(58, "mpp58", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)),
+ MPP_MODE(59, "mpp59", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad24", V_MV78260_PLUS)),
+ MPP_MODE(60, "mpp60", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad25", V_MV78260_PLUS)),
+ MPP_MODE(61, "mpp61", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad26", V_MV78260_PLUS)),
+ MPP_MODE(62, "mpp62", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad27", V_MV78260_PLUS)),
+ MPP_MODE(63, "mpp63", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad28", V_MV78260_PLUS)),
+ MPP_MODE(64, "mpp64", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad29", V_MV78260_PLUS)),
+ MPP_MODE(65, "mpp65", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad30", V_MV78260_PLUS)),
+ MPP_MODE(66, "mpp66", armada_xp_mpp_ctrl,
+ MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS),
+ MPP_VAR_FUNCTION(0x1, "dev", "ad31", V_MV78260_PLUS)),
+};
+
+static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info = {
+ .modes = armada_xp_mpp_modes,
+ .nmodes = ARRAY_SIZE(armada_xp_mpp_modes),
+};
+
+static struct of_device_id armada_xp_pinctrl_of_match[] = {
+ { .compatible = "marvell,mv78230-pinctrl", .data = (u32)V_MV78230, },
+ { .compatible = "marvell,mv78260-pinctrl", .data = (u32)V_MV78260, },
+ { .compatible = "marvell,mv78460-pinctrl", .data = (u32)V_MV78460, },
+ { },
+};
+
+static int armada_xp_pinctrl_probe(struct device_d *dev)
+{
+ const struct of_device_id *match =
+ of_match_node(armada_xp_pinctrl_of_match, dev->device_node);
+ struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info;
+
+ mpp_base = dev_request_mem_region(dev, 0);
+ if (!mpp_base)
+ return -EBUSY;
+
+ soc->variant = (enum armada_xp_variant)match->data;
+
+ /*
+ * We don't necessarily want the full list of the armada_xp_mpp_modes,
+ * but only the first 'n' ones that are available on this SoC
+ */
+ if (soc->variant == V_MV78230)
+ soc->nmodes = 49;
+
+ return mvebu_pinctrl_probe(dev, soc);
+}
+
+static struct driver_d armada_xp_pinctrl_driver = {
+ .name = "pinctrl-armada-xp",
+ .probe = armada_xp_pinctrl_probe,
+ .of_compatible = armada_xp_pinctrl_of_match,
+};
+
+static int armada_xp_pinctrl_init(void)
+{
+ return platform_driver_register(&armada_xp_pinctrl_driver);
+}
+postcore_initcall(armada_xp_pinctrl_init);
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig
index f51c6e6b02..146bf1ec3c 100644
--- a/drivers/serial/Kconfig
+++ b/drivers/serial/Kconfig
@@ -45,6 +45,10 @@ config DRIVER_SERIAL_LINUX_CONSOLE
default y
bool "linux console driver"
+config DRIVER_SERIAL_EFI_STDIO
+ depends on ARCH_EFI
+ bool "EFI stdio driver"
+
config DRIVER_SERIAL_MPC5XXX
depends on MPC5200
default y
@@ -129,4 +133,8 @@ config DRIVER_SERIAL_CADENCE
help
Say Y here if you have a Cadence serial IP core.
+config DRIVER_SERIAL_DIGIC
+ bool "Canon DIGIC serial driver"
+ depends on ARCH_DIGIC
+
endmenu
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile
index e1865f725a..189e777777 100644
--- a/drivers/serial/Makefile
+++ b/drivers/serial/Makefile
@@ -18,3 +18,5 @@ obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o
obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o
obj-$(CONFIG_DRIVER_SERIAL_AUART) += serial_auart.o
obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o
+obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o
+obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o
diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c
new file mode 100644
index 0000000000..bf14c5e24a
--- /dev/null
+++ b/drivers/serial/efi-stdio.c
@@ -0,0 +1,367 @@
+/*
+ * efi_console.c - EFI console support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <console.h>
+#include <xfuncs.h>
+#include <efi.h>
+#include <readkey.h>
+#include <linux/ctype.h>
+#include <mach/efi.h>
+
+#define EFI_SHIFT_STATE_VALID 0x80000000
+#define EFI_RIGHT_CONTROL_PRESSED 0x00000004
+#define EFI_LEFT_CONTROL_PRESSED 0x00000008
+#define EFI_RIGHT_ALT_PRESSED 0x00000010
+#define EFI_LEFT_ALT_PRESSED 0x00000020
+
+#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED)
+#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED)
+#define KEYPRESS(keys, scan, uni) ((((uint64_t)keys) << 32) | ((scan) << 16) | (uni))
+#define KEYCHAR(k) ((k) & 0xffff)
+#define CHAR_CTRL(c) ((c) - 'a' + 1)
+
+#define EFI_BLACK 0x00
+#define EFI_BLUE 0x01
+#define EFI_GREEN 0x02
+#define EFI_CYAN (EFI_BLUE | EFI_GREEN)
+#define EFI_RED 0x04
+#define EFI_MAGENTA (EFI_BLUE | EFI_RED)
+#define EFI_BROWN (EFI_GREEN | EFI_RED)
+#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED)
+#define EFI_BRIGHT 0x08
+#define EFI_DARKGRAY (EFI_BRIGHT)
+#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT)
+#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT)
+#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT)
+#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT)
+#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT)
+#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT)
+#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT)
+
+#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4))
+
+#define EFI_BACKGROUND_BLACK 0x00
+#define EFI_BACKGROUND_BLUE 0x10
+#define EFI_BACKGROUND_GREEN 0x20
+#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN)
+#define EFI_BACKGROUND_RED 0x40
+#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED)
+
+struct efi_console_priv {
+ struct efi_simple_text_output_protocol *out;
+ struct efi_simple_input_interface *in;
+ struct console_device cdev;
+ int lastkey;
+ u16 efi_console_buffer[CONFIG_CBSIZE];
+
+ unsigned long columns, rows;
+
+ int current_color;
+ s16 *blank_line;
+};
+
+static inline struct efi_console_priv *to_efi(struct console_device *cdev)
+{
+ return container_of(cdev, struct efi_console_priv, cdev);
+}
+
+struct efi_ctrlkey {
+ u8 scan_code;
+ u8 bb_key;
+};
+
+static struct efi_ctrlkey ctrlkeys[] = {
+ { 0x01, BB_KEY_UP },
+ { 0x02, BB_KEY_DOWN },
+ { 0x03, BB_KEY_RIGHT },
+ { 0x04, BB_KEY_LEFT },
+ { 0x05, BB_KEY_HOME },
+ { 0x06, BB_KEY_END },
+ { 0x07, BB_KEY_INSERT },
+ { 0x08, BB_KEY_DEL },
+ { 0x09, BB_KEY_PAGEUP },
+ { 0x0a, BB_KEY_PAGEDOWN },
+};
+
+static int efi_read_key(struct efi_console_priv *priv, bool wait)
+{
+ unsigned long index;
+ efi_status_t efiret;
+ struct efi_input_key k;
+ int i;
+
+ /* wait until key is pressed */
+ if (wait)
+ BS->wait_for_event(1, priv->in->wait_for_key, &index);
+
+ efiret = priv->in->read_key_stroke(efi_sys_table->con_in, &k);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
+ for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) {
+ if (ctrlkeys[i].scan_code == k.scan_code)
+ return ctrlkeys[i].bb_key;
+
+ }
+
+ return k.unicode_char & 0xff;
+}
+
+static void efi_console_putc(struct console_device *cdev, char c)
+{
+ uint16_t str[2] = {};
+ struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out;
+
+ str[0] = c;
+
+ con_out->output_string(con_out, str);
+}
+
+static void clear_to_eol(struct efi_console_priv *priv)
+{
+ int pos = priv->out->mode->cursor_column;
+
+ priv->out->output_string(priv->out, priv->blank_line + pos);
+}
+
+static int efi_process_square_bracket(struct efi_console_priv *priv, const char *inp)
+{
+ int x, y;
+ char *endp;
+
+ inp++;
+
+ switch (*inp) {
+ case 'A':
+ /* Cursor up */
+ case 'B':
+ /* Cursor down */
+ case 'C':
+ /* Cursor right */
+ case 'D':
+ /* Cursor left */
+ case 'H':
+ /* home */
+ case 'F':
+ /* end */
+ return 3;
+ case 'K':
+ clear_to_eol(priv);
+ return 3;
+ }
+
+ if (*inp == '2' && *(inp + 1) == 'J') {
+ priv->out->clear_screen(priv->out);
+ return 4;
+ }
+
+ if (*inp == '0' && *(inp + 1) == 'm') {
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(EFI_WHITE, EFI_BLACK));
+ return 4;
+ }
+
+ if (*inp == '7' && *(inp + 1) == 'm') {
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(EFI_BLACK, priv->current_color));
+ return 4;
+ }
+
+ if (*inp == '1' &&
+ *(inp + 1) == ';' &&
+ *(inp + 2) == '3' &&
+ *(inp + 3) &&
+ *(inp + 4) == 'm') {
+ int color;
+ switch (*(inp + 3)) {
+ case '1': color = EFI_RED; break;
+ case '4': color = EFI_BLUE; break;
+ case '2': color = EFI_GREEN; break;
+ case '6': color = EFI_CYAN; break;
+ case '3': color = EFI_YELLOW; break;
+ case '5': color = EFI_MAGENTA; break;
+ case '7': color = EFI_WHITE; break;
+ default: color = EFI_WHITE; break;
+ }
+
+ priv->current_color = color;
+
+ priv->out->set_attribute(priv->out,
+ EFI_TEXT_ATTR(color, EFI_BLACK));
+ return 7;
+ }
+
+ y = simple_strtoul(inp, &endp, 10);
+ if (*endp == ';') {
+ x = simple_strtoul(endp + 1, &endp, 10);
+ if (*endp == 'H') {
+ priv->out->set_cursor_position(priv->out, x - 1, y - 1);
+ return endp - inp + 3;
+ }
+ }
+
+ return 8;
+}
+
+static int efi_process_key(struct efi_console_priv *priv, const char *inp)
+{
+ char c;
+
+ c = *inp;
+
+ if (c != 27)
+ return 0;
+
+ inp++;
+
+ if (*inp == '[')
+ return efi_process_square_bracket(priv, inp);
+
+ return 1;
+}
+
+static int efi_console_puts(struct console_device *cdev, const char *s)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int n = 0;
+
+ while (*s) {
+ if (*s == 27) {
+ priv->efi_console_buffer[n] = 0;
+ priv->out->output_string(priv->out,
+ priv->efi_console_buffer);
+ n = 0;
+ s += efi_process_key(priv, s);
+ continue;
+ }
+
+ if (*s == '\n')
+ priv->efi_console_buffer[n++] = '\r';
+ priv->efi_console_buffer[n] = *s;
+ s++;
+ n++;
+ }
+
+ priv->efi_console_buffer[n] = 0;
+
+ priv->out->output_string(priv->out, priv->efi_console_buffer);
+
+ return n;
+}
+
+static int efi_console_tstc(struct console_device *cdev)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int key;
+
+ if (priv->lastkey > 0)
+ return 1;
+
+ key = efi_read_key(priv, 0);
+ if (key < 0)
+ return 0;
+
+ priv->lastkey = key;
+
+ return 1;
+}
+
+static int efi_console_getc(struct console_device *cdev)
+{
+ struct efi_console_priv *priv = to_efi(cdev);
+ int key;
+
+ if (priv->lastkey > 0) {
+ key = priv->lastkey;
+ priv->lastkey = -1;
+ return key;
+ }
+
+ return efi_read_key(priv, 1);
+}
+
+static void efi_set_mode(struct efi_console_priv *priv)
+{
+#if 0
+ int i;
+ unsigned long rows, columns, best = 0, mode = 0;
+ efi_status_t efiret;
+
+ for (i = 0; i < priv->out->mode->max_mode; i++) {
+ priv->out->query_mode(priv->out, i, &columns, &rows);
+ printf("%d: %ld %ld\n", i, columns, rows);
+ if (rows * columns > best) {
+ best = rows * columns;
+ mode = i;
+ }
+ }
+
+ /*
+ * Setting the mode doesn't work as expected. set_mode succeeds, but
+ * the graphics resolution is not changed.
+ */
+ priv->out->set_mode(priv->out, mode);
+#endif
+ priv->out->query_mode(priv->out, priv->out->mode->mode, &priv->columns, &priv->rows);
+}
+
+static int efi_console_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+ struct efi_console_priv *priv;
+ int i;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->out = efi_sys_table->con_out;
+ priv->in = efi_sys_table->con_in;
+
+ priv->current_color = EFI_WHITE;
+
+ efi_set_mode(priv);
+
+ priv->out->enable_cursor(priv->out, 1);
+
+ priv->blank_line = xzalloc((priv->columns + 1) * sizeof(s16));
+ for (i = 0; i < priv->columns; i++)
+ priv->blank_line[i] = ' ';
+
+ cdev = &priv->cdev;
+ cdev->dev = dev;
+ cdev->tstc = efi_console_tstc;
+ cdev->getc = efi_console_getc;
+ cdev->putc = efi_console_putc;
+ cdev->puts = efi_console_puts;
+
+ priv->lastkey = -1;
+
+ return console_register(cdev);
+}
+
+static struct driver_d efi_console_driver = {
+ .name = "efi-stdio",
+ .probe = efi_console_probe,
+};
+console_platform_driver(efi_console_driver);
diff --git a/drivers/serial/serial_digic.c b/drivers/serial/serial_digic.c
new file mode 100644
index 0000000000..235ea0ff47
--- /dev/null
+++ b/drivers/serial/serial_digic.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com>
+ *
+ * This file is part of barebox.
+ * See file CREDITS for list of people who contributed to this project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <io.h>
+
+#include <mach/uart.h>
+
+/*
+ * This driver is based on the "Serial terminal" docs here:
+ * http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers
+ *
+ * See also disassembler output for Canon A1100IS firmware
+ * (version a1100_100c):
+ * * a outc-like function can be found at address 0xffff18f0;
+ * * a getc-like function can be found at address 0xffff192c.
+ */
+
+static inline uint32_t digic_serial_readl(struct console_device *cdev,
+ uint32_t offset)
+{
+ void __iomem *base = cdev->dev->priv;
+
+ return readl(base + offset);
+}
+
+static inline void digic_serial_writel(struct console_device *cdev,
+ uint32_t value, uint32_t offset)
+{
+ void __iomem *base = cdev->dev->priv;
+
+ writel(value, base + offset);
+}
+
+static int digic_serial_setbaudrate(struct console_device *cdev, int baudrate)
+{
+ /* I don't know how to setup baudrate :( */
+
+ return 0;
+}
+
+static void digic_serial_putc(struct console_device *cdev, char c)
+{
+ uint32_t status;
+
+ do {
+ status = digic_serial_readl(cdev, DIGIC_UART_ST);
+ } while (!(status & DIGIC_UART_ST_TX_RDY));
+
+ digic_serial_writel(cdev, 0x06, DIGIC_UART_ST);
+ digic_serial_writel(cdev, c, DIGIC_UART_TX);
+}
+
+static int digic_serial_getc(struct console_device *cdev)
+{
+ uint32_t status;
+
+ do {
+ status = digic_serial_readl(cdev, DIGIC_UART_ST);
+ } while (!(status & DIGIC_UART_ST_RX_RDY));
+
+ digic_serial_writel(cdev, 0x01, DIGIC_UART_ST);
+
+ return digic_serial_readl(cdev, DIGIC_UART_RX);
+}
+
+static int digic_serial_tstc(struct console_device *cdev)
+{
+ uint32_t status = digic_serial_readl(cdev, DIGIC_UART_ST);
+
+ return ((status & DIGIC_UART_ST_RX_RDY) != 0);
+
+ /*
+ * Canon folks use additional check, something like this:
+ *
+ * if (digic_serial_readl(cdev, DIGIC_UART_ST) & 0x38) {
+ * digic_serial_writel(cdev, 0x38, DIGIC_UART_ST);
+ * return 0;
+ * }
+ *
+ * But I know nothing about these magic bits in the status register...
+ *
+ */
+}
+
+static int digic_serial_probe(struct device_d *dev)
+{
+ struct console_device *cdev;
+
+ cdev = xzalloc(sizeof(struct console_device));
+ dev->priv = dev_request_mem_region(dev, 0);
+ cdev->dev = dev;
+ cdev->tstc = &digic_serial_tstc;
+ cdev->putc = &digic_serial_putc;
+ cdev->getc = &digic_serial_getc;
+ cdev->setbrg = &digic_serial_setbaudrate;
+
+ console_register(cdev);
+
+ return 0;
+}
+
+static __maybe_unused struct of_device_id digic_serial_dt_ids[] = {
+ {
+ .compatible = "canon,digic-uart",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d digic_serial_driver = {
+ .name = "digic-uart",
+ .probe = digic_serial_probe,
+ .of_compatible = DRV_OF_COMPAT(digic_serial_dt_ids),
+};
+console_platform_driver(digic_serial_driver);
diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c
index cb106271d5..474bfafff0 100644
--- a/drivers/serial/serial_imx.c
+++ b/drivers/serial/serial_imx.c
@@ -313,6 +313,7 @@ static int imx_serial_probe(struct device_d *dev)
uint32_t val;
struct imx_serial_devtype_data *devtype;
int ret;
+ const char *devname;
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
if (ret)
@@ -337,6 +338,9 @@ static int imx_serial_probe(struct device_d *dev)
cdev->flush = imx_serial_flush;
cdev->setbrg = imx_serial_setbaudrate;
cdev->linux_console_name = "ttymxc";
+ devname = of_alias_get(dev->device_node);
+ if (devname)
+ cdev->devname = xstrdup(devname);
imx_serial_init_port(cdev);
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 709f704cb4..09e6a6aba8 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -46,10 +46,17 @@
struct ns16550_priv {
struct console_device cdev;
struct NS16550_plat plat;
- int access_width;
- int mmio;
struct clk *clk;
uint32_t fcrval;
+ void __iomem *mmiobase;
+ unsigned iobase;
+ void (*write_reg)(struct ns16550_priv *, uint8_t val, unsigned offset);
+ uint8_t (*read_reg)(struct ns16550_priv *, unsigned offset);
+};
+
+struct ns16550_drvdata {
+ void (*init_port)(struct console_device *cdev);
+ const char *linux_console_name;
};
static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
@@ -57,93 +64,64 @@ static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev)
return container_of(cdev, struct ns16550_priv, cdev);
}
-struct ns16550_drvdata {
- void (*init_port)(struct console_device *cdev);
- const char *linux_console_name;
-};
+static uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset)
+{
+ return readb(priv->mmiobase + offset);
+}
-/**
- * @brief read system i/o (byte)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint8_t ns16550_sys_readb(void __iomem *addr, int mmio)
+static void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- return readb(addr);
- else
- return (uint8_t) inb((int) addr);
+ writeb(val, priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (word)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint16_t ns16550_sys_readw(void __iomem *addr, int mmio)
+static uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- return readw(addr);
- else
- return (uint16_t) inw((int) addr);
+ return readw(priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (dword)
- * @param[in] addr address to read
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline uint32_t ns16550_sys_readl(void __iomem *addr, int mmio)
+static void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- return readl(addr);
- else
- return (uint32_t) inl((int) addr);
+ writew(val, priv->mmiobase + offset);
}
-/**
- * @brief write system i/o (byte)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writeb(uint8_t val, void __iomem *addr,
- int mmio)
+static uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- writeb(val, addr);
- else
- outb(val, (int) addr);
+ return readl(priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (word)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writew(uint16_t val, void __iomem *addr,
- int mmio)
+static void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
{
- if (mmio)
- writew(val, addr);
- else
- outw(val, (int) addr);
+ writel(val, priv->mmiobase + offset);
}
-/**
- * @brief read system i/o (dword)
- * @param[in] val data to write
- * @param[in] addr address to write to
- * @param[in] mmio memory i/o space or i/o port space
- */
-static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr,
- int mmio)
+static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset)
{
- if (mmio)
- writel(val, addr);
- else
- outl(val, (int) addr);
+ return inb(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_8(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outb(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_16(struct ns16550_priv *priv, unsigned offset)
+{
+ return inw(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_16(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outw(val, priv->iobase + offset);
+}
+
+static uint8_t ns16550_read_reg_ioport_32(struct ns16550_priv *priv, unsigned offset)
+{
+ return inl(priv->iobase + offset);
+}
+
+static void ns16550_write_reg_ioport_32(struct ns16550_priv *priv, uint8_t val, unsigned offset)
+{
+ outl(val, priv->iobase + offset);
}
/**
@@ -157,21 +135,9 @@ static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr,
static uint32_t ns16550_read(struct console_device *cdev, uint32_t off)
{
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- struct device_d *dev = cdev->dev;
struct NS16550_plat *plat = &priv->plat;
- int width = priv->access_width;
-
- off <<= plat->shift;
- switch (width) {
- case IORESOURCE_MEM_8BIT:
- return ns16550_sys_readb(dev->priv + off, priv->mmio);
- case IORESOURCE_MEM_16BIT:
- return ns16550_sys_readw(dev->priv + off, priv->mmio);
- case IORESOURCE_MEM_32BIT:
- return ns16550_sys_readl(dev->priv + off, priv->mmio);
- }
- return -1;
+ return priv->read_reg(priv, off << plat->shift);
}
/**
@@ -185,23 +151,9 @@ static void ns16550_write(struct console_device *cdev, uint32_t val,
uint32_t off)
{
struct ns16550_priv *priv = to_ns16550_priv(cdev);
- struct device_d *dev = cdev->dev;
struct NS16550_plat *plat = &priv->plat;
- int width = priv->access_width;
-
- off <<= plat->shift;
- switch (width) {
- case IORESOURCE_MEM_8BIT:
- ns16550_sys_writeb(val & 0xff, dev->priv + off, priv->mmio);
- break;
- case IORESOURCE_MEM_16BIT:
- ns16550_sys_writew(val & 0xffff, dev->priv + off, priv->mmio);
- break;
- case IORESOURCE_MEM_32BIT:
- ns16550_sys_writel(val, dev->priv + off, priv->mmio);
- break;
- }
+ priv->write_reg(priv, val, off << plat->shift);
}
/**
@@ -359,6 +311,70 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = {
.init_port = ns16550_jz_init_port,
};
+static int ns16550_init_iomem(struct device_d *dev, struct ns16550_priv *priv)
+{
+ struct resource *res;
+ int width;
+
+ res = dev_get_resource(dev, IORESOURCE_MEM, 0);
+ if (!res)
+ return -ENODEV;
+
+ priv->mmiobase = dev_request_mem_region(dev, 0);
+
+ width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+ switch (width) {
+ case IORESOURCE_MEM_8BIT:
+ priv->read_reg = ns16550_read_reg_mmio_8;
+ priv->write_reg = ns16550_write_reg_mmio_8;
+ break;
+ case IORESOURCE_MEM_16BIT:
+ priv->read_reg = ns16550_read_reg_mmio_16;
+ priv->write_reg = ns16550_write_reg_mmio_16;
+ break;
+ case IORESOURCE_MEM_32BIT:
+ priv->read_reg = ns16550_read_reg_mmio_32;
+ priv->write_reg = ns16550_write_reg_mmio_32;
+ break;
+ }
+
+ return 0;
+}
+
+static int ns16550_init_ioport(struct device_d *dev, struct ns16550_priv *priv)
+{
+ struct resource *res;
+ int width;
+
+ res = dev_get_resource(dev, IORESOURCE_IO, 0);
+ if (!res)
+ return -ENODEV;
+
+ res = request_ioport_region(dev_name(dev), res->start, res->end);
+ if (!res)
+ return -ENODEV;
+
+ priv->iobase = res->start;
+
+ width = res->flags & IORESOURCE_MEM_TYPE_MASK;
+ switch (width) {
+ case IORESOURCE_MEM_8BIT:
+ priv->read_reg = ns16550_read_reg_ioport_8;
+ priv->write_reg = ns16550_write_reg_ioport_8;
+ break;
+ case IORESOURCE_MEM_16BIT:
+ priv->read_reg = ns16550_read_reg_ioport_16;
+ priv->write_reg = ns16550_write_reg_ioport_16;
+ break;
+ case IORESOURCE_MEM_32BIT:
+ priv->read_reg = ns16550_read_reg_ioport_32;
+ priv->write_reg = ns16550_write_reg_ioport_32;
+ break;
+ }
+
+ return 0;
+}
+
/**
* @brief Probe entry point -called on the first match for device
*
@@ -374,7 +390,6 @@ static int ns16550_probe(struct device_d *dev)
struct console_device *cdev;
struct NS16550_plat *plat = (struct NS16550_plat *)dev->platform_data;
struct ns16550_drvdata *devtype;
- struct resource *res;
int ret;
ret = dev_get_drvdata(dev, (unsigned long *)&devtype);
@@ -383,20 +398,12 @@ static int ns16550_probe(struct device_d *dev)
priv = xzalloc(sizeof(*priv));
- res = dev_get_resource(dev, IORESOURCE_MEM, 0);
- priv->mmio = (res != NULL);
- if (res) {
- res = request_iomem_region(dev_name(dev), res->start, res->end);
- } else {
- res = dev_get_resource(dev, IORESOURCE_IO, 0);
- if (res)
- res = request_ioport_region(dev_name(dev), res->start,
- res->end);
- }
- if (!res)
- goto err;
- dev->priv = (void __force __iomem *) res->start;
+ ret = ns16550_init_iomem(dev, priv);
+ if (ret)
+ ret = ns16550_init_ioport(dev, priv);
+ if (ret)
+ return ret;
if (plat)
priv->plat = *plat;
@@ -424,8 +431,6 @@ static int ns16550_probe(struct device_d *dev)
goto err;
}
- priv->access_width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK;
-
cdev = &priv->cdev;
cdev->dev = dev;
cdev->tstc = ns16550_tstc;
diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c
index d0f2155e49..bc5ee9c7dd 100644
--- a/drivers/usb/gadget/dfu.c
+++ b/drivers/usb/gadget/dfu.c
@@ -43,6 +43,7 @@
#include <linux/list.h>
#include <usb/gadget.h>
#include <linux/stat.h>
+#include <libfile.h>
#include <usb/ch9.h>
#include <usb/dfu.h>
#include <config.h>
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index 574e0975b9..2f9353edca 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -475,7 +475,12 @@ int gserial_connect(struct gserial *gser, u8 port_num)
cdev->getc = serial_getc;
cdev->flush = serial_flush;
cdev->setbrg = serial_setbaudrate;
- console_register(cdev);
+ cdev->devname = "usbserial";
+
+ status = console_register(cdev);
+ if (status)
+ goto fail_out;
+
mycdev = cdev;
return status;
diff --git a/dts/Bindings/arm/armada-38x.txt b/dts/Bindings/arm/armada-38x.txt
index 11f2330a65..ad9f8ed4d9 100644
--- a/dts/Bindings/arm/armada-38x.txt
+++ b/dts/Bindings/arm/armada-38x.txt
@@ -6,5 +6,15 @@ following property:
Required root node property:
- - compatible: must contain either "marvell,armada380" or
- "marvell,armada385" depending on the variant of the SoC being used.
+ - compatible: must contain "marvell,armada380"
+
+In addition, boards using the Marvell Armada 385 SoC shall have the
+following property before the previous one:
+
+Required root node property:
+
+compatible: must contain "marvell,armada385"
+
+Example:
+
+compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada380";
diff --git a/dts/Bindings/arm/exynos/power_domain.txt b/dts/Bindings/arm/exynos/power_domain.txt
index 5216b41901..8b4f7b7fe8 100644
--- a/dts/Bindings/arm/exynos/power_domain.txt
+++ b/dts/Bindings/arm/exynos/power_domain.txt
@@ -9,6 +9,18 @@ Required Properties:
- reg: physical base address of the controller and length of memory mapped
region.
+Optional Properties:
+- clocks: List of clock handles. The parent clocks of the input clocks to the
+ devices in this power domain are set to oscclk before power gating
+ and restored back after powering on a domain. This is required for
+ all domains which are powered on and off and not required for unused
+ domains.
+- clock-names: The following clocks can be specified:
+ - oscclk: Oscillator clock.
+ - pclkN, clkN: Pairs of parent of input clock and input clock to the
+ devices in this power domain. Maximum of 4 pairs (N = 0 to 3)
+ are supported currently.
+
Node of a device using power domains must have a samsung,power-domain property
defined with a phandle to respective power domain.
@@ -19,6 +31,14 @@ Example:
reg = <0x10023C00 0x10>;
};
+ mfc_pd: power-domain@10044060 {
+ compatible = "samsung,exynos4210-pd";
+ reg = <0x10044060 0x20>;
+ clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>,
+ <&clock CLK_MOUT_USER_ACLK333>;
+ clock-names = "oscclk", "pclk0", "clk0";
+ };
+
Example of the node using power domain:
node {
diff --git a/dts/Bindings/arm/l2cc.txt b/dts/Bindings/arm/l2cc.txt
index b513cb8196..af527ee111 100644
--- a/dts/Bindings/arm/l2cc.txt
+++ b/dts/Bindings/arm/l2cc.txt
@@ -40,6 +40,9 @@ Optional properties:
- arm,filter-ranges : <start length> Starting address and length of window to
filter. Addresses in the filter window are directed to the M1 port. Other
addresses will go to the M0 port.
+- arm,io-coherent : indicates that the system is operating in an hardware
+ I/O coherent mode. Valid only when the arm,pl310-cache compatible
+ string is used.
- interrupts : 1 combined interrupt.
- cache-id-part: cache id part number to be used if it is not present
on hardware
diff --git a/dts/Bindings/arm/samsung/exynos-adc.txt b/dts/Bindings/arm/samsung/exynos-adc.txt
index 5d49f2b37f..832fe8cc24 100644
--- a/dts/Bindings/arm/samsung/exynos-adc.txt
+++ b/dts/Bindings/arm/samsung/exynos-adc.txt
@@ -48,7 +48,7 @@ adc@12D10000 {
/* NTC thermistor is a hwmon device */
ncp15wb473@0 {
- compatible = "ntc,ncp15wb473";
+ compatible = "murata,ncp15wb473";
pullup-uv = <1800000>;
pullup-ohm = <47000>;
pulldown-ohm = <0>;
diff --git a/dts/Bindings/cpufreq/cpufreq-cpu0.txt b/dts/Bindings/cpufreq/cpufreq-cpu0.txt
index f055515d2b..366690cb86 100644
--- a/dts/Bindings/cpufreq/cpufreq-cpu0.txt
+++ b/dts/Bindings/cpufreq/cpufreq-cpu0.txt
@@ -8,10 +8,12 @@ Both required and optional properties listed below must be defined
under node /cpus/cpu@0.
Required properties:
-- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt
- for details
+- None
Optional properties:
+- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt for
+ details. OPPs *must* be supplied either via DT, i.e. this property, or
+ populated at runtime.
- clock-latency: Specify the possible maximum transition latency for clock,
in unit of nanoseconds.
- voltage-tolerance: Specify the CPU voltage tolerance in percentage.
diff --git a/dts/Bindings/hwmon/ntc_thermistor.txt b/dts/Bindings/hwmon/ntc_thermistor.txt
index c6f66674f1..b117b2e9e1 100644
--- a/dts/Bindings/hwmon/ntc_thermistor.txt
+++ b/dts/Bindings/hwmon/ntc_thermistor.txt
@@ -3,11 +3,19 @@ NTC Thermistor hwmon sensors
Requires node properties:
- "compatible" value : one of
- "ntc,ncp15wb473"
- "ntc,ncp18wb473"
- "ntc,ncp21wb473"
- "ntc,ncp03wb473"
- "ntc,ncp15wl333"
+ "murata,ncp15wb473"
+ "murata,ncp18wb473"
+ "murata,ncp21wb473"
+ "murata,ncp03wb473"
+ "murata,ncp15wl333"
+
+/* Usage of vendor name "ntc" is deprecated */
+<DEPRECATED> "ntc,ncp15wb473"
+<DEPRECATED> "ntc,ncp18wb473"
+<DEPRECATED> "ntc,ncp21wb473"
+<DEPRECATED> "ntc,ncp03wb473"
+<DEPRECATED> "ntc,ncp15wl333"
+
- "pullup-uv" Pull up voltage in micro volts
- "pullup-ohm" Pull up resistor value in ohms
- "pulldown-ohm" Pull down resistor value in ohms
@@ -21,7 +29,7 @@ Read more about iio bindings at
Example:
ncp15wb473@0 {
- compatible = "ntc,ncp15wb473";
+ compatible = "murata,ncp15wb473";
pullup-uv = <1800000>;
pullup-ohm = <47000>;
pulldown-ohm = <0>;
diff --git a/dts/Bindings/serial/renesas,sci-serial.txt b/dts/Bindings/serial/renesas,sci-serial.txt
index 64fd7dec1b..b3556609a0 100644
--- a/dts/Bindings/serial/renesas,sci-serial.txt
+++ b/dts/Bindings/serial/renesas,sci-serial.txt
@@ -4,6 +4,13 @@ Required properties:
- compatible: Must contain one of the following:
+ - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART.
+ - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART.
+ - "renesas,scifa-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFA compatible UART.
+ - "renesas,scifb-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFB compatible UART.
+ - "renesas,scifa-r8a7740" for R8A7740 (R-Mobile A1) SCIFA compatible UART.
+ - "renesas,scifb-r8a7740" for R8A7740 (R-Mobile A1) SCIFB compatible UART.
+ - "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART.
- "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART.
- "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART.
- "renesas,scifa-r8a7790" for R8A7790 (R-Car H2) SCIFA compatible UART.
diff --git a/dts/Bindings/spi/qcom,spi-qup.txt b/dts/Bindings/spi/qcom,spi-qup.txt
index b82a268f1b..bee6ff204b 100644
--- a/dts/Bindings/spi/qcom,spi-qup.txt
+++ b/dts/Bindings/spi/qcom,spi-qup.txt
@@ -23,6 +23,12 @@ Optional properties:
- spi-max-frequency: Specifies maximum SPI clock frequency,
Units - Hz. Definition as per
Documentation/devicetree/bindings/spi/spi-bus.txt
+- num-cs: total number of chipselects
+- cs-gpios: should specify GPIOs used for chipselects.
+ The gpios will be referred to as reg = <index> in the SPI child
+ nodes. If unspecified, a single SPI device without a chip
+ select can be used.
+
SPI slave nodes must be children of the SPI master node and can contain
properties described in Documentation/devicetree/bindings/spi/spi-bus.txt
diff --git a/dts/Bindings/vendor-prefixes.txt b/dts/Bindings/vendor-prefixes.txt
index 4d7f3758d1..46a311e728 100644
--- a/dts/Bindings/vendor-prefixes.txt
+++ b/dts/Bindings/vendor-prefixes.txt
@@ -83,6 +83,7 @@ mosaixtech Mosaix Technologies, Inc.
moxa Moxa
mpl MPL AG
mundoreader Mundo Reader S.L.
+murata Murata Manufacturing Co., Ltd.
mxicy Macronix International Co., Ltd.
national National Semiconductor
neonode Neonode Inc.
diff --git a/dts/include/dt-bindings/clock/exynos5420.h b/dts/include/dt-bindings/clock/exynos5420.h
index 97dcb89d37..21d51ae1d2 100644
--- a/dts/include/dt-bindings/clock/exynos5420.h
+++ b/dts/include/dt-bindings/clock/exynos5420.h
@@ -63,7 +63,6 @@
#define CLK_SCLK_MPHY_IXTAL24 161
/* gate clocks */
-#define CLK_ACLK66_PERIC 256
#define CLK_UART0 257
#define CLK_UART1 258
#define CLK_UART2 259
@@ -203,6 +202,8 @@
#define CLK_MOUT_G3D 641
#define CLK_MOUT_VPLL 642
#define CLK_MOUT_MAUDIO0 643
+#define CLK_MOUT_USER_ACLK333 644
+#define CLK_MOUT_SW_ACLK333 645
/* divider clocks */
#define CLK_DOUT_PIXEL 768
diff --git a/dts/include/dt-bindings/clock/imx6sl-clock.h b/dts/include/dt-bindings/clock/imx6sl-clock.h
index 7cf5c99693..b91dd462ba 100644
--- a/dts/include/dt-bindings/clock/imx6sl-clock.h
+++ b/dts/include/dt-bindings/clock/imx6sl-clock.h
@@ -145,6 +145,7 @@
#define IMX6SL_CLK_USDHC4 132
#define IMX6SL_CLK_PLL4_AUDIO_DIV 133
#define IMX6SL_CLK_SPBA 134
-#define IMX6SL_CLK_END 135
+#define IMX6SL_CLK_ENET 135
+#define IMX6SL_CLK_END 136
#endif /* __DT_BINDINGS_CLOCK_IMX6SL_H */
diff --git a/dts/include/dt-bindings/clock/stih415-clks.h b/dts/include/dt-bindings/clock/stih415-clks.h
index 0d2c7397e0..d80caa68ae 100644
--- a/dts/include/dt-bindings/clock/stih415-clks.h
+++ b/dts/include/dt-bindings/clock/stih415-clks.h
@@ -10,6 +10,7 @@
#define CLK_ETH1_PHY 4
/* CLOCKGEN A1 */
+#define CLK_ICN_IF_2 0
#define CLK_GMAC0_PHY 3
#endif
diff --git a/dts/include/dt-bindings/clock/stih416-clks.h b/dts/include/dt-bindings/clock/stih416-clks.h
index 552c779eb6..f9bdbd1356 100644
--- a/dts/include/dt-bindings/clock/stih416-clks.h
+++ b/dts/include/dt-bindings/clock/stih416-clks.h
@@ -10,6 +10,7 @@
#define CLK_ETH1_PHY 4
/* CLOCKGEN A1 */
+#define CLK_ICN_IF_2 0
#define CLK_GMAC0_PHY 3
#endif
diff --git a/dts/include/dt-bindings/pinctrl/dra.h b/dts/include/dt-bindings/pinctrl/dra.h
index 002a2855c0..3d33794e4f 100644
--- a/dts/include/dt-bindings/pinctrl/dra.h
+++ b/dts/include/dt-bindings/pinctrl/dra.h
@@ -30,7 +30,8 @@
#define MUX_MODE14 0xe
#define MUX_MODE15 0xf
-#define PULL_ENA (1 << 16)
+#define PULL_ENA (0 << 16)
+#define PULL_DIS (1 << 16)
#define PULL_UP (1 << 17)
#define INPUT_EN (1 << 18)
#define SLEWCONTROL (1 << 19)
@@ -38,10 +39,10 @@
#define WAKEUP_EVENT (1 << 25)
/* Active pin states */
-#define PIN_OUTPUT 0
+#define PIN_OUTPUT (0 | PULL_DIS)
#define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP)
#define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA)
-#define PIN_INPUT INPUT_EN
+#define PIN_INPUT (INPUT_EN | PULL_DIS)
#define PIN_INPUT_SLEW (INPUT_EN | SLEWCONTROL)
#define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP)
#define PIN_INPUT_PULLDOWN (PULL_ENA | INPUT_EN)
diff --git a/dts/src/arm/am335x-evm.dts b/dts/src/arm/am335x-evm.dts
index ecb267767c..e2156a583d 100644
--- a/dts/src/arm/am335x-evm.dts
+++ b/dts/src/arm/am335x-evm.dts
@@ -529,8 +529,8 @@
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 1 2
>;
- tx-num-evt = <1>;
- rx-num-evt = <1>;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
};
&tps {
diff --git a/dts/src/arm/am335x-evmsk.dts b/dts/src/arm/am335x-evmsk.dts
index ab9a34ce52..80a3b215e7 100644
--- a/dts/src/arm/am335x-evmsk.dts
+++ b/dts/src/arm/am335x-evmsk.dts
@@ -560,8 +560,8 @@
serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */
0 0 1 2
>;
- tx-num-evt = <1>;
- rx-num-evt = <1>;
+ tx-num-evt = <32>;
+ rx-num-evt = <32>;
};
&tscadc {
diff --git a/dts/src/arm/am335x-igep0033.dtsi b/dts/src/arm/am335x-igep0033.dtsi
index 8a0a72dc7d..a1a0cc5eb3 100644
--- a/dts/src/arm/am335x-igep0033.dtsi
+++ b/dts/src/arm/am335x-igep0033.dtsi
@@ -105,10 +105,16 @@
&cpsw_emac0 {
phy_id = <&davinci_mdio>, <0>;
+ phy-mode = "rmii";
};
&cpsw_emac1 {
phy_id = <&davinci_mdio>, <1>;
+ phy-mode = "rmii";
+};
+
+&phy_sel {
+ rmii-clock-ext;
};
&elm {
diff --git a/dts/src/arm/am43x-epos-evm.dts b/dts/src/arm/am43x-epos-evm.dts
index 19f1f7e875..90098f98a5 100644
--- a/dts/src/arm/am43x-epos-evm.dts
+++ b/dts/src/arm/am43x-epos-evm.dts
@@ -319,6 +319,10 @@
phy-mode = "rmii";
};
+&phy_sel {
+ rmii-clock-ext;
+};
+
&i2c0 {
status = "okay";
pinctrl-names = "default";
diff --git a/dts/src/arm/armada-380.dtsi b/dts/src/arm/armada-380.dtsi
index e69bc6759c..4173a8ab34 100644
--- a/dts/src/arm/armada-380.dtsi
+++ b/dts/src/arm/armada-380.dtsi
@@ -16,7 +16,7 @@
/ {
model = "Marvell Armada 380 family SoC";
- compatible = "marvell,armada380", "marvell,armada38x";
+ compatible = "marvell,armada380";
cpus {
#address-cells = <1>;
diff --git a/dts/src/arm/armada-385-db.dts b/dts/src/arm/armada-385-db.dts
index 5bae473182..1af886f1e4 100644
--- a/dts/src/arm/armada-385-db.dts
+++ b/dts/src/arm/armada-385-db.dts
@@ -16,7 +16,7 @@
/ {
model = "Marvell Armada 385 Development Board";
- compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada38x";
+ compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada380";
chosen {
bootargs = "console=ttyS0,115200 earlyprintk";
diff --git a/dts/src/arm/armada-385-rd.dts b/dts/src/arm/armada-385-rd.dts
index 40893255a3..aaca2861dc 100644
--- a/dts/src/arm/armada-385-rd.dts
+++ b/dts/src/arm/armada-385-rd.dts
@@ -17,7 +17,7 @@
/ {
model = "Marvell Armada 385 Reference Design";
- compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada38x";
+ compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada380";
chosen {
bootargs = "console=ttyS0,115200 earlyprintk";
diff --git a/dts/src/arm/armada-385.dtsi b/dts/src/arm/armada-385.dtsi
index f011009bf4..6283d7912f 100644
--- a/dts/src/arm/armada-385.dtsi
+++ b/dts/src/arm/armada-385.dtsi
@@ -16,7 +16,7 @@
/ {
model = "Marvell Armada 385 family SoC";
- compatible = "marvell,armada385", "marvell,armada38x";
+ compatible = "marvell,armada385", "marvell,armada380";
cpus {
#address-cells = <1>;
diff --git a/dts/src/arm/armada-38x.dtsi b/dts/src/arm/armada-38x.dtsi
index 3de364e81b..689fa1a467 100644
--- a/dts/src/arm/armada-38x.dtsi
+++ b/dts/src/arm/armada-38x.dtsi
@@ -20,7 +20,7 @@
/ {
model = "Marvell Armada 38x family SoC";
- compatible = "marvell,armada38x";
+ compatible = "marvell,armada380";
aliases {
gpio0 = &gpio0;
diff --git a/dts/src/arm/at91sam9261.dtsi b/dts/src/arm/at91sam9261.dtsi
index b309c1c6e8..04927db1d6 100644
--- a/dts/src/arm/at91sam9261.dtsi
+++ b/dts/src/arm/at91sam9261.dtsi
@@ -568,24 +568,17 @@
#size-cells = <0>;
#interrupt-cells = <1>;
- slow_rc_osc: slow_rc_osc {
- compatible = "fixed-clock";
+ main_osc: main_osc {
+ compatible = "atmel,at91rm9200-clk-main-osc";
#clock-cells = <0>;
- clock-frequency = <32768>;
- clock-accuracy = <50000000>;
- };
-
- clk32k: slck {
- compatible = "atmel,at91sam9260-clk-slow";
- #clock-cells = <0>;
- clocks = <&slow_rc_osc &slow_xtal>;
+ interrupts-extended = <&pmc AT91_PMC_MOSCS>;
+ clocks = <&main_xtal>;
};
main: mainck {
compatible = "atmel,at91rm9200-clk-main";
#clock-cells = <0>;
- interrupts-extended = <&pmc AT91_PMC_MOSCS>;
- clocks = <&main_xtal>;
+ clocks = <&main_osc>;
};
plla: pllack {
@@ -615,7 +608,7 @@
compatible = "atmel,at91rm9200-clk-master";
#clock-cells = <0>;
interrupts-extended = <&pmc AT91_PMC_MCKRDY>;
- clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
atmel,clk-output-range = <0 94000000>;
atmel,clk-divisors = <1 2 4 0>;
};
@@ -632,7 +625,7 @@
#address-cells = <1>;
#size-cells = <0>;
interrupt-parent = <&pmc>;
- clocks = <&clk32k>, <&main>, <&plla>, <&pllb>;
+ clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>;
prog0: prog0 {
#clock-cells = <0>;
diff --git a/dts/src/arm/at91sam9261ek.dts b/dts/src/arm/at91sam9261ek.dts
index c6683ea8b7..aa35a7aec9 100644
--- a/dts/src/arm/at91sam9261ek.dts
+++ b/dts/src/arm/at91sam9261ek.dts
@@ -20,6 +20,10 @@
reg = <0x20000000 0x4000000>;
};
+ slow_xtal {
+ clock-frequency = <32768>;
+ };
+
main_xtal {
clock-frequency = <18432000>;
};
diff --git a/dts/src/arm/at91sam9n12.dtsi b/dts/src/arm/at91sam9n12.dtsi
index d1b82e6635..b84bac5bad 100644
--- a/dts/src/arm/at91sam9n12.dtsi
+++ b/dts/src/arm/at91sam9n12.dtsi
@@ -132,8 +132,8 @@
<595000000 650000000 3 0>,
<545000000 600000000 0 1>,
<495000000 555000000 1 1>,
- <445000000 500000000 1 2>,
- <400000000 450000000 1 3>;
+ <445000000 500000000 2 1>,
+ <400000000 450000000 3 1>;
};
plladiv: plladivck {
@@ -925,7 +925,7 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00500000 0x00100000>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
- clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>,
+ clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>,
<&uhpck>;
clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
diff --git a/dts/src/arm/at91sam9x5.dtsi b/dts/src/arm/at91sam9x5.dtsi
index 1a57298636..2c0d6ea3ab 100644
--- a/dts/src/arm/at91sam9x5.dtsi
+++ b/dts/src/arm/at91sam9x5.dtsi
@@ -140,8 +140,8 @@
595000000 650000000 3 0
545000000 600000000 0 1
495000000 555000000 1 1
- 445000000 500000000 1 2
- 400000000 450000000 1 3>;
+ 445000000 500000000 2 1
+ 400000000 450000000 3 1>;
};
plladiv: plladivck {
@@ -1045,6 +1045,8 @@
reg = <0x00500000 0x80000
0xf803c000 0x400>;
interrupts = <23 IRQ_TYPE_LEVEL_HIGH 0>;
+ clocks = <&usb>, <&udphs_clk>;
+ clock-names = "hclk", "pclk";
status = "disabled";
ep0 {
@@ -1122,6 +1124,7 @@
compatible = "atmel,at91sam9rl-pwm";
reg = <0xf8034000 0x300>;
interrupts = <18 IRQ_TYPE_LEVEL_HIGH 4>;
+ clocks = <&pwm_clk>;
#pwm-cells = <3>;
status = "disabled";
};
@@ -1153,8 +1156,7 @@
compatible = "atmel,at91rm9200-ohci", "usb-ohci";
reg = <0x00600000 0x100000>;
interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>;
- clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>,
- <&uhpck>;
+ clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>;
clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck";
status = "disabled";
};
diff --git a/dts/src/arm/dra7-evm.dts b/dts/src/arm/dra7-evm.dts
index 4adc28039c..83089540e3 100644
--- a/dts/src/arm/dra7-evm.dts
+++ b/dts/src/arm/dra7-evm.dts
@@ -240,6 +240,7 @@
regulator-name = "ldo3";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
+ regulator-always-on;
regulator-boot-on;
};
diff --git a/dts/src/arm/dra7.dtsi b/dts/src/arm/dra7.dtsi
index c29945e07c..80127638b3 100644
--- a/dts/src/arm/dra7.dtsi
+++ b/dts/src/arm/dra7.dtsi
@@ -773,7 +773,6 @@
clocks = <&qspi_gfclk_div>;
clock-names = "fck";
num-cs = <4>;
- interrupts = <0 343 0x4>;
status = "disabled";
};
@@ -984,6 +983,17 @@
#size-cells = <1>;
status = "disabled";
};
+
+ atl: atl@4843c000 {
+ compatible = "ti,dra7-atl";
+ reg = <0x4843c000 0x3ff>;
+ ti,hwmods = "atl";
+ ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>,
+ <&atl_clkin2_ck>, <&atl_clkin3_ck>;
+ clocks = <&atl_gfclk_mux>;
+ clock-names = "fck";
+ status = "disabled";
+ };
};
};
diff --git a/dts/src/arm/dra7xx-clocks.dtsi b/dts/src/arm/dra7xx-clocks.dtsi
index b03cfe49d2..dc7a292fe9 100644
--- a/dts/src/arm/dra7xx-clocks.dtsi
+++ b/dts/src/arm/dra7xx-clocks.dtsi
@@ -10,26 +10,26 @@
&cm_core_aon_clocks {
atl_clkin0_ck: atl_clkin0_ck {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
};
atl_clkin1_ck: atl_clkin1_ck {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
};
atl_clkin2_ck: atl_clkin2_ck {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
};
atl_clkin3_ck: atl_clkin3_ck {
#clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <0>;
+ compatible = "ti,dra7-atl-clock";
+ clocks = <&atl_gfclk_mux>;
};
hdmi_clkin_ck: hdmi_clkin_ck {
@@ -673,10 +673,12 @@
l3_iclk_div: l3_iclk_div {
#clock-cells = <0>;
- compatible = "fixed-factor-clock";
+ compatible = "ti,divider-clock";
+ ti,max-div = <2>;
+ ti,bit-shift = <4>;
+ reg = <0x0100>;
clocks = <&dpll_core_h12x2_ck>;
- clock-mult = <1>;
- clock-div = <1>;
+ ti,index-power-of-two;
};
l4_root_clk_div: l4_root_clk_div {
@@ -684,7 +686,7 @@
compatible = "fixed-factor-clock";
clocks = <&l3_iclk_div>;
clock-mult = <1>;
- clock-div = <1>;
+ clock-div = <2>;
};
video1_clk2_div: video1_clk2_div {
diff --git a/dts/src/arm/exynos4.dtsi b/dts/src/arm/exynos4.dtsi
index b8ece4be41..17b22e9cc2 100644
--- a/dts/src/arm/exynos4.dtsi
+++ b/dts/src/arm/exynos4.dtsi
@@ -113,7 +113,7 @@
compatible = "arm,cortex-a9-gic";
#interrupt-cells = <3>;
interrupt-controller;
- reg = <0x10490000 0x1000>, <0x10480000 0x100>;
+ reg = <0x10490000 0x10000>, <0x10480000 0x10000>;
};
combiner: interrupt-controller@10440000 {
@@ -554,7 +554,7 @@
interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>;
clocks = <&clock CLK_PWM>;
clock-names = "timers";
- #pwm-cells = <2>;
+ #pwm-cells = <3>;
status = "disabled";
};
diff --git a/dts/src/arm/exynos5420.dtsi b/dts/src/arm/exynos5420.dtsi
index e38532271e..15957227ff 100644
--- a/dts/src/arm/exynos5420.dtsi
+++ b/dts/src/arm/exynos5420.dtsi
@@ -167,7 +167,7 @@
compatible = "samsung,exynos5420-audss-clock";
reg = <0x03810000 0x0C>;
#clock-cells = <1>;
- clocks = <&clock CLK_FIN_PLL>, <&clock CLK_FOUT_EPLL>,
+ clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MAU_EPLL>,
<&clock CLK_SCLK_MAUDIO0>, <&clock CLK_SCLK_MAUPCM0>;
clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in";
};
@@ -260,6 +260,9 @@
mfc_pd: power-domain@10044060 {
compatible = "samsung,exynos4210-pd";
reg = <0x10044060 0x20>;
+ clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>,
+ <&clock CLK_MOUT_USER_ACLK333>;
+ clock-names = "oscclk", "pclk0", "clk0";
};
disp_pd: power-domain@100440C0 {
diff --git a/dts/src/arm/hi3620.dtsi b/dts/src/arm/hi3620.dtsi
index ab1116d086..83a5b8685b 100644
--- a/dts/src/arm/hi3620.dtsi
+++ b/dts/src/arm/hi3620.dtsi
@@ -73,7 +73,7 @@
L2: l2-cache {
compatible = "arm,pl310-cache";
- reg = <0xfc10000 0x100000>;
+ reg = <0x100000 0x100000>;
interrupts = <0 15 4>;
cache-unified;
cache-level = <2>;
diff --git a/dts/src/arm/imx51-babbage.dts b/dts/src/arm/imx51-babbage.dts
index 6bc3243a80..181d77fa2f 100644
--- a/dts/src/arm/imx51-babbage.dts
+++ b/dts/src/arm/imx51-babbage.dts
@@ -315,15 +315,15 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1>;
- fsl,cd-controller;
- fsl,wp-controller;
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
+ wp-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>;
status = "okay";
};
&esdhc2 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc2>;
- cd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ cd-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>;
wp-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>;
status = "okay";
};
@@ -468,8 +468,8 @@
MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5
MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5
MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5
- MX51_PAD_GPIO1_0__SD1_CD 0x20d5
- MX51_PAD_GPIO1_1__SD1_WP 0x20d5
+ MX51_PAD_GPIO1_0__GPIO1_0 0x100
+ MX51_PAD_GPIO1_1__GPIO1_1 0x100
>;
};
diff --git a/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts b/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts
index 75e66c9c61..31cfb7f2b0 100644
--- a/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts
+++ b/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts
@@ -107,7 +107,7 @@
&esdhc1 {
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_esdhc1 &pinctrl_esdhc1_cd>;
- fsl,cd-controller;
+ cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>;
status = "okay";
};
@@ -206,7 +206,7 @@
pinctrl_esdhc1_cd: esdhc1_cd {
fsl,pins = <
- MX51_PAD_GPIO1_0__SD1_CD 0x20d5
+ MX51_PAD_GPIO1_0__GPIO1_0 0xd5
>;
};
diff --git a/dts/src/arm/imx53-m53evk.dts b/dts/src/arm/imx53-m53evk.dts
index d5d146a8b1..c4956b0ffb 100644
--- a/dts/src/arm/imx53-m53evk.dts
+++ b/dts/src/arm/imx53-m53evk.dts
@@ -21,27 +21,25 @@
<0xb0000000 0x20000000>;
};
- soc {
- display1: display@di1 {
- compatible = "fsl,imx-parallel-display";
- interface-pix-fmt = "bgr666";
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_ipu_disp1>;
-
- display-timings {
- 800x480p60 {
- native-mode;
- clock-frequency = <31500000>;
- hactive = <800>;
- vactive = <480>;
- hfront-porch = <40>;
- hback-porch = <88>;
- hsync-len = <128>;
- vback-porch = <33>;
- vfront-porch = <9>;
- vsync-len = <3>;
- vsync-active = <1>;
- };
+ display1: display@di1 {
+ compatible = "fsl,imx-parallel-display";
+ interface-pix-fmt = "bgr666";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_ipu_disp1>;
+
+ display-timings {
+ 800x480p60 {
+ native-mode;
+ clock-frequency = <31500000>;
+ hactive = <800>;
+ vactive = <480>;
+ hfront-porch = <40>;
+ hback-porch = <88>;
+ hsync-len = <128>;
+ vback-porch = <33>;
+ vfront-porch = <9>;
+ vsync-len = <3>;
+ vsync-active = <1>;
};
};
diff --git a/dts/src/arm/imx6dl-hummingboard.dts b/dts/src/arm/imx6dl-hummingboard.dts
index 5373a5f278..c8e51dd41b 100644
--- a/dts/src/arm/imx6dl-hummingboard.dts
+++ b/dts/src/arm/imx6dl-hummingboard.dts
@@ -143,6 +143,14 @@
fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>;
};
+ pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-id {
+ /*
+ * Similar to pinctrl_usbotg_2, but we want it
+ * pulled down for a fixed host connection.
+ */
+ fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+ };
+
pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus {
fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>;
};
@@ -178,6 +186,8 @@
};
&usbotg {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>;
vbus-supply = <&reg_usbotg_vbus>;
status = "okay";
};
diff --git a/dts/src/arm/imx6q-embedsky-e9.dtsi b/dts/src/arm/imx6q-embedsky-e9.dtsi
new file mode 100644
index 0000000000..a29de9f3c4
--- /dev/null
+++ b/dts/src/arm/imx6q-embedsky-e9.dtsi
@@ -0,0 +1,395 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2011 Linaro Ltd.
+ *
+ * The code contained herein is licensed under the GNU General Public
+ * License. You may obtain a copy of the GNU General Public License
+ * Version 2 or later at the following locations:
+ *
+ * http://www.opensource.org/licenses/gpl-license.html
+ * http://www.gnu.org/copyleft/gpl.html
+ */
+
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+
+/ {
+ model = "Embedsky E9";
+ compatible = "embedsky,e9", "fsl,imx6q";
+
+ regulators {
+ compatible = "simple-bus";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ reg_2p5v: regulator@0 {
+ compatible = "regulator-fixed";
+ reg = <0>;
+ regulator-name = "2P5V";
+ regulator-min-microvolt = <2500000>;
+ regulator-max-microvolt = <2500000>;
+ regulator-always-on;
+ };
+
+ reg_3p3v: regulator@1 {
+ compatible = "regulator-fixed";
+ reg = <1>;
+ regulator-name = "3P3V";
+ regulator-min-microvolt = <3300000>;
+ regulator-max-microvolt = <3300000>;
+ regulator-always-on;
+ };
+
+ reg_usb_otg_vbus: regulator@2 {
+ compatible = "regulator-fixed";
+ reg = <2>;
+ regulator-name = "usb_otg_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio3 22 0>;
+ enable-active-high;
+ };
+
+ reg_usb_h1_vbus: regulator@3 {
+ compatible = "regulator-fixed";
+ reg = <3>;
+ regulator-name = "usb_h1_vbus";
+ regulator-min-microvolt = <5000000>;
+ regulator-max-microvolt = <5000000>;
+ gpio = <&gpio1 29 0>;
+ enable-active-high;
+ };
+
+ };
+
+ gpio-keys {
+ compatible = "gpio-keys";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_gpio_keys>;
+
+ power {
+ label = "Power Button";
+ gpios = <&gpio6 31 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_POWER>;
+ };
+
+ volume-up {
+ label = "Volume Up";
+ gpios = <&gpio4 8 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_VOLUMEUP>;
+ };
+
+ volume-down {
+ label = "Volume Down";
+ gpios = <&gpio4 9 GPIO_ACTIVE_LOW>;
+ gpio-key,wakeup;
+ linux,code = <KEY_VOLUMEDOWN>;
+ };
+ };
+
+};
+
+&audmux {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_audmux>;
+ status = "okay";
+};
+
+&fec {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_enet>;
+ phy-mode = "rgmii";
+ phy-supply=<&reg_3p3v>;
+ status = "okay";
+};
+
+&i2c1 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c1>;
+ status = "okay";
+
+};
+
+&i2c2 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c2>;
+ status = "okay";
+};
+
+&i2c3 {
+ clock-frequency = <100000>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_i2c3>;
+ status = "okay";
+};
+
+&iomuxc {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_hog>;
+
+ imx6qdl-embedsky-e9 {
+ pinctrl_hog: hoggrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000
+ MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000
+ MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000
+ MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000
+ MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000
+ MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0
+ MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000
+ MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000
+ MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000
+ >;
+ };
+
+ pinctrl_audmux: audmuxgrp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0
+ MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0
+ MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0
+ MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0
+ >;
+ };
+
+ pinctrl_ecspi1: ecspi1grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1
+ MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1
+ MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1
+ >;
+ };
+
+ pinctrl_enet: enetgrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0
+ MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0
+ MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0
+ MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0
+ MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0
+ MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0
+ MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0
+ MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0
+ MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0
+ MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0
+ MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0
+ MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0
+ MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0
+ MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0
+ MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x4001b0a8
+ MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8
+ MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x4001b0a8
+ >;
+ };
+
+ pinctrl_gpio_keys: gpio_keysgrp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000
+ MX6QDL_PAD_KEY_COL1__KEY_COL1 0x80000000
+ MX6QDL_PAD_KEY_ROW1__KEY_ROW1 0x80000000
+ >;
+ };
+
+ pinctrl_i2c1: i2c1grp {
+ fsl,pins = <
+ MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1
+ MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c2: i2c2grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1
+ MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_i2c3: i2c3grp {
+ fsl,pins = <
+ MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1
+ MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1
+ >;
+ };
+
+ pinctrl_uart1: uart1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1
+ MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart2: uart2grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1
+ MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart3: uart3grp {
+ fsl,pins = <
+ MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1
+ MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_uart4: uart4grp {
+ fsl,pins = <
+ MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1
+ MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1
+ >;
+ };
+
+ pinctrl_usbotg: usbotggrp {
+ fsl,pins = <
+ MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059
+ >;
+ };
+
+ pinctrl_usdhc1: usdhc1grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059
+ MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059
+ MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059
+ MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059
+ MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059
+ MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc2: usdhc2grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059
+ MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059
+ MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059
+ MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059
+ MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059
+ MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059
+ MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071
+ >;
+ };
+
+ pinctrl_usdhc3: usdhc3grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059
+ MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059
+ MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059
+ MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059
+ MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059
+ MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059
+ >;
+ };
+
+ pinctrl_usdhc4: usdhc4grp {
+ fsl,pins = <
+ MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059
+ MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059
+ MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059
+ MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059
+ MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059
+ MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059
+ MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059
+ MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059
+ MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059
+ MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059
+ >;
+ };
+ };
+};
+
+&ldb {
+ status = "okay";
+};
+
+&uart1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart1>;
+ status = "okay";
+};
+
+&uart2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart2>;
+ status = "okay";
+};
+
+&uart3 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart3>;
+ status = "okay";
+};
+
+&uart4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_uart4>;
+ status = "okay";
+};
+
+&usbh1 {
+ vbus-supply = <&reg_usb_h1_vbus>;
+ status = "okay";
+};
+
+&usbotg {
+ vbus-supply = <&reg_usb_otg_vbus>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usbotg>;
+ disable-over-current;
+ status = "okay";
+};
+
+&usdhc1 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc1>;
+ vmmc-supply = <&reg_3p3v>;
+ status = "okay";
+};
+
+&usdhc2 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc2>;
+ cd-gpios = <&gpio1 4 0>;
+ vmmc-supply = <&reg_3p3v>;
+ status = "okay";
+};
+
+&usdhc4 {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_usdhc4>;
+ vmmc-supply = <&reg_3p3v>;
+ non-removable;
+ status = "okay";
+};
+
+&ldb {
+ status = "okay";
+};
+
+&hdmi {
+ status = "okay";
+};
+
+&pcie {
+ status = "okay";
+};
+
+&can1 {
+ status = "okay";
+};
+
+&sata {
+ status = "okay";
+};
+
+&usdhc3 {
+ status = "disabled";
+};
+
+&ecspi1 {
+ status = "disabled";
+};
diff --git a/dts/src/arm/imx6q-gw51xx.dts b/dts/src/arm/imx6q-gw51xx.dts
index af4929aee0..0e1406e58e 100644
--- a/dts/src/arm/imx6q-gw51xx.dts
+++ b/dts/src/arm/imx6q-gw51xx.dts
@@ -11,7 +11,7 @@
/dts-v1/;
#include "imx6q.dtsi"
-#include "imx6qdl-gw54xx.dtsi"
+#include "imx6qdl-gw51xx.dtsi"
/ {
model = "Gateworks Ventana i.MX6 Quad GW51XX";
diff --git a/dts/src/arm/imx6qdl-cubox-i.dtsi b/dts/src/arm/imx6qdl-cubox-i.dtsi
index 25da82a031..e8e781656b 100644
--- a/dts/src/arm/imx6qdl-cubox-i.dtsi
+++ b/dts/src/arm/imx6qdl-cubox-i.dtsi
@@ -12,6 +12,19 @@
pinctrl-0 = <&pinctrl_cubox_i_ir>;
};
+ pwmleds {
+ compatible = "pwm-leds";
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cubox_i_pwm1>;
+
+ front {
+ active-low;
+ label = "imx6:red:front";
+ max-brightness = <248>;
+ pwms = <&pwm1 0 50000>;
+ };
+ };
+
regulators {
compatible = "simple-bus";
@@ -109,6 +122,10 @@
>;
};
+ pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led {
+ fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>;
+ };
+
pinctrl_cubox_i_spdif: cubox-i-spdif {
fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>;
};
@@ -117,6 +134,14 @@
fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>;
};
+ pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id {
+ /*
+ * The Cubox-i pulls this low, but as it's pointless
+ * leaving it as a pull-up, even if it is just 10uA.
+ */
+ fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
+ };
+
pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus {
fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>;
};
@@ -153,6 +178,8 @@
};
&usbotg {
+ pinctrl-names = "default";
+ pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>;
vbus-supply = <&reg_usbotg_vbus>;
status = "okay";
};
diff --git a/dts/src/arm/imx6qdl-gw51xx.dtsi b/dts/src/arm/imx6qdl-gw51xx.dtsi
index 31665adcbf..0db15af41c 100644
--- a/dts/src/arm/imx6qdl-gw51xx.dtsi
+++ b/dts/src/arm/imx6qdl-gw51xx.dtsi
@@ -161,7 +161,7 @@
status = "okay";
pmic: ltc3676@3c {
- compatible = "ltc,ltc3676";
+ compatible = "lltc,ltc3676";
reg = <0x3c>;
regulators {
diff --git a/dts/src/arm/imx6qdl-gw52xx.dtsi b/dts/src/arm/imx6qdl-gw52xx.dtsi
index 367af3ec94..744c8a2d81 100644
--- a/dts/src/arm/imx6qdl-gw52xx.dtsi
+++ b/dts/src/arm/imx6qdl-gw52xx.dtsi
@@ -220,7 +220,7 @@
};
pmic: ltc3676@3c {
- compatible = "ltc,ltc3676";
+ compatible = "lltc,ltc3676";
reg = <0x3c>;
regulators {
@@ -288,7 +288,7 @@
codec: sgtl5000@0a {
compatible = "fsl,sgtl5000";
reg = <0x0a>;
- clocks = <&clks 169>;
+ clocks = <&clks 201>;
VDDA-supply = <&reg_1p8v>;
VDDIO-supply = <&reg_3p3v>;
};
diff --git a/dts/src/arm/imx6qdl-gw53xx.dtsi b/dts/src/arm/imx6qdl-gw53xx.dtsi
index c91b5a6c76..adf150c1be 100644
--- a/dts/src/arm/imx6qdl-gw53xx.dtsi
+++ b/dts/src/arm/imx6qdl-gw53xx.dtsi
@@ -234,7 +234,7 @@
};
pmic: ltc3676@3c {
- compatible = "ltc,ltc3676";
+ compatible = "lltc,ltc3676";
reg = <0x3c>;
regulators {
diff --git a/dts/src/arm/imx6qdl-microsom.dtsi b/dts/src/arm/imx6qdl-microsom.dtsi
index d729d0b15f..79eac6849d 100644
--- a/dts/src/arm/imx6qdl-microsom.dtsi
+++ b/dts/src/arm/imx6qdl-microsom.dtsi
@@ -10,14 +10,6 @@
MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1
>;
};
-
- pinctrl_microsom_usbotg: microsom-usbotg {
- /*
- * Similar to pinctrl_usbotg_2, but we want it
- * pulled down for a fixed host connection.
- */
- fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>;
- };
};
};
@@ -26,8 +18,3 @@
pinctrl-0 = <&pinctrl_microsom_uart1>;
status = "okay";
};
-
-&usbotg {
- pinctrl-names = "default";
- pinctrl-0 = <&pinctrl_microsom_usbotg>;
-};
diff --git a/dts/src/arm/imx6sl.dtsi b/dts/src/arm/imx6sl.dtsi
index 2d4e5285f3..57d4abe03a 100644
--- a/dts/src/arm/imx6sl.dtsi
+++ b/dts/src/arm/imx6sl.dtsi
@@ -686,7 +686,7 @@
compatible = "fsl,imx6sl-fec", "fsl,imx25-fec";
reg = <0x02188000 0x4000>;
interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&clks IMX6SL_CLK_ENET_REF>,
+ clocks = <&clks IMX6SL_CLK_ENET>,
<&clks IMX6SL_CLK_ENET_REF>;
clock-names = "ipg", "ahb";
status = "disabled";
diff --git a/dts/src/arm/kirkwood-guruplug-server-plus.dts b/dts/src/arm/kirkwood-guruplug-server-plus.dts
index c5a1fc75c7..b2d9834bf4 100644
--- a/dts/src/arm/kirkwood-guruplug-server-plus.dts
+++ b/dts/src/arm/kirkwood-guruplug-server-plus.dts
@@ -105,7 +105,6 @@
compatible = "ethernet-phy-id0141.0cb0",
"ethernet-phy-ieee802.3-c22";
reg = <0>;
- phy-connection-type = "rgmii-id";
};
ethphy1: ethernet-phy@1 {
@@ -113,7 +112,6 @@
compatible = "ethernet-phy-id0141.0cb0",
"ethernet-phy-ieee802.3-c22";
reg = <1>;
- phy-connection-type = "rgmii-id";
};
};
@@ -121,6 +119,7 @@
status = "okay";
ethernet0-port@0 {
phy-handle = <&ethphy0>;
+ phy-connection-type = "rgmii-id";
};
};
@@ -128,5 +127,6 @@
status = "okay";
ethernet1-port@0 {
phy-handle = <&ethphy1>;
+ phy-connection-type = "rgmii-id";
};
};
diff --git a/dts/src/arm/omap3-beagle-xm.dts b/dts/src/arm/omap3-beagle-xm.dts
index cf0be66229..1becefce82 100644
--- a/dts/src/arm/omap3-beagle-xm.dts
+++ b/dts/src/arm/omap3-beagle-xm.dts
@@ -251,6 +251,11 @@
codec {
};
};
+
+ twl_power: power {
+ compatible = "ti,twl4030-power-beagleboard-xm", "ti,twl4030-power-idle-osc-off";
+ ti,use_poweroff;
+ };
};
};
@@ -301,6 +306,7 @@
};
&uart3 {
+ interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
pinctrl-names = "default";
pinctrl-0 = <&uart3_pins>;
};
diff --git a/dts/src/arm/omap3-evm-common.dtsi b/dts/src/arm/omap3-evm-common.dtsi
index 8ae8f007c8..c8747c7f1c 100644
--- a/dts/src/arm/omap3-evm-common.dtsi
+++ b/dts/src/arm/omap3-evm-common.dtsi
@@ -50,6 +50,13 @@
gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>;
};
+&twl {
+ twl_power: power {
+ compatible = "ti,twl4030-power-omap3-evm", "ti,twl4030-power-idle";
+ ti,use_poweroff;
+ };
+};
+
&i2c2 {
clock-frequency = <400000>;
};
diff --git a/dts/src/arm/omap3-n900.dts b/dts/src/arm/omap3-n900.dts
index ae8ae3f4f9..b15f1a77d6 100644
--- a/dts/src/arm/omap3-n900.dts
+++ b/dts/src/arm/omap3-n900.dts
@@ -351,6 +351,11 @@
compatible = "ti,twl4030-audio";
ti,enable-vibra = <1>;
};
+
+ twl_power: power {
+ compatible = "ti,twl4030-power-n900";
+ ti,use_poweroff;
+ };
};
&twl_keypad {
diff --git a/dts/src/arm/omap5.dtsi b/dts/src/arm/omap5.dtsi
index 3bfda16c8b..a4ed549888 100644
--- a/dts/src/arm/omap5.dtsi
+++ b/dts/src/arm/omap5.dtsi
@@ -45,7 +45,6 @@
operating-points = <
/* kHz uV */
- 500000 880000
1000000 1060000
1500000 1250000
>;
diff --git a/dts/src/arm/r8a7791.dtsi b/dts/src/arm/r8a7791.dtsi
index 8d7ffaeff6..79f68acfd5 100644
--- a/dts/src/arm/r8a7791.dtsi
+++ b/dts/src/arm/r8a7791.dtsi
@@ -540,9 +540,9 @@
#clock-cells = <0>;
clock-output-names = "sd1";
};
- sd2_clk: sd3_clk@e615007c {
+ sd2_clk: sd3_clk@e615026c {
compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock";
- reg = <0 0xe615007c 0 4>;
+ reg = <0 0xe615026c 0 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "sd2";
diff --git a/dts/src/arm/ste-nomadik-s8815.dts b/dts/src/arm/ste-nomadik-s8815.dts
index f557feb997..90d8b6c7a2 100644
--- a/dts/src/arm/ste-nomadik-s8815.dts
+++ b/dts/src/arm/ste-nomadik-s8815.dts
@@ -4,7 +4,7 @@
*/
/dts-v1/;
-/include/ "ste-nomadik-stn8815.dtsi"
+#include "ste-nomadik-stn8815.dtsi"
/ {
model = "Calao Systems USB-S8815";
diff --git a/dts/src/arm/ste-nomadik-stn8815.dtsi b/dts/src/arm/ste-nomadik-stn8815.dtsi
index d316c955bd..dbcf521b01 100644
--- a/dts/src/arm/ste-nomadik-stn8815.dtsi
+++ b/dts/src/arm/ste-nomadik-stn8815.dtsi
@@ -1,7 +1,9 @@
/*
* Device Tree for the ST-Ericsson Nomadik 8815 STn8815 SoC
*/
-/include/ "skeleton.dtsi"
+
+#include <dt-bindings/gpio/gpio.h>
+#include "skeleton.dtsi"
/ {
#address-cells = <1>;
@@ -842,8 +844,7 @@
bus-width = <4>;
cap-mmc-highspeed;
cap-sd-highspeed;
- cd-gpios = <&gpio3 15 0x1>;
- cd-inverted;
+ cd-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>;
pinctrl-names = "default";
pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>;
vmmc-supply = <&vmmc_regulator>;
diff --git a/dts/src/arm/stih415.dtsi b/dts/src/arm/stih415.dtsi
index d6f254f302..a0f6f75fe3 100644
--- a/dts/src/arm/stih415.dtsi
+++ b/dts/src/arm/stih415.dtsi
@@ -169,8 +169,8 @@
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mii0>;
- clock-names = "stmmaceth";
- clocks = <&clk_s_a1_ls CLK_GMAC0_PHY>;
+ clock-names = "stmmaceth", "sti-ethclk";
+ clocks = <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>;
};
ethernet1: dwmac@fef08000 {
@@ -192,8 +192,8 @@
reset-names = "stmmaceth";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mii1>;
- clock-names = "stmmaceth";
- clocks = <&clk_s_a0_ls CLK_ETH1_PHY>;
+ clock-names = "stmmaceth", "sti-ethclk";
+ clocks = <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>;
};
rc: rc@fe518000 {
diff --git a/dts/src/arm/stih416-b2020-revE.dts b/dts/src/arm/stih416-b2020e.dts
index ba0fa2caaf..ba0fa2caaf 100644
--- a/dts/src/arm/stih416-b2020-revE.dts
+++ b/dts/src/arm/stih416-b2020e.dts
diff --git a/dts/src/arm/stih416.dtsi b/dts/src/arm/stih416.dtsi
index 06473c5d9e..84758d76d0 100644
--- a/dts/src/arm/stih416.dtsi
+++ b/dts/src/arm/stih416.dtsi
@@ -175,8 +175,8 @@
reset-names = "stmmaceth";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mii0>;
- clock-names = "stmmaceth";
- clocks = <&clk_s_a1_ls CLK_GMAC0_PHY>;
+ clock-names = "stmmaceth", "sti-ethclk";
+ clocks = <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>;
};
ethernet1: dwmac@fef08000 {
@@ -197,8 +197,8 @@
reset-names = "stmmaceth";
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_mii1>;
- clock-names = "stmmaceth";
- clocks = <&clk_s_a0_ls CLK_ETH1_PHY>;
+ clock-names = "stmmaceth", "sti-ethclk";
+ clocks = <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>;
};
rc: rc@fe518000 {
diff --git a/fs/Kconfig b/fs/Kconfig
index 3724b34f9a..64fc1176a6 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -41,6 +41,21 @@ config FS_NFS
bool
prompt "nfs support"
+config FS_EFI
+ depends on ARCH_EFI
+ bool
+ prompt "EFI filesystem support"
+ help
+ This filesystem driver provides access to the filesystems provided
+ by the EFI Firmware via the EFI Simple File System Protocol.
+
+config FS_EFIVARFS
+ depends on ARCH_EFI
+ bool
+ prompt "EFI variable filesystem support (efivarfs)"
+ help
+ This filesystem driver provides access to EFI variables.
+
source fs/fat/Kconfig
source fs/ubifs/Kconfig
diff --git a/fs/Makefile b/fs/Makefile
index d3465edfa5..f5aae91a60 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -11,3 +11,5 @@ obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o
obj-$(CONFIG_FS_NFS) += nfs.o parseopt.o
obj-$(CONFIG_FS_BPKFS) += bpkfs.o
obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o
+obj-$(CONFIG_FS_EFI) += efi.o
+obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o
diff --git a/fs/efi.c b/fs/efi.c
new file mode 100644
index 0000000000..f096f91f58
--- /dev/null
+++ b/fs/efi.c
@@ -0,0 +1,563 @@
+/*
+ * efi.c - EFI filesystem mirror driver
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <string.h>
+#include <command.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <wchar.h>
+#include <efi.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+/* Open modes */
+#define EFI_FILE_MODE_READ 0x0000000000000001
+#define EFI_FILE_MODE_WRITE 0x0000000000000002
+#define EFI_FILE_MODE_CREATE 0x8000000000000000
+
+/* File attributes */
+#define EFI_FILE_READ_ONLY 0x0000000000000001
+#define EFI_FILE_HIDDEN 0x0000000000000002
+#define EFI_FILE_SYSTEM 0x0000000000000004
+#define EFI_FILE_RESERVIED 0x0000000000000008
+#define EFI_FILE_DIRECTORY 0x0000000000000010
+#define EFI_FILE_ARCHIVE 0x0000000000000020
+#define EFI_FILE_VALID_ATTR 0x0000000000000037
+
+#define EFI_FILE_HANDLE_REVISION 0x00010000
+struct efi_file_handle {
+ uint64_t Revision;
+ efi_status_t(EFIAPI *open)(struct efi_file_handle *File,
+ struct efi_file_handle **NewHandle, s16 *FileName,
+ uint64_t OpenMode, uint64_t Attributes);
+ efi_status_t(EFIAPI *close)(struct efi_file_handle *File);
+ efi_status_t(EFIAPI *delete)(struct efi_file_handle *File);
+ efi_status_t(EFIAPI *read)(struct efi_file_handle *File, unsigned long *BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *write)(struct efi_file_handle *File,
+ unsigned long *BufferSize, void *Buffer);
+ efi_status_t(EFIAPI *get_position)(struct efi_file_handle *File,
+ uint64_t *Position);
+ efi_status_t(EFIAPI *set_position)(struct efi_file_handle *File,
+ uint64_t Position);
+ efi_status_t(EFIAPI *get_info)(struct efi_file_handle *File,
+ efi_guid_t *InformationType, unsigned long *BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *set_info)(struct efi_file_handle *File,
+ efi_guid_t *InformationType, unsigned long BufferSize,
+ void *Buffer);
+ efi_status_t(EFIAPI *flush)(struct efi_file_handle *File);
+};
+
+#define EFI_FILE_IO_INTERFACE_REVISION 0x00010000
+
+struct efi_file_io_interface {
+ uint64_t Revision;
+ efi_status_t(EFIAPI *open_volume)(
+ struct efi_file_io_interface *This,
+ struct efi_file_handle **Root);
+};
+
+struct efi_file_info {
+ uint64_t Size;
+ uint64_t FileSize;
+ uint64_t PhysicalSize;
+ efi_time_t CreateTime;
+ efi_time_t LastAccessTime;
+ efi_time_t ModificationTime;
+ uint64_t Attribute;
+ s16 FileName[1];
+};
+
+typedef unsigned short wchar_t;
+
+struct efifs_priv {
+ struct efi_file_handle *root_dir;
+ struct efi_file_io_interface *protocol;
+};
+
+struct efifs_file {
+ struct efi_file_handle *entry;
+};
+
+struct efifs_dir {
+ DIR dir;
+ struct efi_file_handle *entries;
+};
+
+static wchar_t *path_to_efi(const char *path)
+{
+ wchar_t *dst;
+ wchar_t *ret;
+
+ if (!*path)
+ return strdup_char_to_wchar("\\");
+
+ dst = strdup_char_to_wchar(path);
+ if (!dst)
+ return NULL;
+
+ ret = dst;
+
+ while (*dst) {
+ if (*dst == '/')
+ *dst = '\\';
+ dst++;
+ }
+
+ return ret;
+}
+
+static int efifs_create(struct device_d *dev, const char *pathname, mode_t mode)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ 0ULL);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret)) {
+ printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ entry->close(entry);
+
+ return 0;
+}
+
+static int efifs_unlink(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0ULL);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ efiret = entry->delete(entry);
+ if (EFI_ERROR(efiret))
+ return -efi_errno(efiret);
+
+ return 0;
+}
+
+static int efifs_mkdir(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path = path_to_efi(pathname);
+ struct efi_file_handle *entry;
+ efi_status_t efiret;
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ EFI_FILE_DIRECTORY);
+
+ free(efi_path);
+
+ if (EFI_ERROR(efiret)) {
+ printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ entry->close(entry);
+
+ return 0;
+}
+
+static int efifs_rmdir(struct device_d *dev, const char *pathname)
+{
+ return efifs_unlink(dev, pathname);
+}
+
+static int efifs_open(struct device_d *dev, FILE *f, const char *filename)
+{
+ struct efifs_priv *priv = dev->priv;
+ efi_status_t efiret;
+ struct efifs_file *ufile;
+ wchar_t *efi_path = path_to_efi(filename);
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ uint64_t efimode = EFI_FILE_MODE_READ;
+ int ret;
+
+ ufile = xzalloc(sizeof(*ufile));
+
+ if (f->flags & O_ACCMODE)
+ efimode |= EFI_FILE_MODE_WRITE;
+
+ efiret = priv->root_dir->open(priv->root_dir, &ufile->entry, efi_path,
+ efimode, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to Open %s: %s\n", __func__,
+ filename, efi_strerror(efiret));
+ free(ufile);
+ return -efi_errno(efiret);
+ }
+
+ free(efi_path);
+
+ info = xzalloc(1024);
+ efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo %s: %s\n", __func__,
+ filename, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ f->size = info->FileSize;
+
+ free(info);
+ f->inode = ufile;
+
+ return 0;
+out:
+ free(info);
+ free(ufile);
+ return ret;
+}
+
+static int efifs_close(struct device_d *dev, FILE *f)
+{
+ struct efifs_file *ufile = f->inode;
+
+ ufile->entry->close(ufile->entry);
+
+ free(ufile);
+
+ return 0;
+}
+
+static int efifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ unsigned long bufsize = insize;
+
+ efiret = ufile->entry->read(ufile->entry, &bufsize, buf);
+ if (EFI_ERROR(efiret)) {
+ return -efi_errno(efiret);
+ }
+
+ return bufsize;
+}
+
+static int efifs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ unsigned long bufsize = insize;
+
+ efiret = ufile->entry->write(ufile->entry, &bufsize, (void *)buf);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to write: %s\n", __func__, efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ return bufsize;
+}
+
+static loff_t efifs_lseek(struct device_d *dev, FILE *f, loff_t pos)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+
+ f->pos = pos;
+
+ efiret = ufile->entry->set_position(ufile->entry, pos);
+ if (EFI_ERROR(efiret)) {
+ return -efi_errno(efiret);
+ }
+
+ return f->pos;
+}
+
+static int efifs_truncate(struct device_d *dev, FILE *f, unsigned long size)
+{
+ struct efifs_file *ufile = f->inode;
+ efi_status_t efiret;
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ int ret;
+
+ info = xzalloc(1024);
+
+ efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo: %s\n", __func__, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ if (size > info->FileSize)
+ return 0;
+
+ info->FileSize = size;
+
+ efiret = ufile->entry->set_info(ufile->entry, &efi_file_info_id, bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to SetInfo: %s\n", __func__, efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ return 0;
+out:
+ return ret;
+}
+
+static DIR *efifs_opendir(struct device_d *dev, const char *pathname)
+{
+ struct efifs_priv *priv = dev->priv;
+ efi_status_t efiret;
+ struct efifs_dir *udir;
+ wchar_t *efi_path = path_to_efi(pathname);
+
+ udir = xzalloc(sizeof(*udir));
+
+ efiret = priv->root_dir->open(priv->root_dir, &udir->entries, efi_path, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ free(udir);
+ return NULL;
+ }
+
+ free(efi_path);
+
+ return &udir->dir;
+}
+
+static struct dirent *efifs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
+ efi_status_t efiret;
+ unsigned long bufsize = 256;
+ s16 buf[256];
+ struct efi_file_info *f;
+
+ efiret = udir->entries->read(udir->entries, &bufsize, buf);
+ if (EFI_ERROR(efiret) || bufsize == 0)
+ return NULL;
+
+ f = (struct efi_file_info *)buf;
+
+ strcpy_wchar_to_char(dir->d.d_name, f->FileName);
+
+ return &dir->d;
+}
+
+static int efifs_closedir(struct device_d *dev, DIR *dir)
+{
+ struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir);
+
+ udir->entries->close(udir->entries);
+
+ free(dir);
+
+ return 0;
+}
+
+static int efifs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ struct efifs_priv *priv = dev->priv;
+ wchar_t *efi_path;
+ efi_status_t efiret;
+ struct efi_file_handle *entry;
+ struct efi_file_info *info;
+ unsigned long bufsize = 1024;
+ int ret;
+
+ info = xzalloc(1024);
+
+ efi_path = path_to_efi(filename);
+
+ efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, EFI_FILE_MODE_READ, 0ULL);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to Open %s: %s\n", __func__, filename,
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out_free;
+ }
+
+ efiret = entry->get_info(entry, &efi_file_info_id, &bufsize, info);
+ if (EFI_ERROR(efiret)) {
+ pr_err("%s: unable to GetInfo %s: %s\n", __func__, filename,
+ efi_strerror(efiret));
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ s->st_size = info->FileSize;
+ s->st_mode = 00555;
+
+ if (!info->Attribute & EFI_FILE_READ_ONLY)
+ s->st_mode |= 00222;
+
+ if (info->Attribute & EFI_FILE_DIRECTORY)
+ s->st_mode |= S_IFDIR;
+ else
+ s->st_mode |= S_IFREG;
+
+ ret = 0;
+out:
+ entry->close(entry);
+out_free:
+ free(efi_path);
+ free(info);
+
+ return ret;
+}
+
+static int efifs_symlink(struct device_d *dev, const char *pathname,
+ const char *newpath)
+{
+ return -EROFS;
+}
+
+static int efifs_readlink(struct device_d *dev, const char *pathname,
+ char *buf, size_t bufsiz)
+{
+ return -ENOENT;
+}
+
+static int efifs_probe(struct device_d *dev)
+{
+ struct fs_device_d *fsdev = dev_to_fs_device(dev);
+ struct efifs_priv *priv;
+ efi_status_t efiret;
+ struct efi_file_handle *file;
+ struct device_d *efi = get_device_by_name(fsdev->backingstore);
+ struct efi_device *udev = container_of(efi, struct efi_device, dev);
+
+ priv = xzalloc(sizeof(struct efifs_priv));
+ priv->protocol = udev->protocol;
+ dev->priv = priv;
+ dev->parent = &udev->dev;
+
+ efiret = priv->protocol->open_volume(priv->protocol, &file);
+ if (EFI_ERROR(efiret)) {
+ dev_err(dev, "failed to open volume: %s\n", efi_strerror(efiret));
+ return -efi_errno(efiret);
+ }
+
+ priv->root_dir = file;
+
+ return 0;
+}
+
+static void efifs_remove(struct device_d *dev)
+{
+ free(dev->priv);
+}
+
+static struct fs_driver_d efifs_driver = {
+ .create = efifs_create,
+ .unlink = efifs_unlink,
+ .open = efifs_open,
+ .close = efifs_close,
+ .truncate = efifs_truncate,
+ .read = efifs_read,
+ .write = efifs_write,
+ .lseek = efifs_lseek,
+ .mkdir = efifs_mkdir,
+ .rmdir = efifs_rmdir,
+ .opendir = efifs_opendir,
+ .readdir = efifs_readdir,
+ .closedir = efifs_closedir,
+ .stat = efifs_stat,
+ .symlink = efifs_symlink,
+ .readlink = efifs_readlink,
+ .drv = {
+ .probe = efifs_probe,
+ .remove = efifs_remove,
+ .name = "efifs",
+ }
+};
+
+static int efifs_init(void)
+{
+ return register_fs_driver(&efifs_driver);
+}
+
+coredevice_initcall(efifs_init);
+
+static int index;
+
+int efi_fs_probe(struct efi_device *efidev)
+{
+ char *path, *device;
+ int ret;
+ struct efi_file_io_interface *volume;
+
+ if (efi_loaded_image)
+ BS->handle_protocol(efi_loaded_image->device_handle,
+ &efi_simple_file_system_protocol_guid, (void*)&volume);
+
+ if (efidev->protocol == volume)
+ path = xstrdup("/boot");
+ else
+ path = asprintf("/efi%d", index);
+ device = asprintf("%s", dev_name(&efidev->dev));
+
+ ret = make_directory(path);
+ if (ret)
+ goto out;
+
+ ret = mount(device, "efifs", path, NULL);
+ if (ret)
+ goto out;
+
+ index++;
+
+ dev_info(&efidev->dev, "mounted on %s\n", path);
+
+ ret = 0;
+out:
+ free(path);
+ free(device);
+
+ return ret;
+}
+
+static struct efi_driver efi_fs_driver = {
+ .driver = {
+ .name = "efi-fs",
+ },
+ .probe = efi_fs_probe,
+ .guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID,
+};
+device_efi_driver(efi_fs_driver);
diff --git a/fs/efivarfs.c b/fs/efivarfs.c
new file mode 100644
index 0000000000..58c637ef19
--- /dev/null
+++ b/fs/efivarfs.c
@@ -0,0 +1,340 @@
+/*
+ * ramfs.c - a malloc based filesystem
+ *
+ * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <driver.h>
+#include <init.h>
+#include <malloc.h>
+#include <fs.h>
+#include <string.h>
+#include <errno.h>
+#include <linux/stat.h>
+#include <xfuncs.h>
+#include <fcntl.h>
+#include <efi.h>
+#include <wchar.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <mach/efi.h>
+#include <mach/efi-device.h>
+
+struct efivarfs_priv {
+ struct efi_file_handle *root_dir;
+ struct efi_file_io_interface *protocol;
+};
+
+static int char_to_nibble(char c)
+{
+ int ret = tolower(c);
+
+ return ret <= '9' ? ret - '0' : ret - 'a' + 10;
+}
+
+static int read_byte_str(const char *str, u8 *out)
+{
+ if (!isxdigit(*str) || !isxdigit(*(str + 1)))
+ return -EINVAL;
+
+ *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1));
+
+ return 0;
+}
+
+int efi_guid_parse(const char *str, efi_guid_t *guid)
+{
+ int i, ret;
+ u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 };
+
+ for (i = 0; i < 16; i++) {
+ ret = read_byte_str(str, &guid->b[idx[i]]);
+ if (ret)
+ return ret;
+ str += 2;
+
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ if (*str != '-')
+ return -EINVAL;
+ str++;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name)
+{
+ int len, ret;
+ const char *guidstr;
+ s16 *varname;
+ int i;
+
+ if (*filename == '/')
+ filename++;
+
+ len = strlen(filename);
+
+ if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"))
+ return -EINVAL;
+
+ guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx");
+ if (*guidstr != '-')
+ return -EINVAL;
+
+ guidstr++;
+
+ ret = efi_guid_parse(guidstr, vendor);
+
+ varname = xzalloc((guidstr - filename) * sizeof(s16));
+
+ for (i = 0; i < guidstr - filename - 1; i++)
+ varname[i] = filename[i];
+
+ *name = varname;
+
+ return 0;
+}
+
+struct efivars_file {
+ void *buf;
+ unsigned long size;
+ efi_guid_t vendor;
+ s16 *name;
+};
+
+static int efivarfs_open(struct device_d *dev, FILE *f, const char *filename)
+{
+ struct efivars_file *efile;
+ efi_status_t efiret;
+ int ret;
+ uint32_t attributes;
+
+ efile = xzalloc(sizeof(*efile));
+
+ ret = efivarfs_parse_filename(filename, &efile->vendor, &efile->name);
+ if (ret)
+ return -ENOENT;
+
+ efiret = RT->get_variable(efile->name, &efile->vendor, &attributes, &efile->size, NULL);
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) {
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ efile->buf = malloc(efile->size + sizeof(uint32_t));
+ if (!efile->buf) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ efiret = RT->get_variable(efile->name, &efile->vendor, NULL, &efile->size,
+ efile->buf + sizeof(uint32_t));
+ if (EFI_ERROR(efiret)) {
+ ret = -efi_errno(efiret);
+ goto out;
+ }
+
+ *(uint32_t *)efile->buf = attributes;
+
+ f->size = efile->size + sizeof(uint32_t);
+ f->inode = efile;
+
+ return 0;
+
+out:
+ free(efile->buf);
+ free(efile);
+
+ return ret;
+}
+
+static int efivarfs_close(struct device_d *dev, FILE *f)
+{
+ struct efivars_file *efile = f->inode;
+
+ free(efile->buf);
+ free(efile);
+
+ return 0;
+}
+
+static int efivarfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
+{
+ struct efivars_file *efile = f->inode;
+
+ memcpy(buf, efile->buf + f->pos, insize);
+
+ return insize;
+}
+
+static loff_t efivarfs_lseek(struct device_d *dev, FILE *f, loff_t pos)
+{
+ f->pos = pos;
+
+ return f->pos;
+}
+
+struct efivarfs_dir_entry {
+ char *name;
+ struct efivarfs_dir_entry *next;
+};
+
+struct efivarfs_dir {
+ struct efivarfs_dir_entry *first;
+ struct efivarfs_dir_entry *current;
+ DIR dir;
+};
+
+static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname)
+{
+ efi_status_t efiret;
+ efi_guid_t vendor;
+ s16 name[1024];
+ struct efivarfs_dir *edir;
+ unsigned long size;
+ unsigned char *name8;
+
+ name[0] = 0;
+
+ edir = xzalloc(sizeof(*edir));
+
+ while (1) {
+ struct efivarfs_dir_entry *entry;
+
+ size = sizeof(name);
+ efiret = RT->get_next_variable(&size, name, &vendor);
+ if (EFI_ERROR(efiret))
+ break;
+
+ entry = xzalloc(sizeof(*entry));
+ name8 = strdup_wchar_to_char(name);
+
+ entry->name = asprintf("%s-%pUl", name8, &vendor);
+
+ free(name8);
+
+ if (!edir->first)
+ edir->first = entry;
+
+ if (edir->current)
+ edir->current->next = entry;
+
+ edir->current = entry;
+ }
+
+ edir->current = edir->first;
+
+ return &edir->dir;
+}
+
+static struct dirent *efivarfs_readdir(struct device_d *dev, DIR *dir)
+{
+ struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
+
+ if (!edir->current)
+ return NULL;
+
+ strcpy(dir->d.d_name, edir->current->name);
+
+ edir->current = edir->current->next;
+
+ return &dir->d;
+}
+
+static int efivarfs_closedir(struct device_d *dev, DIR *dir)
+{
+ struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir);
+ struct efivarfs_dir_entry *entry;
+
+ entry = edir->first;
+
+ while (entry) {
+ struct efivarfs_dir_entry *tmp;
+ free(entry->name);
+ tmp = entry->next;
+ free(entry);
+ entry = tmp;
+ }
+
+ free(edir);
+
+ return 0;
+}
+
+static int efivarfs_stat(struct device_d *dev, const char *filename, struct stat *s)
+{
+ efi_guid_t vendor;
+ s16 *name;
+ efi_status_t efiret;
+ unsigned long size = 0;
+ int ret;
+
+ ret = efivarfs_parse_filename(filename, &vendor, &name);
+ if (ret)
+ return -ENOENT;
+
+ efiret = RT->get_variable(name, &vendor, NULL, &size, NULL);
+
+ free(name);
+
+ if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL)
+ return -efi_errno(efiret);
+
+ s->st_mode = 00666 | S_IFREG;
+ s->st_size = size;
+
+ return 0;
+}
+
+static int efivarfs_probe(struct device_d *dev)
+{
+ return 0;
+}
+
+static void efivarfs_remove(struct device_d *dev)
+{
+ free(dev->priv);
+}
+
+static struct fs_driver_d efivarfs_driver = {
+ .open = efivarfs_open,
+ .close = efivarfs_close,
+ .read = efivarfs_read,
+ .lseek = efivarfs_lseek,
+ .opendir = efivarfs_opendir,
+ .readdir = efivarfs_readdir,
+ .closedir = efivarfs_closedir,
+ .stat = efivarfs_stat,
+ .drv = {
+ .probe = efivarfs_probe,
+ .remove = efivarfs_remove,
+ .name = "efivarfs",
+ }
+};
+
+static int efivarfs_init(void)
+{
+ return register_fs_driver(&efivarfs_driver);
+}
+
+coredevice_initcall(efivarfs_init);
diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c
index ceb965f492..ab0e6b5fbc 100644
--- a/fs/ext4/ext4_common.c
+++ b/fs/ext4/ext4_common.c
@@ -45,12 +45,13 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
struct ext4_extent_idx *index;
unsigned long long block;
struct ext_filesystem *fs = data->fs;
+ int blksz = EXT2_BLOCK_SIZE(data);
int i, ret;
while (1) {
index = (struct ext4_extent_idx *)(ext_block + 1);
- if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
+ if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC)
return 0;
if (ext_block->eh_depth == 0)
@@ -58,17 +59,17 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data
i = -1;
do {
i++;
- if (i >= le32_to_cpu(ext_block->eh_entries))
+ if (i >= le16_to_cpu(ext_block->eh_entries))
break;
- } while (fileblock > le32_to_cpu(index[i].ei_block));
+ } while (fileblock >= le32_to_cpu(index[i].ei_block));
if (--i < 0)
return 0;
- block = le32_to_cpu(index[i].ei_leaf_hi);
+ block = le16_to_cpu(index[i].ei_leaf_hi);
block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo);
- ret = ext4fs_devread(fs, block << log2_blksz, 0, fs->blksz, buf);
+ ret = ext4fs_devread(fs, block << log2_blksz, 0, blksz, buf);
if (ret)
return NULL;
else
@@ -186,18 +187,18 @@ long int read_allocated_block(struct ext2fs_node *node, int fileblock)
do {
i++;
- if (i >= le32_to_cpu(ext_block->eh_entries))
+ if (i >= le16_to_cpu(ext_block->eh_entries))
break;
} while (fileblock >= le32_to_cpu(extent[i].ee_block));
if (--i >= 0) {
fileblock -= le32_to_cpu(extent[i].ee_block);
- if (fileblock >= le32_to_cpu(extent[i].ee_len)) {
+ if (fileblock >= le16_to_cpu(extent[i].ee_len)) {
free(buf);
return 0;
}
- start = le32_to_cpu(extent[i].ee_start_hi);
+ start = le16_to_cpu(extent[i].ee_start_hi);
start = (start << 32) +
le32_to_cpu(extent[i].ee_start_lo);
free(buf);
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index e65ef585a2..f8094d0608 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -167,7 +167,7 @@ static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t ins
ret = f_write(f_file, buf, insize, &outsize);
- debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file);
+ debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file);
if (ret)
return ret;
@@ -260,7 +260,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize)
ret = f_read(f_file, buf, insize, &outsize);
- debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file);
+ debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file);
if (ret)
return ret;
diff --git a/fs/fs.c b/fs/fs.c
index dd410b731a..fd3d353588 100644
--- a/fs/fs.c
+++ b/fs/fs.c
@@ -34,78 +34,6 @@
#include <libgen.h>
#include <block.h>
-void *read_file(const char *filename, size_t *size)
-{
- int fd;
- struct stat s;
- void *buf = NULL;
- const char *tmpfile = "/.read_file_tmp";
- int ret;
-
-again:
- if (stat(filename, &s))
- return NULL;
-
- if (s.st_size == FILESIZE_MAX) {
- ret = copy_file(filename, tmpfile, 0);
- if (ret)
- return NULL;
- filename = tmpfile;
- goto again;
- }
-
- buf = xzalloc(s.st_size + 1);
-
- fd = open(filename, O_RDONLY);
- if (fd < 0)
- goto err_out;
-
- ret = read_full(fd, buf, s.st_size);
- if (ret < 0)
- goto err_out1;
-
- close(fd);
-
- if (size)
- *size = s.st_size;
-
- if (filename == tmpfile)
- unlink(tmpfile);
-
- return buf;
-
-err_out1:
- close(fd);
-err_out:
- free(buf);
-
- if (filename == tmpfile)
- unlink(tmpfile);
-
- return NULL;
-}
-
-EXPORT_SYMBOL(read_file);
-
-int write_file(const char *filename, void *buf, size_t size)
-{
- int fd, ret;
-
- fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT);
- if (fd < 0)
- return fd;
-
- ret = write_full(fd, buf, size);
-
- close(fd);
-
- if (ret < 0)
- return ret;
-
- return 0;
-}
-EXPORT_SYMBOL(write_file);
-
char *mkmodestr(unsigned long mode, char *str)
{
static const char *l = "xwr";
diff --git a/fs/uimagefs.c b/fs/uimagefs.c
index 6547b7cb77..63931c2d7d 100644
--- a/fs/uimagefs.c
+++ b/fs/uimagefs.c
@@ -17,6 +17,7 @@
#include <uimagefs.h>
#include <libbb.h>
#include <rtc.h>
+#include <libfile.h>
static bool uimagefs_is_data_file(struct uimagefs_handle_data *d)
{
diff --git a/images/.gitignore b/images/.gitignore
index ec9e3c0bc6..d27e71a0c8 100644
--- a/images/.gitignore
+++ b/images/.gitignore
@@ -14,6 +14,8 @@
*.t30img.cfg
*.t124img
*.t124img.cfg
+*.mlo
+*.mlospi
pbl.lds
barebox.x
barebox.z
diff --git a/images/Makefile b/images/Makefile
index 740c197754..738fcb6bd3 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -118,5 +118,5 @@ images: $(addprefix $(obj)/, $(image-y)) FORCE
clean-files := *.pbl *.pblb *.pblx *.map start_*.imximg *.img barebox.z start_*.kwbimg \
start_*.kwbuartimg *.socfpgaimg *.mlo *.t20img *.t20img.cfg *.t30img \
- *.t30img.cfg *.t124img *.t124img.cfg
+ *.t30img.cfg *.t124img *.t124img.cfg *.mlospi *.mlo
clean-files += pbl.lds
diff --git a/images/Makefile.am33xx b/images/Makefile.am33xx
index dacc2d123c..fa1f848816 100644
--- a/images/Makefile.am33xx
+++ b/images/Makefile.am33xx
@@ -11,9 +11,17 @@ pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sdram
FILE_barebox-am33xx-phytec-phycore.img = start_am33xx_phytec_phycore_sdram.pblx
am33xx-barebox-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore.img
-pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram
-FILE_barebox-am33xx-phytec-phycore-mlo.img = start_am33xx_phytec_phycore_sram.pblx.mlo
-am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo.img
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x256m16
+FILE_barebox-am33xx-phytec-phycore-mlo-1x256m16.img = start_am33xx_phytec_phycore_sram_1x256m16.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x256m16.img
+
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x128m16
+FILE_barebox-am33xx-phytec-phycore-mlo-1x128m16.img = start_am33xx_phytec_phycore_sram_1x128m16.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x128m16.img
+
+pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x512m16
+FILE_barebox-am33xx-phytec-phycore-mlo-1x512m16.img = start_am33xx_phytec_phycore_sram_1x512m16.pblx.mlo
+am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x512m16.img
pblx-$(CONFIG_MACH_BEAGLEBONE) += start_am33xx_beaglebone_sdram
FILE_barebox-am33xx-beaglebone.img = start_am33xx_beaglebone_sdram.pblx
diff --git a/images/Makefile.imx b/images/Makefile.imx
index 1d0edd2fda..5ff72957c6 100644
--- a/images/Makefile.imx
+++ b/images/Makefile.imx
@@ -92,7 +92,6 @@ image-$(CONFIG_MACH_TQMA6X) += barebox-tq-tqma6q-mba6x.img
pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib
CFG_start_phytec_pbab01_4gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg
-imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib.pblx.imximg
FILE_barebox-phytec-pbab01-4gib.img = start_phytec_pbab01_4gib.pblx.imximg
image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-4gib.img
@@ -108,13 +107,11 @@ image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-1gib.img
pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib
CFG_start_phytec_pbab01dl_1gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg
-imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib.pblx.imximg
FILE_barebox-phytec-pbab01dl-1gib.img = start_phytec_pbab01dl_1gib.pblx.imximg
image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01dl-1gib.img
pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb
CFG_start_phytec_pbab01s_512mb.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg
-imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb.pblx.imximg
FILE_barebox-phytec-pbab01s-512mb.img = start_phytec_pbab01s_512mb.pblx.imximg
image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01s-512mb.img
@@ -125,13 +122,11 @@ image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6s.img
pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_micron
CFG_start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-micron.imxcfg
-imximage-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg
FILE_barebox-dfi-fs700-m60-6q-micron.img = start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg
image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-micron.img
pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_nanya
CFG_start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-nanya.imxcfg
-imximage-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg
FILE_barebox-dfi-fs700-m60-6q-nanya.img = start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg
image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-nanya.img
@@ -175,6 +170,11 @@ CFG_start_variscite_custom.pblx.imximg = $(board)/variscite-mx6/flash-header-var
FILE_barebox-variscite-custom.img = start_variscite_custom.pblx.imximg
image-$(CONFIG_MACH_VARISCITE_MX6) += barebox-variscite-custom.img
+pblx-$(CONFIG_MACH_EMBEDSKY_E9) += start_imx6q_embedsky_e9
+CFG_start_imx6q_embedsky_e9.pblx.imximg = $(board)/embedsky-e9/flash-header-e9.imxcfg
+FILE_barebox-freescale-imx6q-embedsky-e9.img = start_imx6q_embedsky_e9.pblx.imximg
+image-$(CONFIG_MACH_EMBEDSKY_E9) += barebox-freescale-imx6q-embedsky-e9.img
+
pblx-$(CONFIG_MACH_EMBEST_RIOTBOARD) += start_imx6s_riotboard
CFG_start_imx6s_riotboard.pblx.imximg = $(board)/embest-riotboard/flash-header-embest-riotboard.imxcfg
FILE_barebox-embest-imx6s-riotboard.img = start_imx6s_riotboard.pblx.imximg
diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h
index 5dabda3fbb..66abff30fa 100644
--- a/include/asm-generic/barebox.lds.h
+++ b/include/asm-generic/barebox.lds.h
@@ -53,6 +53,12 @@
KEEP(*(.dtb.rodata.*)); \
__dtb_end = .;
+#define BAREBOX_IMD \
+ KEEP(*(.barebox_imd_start)) \
+ KEEP(*(.barebox_imd_1*)) \
+ *(.barebox_imd_0*) \
+ KEEP(*(.barebox_imd_end))
+
#if defined(CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE) && \
CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE
#define MAX_BARE_INIT_SIZE CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE
diff --git a/include/block.h b/include/block.h
index 872a4c1bba..91377679b0 100644
--- a/include/block.h
+++ b/include/block.h
@@ -9,6 +9,7 @@ struct block_device;
struct block_device_ops {
int (*read)(struct block_device *, void *buf, int block, int num_blocks);
int (*write)(struct block_device *, const void *buf, int block, int num_blocks);
+ int (*flush)(struct block_device *);
};
struct chunk;
diff --git a/include/console.h b/include/console.h
index 6da0199aba..97a406d9c9 100644
--- a/include/console.h
+++ b/include/console.h
@@ -39,11 +39,14 @@ struct console_device {
int (*tstc)(struct console_device *cdev);
void (*putc)(struct console_device *cdev, char c);
+ int (*puts)(struct console_device *cdev, const char *s);
int (*getc)(struct console_device *cdev);
int (*setbrg)(struct console_device *cdev, int baudrate);
void (*flush)(struct console_device *cdev);
int (*set_mode)(struct console_device *cdev, enum console_mode mode);
+ char *devname;
+
struct list_head list;
unsigned char f_active;
diff --git a/include/efi.h b/include/efi.h
new file mode 100644
index 0000000000..4ad9f69237
--- /dev/null
+++ b/include/efi.h
@@ -0,0 +1,621 @@
+#ifndef _LINUX_EFI_H
+#define _LINUX_EFI_H
+
+/*
+ * Extensible Firmware Interface
+ * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co.
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
+ */
+#include <linux/string.h>
+#include <linux/types.h>
+
+#ifdef CONFIG_ARCH_EFI
+#define EFIAPI __attribute__((ms_abi))
+#else
+#define EFIAPI
+#endif
+
+struct efi_device_path;
+
+#define EFI_SUCCESS 0
+#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_VOLUME_CORRUPTED ( 10 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_VOLUME_FULL ( 11 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_MEDIA ( 12 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_MEDIA_CHANGED ( 13 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_FOUND ( 14 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ACCESS_DENIED ( 15 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_RESPONSE ( 16 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NO_MAPPING ( 17 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TIMEOUT ( 18 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_NOT_STARTED ( 19 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ALREADY_STARTED ( 20 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ABORTED ( 21 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_ICMP_ERROR ( 22 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_TFTP_ERROR ( 23 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_PROTOCOL_ERROR ( 24 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INCOMPATIBLE_VERSION ( 25 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_SECURITY_VIOLATION ( 26 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_CRC_ERROR ( 27 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_END_OF_MEDIA ( 28 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_END_OF_FILE ( 31 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_INVALID_LANGUAGE ( 32 | (1UL << (BITS_PER_LONG-1)))
+#define EFI_COMPROMISED_DATA ( 33 | (1UL << (BITS_PER_LONG-1)))
+
+#define EFI_ERROR(a) (((signed long) a) < 0)
+
+typedef unsigned long efi_status_t;
+typedef u8 efi_bool_t;
+typedef u16 efi_char16_t; /* UNICODE character */
+typedef u64 efi_physical_addr_t;
+typedef void *efi_handle_t;
+
+
+typedef struct {
+ u8 b[16];
+} efi_guid_t;
+
+#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \
+((efi_guid_t) \
+{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
+ (b) & 0xff, ((b) >> 8) & 0xff, \
+ (c) & 0xff, ((c) >> 8) & 0xff, \
+ (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
+
+/*
+ * Generic EFI table header
+ */
+typedef struct {
+ u64 signature;
+ u32 revision;
+ u32 headersize;
+ u32 crc32;
+ u32 reserved;
+} efi_table_hdr_t;
+
+/*
+ * Memory map descriptor:
+ */
+
+/* Memory types: */
+#define EFI_RESERVED_TYPE 0
+#define EFI_LOADER_CODE 1
+#define EFI_LOADER_DATA 2
+#define EFI_BOOT_SERVICES_CODE 3
+#define EFI_BOOT_SERVICES_DATA 4
+#define EFI_RUNTIME_SERVICES_CODE 5
+#define EFI_RUNTIME_SERVICES_DATA 6
+#define EFI_CONVENTIONAL_MEMORY 7
+#define EFI_UNUSABLE_MEMORY 8
+#define EFI_ACPI_RECLAIM_MEMORY 9
+#define EFI_ACPI_MEMORY_NVS 10
+#define EFI_MEMORY_MAPPED_IO 11
+#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
+#define EFI_PAL_CODE 13
+#define EFI_MAX_MEMORY_TYPE 14
+
+/* Attribute values: */
+#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
+#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
+#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
+#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
+#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
+#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
+#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
+#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
+#define EFI_MEMORY_DESCRIPTOR_VERSION 1
+
+#define EFI_PAGE_SHIFT 12
+#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT)
+
+/*
+ * Allocation types for calls to boottime->allocate_pages.
+ */
+#define EFI_ALLOCATE_ANY_PAGES 0
+#define EFI_ALLOCATE_MAX_ADDRESS 1
+#define EFI_ALLOCATE_ADDRESS 2
+#define EFI_MAX_ALLOCATE_TYPE 3
+
+typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
+
+/*
+ * Types and defines for Time Services
+ */
+#define EFI_TIME_ADJUST_DAYLIGHT 0x1
+#define EFI_TIME_IN_DAYLIGHT 0x2
+#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
+
+typedef struct {
+ u16 year;
+ u8 month;
+ u8 day;
+ u8 hour;
+ u8 minute;
+ u8 second;
+ u8 pad1;
+ u32 nanosecond;
+ s16 timezone;
+ u8 daylight;
+ u8 pad2;
+} efi_time_t;
+
+typedef struct {
+ u32 resolution;
+ u32 accuracy;
+ u8 sets_to_zero;
+} efi_time_cap_t;
+
+enum efi_locate_search_type {
+ all_handles,
+ by_register_notify,
+ by_protocol
+};
+
+struct efi_open_protocol_information_entry {
+ efi_handle_t agent_handle;
+ efi_handle_t controller_handle;
+ u32 attributes;
+ u32 open_count;
+};
+
+/*
+ * EFI Boot Services table
+ */
+typedef struct {
+ efi_table_hdr_t hdr;
+ void *raise_tpl;
+ void *restore_tpl;
+ efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long,
+ efi_physical_addr_t *);
+ efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, unsigned long);
+ efi_status_t (EFIAPI *get_memory_map)(unsigned long *, void *, unsigned long *,
+ unsigned long *, u32 *);
+ efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **);
+ efi_status_t (EFIAPI *free_pool)(void *);
+ void *create_event;
+ void *set_timer;
+ efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event,
+ unsigned long *index);
+ void *signal_event;
+ void *close_event;
+ void *check_event;
+ void *install_protocol_interface;
+ void *reinstall_protocol_interface;
+ void *uninstall_protocol_interface;
+ efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, void **);
+ void *__reserved;
+ void *register_protocol_notify;
+ efi_status_t (EFIAPI *locate_handle) (enum efi_locate_search_type search_type,
+ efi_guid_t *protocol, void *search_key,
+ unsigned long *buffer_size, efi_handle_t *buffer);
+ efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol,
+ struct efi_device_path **device_path, efi_handle_t *device);
+ void *install_configuration_table;
+ efi_status_t (EFIAPI *load_image)(bool boot_policiy, efi_handle_t parent_image,
+ struct efi_device_path *file_path, void *source_buffer,
+ unsigned long source_size, efi_handle_t *image);
+ efi_status_t (EFIAPI *start_image)(efi_handle_t handle,
+ unsigned long *exitdata_size, s16 **exitdata);
+ efi_status_t(EFIAPI *exit)(efi_handle_t handle, efi_status_t exit_status,
+ unsigned long exitdata_size, s16 *exitdata);
+ void *unload_image;
+ efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long);
+ void *get_next_monotonic_count;
+ efi_status_t (EFIAPI *stall)(unsigned long usecs);
+ void *set_watchdog_timer;
+ efi_status_t(EFIAPI *connect_controller)(efi_handle_t controller_handle,
+ efi_handle_t *driver_image_handle,
+ struct efi_device_path *remaining_device_path,
+ bool Recursive);
+ void *disconnect_controller;
+#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001
+#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002
+#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004
+#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008
+#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010
+#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020
+ efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, efi_guid_t *protocol,
+ void ** interface, efi_handle_t agent_handle,
+ efi_handle_t controller_handle, u32 attributes);
+ void *close_protocol;
+ efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, efi_guid_t *Protocol,
+ struct efi_open_protocol_information_entry **entry_buffer,
+ unsigned long *entry_count);
+ efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle,
+ efi_guid_t ***protocol_buffer,
+ unsigned long *protocols_buffer_count);
+ efi_status_t (EFIAPI *locate_handle_buffer) (
+ enum efi_locate_search_type search_type,
+ efi_guid_t *protocol, void *search_key,
+ unsigned long *no_handles, efi_handle_t **buffer);
+ void *locate_protocol;
+ void *install_multiple_protocol_interfaces;
+ void *uninstall_multiple_protocol_interfaces;
+ void *calculate_crc32;
+ void *copy_mem;
+ void *set_mem;
+ void *create_event_ex;
+} efi_boot_services_t;
+
+extern efi_boot_services_t *BS;
+
+/*
+ * Types and defines for EFI ResetSystem
+ */
+#define EFI_RESET_COLD 0
+#define EFI_RESET_WARM 1
+#define EFI_RESET_SHUTDOWN 2
+
+/*
+ * EFI Runtime Services table
+ */
+#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
+#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ void *get_time;
+ void *set_time;
+ void *get_wakeup_time;
+ void *set_wakeup_time;
+ void *set_virtual_address_map;
+ void *convert_pointer;
+ efi_status_t (EFIAPI *get_variable)(s16 *variable_name, efi_guid_t *vendor,
+ u32 *Attributes, unsigned long *data_size, void *data);
+ efi_status_t (EFIAPI *get_next_variable)(unsigned long *variable_name_size,
+ s16 *variable_name, efi_guid_t *vendor);
+ void *set_variable;
+ void *get_next_high_mono_count;
+ void *reset_system;
+ void *update_capsule;
+ void *query_capsule_caps;
+ void *query_variable_info;
+} efi_runtime_services_t;
+
+extern efi_runtime_services_t *RT;
+
+/*
+ * EFI Configuration Table and GUID definitions
+ */
+#define EFI_NULL_GUID \
+ EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
+
+#define EFI_MPS_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_ACPI_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_ACPI_20_TABLE_GUID \
+ EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
+
+#define EFI_SMBIOS_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_SAL_SYSTEM_TABLE_GUID \
+ EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
+
+#define EFI_HCDP_TABLE_GUID \
+ EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
+
+#define EFI_UGA_IO_PROTOCOL_GUID \
+ EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
+
+#define EFI_GLOBAL_VARIABLE_GUID \
+ EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
+
+#define EFI_UV_SYSTEM_TABLE_GUID \
+ EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
+
+#define EFI_LINUX_EFI_CRASH_GUID \
+ EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
+
+#define EFI_LOADED_IMAGE_PROTOCOL_GUID \
+ EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
+ EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a )
+
+#define EFI_UGA_PROTOCOL_GUID \
+ EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 )
+
+#define EFI_PCI_IO_PROTOCOL_GUID \
+ EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
+
+#define EFI_FILE_INFO_GUID \
+ EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_SIMPLE_FILE_SYSTEM_GUID \
+ EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_DEVICE_TREE_GUID \
+ EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 )
+
+#define EFI_DEVICE_PATH_PROTOCOL_GUID \
+ EFI_GUID( 0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
+
+#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \
+ EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D )
+
+#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \
+ EFI_GUID(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_UNKNOWN_DEVICE_GUID \
+ EFI_GUID(0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b)
+
+#define EFI_BLOCK_IO_PROTOCOL_GUID \
+ EFI_GUID(0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+/* additional GUID from EDK2 */
+#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID \
+ EFI_GUID(0x220e73b6, 0x6bdb, 0x4413, 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a)
+
+#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \
+ EFI_GUID(0x8f644fa9, 0xe850, 0x4db1, 0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4)
+
+#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \
+ EFI_GUID(0x2f707ebb, 0x4a1a, 0x11d4, 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_ISA_ACPI_PROTOCOL_GUID \
+ EFI_GUID(0x64a892dc, 0x5561, 0x4536, 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55)
+
+#define EFI_ISA_IO_PROTOCOL_GUID \
+ EFI_GUID(0x7ee2bd44, 0x3da0, 0x11d4, 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_STANDARD_ERROR_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2d, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_CONSOLE_OUT_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_CONSOLE_IN_DEVICE_GUID \
+ EFI_GUID(0xd3b36f2b, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
+
+#define EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID \
+ EFI_GUID(0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
+ EFI_GUID(0xdd9e7534, 0x7762, 0x4698, 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa)
+
+#define EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID \
+ EFI_GUID(0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_DISK_IO_PROTOCOL_GUID \
+ EFI_GUID(0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \
+ EFI_GUID(0xa1e37052, 0x80d9, 0x4e65, 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9)
+
+#define EFI_DISK_INFO_PROTOCOL_GUID \
+ EFI_GUID(0xd432a67f, 0x14dc, 0x484b, 0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27)
+
+#define EFI_SERIAL_IO_PROTOCOL_GUID \
+ EFI_GUID(0xbb25cf6f, 0xf1d4, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0xfd)
+
+#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \
+ EFI_GUID(0x3bc1b285, 0x8a15, 0x4a82, 0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65)
+
+#define EFI_LOAD_FILE2_PROTOCOL_GUID \
+ EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d)
+
+#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x2fe800be, 0x8f01, 0x4aa6, 0x94, 0x6b, 0xd7, 0x13, 0x88, 0xe1, 0x83, 0x3f)
+
+#define EFI_DHCP4_PROTOCOL_GUID \
+ EFI_GUID(0x9d9a39d8, 0xbd42, 0x4a73, 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80)
+
+#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x83f01464, 0x99bd, 0x45e5, 0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6)
+
+#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0x00720665, 0x67EB, 0x4a99, 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9)
+
+#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0xc51711e7, 0xb4bf, 0x404a, 0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4)
+
+#define EFI_IP4_CONFIG_PROTOCOL_GUID \
+ EFI_GUID(0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e)
+
+#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID\
+ EFI_GUID(0xf44c00ee, 0x1f2c, 0x4a00, 0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3)
+
+#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \
+ EFI_GUID(0xf36ff770, 0xa7e1, 0x42cf, 0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c)
+
+#define EFI_VLAN_CONFIG_PROTOCOL_GUID \
+ EFI_GUID(0x9e23d768, 0xd2f3, 0x4366, 0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74)
+
+#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \
+ EFI_GUID(0x330d4706, 0xf2a0, 0x4e4f, 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85)
+
+#define LOAD_FILE_PROTOCOL_GUID \
+ EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b)
+
+#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \
+ EFI_GUID(0x6a7a5cff, 0xe8d9, 0x4f70, 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14)
+
+#define EFI_IDEBUSDXE_INF_GUID \
+ EFI_GUID(0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2)
+
+#define EFI_TERMINALDXE_INF_GUID \
+ EFI_GUID(0x9e863906, 0xa40f, 0x4875, 0x97, 0x7f, 0x5b, 0x93, 0xff, 0x23, 0x7f, 0xc6)
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \
+ EFI_GUID(0x1aced566, 0x76ed, 0x4218, 0xbc, 0x81, 0x76, 0x7f, 0x1f, 0x97, 0x7a, 0x89)
+
+#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \
+ EFI_GUID(0xe18541cd, 0xf755, 0x4f73, 0x92, 0x8d, 0x64, 0x3c, 0x8a, 0x79, 0xb2, 0x29)
+
+#define EFI_ISCSIDXE_INF_GUID \
+ EFI_GUID(0x4579b72d, 0x7ec4, 0x4dd4, 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7)
+
+#define EFI_VLANCONFIGDXE_INF_GUID \
+ EFI_GUID(0xe4f61863, 0xfe2c, 0x4b56, 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf)
+
+extern efi_guid_t efi_file_info_id;
+extern efi_guid_t efi_simple_file_system_protocol_guid;
+extern efi_guid_t efi_device_path_protocol_guid;
+extern efi_guid_t efi_loaded_image_protocol_guid;
+extern efi_guid_t efi_unknown_device_guid;
+extern efi_guid_t efi_null_guid;
+extern efi_guid_t efi_global_variable_guid;
+extern efi_guid_t efi_block_io_protocol_guid;
+
+#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
+
+#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
+#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
+#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
+#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00))
+#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
+#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
+
+typedef struct {
+ efi_table_hdr_t hdr;
+ unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
+ u32 fw_revision;
+ unsigned long con_in_handle;
+ struct efi_simple_input_interface *con_in;
+ unsigned long con_out_handle;
+ struct efi_simple_text_output_protocol *con_out;
+ unsigned long stderr_handle;
+ unsigned long std_err;
+ efi_runtime_services_t *runtime;
+ efi_boot_services_t *boottime;
+ unsigned long nr_tables;
+ unsigned long tables;
+} efi_system_table_t;
+
+typedef struct {
+ u32 revision;
+ void *parent_handle;
+ efi_system_table_t *system_table;
+ void *device_handle;
+ void *file_path;
+ void *reserved;
+ u32 load_options_size;
+ void *load_options;
+ void *image_base;
+ __aligned_u64 image_size;
+ unsigned int image_code_type;
+ unsigned int image_data_type;
+ unsigned long unload;
+} efi_loaded_image_t;
+
+static inline int
+efi_guidcmp (efi_guid_t left, efi_guid_t right)
+{
+ return memcmp(&left, &right, sizeof (efi_guid_t));
+}
+
+/*
+ * Variable Attributes
+ */
+#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
+#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
+#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
+#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
+#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
+#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
+#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
+
+#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | \
+ EFI_VARIABLE_RUNTIME_ACCESS | \
+ EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
+ EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
+ EFI_VARIABLE_APPEND_WRITE)
+/*
+ * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"))
+ * not including trailing NUL
+ */
+#define EFI_VARIABLE_GUID_LEN 36
+
+struct efi_device_path {
+ u8 type;
+ u8 sub_type;
+ u16 length;
+} __attribute ((packed));
+
+struct simple_text_output_mode {
+ s32 max_mode;
+ s32 mode;
+ s32 attribute;
+ s32 cursor_column;
+ s32 cursor_row;
+ bool cursor_visible;
+};
+
+struct efi_simple_text_output_protocol {
+ void *reset;
+ efi_status_t (EFIAPI *output_string)(void *, void *);
+ void *test_string;
+
+ efi_status_t(EFIAPI *query_mode)(struct efi_simple_text_output_protocol *this,
+ unsigned long mode_number, unsigned long *columns, unsigned long *rows);
+ efi_status_t(EFIAPI *set_mode)(struct efi_simple_text_output_protocol *this,
+ unsigned long mode_number);
+ efi_status_t(EFIAPI *set_attribute)(struct efi_simple_text_output_protocol *this,
+ unsigned long attribute);
+ efi_status_t(EFIAPI *clear_screen) (struct efi_simple_text_output_protocol *this);
+ efi_status_t(EFIAPI *set_cursor_position) (struct efi_simple_text_output_protocol *this,
+ unsigned long column, unsigned long row);
+ efi_status_t(EFIAPI *enable_cursor)(void *, bool enable);
+ struct simple_text_output_mode *mode;
+};
+
+struct efi_input_key {
+ u16 scan_code;
+ s16 unicode_char;
+};
+
+struct efi_simple_input_interface {
+ efi_status_t(EFIAPI *reset)(struct efi_simple_input_interface *this,
+ bool ExtendedVerification);
+ efi_status_t(EFIAPI *read_key_stroke)(struct efi_simple_input_interface *this,
+ struct efi_input_key *key);
+ void *wait_for_key;
+};
+
+typedef struct {
+ uint8_t Addr[32];
+} efi_mac_address;
+
+typedef struct {
+ uint8_t Addr[4];
+} efi_ipv4_address;
+
+typedef struct {
+ uint8_t Addr[16];
+} efi_ipv6_address;
+
+typedef union {
+ uint32_t Addr[4];
+ efi_ipv4_address v4;
+ efi_ipv6_address v6;
+} efi_ip_address;
+
+static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b)
+{
+ return memcmp(a, b, sizeof(efi_guid_t));
+}
+
+char *device_path_to_str(struct efi_device_path *dev_path);
+
+const char *efi_guid_string(efi_guid_t *g);
+
+#endif /* _LINUX_EFI_H */
diff --git a/include/envfs.h b/include/envfs.h
index 9b86398984..fdcb8a8d97 100644
--- a/include/envfs.h
+++ b/include/envfs.h
@@ -43,6 +43,7 @@ struct envfs_super {
uint8_t minor; /* minor */
uint16_t future; /* reserved for future use */
uint32_t flags; /* feature flags */
+#define ENVFS_FLAGS_FORCE_BUILT_IN (1 << 0)
uint32_t sb_crc; /* crc for the superblock */
};
@@ -92,7 +93,7 @@ struct envfs_super {
#define ENV_FLAG_NO_OVERWRITE (1 << 0)
int envfs_load(const char *filename, const char *dirname, unsigned flags);
-int envfs_save(const char *filename, const char *dirname);
+int envfs_save(const char *filename, const char *dirname, unsigned flags);
int envfs_load_from_buf(void *buf, int len, const char *dir, unsigned flags);
/* defaults to /dev/env0 */
diff --git a/include/filetype.h b/include/filetype.h
index c20a4f9395..eedf4b4afe 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -30,6 +30,9 @@ enum filetype {
filetype_ubifs,
filetype_bpk,
filetype_barebox_env,
+ filetype_ch_image,
+ filetype_ch_image_be,
+ filetype_exe,
filetype_max,
};
diff --git a/include/fs.h b/include/fs.h
index 073641c747..b2541a4ee5 100644
--- a/include/fs.h
+++ b/include/fs.h
@@ -164,20 +164,6 @@ int ls(const char *path, ulong flags);
char *mkmodestr(unsigned long mode, char *str);
/*
- * Read a file into memory. Memory is allocated with malloc and must
- * be freed with free() afterwards. This function allocates one
- * byte more than actually needed and sets this to zero, so that
- * it can be used for text files.
- * If size is nonzero it s set to the file size.
- */
-void *read_file(const char *filename, size_t *size);
-
-/*
- * Write a buffer to a file. This file is newly created.
- */
-int write_file(const char *filename, void *buf, size_t size);
-
-/*
* This function turns 'path' into an absolute path and removes all occurrences
* of "..", "." and double slashes. The returned string must be freed wit free().
*/
diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h
index a107f5edb7..4696f43e31 100644
--- a/include/i2c/i2c.h
+++ b/include/i2c/i2c.h
@@ -85,6 +85,63 @@ struct i2c_client {
#define to_i2c_client(a) container_of(a, struct i2c_client, dev)
+/*flags for the client struct: */
+#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */
+#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */
+ /* Must match I2C_M_STOP|IGNORE_NAK */
+
+/*
+ * Data for SMBus Messages
+ */
+#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */
+union i2c_smbus_data {
+ __u8 byte;
+ __u16 word;
+ __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */
+ /* and one more for user-space compatibility */
+};
+
+/* i2c_smbus_xfer read or write markers */
+#define I2C_SMBUS_READ 1
+#define I2C_SMBUS_WRITE 0
+
+/* SMBus transaction types (size parameter in the above functions)
+ Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */
+#define I2C_SMBUS_QUICK 0
+#define I2C_SMBUS_BYTE 1
+#define I2C_SMBUS_BYTE_DATA 2
+#define I2C_SMBUS_WORD_DATA 3
+#define I2C_SMBUS_I2C_BLOCK_DATA 8
+
+/* This is the very generalized SMBus access routine. You probably do not
+ want to use this, though; one of the functions below may be much easier,
+ and probably just as fast.
+ Note that we use i2c_adapter here, because you do not need a specific
+ smbus adapter to call this function. */
+extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
+ unsigned short flags, char read_write, u8 command,
+ int size, union i2c_smbus_data *data);
+
+/* Now follow the 'nice' access routines. These also document the calling
+ conventions of i2c_smbus_xfer. */
+
+extern s32 i2c_smbus_read_byte(const struct i2c_client *client);
+extern s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value);
+extern s32 i2c_smbus_read_byte_data(const struct i2c_client *client,
+ u8 command);
+extern s32 i2c_smbus_write_byte_data(const struct i2c_client *client,
+ u8 command, u8 value);
+extern s32 i2c_smbus_read_word_data(const struct i2c_client *client,
+ u8 command);
+extern s32 i2c_smbus_write_word_data(const struct i2c_client *client,
+ u8 command, u16 value);
+
+/* Returns the number of read bytes */
+extern s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client,
+ u8 command, u8 length, u8 *values);
+extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
+ u8 command, u8 length,
+ const u8 *values);
/**
* struct i2c_board_info - template for device creation
diff --git a/include/image-metadata.h b/include/image-metadata.h
new file mode 100644
index 0000000000..34dae5ce34
--- /dev/null
+++ b/include/image-metadata.h
@@ -0,0 +1,117 @@
+#ifndef __INCLUDE_IMAGE_METADTA_H
+#define __INCLUDE_IMAGE_METADTA_H
+
+/*
+ * barebox Image MetaData (IMD)
+ *
+ * IMD is a mechanism to store metadata in barebox images. With IMD
+ * it's possible to extract the release, the build timestamp and the
+ * board type from a barebox image.
+ *
+ * Since there is no fixed place in the image suitable for all SoC image
+ * types the metadata can be stored anywhere in the image and is found
+ * by iterating over the image. The metadata starts with a start header
+ * and ends with an end header. All tags in between carry the payload.
+ *
+ * Make sure source files containing IMD data are compiled with lwl-y so
+ * that the tags end up in the PBL if one exists and in the regular image
+ * without PBL.
+ *
+ * The following types exist:
+ */
+#define IMD_TYPE_START 0x640c0001
+#define IMD_TYPE_RELEASE 0x640c8002 /* The barebox release aka UTS_RELEASE */
+#define IMD_TYPE_BUILD 0x640c8003 /* build number and timestamp (UTS_VERSION) */
+#define IMD_TYPE_MODEL 0x640c8004 /* The board name this image is for */
+#define IMD_TYPE_OF_COMPATIBLE 0x640c8005 /* the device tree compatible string */
+#define IMD_TYPE_PARAMETER 0x640c8006 /* A generic parameter. Use key=value as data */
+#define IMD_TYPE_END 0x640c7fff
+#define IMD_TYPE_INVALID 0xffffffff
+
+/*
+ * The IMD header. All data is stored in little endian format in the image.
+ * The next header starts at the next 4 byte boundary after the data.
+ */
+struct imd_header {
+ uint32_t type; /* One of IMD_TYPE_* above */
+ uint32_t datalength; /* Length of the data (exluding the header) */
+};
+
+/*
+ * A IMD string. Set bit 15 of the IMD_TYPE to indicate the data is printable
+ * as string.
+ */
+struct imd_entry_string {
+ struct imd_header header;
+ char data[];
+};
+
+static inline int imd_is_string(uint32_t type)
+{
+ return (type & 0x8000) ? 1 : 0;
+}
+
+static inline int imd_type_valid(uint32_t type)
+{
+ return (type & 0xffff0000) == 0x640c0000;
+}
+
+struct imd_header *imd_next(struct imd_header *imd);
+
+#define imd_for_each(start, imd) \
+ for (imd = imd_next(start); imd_read_type(imd) != IMD_TYPE_END; imd = imd_next(imd))
+
+static inline uint32_t imd_read_le32(void *_ptr)
+{
+ uint8_t *ptr = _ptr;
+
+ return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24);
+}
+
+static inline uint32_t imd_read_type(struct imd_header *imd)
+{
+ return imd_read_le32(&imd->type);
+}
+
+static inline uint32_t imd_read_length(struct imd_header *imd)
+{
+ return imd_read_le32(&imd->datalength);
+}
+
+struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type);
+
+extern int imd_command_verbose;
+int imd_command_setenv(const char *variable_name, const char *value);
+int imd_command(int argc, char *argv[]);
+
+#ifdef __BAREBOX__
+
+#include <linux/stringify.h>
+
+#define __BAREBOX_IMD_SECTION(_section) \
+ __attribute__ ((unused,section (__stringify(_section)))) \
+ __attribute__((aligned(4)))
+
+#define BAREBOX_IMD_TAG_STRING(_name, _type, _string, _keep_if_unused) \
+ const struct imd_entry_string __barebox_imd_##_name \
+ __BAREBOX_IMD_SECTION(.barebox_imd_ ## _keep_if_unused ## _ ## _name) = { \
+ .header.type = cpu_to_le32(_type), \
+ .header.datalength = cpu_to_le32(sizeof(_string)), \
+ .data = _string, \
+ }
+
+
+#ifdef CONFIG_IMD
+void imd_used(const void *);
+#else
+static inline void imd_used(const void *unused)
+{
+}
+#endif
+
+#define IMD_USED(_name) \
+ imd_used(&__barebox_imd_##_name)
+
+#endif /* __BAREBOX__ */
+
+#endif /* __INCLUDE_IMAGE_METADTA_H */
diff --git a/include/libbb.h b/include/libbb.h
index 2fe710c368..a362bd32d8 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -26,15 +26,8 @@ int recursive_action(const char *fileName, unsigned flags,
char * safe_strncpy(char *dst, const char *src, size_t size);
-int copy_file(const char *src, const char *dst, int verbose);
-
int process_escape_sequence(const char *source, char *dest, int destlen);
char *simple_itoa(unsigned int i);
-int write_full(int fd, void *buf, size_t size);
-int read_full(int fd, void *buf, size_t size);
-
-char *read_file_line(const char *fmt, ...);
-
#endif /* __LIBBB_H */
diff --git a/include/libfile.h b/include/libfile.h
new file mode 100644
index 0000000000..4a25a9153c
--- /dev/null
+++ b/include/libfile.h
@@ -0,0 +1,18 @@
+#ifndef __LIBFILE_H
+#define __LIBFILE_H
+
+int write_full(int fd, void *buf, size_t size);
+int read_full(int fd, void *buf, size_t size);
+
+char *read_file_line(const char *fmt, ...);
+
+void *read_file(const char *filename, size_t *size);
+
+int read_file_2(const char *filename, size_t *size, void **outbuf,
+ loff_t max_size);
+
+int write_file(const char *filename, void *buf, size_t size);
+
+int copy_file(const char *src, const char *dst, int verbose);
+
+#endif /* __LIBFILE_H */
diff --git a/include/linux/efi.h b/include/linux/efi.h
deleted file mode 100644
index 570eff75de..0000000000
--- a/include/linux/efi.h
+++ /dev/null
@@ -1,547 +0,0 @@
-#ifndef _LINUX_EFI_H
-#define _LINUX_EFI_H
-
-/*
- * Extensible Firmware Interface
- * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999
- *
- * Copyright (C) 1999 VA Linux Systems
- * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
- * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co.
- * David Mosberger-Tang <davidm@hpl.hp.com>
- * Stephane Eranian <eranian@hpl.hp.com>
- */
-#include <linux/string.h>
-#include <linux/types.h>
-
-#define EFI_SUCCESS 0
-#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1)))
-#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1)))
-
-typedef unsigned long efi_status_t;
-typedef u8 efi_bool_t;
-typedef u16 efi_char16_t; /* UNICODE character */
-
-
-typedef struct {
- u8 b[16];
-} efi_guid_t;
-
-#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
-((efi_guid_t) \
-{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
- (b) & 0xff, ((b) >> 8) & 0xff, \
- (c) & 0xff, ((c) >> 8) & 0xff, \
- (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})
-
-/*
- * Generic EFI table header
- */
-typedef struct {
- u64 signature;
- u32 revision;
- u32 headersize;
- u32 crc32;
- u32 reserved;
-} efi_table_hdr_t;
-
-/*
- * Memory map descriptor:
- */
-
-/* Memory types: */
-#define EFI_RESERVED_TYPE 0
-#define EFI_LOADER_CODE 1
-#define EFI_LOADER_DATA 2
-#define EFI_BOOT_SERVICES_CODE 3
-#define EFI_BOOT_SERVICES_DATA 4
-#define EFI_RUNTIME_SERVICES_CODE 5
-#define EFI_RUNTIME_SERVICES_DATA 6
-#define EFI_CONVENTIONAL_MEMORY 7
-#define EFI_UNUSABLE_MEMORY 8
-#define EFI_ACPI_RECLAIM_MEMORY 9
-#define EFI_ACPI_MEMORY_NVS 10
-#define EFI_MEMORY_MAPPED_IO 11
-#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12
-#define EFI_PAL_CODE 13
-#define EFI_MAX_MEMORY_TYPE 14
-
-/* Attribute values: */
-#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
-#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
-#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
-#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */
-#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */
-#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */
-#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */
-#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */
-#define EFI_MEMORY_DESCRIPTOR_VERSION 1
-
-#define EFI_PAGE_SHIFT 12
-
-typedef struct {
- u32 type;
- u32 pad;
- u64 phys_addr;
- u64 virt_addr;
- u64 num_pages;
- u64 attribute;
-} efi_memory_desc_t;
-
-typedef struct {
- efi_guid_t guid;
- u32 headersize;
- u32 flags;
- u32 imagesize;
-} efi_capsule_header_t;
-
-/*
- * Allocation types for calls to boottime->allocate_pages.
- */
-#define EFI_ALLOCATE_ANY_PAGES 0
-#define EFI_ALLOCATE_MAX_ADDRESS 1
-#define EFI_ALLOCATE_ADDRESS 2
-#define EFI_MAX_ALLOCATE_TYPE 3
-
-typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg);
-
-/*
- * Types and defines for Time Services
- */
-#define EFI_TIME_ADJUST_DAYLIGHT 0x1
-#define EFI_TIME_IN_DAYLIGHT 0x2
-#define EFI_UNSPECIFIED_TIMEZONE 0x07ff
-
-typedef struct {
- u16 year;
- u8 month;
- u8 day;
- u8 hour;
- u8 minute;
- u8 second;
- u8 pad1;
- u32 nanosecond;
- s16 timezone;
- u8 daylight;
- u8 pad2;
-} efi_time_t;
-
-typedef struct {
- u32 resolution;
- u32 accuracy;
- u8 sets_to_zero;
-} efi_time_cap_t;
-
-/*
- * EFI Boot Services table
- */
-typedef struct {
- efi_table_hdr_t hdr;
- void *raise_tpl;
- void *restore_tpl;
- void *allocate_pages;
- void *free_pages;
- void *get_memory_map;
- void *allocate_pool;
- void *free_pool;
- void *create_event;
- void *set_timer;
- void *wait_for_event;
- void *signal_event;
- void *close_event;
- void *check_event;
- void *install_protocol_interface;
- void *reinstall_protocol_interface;
- void *uninstall_protocol_interface;
- void *handle_protocol;
- void *__reserved;
- void *register_protocol_notify;
- void *locate_handle;
- void *locate_device_path;
- void *install_configuration_table;
- void *load_image;
- void *start_image;
- void *exit;
- void *unload_image;
- void *exit_boot_services;
- void *get_next_monotonic_count;
- void *stall;
- void *set_watchdog_timer;
- void *connect_controller;
- void *disconnect_controller;
- void *open_protocol;
- void *close_protocol;
- void *open_protocol_information;
- void *protocols_per_handle;
- void *locate_handle_buffer;
- void *locate_protocol;
- void *install_multiple_protocol_interfaces;
- void *uninstall_multiple_protocol_interfaces;
- void *calculate_crc32;
- void *copy_mem;
- void *set_mem;
- void *create_event_ex;
-} efi_boot_services_t;
-
-/*
- * Types and defines for EFI ResetSystem
- */
-#define EFI_RESET_COLD 0
-#define EFI_RESET_WARM 1
-#define EFI_RESET_SHUTDOWN 2
-
-/*
- * EFI Runtime Services table
- */
-#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL)
-#define EFI_RUNTIME_SERVICES_REVISION 0x00010000
-
-typedef struct {
- efi_table_hdr_t hdr;
- unsigned long get_time;
- unsigned long set_time;
- unsigned long get_wakeup_time;
- unsigned long set_wakeup_time;
- unsigned long set_virtual_address_map;
- unsigned long convert_pointer;
- unsigned long get_variable;
- unsigned long get_next_variable;
- unsigned long set_variable;
- unsigned long get_next_high_mono_count;
- unsigned long reset_system;
- unsigned long update_capsule;
- unsigned long query_capsule_caps;
- unsigned long query_variable_info;
-} efi_runtime_services_t;
-
-typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc);
-typedef efi_status_t efi_set_time_t (efi_time_t *tm);
-typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending,
- efi_time_t *tm);
-typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm);
-typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr,
- unsigned long *data_size, void *data);
-typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name,
- efi_guid_t *vendor);
-typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor,
- u32 attr, unsigned long data_size,
- void *data);
-typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count);
-typedef void efi_reset_system_t (int reset_type, efi_status_t status,
- unsigned long data_size, efi_char16_t *data);
-typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size,
- unsigned long descriptor_size,
- u32 descriptor_version,
- efi_memory_desc_t *virtual_map);
-typedef efi_status_t efi_query_variable_info_t(u32 attr,
- u64 *storage_space,
- u64 *remaining_space,
- u64 *max_variable_size);
-typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules,
- unsigned long count,
- unsigned long sg_list);
-typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules,
- unsigned long count,
- u64 *max_size,
- int *reset_type);
-
-/*
- * EFI Configuration Table and GUID definitions
- */
-#define NULL_GUID \
- EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 )
-
-#define MPS_TABLE_GUID \
- EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define ACPI_TABLE_GUID \
- EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define ACPI_20_TABLE_GUID \
- EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 )
-
-#define SMBIOS_TABLE_GUID \
- EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define SAL_SYSTEM_TABLE_GUID \
- EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d )
-
-#define HCDP_TABLE_GUID \
- EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 )
-
-#define UGA_IO_PROTOCOL_GUID \
- EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 )
-
-#define EFI_GLOBAL_VARIABLE_GUID \
- EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c )
-
-#define UV_SYSTEM_TABLE_GUID \
- EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 )
-
-#define LINUX_EFI_CRASH_GUID \
- EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 )
-
-#define LOADED_IMAGE_PROTOCOL_GUID \
- EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
-
-#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \
- EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a )
-
-#define EFI_UGA_PROTOCOL_GUID \
- EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 )
-
-#define EFI_PCI_IO_PROTOCOL_GUID \
- EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a )
-
-#define EFI_FILE_INFO_ID \
- EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
-
-#define EFI_FILE_SYSTEM_GUID \
- EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b )
-
-typedef struct {
- efi_guid_t guid;
- u64 table;
-} efi_config_table_64_t;
-
-typedef struct {
- efi_guid_t guid;
- u32 table;
-} efi_config_table_32_t;
-
-typedef struct {
- efi_guid_t guid;
- unsigned long table;
-} efi_config_table_t;
-
-#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL)
-
-#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30))
-#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20))
-#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10))
-#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00))
-#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10))
-#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02))
-
-typedef struct {
- efi_table_hdr_t hdr;
- u64 fw_vendor; /* physical addr of CHAR16 vendor string */
- u32 fw_revision;
- u32 __pad1;
- u64 con_in_handle;
- u64 con_in;
- u64 con_out_handle;
- u64 con_out;
- u64 stderr_handle;
- u64 _stderr;
- u64 runtime;
- u64 boottime;
- u32 nr_tables;
- u32 __pad2;
- u64 tables;
-} efi_system_table_64_t;
-
-typedef struct {
- efi_table_hdr_t hdr;
- u32 fw_vendor; /* physical addr of CHAR16 vendor string */
- u32 fw_revision;
- u32 con_in_handle;
- u32 con_in;
- u32 con_out_handle;
- u32 con_out;
- u32 stderr_handle;
- u32 _stderr;
- u32 runtime;
- u32 boottime;
- u32 nr_tables;
- u32 tables;
-} efi_system_table_32_t;
-
-typedef struct {
- efi_table_hdr_t hdr;
- unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */
- u32 fw_revision;
- unsigned long con_in_handle;
- unsigned long con_in;
- unsigned long con_out_handle;
- unsigned long con_out;
- unsigned long stderr_handle;
- unsigned long _stderr;
- efi_runtime_services_t *runtime;
- efi_boot_services_t *boottime;
- unsigned long nr_tables;
- unsigned long tables;
-} efi_system_table_t;
-
-struct efi_memory_map {
- void *phys_map;
- void *map;
- void *map_end;
- int nr_map;
- unsigned long desc_version;
- unsigned long desc_size;
-};
-
-typedef struct {
- u32 revision;
- void *parent_handle;
- efi_system_table_t *system_table;
- void *device_handle;
- void *file_path;
- void *reserved;
- u32 load_options_size;
- void *load_options;
- void *image_base;
- __aligned_u64 image_size;
- unsigned int image_code_type;
- unsigned int image_data_type;
- unsigned long unload;
-} efi_loaded_image_t;
-
-typedef struct {
- u64 revision;
- void *open_volume;
-} efi_file_io_interface_t;
-
-typedef struct {
- u64 size;
- u64 file_size;
- u64 phys_size;
- efi_time_t create_time;
- efi_time_t last_access_time;
- efi_time_t modification_time;
- __aligned_u64 attribute;
- efi_char16_t filename[1];
-} efi_file_info_t;
-
-typedef struct {
- u64 revision;
- void *open;
- void *close;
- void *delete;
- void *read;
- void *write;
- void *get_position;
- void *set_position;
- void *get_info;
- void *set_info;
- void *flush;
-} efi_file_handle_t;
-
-#define EFI_FILE_MODE_READ 0x0000000000000001
-#define EFI_FILE_MODE_WRITE 0x0000000000000002
-#define EFI_FILE_MODE_CREATE 0x8000000000000000
-
-#define EFI_INVALID_TABLE_ADDR (~0UL)
-
-/*
- * All runtime access to EFI goes through this structure:
- */
-extern struct efi {
- efi_system_table_t *systab; /* EFI system table */
- unsigned int runtime_version; /* Runtime services version */
- unsigned long mps; /* MPS table */
- unsigned long acpi; /* ACPI table (IA64 ext 0.71) */
- unsigned long acpi20; /* ACPI table (ACPI 2.0) */
- unsigned long smbios; /* SM BIOS table */
- unsigned long sal_systab; /* SAL system table */
- unsigned long boot_info; /* boot info table */
- unsigned long hcdp; /* HCDP table */
- unsigned long uga; /* UGA table */
- unsigned long uv_systab; /* UV system table */
- efi_get_time_t *get_time;
- efi_set_time_t *set_time;
- efi_get_wakeup_time_t *get_wakeup_time;
- efi_set_wakeup_time_t *set_wakeup_time;
- efi_get_variable_t *get_variable;
- efi_get_next_variable_t *get_next_variable;
- efi_set_variable_t *set_variable;
- efi_query_variable_info_t *query_variable_info;
- efi_update_capsule_t *update_capsule;
- efi_query_capsule_caps_t *query_capsule_caps;
- efi_get_next_high_mono_count_t *get_next_high_mono_count;
- efi_reset_system_t *reset_system;
- efi_set_virtual_address_map_t *set_virtual_address_map;
-} efi;
-
-static inline int
-efi_guidcmp (efi_guid_t left, efi_guid_t right)
-{
- return memcmp(&left, &right, sizeof (efi_guid_t));
-}
-
-static inline char *
-efi_guid_unparse(efi_guid_t *guid, char *out)
-{
- sprintf(out, "%pUl", guid->b);
- return out;
-}
-
-/*
- * Variable Attributes
- */
-#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001
-#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002
-#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004
-#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008
-#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010
-#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020
-#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040
-
-#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \
- EFI_VARIABLE_BOOTSERVICE_ACCESS | \
- EFI_VARIABLE_RUNTIME_ACCESS | \
- EFI_VARIABLE_HARDWARE_ERROR_RECORD | \
- EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \
- EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \
- EFI_VARIABLE_APPEND_WRITE)
-/*
- * The type of search to perform when calling boottime->locate_handle
- */
-#define EFI_LOCATE_ALL_HANDLES 0
-#define EFI_LOCATE_BY_REGISTER_NOTIFY 1
-#define EFI_LOCATE_BY_PROTOCOL 2
-
-/*
- * EFI Device Path information
- */
-#define EFI_DEV_HW 0x01
-#define EFI_DEV_PCI 1
-#define EFI_DEV_PCCARD 2
-#define EFI_DEV_MEM_MAPPED 3
-#define EFI_DEV_VENDOR 4
-#define EFI_DEV_CONTROLLER 5
-#define EFI_DEV_ACPI 0x02
-#define EFI_DEV_BASIC_ACPI 1
-#define EFI_DEV_EXPANDED_ACPI 2
-#define EFI_DEV_MSG 0x03
-#define EFI_DEV_MSG_ATAPI 1
-#define EFI_DEV_MSG_SCSI 2
-#define EFI_DEV_MSG_FC 3
-#define EFI_DEV_MSG_1394 4
-#define EFI_DEV_MSG_USB 5
-#define EFI_DEV_MSG_USB_CLASS 15
-#define EFI_DEV_MSG_I20 6
-#define EFI_DEV_MSG_MAC 11
-#define EFI_DEV_MSG_IPV4 12
-#define EFI_DEV_MSG_IPV6 13
-#define EFI_DEV_MSG_INFINIBAND 9
-#define EFI_DEV_MSG_UART 14
-#define EFI_DEV_MSG_VENDOR 10
-#define EFI_DEV_MEDIA 0x04
-#define EFI_DEV_MEDIA_HARD_DRIVE 1
-#define EFI_DEV_MEDIA_CDROM 2
-#define EFI_DEV_MEDIA_VENDOR 3
-#define EFI_DEV_MEDIA_FILE 4
-#define EFI_DEV_MEDIA_PROTOCOL 5
-#define EFI_DEV_BIOS_BOOT 0x05
-#define EFI_DEV_END_PATH 0x7F
-#define EFI_DEV_END_PATH2 0xFF
-#define EFI_DEV_END_INSTANCE 0x01
-#define EFI_DEV_END_ENTIRE 0xFF
-
-#endif /* _LINUX_EFI_H */
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index b90d8f7e04..d512adcea1 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -130,5 +130,26 @@
} \
)
-#endif /* _LINUX_KERNEL_H */
+extern const char hex_asc[];
+#define hex_asc_lo(x) hex_asc[((x) & 0x0f)]
+#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4]
+
+static inline char *hex_byte_pack(char *buf, u8 byte)
+{
+ *buf++ = hex_asc_hi(byte);
+ *buf++ = hex_asc_lo(byte);
+ return buf;
+}
+
+extern const char hex_asc_upper[];
+#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)]
+#define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xf0) >> 4]
+static inline char *hex_byte_pack_upper(char *buf, u8 byte)
+{
+ *buf++ = hex_asc_upper_hi(byte);
+ *buf++ = hex_asc_upper_lo(byte);
+ return buf;
+}
+
+#endif /* _LINUX_KERNEL_H */
diff --git a/include/linux/mbus.h b/include/linux/mbus.h
index 578ff33146..ac14982875 100644
--- a/include/linux/mbus.h
+++ b/include/linux/mbus.h
@@ -58,4 +58,6 @@ int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute,
phys_addr_t base, size_t size);
int mvebu_mbus_del_window(phys_addr_t base, size_t size);
+void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap);
+
#endif /* __LINUX_MBUS_H */
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 6caed01c99..0ec1320b2f 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -91,9 +91,6 @@ struct pci_dev {
struct list_head bus_list; /* node in per-bus list */
struct pci_bus *bus; /* bus this device is on */
struct pci_bus *subordinate; /* bus this device bridges to */
-
- void *sysdata; /* hook for sys-specific extension */
- struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */
struct pci_slot *slot; /* Physical slot this device is in */
struct device_d dev;
@@ -118,6 +115,7 @@ struct pci_dev {
#define to_pci_dev(dev) container_of(dev, struct pci_dev, dev)
struct pci_bus {
+ struct pci_controller *host; /* associated host controller */
struct list_head node; /* node in list of buses */
struct list_head children; /* list of child buses */
struct list_head devices; /* list of devices on this bus */
@@ -126,8 +124,6 @@ struct pci_bus {
struct list_head resources; /* address space routed to this bus */
struct pci_ops *ops; /* configuration access functions */
- void *sysdata; /* hook for sys-specific extension */
- struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */
unsigned char number; /* bus number */
unsigned char primary; /* number of primary bridge */
@@ -167,10 +163,8 @@ struct pci_controller {
unsigned int index;
- /* Optional access methods for reading/writing the bus number
- of the PCI controller */
- int (*get_busno)(void);
- void (*set_busno)(int busno);
+ /* Optional access method for writing the bus number */
+ void (*set_busno)(struct pci_controller *host, int busno);
};
struct pci_driver {
diff --git a/include/of_pci.h b/include/of_pci.h
new file mode 100644
index 0000000000..c95cb0135a
--- /dev/null
+++ b/include/of_pci.h
@@ -0,0 +1,17 @@
+#ifndef __OF_PCI_H
+#define __OF_PCI_H
+
+#include <linux/pci.h>
+
+#ifdef CONFIG_OF_PCI
+int of_pci_get_devfn(struct device_node *np);
+
+#else
+static inline int of_pci_get_devfn(struct device_node *np)
+{
+ return -EINVAL;
+}
+
+#endif
+
+#endif
diff --git a/include/param.h b/include/param.h
index 24827c5e78..8f200df847 100644
--- a/include/param.h
+++ b/include/param.h
@@ -7,7 +7,7 @@
#define PARAM_FLAG_RO (1 << 0)
struct device_d;
-typedef unsigned long IPaddr_t;
+typedef uint32_t IPaddr_t;
struct param_d {
const char* (*get)(struct device_d *, struct param_d *param);
diff --git a/include/platform_data/pca953x.h b/include/platform_data/pca953x.h
new file mode 100644
index 0000000000..cfd253ebce
--- /dev/null
+++ b/include/platform_data/pca953x.h
@@ -0,0 +1,27 @@
+#ifndef _LINUX_PCA953X_H
+#define _LINUX_PCA953X_H
+
+#include <linux/types.h>
+#include <i2c/i2c.h>
+
+/* platform data for the PCA9539 16-bit I/O expander driver */
+
+struct pca953x_platform_data {
+ /* number of the first GPIO */
+ unsigned gpio_base;
+
+ /* initial polarity inversion setting */
+ u32 invert;
+
+ void *context; /* param to setup/teardown */
+
+ int (*setup)(struct i2c_client *client,
+ unsigned gpio, unsigned ngpio,
+ void *context);
+ int (*teardown)(struct i2c_client *client,
+ unsigned gpio, unsigned ngpio,
+ void *context);
+ const char *const *names;
+};
+
+#endif /* _LINUX_PCA953X_H */
diff --git a/include/wchar.h b/include/wchar.h
new file mode 100644
index 0000000000..80dcd81bf4
--- /dev/null
+++ b/include/wchar.h
@@ -0,0 +1,18 @@
+#ifndef __WCHAR_H
+#define __WCHAR_H
+
+#include <linux/types.h>
+
+typedef u16 wchar_t;
+
+char *strcpy_wchar_to_char(char *dst, const wchar_t *src);
+
+wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src);
+
+wchar_t *strdup_char_to_wchar(const char *src);
+
+char *strdup_wchar_to_char(const wchar_t *src);
+
+size_t wcslen(const wchar_t *s);
+
+#endif /* __WCHAR_H */
diff --git a/lib/Kconfig b/lib/Kconfig
index d9ad4aa949..09a1674820 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -54,4 +54,7 @@ source lib/gui/Kconfig
source lib/bootstrap/Kconfig
+config PRINTF_UUID
+ bool
+
endmenu
diff --git a/lib/Makefile b/lib/Makefile
index 78f724a095..77207dc773 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -25,7 +25,6 @@ obj-$(CONFIG_GLOB) += fnmatch.o
obj-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o
obj-y += glob.o
obj-y += notifier.o
-obj-y += copy_file.o
obj-y += random.o
obj-y += lzo/
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
@@ -44,4 +43,6 @@ obj-y += gui/
obj-$(CONFIG_XYMODEM) += xymodem.o
obj-y += unlink-recursive.o
obj-$(CONFIG_STMP_DEVICE) += stmp-device.o
+obj-y += wchar.o
+obj-y += libfile.o
obj-y += bitmap.o
diff --git a/lib/bootstrap/disk.c b/lib/bootstrap/disk.c
index 527e430897..1e9fbd834b 100644
--- a/lib/bootstrap/disk.c
+++ b/lib/bootstrap/disk.c
@@ -11,6 +11,7 @@
#include <sizes.h>
#include <errno.h>
#include <malloc.h>
+#include <libfile.h>
#include <bootstrap.h>
void* bootstrap_read_disk(char *dev, char *fstype)
diff --git a/lib/copy_file.c b/lib/copy_file.c
deleted file mode 100644
index fdd0cacb40..0000000000
--- a/lib/copy_file.c
+++ /dev/null
@@ -1,86 +0,0 @@
-#include <common.h>
-#include <fs.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <malloc.h>
-#include <libbb.h>
-#include <progress.h>
-
-/**
- * @param[in] src FIXME
- * @param[out] dst FIXME
- * @param[in] verbose FIXME
- */
-int copy_file(const char *src, const char *dst, int verbose)
-{
- char *rw_buf = NULL;
- int srcfd = 0, dstfd = 0;
- int r, w;
- int ret = 1;
- void *buf;
- int total = 0;
- struct stat statbuf;
-
- rw_buf = xmalloc(RW_BUF_SIZE);
-
- srcfd = open(src, O_RDONLY);
- if (srcfd < 0) {
- printf("could not open %s: %s\n", src, errno_str());
- goto out;
- }
-
- dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
- if (dstfd < 0) {
- printf("could not open %s: %s\n", dst, errno_str());
- goto out;
- }
-
- if (verbose) {
- if (stat(src, &statbuf) < 0)
- statbuf.st_size = 0;
-
- init_progression_bar(statbuf.st_size);
- }
-
- while(1) {
- r = read(srcfd, rw_buf, RW_BUF_SIZE);
- if (r < 0) {
- perror("read");
- goto out;
- }
- if (!r)
- break;
-
- buf = rw_buf;
- while (r) {
- w = write(dstfd, buf, r);
- if (w < 0) {
- perror("write");
- goto out;
- }
- buf += w;
- r -= w;
- total += w;
- }
-
- if (verbose) {
- if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
- show_progress(total);
- else
- show_progress(total / 16384);
- }
- }
-
- ret = 0;
-out:
- if (verbose)
- putchar('\n');
-
- free(rw_buf);
- if (srcfd > 0)
- close(srcfd);
- if (dstfd > 0)
- close(dstfd);
-
- return ret;
-}
diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c
index 8047961e9e..dd29389baa 100644
--- a/lib/gui/image_renderer.c
+++ b/lib/gui/image_renderer.c
@@ -10,6 +10,7 @@
#include <errno.h>
#include <fs.h>
#include <malloc.h>
+#include <libfile.h>
static LIST_HEAD(image_renderers);
diff --git a/lib/libbb.c b/lib/libbb.c
index dd42e662b4..239611c27b 100644
--- a/lib/libbb.c
+++ b/lib/libbb.c
@@ -126,96 +126,3 @@ char *simple_itoa(unsigned int i)
return p + 1;
}
EXPORT_SYMBOL(simple_itoa);
-
-/*
- * write_full - write to filedescriptor
- *
- * Like write, but guarantees to write the full buffer out, else
- * it returns with an error.
- */
-int write_full(int fd, void *buf, size_t size)
-{
- size_t insize = size;
- int now;
-
- while (size) {
- now = write(fd, buf, size);
- if (now <= 0)
- return now;
- size -= now;
- buf += now;
- }
-
- return insize;
-}
-EXPORT_SYMBOL(write_full);
-
-/*
- * read_full - read from filedescriptor
- *
- * Like read, but this function only returns less bytes than
- * requested when the end of file is reached.
- */
-int read_full(int fd, void *buf, size_t size)
-{
- size_t insize = size;
- int now;
- int total = 0;
-
- while (size) {
- now = read(fd, buf, size);
- if (now == 0)
- return total;
- if (now < 0)
- return now;
- total += now;
- size -= now;
- buf += now;
- }
-
- return insize;
-}
-EXPORT_SYMBOL(read_full);
-
-/*
- * read_file_line - read a line from a file
- *
- * Used to compose a filename from a printf format and to read a line from this
- * file. All leading and trailing whitespaces (including line endings) are
- * removed. The returned buffer must be freed with free(). This function is
- * supposed for reading variable like content into a buffer, so files > 1024
- * bytes are ignored.
- */
-char *read_file_line(const char *fmt, ...)
-{
- va_list args;
- char *filename;
- char *buf, *line = NULL;
- size_t size;
- int ret;
- struct stat s;
-
- va_start(args, fmt);
- filename = vasprintf(fmt, args);
- va_end(args);
-
- ret = stat(filename, &s);
- if (ret)
- goto out;
-
- if (s.st_size > 1024)
- goto out;
-
- buf = read_file(filename, &size);
- if (!buf)
- goto out;
-
- line = strim(buf);
-
- line = xstrdup(line);
- free(buf);
-out:
- free(filename);
- return line;
-}
-EXPORT_SYMBOL_GPL(read_file_line);
diff --git a/lib/libfile.c b/lib/libfile.c
new file mode 100644
index 0000000000..c6fb6d7157
--- /dev/null
+++ b/lib/libfile.c
@@ -0,0 +1,331 @@
+/*
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+#include <common.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <libfile.h>
+#include <progress.h>
+#include <linux/stat.h>
+
+/*
+ * write_full - write to filedescriptor
+ *
+ * Like write, but guarantees to write the full buffer out, else
+ * it returns with an error.
+ */
+int write_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+
+ while (size) {
+ now = write(fd, buf, size);
+ if (now <= 0)
+ return now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(write_full);
+
+/*
+ * read_full - read from filedescriptor
+ *
+ * Like read, but this function only returns less bytes than
+ * requested when the end of file is reached.
+ */
+int read_full(int fd, void *buf, size_t size)
+{
+ size_t insize = size;
+ int now;
+ int total = 0;
+
+ while (size) {
+ now = read(fd, buf, size);
+ if (now == 0)
+ return total;
+ if (now < 0)
+ return now;
+ total += now;
+ size -= now;
+ buf += now;
+ }
+
+ return insize;
+}
+EXPORT_SYMBOL(read_full);
+
+/*
+ * read_file_line - read a line from a file
+ *
+ * Used to compose a filename from a printf format and to read a line from this
+ * file. All leading and trailing whitespaces (including line endings) are
+ * removed. The returned buffer must be freed with free(). This function is
+ * supposed for reading variable like content into a buffer, so files > 1024
+ * bytes are ignored.
+ */
+char *read_file_line(const char *fmt, ...)
+{
+ va_list args;
+ char *filename;
+ char *buf, *line = NULL;
+ size_t size;
+ int ret;
+ struct stat s;
+
+ va_start(args, fmt);
+ filename = vasprintf(fmt, args);
+ va_end(args);
+
+ ret = stat(filename, &s);
+ if (ret)
+ goto out;
+
+ if (s.st_size > 1024)
+ goto out;
+
+ buf = read_file(filename, &size);
+ if (!buf)
+ goto out;
+
+ line = strim(buf);
+
+ line = xstrdup(line);
+ free(buf);
+out:
+ free(filename);
+ return line;
+}
+EXPORT_SYMBOL_GPL(read_file_line);
+
+/**
+ * read_file_2 - read a file to an allocated buffer
+ * @filename: The filename to read
+ * @size: After successful return contains the size of the file
+ * @outbuf: contains a pointer to the file data after successful return
+ * @max_size: The maximum size to read. Use FILESIZE_MAX for reading files
+ * of any size.
+ *
+ * This function reads a file to an allocated buffer. At maximum @max_size
+ * bytes are read. The actual read size is returned in @size. -EFBIG is
+ * returned if the file is bigger than @max_size, but the buffer is read
+ * anyway up to @max_size in this case. Free the buffer with free() after
+ * usage.
+ *
+ * Return: 0 for success, or negative error code. -EFBIG is returned
+ * when the file has been bigger than max_size.
+ */
+int read_file_2(const char *filename, size_t *size, void **outbuf,
+ loff_t max_size)
+{
+ int fd;
+ struct stat s;
+ void *buf = NULL;
+ const char *tmpfile = "/.read_file_tmp";
+ int ret;
+ loff_t read_size;
+
+again:
+ ret = stat(filename, &s);
+ if (ret)
+ return ret;
+
+ if (max_size == FILESIZE_MAX)
+ read_size = s.st_size;
+ else
+ read_size = max_size;
+
+ if (read_size == FILESIZE_MAX) {
+ ret = copy_file(filename, tmpfile, 0);
+ if (ret)
+ return ret;
+ filename = tmpfile;
+ goto again;
+ }
+
+ buf = xzalloc(read_size + 1);
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0)
+ goto err_out;
+
+ ret = read_full(fd, buf, read_size);
+ if (ret < 0)
+ goto err_out1;
+
+ close(fd);
+
+ if (size)
+ *size = ret;
+
+ if (filename == tmpfile)
+ unlink(tmpfile);
+
+ *outbuf = buf;
+
+ if (read_size < s.st_size)
+ return -EFBIG;
+ else
+ return 0;
+
+err_out1:
+ close(fd);
+err_out:
+ free(buf);
+
+ if (filename == tmpfile)
+ unlink(tmpfile);
+
+ return ret;
+}
+EXPORT_SYMBOL(read_file_2);
+
+/**
+ * read_file - read a file to an allocated buffer
+ * @filename: The filename to read
+ * @size: After successful return contains the size of the file
+ *
+ * This function reads a file to an allocated buffer.
+ * Some TFTP servers do not transfer the size of a file. In this case
+ * a the file is first read to a temporary file.
+ *
+ * Return: The buffer conataining the file or NULL on failure
+ */
+void *read_file(const char *filename, size_t *size)
+{
+ int ret;
+ void *buf;
+
+ ret = read_file_2(filename, size, &buf, FILESIZE_MAX);
+ if (!ret)
+ return buf;
+
+ return NULL;
+}
+EXPORT_SYMBOL(read_file);
+
+/**
+ * write_file - write a buffer to a file
+ * @filename: The filename to write
+ * @size: The size of the buffer
+ *
+ * Return: 0 for success or negative error value
+ */
+int write_file(const char *filename, void *buf, size_t size)
+{
+ int fd, ret;
+
+ fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT);
+ if (fd < 0)
+ return fd;
+
+ ret = write_full(fd, buf, size);
+
+ close(fd);
+
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(write_file);
+
+/**
+ * copy_file - Copy a file
+ * @src: The source filename
+ * @dst: The destination filename
+ * @verbose: if true, show a progression bar
+ *
+ * Return: 0 for success or negative error code
+ */
+int copy_file(const char *src, const char *dst, int verbose)
+{
+ char *rw_buf = NULL;
+ int srcfd = 0, dstfd = 0;
+ int r, w;
+ int ret = 1;
+ void *buf;
+ int total = 0;
+ struct stat statbuf;
+
+ rw_buf = xmalloc(RW_BUF_SIZE);
+
+ srcfd = open(src, O_RDONLY);
+ if (srcfd < 0) {
+ printf("could not open %s: %s\n", src, errno_str());
+ goto out;
+ }
+
+ dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC);
+ if (dstfd < 0) {
+ printf("could not open %s: %s\n", dst, errno_str());
+ goto out;
+ }
+
+ if (verbose) {
+ if (stat(src, &statbuf) < 0)
+ statbuf.st_size = 0;
+
+ init_progression_bar(statbuf.st_size);
+ }
+
+ while (1) {
+ r = read(srcfd, rw_buf, RW_BUF_SIZE);
+ if (r < 0) {
+ perror("read");
+ goto out;
+ }
+ if (!r)
+ break;
+
+ buf = rw_buf;
+ while (r) {
+ w = write(dstfd, buf, r);
+ if (w < 0) {
+ perror("write");
+ goto out;
+ }
+ buf += w;
+ r -= w;
+ total += w;
+ }
+
+ if (verbose) {
+ if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX)
+ show_progress(total);
+ else
+ show_progress(total / 16384);
+ }
+ }
+
+ ret = 0;
+out:
+ if (verbose)
+ putchar('\n');
+
+ free(rw_buf);
+ if (srcfd > 0)
+ close(srcfd);
+ if (dstfd > 0)
+ close(dstfd);
+
+ return ret;
+}
+EXPORT_SYMBOL(copy_file);
diff --git a/lib/misc.c b/lib/misc.c
index 0f3eb9aabb..87626c1e8b 100644
--- a/lib/misc.c
+++ b/lib/misc.c
@@ -21,6 +21,7 @@
#include <malloc.h>
#include <errno.h>
#include <fs.h>
+#include <string.h>
#include <linux/ctype.h>
/*
@@ -113,3 +114,5 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size)
return -1;
}
EXPORT_SYMBOL(parse_area_spec);
+
+const char hex_asc[] = "0123456789abcdef";
diff --git a/lib/readkey.c b/lib/readkey.c
index 7b38110113..2073a732f4 100644
--- a/lib/readkey.c
+++ b/lib/readkey.c
@@ -25,7 +25,7 @@
struct esc_cmds {
const char *seq;
- char val;
+ unsigned char val;
};
static const struct esc_cmds esccmds[] = {
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 066338b4e8..512c88247f 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -253,6 +253,53 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
#endif
}
+static noinline_for_stack
+char *uuid_string(char *buf, char *end, const u8 *addr, int field_width,
+ int precision, int flags, const char *fmt)
+{
+ char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")];
+ char *p = uuid;
+ int i;
+ static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+ static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15};
+ const u8 *index = be;
+ bool uc = false;
+
+ switch (*(++fmt)) {
+ case 'L':
+ uc = true; /* fall-through */
+ case 'l':
+ index = le;
+ break;
+ case 'B':
+ uc = true;
+ break;
+ }
+
+ for (i = 0; i < 16; i++) {
+ p = hex_byte_pack(p, addr[index[i]]);
+ switch (i) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ *p++ = '-';
+ break;
+ }
+ }
+
+ *p = 0;
+
+ if (uc) {
+ p = uuid;
+ do {
+ *p = toupper(*p);
+ } while (*(++p));
+ }
+
+ return string(buf, end, uuid, field_width, precision, flags);
+}
+
/*
* Show a '%p' thing. A kernel extension is that the '%p' is followed
* by an extra set of alphanumeric characters that are extended format
@@ -261,6 +308,17 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int
* Right now we handle:
*
* - 'S' For symbolic direct pointers
+ * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form
+ * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
+ * Options for %pU are:
+ * b big endian lower case hex (default)
+ * B big endian UPPER case hex
+ * l little endian lower case hex
+ * L little endian UPPER case hex
+ * big endian output byte order is:
+ * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15]
+ * little endian output byte order is:
+ * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15]
*
* Note: The difference between 'S' and 'F' is that on ia64 and ppc64
* function pointers are really function descriptors, which contain a
@@ -271,6 +329,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
switch (*fmt) {
case 'S':
return symbol_string(buf, end, ptr, field_width, precision, flags);
+ case 'U':
+ if (IS_ENABLED(CONFIG_PRINTF_UUID))
+ return uuid_string(buf, end, ptr, field_width, precision, flags, fmt);
+ break;
}
flags |= SMALL;
if (field_width == -1) {
diff --git a/lib/wchar.c b/lib/wchar.c
new file mode 100644
index 0000000000..6368a01994
--- /dev/null
+++ b/lib/wchar.c
@@ -0,0 +1,80 @@
+/*
+ * wchar.c - wide character support
+ *
+ * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <wchar.h>
+#include <malloc.h>
+#include <string.h>
+
+size_t wcslen(const wchar_t *s)
+{
+ size_t len = 0;
+
+ while (*s++)
+ len++;
+
+ return len;
+}
+
+char *strcpy_wchar_to_char(char *dst, const wchar_t *src)
+{
+ char *ret = dst;
+
+ while (*src)
+ *dst++ = *src++ & 0xff;
+
+ *dst = 0;
+
+ return ret;
+}
+
+wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src)
+{
+ wchar_t *ret = dst;
+
+ while (*src)
+ *dst++ = *src++;
+
+ *dst = 0;
+
+ return ret;
+}
+
+wchar_t *strdup_char_to_wchar(const char *src)
+{
+ wchar_t *dst = malloc((strlen(src) + 1) * sizeof(wchar_t));
+
+ if (!dst)
+ return NULL;
+
+ strcpy_char_to_wchar(dst, src);
+
+ return dst;
+}
+
+char *strdup_wchar_to_char(const wchar_t *src)
+{
+ char *dst = malloc((wcslen(src) + 1));
+
+ if (!dst)
+ return NULL;
+
+ strcpy_wchar_to_char(dst, src);
+
+ return dst;
+}
diff --git a/net/netconsole.c b/net/netconsole.c
index 021820b13a..c817107296 100644
--- a/net/netconsole.c
+++ b/net/netconsole.c
@@ -141,6 +141,7 @@ static int netconsole_init(void)
cdev->tstc = nc_tstc;
cdev->putc = nc_putc;
cdev->getc = nc_getc;
+ cdev->devname = "netconsole";
g_priv = priv;
diff --git a/scripts/Makefile b/scripts/Makefile
index 9c77680a17..2050ec497d 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -10,6 +10,7 @@ hostprogs-y += fix_size
hostprogs-y += bareboxenv
hostprogs-y += bareboxcrc32
hostprogs-y += kernel-install
+hostprogs-$(CONFIG_IMD) += bareboximd
hostprogs-$(CONFIG_KALLSYMS) += kallsyms
hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot
hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image
@@ -29,6 +30,7 @@ subdir-$(CONFIG_ARCH_TEGRA) += tegra
targetprogs-$(CONFIG_BAREBOXENV_TARGET) += bareboxenv-target
targetprogs-$(CONFIG_KERNEL_INSTALL_TARGET) += kernel-install-target
targetprogs-$(CONFIG_BAREBOXCRC32_TARGET) += bareboxcrc32-target
+targetprogs-$(CONFIG_IMD_TARGET) += bareboximd-target
# Let clean descend into subdirs
subdir- += basic kconfig setupmbr
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 08518704fe..7d97d573ab 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -14,6 +14,13 @@ obj-m := $(filter-out $(obj-y),$(obj-m))
lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m)))
+pbl-y += $(pbl-dtb-y)
+obj-y += $(obj-dtb-y)
+extra-y += $(patsubst %.dtb.o,%.dtb.S,$(obj-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb,$(obj-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb.S,$(pbl-dtb-y))
+extra-y += $(patsubst %.dtb.o,%.dtb,$(pbl-dtb-y))
+
# Handle objects in subdirs
# ---------------------------------------------------------------------------
# o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o
@@ -203,21 +210,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \
# Generate an assembly file to wrap the output of the device tree compiler
quiet_cmd_dt_S_dtb = DTB $@
-cmd_dt_S_dtb= \
-( \
- echo '\#include <asm-generic/barebox.lds.h>'; \
- echo '.section .dtb.rodata.$(subst -,_,$(*F)),"a"'; \
- echo '.balign STRUCT_ALIGNMENT'; \
- echo '.global __dtb_$(subst -,_,$(*F))_start'; \
- echo '__dtb_$(subst -,_,$(*F))_start:'; \
- echo '.incbin "$<" '; \
- echo '__dtb_$(subst -,_,$(*F))_end:'; \
- echo '.global __dtb_$(subst -,_,$(*F))_end'; \
- echo '.balign STRUCT_ALIGNMENT'; \
-) > $@
-
-$(obj)/%.dtb.S: $(obj)/%.dtb
- $(call cmd,dt_S_dtb)
+cmd_dt_S_dtb = $(srctree)/scripts/gen-dtb-s $(subst -,_,$(*F)) $< $(CONFIG_IMD) > $@
+$(obj)/%.dtb.S: $(obj)/%.dtb $(srctree)/scripts/gen-dtb-s FORCE
+ $(call if_changed,dt_S_dtb)
quiet_cmd_dtc = DTC $@
cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \
diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c
index da420db578..249e65b251 100644
--- a/scripts/bareboxenv.c
+++ b/scripts/bareboxenv.c
@@ -109,6 +109,7 @@ static void usage(char *prgname)
"\n"
"options:\n"
" -s save (directory -> environment sector)\n"
+ " -z force the built-in default environment at startup\n"
" -l load (environment sector -> directory)\n"
" -p <size> pad output file to given size\n"
" -v verbose\n",
@@ -120,9 +121,10 @@ int main(int argc, char *argv[])
int opt;
int save = 0, load = 0, pad = 0, err = 0, fd;
char *filename = NULL, *dirname = NULL;
+ unsigned envfs_flags = 0;
int verbose = 0;
- while((opt = getopt(argc, argv, "slp:v")) != -1) {
+ while((opt = getopt(argc, argv, "slp:vz")) != -1) {
switch (opt) {
case 's':
save = 1;
@@ -133,6 +135,10 @@ int main(int argc, char *argv[])
case 'p':
pad = strtoul(optarg, NULL, 0);
break;
+ case 'z':
+ envfs_flags |= ENVFS_FLAGS_FORCE_BUILT_IN;
+ save = 1;
+ break;
case 'v':
verbose = 1;
break;
@@ -181,7 +187,7 @@ int main(int argc, char *argv[])
if (verbose)
printf("saving contents of %s to file %s\n", dirname, filename);
- err = envfs_save(filename, dirname);
+ err = envfs_save(filename, dirname, envfs_flags);
if (verbose && err)
printf("saving env failed: %d\n", err);
diff --git a/scripts/bareboximd.c b/scripts/bareboximd.c
new file mode 100644
index 0000000000..a3622af821
--- /dev/null
+++ b/scripts/bareboximd.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2014 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 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.
+ *
+ */
+
+#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask))
+#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1)
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <asm-generic/errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <string.h>
+#include <errno.h>
+#include <stdarg.h>
+
+#include "../include/image-metadata.h"
+
+static void debug(const char *fmt, ...)
+{
+ va_list ap;
+
+ if (!imd_command_verbose)
+ return;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+
+int imd_command_setenv(const char *variable_name, const char *value)
+{
+ fprintf(stderr, "-s option ignored\n");
+
+ return -EINVAL;
+}
+
+static int read_file_2(const char *filename, size_t *size, void **outbuf, loff_t max_size)
+{
+ off_t fsize;
+ ssize_t rsize;
+ int ret, fd;
+ void *buf;
+
+ *size = 0;
+ *outbuf = NULL;
+
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno));
+ return -errno;
+ }
+
+ fsize = lseek(fd, 0, SEEK_END);
+ if (fsize == -1) {
+ fprintf(stderr, "Cannot get size %s: %s\n", filename, strerror(errno));
+ ret = -errno;
+ goto close;
+ }
+
+ if (fsize < max_size)
+ max_size = fsize;
+
+ if (lseek(fd, 0, SEEK_SET) == -1) {
+ fprintf(stderr, "Cannot seek to start %s: %s\n", filename, strerror(errno));
+ ret = -errno;
+ goto close;
+ }
+
+ buf = malloc(max_size);
+ if (!buf) {
+ fprintf(stderr, "Cannot allocate memory\n");
+ ret = -ENOMEM;
+ goto close;
+ }
+
+ *outbuf = buf;
+ while (*size < max_size) {
+ rsize = read(fd, buf, max_size-*size);
+ if (rsize == 0) {
+ ret = -EIO;
+ goto free;
+ } else if (rsize < 0) {
+ if (errno == EAGAIN)
+ continue;
+ else {
+ ret = -errno;
+ goto free;
+ }
+ } /* ret > 0 */
+ buf += rsize;
+ *size += rsize;
+ }
+
+ ret = 0;
+ goto close;
+free:
+ *outbuf = NULL;
+ free(buf);
+close:
+ close(fd);
+ return ret;
+}
+
+static unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base)
+{
+ return strtoul(cp, endp, base);
+}
+
+#include "../common/imd.c"
+
+static void usage(const char *prgname)
+{
+ printf(
+"Extract metadata from a barebox image\n"
+"\n"
+"Usage: %s [OPTIONS] FILE\n"
+"Options:\n"
+"-t <type> only show information of <type>\n"
+"-n <no> for tags with multiple strings only show string <no>\n"
+"\n"
+"Without options all information available is printed. Valid types are:\n"
+"release, build, model, of_compatible\n",
+ prgname);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ ret = imd_command(argc, argv);
+ if (ret == -ENOSYS) {
+ usage(argv[0]);
+ exit(1);
+ }
+
+ if (ret)
+ fprintf(stderr, "%s\n", strerror(-ret));
+
+ return ret ? 1 : 0;
+}
diff --git a/scripts/canon-a1100-image b/scripts/canon-a1100-image
new file mode 100755
index 0000000000..6c08d7493a
--- /dev/null
+++ b/scripts/canon-a1100-image
@@ -0,0 +1,10 @@
+#!/bin/bash -e
+
+IFILE=$1
+OFILE=$2
+
+dd if=/dev/zero bs=4M count=1 of=$OFILE 2>/dev/null
+dd if=$IFILE of=$OFILE conv=notrunc 2>/dev/null
+
+# 0xffff0000: fe 3f f0 ea b 0xffc00000
+echo -n -e "\xfe\x3f\xf0\xea" | dd of=$OFILE bs=64K seek=63 conv=notrunc 2>/dev/null
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index e80926fa0b..153af8dd82 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -329,7 +329,7 @@ sub top_of_kernel_tree {
my @tree_check = (
"arch", "commands", "common", "COPYING", "CREDITS", "defaultenv",
- "Documentation", "Doxyfile", "drivers", "fs", "include", "lib",
+ "Documentation", "drivers", "fs", "include", "lib",
"MAKEALL", "Makefile", "net", "README", "scripts", "TODO"
);
diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore
index cdabdc95a6..80f6b50fdf 100644
--- a/scripts/dtc/.gitignore
+++ b/scripts/dtc/.gitignore
@@ -2,3 +2,4 @@ dtc
dtc-lexer.lex.c
dtc-parser.tab.c
dtc-parser.tab.h
+fdtget
diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 2a48022c41..05973b12aa 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -1,15 +1,20 @@
# scripts/dtc makefile
-hostprogs-y := dtc
+hostprogs-y := dtc fdtget
always := $(hostprogs-y)
dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
srcpos.o checks.o util.o
dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o
+libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o
+libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o
+
+fdtget-objs += fdtget.o $(libfdt-objs) util.o
+
# Source files need to get at the userspace version of libfdt_env.h to compile
-HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
+HOSTCFLAGS_DTC := -I$(src)
HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
@@ -21,6 +26,15 @@ HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC)
+
HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC)
HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC)
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/fdt.c
index e56833ae9b..e56833ae9b 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/fdt.c
diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/fdt.h
index 48ccfd9100..48ccfd9100 100644
--- a/scripts/dtc/libfdt/fdt.h
+++ b/scripts/dtc/fdt.h
diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c
index f72d13b1d1..f72d13b1d1 100644
--- a/scripts/dtc/libfdt/fdt_empty_tree.c
+++ b/scripts/dtc/fdt_empty_tree.c
diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/fdt_ro.c
index 02b6d68753..02b6d68753 100644
--- a/scripts/dtc/libfdt/fdt_ro.c
+++ b/scripts/dtc/fdt_ro.c
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/fdt_rw.c
index 24437dfc32..24437dfc32 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/fdt_rw.c
diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/fdt_strerror.c
index e6c3ceee8c..e6c3ceee8c 100644
--- a/scripts/dtc/libfdt/fdt_strerror.c
+++ b/scripts/dtc/fdt_strerror.c
diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/fdt_sw.c
index 55ebebf1eb..55ebebf1eb 100644
--- a/scripts/dtc/libfdt/fdt_sw.c
+++ b/scripts/dtc/fdt_sw.c
diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/fdt_wip.c
index 6025fa1fe8..6025fa1fe8 100644
--- a/scripts/dtc/libfdt/fdt_wip.c
+++ b/scripts/dtc/fdt_wip.c
diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt.h
index 73f49759a5..73f49759a5 100644
--- a/scripts/dtc/libfdt/libfdt.h
+++ b/scripts/dtc/libfdt.h
diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt_env.h
index 213d7fb81c..213d7fb81c 100644
--- a/scripts/dtc/libfdt/libfdt_env.h
+++ b/scripts/dtc/libfdt_env.h
diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt_internal.h
index 381133ba81..381133ba81 100644
--- a/scripts/dtc/libfdt/libfdt_internal.h
+++ b/scripts/dtc/libfdt_internal.h
diff --git a/scripts/gen-dtb-s b/scripts/gen-dtb-s
new file mode 100755
index 0000000000..434612f362
--- /dev/null
+++ b/scripts/gen-dtb-s
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+name=$1
+dtb=$2
+imd=$3
+
+echo "#include <asm-generic/barebox.lds.h>"
+
+le32() {
+ printf ".byte 0x%02x, 0x%02x, 0x%02x, 0x%02x\n" \
+ $(($1 & 0xff)) \
+ $((($1 >> 8) & 0xff)) \
+ $((($1 >> 16) & 0xff)) \
+ $((($1 >> 24) & 0xff))
+}
+
+FDTGET=scripts/dtc/fdtget
+
+if [ "$imd" = "y" ]; then
+ echo ".section .barebox_imd_0.${name},\"a\""
+ echo ".global __imd_${name}_start"
+ echo "__imd_${name}_start:"
+
+ compat=$($FDTGET -d notfound -t bi "$dtb" / compatible | sed "s^ ^,^g")
+ if [ "$compat" != "notfound" ]; then
+
+ compatlen=$($FDTGET -t s "$dtb" / compatible | wc -c)
+ le32 0x640c8005
+ le32 $compatlen
+ echo ".byte " $compat
+ echo ".balign 4"
+ fi
+
+ model=$($FDTGET -d notfound -t bi "$dtb" / model | sed "s^ ^,^g")
+
+ if [ "$model" != "notfound" ]; then
+ modellen=$($FDTGET -t s "$dtb" / model | wc -c)
+ le32 0x640c8004
+ le32 $compatlen
+ echo ".byte " $model
+ echo ".balign 4"
+ fi
+fi
+
+echo ".section .dtb.rodata.${name},\"a\""
+echo ".balign STRUCT_ALIGNMENT"
+echo ".global __dtb_${name}_start"
+echo "__dtb_${name}_start:"
+echo ".incbin \"$dtb\""
+echo "__dtb_${name}_end:"
+echo ".global __dtb_${name}_end"
+echo ".balign STRUCT_ALIGNMENT"
+
+if [ "$imd" = "y" ]; then
+ echo ".word __imd_${name}_start"
+fi