summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/boards/imx.rst2
-rw-r--r--Documentation/devicetree/bindings/barebox/barebox,state.rst19
-rw-r--r--Documentation/user/reset-reason.rst47
-rw-r--r--Documentation/user/system-reset.rst64
-rw-r--r--Documentation/user/ubi.rst44
-rw-r--r--Documentation/user/user-manual.rst2
-rw-r--r--Makefile2
-rw-r--r--arch/arm/boards/beagle/Makefile1
-rw-r--r--arch/arm/boards/beagle/board.c20
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/mmc (renamed from arch/arm/boards/beagle/env/boot/mmc)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi (renamed from arch/arm/boards/beagle/env/boot/nand-ubi)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt (renamed from arch/arm/boards/beagle/env/boot/nand-ubi-dt)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand (renamed from arch/arm/boards/beagle/env/init/mtdparts-nand)0
-rw-r--r--arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover (renamed from arch/arm/boards/beagle/env/network/eth0-discover)0
-rw-r--r--arch/arm/boards/beagle/lowlevel.c39
-rw-r--r--arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg3
-rw-r--r--arch/arm/boards/phytec-som-am335x/board.c5
-rw-r--r--arch/arm/configs/am335x_mlo_defconfig1
-rw-r--r--arch/arm/configs/lubbock_defconfig1
-rw-r--r--arch/arm/configs/omap3530_beagle_defconfig81
-rw-r--r--arch/arm/configs/omap3530_beagle_xload_defconfig17
-rw-r--r--arch/arm/configs/phytec-phycard-omap3_defconfig1
-rw-r--r--arch/arm/configs/socfpga_defconfig70
-rw-r--r--arch/arm/cpu/start.c45
-rw-r--r--arch/arm/dts/am33xx-strip.dtsi5
-rw-r--r--arch/arm/dts/imx6dl-tx6u-801x.dts4
-rw-r--r--arch/arm/include/asm/barebox-arm.h27
-rw-r--r--arch/arm/mach-clps711x/reset.c2
-rw-r--r--arch/arm/mach-imx/Kconfig9
-rw-r--r--arch/arm/mach-imx/Makefile1
-rw-r--r--arch/arm/mach-imx/include/mach/bbu.h9
-rw-r--r--arch/arm/mach-mxs/include/mach/imx28-regs.h1
-rw-r--r--arch/arm/mach-mxs/ocotp.c9
-rw-r--r--arch/arm/mach-omap/Kconfig37
-rw-r--r--arch/arm/mach-omap/Makefile6
-rw-r--r--arch/arm/mach-omap/am33xx_bbu_spi_mlo.c56
-rw-r--r--arch/arm/mach-omap/include/mach/bbu.h5
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-clock.h2
-rw-r--r--arch/arm/mach-omap/include/mach/omap3-generic.h2
-rw-r--r--arch/arm/mach-omap/omap3_generic.c5
-rw-r--r--arch/arm/mach-omap/omap3_xload_usb.c185
-rw-r--r--arch/arm/mach-omap/xload.c8
-rw-r--r--arch/arm/mach-pxa/Kconfig1
-rw-r--r--arch/arm/mach-socfpga/Kconfig4
-rw-r--r--arch/arm/mach-tegra/include/mach/lowlevel.h15
-rw-r--r--arch/arm/mach-tegra/tegra_avp_init.c3
-rw-r--r--arch/blackfin/include/asm/io.h8
-rw-r--r--arch/blackfin/include/asm/processor.h6
-rw-r--r--arch/blackfin/include/asm/swab.h8
-rw-r--r--arch/mips/mach-bcm47xx/reset.c5
-rw-r--r--arch/ppc/include/asm/atomic.h8
-rw-r--r--arch/ppc/include/asm/bitops.h20
-rw-r--r--arch/ppc/include/asm/io.h20
-rw-r--r--arch/ppc/include/asm/swab.h8
-rw-r--r--arch/sandbox/include/asm/byteorder.h6
-rw-r--r--commands/automount.c1
-rw-r--r--commands/detect.c5
-rw-r--r--commands/devinfo.c7
-rw-r--r--commands/digest.c2
-rw-r--r--commands/export.c1
-rw-r--r--commands/false.c1
-rw-r--r--commands/help.c1
-rw-r--r--commands/login.c2
-rw-r--r--commands/mount.c2
-rw-r--r--commands/net.c1
-rw-r--r--commands/readline.c1
-rw-r--r--commands/timeout.c1
-rw-r--r--commands/trigger.c1
-rw-r--r--commands/true.c1
-rw-r--r--commands/ubi.c1
-rw-r--r--commands/version.c1
-rw-r--r--common/Kconfig18
-rw-r--r--common/Makefile1
-rw-r--r--common/bbu.c113
-rw-r--r--common/blspec.c59
-rw-r--r--common/complete.c1
-rw-r--r--common/filetype.c3
-rw-r--r--common/imx-bbu-nand-fcb.c (renamed from arch/arm/mach-imx/imx6-bbu-nand.c)248
-rw-r--r--common/kallsyms.c1
-rw-r--r--common/parser.c1
-rw-r--r--common/state.c204
-rw-r--r--drivers/base/driver.c25
-rw-r--r--drivers/bus/omap-gpmc.c144
-rw-r--r--drivers/clk/mxs/clk-imx28.c1
-rw-r--r--drivers/mci/Kconfig2
-rw-r--r--drivers/mtd/Kconfig10
-rw-r--r--drivers/mtd/Makefile1
-rw-r--r--drivers/mtd/core.c42
-rw-r--r--drivers/mtd/devices/Kconfig3
-rw-r--r--drivers/mtd/devices/m25p80.c33
-rw-r--r--drivers/mtd/mtd.h2
-rw-r--r--drivers/mtd/mtdconcat.c765
-rw-r--r--drivers/mtd/mtdoob.c2
-rw-r--r--drivers/mtd/mtdraw.c2
-rw-r--r--drivers/mtd/nor/cfi_flash.c747
-rw-r--r--drivers/mtd/nor/cfi_flash.h138
-rw-r--r--drivers/mtd/nor/cfi_flash_amd.c41
-rw-r--r--drivers/mtd/nor/cfi_flash_intel.c107
-rw-r--r--drivers/mtd/partition.c13
-rw-r--r--drivers/mtd/ubi/build.c9
-rw-r--r--drivers/mtd/ubi/cdev.c4
-rw-r--r--drivers/net/altera_tse.c2
-rw-r--r--drivers/net/ar231x.c2
-rw-r--r--drivers/net/arc_emac.c2
-rw-r--r--drivers/net/at91_ether.c2
-rw-r--r--drivers/net/cpsw.c2
-rw-r--r--drivers/net/cs8900.c2
-rw-r--r--drivers/net/davinci_emac.c2
-rw-r--r--drivers/net/designware.c2
-rw-r--r--drivers/net/dm9k.c2
-rw-r--r--drivers/net/ep93xx.c2
-rw-r--r--drivers/net/ethoc.c2
-rw-r--r--drivers/net/fec_imx.c2
-rw-r--r--drivers/net/fec_mpc5200.c2
-rw-r--r--drivers/net/gianfar.c2
-rw-r--r--drivers/net/ks8851_mll.c2
-rw-r--r--drivers/net/macb.c2
-rw-r--r--drivers/net/mvneta.c2
-rw-r--r--drivers/net/netx_eth.c2
-rw-r--r--drivers/net/orion-gbe.c2
-rw-r--r--drivers/net/rtl8139.c2
-rw-r--r--drivers/net/rtl8169.c2
-rw-r--r--drivers/net/smc91111.c2
-rw-r--r--drivers/net/smc911x.c8
-rw-r--r--drivers/net/tap.c2
-rw-r--r--drivers/net/usb/asix.c2
-rw-r--r--drivers/net/usb/smsc95xx.c2
-rw-r--r--drivers/net/xgmac.c2
-rw-r--r--drivers/of/platform.c2
-rw-r--r--drivers/pci/pci.c44
-rw-r--r--drivers/pwm/Kconfig6
-rw-r--r--drivers/pwm/Makefile1
-rw-r--r--drivers/pwm/core.c7
-rw-r--r--drivers/pwm/pwm-mxs.c174
-rw-r--r--drivers/serial/serial_ns16550.c9
-rw-r--r--drivers/usb/gadget/Kconfig2
-rw-r--r--drivers/usb/musb/musb_core.c13
-rw-r--r--drivers/video/Kconfig12
-rw-r--r--drivers/video/Makefile2
-rw-r--r--drivers/video/backlight-pwm.c199
-rw-r--r--drivers/video/backlight.c90
-rw-r--r--drivers/video/stm.c52
-rw-r--r--dts/Bindings/clock/silabs,si5351.txt4
-rw-r--r--dts/Bindings/input/touchscreen/tsc2005.txt4
-rw-r--r--dts/Bindings/mtd/jedec,spi-nor.txt (renamed from dts/Bindings/mtd/m25p80.txt)6
-rw-r--r--dts/Bindings/net/cdns-emac.txt3
-rw-r--r--dts/Bindings/usb/renesas_usbhs.txt6
-rw-r--r--dts/src/arm/am335x-bone-common.dtsi19
-rw-r--r--dts/src/arm/am335x-boneblack.dts4
-rw-r--r--dts/src/arm/am335x-evmsk.dts2
-rw-r--r--dts/src/arm/am35xx-clocks.dtsi14
-rw-r--r--dts/src/arm/armada-375.dtsi2
-rw-r--r--dts/src/arm/armada-38x.dtsi2
-rw-r--r--dts/src/arm/armada-39x.dtsi2
-rw-r--r--dts/src/arm/armada-xp-linksys-mamba.dts5
-rw-r--r--dts/src/arm/dm816x.dtsi4
-rw-r--r--dts/src/arm/dove-cubox.dts1
-rw-r--r--dts/src/arm/exynos4412-trats2.dts2
-rw-r--r--dts/src/arm/exynos5420-peach-pit.dts1
-rw-r--r--dts/src/arm/exynos5800-peach-pi.dts1
-rw-r--r--dts/src/arm/imx27.dtsi2
-rw-r--r--dts/src/arm/omap3-devkit8000.dts2
-rw-r--r--dts/src/arm/omap3-n900.dts4
-rw-r--r--dts/src/arm/tegra124.dtsi8
-rw-r--r--dts/src/arm/vexpress-v2p-ca15_a7.dts1
-rw-r--r--dts/src/arm/vexpress-v2p-ca9.dts11
-rw-r--r--dts/src/arm/zynq-7000.dtsi4
-rw-r--r--dts/src/arm64/arm/juno-motherboard.dtsi31
-rw-r--r--dts/src/arm64/mediatek/mt8173-evb.dts3
-rw-r--r--fs/cramfs/cramfs.c1
-rw-r--r--fs/fat/fat.c1
-rw-r--r--fs/ramfs.c1
-rw-r--r--fs/tftp.c47
-rw-r--r--images/Makefile3
-rw-r--r--images/Makefile.am33xx28
-rw-r--r--images/Makefile.omap319
-rw-r--r--include/bbu.h23
-rw-r--r--include/blspec.h1
-rw-r--r--include/digest.h11
-rw-r--r--include/filetype.h1
-rw-r--r--include/linux/bitops.h4
-rw-r--r--include/linux/mtd/concat.h34
-rw-r--r--include/linux/mtd/mtd.h2
-rw-r--r--include/net.h4
-rw-r--r--include/of.h2
-rw-r--r--include/pwm.h2
-rw-r--r--include/video/backlight.h20
-rw-r--r--include/xfuncs.h1
-rw-r--r--lib/fnmatch.c1
-rw-r--r--lib/gui/bmp.c11
-rw-r--r--lib/gui/image_renderer.c8
-rw-r--r--lib/libfile.c4
-rw-r--r--lib/lzo/lzo1x_decompress_safe.c1
-rw-r--r--lib/parameter.c14
-rw-r--r--lib/random.c1
-rw-r--r--lib/strtox.c1
-rw-r--r--lib/xfuncs.c22
-rw-r--r--net/Makefile1
-rw-r--r--net/dns.c13
-rw-r--r--net/eth.c27
-rw-r--r--net/lib.c109
-rw-r--r--net/net.c81
-rw-r--r--net/nfs.c1
-rw-r--r--scripts/Makefile3
-rw-r--r--scripts/omap3-usb-loader.c921
205 files changed, 4749 insertions, 1214 deletions
diff --git a/Documentation/boards/imx.rst b/Documentation/boards/imx.rst
index ef1a6a507e..837bf5cf32 100644
--- a/Documentation/boards/imx.rst
+++ b/Documentation/boards/imx.rst
@@ -47,7 +47,7 @@ The images can also always be started second stage::
bootm /mnt/tftp/barebox-freescale-imx51-babbage.img
Internal Boot Mode Through Internal RAM(IRAM)
----------------------------------------
+---------------------------------------------
The Internal Boot Mode Through Internal RAM is supported on:
diff --git a/Documentation/devicetree/bindings/barebox/barebox,state.rst b/Documentation/devicetree/bindings/barebox/barebox,state.rst
index 3d664f1f02..4c5b06db47 100644
--- a/Documentation/devicetree/bindings/barebox/barebox,state.rst
+++ b/Documentation/devicetree/bindings/barebox/barebox,state.rst
@@ -40,8 +40,8 @@ variable. The node name may end with ``@<ADDRESS>``, but the suffix is
sripped from the variable name.
State variables have a type. Currenty supported types are: ``uint8``,
-``uint32``, ``enum32`` and ``mac`` address. Fixed length strings are
-planned but not implemented. Variable length strings are not planned.
+``uint32``, ``enum32``, ``mac`` address or ``string``. Variable length
+strings are not planned.
Required properties:
@@ -49,8 +49,8 @@ Required properties:
``#size-cells = <1>``. Defines the ``offset`` and ``size`` of the
variable in the ``raw`` backend. ``size`` must fit the node
``type``. Variables are not allowed to overlap.
-* ``type``: Should be ``uint8``, ``uint32``, ``enum32`` or ``mac`` for
- the type of the variable
+* ``type``: Should be ``uint8``, ``uint32``, ``enum32``, ``mac`` or
+ ``string`` for the type of the variable
* ``names``: For ``enum32`` values only, this specifies the values
possible for ``enum32``.
@@ -82,6 +82,17 @@ Example::
};
};
+Variable Types
+--------------
+
+* ``uint8``:
+* ``uint32``:
+* ``enum32``: The ``default`` value is an integer representing an
+ offset into the names array.
+* ``mac``:
+* ``string``: The length of the string excluding the trailing 0 is
+ determined by the length given in the ``reg`` property.
+
Backends
--------
diff --git a/Documentation/user/reset-reason.rst b/Documentation/user/reset-reason.rst
new file mode 100644
index 0000000000..26d37f86dd
--- /dev/null
+++ b/Documentation/user/reset-reason.rst
@@ -0,0 +1,47 @@
+.. _reset_reason:
+
+Reset Reason
+------------
+
+To handle a device in a secure and safe manner many applications are using
+a watchdog or other ways to reset a system to bring it back into life if it
+hangs or crashes somehow.
+
+In these cases the hardware restarts and runs the bootloader again. Depending on
+the root cause of the hang or crash, the bootloader sometimes should not just
+re-start the main system again. Maybe it should do some kind of recovery instead.
+For example it should wait for another update (for the case the cause of a
+crash is a failed update) or should start into a fall back system instead.
+
+In order to handle failing systems gracefully the bootloader needs the
+information why it runs. This is called the "reset reason". It is provided by
+the global variable ``system.reset`` and can be used in scripts via
+``$global.system.reset``.
+
+The following values can help to detect the reason why the bootloader runs:
+
+* ``unknown``: the software wasn't able to detect the reset cause or there
+ isn't support for this feature at all.
+* ``POR`` (Power On Reset): a cold start. The power of the system
+ was switched on. This is a regular state and nothing to worry about.
+* ``RST`` (ReSeT): a warm start. The user has triggered a reset somehow. This
+ is a regular state and nothing to worry about.
+* ``WDG`` (WatchDoG): also some kind of warm start, but triggered by a watchdog
+ unit. It depends on the application if this reason signals a regular state
+ and therefore nothing to worry about, or if this state was entered by a hanging
+ or crashed system and must implicitly be handled.
+* ``WKE`` (WaKEup): a mixture of cold and warm start. The system is woken up
+ from some state of suspend. This is a regular state and nothing to worry
+ about.
+* ``JTAG``: an external JTAG based debugger has triggered the reset.
+* ``THERM`` (THERMal): some SoCs are able to detect if they got reset in
+ response to an overtemperature event. This can be a regular state and nothing
+ to worry about (the reset has brought the system back into a safe state) or
+ must implicitly be handled.
+* ``EXT`` (EXTernal): some SoCs have special device pins for external reset
+ signals other than the ``RST`` one. Application specific how to handle this
+ state.
+
+It depends on your board/SoC and its features if the hardware is able to detect
+these reset reasons. Most of the time only ``POR`` and ``RST`` are supported
+but often ``WDG`` as well.
diff --git a/Documentation/user/system-reset.rst b/Documentation/user/system-reset.rst
new file mode 100644
index 0000000000..e76e3a23c1
--- /dev/null
+++ b/Documentation/user/system-reset.rst
@@ -0,0 +1,64 @@
+.. _system_reset:
+
+System Restart
+--------------
+
+When running the reset command barebox restarts the SoC somehow. Restart can
+be done in software, but a more reliable way is to use a hard reset line, which
+really resets the whole machine.
+The most common way to force such a hard reset is by using a watchdog. Its
+trigger time will be setup as short as possible and after that the software just
+waits for its reset. Very simple and most of the time it does what's expected.
+
+But there are some drawbacks within this simple approach.
+
+* most used watchdogs are built-in units in the SoCs. There is nothing wrong
+ with that, but these units can mostly reset the CPU core and sometimes a little
+ bit more of the SoC. This means this reset is not exactly the same than the
+ real POR (e.g. power on reset). In this case you must still handle different
+ hardware in a special way because it hasn't seen the reset the CPU has seen.
+ Enabled DMA units for example can continue to run and transfer data while the
+ CPU core runs through its reset code. This can trigger very strange failures.
+
+* when interacting with flash memories (mostly NOR types and used to store the
+ root filesystem) it cannot provide data (sometimes called 'array mode') the
+ CPU wants to read after a reset while it is still in some programming mode.
+ And if the software is currently changing some data inside the flash and
+ an internal reset happens the CPU and the flash memory are doing different
+ things and the system hangs until a real POR which also resets the flash
+ memory into the 'array mode'.
+
+* some SoC's boot behaviour gets parametrized by so called 'bootstrap pins'.
+ These pins can have a different meaning at reset time and at run-time later
+ on (multi purpose pins) but their correct values at reset time are very
+ important to boot the SoC sucessfully. If external devices are connected to
+ these multi purpose pins they can disturb the reset values, and so parametrizing
+ the boot behaviour differently and hence crashing the SoC until the next real
+ POR happens which also resets the external devices (and keep them away from the
+ multi purpose pins).
+
+* when power management comes into play another level of failure is
+ possible. To save power the software can lower the clock(s), but to really
+ save power, the power supply voltages must be lowered as well. Most PMICs
+ (e.g. power management controllers) are dedicated external companion devices,
+ loosely connected to their SoC. If the SoC's internal reset source now resets
+ the CPU it may increases its clock(s) back to the frequencies after a POR, but
+ the external PMIC still provides voltages related to lower frequencies. The
+ system isn't consistent any more. If you are in luck, the SoC still works
+ somehow, even if the voltages are out of their specifications for the
+ currently used clock speeds. But don't rely on it.
+
+To workaround these issues the reset signal triggered by a SoC internal source
+must be 'visible' to the external devices to also reset them like a real POR does.
+But many SoCs do not provide such a signal. So you can't use the internal reset
+source if you face one of the above listed issues!
+
+A different solution is to use the PMIC (if available) to trigger the reset.
+Many PMICs provide their own watchdog units and if they trigger a reset they
+also switch their voltages back to the real POR values. This will be a system
+wide reset, like the POR is.
+
+Drawback of the PMIC solution is, you can't use the SoC's internal mechanisms to
+detect the :ref:`reset_reason` anymore. From the SoC point of view it is always
+a POR when the PMIC handles the system reset. If you are in luck the PMIC
+instead can provide this information if you depend on it.
diff --git a/Documentation/user/ubi.rst b/Documentation/user/ubi.rst
index a187680e2c..c300c0f951 100644
--- a/Documentation/user/ubi.rst
+++ b/Documentation/user/ubi.rst
@@ -5,9 +5,6 @@ barebox has both UBI and UBIFS support. For handling UBI barebox has commands si
the Linux commands :ref:`command_ubiformat`, :ref:`command_ubiattach`, :ref:`command_ubidetach`,
:ref:`command_ubimkvol` and :ref:`command_ubirmvol`.
-The following examples assume we work on the first UBI device. Replace ``ubi0`` with
-the appropriate number when you have multiple UBI devices.
-
The first step for preparing a pristine Flash for UBI is to :ref:`command_ubiformat` the
device:
@@ -28,17 +25,17 @@ After a device has been formatted it can be attached with :ref:`command_ubiattac
ubiattach /dev/nand0.root
-This will create the controlling node ``/dev/ubi0`` and also register all volumes present
-on the device as ``/dev/ubi0.<volname>``. When freshly formatted there won't be any volumes
-present. A volume can be created with:
+This will create the controlling node ``/dev/nand0.root.ubi`` and also register all volumes
+present on the device as ``/dev/nand0.root.ubi.<volname>``. When freshly formatted there won't
+be any volumes present. A volume can be created with:
.. code-block:: sh
- ubimkvol /dev/ubi0 root 0
+ ubimkvol /dev/nand0.root.ubi root 0
The first parameter is the controlling node. The second parameter is the name of the volume.
-In this case the volume can be found under ``/dev/ubi.root``. The third parameter contains
-the size. A size of zero means that all available space shall be used.
+In this case the volume can be found under ``/dev/dev/nand0.root.ubi.root``. The third
+parameter contains the size. A size of zero means that all available space shall be used.
The next step is to write a UBIFS image to the volume. The image must be created on a host using
the ``mkfs.ubifs`` command. ``mkfs.ubifs`` requires several arguments for describing the
@@ -46,7 +43,7 @@ flash layout. Values for these arguments can be retrieved from a ``devinfo ubi``
.. code-block:: sh
- barebox@Phytec pcm970:/ devinfo ubi0
+ barebox@Phytec pcm970:/ devinfo nand0.root.ubi
Parameters:
peb_size: 16384
leb_size: 15360
@@ -76,38 +73,27 @@ The UBIFS image can be transferred to the board for example with TFTP:
.. code-block:: sh
- cp /mnt/tftp/root.ubifs /dev/ubi0.root
+ cp /mnt/tftp/root.ubifs /dev/nand0.root.ubi.root
Finally it can be mounted using the :ref:`command_mount` command:
.. code-block:: sh
- mkdir -p /mnt/ubi
- mount -t ubifs /dev/ubi0.root /mnt/ubi
+ mount /dev/nand0.root.ubi.root
+The default mount path when the mount point is skipped is ``/mnt/<devname>``,
+so in this example it will be ``/mnt/nand0.root.ubi.root``.
The second time the UBIFS is mounted the above can be simplified to:
.. code-block:: sh
ubiattach /dev/nand0.root
- mount -t ubifs /dev/ubi0.root /mnt/ubi
+ mount /dev/nand0.root.ubi.root
Mounting the UBIFS can also be made transparent with the automount command.
-With this helper script in ``/env/bin/automount-ubi:``:
-
-.. code-block:: sh
-
- #!/bin/sh
-
- if [ ! -e /dev/ubi0 ]; then
- ubiattach /dev/nand0 || exit 1
- fi
-
- mount -t ubifs /dev/ubi0.root $automount_path
-
-
-The command ``automount -d /mnt/ubi/ '/env/bin/automount-ubi'`` will automatically
-attach the UBI device and mount the UBIFS image to ``/mnt/ubi`` whenever ``/mnt/ubi``
+The command ``automount -d /mnt/nand0.root.ubi.root 'mount nand0.root.ubi.root'``
+will automatically attach the UBI device and mount the UBIFS image to
+``/mnt/nand0.root.ubi.root`` whenever ``/mnt/nand0.root.ubi.root``
is first accessed. The automount command can be added to ``/env/init/automount`` to
execute it during startup.
diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst
index 3d68bbb9ae..0d6daee70e 100644
--- a/Documentation/user/user-manual.rst
+++ b/Documentation/user/user-manual.rst
@@ -28,6 +28,8 @@ Contents:
ubi
booting-linux
system-setup
+ reset-reason
+ system-reset
* :ref:`search`
* :ref:`genindex`
diff --git a/Makefile b/Makefile
index 976ae322d4..e7db67af85 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
VERSION = 2015
-PATCHLEVEL = 06
+PATCHLEVEL = 07
SUBLEVEL = 0
EXTRAVERSION =
NAME = None
diff --git a/arch/arm/boards/beagle/Makefile b/arch/arm/boards/beagle/Makefile
index 01c7a259e9..3bee9a22ab 100644
--- a/arch/arm/boards/beagle/Makefile
+++ b/arch/arm/boards/beagle/Makefile
@@ -1,2 +1,3 @@
obj-y += board.o
lwl-y += lowlevel.o
+bbenv-y += defaultenv-beagle
diff --git a/arch/arm/boards/beagle/board.c b/arch/arm/boards/beagle/board.c
index 775621069c..4ac9517dbe 100644
--- a/arch/arm/boards/beagle/board.c
+++ b/arch/arm/boards/beagle/board.c
@@ -21,7 +21,10 @@
#include <driver.h>
#include <linux/sizes.h>
#include <io.h>
+#include <bbu.h>
+#include <filetype.h>
#include <ns16550.h>
+#include <envfs.h>
#include <asm/armlinux.h>
#include <generated/mach-types.h>
#include <mach/gpmc.h>
@@ -31,6 +34,7 @@
#include <i2c/i2c.h>
#include <linux/err.h>
#include <usb/ehci.h>
+#include <asm/barebox-arm.h>
#ifdef CONFIG_DRIVER_SERIAL_NS16550
@@ -42,6 +46,9 @@
*/
static int beagle_console_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
barebox_set_model("Texas Instruments beagle");
barebox_set_hostname("beagle");
@@ -82,6 +89,9 @@ static struct gpmc_nand_platform_data nand_plat = {
static int beagle_mem_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
omap_add_ram0(SZ_128M);
return 0;
@@ -90,6 +100,9 @@ mem_initcall(beagle_mem_init);
static int beagle_devices_init(void)
{
+ if (barebox_arm_machine() != MACH_TYPE_OMAP3_BEAGLE)
+ return 0;
+
i2c_register_board_info(0, i2c_devices, ARRAY_SIZE(i2c_devices));
omap3_add_i2c1(NULL);
@@ -107,6 +120,13 @@ static int beagle_devices_init(void)
armlinux_set_architecture(MACH_TYPE_OMAP3_BEAGLE);
+ bbu_register_std_file_update("nand-xload", 0,
+ "/dev/nand0.xload.bb", filetype_ch_image);
+ bbu_register_std_file_update("nand", 0,
+ "/dev/nand0.barebox.bb", filetype_arm_barebox);
+
+ defaultenv_append_directory(defaultenv_beagle);
+
return 0;
}
device_initcall(beagle_devices_init);
diff --git a/arch/arm/boards/beagle/env/boot/mmc b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
index db638f8cf8..db638f8cf8 100644
--- a/arch/arm/boards/beagle/env/boot/mmc
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/mmc
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
index e0ef904432..e0ef904432 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi
diff --git a/arch/arm/boards/beagle/env/boot/nand-ubi-dt b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
index 5fc0a6c53a..5fc0a6c53a 100644
--- a/arch/arm/boards/beagle/env/boot/nand-ubi-dt
+++ b/arch/arm/boards/beagle/defaultenv-beagle/boot/nand-ubi-dt
diff --git a/arch/arm/boards/beagle/env/init/mtdparts-nand b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
index 9335bb17a3..9335bb17a3 100644
--- a/arch/arm/boards/beagle/env/init/mtdparts-nand
+++ b/arch/arm/boards/beagle/defaultenv-beagle/init/mtdparts-nand
diff --git a/arch/arm/boards/beagle/env/network/eth0-discover b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
index 86d13f5c43..86d13f5c43 100644
--- a/arch/arm/boards/beagle/env/network/eth0-discover
+++ b/arch/arm/boards/beagle/defaultenv-beagle/network/eth0-discover
diff --git a/arch/arm/boards/beagle/lowlevel.c b/arch/arm/boards/beagle/lowlevel.c
index d6e6b9f91c..30cc1f2c54 100644
--- a/arch/arm/boards/beagle/lowlevel.c
+++ b/arch/arm/boards/beagle/lowlevel.c
@@ -1,4 +1,5 @@
#include <init.h>
+#include <debug_ll.h>
#include <io.h>
#include <linux/sizes.h>
#include <asm/barebox-arm-head.h>
@@ -11,6 +12,7 @@
#include <mach/sdrc.h>
#include <mach/syslib.h>
#include <mach/sys_info.h>
+#include <generated/mach-types.h>
/**
* @brief Do the pin muxing required for Board operation.
@@ -157,6 +159,22 @@ static void sdrc_init(void)
return;
}
+static noinline int beagle_board_init_sdram(void)
+{
+ struct barebox_arm_boarddata *bd = (void *)OMAP3_SRAM_SCRATCH_SPACE + 0x10;
+
+ boarddata_create(bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, bd);
+}
+
+ENTRY_FUNCTION(start_omap3_beagleboard_sdram, bootinfo, r1, r2)
+{
+ omap3_save_bootinfo((void *)bootinfo);
+
+ beagle_board_init_sdram();
+}
+
/**
* @brief The basic entry point for board initialization.
*
@@ -166,28 +184,37 @@ static void sdrc_init(void)
*
* @return void
*/
-static int beagle_board_init(void)
+static noinline int beagle_board_init(void)
{
int in_sdram = omap3_running_in_sdram();
+ struct barebox_arm_boarddata bd;
if (!in_sdram)
omap3_core_init();
mux_config();
+
+ omap_uart_lowlevel_init((void *)OMAP3_UART3_BASE);
+
/* Dont reconfigure SDRAM while running in SDRAM! */
if (!in_sdram)
sdrc_init();
- return 0;
+ boarddata_create(&bd, MACH_TYPE_OMAP3_BEAGLE);
+
+ barebox_arm_entry(0x80000000, SZ_128M, &bd);
}
-void __naked __bare_init barebox_arm_reset_vector(uint32_t *data)
+ENTRY_FUNCTION(start_omap3_beagleboard_sram, bootinfo, r1, r2)
{
- omap3_save_bootinfo(data);
+ omap3_save_bootinfo((void *)bootinfo);
arm_cpu_lowlevel_init();
- beagle_board_init();
+ omap3_gp_romcode_call(OMAP3_GP_ROMCODE_API_L2_INVAL, 0);
+
+ relocate_to_current_adr();
+ setup_c();
- barebox_arm_entry(0x80000000, SZ_128M, NULL);
+ beagle_board_init();
}
diff --git a/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg b/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
index 95bcd19805..f43b484ee6 100644
--- a/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
+++ b/arch/arm/boards/freescale-mx53-qsb/flash-header-imx53-loco.imxcfg
@@ -30,7 +30,7 @@ wm 32 0x63fd9090 0x4d444c44
wm 32 0x63fd907c 0x01370138
wm 32 0x63fd9080 0x013b013c
wm 32 0x63fd9018 0x00011740
-wm 32 0x63fd9000 0xc3190000
+wm 32 0x63fd9000 0x83190000
wm 32 0x63fd900c 0x9f5152e3
wm 32 0x63fd9010 0xb68e8a63
wm 32 0x63fd9014 0x01ff00db
@@ -43,6 +43,7 @@ wm 32 0x63fd901c 0x00008033
wm 32 0x63fd901c 0x00028031
wm 32 0x63fd901c 0x052080b0
wm 32 0x63fd901c 0x04008040
+wm 32 0x63fd9000 0xc3190000
wm 32 0x63fd901c 0x0000803a
wm 32 0x63fd901c 0x0000803b
wm 32 0x63fd901c 0x00028039
diff --git a/arch/arm/boards/phytec-som-am335x/board.c b/arch/arm/boards/phytec-som-am335x/board.c
index 74e39d70fc..7a878415f8 100644
--- a/arch/arm/boards/phytec-som-am335x/board.c
+++ b/arch/arm/boards/phytec-som-am335x/board.c
@@ -68,7 +68,10 @@ static int physom_devices_init(void)
of_device_enable_path("/chosen/environment-spi");
break;
case BOOTSOURCE_MMC:
- omap_set_bootmmc_devname("mmc0");
+ if (bootsource_get_instance() == 0)
+ omap_set_bootmmc_devname("mmc0");
+ else
+ omap_set_bootmmc_devname("mmc1");
break;
default:
of_device_enable_path("/chosen/environment-nand");
diff --git a/arch/arm/configs/am335x_mlo_defconfig b/arch/arm/configs/am335x_mlo_defconfig
index 1dd7567d0d..b66a653681 100644
--- a/arch/arm/configs/am335x_mlo_defconfig
+++ b/arch/arm/configs/am335x_mlo_defconfig
@@ -9,6 +9,7 @@ CONFIG_THUMB2_BAREBOX=y
# CONFIG_MEMINFO is not set
CONFIG_MMU=y
CONFIG_TEXT_BASE=0x0
+CONFIG_BAREBOX_MAX_PBLX_SIZE=0x1b400
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_RELOCATABLE=y
diff --git a/arch/arm/configs/lubbock_defconfig b/arch/arm/configs/lubbock_defconfig
index bf04fa3b18..224854c7cc 100644
--- a/arch/arm/configs/lubbock_defconfig
+++ b/arch/arm/configs/lubbock_defconfig
@@ -6,7 +6,6 @@ CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
# CONFIG_BANNER is not set
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0xa3d00000
CONFIG_BAREBOX_MAX_BARE_INIT_SIZE=0x80000
CONFIG_MALLOC_SIZE=0x1000000
CONFIG_EXPERIMENTAL=y
diff --git a/arch/arm/configs/omap3530_beagle_defconfig b/arch/arm/configs/omap3530_beagle_defconfig
index 3068fbb94b..070f1566ee 100644
--- a/arch/arm/configs/omap3530_beagle_defconfig
+++ b/arch/arm/configs/omap3530_beagle_defconfig
@@ -1,67 +1,79 @@
CONFIG_ARCH_OMAP=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
-CONFIG_PBL_IMAGE=y
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x87e00000
-CONFIG_MALLOC_SIZE=0x2000000
+CONFIG_TEXT_BASE=0x0
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="barebox> "
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
+CONFIG_BLSPEC=y
+CONFIG_IMD_TARGET=y
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_DEFAULT_ENVIRONMENT_PATH="arch/arm/boards/beagle/env"
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_DIRNAME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_READLINK=y
-CONFIG_CMD_TFTP=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_LOADB=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_RESET_SOURCE=y
+CONFIG_DEBUG_LL=y
+CONFIG_DEBUG_OMAP_UART_PORT=3
+CONFIG_DEBUG_INITCALLS=y
+CONFIG_CMD_DMESG=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
-CONFIG_CMD_FLASH=y
+CONFIG_CMD_IMD=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
CONFIG_CMD_BOOTM_OFTREE_UIMAGE=y
# CONFIG_CMD_BOOTU is not set
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_LOADB=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_DEFAULTENV=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
-CONFIG_CMD_I2C=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_READF=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
+CONFIG_CMD_HOST=y
CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_TFTP=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_MENUTREE=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_DETECT=y
+CONFIG_CMD_FLASH=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_I2C=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_TIME=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
CONFIG_NET_NFS=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
-CONFIG_NET_RESOLV=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
CONFIG_NET_USB=y
@@ -81,6 +93,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
CONFIG_MCI_OMAP_HSMMC=y
CONFIG_MFD_TWL4030=y
+CONFIG_FS_EXT4=y
CONFIG_FS_TFTP=y
CONFIG_FS_NFS=y
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/omap3530_beagle_xload_defconfig b/arch/arm/configs/omap3530_beagle_xload_defconfig
index 585ee0f1d1..074cc2116b 100644
--- a/arch/arm/configs/omap3530_beagle_xload_defconfig
+++ b/arch/arm/configs/omap3530_beagle_xload_defconfig
@@ -1,21 +1,25 @@
CONFIG_ARCH_OMAP=y
CONFIG_OMAP_BUILD_IFT=y
+CONFIG_OMAP3_USBBOOT=y
+CONFIG_OMAP3_USB_LOADER=y
+CONFIG_OMAP_MULTI_BOARDS=y
CONFIG_MACH_BEAGLE=y
CONFIG_THUMB2_BAREBOX=y
-# CONFIG_CMD_ARM_CPUINFO is not set
-# CONFIG_ARM_EXCEPTIONS is not set
-CONFIG_TEXT_BASE=0x40200000
-CONFIG_MEMORY_LAYOUT_FIXED=y
-CONFIG_STACK_BASE=0x4020F000
+CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
+CONFIG_ARM_UNWIND=y
+CONFIG_MMU=y
+CONFIG_TEXT_BASE=0x0
CONFIG_STACK_SIZE=0xc00
-CONFIG_MALLOC_BASE=0x87BFFF10
+CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_DUMMY=y
+CONFIG_RELOCATABLE=y
CONFIG_PROMPT="X-load Beagle>"
CONFIG_SHELL_NONE=y
# CONFIG_ERRNO_MESSAGES is not set
# CONFIG_TIMESTAMP is not set
CONFIG_CONSOLE_SIMPLE=y
# CONFIG_DEFAULT_ENVIRONMENT is not set
+CONFIG_OFDEVICE=y
CONFIG_DRIVER_SERIAL_NS16550=y
CONFIG_DRIVER_SERIAL_NS16550_OMAP_EXTENSIONS=y
# CONFIG_SPI is not set
@@ -33,6 +37,7 @@ CONFIG_MCI=y
CONFIG_MCI_STARTUP=y
# CONFIG_MCI_WRITE is not set
CONFIG_MCI_OMAP_HSMMC=y
+# CONFIG_PINCTRL is not set
# CONFIG_FS_RAMFS is not set
# CONFIG_FS_DEVFS is not set
CONFIG_FS_FAT=y
diff --git a/arch/arm/configs/phytec-phycard-omap3_defconfig b/arch/arm/configs/phytec-phycard-omap3_defconfig
index a2564d4459..5865ebd8b9 100644
--- a/arch/arm/configs/phytec-phycard-omap3_defconfig
+++ b/arch/arm/configs/phytec-phycard-omap3_defconfig
@@ -7,7 +7,6 @@ CONFIG_CPU_V7=y
CONFIG_CPU_32v7=y
CONFIG_ARCH_OMAP3=y
CONFIG_OMAP_CLOCK_SOURCE_S32K=y
-CONFIG_OMAP3_CLOCK_CONFIG=y
CONFIG_OMAP3_COPY_CLOCK_SRAM=n
CONFIG_OMAP_GPMC=y
CONFIG_MACH_PCAAL1=y
diff --git a/arch/arm/configs/socfpga_defconfig b/arch/arm/configs/socfpga_defconfig
index ca54a1a491..ec369ae42e 100644
--- a/arch/arm/configs/socfpga_defconfig
+++ b/arch/arm/configs/socfpga_defconfig
@@ -1,70 +1,68 @@
CONFIG_ARCH_SOCFPGA=y
-CONFIG_ARCH_SOCFPGA_FPGA=y
CONFIG_MACH_SOCFPGA_EBV_SOCRATES=y
CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT=y
CONFIG_THUMB2_BAREBOX=y
-CONFIG_CMD_ARM_MMUINFO=y
CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y
CONFIG_ARM_UNWIND=y
CONFIG_MMU=y
-CONFIG_TEXT_BASE=0x0
CONFIG_MALLOC_SIZE=0x0
CONFIG_MALLOC_TLSF=y
CONFIG_KALLSYMS=y
CONFIG_RELOCATABLE=y
-CONFIG_LONGHELP=y
CONFIG_HUSH_FANCY_PROMPT=y
CONFIG_CMDLINE_EDITING=y
CONFIG_AUTO_COMPLETE=y
CONFIG_MENU=y
# CONFIG_TIMESTAMP is not set
CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y
-CONFIG_CMD_EDIT=y
-CONFIG_CMD_SLEEP=y
-CONFIG_CMD_MSLEEP=y
-CONFIG_CMD_SAVEENV=y
-CONFIG_CMD_EXPORT=y
-CONFIG_CMD_PRINTENV=y
-CONFIG_CMD_READLINE=y
-CONFIG_CMD_LET=y
-CONFIG_CMD_MENU=y
-CONFIG_CMD_MENU_MANAGEMENT=y
-CONFIG_CMD_TIME=y
-CONFIG_CMD_LN=y
-CONFIG_CMD_FILETYPE=y
-CONFIG_CMD_ECHO_E=y
-CONFIG_CMD_MEMINFO=y
+CONFIG_LONGHELP=y
CONFIG_CMD_IOMEM=y
-CONFIG_CMD_MM=y
-CONFIG_CMD_CRC=y
-CONFIG_CMD_CRC_CMP=y
-CONFIG_CMD_MD5SUM=y
+CONFIG_CMD_MEMINFO=y
+CONFIG_CMD_ARM_MMUINFO=y
CONFIG_CMD_BOOTM_SHOW_TYPE=y
CONFIG_CMD_BOOTM_VERBOSE=y
CONFIG_CMD_BOOTM_INITRD=y
CONFIG_CMD_BOOTM_OFTREE=y
-CONFIG_CMD_RESET=y
CONFIG_CMD_GO=y
-CONFIG_CMD_OFTREE=y
-CONFIG_CMD_OF_PROPERTY=y
-CONFIG_CMD_OF_NODE=y
-CONFIG_CMD_MEMTEST=y
-CONFIG_CMD_BAREBOX_UPDATE=y
-CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_RESET=y
CONFIG_CMD_PARTITION=y
+CONFIG_CMD_EXPORT=y
+CONFIG_CMD_PRINTENV=y
CONFIG_CMD_MAGICVAR=y
CONFIG_CMD_MAGICVAR_HELP=y
-CONFIG_CMD_GPIO=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_FILETYPE=y
+CONFIG_CMD_LN=y
+CONFIG_CMD_MD5SUM=y
CONFIG_CMD_UNCOMPRESS=y
-CONFIG_CMD_SPI=y
-CONFIG_CMD_LED=y
-CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_LET=y
+CONFIG_CMD_MSLEEP=y
+CONFIG_CMD_SLEEP=y
+CONFIG_CMD_DHCP=y
CONFIG_CMD_MIITOOL=y
+CONFIG_CMD_PING=y
+CONFIG_CMD_ECHO_E=y
+CONFIG_CMD_EDIT=y
+CONFIG_CMD_MENU=y
+CONFIG_CMD_MENU_MANAGEMENT=y
+CONFIG_CMD_READLINE=y
+CONFIG_CMD_TIMEOUT=y
+CONFIG_CMD_CRC=y
+CONFIG_CMD_CRC_CMP=y
+CONFIG_CMD_MEMTEST=y
+CONFIG_CMD_MM=y
CONFIG_CMD_CLK=y
CONFIG_CMD_DETECT=y
+CONFIG_CMD_GPIO=y
+CONFIG_CMD_LED=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_LED_TRIGGER=y
+CONFIG_CMD_BAREBOX_UPDATE=y
+CONFIG_CMD_OF_NODE=y
+CONFIG_CMD_OF_PROPERTY=y
+CONFIG_CMD_OFTREE=y
+CONFIG_CMD_TIME=y
CONFIG_NET=y
-CONFIG_CMD_DHCP=y
-CONFIG_CMD_PING=y
CONFIG_NET_NETCONSOLE=y
CONFIG_NET_RESOLV=y
CONFIG_OFDEVICE=y
diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c
index 304ed0cee7..8e5097b560 100644
--- a/arch/arm/cpu/start.c
+++ b/arch/arm/cpu/start.c
@@ -28,17 +28,22 @@
#include <asm/cache.h>
#include <memory.h>
+#include <debug_ll.h>
#include "mmu-early.h"
unsigned long arm_stack_top;
static void *barebox_boarddata;
-/*
- * return the boarddata variable passed to barebox_arm_entry
- */
-void *barebox_arm_boarddata(void)
+u32 barebox_arm_machine(void)
{
- return barebox_boarddata;
+ struct barebox_arm_boarddata *bd;
+
+ if (!barebox_boarddata)
+ return 0;
+
+ bd = barebox_boarddata;
+
+ return bd->machine;
}
static void *barebox_boot_dtb;
@@ -61,6 +66,8 @@ static noinline __noreturn void __start(unsigned long membase,
setup_c();
+ barrier();
+
pr_debug("memory at 0x%08lx, size 0x%08lx\n", membase, memsize);
barebox_boarddata = boarddata;
@@ -81,17 +88,23 @@ static noinline __noreturn void __start(unsigned long membase,
}
}
- /*
- * If boarddata is a pointer inside valid memory and contains a
- * FDT magic then use it as later to probe devices
- */
- if (boarddata && get_unaligned_be32(boarddata) == FDT_MAGIC) {
- uint32_t totalsize = get_unaligned_be32(boarddata + 4);
- endmem -= ALIGN(totalsize, 64);
- barebox_boot_dtb = (void *)endmem;
- pr_debug("found DTB in boarddata, copying to 0x%p\n",
- barebox_boot_dtb);
- memcpy(barebox_boot_dtb, boarddata, totalsize);
+ if (boarddata) {
+ if (get_unaligned_be32(boarddata) == FDT_MAGIC) {
+ uint32_t totalsize = get_unaligned_be32(boarddata + 4);
+ endmem -= ALIGN(totalsize, 64);
+ barebox_boot_dtb = (void *)endmem;
+ pr_debug("found DTB in boarddata, copying to 0x%p\n",
+ barebox_boot_dtb);
+ memcpy(barebox_boot_dtb, boarddata, totalsize);
+ } else if (((struct barebox_arm_boarddata *)boarddata)->magic ==
+ BAREBOX_ARM_BOARDDATA_MAGIC) {
+ endmem -= ALIGN(sizeof(struct barebox_arm_boarddata), 64);
+ barebox_boarddata = (void *)endmem;
+ pr_debug("found machine type in boarddata, copying to 0x%p\n",
+ barebox_boarddata);
+ memcpy(barebox_boarddata, boarddata,
+ sizeof(struct barebox_arm_boarddata));
+ }
}
if ((unsigned long)_text > membase + memsize ||
diff --git a/arch/arm/dts/am33xx-strip.dtsi b/arch/arm/dts/am33xx-strip.dtsi
index 3dc9a5798a..04cf3151ea 100644
--- a/arch/arm/dts/am33xx-strip.dtsi
+++ b/arch/arm/dts/am33xx-strip.dtsi
@@ -11,8 +11,6 @@
aliases {
/delete-property/ i2c1;
/delete-property/ i2c2;
- /delete-property/ mmc0;
- /delete-property/ mmc1;
/delete-property/ mmc2;
/delete-property/ d_can0;
/delete-property/ d_can1;
@@ -21,7 +19,6 @@
/delete-node/ &i2c1;
/delete-node/ &i2c2;
-/delete-node/ &mmc2;
/delete-node/ &mmc3;
/delete-node/ &hwspinlock;
/delete-node/ &wdt2;
@@ -46,3 +43,5 @@
/delete-node/ &mcasp0;
/delete-node/ &mcasp1;
/delete-node/ &rng;
+/delete-node/ &rtc;
+/delete-node/ &wkup_m3;
diff --git a/arch/arm/dts/imx6dl-tx6u-801x.dts b/arch/arm/dts/imx6dl-tx6u-801x.dts
index 43104b2b88..a480408f50 100644
--- a/arch/arm/dts/imx6dl-tx6u-801x.dts
+++ b/arch/arm/dts/imx6dl-tx6u-801x.dts
@@ -18,12 +18,12 @@
&gpmi {
partition@0 {
label = "barebox";
- reg = <0x0 0x100000>;
+ reg = <0x0 0x400000>;
};
partition@1 {
label = "barebox-environment";
- reg = <0x100000 0x100000>;
+ reg = <0x400000 0x100000>;
};
};
diff --git a/arch/arm/include/asm/barebox-arm.h b/arch/arm/include/asm/barebox-arm.h
index dbc8aaaba7..0b8acb8b8e 100644
--- a/arch/arm/include/asm/barebox-arm.h
+++ b/arch/arm/include/asm/barebox-arm.h
@@ -48,7 +48,32 @@ void setup_c(void);
void relocate_to_current_adr(void);
void relocate_to_adr(unsigned long target);
void __noreturn barebox_arm_entry(unsigned long membase, unsigned long memsize, void *boarddata);
-void *barebox_arm_boarddata(void);
+
+struct barebox_arm_boarddata {
+#define BAREBOX_ARM_BOARDDATA_MAGIC 0xabe742c3
+ u32 magic;
+ u32 machine; /* machine number to pass to barebox. This may or may
+ * not be a ARM machine number registered on arm.linux.org.uk.
+ * It must only be unique across barebox. Please use a number
+ * that do not potientially clashes with registered machines,
+ * i.e. use a number > 0x10000.
+ */
+};
+
+/*
+ * Create a boarddata struct at given address. Suitable to be passed
+ * as boarddata to barebox_arm_entry(). The machine can be retrieved
+ * later with barebox_arm_machine().
+ */
+static inline void boarddata_create(void *adr, u32 machine)
+{
+ struct barebox_arm_boarddata *bd = adr;
+
+ bd->magic = BAREBOX_ARM_BOARDDATA_MAGIC;
+ bd->machine = machine;
+}
+
+u32 barebox_arm_machine(void);
#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_ARM_EXCEPTIONS)
void arm_fixup_vectors(void);
diff --git a/arch/arm/mach-clps711x/reset.c b/arch/arm/mach-clps711x/reset.c
index 67c9c8b8c5..859d8ae574 100644
--- a/arch/arm/mach-clps711x/reset.c
+++ b/arch/arm/mach-clps711x/reset.c
@@ -11,7 +11,7 @@
void __noreturn reset_cpu(unsigned long addr)
{
- arch_shutdown();
+ shutdown_barebox();
asm("mov pc, #0");
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3ccd060a5b..f8f6004630 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -127,15 +127,6 @@ config BAREBOX_UPDATE_IMX_EXTERNAL_NAND
depends on MTD_WRITE
default y
-config BAREBOX_UPDATE_IMX6_NAND
- bool
- depends on ARCH_IMX6
- depends on BAREBOX_UPDATE
- depends on MTD
- depends on MTD_WRITE
- depends on NAND_MXS
- default y
-
comment "Freescale i.MX System-on-Chip"
config ARCH_IMX1
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0320d1c2ea..458d7b45bb 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -22,6 +22,5 @@ obj-y += devices.o imx.o esdctl.o
obj-y += boot.o
obj-$(CONFIG_BAREBOX_UPDATE) += imx-bbu-internal.o
obj-$(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND) += imx-bbu-external-nand.o
-obj-$(CONFIG_BAREBOX_UPDATE_IMX6_NAND) += imx6-bbu-nand.o
pbl-y += esdctl.o
lwl-y += cpu_init.o
diff --git a/arch/arm/mach-imx/include/mach/bbu.h b/arch/arm/mach-imx/include/mach/bbu.h
index 5eb9a47363..8039091395 100644
--- a/arch/arm/mach-imx/include/mach/bbu.h
+++ b/arch/arm/mach-imx/include/mach/bbu.h
@@ -75,15 +75,6 @@ static inline int imx_bbu_external_nor_register_handler(const char *name, char *
}
#endif
-#if defined(CONFIG_BAREBOX_UPDATE_IMX6_NAND)
-int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
-#else
-static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
-{
- return -ENOSYS;
-}
-#endif
-
#if defined(CONFIG_BAREBOX_UPDATE_IMX_EXTERNAL_NAND)
int imx_bbu_external_nand_register_handler(const char *name, char *devicefile,
unsigned long flags);
diff --git a/arch/arm/mach-mxs/include/mach/imx28-regs.h b/arch/arm/mach-mxs/include/mach/imx28-regs.h
index de0d882414..1a90ec2aa5 100644
--- a/arch/arm/mach-mxs/include/mach/imx28-regs.h
+++ b/arch/arm/mach-mxs/include/mach/imx28-regs.h
@@ -34,6 +34,7 @@
#define IMX_WDT_BASE 0x80056000
#define IMX_I2C0_BASE 0x80058000
#define IMX_I2C1_BASE 0x8005a000
+#define IMX_PWM_BASE 0x80064000
#define IMX_TIM1_BASE 0x80068000
#define IMX_UART0_BASE 0x8006a000
#define IMX_UART1_BASE 0x8006c000
diff --git a/arch/arm/mach-mxs/ocotp.c b/arch/arm/mach-mxs/ocotp.c
index 2029b90acb..00758450cc 100644
--- a/arch/arm/mach-mxs/ocotp.c
+++ b/arch/arm/mach-mxs/ocotp.c
@@ -43,6 +43,7 @@
#define OCOTP_WORD_OFFSET 0x20
struct ocotp_priv {
+ struct device_d dev;
struct cdev cdev;
void __iomem *base;
unsigned int write_enable;
@@ -194,13 +195,19 @@ static int mxs_ocotp_probe(struct device_d *dev)
priv->cdev.size = cpu_is_mx23() ? 128 : 160;
priv->cdev.name = DRIVERNAME;
+ strcpy(priv->dev.name, "ocotp");
+ priv->dev.parent = dev;
+ err = register_device(&priv->dev);
+ if (err)
+ return err;
+
err = devfs_create(&priv->cdev);
if (err < 0)
return err;
if (IS_ENABLED(CONFIG_MXS_OCOTP_WRITABLE)) {
mxs_ocotp_ops.write = mxs_ocotp_cdev_write;
- dev_add_param_bool(dev, "permanent_write_enable",
+ dev_add_param_bool(&priv->dev, "permanent_write_enable",
NULL, NULL, &priv->write_enable, NULL);
}
diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig
index bc00d5bf7f..af359756ba 100644
--- a/arch/arm/mach-omap/Kconfig
+++ b/arch/arm/mach-omap/Kconfig
@@ -54,14 +54,6 @@ config OMAP_CLOCK_SOURCE_S32K
config OMAP_CLOCK_SOURCE_DMTIMER0
bool
-config OMAP3_CLOCK_CONFIG
- prompt "Clock Configuration"
- bool
- depends on ARCH_OMAP3
- default y
- help
- Say Y here if you like to have OMAP3 Clock configuration done.
-
config OMAP_GPMC
prompt "Support for GPMC configuration"
bool
@@ -128,6 +120,21 @@ config OMAP4_USBBOOT
You need the utility program omap4_usbboot to boot from USB.
Please read omap4_usb_booting.txt for more information.
+config OMAP3_USBBOOT
+ bool "enable booting from USB"
+ depends on ARCH_OMAP3
+ help
+ Say Y here if you want to be able to boot the 2nd stage via USB. This
+ works by transferring the 2nd stage image using the MUSB controller
+ which is already initialized by the ROM code. Use the omap3-usb-loader
+ tool selectable below to upload images.
+
+config OMAP3_USB_LOADER
+ bool "enable omap3 USB loader host tool"
+ depends on ARCH_OMAP3
+ help
+ Say Y here to build the omap3 usb loader tool.
+
config OMAP_SERIALBOOT
bool "enable booting from serial"
select XYMODEM
@@ -150,6 +157,13 @@ config MACH_AFI_GF
help
Say Y here if you are using afis GF
+config MACH_BEAGLE
+ bool "Texas Instrument's Beagle Board"
+ select HAVE_DEFAULT_ENVIRONMENT_NEW
+ select ARCH_OMAP3
+ help
+ Say Y here if you are using Beagle Board
+
config MACH_BEAGLEBONE
bool "Texas Instrument's Beagle Bone"
select ARCH_AM33XX
@@ -173,13 +187,6 @@ config MACH_OMAP343xSDP
help
Say Y here if you are using SDP343x platform
-config MACH_BEAGLE
- bool "Texas Instrument's Beagle Board"
- select HAVE_DEFAULT_ENVIRONMENT_NEW
- select ARCH_OMAP3
- help
- Say Y here if you are using Beagle Board
-
config MACH_OMAP3EVM
bool "Texas Instrument's OMAP3 EVM"
select ARCH_OMAP3
diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile
index bef1d0500f..65072b91e4 100644
--- a/arch/arm/mach-omap/Makefile
+++ b/arch/arm/mach-omap/Makefile
@@ -25,12 +25,14 @@ obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
pbl-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o
obj-pbl-$(CONFIG_ARCH_AM33XX) += am33xx_generic.o am33xx_clock.o am33xx_mux.o
obj-$(CONFIG_ARCH_AM33XX) += am33xx_scrm.o
-obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
-pbl-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o
+obj-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
+pbl-$(CONFIG_ARCH_OMAP3) += omap3_clock.o
obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o
obj-$(CONFIG_SHELL_NONE) += xload.o
obj-$(CONFIG_MFD_TWL6030) += omap4_twl6030_mmc.o
obj-$(CONFIG_OMAP4_USBBOOT) += omap4_rom_usb.o
+obj-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
+pbl-$(CONFIG_OMAP3_USBBOOT) += omap3_xload_usb.o
obj-$(CONFIG_CMD_BOOT_ORDER) += boot_order.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO) += am33xx_bbu_spi_mlo.o
obj-$(CONFIG_BAREBOX_UPDATE_AM33XX_NAND) += am33xx_bbu_nand.o
diff --git a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
index 97dc54ee10..702bb9af59 100644
--- a/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
+++ b/arch/arm/mach-omap/am33xx_bbu_spi_mlo.c
@@ -97,41 +97,6 @@ out:
return ret;
}
-static int spi_nor_handler(struct bbu_handler *handler,
- struct bbu_data *data)
-{
- int fd, ret;
-
- if (file_detect_type(data->image, data->len) != filetype_arm_barebox) {
- if (!bbu_force(data, "Not an ARM barebox image"))
- return -EINVAL;
- }
-
- fd = open(data->devicefile, O_RDWR | O_CREAT);
- if (fd < 0)
- return fd;
-
- debug("%s: eraseing %s from 0 to 0x%08x\n", __func__,
- data->devicefile, data->len);
- ret = erase(fd, data->len, 0);
- if (ret) {
- printf("erasing %s failed with %s\n", data->devicefile,
- strerror(-ret));
- goto err_close;
- }
-
- ret = write(fd, data->image, data->len);
- if (ret < 0)
- goto err_close;
-
- ret = 0;
-
-err_close:
- close(fd);
-
- return ret;
-}
-
/*
* Register a am33xx MLO update handler for SPI NOR
*/
@@ -152,24 +117,3 @@ int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile)
return ret;
}
-
-/*
- * Register a am33xx update handler for SPI NOR
- */
-int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile)
-{
- struct bbu_handler *handler;
- int ret;
-
- handler = xzalloc(sizeof(*handler));
- handler->devicefile = devicefile;
- handler->name = name;
- handler->handler = spi_nor_handler;
-
- ret = bbu_register_handler(handler);
-
- if (ret)
- free(handler);
-
- return ret;
-}
diff --git a/arch/arm/mach-omap/include/mach/bbu.h b/arch/arm/mach-omap/include/mach/bbu.h
index 36d87e1a00..da5c214d3a 100644
--- a/arch/arm/mach-omap/include/mach/bbu.h
+++ b/arch/arm/mach-omap/include/mach/bbu.h
@@ -5,18 +5,17 @@
#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO
int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile);
-int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile);
#else
static inline int am33xx_bbu_spi_nor_mlo_register_handler(const char *name, char *devicefile)
{
return 0;
}
+#endif
static inline int am33xx_bbu_spi_nor_register_handler(const char *name, char *devicefile)
{
- return 0;
+ return bbu_register_std_file_update(name, 0, devicefile, filetype_arm_barebox);
}
-#endif
#ifdef CONFIG_BAREBOX_UPDATE_AM33XX_NAND
int am33xx_bbu_nand_xloadslots_register_handler(const char *name,
diff --git a/arch/arm/mach-omap/include/mach/omap3-clock.h b/arch/arm/mach-omap/include/mach/omap3-clock.h
index 1ef46aa3e5..7c52da754f 100644
--- a/arch/arm/mach-omap/include/mach/omap3-clock.h
+++ b/arch/arm/mach-omap/include/mach/omap3-clock.h
@@ -107,7 +107,7 @@
/* PER DPLL */
#define PER_M6X2 3 /* 288MHz: CM_CLKSEL1_EMU */
#define PER_M5X2 4 /* 216MHz: CM_CLKSEL_CAM */
-#define PER_M4X2 9 /* 96MHz : CM_CLKSEL_DSS-dss1 */
+#define PER_M4X2 2 /* 432MHz: CM_CLKSEL_DSS-dss1 */
#define PER_M3X2 16 /* 54MHz : CM_CLKSEL_DSS-tv */
#define CLSEL1_EMU_VAL ((CORE_M3X2 << 16) | (PER_M6X2 << 24) | (0x0a50))
diff --git a/arch/arm/mach-omap/include/mach/omap3-generic.h b/arch/arm/mach-omap/include/mach/omap3-generic.h
index 7db0838a5f..ab53b98971 100644
--- a/arch/arm/mach-omap/include/mach/omap3-generic.h
+++ b/arch/arm/mach-omap/include/mach/omap3-generic.h
@@ -29,4 +29,6 @@ void __noreturn omap3_reset_cpu(unsigned long addr);
int omap3_init(void);
int omap3_devices_init(void);
+void *omap3_xload_boot_usb(void);
+
#endif /* __MACH_OMAP3_GENERIC_H */
diff --git a/arch/arm/mach-omap/omap3_generic.c b/arch/arm/mach-omap/omap3_generic.c
index dbb0b5f86c..0f2e9ce6b7 100644
--- a/arch/arm/mach-omap/omap3_generic.c
+++ b/arch/arm/mach-omap/omap3_generic.c
@@ -435,9 +435,6 @@ static void try_unlock_memory(void)
* Does early system init of disabling the watchdog, enable
* memory and configuring the clocks.
*
- * prcm_init is called only if CONFIG_OMAP3_CLOCK_CONFIG is defined.
- * We depend on link time clean up to remove a_init if no caller exists.
- *
* @warning Called path is with SRAM stack
*
* @return void
@@ -459,9 +456,7 @@ void omap3_core_init(void)
sdelay(100);
-#ifdef CONFIG_OMAP3_CLOCK_CONFIG
prcm_init();
-#endif
}
#define OMAP3_TRACING_VECTOR1 0x4020ffb4
diff --git a/arch/arm/mach-omap/omap3_xload_usb.c b/arch/arm/mach-omap/omap3_xload_usb.c
new file mode 100644
index 0000000000..e7dc21e4a7
--- /dev/null
+++ b/arch/arm/mach-omap/omap3_xload_usb.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * Based on a patch by:
+ *
+ * Copyright (C) 2011 Rick Bronson
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <io.h>
+#include <malloc.h>
+#include <mach/omap3-silicon.h>
+#include <mach/omap3-generic.h>
+
+static void __iomem *omap3_usb_base = (void __iomem *)OMAP3_MUSB0_BASE;
+
+#define OMAP34XX_USB_EP(n) (omap3_usb_base + 0x100 + 0x10 * (n))
+
+#define MUSB_RXCSR 0x06
+#define MUSB_RXCOUNT 0x08
+#define MUSB_TXCSR 0x02
+#define MUSB_FIFOSIZE 0x0F
+#define OMAP34XX_USB_RXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_RXCSR)
+#define OMAP34XX_USB_RXCOUNT(n) (OMAP34XX_USB_EP(n) + MUSB_RXCOUNT)
+#define OMAP34XX_USB_TXCSR(n) (OMAP34XX_USB_EP(n) + MUSB_TXCSR)
+#define OMAP34XX_USB_FIFOSIZE(n) (OMAP34XX_USB_EP(n) + MUSB_FIFOSIZE)
+#define OMAP34XX_USB_FIFO(n) (omap3_usb_base + 0x20 + ((n) * 4))
+
+/* memory mapped registers */
+#define BULK_ENDPOINT 1
+#define MUSB_RXCSR_RXPKTRDY 0x0001
+#define MUSB_TXCSR_TXPKTRDY 0x0001
+
+#define PACK4(a,b,c,d) (((d) << 24) | ((c) << 16) | ((b) << 8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U', 'S', 'B', 's') /* send file size */
+#define USBLOAD_CMD_JUMP PACK4('U', 'S', 'B', 'j') /* go where I tell you */
+#define USBLOAD_CMD_FILE_REQ PACK4('U', 'S', 'B', 'f') /* file request */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U', 'S', 'B', 'n') /* echo file size */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U', 'S', 'B', 'o') /* report file size */
+#define USBLOAD_CMD_MESSAGE PACK4('U', 'S', 'B', 'm') /* message for debug */
+
+static int usb_send(unsigned char *buffer, unsigned int buffer_size)
+{
+ unsigned int cntr;
+ u16 txcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_TXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ txcsr = readw(reg);
+
+ if (txcsr & MUSB_TXCSR_TXPKTRDY)
+ return 0;
+
+ for (cntr = 0; cntr < buffer_size; cntr++)
+ writeb(buffer[cntr], bulk_fifo);
+
+ txcsr = readw(reg);
+ txcsr |= MUSB_TXCSR_TXPKTRDY;
+ writew(txcsr, reg);
+
+ return buffer_size;
+}
+
+static int usb_recv(u8 *buffer)
+{
+ int cntr;
+ u16 count = 0;
+ u16 rxcsr;
+ void __iomem *reg = (void *)OMAP34XX_USB_RXCSR(BULK_ENDPOINT);
+ void __iomem *bulk_fifo = (void *)OMAP34XX_USB_FIFO(BULK_ENDPOINT);
+
+ rxcsr = readw(reg);
+
+ if (!(rxcsr & MUSB_RXCSR_RXPKTRDY))
+ return 0;
+
+ count = readw((void *)OMAP34XX_USB_RXCOUNT(BULK_ENDPOINT));
+ for (cntr = 0; cntr < count; cntr++)
+ *buffer++ = readb(bulk_fifo);
+
+ /* Clear the RXPKTRDY bit */
+ rxcsr = readw(reg);
+ rxcsr &= ~MUSB_RXCSR_RXPKTRDY;
+ writew(rxcsr, reg);
+
+ return count;
+}
+
+static unsigned char usb_outbuffer[64];
+
+static void usb_msg(unsigned int cmd, const char *msg)
+{
+ unsigned char *p_char = usb_outbuffer;
+
+ *(int *)p_char = cmd;
+
+ p_char += sizeof(cmd);
+
+ if (msg) {
+ while (*msg)
+ *p_char++= *msg++;
+ *p_char++= 0;
+ }
+
+ usb_send(usb_outbuffer, p_char - usb_outbuffer);
+}
+
+static void usb_code(unsigned int cmd, u32 code)
+{
+ unsigned int *p_int = (unsigned int *)usb_outbuffer;
+
+ *p_int++ = cmd;
+ *p_int++ = code;
+ usb_send (usb_outbuffer, ((unsigned char *) p_int) - usb_outbuffer);
+}
+
+void *omap3_xload_boot_usb(void)
+{
+ int res;
+ void *buf;
+ u32 *buf32;
+ u32 total;
+ void *addr;
+ u32 bytes;
+ int size;
+ int cntr;
+ void *fn;
+ u8 __buf[512];
+
+ buf32 = buf = __buf;
+
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req");
+ for (cntr = 0; cntr < 10000000; cntr++) {
+ size = usb_recv(buf);
+ if (!size)
+ continue;
+
+ switch (buf32[0]) {
+ case USBLOAD_CMD_FILE:
+ pr_debug ("USBLOAD_CMD_FILE total = %d size = 0x%x addr = 0x%x\n",
+ res, buf32[1], buf32[2]);
+ total = buf32[1]; /* get size and address */
+ addr = (void *)buf32[2];
+ usb_code(USBLOAD_CMD_ECHO_SZ, total);
+
+ bytes = 0;
+
+ while (bytes < total) {
+ size = usb_recv(buf);
+ memcpy(addr, buf, size);
+ addr += size;
+ bytes += size;
+ }
+
+ usb_code(USBLOAD_CMD_REPORT_SZ, total); /* tell him we got this many bytes */
+ usb_msg (USBLOAD_CMD_FILE_REQ, "file req"); /* see if they have another file for us */
+ break;
+ case USBLOAD_CMD_JUMP:
+ pr_debug("USBLOAD_CMD_JUMP total = %d addr = 0x%x val = 0x%x\n",
+ res, buf32[0], buf32[1]);
+ fn = (void *)buf32[1];
+ goto out;
+ default:
+ break;
+ }
+ }
+
+ fn = NULL;
+out:
+
+ return fn;
+}
diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c
index 85c9120ccf..4a0714ed93 100644
--- a/arch/arm/mach-omap/xload.c
+++ b/arch/arm/mach-omap/xload.c
@@ -14,6 +14,7 @@
#include <xymodem.h>
#include <mach/generic.h>
#include <mach/am33xx-generic.h>
+#include <mach/omap3-generic.h>
#include <net.h>
#include <environment.h>
#include <dhcp.h>
@@ -284,13 +285,16 @@ static __noreturn int omap_xload(void)
func = omap_xload_boot_mmc();
break;
case BOOTSOURCE_USB:
- if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
+ if (IS_ENABLED(CONFIG_OMAP3_USBBOOT) && cpu_is_omap3()) {
+ printf("booting from USB\n");
+ func = omap3_xload_boot_usb();
+ } else if (IS_ENABLED(CONFIG_FS_OMAP4_USBBOOT)) {
printf("booting from USB\n");
func = omap4_xload_boot_usb();
- break;
} else {
printf("booting from USB not enabled\n");
}
+ break;
case BOOTSOURCE_NAND:
printf("booting from NAND\n");
func = omap_xload_boot_nand(barebox_part->nand_offset,
diff --git a/arch/arm/mach-pxa/Kconfig b/arch/arm/mach-pxa/Kconfig
index 610fb1c80e..2b7f631757 100644
--- a/arch/arm/mach-pxa/Kconfig
+++ b/arch/arm/mach-pxa/Kconfig
@@ -4,6 +4,7 @@ config ARCH_TEXT_BASE
hex
default 0xa0000000 if MACH_MIOA701
default 0xa3f00000 if MACH_PCM027
+ default 0xa3d00000 if MACH_LUBBOCK
default 0x83f00000 if MACH_ZYLONITE
# ----------------------------------------------------------
diff --git a/arch/arm/mach-socfpga/Kconfig b/arch/arm/mach-socfpga/Kconfig
index 90b3533b1f..73b26efd20 100644
--- a/arch/arm/mach-socfpga/Kconfig
+++ b/arch/arm/mach-socfpga/Kconfig
@@ -1,5 +1,9 @@
if ARCH_SOCFPGA
+config ARCH_TEXT_BASE
+ hex
+ default 0x0
+
config ARCH_SOCFPGA_XLOAD
bool
prompt "Build preloader image"
diff --git a/arch/arm/mach-tegra/include/mach/lowlevel.h b/arch/arm/mach-tegra/include/mach/lowlevel.h
index 768b13d968..0c76b8883c 100644
--- a/arch/arm/mach-tegra/include/mach/lowlevel.h
+++ b/arch/arm/mach-tegra/include/mach/lowlevel.h
@@ -243,11 +243,20 @@ void tegra_ll_delay_usec(int delay)
while ((int)readl(TEGRA_TMRUS_BASE + TIMER_CNTR_1US) - timeout < 0);
}
+/* reset vector for the AVP, to be called from board reset vector */
+void tegra_avp_reset_vector(uint32_t boarddata);
+
+/* reset vector for the main CPU complex */
+void tegra_maincomplex_entry(void);
+
static __always_inline
void tegra_cpu_lowlevel_setup(void)
{
uint32_t r;
+ if (tegra_cpu_is_maincomplex())
+ tegra_maincomplex_entry();
+
/* set the cpu to SVC32 mode */
__asm__ __volatile__("mrs %0, cpsr":"=r"(r));
r &= ~0x1f;
@@ -258,10 +267,4 @@ void tegra_cpu_lowlevel_setup(void)
tegra_ll_delay_setup();
}
-/* reset vector for the AVP, to be called from board reset vector */
-void tegra_avp_reset_vector(uint32_t boarddata);
-
-/* reset vector for the main CPU complex */
-void tegra_maincomplex_entry(void);
-
#endif /* __TEGRA_LOWLEVEL_H */
diff --git a/arch/arm/mach-tegra/tegra_avp_init.c b/arch/arm/mach-tegra/tegra_avp_init.c
index 91fd894dca..20fcf3f1d1 100644
--- a/arch/arm/mach-tegra/tegra_avp_init.c
+++ b/arch/arm/mach-tegra/tegra_avp_init.c
@@ -265,9 +265,6 @@ void tegra_avp_reset_vector(uint32_t boarddata)
/* put boarddata in scratch reg, for main CPU to fetch after startup */
writel(boarddata, TEGRA_PMC_BASE + PMC_SCRATCH(10));
- if (tegra_cpu_is_maincomplex())
- tegra_maincomplex_entry();
-
/* we want to bring up the high performance CPU complex */
if (tegra_get_chiptype() >= TEGRA30)
tegra_cluster_switch_hp();
diff --git a/arch/blackfin/include/asm/io.h b/arch/blackfin/include/asm/io.h
index 2837b6a1aa..703104e1b8 100644
--- a/arch/blackfin/include/asm/io.h
+++ b/arch/blackfin/include/asm/io.h
@@ -90,21 +90,21 @@ extern void *__ioremap(unsigned long physaddr, unsigned long size,
int cacheflag);
extern void __iounmap(void *addr, unsigned long size);
-extern inline void *ioremap(unsigned long physaddr, unsigned long size)
+static inline void *ioremap(unsigned long physaddr, unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-extern inline void *ioremap_nocache(unsigned long physaddr,
+static inline void *ioremap_nocache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_NOCACHE_SER);
}
-extern inline void *ioremap_writethrough(unsigned long physaddr,
+static inline void *ioremap_writethrough(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_WRITETHROUGH);
}
-extern inline void *ioremap_fullcache(unsigned long physaddr,
+static inline void *ioremap_fullcache(unsigned long physaddr,
unsigned long size)
{
return __ioremap(physaddr, size, IOMAP_FULL_CACHING);
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h
index eaa1e4a03f..f46363732a 100644
--- a/arch/blackfin/include/asm/processor.h
+++ b/arch/blackfin/include/asm/processor.h
@@ -36,7 +36,7 @@
#include <asm/ptrace.h>
#include <asm/current.h>
-extern inline unsigned long rdusp(void)
+static inline unsigned long rdusp(void)
{
unsigned long usp;
@@ -44,7 +44,7 @@ extern inline unsigned long rdusp(void)
return usp;
}
-extern inline void wrusp(unsigned long usp)
+static inline void wrusp(unsigned long usp)
{
__asm__ __volatile__("usp = %0;\n\t"::"da"(usp));
}
@@ -130,7 +130,7 @@ static inline void exit_thread(void)
/*
* Return saved PC of a blocked thread.
*/
-extern inline unsigned long thread_saved_pc(struct thread_struct *t)
+static inline unsigned long thread_saved_pc(struct thread_struct *t)
{
extern void scheduling_functions_start_here(void);
extern void scheduling_functions_end_here(void);
diff --git a/arch/blackfin/include/asm/swab.h b/arch/blackfin/include/asm/swab.h
index 89de6507ca..1f645db374 100644
--- a/arch/blackfin/include/asm/swab.h
+++ b/arch/blackfin/include/asm/swab.h
@@ -12,7 +12,7 @@
#ifdef __GNUC__
-static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swahb32(__u32 xx)
{
__u32 tmp;
__asm__("%1 = %0 >> 8 (V);\n\t"
@@ -23,7 +23,7 @@ static __inline__ __attribute_const__ __u32 __arch_swahb32(__u32 xx)
}
#define __arch_swahb32 __arch_swahb32
-static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swahw32(__u32 xx)
{
__u32 rv;
__asm__("%0 = PACK(%1.L, %1.H);\n\t": "=d"(rv): "d"(xx));
@@ -31,13 +31,13 @@ static __inline__ __attribute_const__ __u32 __arch_swahw32(__u32 xx)
}
#define __arch_swahw32 __arch_swahw32
-static __inline__ __attribute_const__ __u32 __arch_swab32(__u32 xx)
+static inline __attribute_const__ __u32 __arch_swab32(__u32 xx)
{
return __arch_swahb32(__arch_swahw32(xx));
}
#define __arch_swab32 __arch_swab32
-static __inline__ __attribute_const__ __u16 __arch_swab16(__u16 xx)
+static inline __attribute_const__ __u16 __arch_swab16(__u16 xx)
{
__u32 xw = xx;
__asm__("%0 <<= 8;\n %0.L = %0.L + %0.H (NS);\n": "+d"(xw));
diff --git a/arch/mips/mach-bcm47xx/reset.c b/arch/mips/mach-bcm47xx/reset.c
index f1dc68afb5..00aee190fe 100644
--- a/arch/mips/mach-bcm47xx/reset.c
+++ b/arch/mips/mach-bcm47xx/reset.c
@@ -15,11 +15,6 @@
*
*/
-/**
- * @file
- * @brief Resetting an malta board
- */
-
#include <common.h>
#include <io.h>
#include <mach/hardware.h>
diff --git a/arch/ppc/include/asm/atomic.h b/arch/ppc/include/asm/atomic.h
index 23f22df1b7..a98d892ea7 100644
--- a/arch/ppc/include/asm/atomic.h
+++ b/arch/ppc/include/asm/atomic.h
@@ -21,7 +21,7 @@ typedef struct { int counter; } atomic_t;
extern void atomic_clear_mask(unsigned long mask, unsigned long *addr);
extern void atomic_set_mask(unsigned long mask, unsigned long *addr);
-extern __inline__ int atomic_add_return(int a, atomic_t *v)
+static inline int atomic_add_return(int a, atomic_t *v)
{
int t;
@@ -37,7 +37,7 @@ extern __inline__ int atomic_add_return(int a, atomic_t *v)
return t;
}
-extern __inline__ int atomic_sub_return(int a, atomic_t *v)
+static inline int atomic_sub_return(int a, atomic_t *v)
{
int t;
@@ -53,7 +53,7 @@ extern __inline__ int atomic_sub_return(int a, atomic_t *v)
return t;
}
-extern __inline__ int atomic_inc_return(atomic_t *v)
+static inline int atomic_inc_return(atomic_t *v)
{
int t;
@@ -69,7 +69,7 @@ extern __inline__ int atomic_inc_return(atomic_t *v)
return t;
}
-extern __inline__ int atomic_dec_return(atomic_t *v)
+static inline int atomic_dec_return(atomic_t *v)
{
int t;
diff --git a/arch/ppc/include/asm/bitops.h b/arch/ppc/include/asm/bitops.h
index e4572bcd4d..2fdd57eff0 100644
--- a/arch/ppc/include/asm/bitops.h
+++ b/arch/ppc/include/asm/bitops.h
@@ -28,7 +28,7 @@
* These used to be if'd out here because using : "cc" as a constraint
* resulted in errors from egcs. Things may be OK with gcc-2.95.
*/
-extern __inline__ void set_bit(int nr, volatile void * addr)
+static inline void set_bit(int nr, volatile void * addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -45,7 +45,7 @@ extern __inline__ void set_bit(int nr, volatile void * addr)
: "cc" );
}
-extern __inline__ void clear_bit(int nr, volatile void *addr)
+static inline void clear_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -62,7 +62,7 @@ extern __inline__ void clear_bit(int nr, volatile void *addr)
: "cc");
}
-extern __inline__ void change_bit(int nr, volatile void *addr)
+static inline void change_bit(int nr, volatile void *addr)
{
unsigned long old;
unsigned long mask = 1 << (nr & 0x1f);
@@ -79,7 +79,7 @@ extern __inline__ void change_bit(int nr, volatile void *addr)
: "cc");
}
-extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
+static inline int test_and_set_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -98,7 +98,7 @@ extern __inline__ int test_and_set_bit(int nr, volatile void *addr)
return (old & mask) != 0;
}
-extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
+static inline int test_and_clear_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -117,7 +117,7 @@ extern __inline__ int test_and_clear_bit(int nr, volatile void *addr)
return (old & mask) != 0;
}
-extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
+static inline int test_and_change_bit(int nr, volatile void *addr)
{
unsigned int old, t;
unsigned int mask = 1 << (nr & 0x1f);
@@ -138,7 +138,7 @@ extern __inline__ int test_and_change_bit(int nr, volatile void *addr)
#endif /* __INLINE_BITOPS */
/* Return the bit position of the most significant 1 bit in a word */
-extern __inline__ int __ilog2(unsigned int x)
+static inline int __ilog2(unsigned int x)
{
int lz;
@@ -146,14 +146,14 @@ extern __inline__ int __ilog2(unsigned int x)
return 31 - lz;
}
-extern __inline__ int ffz(unsigned int x)
+static inline int ffz(unsigned int x)
{
if ((x = ~x) == 0)
return 32;
return __ilog2(x & -x);
}
-static __inline__ int __ffs(unsigned long x)
+static inline int __ffs(unsigned long x)
{
return __ilog2(x & -x);
}
@@ -177,7 +177,7 @@ static inline int fls(unsigned int x)
* the libc and compiler builtin ffs routines, therefore
* differs in spirit from the above ffz (man ffs).
*/
-extern __inline__ int ffs(int x)
+static inline int ffs(int x)
{
return __ilog2(x & -x) + 1;
}
diff --git a/arch/ppc/include/asm/io.h b/arch/ppc/include/asm/io.h
index 98bf5132cd..f83ab6ee0b 100644
--- a/arch/ppc/include/asm/io.h
+++ b/arch/ppc/include/asm/io.h
@@ -136,7 +136,7 @@ static inline void __raw_writel(unsigned int v, volatile void __iomem *addr)
/*
* 8, 16 and 32 bit, big and little endian I/O operations, with barrier.
*/
-extern inline u8 in_8(const volatile u8 __iomem *addr)
+static inline u8 in_8(const volatile u8 __iomem *addr)
{
u8 ret;
@@ -145,12 +145,12 @@ extern inline u8 in_8(const volatile u8 __iomem *addr)
return ret;
}
-extern inline void out_8(volatile u8 __iomem *addr, u8 val)
+static inline void out_8(volatile u8 __iomem *addr, u8 val)
{
__asm__ __volatile__("sync;stb%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
-extern inline u16 in_le16(const volatile u16 __iomem *addr)
+static inline u16 in_le16(const volatile u16 __iomem *addr)
{
u16 ret;
@@ -159,7 +159,7 @@ extern inline u16 in_le16(const volatile u16 __iomem *addr)
return ret;
}
-extern inline u16 in_be16(const volatile u16 __iomem *addr)
+static inline u16 in_be16(const volatile u16 __iomem *addr)
{
u16 ret;
@@ -168,18 +168,18 @@ extern inline u16 in_be16(const volatile u16 __iomem *addr)
return ret;
}
-extern inline void out_le16(volatile u16 __iomem *addr, u16 val)
+static inline void out_le16(volatile u16 __iomem *addr, u16 val)
{
__asm__ __volatile__("sync; sthbrx %1,0,%2"
: "=m" (*addr) : "r" (val), "r" (addr));
}
-extern inline void out_be16(volatile u16 __iomem *addr, u16 val)
+static inline void out_be16(volatile u16 __iomem *addr, u16 val)
{
__asm__ __volatile__("sync;sth%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
-extern inline u32 in_le32(const volatile u32 __iomem *addr)
+static inline u32 in_le32(const volatile u32 __iomem *addr)
{
u32 ret;
@@ -188,7 +188,7 @@ extern inline u32 in_le32(const volatile u32 __iomem *addr)
return ret;
}
-extern inline u32 in_be32(const volatile u32 __iomem *addr)
+static inline u32 in_be32(const volatile u32 __iomem *addr)
{
u32 ret;
@@ -197,13 +197,13 @@ extern inline u32 in_be32(const volatile u32 __iomem *addr)
return ret;
}
-extern inline void out_le32(volatile u32 __iomem *addr, u32 val)
+static inline void out_le32(volatile u32 __iomem *addr, u32 val)
{
__asm__ __volatile__("sync; stwbrx %1,0,%2"
: "=m" (*addr) : "r" (val), "r" (addr));
}
-extern inline void out_be32(volatile u32 __iomem *addr, u32 val)
+static inline void out_be32(volatile u32 __iomem *addr, u32 val)
{
__asm__ __volatile__("sync;stw%U0%X0 %1,%0" : "=m" (*addr) : "r" (val));
}
diff --git a/arch/ppc/include/asm/swab.h b/arch/ppc/include/asm/swab.h
index c581e3ef73..110488e641 100644
--- a/arch/ppc/include/asm/swab.h
+++ b/arch/ppc/include/asm/swab.h
@@ -19,7 +19,7 @@
#ifdef __KERNEL__
-static __inline__ __u16 ld_le16(const volatile __u16 *addr)
+static inline __u16 ld_le16(const volatile __u16 *addr)
{
__u16 val;
@@ -28,7 +28,7 @@ static __inline__ __u16 ld_le16(const volatile __u16 *addr)
}
#define __arch_swab16p ld_le16
-static __inline__ void st_le16(volatile __u16 *addr, const __u16 val)
+static inline void st_le16(volatile __u16 *addr, const __u16 val)
{
__asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
}
@@ -39,7 +39,7 @@ static inline void __arch_swab16s(__u16 *addr)
}
#define __arch_swab16s __arch_swab16s
-static __inline__ __u32 ld_le32(const volatile __u32 *addr)
+static inline __u32 ld_le32(const volatile __u32 *addr)
{
__u32 val;
@@ -48,7 +48,7 @@ static __inline__ __u32 ld_le32(const volatile __u32 *addr)
}
#define __arch_swab32p ld_le32
-static __inline__ void st_le32(volatile __u32 *addr, const __u32 val)
+static inline void st_le32(volatile __u32 *addr, const __u32 val)
{
__asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*addr) : "r" (val), "r" (addr));
}
diff --git a/arch/sandbox/include/asm/byteorder.h b/arch/sandbox/include/asm/byteorder.h
index 37316f2371..3d82bcba6e 100644
--- a/arch/sandbox/include/asm/byteorder.h
+++ b/arch/sandbox/include/asm/byteorder.h
@@ -1,8 +1,8 @@
-#ifndef _I386_BYTEORDER_H
-#define _I386_BYTEORDER_H
+#ifndef _SANDBOX_BYTEORDER_H
+#define _SANDBOX_BYTEORDER_H
#include <asm/types.h>
#include <linux/byteorder/little_endian.h>
-#endif /* _I386_BYTEORDER_H */
+#endif /* _SANDBOX_BYTEORDER_H */
diff --git a/commands/automount.c b/commands/automount.c
index a29f286b22..b491d203fd 100644
--- a/commands/automount.c
+++ b/commands/automount.c
@@ -70,4 +70,3 @@ BAREBOX_CMD_START(automount)
BAREBOX_CMD_GROUP(CMD_GRP_PART)
BAREBOX_CMD_HELP(cmd_automount_help)
BAREBOX_CMD_END
-
diff --git a/commands/detect.c b/commands/detect.c
index d8e0afc314..1586a6fb54 100644
--- a/commands/detect.c
+++ b/commands/detect.c
@@ -68,10 +68,7 @@ static int do_detect(int argc, char *argv[])
return COMMAND_ERROR_USAGE;
for (i = optind; i < argc; i++) {
- dev = get_device_by_name(argv[i]);
- if (!dev)
- return -ENODEV;
- ret = device_detect(dev);
+ ret = device_detect_by_name(argv[i]);
if (ret && option_error)
return ret;
}
diff --git a/commands/devinfo.c b/commands/devinfo.c
index e61aaa24e8..3c9d6a6b9d 100644
--- a/commands/devinfo.c
+++ b/commands/devinfo.c
@@ -68,11 +68,8 @@ static int do_devinfo(int argc, char *argv[])
}
} else {
dev = get_device_by_name(argv[1]);
-
- if (!dev) {
- printf("no such device: %s\n",argv[1]);
- return -1;
- }
+ if (!dev)
+ return -ENODEV;
if (dev->num_resources)
printf("Resources:\n");
diff --git a/commands/digest.c b/commands/digest.c
index 340c07a248..4cc615d775 100644
--- a/commands/digest.c
+++ b/commands/digest.c
@@ -68,7 +68,7 @@ err:
return ret;
}
-static void prints_algo_help(void)
+static void __maybe_unused prints_algo_help(void)
{
puts("\navailable algo:\n");
digest_algo_prints("\t");
diff --git a/commands/export.c b/commands/export.c
index 2e8bb49676..4b4cf1e12e 100644
--- a/commands/export.c
+++ b/commands/export.c
@@ -59,4 +59,3 @@ BAREBOX_CMD_START(export)
BAREBOX_CMD_GROUP(CMD_GRP_ENV)
BAREBOX_CMD_HELP(cmd_export_help)
BAREBOX_CMD_END
-
diff --git a/commands/false.c b/commands/false.c
index 6ef9af3155..90aa2cc9ea 100644
--- a/commands/false.c
+++ b/commands/false.c
@@ -32,4 +32,3 @@ BAREBOX_CMD_START(false)
BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/commands/help.c b/commands/help.c
index 6e61bde1af..3d36d9bf48 100644
--- a/commands/help.c
+++ b/commands/help.c
@@ -148,4 +148,3 @@ BAREBOX_CMD_START(help)
BAREBOX_CMD_HELP(cmd_help_help)
BAREBOX_CMD_COMPLETE(command_complete)
BAREBOX_CMD_END
-
diff --git a/commands/login.c b/commands/login.c
index 210eb203ac..bf5085c854 100644
--- a/commands/login.c
+++ b/commands/login.c
@@ -71,7 +71,7 @@ static int do_login(int argc, char *argv[])
run_command(timeout_cmd);
}
- if (check_passwd(passwd, passwd_len))
+ if (check_passwd(passwd, passwd_len) == 1)
return 0;
} while(1);
diff --git a/commands/mount.c b/commands/mount.c
index 939e9bc853..aa769d46fe 100644
--- a/commands/mount.c
+++ b/commands/mount.c
@@ -79,6 +79,8 @@ static int do_mount(int argc, char *argv[])
if (!strncmp(devstr, "/dev/", 5))
devstr += 5;
+ device_detect_by_name(devstr);
+
cdev = cdev_by_name(devstr);
if (!cdev)
return -ENOENT;
diff --git a/commands/net.c b/commands/net.c
index 7508c992f2..219c7efcda 100644
--- a/commands/net.c
+++ b/commands/net.c
@@ -64,4 +64,3 @@ BAREBOX_CMD_START(ethact)
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_COMPLETE(eth_complete)
BAREBOX_CMD_END
-
diff --git a/commands/readline.c b/commands/readline.c
index e537498878..b6e0e3e091 100644
--- a/commands/readline.c
+++ b/commands/readline.c
@@ -53,4 +53,3 @@ BAREBOX_CMD_START(readline)
BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
BAREBOX_CMD_HELP(cmd_readline_help)
BAREBOX_CMD_END
-
diff --git a/commands/timeout.c b/commands/timeout.c
index 2b99d4f749..ef1a037c19 100644
--- a/commands/timeout.c
+++ b/commands/timeout.c
@@ -84,4 +84,3 @@ BAREBOX_CMD_START(timeout)
BAREBOX_CMD_GROUP(CMD_GRP_CONSOLE)
BAREBOX_CMD_HELP(cmd_timeout_help)
BAREBOX_CMD_END
-
diff --git a/commands/trigger.c b/commands/trigger.c
index b605448a91..2758ce74e8 100644
--- a/commands/trigger.c
+++ b/commands/trigger.c
@@ -105,4 +105,3 @@ BAREBOX_CMD_START(trigger)
BAREBOX_CMD_GROUP(CMD_GRP_HWMANIP)
BAREBOX_CMD_HELP(cmd_trigger_help)
BAREBOX_CMD_END
-
diff --git a/commands/true.c b/commands/true.c
index fbb34e7690..24dea46929 100644
--- a/commands/true.c
+++ b/commands/true.c
@@ -32,4 +32,3 @@ BAREBOX_CMD_START(true)
BAREBOX_CMD_GROUP(CMD_GRP_SCRIPT)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/commands/ubi.c b/commands/ubi.c
index 94da799b8c..9463127151 100644
--- a/commands/ubi.c
+++ b/commands/ubi.c
@@ -179,4 +179,3 @@ BAREBOX_CMD_START(ubirmvol)
BAREBOX_CMD_GROUP(CMD_GRP_PART)
BAREBOX_CMD_HELP(cmd_ubirmvol_help)
BAREBOX_CMD_END
-
diff --git a/commands/version.c b/commands/version.c
index 898c719433..090f2dd136 100644
--- a/commands/version.c
+++ b/commands/version.c
@@ -33,4 +33,3 @@ BAREBOX_CMD_START(version)
BAREBOX_CMD_GROUP(CMD_GRP_INFO)
BAREBOX_CMD_COMPLETE(empty_complete)
BAREBOX_CMD_END
-
diff --git a/common/Kconfig b/common/Kconfig
index 3dfb5ac194..983d3059fc 100644
--- a/common/Kconfig
+++ b/common/Kconfig
@@ -97,6 +97,14 @@ config FILE_LIST
config ARCH_DMA_ADDR_T_64BIT
bool
+config BAREBOX_UPDATE_IMX_NAND_FCB
+ bool
+ depends on ARCH_IMX6 || ARCH_IMX28
+ depends on BAREBOX_UPDATE
+ depends on MTD_WRITE
+ depends on NAND_MXS
+ default y
+
menu "General Settings"
config LOCALVERSION
@@ -201,6 +209,16 @@ config BAREBOX_MAX_BARE_INIT_SIZE
this will allow your bare_init to fit in SRAM as example
ARCH can overwrite it via ARCH_BAREBOX_MAX_BARE_INIT_SIZE
+config BAREBOX_MAX_PBLX_SIZE
+ depends on PBL_MULTI_IMAGES
+ depends on IMAGE_COMPRESSION
+ prompt "Maximum PBLX size"
+ hex
+ default 0xffffffff
+ help
+ Define the maximum size of the PBLX image.
+ The pblx is a self extracting barebox binary.
+
config HAVE_CONFIGURABLE_MEMORY_LAYOUT
bool
diff --git a/common/Makefile b/common/Makefile
index 2738238c67..74801f7e28 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -52,6 +52,7 @@ lwl-$(CONFIG_IMD) += imd-barebox.o
obj-$(CONFIG_IMD) += imd.o
obj-$(CONFIG_FILE_LIST) += file-list.o
obj-$(CONFIG_FIRMWARE) += firmware.o
+obj-$(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB) += imx-bbu-nand-fcb.o
quiet_cmd_pwd_h = PWDH $@
ifdef CONFIG_PASSWORD
diff --git a/common/bbu.c b/common/bbu.c
index 7fb154a230..4d71fa4a87 100644
--- a/common/bbu.c
+++ b/common/bbu.c
@@ -20,6 +20,12 @@
#include <linux/list.h>
#include <errno.h>
#include <readkey.h>
+#include <filetype.h>
+#include <libfile.h>
+#include <fs.h>
+#include <fcntl.h>
+#include <malloc.h>
+#include <linux/stat.h>
static LIST_HEAD(bbu_image_handlers);
@@ -153,3 +159,110 @@ int bbu_register_handler(struct bbu_handler *handler)
return 0;
}
+
+struct bbu_std {
+ struct bbu_handler handler;
+ enum filetype filetype;
+};
+
+static int bbu_std_file_handler(struct bbu_handler *handler,
+ struct bbu_data *data)
+{
+ struct bbu_std *std = container_of(handler, struct bbu_std, handler);
+ int fd, ret;
+ enum filetype filetype;
+ struct stat s;
+ unsigned oflags = O_WRONLY;
+
+ filetype = file_detect_type(data->image, data->len);
+ if (filetype != std->filetype) {
+ if (!bbu_force(data, "incorrect image type. Expected: %s, got %s",
+ file_type_to_string(std->filetype),
+ file_type_to_string(filetype)))
+ return -EINVAL;
+ }
+
+ ret = stat(data->devicefile, &s);
+ if (ret) {
+ oflags |= O_CREAT;
+ } else {
+ if (!S_ISREG(s.st_mode) && s.st_size < data->len) {
+ printf("Image (%lld) is too big for device (%d)\n",
+ s.st_size, data->len);
+ }
+ }
+
+ ret = bbu_confirm(data);
+ if (ret)
+ return ret;
+
+ fd = open(data->devicefile, oflags);
+ if (fd < 0)
+ return fd;
+
+ ret = protect(fd, data->len, 0, 0);
+ if (ret && ret != -ENOSYS) {
+ printf("unprotecting %s failed with %s\n", data->devicefile,
+ strerror(-ret));
+ goto err_close;
+ }
+
+ ret = erase(fd, data->len, 0);
+ if (ret && ret != -ENOSYS) {
+ printf("erasing %s failed with %s\n", data->devicefile,
+ strerror(-ret));
+ goto err_close;
+ }
+
+ ret = write_full(fd, data->image, data->len);
+ if (ret < 0)
+ goto err_close;
+
+ protect(fd, data->len, 0, 1);
+
+ ret = 0;
+
+err_close:
+ close(fd);
+
+ return ret;
+}
+
+/**
+ * bbu_register_std_file_update() - register a barebox update handler for a
+ * standard file-to-device-copy operation
+ * @name: Name of the handler
+ * @flags: BBU_HANDLER_FLAG_* flags
+ * @devicefile: the file to write the update image to
+ * @imagetype: The filetype that the update image must have
+ *
+ * This update handler us suitable for a standard file-to-device copy operation.
+ * The handler checks for a filetype and unprotects/erases the device if
+ * necessary. If devicefile belongs to a device then the device is checkd for
+ * enough space before touching it.
+ *
+ * Return: 0 if successful, negative error code otherwise
+ */
+int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype)
+{
+ struct bbu_std *std;
+ struct bbu_handler *handler;
+ int ret;
+
+ std = xzalloc(sizeof(*std));
+ std->filetype = imagetype;
+
+ handler = &std->handler;
+
+ handler->flags = flags;
+ handler->devicefile = devicefile;
+ handler->name = name;
+ handler->handler = bbu_std_file_handler;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(std);
+
+ return ret;
+}
diff --git a/common/blspec.c b/common/blspec.c
index 742065ea63..ab18602715 100644
--- a/common/blspec.c
+++ b/common/blspec.c
@@ -30,6 +30,7 @@
#include <of.h>
#include <linux/stat.h>
#include <linux/err.h>
+#include <mtd/ubi-user.h>
/*
* blspec_entry_var_set - set a variable to a value
@@ -436,6 +437,35 @@ err_out:
}
/*
+ * blspec_scan_ubi - scan over a cdev containing UBI volumes
+ *
+ * This function attaches a cdev as UBI devices and collects all blspec
+ * entries found in the UBI volumes
+ *
+ * returns the number of entries found or a negative error code if some unexpected
+ * error occured.
+ */
+static int blspec_scan_ubi(struct blspec *blspec, struct cdev *cdev)
+{
+ struct device_d *child;
+ int ret, found = 0;
+
+ pr_debug("%s: %s\n", __func__, cdev->name);
+
+ ret = ubi_attach_mtd_dev(cdev->mtd, UBI_DEV_NUM_AUTO, 0, 20);
+ if (ret && ret != -EEXIST)
+ return 0;
+
+ device_for_each_child(cdev->dev, child) {
+ ret = blspec_scan_device(blspec, child);
+ if (ret > 0)
+ found += ret;
+ }
+
+ return found;
+}
+
+/*
* blspec_scan_cdev - scan over a cdev
*
* Given a cdev this function mounts the filesystem and collects all blspec
@@ -446,9 +476,9 @@ err_out:
*/
static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
{
- int ret;
+ int ret, found = 0;
void *buf = xzalloc(512);
- enum filetype type;
+ enum filetype type, filetype;
const char *rootpath;
pr_debug("%s: %s\n", __func__, cdev->name);
@@ -460,16 +490,26 @@ static int blspec_scan_cdev(struct blspec *blspec, struct cdev *cdev)
}
type = file_detect_partition_table(buf, 512);
+ filetype = file_detect_type(buf, 512);
free(buf);
if (type == filetype_mbr || type == filetype_gpt)
return -EINVAL;
+ if (filetype == filetype_ubi && IS_ENABLED(CONFIG_MTD_UBI)) {
+ ret = blspec_scan_ubi(blspec, cdev);
+ if (ret > 0)
+ found += ret;
+ }
+
rootpath = cdev_mount_default(cdev, NULL);
- if (IS_ERR(rootpath))
- return PTR_ERR(rootpath);
+ if (!IS_ERR(rootpath)) {
+ ret = blspec_scan_directory(blspec, rootpath);
+ if (ret > 0)
+ found += ret;
+ }
- return blspec_scan_directory(blspec, rootpath);
+ return found;
}
/*
@@ -575,17 +615,10 @@ int blspec_scan_devicename(struct blspec *blspec, const char *devname)
{
struct device_d *dev;
struct cdev *cdev;
- const char *colon;
pr_debug("%s: %s\n", __func__, devname);
- colon = strchr(devname, '.');
- if (colon) {
- char *name = xstrdup(devname);
- *strchr(name, '.') = 0;
- device_detect_by_name(name);
- free(name);
- }
+ device_detect_by_name(devname);
cdev = cdev_by_name(devname);
if (cdev) {
diff --git a/common/complete.c b/common/complete.c
index 5b71f03cf8..f0ef576401 100644
--- a/common/complete.c
+++ b/common/complete.c
@@ -466,4 +466,3 @@ int complete(char *instr, char **outstr)
return reprint;
}
-
diff --git a/common/filetype.c b/common/filetype.c
index 25d97614e4..28a4b2ca25 100644
--- a/common/filetype.c
+++ b/common/filetype.c
@@ -60,6 +60,7 @@ static const struct filetype_str filetype_str[] = {
"TI OMAP CH boot image (big endian)", "ch-image-be" },
[filetype_xz_compressed] = { "XZ compressed", "xz" },
[filetype_exe] = { "MS-DOS executable", "exe" },
+ [filetype_mxs_bootstream] = { "Freescale MXS bootstream", "mxsbs" },
};
const char *file_type_to_string(enum filetype f)
@@ -292,6 +293,8 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize)
if (buf8[0] == 'M' && buf8[1] == 'Z')
return filetype_exe;
+ if (le32_to_cpu(buf[5]) == 0x504d5453)
+ return filetype_mxs_bootstream;
if (is_barebox_arm_head(_buf))
return filetype_arm_barebox;
diff --git a/arch/arm/mach-imx/imx6-bbu-nand.c b/common/imx-bbu-nand-fcb.c
index d2bfedbad5..22031f5b7f 100644
--- a/arch/arm/mach-imx/imx6-bbu-nand.c
+++ b/common/imx-bbu-nand-fcb.c
@@ -17,7 +17,7 @@
*
*/
-#define pr_fmt(fmt) "imx6-bbu-nand: " fmt
+#define pr_fmt(fmt) "imx-bbu-nand-fcb: " fmt
#include <filetype.h>
#include <common.h>
@@ -28,17 +28,17 @@
#include <linux/sizes.h>
#include <bbu.h>
#include <fs.h>
-#include <mach/bbu.h>
#include <linux/mtd/mtd-abi.h>
#include <linux/mtd/nand_mxs.h>
#include <linux/mtd/mtd.h>
#include <linux/stat.h>
+#include <io.h>
struct dbbt_block {
uint32_t Checksum;
uint32_t FingerPrint;
uint32_t Version;
- uint32_t reserved;
+ uint32_t numberBB; /* reserved on i.MX6 */
uint32_t DBBTNumOfPages;
};
@@ -102,6 +102,16 @@ struct fcb_block {
uint32_t BBMarkerPhysicalOffsetInSpareData; /* The swap position of main area in spare area */
};
+struct imx_nand_fcb_bbu_handler {
+ struct bbu_handler handler;
+
+ void (*fcb_create)(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd);
+ void (*dbbt_create)(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct dbbt_block *dbbt, int num_bad_blocks);
+ enum filetype filetype;
+};
+
#define BF_VAL(v, bf) (((v) & bf##_MASK) >> bf##_OFFSET)
#define GETBIT(v,n) (((v) >> (n)) & 0x1)
@@ -228,7 +238,8 @@ static ssize_t raw_write_page(struct mtd_info *mtd, void *buf, loff_t offset)
return ret;
}
-static int fcb_create(struct fcb_block *fcb, struct mtd_info *mtd)
+static int fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
{
fcb->FingerPrint = 0x20424346;
fcb->Version = 0x01000000;
@@ -241,42 +252,37 @@ static int fcb_create(struct fcb_block *fcb, struct mtd_info *mtd)
mxs_nand_get_ecc_strength(mtd->writesize, mtd->oobsize) >> 1;
fcb->EccBlockNEccType = fcb->EccBlock0EccType;
- /* Also hardcoded in kobs-ng */
- fcb->DataSetup = 80;
- fcb->DataHold = 60;
- fcb->AddressSetup = 25;
- fcb->DSAMPLE_TIME = 6;
- fcb->MetadataBytes = 0x0000000a;
fcb->EccBlock0Size = 0x00000200;
fcb->EccBlockNSize = 0x00000200;
fcb->NumEccBlocksPerPage = mtd->writesize / fcb->EccBlock0Size - 1;
- /* DBBT search area starts at third block */
- fcb->DBBTSearchAreaStartAddress = mtd->erasesize / mtd->writesize * 2;
+ /* DBBT search area starts at second page on first block */
+ fcb->DBBTSearchAreaStartAddress = 1;
fcb->BadBlockMarkerByte = mxs_nand_mark_byte_offset(mtd);
fcb->BadBlockMarkerStartBit = mxs_nand_mark_bit_offset(mtd);
fcb->BBMarkerPhysicalOffset = mtd->writesize;
+ imx_handler->fcb_create(imx_handler, fcb, mtd);
+
fcb->Checksum = calc_chksum((void *)fcb + 4, sizeof(*fcb) - 4);
return 0;
}
-static int imx6_bbu_erase(struct mtd_info *mtd)
+static int imx_bbu_erase(struct mtd_info *mtd)
{
uint64_t offset = 0;
- int len = SZ_2M;
struct erase_info erase;
int ret;
- while (len > 0) {
+ while (offset < mtd->size) {
pr_debug("erasing at 0x%08llx\n", offset);
if (mtd_block_isbad(mtd, offset)) {
- offset += mtd->erasesize;
pr_debug("erase skip block @ 0x%08llx\n", offset);
+ offset += mtd->erasesize;
continue;
}
@@ -289,13 +295,13 @@ static int imx6_bbu_erase(struct mtd_info *mtd)
return ret;
offset += mtd->erasesize;
- len -= mtd->erasesize;
}
return 0;
}
-static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, size_t len)
+static int imx_bbu_write_firmware(struct mtd_info *mtd, unsigned block,
+ unsigned num_blocks, void *buf, size_t len)
{
uint64_t offset = block * mtd->erasesize;
int ret;
@@ -304,13 +310,16 @@ static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, s
while (len > 0) {
int now = min(len, mtd->erasesize);
+ if (!num_blocks)
+ return -ENOSPC;
+
pr_debug("writing %p at 0x%08llx, left 0x%08x\n",
buf, offset, len);
if (mtd_block_isbad(mtd, offset)) {
+ pr_debug("write skip block @ 0x%08llx\n", offset);
offset += mtd->erasesize;
block++;
- pr_debug("write skip block @ 0x%08llx\n", offset);
continue;
}
@@ -322,6 +331,7 @@ static int imx6_bbu_write_firmware(struct mtd_info *mtd, int block, void *buf, s
len -= now;
buf += now;
block++;
+ num_blocks--;
}
return block;
@@ -348,35 +358,40 @@ static int dbbt_data_create(struct mtd_info *mtd, void *buf, int block_last)
return n_bad_blocks;
}
-static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *data)
+static int imx_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *data)
{
+ struct imx_nand_fcb_bbu_handler *imx_handler =
+ container_of(handler, struct imx_nand_fcb_bbu_handler, handler);
struct cdev *bcb_cdev;
struct mtd_info *mtd;
- int ret, block_fw1, block_fw2, block_last;
+ int ret, block_fw1, block_fw2;
struct fcb_block *fcb;
struct dbbt_block *dbbt;
void *fcb_raw_page, *dbbt_page, *dbbt_data_page;
void *ecc;
int written;
void *fw;
- unsigned fw_size;
+ unsigned fw_size, partition_size;
int i;
+ enum filetype filetype;
+ unsigned num_blocks_fcb_dbbt, num_blocks, num_blocks_fw;
- if (file_detect_type(data->image, data->len) != filetype_arm_barebox &&
- !bbu_force(data, "Not an ARM barebox image"))
- return -EINVAL;
+ filetype = file_detect_type(data->image, data->len);
- ret = bbu_confirm(data);
- if (ret)
- return ret;
+ if (filetype != imx_handler->filetype &&
+ !bbu_force(data, "Image is not of type %s but of type %s",
+ file_type_to_string(imx_handler->filetype),
+ file_type_to_string(filetype)))
+ return -EINVAL;
- bcb_cdev = cdev_by_name("nand0");
+ bcb_cdev = cdev_by_name(handler->devicefile);
if (!bcb_cdev) {
pr_err("%s: No FCB device!\n", __func__);
return -ENODEV;
}
mtd = bcb_cdev->mtd;
+ partition_size = mtd->size;
fcb_raw_page = xzalloc(mtd->writesize + mtd->oobsize);
@@ -396,30 +411,45 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
fw = xzalloc(fw_size);
memcpy(fw, data->image, data->len);
- block_fw1 = 4;
+ num_blocks_fcb_dbbt = 4;
+ num_blocks = partition_size / mtd->erasesize;
+ num_blocks_fw = (num_blocks - num_blocks_fcb_dbbt) / 2;
+
+ block_fw1 = num_blocks_fcb_dbbt;
+ block_fw2 = num_blocks_fcb_dbbt + num_blocks_fw;
+
+ pr_info("writing first firmware to block %d (ofs 0x%08x)\n",
+ block_fw1, block_fw1 * mtd->erasesize);
+ pr_info("writing second firmware to block %d (ofs 0x%08x)\n",
+ block_fw2, block_fw2 * mtd->erasesize);
+ pr_info("maximum size per firmware: 0x%08x bytes\n",
+ num_blocks_fw * mtd->erasesize);
- ret = imx6_bbu_erase(mtd);
+ if (num_blocks_fw * mtd->erasesize < fw_size)
+ return -ENOSPC;
+
+ ret = bbu_confirm(data);
if (ret)
goto out;
- ret = imx6_bbu_write_firmware(mtd, block_fw1, fw, fw_size);
- if (ret < 0)
+ ret = imx_bbu_erase(mtd);
+ if (ret)
goto out;
- block_fw2 = ret;
-
- ret = imx6_bbu_write_firmware(mtd, block_fw2, fw, fw_size);
+ ret = imx_bbu_write_firmware(mtd, block_fw1, num_blocks_fw, fw, fw_size);
if (ret < 0)
goto out;
- block_last = ret;
+ ret = imx_bbu_write_firmware(mtd, block_fw2, num_blocks_fw, fw, fw_size);
+ if (ret < 0)
+ goto out;
fcb->Firmware1_startingPage = block_fw1 * mtd->erasesize / mtd->writesize;
fcb->Firmware2_startingPage = block_fw2 * mtd->erasesize / mtd->writesize;
fcb->PagesInFirmware1 = ALIGN(data->len, mtd->writesize) / mtd->writesize;
fcb->PagesInFirmware2 = fcb->PagesInFirmware1;
- fcb_create(fcb, mtd);
+ fcb_create(imx_handler, fcb, mtd);
encode_hamming_13_8(fcb, ecc, 512);
/*
@@ -431,10 +461,6 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
*/
memset(fcb_raw_page + mtd->writesize, 0xFF, 2);
- ret = raw_write_page(mtd, fcb_raw_page, 0);
- if (ret)
- goto out;
-
ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize);
if (ret)
goto out;
@@ -443,21 +469,29 @@ static int imx6_bbu_nand_update(struct bbu_handler *handler, struct bbu_data *da
dbbt->FingerPrint = 0x54424244;
dbbt->Version = 0x01000000;
- ret = dbbt_data_create(mtd, dbbt_data_page, block_last);
+ ret = dbbt_data_create(mtd, dbbt_data_page, block_fw2 + num_blocks_fw);
if (ret < 0)
goto out;
- if (ret > 0)
+ if (ret > 0) {
dbbt->DBBTNumOfPages = 1;
+ if (imx_handler->dbbt_create)
+ imx_handler->dbbt_create(imx_handler, dbbt, ret);
+ }
- for (i = 2; i < 4; i++) {
- ret = mtd_write(mtd, mtd->erasesize * i, 2048, &written, dbbt_page);
+ for (i = 0; i < 4; i++) {
+ ret = raw_write_page(mtd, fcb_raw_page, mtd->erasesize * i);
+ if (ret)
+ goto out;
+
+ ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize,
+ mtd->writesize, &written, dbbt_page);
if (ret)
goto out;
if (dbbt->DBBTNumOfPages > 0) {
- ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize * 4,
- 2048, &written, dbbt_data_page);
+ ret = mtd_write(mtd, mtd->erasesize * i + mtd->writesize * 5,
+ mtd->writesize, &written, dbbt_data_page);
if (ret)
goto out;
}
@@ -472,16 +506,127 @@ out:
return ret;
}
+static void imx6_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
+{
+ /* Also hardcoded in kobs-ng */
+ fcb->DataSetup = 80;
+ fcb->DataHold = 60;
+ fcb->AddressSetup = 25;
+ fcb->DSAMPLE_TIME = 6;
+ fcb->MetadataBytes = 10;
+}
+
int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
{
+ struct imx_nand_fcb_bbu_handler *imx_handler;
struct bbu_handler *handler;
int ret;
- handler = xzalloc(sizeof(*handler));
- handler->devicefile = "/dev/nand0";
+ imx_handler = xzalloc(sizeof(*imx_handler));
+ imx_handler->fcb_create = imx6_fcb_create;
+ imx_handler->filetype = filetype_arm_barebox;
+
+ handler = &imx_handler->handler;
+ handler->devicefile = "nand0.barebox";
+ handler->name = name;
+ handler->flags = flags;
+ handler->handler = imx_bbu_nand_update;
+
+ ret = bbu_register_handler(handler);
+ if (ret)
+ free(handler);
+
+ return ret;
+}
+
+#ifdef CONFIG_ARCH_IMX28
+#include <mach/imx28-regs.h>
+
+#define GPMI_TIMING0 0x00000070
+#define GPMI_TIMING0_ADDRESS_SETUP_MASK (0xff << 16)
+#define GPMI_TIMING0_ADDRESS_SETUP_OFFSET 16
+#define GPMI_TIMING0_DATA_HOLD_MASK (0xff << 8)
+#define GPMI_TIMING0_DATA_HOLD_OFFSET 8
+#define GPMI_TIMING0_DATA_SETUP_MASK 0xff
+#define GPMI_TIMING0_DATA_SETUP_OFFSET 0
+
+#define GPMI_TIMING1 0x00000080
+
+#define BCH_MODE 0x00000020
+
+#define BCH_FLASH0LAYOUT0 0x00000080
+#define BCH_FLASHLAYOUT0_NBLOCKS_MASK (0xff << 24)
+#define BCH_FLASHLAYOUT0_NBLOCKS_OFFSET 24
+#define BCH_FLASHLAYOUT0_META_SIZE_MASK (0xff << 16)
+#define BCH_FLASHLAYOUT0_META_SIZE_OFFSET 16
+#define BCH_FLASHLAYOUT0_ECC0_MASK (0xf << 12)
+#define BCH_FLASHLAYOUT0_ECC0_OFFSET 12
+#define BCH_FLASHLAYOUT0_DATA0_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT0_DATA0_SIZE_OFFSET 0
+
+#define BCH_FLASH0LAYOUT1 0x00000090
+#define BCH_FLASHLAYOUT1_PAGE_SIZE_MASK (0xffff << 16)
+#define BCH_FLASHLAYOUT1_PAGE_SIZE_OFFSET 16
+#define BCH_FLASHLAYOUT1_ECCN_MASK (0xf << 12)
+#define BCH_FLASHLAYOUT1_ECCN_OFFSET 12
+#define BCH_FLASHLAYOUT1_DATAN_SIZE_MASK 0xfff
+#define BCH_FLASHLAYOUT1_DATAN_SIZE_OFFSET 0
+
+static void imx28_fcb_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct fcb_block *fcb, struct mtd_info *mtd)
+{
+ u32 fl0, fl1, t0;
+ void __iomem *bch_regs = (void *)MXS_BCH_BASE;
+ void __iomem *gpmi_regs = (void *)MXS_GPMI_BASE;
+
+ fl0 = readl(bch_regs + BCH_FLASH0LAYOUT0);
+ fl1 = readl(bch_regs + BCH_FLASH0LAYOUT1);
+ t0 = readl(gpmi_regs + GPMI_TIMING0);
+
+ fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->DataSetup = BF_VAL(t0, GPMI_TIMING0_DATA_SETUP);
+ fcb->DataHold = BF_VAL(t0, GPMI_TIMING0_DATA_HOLD);
+ fcb->AddressSetup = BF_VAL(t0, GPMI_TIMING0_ADDRESS_SETUP);
+ fcb->MetadataBytes = BF_VAL(fl0, BCH_FLASHLAYOUT0_META_SIZE);
+ fcb->NumEccBlocksPerPage = BF_VAL(fl0, BCH_FLASHLAYOUT0_NBLOCKS);
+ fcb->EraseThreshold = readl(bch_regs + BCH_MODE);
+}
+
+static void imx28_dbbt_create(struct imx_nand_fcb_bbu_handler *imx_handler,
+ struct dbbt_block *dbbt, int num_bad_blocks)
+{
+ uint32_t a = 0;
+ uint8_t *p = (void *)dbbt;
+ int i;
+
+ dbbt->numberBB = num_bad_blocks;
+
+ for (i = 4; i < 512; i++)
+ a += p[i];
+
+ a ^= 0xffffffff;
+
+ dbbt->Checksum = a;
+}
+
+int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ struct imx_nand_fcb_bbu_handler *imx_handler;
+ struct bbu_handler *handler;
+ int ret;
+
+ imx_handler = xzalloc(sizeof(*imx_handler));
+ imx_handler->fcb_create = imx28_fcb_create;
+ imx_handler->dbbt_create = imx28_dbbt_create;
+
+ imx_handler->filetype = filetype_mxs_bootstream;
+
+ handler = &imx_handler->handler;
+ handler->devicefile = "nand0.barebox";
handler->name = name;
handler->flags = flags;
- handler->handler = imx6_bbu_nand_update;
+ handler->handler = imx_bbu_nand_update;
ret = bbu_register_handler(handler);
if (ret)
@@ -489,3 +634,4 @@ int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
return ret;
}
+#endif
diff --git a/common/kallsyms.c b/common/kallsyms.c
index 53e22cdc73..e15dec5dfc 100644
--- a/common/kallsyms.c
+++ b/common/kallsyms.c
@@ -212,4 +212,3 @@ int sprint_symbol(char *buffer, unsigned long address)
return len;
}
EXPORT_SYMBOL_GPL(sprint_symbol);
-
diff --git a/common/parser.c b/common/parser.c
index 4a48210c4d..207599f429 100644
--- a/common/parser.c
+++ b/common/parser.c
@@ -284,4 +284,3 @@ int run_shell(void)
}
return 0;
}
-
diff --git a/common/state.c b/common/state.c
index 7076f5764d..1243320226 100644
--- a/common/state.c
+++ b/common/state.c
@@ -64,6 +64,7 @@ enum state_variable_type {
STATE_TYPE_U8,
STATE_TYPE_U32,
STATE_TYPE_MAC,
+ STATE_TYPE_STRING,
};
/* instance of a single variable */
@@ -90,7 +91,7 @@ struct variable_type {
struct list_head list;
int (*export)(struct state_variable *, struct device_node *,
enum state_convert);
- int (*import)(struct state_variable *, const struct device_node *);
+ int (*import)(struct state_variable *, struct device_node *);
struct state_variable *(*create)(struct state *state,
const char *name, struct device_node *);
};
@@ -113,6 +114,7 @@ static int state_set_dirty(struct param_d *p, void *priv)
struct state_uint32 {
struct state_variable var;
struct param_d *param;
+ struct state *state;
uint32_t value;
uint32_t value_default;
};
@@ -141,18 +143,21 @@ static int state_uint32_export(struct state_variable *var,
struct state_uint32 *su32 = to_state_uint32(var);
int ret;
- if (su32->value_default || conv == STATE_CONVERT_FIXUP) {
+ if (su32->value_default) {
ret = of_property_write_u32(node, "default",
su32->value_default);
- if (ret || conv == STATE_CONVERT_FIXUP)
+ if (ret)
return ret;
}
+ if (conv == STATE_CONVERT_FIXUP)
+ return 0;
+
return of_property_write_u32(node, "value", su32->value);
}
static int state_uint32_import(struct state_variable *sv,
- const struct device_node *node)
+ struct device_node *node)
{
struct state_uint32 *su32 = to_state_uint32(sv);
@@ -163,6 +168,17 @@ static int state_uint32_import(struct state_variable *sv,
return 0;
}
+static int state_uint8_set(struct param_d *p, void *priv)
+{
+ struct state_uint32 *su32 = priv;
+ struct state *state = su32->state;
+
+ if (su32->value > 255)
+ return -ERANGE;
+
+ return state_set_dirty(p, state);
+}
+
static struct state_variable *state_uint8_create(struct state *state,
const char *name, struct device_node *node)
{
@@ -171,8 +187,8 @@ static struct state_variable *state_uint8_create(struct state *state,
su32 = xzalloc(sizeof(*su32));
- param = dev_add_param_int(&state->dev, name, state_set_dirty,
- NULL, &su32->value, "%d", state);
+ param = dev_add_param_int(&state->dev, name, state_uint8_set,
+ NULL, &su32->value, "%u", su32);
if (IS_ERR(param)) {
free(su32);
return ERR_CAST(param);
@@ -185,6 +201,7 @@ static struct state_variable *state_uint8_create(struct state *state,
#else
su32->var.raw = &su32->value + 3;
#endif
+ su32->state = state;
return &su32->var;
}
@@ -235,13 +252,16 @@ static int state_enum32_export(struct state_variable *var,
int ret, i, len;
char *prop, *str;
- if (enum32->value_default || conv == STATE_CONVERT_FIXUP) {
+ if (enum32->value_default) {
ret = of_property_write_u32(node, "default",
enum32->value_default);
- if (ret || conv == STATE_CONVERT_FIXUP)
+ if (ret)
return ret;
}
+ if (conv == STATE_CONVERT_FIXUP)
+ return 0;
+
ret = of_property_write_u32(node, "value", enum32->value);
if (ret)
return ret;
@@ -265,7 +285,7 @@ static int state_enum32_export(struct state_variable *var,
}
static int state_enum32_import(struct state_variable *sv,
- const struct device_node *node)
+ struct device_node *node)
{
struct state_enum32 *enum32 = to_state_enum32(sv);
int len;
@@ -350,17 +370,22 @@ static int state_mac_export(struct state_variable *var,
struct state_mac *mac = to_state_mac(var);
int ret;
- ret = of_property_write_u8_array(node, "default", mac->value_default,
- ARRAY_SIZE(mac->value_default));
- if (ret || conv == STATE_CONVERT_FIXUP)
- return ret;
+ if (!is_zero_ether_addr(mac->value_default)) {
+ ret = of_property_write_u8_array(node, "default", mac->value_default,
+ ARRAY_SIZE(mac->value_default));
+ if (ret)
+ return ret;
+ }
+
+ if (conv == STATE_CONVERT_FIXUP)
+ return 0;
return of_property_write_u8_array(node, "value", mac->value,
ARRAY_SIZE(mac->value));
}
static int state_mac_import(struct state_variable *sv,
- const struct device_node *node)
+ struct device_node *node)
{
struct state_mac *mac = to_state_mac(sv);
@@ -397,6 +422,151 @@ out:
return ERR_PTR(ret);
}
+/*
+ * string
+ */
+struct state_string {
+ struct state_variable var;
+ struct param_d *param;
+ struct state *state;
+ char *value;
+ const char *value_default;
+ char raw[];
+};
+
+static inline struct state_string *to_state_string(struct state_variable *s)
+{
+ return container_of(s, struct state_string, var);
+}
+
+static int state_string_export(struct state_variable *var,
+ struct device_node *node, enum state_convert conv)
+{
+ struct state_string *string = to_state_string(var);
+ int ret = 0;
+
+ if (string->value_default) {
+ ret = of_set_property(node, "default", string->value_default,
+ strlen(string->value_default) + 1, 1);
+
+ if (ret)
+ return ret;
+ }
+
+ if (conv == STATE_CONVERT_FIXUP)
+ return 0;
+
+ if (string->value)
+ ret = of_set_property(node, "value", string->value,
+ strlen(string->value) + 1, 1);
+
+ return ret;
+}
+
+static int state_string_copy_to_raw(struct state_string *string,
+ const char *src)
+{
+ size_t len;
+
+ len = strlen(src);
+ if (len > string->var.size)
+ return -EILSEQ;
+
+ /* copy string and clear remaining contents of buffer */
+ memcpy(string->raw, src, len);
+ memset(string->raw + len, 0x0, string->var.size - len);
+
+ return 0;
+}
+
+static int state_string_import(struct state_variable *sv,
+ struct device_node *node)
+{
+ struct state_string *string = to_state_string(sv);
+ const char *value = NULL;
+ size_t len;
+ int ret;
+
+ of_property_read_string(node, "default", &string->value_default);
+ if (string->value_default) {
+ len = strlen(string->value_default);
+ if (len > string->var.size)
+ return -EILSEQ;
+ }
+
+ ret = of_property_read_string(node, "value", &value);
+ if (ret)
+ value = string->value_default;
+
+ if (value)
+ return state_string_copy_to_raw(string, value);
+
+ return 0;
+}
+
+static int state_string_set(struct param_d *p, void *priv)
+{
+ struct state_string *string = priv;
+ struct state *state = string->state;
+ int ret;
+
+ ret = state_string_copy_to_raw(string, string->value);
+ if (ret)
+ return ret;
+
+ return state_set_dirty(p, state);
+}
+
+static int state_string_get(struct param_d *p, void *priv)
+{
+ struct state_string *string = priv;
+
+ free(string->value);
+ if (string->raw[0])
+ string->value = xstrndup(string->raw, string->var.size);
+ else
+ string->value = xstrdup("");
+
+ return 0;
+}
+
+static struct state_variable *state_string_create(struct state *state,
+ const char *name, struct device_node *node)
+{
+ struct state_string *string;
+ u32 start_size[2];
+ int ret;
+
+ ret = of_property_read_u32_array(node, "reg", start_size,
+ ARRAY_SIZE(start_size));
+ if (ret) {
+ dev_err(&state->dev,
+ "%s: reg property not found\n", name);
+ return ERR_PTR(ret);
+ }
+
+ /* limit to arbitrary len of 4k */
+ if (start_size[1] > 4096)
+ return ERR_PTR(-EILSEQ);
+
+ string = xzalloc(sizeof(*string) + start_size[1]);
+ string->var.size = start_size[1];
+ string->var.raw = &string->raw;
+ string->state = state;
+
+ string->param = dev_add_param_string(&state->dev, name, state_string_set,
+ state_string_get, &string->value, string);
+ if (IS_ERR(string->param)) {
+ ret = PTR_ERR(string->param);
+ goto out;
+ }
+
+ return &string->var;
+out:
+ free(string);
+ return ERR_PTR(ret);
+}
+
static struct variable_type types[] = {
{
.type = STATE_TYPE_U8,
@@ -422,6 +592,12 @@ static struct variable_type types[] = {
.export = state_mac_export,
.import = state_mac_import,
.create = state_mac_create,
+ }, {
+ .type = STATE_TYPE_STRING,
+ .type_name = "string",
+ .export = state_string_export,
+ .import = state_string_import,
+ .create = state_string_create,
},
};
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 24cb5bc62b..338bea1280 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -113,14 +113,29 @@ int device_detect(struct device_d *dev)
return dev->detect(dev);
}
-int device_detect_by_name(const char *devname)
+int device_detect_by_name(const char *__devname)
{
- struct device_d *dev = get_device_by_name(devname);
+ char *devname = xstrdup(__devname);
+ char *str = devname;
+ struct device_d *dev;
+ int ret = -ENODEV;
+
+ while (1) {
+ strsep(&str, ".");
+
+ dev = get_device_by_name(devname);
+ if (dev)
+ ret = device_detect(dev);
- if (!dev)
- return -ENODEV;
+ if (!str)
+ break;
+ else
+ *(str - 1) = '.';
+ }
- return device_detect(dev);
+ free(devname);
+
+ return ret;
}
static int match(struct driver_d *drv, struct device_d *dev)
diff --git a/drivers/bus/omap-gpmc.c b/drivers/bus/omap-gpmc.c
index 6752c42a35..8ae909a1b6 100644
--- a/drivers/bus/omap-gpmc.c
+++ b/drivers/bus/omap-gpmc.c
@@ -24,6 +24,14 @@
#define GPMC_CS_NUM 8
#define GPMC_NR_WAITPINS 4
+#define GPMC_BURST_4 4 /* 4 word burst */
+#define GPMC_BURST_8 8 /* 8 word burst */
+#define GPMC_BURST_16 16 /* 16 word burst */
+#define GPMC_DEVWIDTH_8BIT 1 /* 8-bit device width */
+#define GPMC_DEVWIDTH_16BIT 2 /* 16-bit device width */
+#define GPMC_MUX_AAD 1 /* Addr-Addr-Data multiplex */
+#define GPMC_MUX_AD 2 /* Addr-Data multiplex */
+
#define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31)
#define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30)
#define GPMC_CONFIG1_READTYPE_ASYNC (0 << 29)
@@ -55,6 +63,9 @@
#define GPMC_CONFIG6_CYCLE2CYCLESAMECSEN (1 << 7)
#define GPMC_CONFIG7_CSVALID (1 << 6)
+#define GPMC_DEVICETYPE_NOR 0
+#define GPMC_DEVICETYPE_NAND 2
+
static unsigned int gpmc_cs_num = GPMC_CS_NUM;
static unsigned int gpmc_nr_waitpins;
static unsigned long gpmc_l3_clk = 100000000; /* This should be a proper clock */
@@ -149,7 +160,7 @@ static void gpmc_cs_bool_timings(struct gpmc_config *gpmc_config, const struct g
if (p->oe_extra_delay)
gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
if (p->we_extra_delay)
- gpmc_config->cfg[3] |= GPMC_CONFIG4_OEEXTRADELAY;
+ gpmc_config->cfg[3] |= GPMC_CONFIG4_WEEXTRADELAY;
if (p->cycle2cyclesamecsen)
gpmc_config->cfg[5] |= GPMC_CONFIG6_CYCLE2CYCLESAMECSEN;
if (p->cycle2cyclediffcsen)
@@ -220,6 +231,8 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
if (div < 0)
return div;
+ gpmc_config->cfg[0] |= div - 1;
+
ret |= set_cfg(gpmc_config, 0, 18, 19, t->wait_monitoring);
ret |= set_cfg(gpmc_config, 0, 25, 26, t->clk_activation);
@@ -255,6 +268,60 @@ static int gpmc_timings_to_config(struct gpmc_config *gpmc_config, const struct
return 0;
}
+static int gpmc_settings_to_config(struct gpmc_config *gpmc_config,
+ struct gpmc_settings *p)
+{
+ u32 config1 = gpmc_config->cfg[0];
+
+ /* Page/burst mode supports lengths of 4, 8 and 16 bytes */
+ if (p->burst_read || p->burst_write) {
+ switch (p->burst_len) {
+ case GPMC_BURST_4:
+ case GPMC_BURST_8:
+ case GPMC_BURST_16:
+ break;
+ default:
+ pr_err("%s: invalid page/burst-length (%d)\n",
+ __func__, p->burst_len);
+ return -EINVAL;
+ }
+ }
+
+ if (p->wait_pin > gpmc_nr_waitpins) {
+ pr_err("%s: invalid wait-pin (%d)\n", __func__, p->wait_pin);
+ return -EINVAL;
+ }
+
+ config1 |= GPMC_CONFIG1_DEVICESIZE((p->device_width - 1));
+
+ if (p->sync_read)
+ config1 |= GPMC_CONFIG1_READTYPE_SYNC;
+ if (p->sync_write)
+ config1 |= GPMC_CONFIG1_WRITETYPE_SYNC;
+ if (p->wait_on_read)
+ config1 |= GPMC_CONFIG1_WAIT_READ_MON;
+ if (p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_WRITE_MON;
+ if (p->wait_on_read || p->wait_on_write)
+ config1 |= GPMC_CONFIG1_WAIT_PIN_SEL(p->wait_pin);
+ if (p->device_nand)
+ config1 |= GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NAND);
+ if (p->mux_add_data)
+ config1 |= GPMC_CONFIG1_MUXTYPE(p->mux_add_data);
+ if (p->burst_read)
+ config1 |= GPMC_CONFIG1_READMULTIPLE_SUPP;
+ if (p->burst_write)
+ config1 |= GPMC_CONFIG1_WRITEMULTIPLE_SUPP;
+ if (p->burst_read || p->burst_write) {
+ config1 |= GPMC_CONFIG1_PAGE_LEN(p->burst_len >> 3);
+ config1 |= p->burst_wrap ? GPMC_CONFIG1_WRAPBURST_SUPP : 0;
+ }
+
+ gpmc_config->cfg[0] = config1;
+
+ return 0;
+}
+
/**
* gpmc_read_settings_dt - read gpmc settings from device-tree
* @np: pointer to device-tree node for a gpmc child device
@@ -464,6 +531,77 @@ static int gpmc_probe_nand_child(struct device_d *dev,
return 0;
}
+/**
+ * gpmc_probe_generic_child - configures the gpmc for a child device
+ * @pdev: pointer to gpmc platform device
+ * @child: pointer to device-tree node for child device
+ *
+ * Allocates and configures a GPMC chip-select for a child device.
+ * Returns 0 on success and appropriate negative error code on failure.
+ */
+static int gpmc_probe_generic_child(struct device_d *dev,
+ struct device_node *child)
+{
+ struct gpmc_settings gpmc_s = {};
+ struct gpmc_timings gpmc_t = {};
+ struct resource res;
+ int ret, cs;
+ struct gpmc_config cfg = {};
+ resource_size_t size;
+
+ if (of_property_read_u32(child, "reg", &cs) < 0) {
+ dev_err(dev, "%s has no 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ if (of_address_to_resource(child, 0, &res) < 0) {
+ dev_err(dev, "%s has malformed 'reg' property\n",
+ child->full_name);
+ return -ENODEV;
+ }
+
+ gpmc_read_settings_dt(child, &gpmc_s);
+ gpmc_read_timings_dt(child, &gpmc_t);
+
+ ret = of_property_read_u32(child, "bank-width", &gpmc_s.device_width);
+ if (ret < 0)
+ goto err;
+
+ gpmc_timings_to_config(&cfg, &gpmc_t);
+
+ cfg.base = res.start;
+
+ size = resource_size(&res);
+ if (size > SZ_64M)
+ cfg.size = GPMC_SIZE_128M;
+ else if (size > SZ_32M)
+ cfg.size = GPMC_SIZE_64M;
+ else if (size > SZ_16M)
+ cfg.size = GPMC_SIZE_32M;
+ else
+ cfg.size = GPMC_SIZE_16M;
+
+ gpmc_settings_to_config(&cfg, &gpmc_s);
+
+ gpmc_cs_config(cs, &cfg);
+
+ /* create platform device, NULL on error or when disabled */
+ if (of_get_property(child, "compatible", NULL) && !of_platform_device_create(child, dev))
+ goto err_child_fail;
+
+ return 0;
+
+err_child_fail:
+
+ dev_err(dev, "failed to create gpmc child %s\n", child->name);
+ ret = -ENODEV;
+
+err:
+
+ return ret;
+}
+
static int gpmc_probe(struct device_d *dev)
{
struct device_node *child, *node = dev->device_node;
@@ -488,6 +626,10 @@ static int gpmc_probe(struct device_d *dev)
if (!strncmp(child->name, "nand", 4))
ret = gpmc_probe_nand_child(dev, child);
+ else if (strncmp(child->name, "ethernet", 8) == 0 ||
+ strncmp(child->name, "nor", 3) == 0 ||
+ strncmp(child->name, "uart", 4) == 0)
+ ret = gpmc_probe_generic_child(dev, child);
else
dev_warn(dev, "unhandled child %s\n", child->name);
diff --git a/drivers/clk/mxs/clk-imx28.c b/drivers/clk/mxs/clk-imx28.c
index 77a13bc7ac..a408044264 100644
--- a/drivers/clk/mxs/clk-imx28.c
+++ b/drivers/clk/mxs/clk-imx28.c
@@ -158,6 +158,7 @@ int __init mx28_clocks_init(void __iomem *regs)
clkdev_add_physbase(clks[uart], IMX_UART3_BASE, NULL);
clkdev_add_physbase(clks[uart], IMX_UART4_BASE, NULL);
clkdev_add_physbase(clks[gpmi], MXS_GPMI_BASE, NULL);
+ clkdev_add_physbase(clks[pwm], IMX_PWM_BASE, NULL);
if (IS_ENABLED(CONFIG_DRIVER_VIDEO_STM))
clkdev_add_physbase(clks[lcdif_comp], IMX_FB_BASE, NULL);
diff --git a/drivers/mci/Kconfig b/drivers/mci/Kconfig
index 31f7d2d4ea..ebd8da9591 100644
--- a/drivers/mci/Kconfig
+++ b/drivers/mci/Kconfig
@@ -95,7 +95,7 @@ config MCI_OMAP_HSMMC
config MCI_PXA
bool "PXA"
- depends on ARCH_PXA
+ depends on ARCH_PXA2XX
help
Enable this entry to add support to read and write SD cards on a
XScale PXA25x / PXA27x based system.
diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 49ea88cac4..ea1be556b4 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -20,6 +20,16 @@ config MTD_RAW_DEVICE
default n
prompt "mtdraw device to read/write both data+oob"
+config MTD_CONCAT
+ bool
+ prompt "MTD concatenating support"
+ help
+ Support for concatenating several MTD devices into a single
+ (virtual) one. This allows you to have -for example- a JFFS(2)
+ file system spanning multiple physical flash chips. This option
+ needs driver support, currently only the cfi-flash driver supports
+ concatenating MTD devices.
+
source "drivers/mtd/devices/Kconfig"
source "drivers/mtd/nor/Kconfig"
source "drivers/mtd/nand/Kconfig"
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 148ec6ca23..d3ae7fca3e 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -6,3 +6,4 @@ obj-y += devices/
obj-$(CONFIG_MTD) += core.o partition.o
obj-$(CONFIG_MTD_OOB_DEVICE) += mtdoob.o
obj-$(CONFIG_MTD_RAW_DEVICE) += mtdraw.o
+obj-$(CONFIG_MTD_CONCAT) += mtdconcat.o
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c
index 681dc9313c..fda903441c 100644
--- a/drivers/mtd/core.c
+++ b/drivers/mtd/core.c
@@ -18,7 +18,9 @@
#include <common.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/mtd.h>
+#include <mtd/ubi-user.h>
#include <cmdlinepart.h>
+#include <filetype.h>
#include <init.h>
#include <xfuncs.h>
#include <driver.h>
@@ -542,7 +544,42 @@ static int of_mtd_fixup(struct device_node *root, void *ctx)
return 0;
}
-int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
+static int mtd_detect(struct device_d *dev)
+{
+ struct mtd_info *mtd = container_of(dev, struct mtd_info, class_dev);
+ int bufsize = 512;
+ void *buf;
+ int ret;
+ enum filetype filetype;
+ size_t retlen;
+
+ /*
+ * Do not try to attach an UBI device if this device has partitions
+ * as it's not a good idea to attach UBI on a raw device when the
+ * real UBI only spans the first partition.
+ */
+ if (!list_empty(&mtd->partitions))
+ return -EBUSY;
+
+ buf = xmalloc(bufsize);
+
+ ret = mtd_read(mtd, 0, bufsize, &retlen, buf);
+ if (ret)
+ goto out;
+
+ filetype = file_detect_type(buf, bufsize);
+ if (filetype == filetype_ubi) {
+ ret = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 20);
+ if (ret == -EEXIST)
+ ret = 0;
+ }
+out:
+ free(buf);
+
+ return ret;
+}
+
+int add_mtd_device(struct mtd_info *mtd, const char *devname, int device_id)
{
struct mtddev_hook *hook;
int ret;
@@ -554,6 +591,9 @@ int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id)
if (mtd->parent)
mtd->class_dev.parent = mtd->parent;
+ if (IS_ENABLED(CONFIG_MTD_UBI))
+ mtd->class_dev.detect = mtd_detect;
+
ret = register_device(&mtd->class_dev);
if (ret)
return ret;
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 345c348c69..9c3925bde1 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -21,7 +21,8 @@ config MTD_DATAFLASH_WRITE_VERIFY
config MTD_M25P80
tristate "Support most SPI Flash chips (AT26DF, M25P, W25X, ...)"
- depends on MTD_SPI_NOR
+ depends on SPI
+ select MTD_SPI_NOR
help
This enables access to most modern SPI flash chips, used for
program and data storage. Series supported include Atmel AT26DF,
diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index c941767de9..794c9dbd82 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -148,14 +148,14 @@ static int m25p80_erase(struct spi_nor *nor, loff_t offset)
{
struct m25p *flash = nor->priv;
- dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
- flash->mtd.erasesize / 1024, (u32)offset);
+ dev_dbg(nor->dev, "%dKiB at 0x%08x\n",
+ flash->mtd.erasesize / 1024, (u32)offset);
- /* Set up command buffer. */
- flash->command[0] = nor->erase_opcode;
- m25p_addr2cmd(nor, offset, flash->command);
+ /* Set up command buffer. */
+ flash->command[0] = nor->erase_opcode;
+ m25p_addr2cmd(nor, offset, flash->command);
- spi_write(flash->spi, flash->command, m25p_cmdsz(nor));
+ spi_write(flash->spi, flash->command, m25p_cmdsz(nor));
return 0;
}
@@ -213,11 +213,11 @@ static const struct platform_device_id m25p_ids[] = {
{"w25q128"}, {"w25q256"}, {"cat25c11"},
{"cat25c03"}, {"cat25c09"}, {"cat25c17"}, {"cat25128"},
- /*
- * Generic support for SPI NOR that can be identified by the JEDEC READ
- * ID opcode (0x9F). Use this, if possible.
- */
- {"nor-jedec"},
+ /*
+ * Generic support for SPI NOR that can be identified by the JEDEC READ
+ * ID opcode (0x9F). Use this, if possible.
+ */
+ {"nor-jedec"},
{ },
};
@@ -233,7 +233,7 @@ static int m25p_probe(struct device_d *dev)
struct m25p *flash;
struct spi_nor *nor;
enum read_mode mode = SPI_NOR_NORMAL;
- char *flash_name = NULL;
+ const char *flash_name = NULL;
int device_id;
int ret;
@@ -277,13 +277,10 @@ static int m25p_probe(struct device_d *dev)
return ret;
device_id = DEVICE_ID_SINGLE;
- if (dev->device_node) {
- const char *alias = of_alias_get(dev->device_node);
- if (alias)
- flash_name = xstrdup(alias);
- } else if (data && data->name) {
+ if (dev->device_node)
+ flash_name = of_alias_get(dev->device_node);
+ else if (data && data->name)
flash_name = data->name;
- }
if (!flash_name) {
device_id = DEVICE_ID_DYNAMIC;
diff --git a/drivers/mtd/mtd.h b/drivers/mtd/mtd.h
index 414bd6cdb5..2a85265f98 100644
--- a/drivers/mtd/mtd.h
+++ b/drivers/mtd/mtd.h
@@ -25,7 +25,7 @@
*/
struct mtddev_hook {
struct list_head hook;
- int (*add_mtd_device)(struct mtd_info *mtd, char *devname, void **priv);
+ int (*add_mtd_device)(struct mtd_info *mtd, const char *devname, void **priv);
int (*del_mtd_device)(struct mtd_info *mtd, void **priv);
void *priv;
};
diff --git a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c
new file mode 100644
index 0000000000..10d3dc4c36
--- /dev/null
+++ b/drivers/mtd/mtdconcat.c
@@ -0,0 +1,765 @@
+/*
+ * MTD device concatenation layer
+ *
+ * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
+ * Copyright © 2002-2010 David Woodhouse <dwmw2@infradead.org>
+ *
+ * NAND support by Christian Gan <cgan@iders.ca>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+#include <common.h>
+#include <malloc.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/concat.h>
+
+#include <asm-generic/div64.h>
+
+/*
+ * Our storage structure:
+ * Subdev points to an array of pointers to struct mtd_info objects
+ * which is allocated along with this structure
+ *
+ */
+struct mtd_concat {
+ struct mtd_info mtd;
+ int num_subdev;
+ struct mtd_info **subdev;
+};
+
+/*
+ * how to calculate the size required for the above structure,
+ * including the pointer array subdev points to:
+ */
+#define SIZEOF_STRUCT_MTD_CONCAT(num_subdev) \
+ ((sizeof(struct mtd_concat) + (num_subdev) * sizeof(struct mtd_info *)))
+
+/*
+ * Given a pointer to the MTD object in the mtd_concat structure,
+ * we can retrieve the pointer to that structure with this macro.
+ */
+#define CONCAT(x) ((struct mtd_concat *)(x))
+
+/*
+ * MTD methods which look up the relevant subdevice, translate the
+ * effective address and pass through to the subdevice.
+ */
+
+static int
+concat_read(struct mtd_info *mtd, loff_t from, size_t len,
+ size_t * retlen, u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int ret = 0, err;
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (from >= subdev->size) {
+ /* Not destined for this subdev */
+ size = 0;
+ from -= subdev->size;
+ continue;
+ }
+ if (from + len > subdev->size)
+ /* First part goes into this subdev */
+ size = subdev->size - from;
+ else
+ /* Entire transaction goes into this subdev */
+ size = len;
+
+ err = mtd_read(subdev, from, size, &retsize, buf);
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (mtd_is_eccerr(err)) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (mtd_is_bitflip(err)) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ return ret;
+
+ buf += size;
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write(struct mtd_info *mtd, loff_t to, size_t len,
+ size_t * retlen, const u_char * buf)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int err = -EINVAL;
+ int i;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ size_t size, retsize;
+
+ if (to >= subdev->size) {
+ size = 0;
+ to -= subdev->size;
+ continue;
+ }
+ if (to + len > subdev->size)
+ size = subdev->size - to;
+ else
+ size = len;
+
+ err = mtd_write(subdev, to, size, &retsize, buf);
+ if (err)
+ break;
+
+ *retlen += retsize;
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ buf += size;
+ to = 0;
+ }
+ return err;
+}
+
+static int
+concat_read_oob(struct mtd_info *mtd, loff_t from, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err, ret = 0;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (from >= subdev->size) {
+ from -= subdev->size;
+ continue;
+ }
+
+ /* partial read ? */
+ if (from + devops.len > subdev->size)
+ devops.len = subdev->size - from;
+
+ err = mtd_read_oob(subdev, from, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+
+ /* Save information about bitflips! */
+ if (unlikely(err)) {
+ if (mtd_is_eccerr(err)) {
+ mtd->ecc_stats.failed++;
+ ret = err;
+ } else if (mtd_is_bitflip(err)) {
+ mtd->ecc_stats.corrected++;
+ /* Do not overwrite -EBADMSG !! */
+ if (!ret)
+ ret = err;
+ } else
+ return err;
+ }
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return ret;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return ret;
+ devops.oobbuf += ops->oobretlen;
+ }
+
+ from = 0;
+ }
+ return -EINVAL;
+}
+
+static int
+concat_write_oob(struct mtd_info *mtd, loff_t to, struct mtd_oob_ops *ops)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_oob_ops devops = *ops;
+ int i, err;
+
+ if (!(mtd->flags & MTD_WRITEABLE))
+ return -EROFS;
+
+ ops->retlen = ops->oobretlen = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (to >= subdev->size) {
+ to -= subdev->size;
+ continue;
+ }
+
+ /* partial write ? */
+ if (to + devops.len > subdev->size)
+ devops.len = subdev->size - to;
+
+ err = mtd_write_oob(subdev, to, &devops);
+ ops->retlen += devops.retlen;
+ ops->oobretlen += devops.oobretlen;
+ if (err)
+ return err;
+
+ if (devops.datbuf) {
+ devops.len = ops->len - ops->retlen;
+ if (!devops.len)
+ return 0;
+ devops.datbuf += devops.retlen;
+ }
+ if (devops.oobbuf) {
+ devops.ooblen = ops->ooblen - ops->oobretlen;
+ if (!devops.ooblen)
+ return 0;
+ devops.oobbuf += devops.oobretlen;
+ }
+ to = 0;
+ }
+ return -EINVAL;
+}
+
+static int concat_dev_erase(struct mtd_info *mtd, struct erase_info *erase)
+{
+ int err;
+ wait_queue_head_t waitq;
+
+ erase->mtd = mtd;
+ erase->priv = (unsigned long) &waitq;
+
+ err = mtd_erase(mtd, erase);
+
+ return err;
+}
+
+static int concat_erase(struct mtd_info *mtd, struct erase_info *instr)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ struct mtd_info *subdev;
+ int i, err;
+ uint64_t length, offset = 0;
+ struct erase_info *erase;
+
+ /*
+ * Check for proper erase block alignment of the to-be-erased area.
+ * It is easier to do this based on the super device's erase
+ * region info rather than looking at each particular sub-device
+ * in turn.
+ */
+ if (!concat->mtd.numeraseregions) {
+ /* the easy case: device has uniform erase block size */
+ if (instr->addr & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ if (instr->len & (concat->mtd.erasesize - 1))
+ return -EINVAL;
+ } else {
+ /* device has variable erase size */
+ struct mtd_erase_region_info *erase_regions =
+ concat->mtd.eraseregions;
+
+ /*
+ * Find the erase region where the to-be-erased area begins:
+ */
+ for (i = 0; i < concat->mtd.numeraseregions &&
+ instr->addr >= erase_regions[i].offset; i++) ;
+ --i;
+
+ /*
+ * Now erase_regions[i] is the region in which the
+ * to-be-erased area begins. Verify that the starting
+ * offset is aligned to this region's erase size:
+ */
+ if (i < 0 || instr->addr & (erase_regions[i].erasesize - 1))
+ return -EINVAL;
+
+ /*
+ * now find the erase region where the to-be-erased area ends:
+ */
+ for (; i < concat->mtd.numeraseregions &&
+ (instr->addr + instr->len) >= erase_regions[i].offset;
+ ++i) ;
+ --i;
+ /*
+ * check if the ending offset is aligned to this region's erase size
+ */
+ if (i < 0 || ((instr->addr + instr->len) &
+ (erase_regions[i].erasesize - 1)))
+ return -EINVAL;
+ }
+
+ /* make a local copy of instr to avoid modifying the caller's struct */
+ erase = kmalloc(sizeof (struct erase_info), GFP_KERNEL);
+
+ if (!erase)
+ return -ENOMEM;
+
+ *erase = *instr;
+ length = instr->len;
+
+ /*
+ * find the subdevice where the to-be-erased area begins, adjust
+ * starting offset to be relative to the subdevice start
+ */
+ for (i = 0; i < concat->num_subdev; i++) {
+ subdev = concat->subdev[i];
+ if (subdev->size <= erase->addr) {
+ erase->addr -= subdev->size;
+ offset += subdev->size;
+ } else {
+ break;
+ }
+ }
+
+ /* must never happen since size limit has been verified above */
+ BUG_ON(i >= concat->num_subdev);
+
+ /* now do the erase: */
+ err = 0;
+ for (; length > 0; i++) {
+ /* loop for all subdevices affected by this request */
+ subdev = concat->subdev[i]; /* get current subdevice */
+
+ /* limit length to subdevice's size: */
+ if (erase->addr + length > subdev->size)
+ erase->len = subdev->size - erase->addr;
+ else
+ erase->len = length;
+
+ length -= erase->len;
+ if ((err = concat_dev_erase(subdev, erase))) {
+ /* sanity check: should never happen since
+ * block alignment has been checked above */
+ BUG_ON(err == -EINVAL);
+ if (erase->fail_addr != 0xffffffff)
+ instr->fail_addr = erase->fail_addr + offset;
+ break;
+ }
+ /*
+ * erase->addr specifies the offset of the area to be
+ * erased *within the current subdevice*. It can be
+ * non-zero only the first time through this loop, i.e.
+ * for the first subdevice where blocks need to be erased.
+ * All the following erases must begin at the start of the
+ * current subdevice, i.e. at offset zero.
+ */
+ erase->addr = 0;
+ offset += subdev->size;
+ }
+ instr->state = erase->state;
+ kfree(erase);
+ if (err)
+ return err;
+
+ if (instr->callback)
+ instr->callback(instr);
+ return 0;
+}
+
+static int concat_lock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = mtd_lock(subdev, ofs, size);
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_unlock(struct mtd_info *mtd, loff_t ofs, size_t len)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = 0;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+ uint64_t size;
+
+ if (ofs >= subdev->size) {
+ size = 0;
+ ofs -= subdev->size;
+ continue;
+ }
+ if (ofs + len > subdev->size)
+ size = subdev->size - ofs;
+ else
+ size = len;
+
+ err = mtd_unlock(subdev, ofs, size);
+ if (err)
+ break;
+
+ len -= size;
+ if (len == 0)
+ break;
+
+ err = -EINVAL;
+ ofs = 0;
+ }
+
+ return err;
+}
+
+static int concat_block_isbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, res = 0;
+
+ if (!mtd_can_have_bb(concat->subdev[0]))
+ return res;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ res = mtd_block_isbad(subdev, ofs);
+ break;
+ }
+
+ return res;
+}
+
+static int concat_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ int i, err = -EINVAL;
+
+ for (i = 0; i < concat->num_subdev; i++) {
+ struct mtd_info *subdev = concat->subdev[i];
+
+ if (ofs >= subdev->size) {
+ ofs -= subdev->size;
+ continue;
+ }
+
+ err = mtd_block_markbad(subdev, ofs);
+ if (!err)
+ mtd->ecc_stats.badblocks++;
+ break;
+ }
+
+ return err;
+}
+
+/*
+ * This function constructs a virtual MTD device by concatenating
+ * num_devs MTD devices. A pointer to the new device object is
+ * stored to *new_dev upon success. This function does _not_
+ * register any devices: this is the caller's responsibility.
+ */
+struct mtd_info *mtd_concat_create(struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name)
+{ /* name for the new device */
+ int i;
+ size_t size;
+ struct mtd_concat *concat;
+ uint32_t max_erasesize, curr_erasesize;
+ int num_erase_region;
+ int max_writebufsize = 0;
+
+ printk(KERN_NOTICE "Concatenating MTD devices:\n");
+ for (i = 0; i < num_devs; i++)
+ printk(KERN_NOTICE "(%d): \"%s\"\n", i, subdev[i]->name);
+ printk(KERN_NOTICE "into device \"%s\"\n", name);
+
+ /* allocate the device structure */
+ size = SIZEOF_STRUCT_MTD_CONCAT(num_devs);
+ concat = kzalloc(size, GFP_KERNEL);
+ if (!concat) {
+ printk
+ ("memory allocation error while creating concatenated device \"%s\"\n",
+ name);
+ return NULL;
+ }
+ concat->subdev = (struct mtd_info **) (concat + 1);
+
+ /*
+ * Set up the new "super" device's MTD object structure, check for
+ * incompatibilities between the subdevices.
+ */
+ concat->mtd.type = subdev[0]->type;
+ concat->mtd.flags = subdev[0]->flags;
+ concat->mtd.size = subdev[0]->size;
+ concat->mtd.erasesize = subdev[0]->erasesize;
+ concat->mtd.writesize = subdev[0]->writesize;
+
+ for (i = 0; i < num_devs; i++)
+ if (max_writebufsize < subdev[i]->writebufsize)
+ max_writebufsize = subdev[i]->writebufsize;
+ concat->mtd.writebufsize = max_writebufsize;
+
+ concat->mtd.subpage_sft = subdev[0]->subpage_sft;
+ concat->mtd.oobsize = subdev[0]->oobsize;
+ concat->mtd.oobavail = subdev[0]->oobavail;
+ if (subdev[0]->read_oob)
+ concat->mtd.read_oob = concat_read_oob;
+ if (subdev[0]->write_oob)
+ concat->mtd.write_oob = concat_write_oob;
+ if (subdev[0]->block_isbad)
+ concat->mtd.block_isbad = concat_block_isbad;
+ if (subdev[0]->block_markbad)
+ concat->mtd.block_markbad = concat_block_markbad;
+
+ concat->mtd.ecc_stats.badblocks = subdev[0]->ecc_stats.badblocks;
+
+ concat->subdev[0] = subdev[0];
+
+ for (i = 1; i < num_devs; i++) {
+ if (concat->mtd.type != subdev[i]->type) {
+ kfree(concat);
+ printk("Incompatible device type on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ if (concat->mtd.flags != subdev[i]->flags) {
+ /*
+ * Expect all flags except MTD_WRITEABLE to be
+ * equal on all subdevices.
+ */
+ if ((concat->mtd.flags ^ subdev[i]->
+ flags) & ~MTD_WRITEABLE) {
+ kfree(concat);
+ printk("Incompatible device flags on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ } else
+ /* if writeable attribute differs,
+ make super device writeable */
+ concat->mtd.flags |=
+ subdev[i]->flags & MTD_WRITEABLE;
+ }
+
+ concat->mtd.size += subdev[i]->size;
+ concat->mtd.ecc_stats.badblocks +=
+ subdev[i]->ecc_stats.badblocks;
+ if (concat->mtd.writesize != subdev[i]->writesize ||
+ concat->mtd.subpage_sft != subdev[i]->subpage_sft ||
+ concat->mtd.oobsize != subdev[i]->oobsize ||
+ !concat->mtd.read_oob != !subdev[i]->read_oob ||
+ !concat->mtd.write_oob != !subdev[i]->write_oob) {
+ kfree(concat);
+ printk("Incompatible OOB or ECC data on \"%s\"\n",
+ subdev[i]->name);
+ return NULL;
+ }
+ concat->subdev[i] = subdev[i];
+
+ }
+
+ concat->mtd.ecclayout = subdev[0]->ecclayout;
+
+ concat->num_subdev = num_devs;
+ concat->mtd.name = xstrdup(name);
+
+ concat->mtd.erase = concat_erase;
+ concat->mtd.read = concat_read;
+ concat->mtd.write = concat_write;
+ concat->mtd.lock = concat_lock;
+ concat->mtd.unlock = concat_unlock;
+
+ /*
+ * Combine the erase block size info of the subdevices:
+ *
+ * first, walk the map of the new device and see how
+ * many changes in erase size we have
+ */
+ max_erasesize = curr_erasesize = subdev[0]->erasesize;
+ num_erase_region = 1;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /* if it differs from the last subdevice's erase size, count it */
+ ++num_erase_region;
+ curr_erasesize = subdev[i]->erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].erasesize !=
+ curr_erasesize) {
+ ++num_erase_region;
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ if (curr_erasesize > max_erasesize)
+ max_erasesize = curr_erasesize;
+ }
+ }
+ }
+ }
+
+ if (num_erase_region == 1) {
+ /*
+ * All subdevices have the same uniform erase size.
+ * This is easy:
+ */
+ concat->mtd.erasesize = curr_erasesize;
+ concat->mtd.numeraseregions = 0;
+ } else {
+ uint64_t tmp64;
+
+ /*
+ * erase block size varies across the subdevices: allocate
+ * space to store the data describing the variable erase regions
+ */
+ struct mtd_erase_region_info *erase_region_p;
+ uint64_t begin, position;
+
+ concat->mtd.erasesize = max_erasesize;
+ concat->mtd.numeraseregions = num_erase_region;
+ concat->mtd.eraseregions = erase_region_p =
+ kmalloc(num_erase_region *
+ sizeof (struct mtd_erase_region_info), GFP_KERNEL);
+ if (!erase_region_p) {
+ kfree(concat);
+ printk
+ ("memory allocation error while creating erase region list"
+ " for device \"%s\"\n", name);
+ return NULL;
+ }
+
+ /*
+ * walk the map of the new device once more and fill in
+ * in erase region info:
+ */
+ curr_erasesize = subdev[0]->erasesize;
+ begin = position = 0;
+ for (i = 0; i < num_devs; i++) {
+ if (subdev[i]->numeraseregions == 0) {
+ /* current subdevice has uniform erase size */
+ if (subdev[i]->erasesize != curr_erasesize) {
+ /*
+ * fill in an mtd_erase_region_info structure for the area
+ * we have walked so far:
+ */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize = subdev[i]->erasesize;
+ ++erase_region_p;
+ }
+ position += subdev[i]->size;
+ } else {
+ /* current subdevice has variable erase size */
+ int j;
+ for (j = 0; j < subdev[i]->numeraseregions; j++) {
+ /* walk the list of erase regions, count any changes */
+ if (subdev[i]->eraseregions[j].
+ erasesize != curr_erasesize) {
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize =
+ curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ begin = position;
+
+ curr_erasesize =
+ subdev[i]->eraseregions[j].
+ erasesize;
+ ++erase_region_p;
+ }
+ position +=
+ subdev[i]->eraseregions[j].
+ numblocks * (uint64_t)curr_erasesize;
+ }
+ }
+ }
+ /* Now write the final entry */
+ erase_region_p->offset = begin;
+ erase_region_p->erasesize = curr_erasesize;
+ tmp64 = position - begin;
+ do_div(tmp64, curr_erasesize);
+ erase_region_p->numblocks = tmp64;
+ }
+
+ return &concat->mtd;
+}
+
+/*
+ * This function destroys an MTD object obtained from concat_mtd_devs()
+ */
+
+void mtd_concat_destroy(struct mtd_info *mtd)
+{
+ struct mtd_concat *concat = CONCAT(mtd);
+ if (concat->mtd.numeraseregions)
+ kfree(concat->mtd.eraseregions);
+ kfree(concat);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Kaiser <rkaiser@sysgo.de>");
+MODULE_DESCRIPTION("Generic support for concatenating of MTD devices");
diff --git a/drivers/mtd/mtdoob.c b/drivers/mtd/mtdoob.c
index 10d17e90d2..6160ddba08 100644
--- a/drivers/mtd/mtdoob.c
+++ b/drivers/mtd/mtdoob.c
@@ -69,7 +69,7 @@ static struct file_operations mtd_ops_oob = {
.lseek = dev_lseek_default,
};
-static int add_mtdoob_device(struct mtd_info *mtd, char *devname, void **priv)
+static int add_mtdoob_device(struct mtd_info *mtd, const char *devname, void **priv)
{
struct mtdoob *mtdoob;
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
index c25e4062ee..ae4bec2a4c 100644
--- a/drivers/mtd/mtdraw.c
+++ b/drivers/mtd/mtdraw.c
@@ -281,7 +281,7 @@ static const struct file_operations mtd_raw_fops = {
.lseek = dev_lseek_default,
};
-static int add_mtdraw_device(struct mtd_info *mtd, char *devname, void **priv)
+static int add_mtdraw_device(struct mtd_info *mtd, const char *devname, void **priv)
{
struct mtdraw *mtdraw;
diff --git a/drivers/mtd/nor/cfi_flash.c b/drivers/mtd/nor/cfi_flash.c
index 0fa41bf67b..f2268dfde7 100644
--- a/drivers/mtd/nor/cfi_flash.c
+++ b/drivers/mtd/nor/cfi_flash.c
@@ -40,6 +40,8 @@
#include <errno.h>
#include <progress.h>
#include <linux/err.h>
+#include <asm/unaligned.h>
+#include <linux/mtd/concat.h>
#include "cfi_flash.h"
/*
@@ -58,7 +60,9 @@
*
*/
-static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
+static unsigned int flash_offset_cfi[2] = {
+ FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT
+};
/*
* Check if chip width is defined. If not, start detecting with 8bit.
@@ -72,7 +76,7 @@ static uint flash_offset_cfi[2]={FLASH_OFFSET_CFI,FLASH_OFFSET_CFI_ALT};
* Functions
*/
-static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
+static void flash_add_byte(struct flash_info *info, cfiword_t *cword, u8 c)
{
if (bankwidth_is_1(info)) {
*cword = c;
@@ -94,7 +98,7 @@ static void flash_add_byte (struct flash_info *info, cfiword_t * cword, uchar c)
#endif
}
-static int flash_write_cfiword (struct flash_info *info, ulong dest,
+static int flash_write_cfiword(struct flash_info *info, unsigned long dest,
cfiword_t cword)
{
void *dstaddr = (void *)dest;
@@ -110,34 +114,21 @@ static int flash_write_cfiword (struct flash_info *info, ulong dest,
else if (bankwidth_is_8(info))
flag = ((flash_read64(dstaddr) & cword) == cword);
else
- return 2;
+ return -EIO;
if (!flag)
- return 2;
+ return -EIO;
info->cfi_cmd_set->flash_prepare_write(info);
flash_write_word(info, cword, (void *)dest);
- return flash_status_check (info, find_sector (info, dest),
+ return flash_status_check(info, find_sector (info, dest),
info->write_tout, "write");
}
#ifdef DEBUG
-/*
- * Debug support
- */
-void print_longlong (char *str, unsigned long long data)
-{
- int i;
- char *cp;
-
- cp = (unsigned char *) &data;
- for (i = 0; i < 8; i++)
- sprintf (&str[i * 2], "%2.2x", *cp++);
-}
-
-static void flash_printqry (struct cfi_qry *qry)
+static void flash_printqry(struct cfi_qry *qry)
{
u8 *p = (u8 *)qry;
int x, y;
@@ -163,9 +154,9 @@ static void flash_printqry (struct cfi_qry *qry)
/*
* read a character at a port width address
*/
-uchar flash_read_uchar (struct flash_info *info, uint offset)
+u8 flash_read_uchar(struct flash_info *info, unsigned int offset)
{
- uchar *cp = flash_make_addr(info, 0, offset);
+ u8 *cp = flash_make_addr(info, 0, offset);
#if defined __LITTLE_ENDIAN
return flash_read8(cp);
#else
@@ -177,23 +168,20 @@ uchar flash_read_uchar (struct flash_info *info, uint offset)
* read a long word by picking the least significant byte of each maximum
* port size word. Swap for ppc format.
*/
-static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint offset)
+static unsigned long flash_read_long(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset)
{
- uchar *addr;
- ulong retval;
-
-#ifdef DEBUG
+ u8 *addr;
+ unsigned long retval;
int x;
-#endif
+
addr = flash_make_addr (info, sect, offset);
-#ifdef DEBUG
dev_dbg(info->dev, "long addr is at %p info->portwidth = %d\n", addr,
info->portwidth);
- for (x = 0; x < 4 * info->portwidth; x++) {
+ for (x = 0; x < 4 * info->portwidth; x++)
dev_dbg(info->dev, "addr[%x] = 0x%x\n", x, flash_read8(addr + x));
- }
-#endif
+
#if defined __LITTLE_ENDIAN
retval = ((flash_read8(addr) << 16) |
(flash_read8(addr + info->portwidth) << 24) |
@@ -216,14 +204,14 @@ static ulong flash_read_long (struct flash_info *info, flash_sect_t sect, uint o
u32 jedec_read_mfr(struct flash_info *info)
{
int bank = 0;
- uchar mfr;
+ u8 mfr;
/* According to JEDEC "Standard Manufacturer's Identification Code"
* (http://www.jedec.org/download/search/jep106W.pdf)
* several first banks can contain 0x7f instead of actual ID
*/
do {
- mfr = flash_read_uchar (info,
+ mfr = flash_read_uchar(info,
(bank << 8) | FLASH_OFFSET_MANUFACTURER_ID);
bank++;
} while (mfr == FLASH_ID_CONTINUATION);
@@ -231,7 +219,7 @@ u32 jedec_read_mfr(struct flash_info *info)
return mfr;
}
-static void flash_read_cfi (struct flash_info *info, void *buf,
+static void flash_read_cfi(struct flash_info *info, void *buf,
unsigned int start, size_t len)
{
u8 *p = buf;
@@ -241,45 +229,53 @@ static void flash_read_cfi (struct flash_info *info, void *buf,
p[i] = flash_read_uchar(info, start + i);
}
-static int flash_detect_width (struct flash_info *info, struct cfi_qry *qry)
+static int flash_detect_width(struct flash_info *info, struct cfi_qry *qry)
{
int cfi_offset;
+ int pw, cw;
+
+ for (pw = CFG_FLASH_CFI_WIDTH; pw <= FLASH_CFI_64BIT; pw <<= 1) {
+ for (cw = FLASH_CFI_BY8; cw <= pw; cw <<= 1) {
+ info->chipwidth = cw;
+ info->portwidth = pw;
+
+ flash_write_cmd(info, 0, 0, AMD_CMD_RESET);
+ flash_write_cmd(info, 0, 0, FLASH_CMD_RESET);
+ for (cfi_offset = 0;
+ cfi_offset < sizeof(flash_offset_cfi) / sizeof(unsigned int);
+ cfi_offset++) {
- for (info->portwidth = CFG_FLASH_CFI_WIDTH;
- info->portwidth <= FLASH_CFI_64BIT; info->portwidth <<= 1) {
- for (info->chipwidth = FLASH_CFI_BY8;
- info->chipwidth <= info->portwidth;
- info->chipwidth <<= 1) {
- flash_write_cmd (info, 0, 0, AMD_CMD_RESET);
- flash_write_cmd (info, 0, 0, FLASH_CMD_RESET);
- for (cfi_offset=0; cfi_offset < sizeof(flash_offset_cfi)/sizeof(uint); cfi_offset++) {
- flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
- if (flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')
- && flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y')) {
- flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
- sizeof(struct cfi_qry));
- info->interface = le16_to_cpu(qry->interface_desc);
-
- info->cfi_offset=flash_offset_cfi[cfi_offset];
- dev_dbg(info->dev, "device interface is %d\n",
- info->interface);
- dev_dbg(info->dev, "found port %d chip %d chip_lsb %d ",
- info->portwidth, info->chipwidth, info->chip_lsb);
- dev_dbg(info->dev, "port %d bits chip %d bits\n",
- info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- return 1;
- }
+ flash_write_cmd(info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);
+
+ if (flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP, 'Q') &&
+ flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R') &&
+ flash_isequal(info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y'))
+ goto found;
}
}
}
- dev_dbg(info->dev, "not found\n");
+
+ dev_dbg(info->dev, "no flash found\n");
+
+ return -ENODEV;
+
+found:
+ flash_read_cfi(info, qry, FLASH_OFFSET_CFI_RESP,
+ sizeof(struct cfi_qry));
+ info->interface = get_unaligned_le16(&qry->interface_desc);
+ info->cfi_offset = flash_offset_cfi[cfi_offset];
+ dev_dbg(info->dev, "device interface is %d\n", info->interface);
+ dev_dbg(info->dev, "found port %d chip %d chip_lsb %d ",
+ info->portwidth, info->chipwidth, info->chip_lsb);
+ dev_dbg(info->dev, "port %d bits chip %d bits\n",
+ info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+
return 0;
}
-static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry)
+static int flash_detect_cfi(struct flash_info *info, struct cfi_qry *qry)
{
int ret;
@@ -287,180 +283,184 @@ static int flash_detect_cfi (struct flash_info *info, struct cfi_qry *qry)
info->chip_lsb = 0;
ret = flash_detect_width (info, qry);
- if (!ret) {
- info->chip_lsb = 1;
- ret = flash_detect_width (info, qry);
- }
- return ret;
+ if (!ret)
+ return 0;
+
+ info->chip_lsb = 1;
+ return flash_detect_width (info, qry);
}
/*
* The following code cannot be run from FLASH!
*/
-static ulong flash_get_size (struct flash_info *info)
+static int flash_detect_size(struct flash_info *info)
{
- int i, j;
+ int i, j, ret;
flash_sect_t sect_cnt;
unsigned long sector;
unsigned long tmp;
int size_ratio;
- uchar num_erase_regions;
+ int num_erase_regions;
int erase_region_size;
int erase_region_count;
int cur_offset = 0;
- struct cfi_qry qry;
+ struct cfi_qry qry = {};
unsigned long base = (unsigned long)info->base;
- memset(&qry, 0, sizeof(qry));
-
info->ext_addr = 0;
info->cfi_version = 0;
-#ifdef CFG_FLASH_PROTECTION
- info->legacy_unlock = 0;
-#endif
/* first only malloc space for the first sector */
- info->start = xmalloc(sizeof(ulong));
+ info->start = xmalloc(sizeof(*info->eraseregions));
info->start[0] = base;
info->protect = 0;
- if (flash_detect_cfi (info, &qry)) {
- info->vendor = le16_to_cpu(qry.p_id);
- info->ext_addr = le16_to_cpu(qry.p_adr);
- num_erase_regions = qry.num_erase_regions;
+ ret = flash_detect_cfi(info, &qry);
+ if (ret)
+ return ret;
- if (info->ext_addr) {
- info->cfi_version = (ushort) flash_read_uchar (info,
- info->ext_addr + 3) << 8;
- info->cfi_version |= (ushort) flash_read_uchar (info,
- info->ext_addr + 4);
- }
+ info->vendor = get_unaligned_le16(&qry.p_id);
+ info->ext_addr = get_unaligned_le16(&qry.p_adr);
+ num_erase_regions = qry.num_erase_regions;
+
+ if (info->ext_addr) {
+ info->cfi_version = (u16)flash_read_uchar (info,
+ info->ext_addr + 3) << 8;
+ info->cfi_version |= (u16)flash_read_uchar (info,
+ info->ext_addr + 4);
+ }
#ifdef DEBUG
- flash_printqry (&qry);
+ flash_printqry(&qry);
#endif
- switch (info->vendor) {
-#ifdef CONFIG_DRIVER_CFI_INTEL
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ if (IS_ENABLED(CONFIG_DRIVER_CFI_INTEL))
info->cfi_cmd_set = &cfi_cmd_set_intel;
- break;
-#endif
-#ifdef CONFIG_DRIVER_CFI_AMD
- case CFI_CMDSET_AMD_STANDARD:
- case CFI_CMDSET_AMD_EXTENDED:
+ break;
+ case CFI_CMDSET_AMD_STANDARD:
+ case CFI_CMDSET_AMD_EXTENDED:
+ if (IS_ENABLED(CONFIG_DRIVER_CFI_AMD))
info->cfi_cmd_set = &cfi_cmd_set_amd;
+ break;
+ }
+
+ if (!info->cfi_cmd_set) {
+ dev_err(info->dev, "unsupported vendor 0x%04x\n", info->vendor);
+ return -ENOSYS;
+ }
+
+ info->cfi_cmd_set->flash_read_jedec_ids (info);
+ flash_write_cmd(info, 0, info->cfi_offset, FLASH_CMD_CFI);
+
+ info->cfi_cmd_set->flash_fixup (info, &qry);
+
+ dev_dbg(info->dev, "manufacturer is %d\n", info->vendor);
+ dev_dbg(info->dev, "manufacturer id is 0x%x\n", info->manufacturer_id);
+ dev_dbg(info->dev, "device id is 0x%x\n", info->device_id);
+ dev_dbg(info->dev, "device id2 is 0x%x\n", info->device_id2);
+ dev_dbg(info->dev, "cfi version is 0x%04x\n", info->cfi_version);
+
+ size_ratio = info->portwidth / info->chipwidth;
+
+ /* if the chip is x8/x16 reduce the ratio by half */
+ if ((info->interface == FLASH_CFI_X8X16)
+ && (info->chipwidth == FLASH_CFI_BY8)
+ && (size_ratio != 1)) {
+ size_ratio >>= 1;
+ }
+
+ dev_dbg(info->dev, "size_ratio %d port %d bits chip %d bits\n",
+ size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
+ info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
+ dev_dbg(info->dev, "found %d erase regions\n", num_erase_regions);
+
+ info->eraseregions = xzalloc(sizeof(*info->eraseregions) * num_erase_regions);
+ info->numeraseregions = num_erase_regions;
+ sect_cnt = 0;
+ sector = base;
+
+ for (i = 0; i < num_erase_regions; i++) {
+ struct mtd_erase_region_info *region = &info->eraseregions[i];
+
+ if (i > NUM_ERASE_REGIONS) {
+ dev_info(info->dev, "%d erase regions found, only %d used\n",
+ num_erase_regions, NUM_ERASE_REGIONS);
break;
-#endif
- default:
- dev_err(info->dev, "unsupported vendor\n");
- return 0;
}
- info->cfi_cmd_set->flash_read_jedec_ids (info);
- flash_write_cmd (info, 0, info->cfi_offset, FLASH_CMD_CFI);
-
- info->cfi_cmd_set->flash_fixup (info, &qry);
-
- dev_dbg(info->dev, "manufacturer is %d\n", info->vendor);
- dev_dbg(info->dev, "manufacturer id is 0x%x\n", info->manufacturer_id);
- dev_dbg(info->dev, "device id is 0x%x\n", info->device_id);
- dev_dbg(info->dev, "device id2 is 0x%x\n", info->device_id2);
- dev_dbg(info->dev, "cfi version is 0x%04x\n", info->cfi_version);
-
- size_ratio = info->portwidth / info->chipwidth;
- /* if the chip is x8/x16 reduce the ratio by half */
- if ((info->interface == FLASH_CFI_X8X16)
- && (info->chipwidth == FLASH_CFI_BY8)
- && (size_ratio != 1)) {
- size_ratio >>= 1;
- }
- dev_dbg(info->dev, "size_ratio %d port %d bits chip %d bits\n",
- size_ratio, info->portwidth << CFI_FLASH_SHIFT_WIDTH,
- info->chipwidth << CFI_FLASH_SHIFT_WIDTH);
- dev_dbg(info->dev, "found %d erase regions\n", num_erase_regions);
- info->eraseregions = xzalloc(sizeof(*(info->eraseregions)) * num_erase_regions);
- info->numeraseregions = num_erase_regions;
- sect_cnt = 0;
- sector = base;
-
- for (i = 0; i < num_erase_regions; i++) {
- struct mtd_erase_region_info *region = &info->eraseregions[i];
-
- if (i > NUM_ERASE_REGIONS) {
- dev_info(info->dev, "%d erase regions found, only %d used\n",
- num_erase_regions, NUM_ERASE_REGIONS);
- break;
- }
- tmp = le32_to_cpu(qry.erase_region_info[i]);
- dev_dbg(info->dev, "erase region %u: 0x%08lx\n", i, tmp);
-
- erase_region_count = (tmp & 0xffff) + 1;
- tmp >>= 16;
- erase_region_size =
- (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
- dev_dbg(info->dev, "erase_region_count = %d erase_region_size = %d\n",
- erase_region_count, erase_region_size);
-
- region->offset = cur_offset;
- region->erasesize = erase_region_size * size_ratio;
- region->numblocks = erase_region_count;
- cur_offset += erase_region_size * size_ratio * erase_region_count;
-
- /* increase the space malloced for the sector start addresses */
- info->start = xrealloc(info->start, sizeof(ulong) * (erase_region_count + sect_cnt));
- info->protect = xrealloc(info->protect, sizeof(uchar) * (erase_region_count + sect_cnt));
-
- for (j = 0; j < erase_region_count; j++) {
- info->start[sect_cnt] = sector;
- sector += (erase_region_size * size_ratio);
-
- /*
- * Only read protection status from supported devices (intel...)
- */
- switch (info->vendor) {
- case CFI_CMDSET_INTEL_EXTENDED:
- case CFI_CMDSET_INTEL_STANDARD:
- info->protect[sect_cnt] =
- flash_isset (info, sect_cnt,
- FLASH_OFFSET_PROTECT,
- FLASH_STATUS_PROTECT);
- break;
- default:
- info->protect[sect_cnt] = 0; /* default: not protected */
- }
-
- sect_cnt++;
+ tmp = get_unaligned_le32(&qry.erase_region_info[i]);
+ dev_dbg(info->dev, "erase region %u: 0x%08lx\n", i, tmp);
+
+ erase_region_count = (tmp & 0xffff) + 1;
+ tmp >>= 16;
+ erase_region_size =
+ (tmp & 0xffff) ? ((tmp & 0xffff) * 256) : 128;
+ dev_dbg(info->dev, "erase_region_count = %d erase_region_size = %d\n",
+ erase_region_count, erase_region_size);
+
+ region->offset = cur_offset;
+ region->erasesize = erase_region_size * size_ratio;
+ region->numblocks = erase_region_count;
+ cur_offset += erase_region_size * size_ratio * erase_region_count;
+
+ /* increase the space malloced for the sector start addresses */
+ info->start = xrealloc(info->start, sizeof(*info->eraseregions) *
+ (erase_region_count + sect_cnt));
+ info->protect = xrealloc(info->protect, sizeof(*info->eraseregions) *
+ (erase_region_count + sect_cnt));
+
+ for (j = 0; j < erase_region_count; j++) {
+ info->start[sect_cnt] = sector;
+ sector += (erase_region_size * size_ratio);
+
+ /*
+ * Only read protection status from supported devices (intel...)
+ */
+ switch (info->vendor) {
+ case CFI_CMDSET_INTEL_EXTENDED:
+ case CFI_CMDSET_INTEL_STANDARD:
+ info->protect[sect_cnt] =
+ flash_isset (info, sect_cnt,
+ FLASH_OFFSET_PROTECT,
+ FLASH_STATUS_PROTECT);
+ break;
+ default:
+ info->protect[sect_cnt] = 0; /* default: not protected */
}
- }
- info->sector_count = sect_cnt;
- /* multiply the size by the number of chips */
- info->size = (1 << qry.dev_size) * size_ratio;
- info->buffer_size = (1 << le16_to_cpu(qry.max_buf_write_size));
- info->erase_blk_tout = 1 << (qry.block_erase_timeout_typ +
- qry.block_erase_timeout_max);
- info->buffer_write_tout = 1 << (qry.buf_write_timeout_typ +
- qry.buf_write_timeout_max);
- info->write_tout = 1 << (qry.word_write_timeout_typ +
- qry.word_write_timeout_max);
- info->flash_id = FLASH_MAN_CFI;
- if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8)) {
- info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
+ sect_cnt++;
}
- flash_write_cmd (info, 0, 0, info->cmd_reset);
}
- return info->size;
+ info->sector_count = sect_cnt;
+ /* multiply the size by the number of chips */
+ info->size = (1 << qry.dev_size) * size_ratio;
+ info->buffer_size = (1 << get_unaligned_le16(&qry.max_buf_write_size));
+ info->erase_blk_tout = 1 << (qry.block_erase_timeout_typ +
+ qry.block_erase_timeout_max);
+ info->buffer_write_tout = 1 << (qry.buf_write_timeout_typ +
+ qry.buf_write_timeout_max);
+ info->write_tout = 1 << (qry.word_write_timeout_typ +
+ qry.word_write_timeout_max);
+ info->flash_id = FLASH_MAN_CFI;
+
+ if ((info->interface == FLASH_CFI_X8X16) && (info->chipwidth == FLASH_CFI_BY8))
+ info->portwidth >>= 1; /* XXX - Need to test on x8/x16 in parallel. */
+
+ flash_write_cmd(info, 0, 0, info->cmd_reset);
+
+ return 0;
}
/* loop through the sectors from the highest address
* when the passed address is greater or equal to the sector address
* we have a match
*/
-flash_sect_t find_sector (struct flash_info *info, ulong addr)
+flash_sect_t find_sector(struct flash_info *info, unsigned long addr)
{
flash_sect_t sector;
@@ -468,6 +468,7 @@ flash_sect_t find_sector (struct flash_info *info, ulong addr)
if (addr >= info->start[sector])
break;
}
+
return sector;
}
@@ -496,43 +497,40 @@ out:
return ret;
}
-/*
- * Copy memory to flash, returns:
- * 0 - OK
- * 1 - write timeout
- * 2 - Flash not erased
- */
-static int write_buff (struct flash_info *info, const uchar * src, ulong addr, ulong cnt)
+static int write_buff(struct flash_info *info, const u8 *src,
+ unsigned long addr, unsigned long cnt)
{
- ulong wp;
- uchar *p;
+ unsigned long wp;
+ u8 *p;
int aln;
cfiword_t cword;
- int i, rc;
+ int i, ret;
#ifdef CONFIG_CFI_BUFFER_WRITE
int buffered_size;
#endif
/* get lower aligned address */
- wp = (addr & ~(info->portwidth - 1));
+ wp = addr & ~(info->portwidth - 1);
/* handle unaligned start */
- if ((aln = addr - wp) != 0) {
+ aln = addr - wp;
+ if (aln) {
cword = 0;
- p = (uchar*)wp;
+ p = (u8 *)wp;
for (i = 0; i < aln; ++i)
- flash_add_byte (info, &cword, flash_read8(p + i));
+ flash_add_byte(info, &cword, flash_read8(p + i));
for (; (i < info->portwidth) && (cnt > 0); i++) {
- flash_add_byte (info, &cword, *src++);
+ flash_add_byte(info, &cword, *src++);
cnt--;
}
+
for (; (cnt == 0) && (i < info->portwidth); ++i)
- flash_add_byte (info, &cword, flash_read8(p + i));
+ flash_add_byte(info, &cword, flash_read8(p + i));
- rc = flash_write_cfiword (info, wp, cword);
- if (rc != 0)
- return rc;
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
wp += i;
}
@@ -545,12 +543,17 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
/* prohibit buffer write when buffer_size is 1 */
if (info->buffer_size == 1) {
cword = 0;
+
for (i = 0; i < info->portwidth; i++)
- flash_add_byte (info, &cword, *src++);
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
+ flash_add_byte(info, &cword, *src++);
+
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
+
wp += info->portwidth;
cnt -= info->portwidth;
+
continue;
}
@@ -558,8 +561,11 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
i = buffered_size - (wp % buffered_size);
if (i > cnt)
i = cnt;
- if ((rc = info->cfi_cmd_set->flash_write_cfibuffer (info, wp, src, i)) != ERR_OK)
- return rc;
+
+ ret = info->cfi_cmd_set->flash_write_cfibuffer(info, wp, src, i);
+ if (ret)
+ return ret;
+
i -= i & (info->portwidth - 1);
wp += i;
src += i;
@@ -568,64 +574,67 @@ static int write_buff (struct flash_info *info, const uchar * src, ulong addr, u
#else
while (cnt >= info->portwidth) {
cword = 0;
- for (i = 0; i < info->portwidth; i++) {
- flash_add_byte (info, &cword, *src++);
- }
- if ((rc = flash_write_cfiword (info, wp, cword)) != 0)
- return rc;
+
+ for (i = 0; i < info->portwidth; i++)
+ flash_add_byte(info, &cword, *src++);
+
+ ret = flash_write_cfiword(info, wp, cword);
+ if (ret)
+ return ret;
+
wp += info->portwidth;
cnt -= info->portwidth;
}
#endif /* CONFIG_CFI_BUFFER_WRITE */
- if (cnt == 0) {
+ if (cnt == 0)
return 0;
- }
/*
* handle unaligned tail bytes
*/
cword = 0;
- p = (uchar*)wp;
+ p = (u8 *)wp;
+
for (i = 0; (i < info->portwidth) && (cnt > 0); ++i) {
- flash_add_byte (info, &cword, *src++);
+ flash_add_byte(info, &cword, *src++);
--cnt;
}
- for (; i < info->portwidth; ++i) {
- flash_add_byte (info, &cword, flash_read8(p + i));
- }
- return flash_write_cfiword (info, wp, cword);
+ for (; i < info->portwidth; ++i)
+ flash_add_byte(info, &cword, flash_read8(p + i));
+
+ return flash_write_cfiword(info, wp, cword);
}
-static int flash_real_protect (struct flash_info *info, long sector, int prot)
+static int flash_real_protect(struct flash_info *info, long sector, int prot)
{
- int retcode = 0;
-
- retcode = info->cfi_cmd_set->flash_real_protect(info, sector, prot);
+ int ret;
- if (retcode)
- return retcode;
+ ret = info->cfi_cmd_set->flash_real_protect(info, sector, prot);
+ if (ret)
+ return ret;
- if ((retcode =
- flash_status_check (info, sector, info->erase_blk_tout,
- prot ? "protect" : "unprotect")) == 0) {
+ ret = flash_status_check(info, sector, info->erase_blk_tout,
+ prot ? "protect" : "unprotect");
+ if (ret)
+ return ret;
- info->protect[sector] = prot;
+ info->protect[sector] = prot;
- /*
- * On some of Intel's flash chips (marked via legacy_unlock)
- * unprotect unprotects all locking.
- */
- if ((prot == 0) && (info->legacy_unlock)) {
- flash_sect_t i;
+ /*
+ * On some of Intel's flash chips (marked via legacy_unlock)
+ * unprotect unprotects all locking.
+ */
+ if (prot == 0 && info->legacy_unlock) {
+ flash_sect_t i;
- for (i = 0; i < info->sector_count; i++) {
- if (info->protect[i])
- flash_real_protect (info, i, 1);
- }
+ for (i = 0; i < info->sector_count; i++) {
+ if (info->protect[i])
+ flash_real_protect (info, i, 1);
}
}
- return retcode;
+
+ return 0;
}
static int cfi_mtd_protect(struct flash_info *finfo, loff_t offset, size_t len, int prot)
@@ -637,12 +646,12 @@ static int cfi_mtd_protect(struct flash_info *finfo, loff_t offset, size_t len,
end = find_sector(finfo, (unsigned long)finfo->base + offset + len - 1);
for (i = start; i <= end; i++) {
- ret = flash_real_protect (finfo, i, prot);
+ ret = flash_real_protect(finfo, i, prot);
if (ret)
- goto out;
+ return ret;
}
-out:
- return ret;
+
+ return 0;
}
static int cfi_mtd_lock(struct mtd_info *mtd, loff_t offset, size_t len)
@@ -665,50 +674,53 @@ static void cfi_info (struct device_d* dev)
int i;
if (info->flash_id != FLASH_MAN_CFI) {
- puts ("missing or unknown FLASH type\n");
+ printf("missing or unknown FLASH type\n");
return;
}
- printf ("CFI conformant FLASH (%d x %d)",
+ printf("CFI conformant FLASH (%d x %d)",
(info->portwidth << 3), (info->chipwidth << 3));
- printf (" Size: %ld MB in %d Sectors\n",
+ printf(" Size: %ld MB in %d Sectors\n ",
info->size >> 20, info->sector_count);
- printf (" ");
+
switch (info->vendor) {
case CFI_CMDSET_INTEL_STANDARD:
- printf ("Intel Standard");
+ printf("Intel Standard");
break;
case CFI_CMDSET_INTEL_EXTENDED:
- printf ("Intel Extended");
+ printf("Intel Extended");
break;
case CFI_CMDSET_AMD_STANDARD:
- printf ("AMD Standard");
+ printf("AMD Standard");
break;
case CFI_CMDSET_AMD_EXTENDED:
- printf ("AMD Extended");
+ printf("AMD Extended");
break;
default:
- printf ("Unknown (%d)", info->vendor);
+ printf("Unknown (%d)", info->vendor);
break;
}
- printf (" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
+ printf(" command set, Manufacturer ID: 0x%02X, Device ID: 0x%02X",
info->manufacturer_id, info->device_id);
- if (info->device_id == 0x7E) {
+
+ if (info->device_id == 0x7E)
printf("%04X", info->device_id2);
- }
- printf ("\n Erase timeout: %ld ms, write timeout: %ld us\n",
+
+ printf("\n Erase timeout: %ld ms, write timeout: %ld us\n",
info->erase_blk_tout,
info->write_tout);
+
if (info->buffer_size > 1) {
- printf (" Buffer write timeout: %ld us, buffer size: %d bytes\n",
+ printf(" Buffer write timeout: %ld us, buffer size: %d bytes\n",
info->buffer_write_tout,
info->buffer_size);
}
- puts ("\n Sector Start Addresses:");
+ printf("\n Sector Start Addresses:");
+
for (i = 0; i < info->sector_count; ++i) {
if ((i % 5) == 0)
- printf ("\n");
+ printf("\n");
#ifdef CFG_FLASH_EMPTY_INFO
{
int k;
@@ -724,7 +736,7 @@ static void cfi_info (struct device_d* dev)
else
size = info->start[0] + info->size - info->start[i];
erased = 1;
- flash = (volatile unsigned long *) info->start[i];
+ flash = (volatile unsigned long *)info->start[i];
size = size >> 2; /* divide by 4 for longword access */
for (k = 0; k < size; k++) {
if (*flash++ != 0xffffffff) {
@@ -734,13 +746,13 @@ static void cfi_info (struct device_d* dev)
}
/* print empty and read-only info */
- printf (" %08lX %c %s ",
+ printf(" %08lX %c %s ",
info->start[i],
erased ? 'E' : ' ',
info->protect[i] ? "RO" : " ");
}
#else /* ! CFG_FLASH_EMPTY_INFO */
- printf (" %08lX %s ",
+ printf(" %08lX %s ",
info->start[i],
info->protect[i] ? "RO" : " ");
#endif
@@ -749,41 +761,8 @@ static void cfi_info (struct device_d* dev)
return;
}
-#if 0
-/*
- * flash_read_user_serial - read the OneTimeProgramming cells
- */
-static void flash_read_user_serial (struct flash_info *info, void *buffer, int offset,
- int len)
-{
- uchar *src;
- uchar *dst;
-
- dst = buffer;
- src = flash_make_addr (info, 0, FLASH_OFFSET_USER_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (dst, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-/*
- * flash_read_factory_serial - read the device Id from the protection area
- */
-static void flash_read_factory_serial (struct flash_info *info, void *buffer, int offset,
- int len)
-{
- uchar *src;
-
- src = flash_make_addr (info, 0, FLASH_OFFSET_INTEL_PROTECTION);
- flash_write_cmd (info, 0, 0, FLASH_CMD_READ_ID);
- memcpy (buffer, src + offset, len);
- flash_write_cmd (info, 0, 0, info->cmd_reset);
-}
-
-#endif
-
-int flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+int flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
return info->cfi_cmd_set->flash_status_check(info, sector, tout, prompt);
}
@@ -792,10 +771,10 @@ int flash_status_check (struct flash_info *info, flash_sect_t sector,
* wait for XSR.7 to be set. Time out with an error if it does not.
* This routine does not set the flash to read-array mode.
*/
-int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+int flash_generic_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
- uint64_t start;
+ u64 start;
tout *= 1000000;
@@ -806,12 +785,15 @@ int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
dev_err(info->dev, "Flash %s timeout at address %lx data %lx\n",
prompt, info->start[sector],
flash_read_long (info, sector, 0));
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return ERR_TIMOUT;
+
+ flash_write_cmd(info, sector, 0, info->cmd_reset);
+
+ return -ETIMEDOUT;
}
- udelay (1); /* also triggers watchdog */
+ udelay(1); /* also triggers watchdog */
}
- return ERR_OK;
+
+ return 0;
}
/*
@@ -831,23 +813,22 @@ void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf)
* Write a proper sized command to the correct address
*/
void flash_write_cmd(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
-
- uchar *addr;
+ u8 *addr;
cfiword_t cword;
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
- dev_dbg(info->dev, "%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__,
+ dev_vdbg(info->dev, "%s: %p %lX %X => %p " CFI_WORD_FMT "\n", __func__,
info, sect, offset, addr, cword);
flash_write_word(info, cword, addr);
}
int flash_isequal(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
void *addr;
cfiword_t cword;
@@ -856,36 +837,29 @@ int flash_isequal(struct flash_info *info, flash_sect_t sect,
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
- dev_dbg(info->dev, "is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+ dev_vdbg(info->dev, "is= cmd %x(%c) addr %p ", cmd, cmd, addr);
+
if (bankwidth_is_1(info)) {
- dev_dbg(info->dev, "is= %x %x\n", flash_read8(addr), (u8)cword);
+ dev_vdbg(info->dev, "is= %x %x\n", flash_read8(addr), (u8)cword);
retval = (flash_read8(addr) == cword);
} else if (bankwidth_is_2(info)) {
- dev_dbg(info->dev, "is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword);
+ dev_vdbg(info->dev, "is= %4.4x %4.4x\n", flash_read16(addr), (u16)cword);
retval = (flash_read16(addr) == cword);
} else if (bankwidth_is_4(info)) {
- dev_dbg(info->dev, "is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword);
+ dev_vdbg(info->dev, "is= %8.8x %8.8x\n", flash_read32(addr), (u32)cword);
retval = (flash_read32(addr) == cword);
} else if (bankwidth_is_8(info)) {
-#ifdef DEBUG
- {
- char str1[20];
- char str2[20];
-
- print_longlong (str1, flash_read32(addr));
- print_longlong (str2, cword);
- dev_dbg(info->dev, "is= %s %s\n", str1, str2);
- }
-#endif
+ dev_vdbg(info->dev, "is= %16.16llx %16.16llx\n", flash_read64(addr), (u64)cword);
retval = (flash_read64(addr) == cword);
- } else
+ } else {
retval = 0;
+ }
return retval;
}
int flash_isset(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd)
+ unsigned int offset, u32 cmd)
{
void *addr = flash_make_addr (info, sect, offset);
cfiword_t cword;
@@ -900,14 +874,15 @@ int flash_isset(struct flash_info *info, flash_sect_t sect,
retval = ((flash_read32(addr) & cword) == cword);
} else if (bankwidth_is_8(info)) {
retval = ((flash_read64(addr) & cword) == cword);
- } else
+ } else {
retval = 0;
+ }
return retval;
}
static int cfi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
- size_t *retlen, u_char *buf)
+ size_t *retlen, u8 *buf)
{
struct flash_info *info = container_of(mtd, struct flash_info, mtd);
@@ -918,7 +893,7 @@ static int cfi_mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
}
static int cfi_mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
- size_t *retlen, const u_char *buf)
+ size_t *retlen, const u8 *buf)
{
struct flash_info *info = container_of(mtd, struct flash_info, mtd);
int ret;
@@ -935,7 +910,6 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
int ret;
ret = cfi_erase(info, instr->len, instr->addr);
-
if (ret) {
instr->state = MTD_ERASE_FAILED;
return -EIO;
@@ -947,10 +921,16 @@ static int cfi_mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
return 0;
}
+struct cfi_priv {
+ struct flash_info *infos;
+ int num_devs;
+ struct mtd_info **mtds;
+};
+
static void cfi_init_mtd(struct flash_info *info)
{
struct mtd_info *mtd = &info->mtd;
- u_int32_t erasesize;
+ u32 erasesize;
int i;
mtd->read = cfi_mtd_read;
@@ -961,10 +941,11 @@ static void cfi_init_mtd(struct flash_info *info)
mtd->size = info->size;
erasesize = 0;
- for (i=0; i < info->numeraseregions; i++) {
+ for (i = 0; i < info->numeraseregions; i++) {
if (erasesize < info->eraseregions[i].erasesize)
erasesize = info->eraseregions[i].erasesize;
}
+
mtd->erasesize = erasesize;
mtd->writesize = 1;
@@ -974,38 +955,84 @@ static void cfi_init_mtd(struct flash_info *info)
mtd->flags = MTD_CAP_NORFLASH;
mtd->type = MTD_NORFLASH;
mtd->parent = info->dev;
-
- add_mtd_device(mtd, "nor", DEVICE_ID_DYNAMIC);
}
-static int cfi_probe (struct device_d *dev)
+static int cfi_probe_one(struct flash_info *info, int num)
{
- struct flash_info *info = xzalloc(sizeof(*info));
-
- dev->priv = (void *)info;
+ int ret;
- /* Init: no FLASHes known */
info->flash_id = FLASH_UNKNOWN;
info->cmd_reset = FLASH_CMD_RESET;
- info->base = dev_request_mem_region(dev, 0);
+ info->base = dev_request_mem_region(info->dev, num);
if (IS_ERR(info->base))
return PTR_ERR(info->base);
- info->dev = dev;
- info->size = flash_get_size(info);
-
- if (info->flash_id == FLASH_UNKNOWN) {
- dev_warn(dev, "## Unknown FLASH on Bank at 0x%08x - Size = 0x%08lx = %ld MB\n",
- dev->resource[0].start, info->size, info->size << 20);
+ ret = flash_detect_size(info);
+ if (ret) {
+ dev_warn(info->dev, "## Unknown FLASH on Bank at 0x%p - Size = 0x%08lx = %ld MB\n",
+ info->base, info->size, info->size << 20);
return -ENODEV;
}
- dev_info(dev, "found cfi flash at 0x%p, size %s\n",
+ dev_info(info->dev, "found cfi flash at 0x%p, size %s\n",
info->base, size_human_readable(info->size));
+ cfi_init_mtd(info);
+
+ return 0;
+}
+
+static int cfi_probe(struct device_d *dev)
+{
+ struct cfi_priv *priv;
+ int i, ret;
+ struct mtd_info *mtd;
+ const char *mtd_name = NULL;
+
+ priv = xzalloc(sizeof(*priv));
+
+ priv->num_devs = dev->num_resources;
+ priv->infos = xzalloc(sizeof(*priv->infos) * priv->num_devs);
+ priv->mtds = xzalloc(sizeof(*priv->mtds) * priv->num_devs);
+
+ of_property_read_string(dev->device_node, "linux,mtd-name", &mtd_name);
+
+ if (!mtd_name)
+ mtd_name = dev_name(dev);
+
+ dev->priv = priv;
+
+ for (i = 0; i < priv->num_devs; i++) {
+ struct flash_info *info = &priv->infos[i];
+
+ info->dev = dev;
+ info->mtd.name = xstrdup(mtd_name);
+
+ ret = cfi_probe_one(info, i);
+ if (ret)
+ return ret;
+ priv->mtds[i] = &priv->infos[i].mtd;
+ }
+
dev->info = cfi_info;
- cfi_init_mtd(info);
+ if (priv->num_devs > 1 && IS_ENABLED(CONFIG_MTD_CONCAT)) {
+ mtd = mtd_concat_create(priv->mtds, priv->num_devs, "nor");
+ if (!mtd) {
+ dev_err(dev, "failed to create concat mtd device\n");
+ return -ENODEV;
+ }
+ } else {
+ if (priv->num_devs > 1)
+ dev_warn(dev, "mtd concat disabled. using first chip only\n");
+ mtd = &priv->infos[0].mtd;
+ }
+
+ mtd->parent = dev;
+
+ ret = add_mtd_device(mtd, "nor", DEVICE_ID_DYNAMIC);
+ if (ret)
+ return ret;
return 0;
}
diff --git a/drivers/mtd/nor/cfi_flash.h b/drivers/mtd/nor/cfi_flash.h
index aeaf751aba..e82eb28abe 100644
--- a/drivers/mtd/nor/cfi_flash.h
+++ b/drivers/mtd/nor/cfi_flash.h
@@ -49,32 +49,32 @@ struct cfi_cmd_set;
struct flash_info {
struct device_d *dev;
- ulong size; /* total bank size in bytes */
- ushort sector_count; /* number of erase units */
- ulong flash_id; /* combined device & manufacturer code */
- ulong *start; /* physical sector start addresses */
- uchar *protect; /* sector protection status */
-
- uchar portwidth; /* the width of the port */
- uchar chipwidth; /* the width of the chip */
- uchar chip_lsb; /* extra Least Significant Bit in the */
+ unsigned long size; /* total bank size in bytes */
+ unsigned int sector_count; /* number of erase units */
+ unsigned long flash_id; /* combined device & manufacturer code */
+ unsigned long *start; /* physical sector start addresses */
+ unsigned char *protect; /* sector protection status */
+
+ unsigned int portwidth; /* the width of the port */
+ unsigned int chipwidth; /* the width of the chip */
+ unsigned int chip_lsb; /* extra Least Significant Bit in the */
/* address of chip. */
- ushort buffer_size; /* # of bytes in write buffer */
- ulong erase_blk_tout; /* maximum block erase timeout */
- ulong write_tout; /* maximum write timeout */
- ulong buffer_write_tout; /* maximum buffer write timeout */
- ushort vendor; /* the primary vendor id */
- ushort cmd_reset; /* vendor specific reset command */
- ushort interface; /* used for x8/x16 adjustments */
- ushort legacy_unlock; /* support Intel legacy (un)locking */
- uchar manufacturer_id; /* manufacturer id */
- ushort device_id; /* device id */
- ushort device_id2; /* extended device id */
- ushort ext_addr; /* extended query table address */
- ushort cfi_version; /* cfi version */
- ushort cfi_offset; /* offset for cfi query */
- ulong addr_unlock1; /* unlock address 1 for AMD flash roms */
- ulong addr_unlock2; /* unlock address 2 for AMD flash roms */
+ unsigned int buffer_size; /* # of bytes in write buffer */
+ unsigned long erase_blk_tout; /* maximum block erase timeout */
+ unsigned long write_tout; /* maximum write timeout */
+ unsigned long buffer_write_tout;/* maximum buffer write timeout */
+ unsigned int vendor; /* the primary vendor id */
+ unsigned int cmd_reset; /* vendor specific reset command */
+ unsigned int interface; /* used for x8/x16 adjustments */
+ unsigned int legacy_unlock; /* support Intel legacy (un)locking */
+ unsigned int manufacturer_id; /* manufacturer id */
+ unsigned int device_id; /* device id */
+ unsigned int device_id2; /* extended device id */
+ unsigned int ext_addr; /* extended query table address */
+ unsigned int cfi_version; /* cfi version */
+ unsigned int cfi_offset; /* offset for cfi query */
+ unsigned long addr_unlock1; /* unlock address 1 for AMD flash roms */
+ unsigned long addr_unlock2; /* unlock address 2 for AMD flash roms */
struct cfi_cmd_set *cfi_cmd_set;
struct mtd_info mtd;
int numeraseregions;
@@ -118,14 +118,16 @@ struct cfi_pri_hdr {
struct cfi_cmd_set {
- int (*flash_write_cfibuffer) (struct flash_info *info, ulong dest, const uchar * cp, int len);
- int (*flash_erase_one) (struct flash_info *info, long sect);
- int (*flash_is_busy) (struct flash_info *info, flash_sect_t sect);
- void (*flash_read_jedec_ids) (struct flash_info *info);
- void (*flash_prepare_write) (struct flash_info *info);
- int (*flash_status_check) (struct flash_info *info, flash_sect_t sector, uint64_t tout, char *prompt);
- int (*flash_real_protect) (struct flash_info *info, long sector, int prot);
- void (*flash_fixup) (struct flash_info *info, struct cfi_qry *qry);
+ int (*flash_write_cfibuffer)(struct flash_info *info, unsigned long dest,
+ const u8 *cp, int len);
+ int (*flash_erase_one)(struct flash_info *info, long sect);
+ int (*flash_is_busy)(struct flash_info *info, flash_sect_t sect);
+ void (*flash_read_jedec_ids)(struct flash_info *info);
+ void (*flash_prepare_write)(struct flash_info *info);
+ int (*flash_status_check)(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
+ int (*flash_real_protect)(struct flash_info *info, long sector, int prot);
+ void (*flash_fixup)(struct flash_info *info, struct cfi_qry *qry);
};
extern struct cfi_cmd_set cfi_cmd_set_intel;
@@ -241,17 +243,17 @@ extern struct cfi_cmd_set cfi_cmd_set_amd;
/* Prototypes */
int flash_isset(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
+ unsigned int offset, u32 cmd);
void flash_write_cmd(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
-flash_sect_t find_sector (struct flash_info *info, ulong addr);
-int flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt);
-int flash_generic_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt);
+ unsigned int offset, u32 cmd);
+flash_sect_t find_sector(struct flash_info *info, unsigned long addr);
+int flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
+int flash_generic_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt);
int flash_isequal(struct flash_info *info, flash_sect_t sect,
- uint offset, u32 cmd);
+ unsigned int offset, u32 cmd);
void flash_make_cmd(struct flash_info *info, u32 cmd, cfiword_t *cmdbuf);
static inline void flash_write8(u8 value, void *addr)
@@ -298,12 +300,13 @@ static inline u64 flash_read64(void *addr)
/*
* create an address based on the offset and the port width
*/
-static inline uchar *flash_make_addr (struct flash_info *info, flash_sect_t sect, uint offset)
+static inline u8 *flash_make_addr(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset)
{
- return ((uchar *) (info->start[sect] + ((offset * info->portwidth) << info->chip_lsb)));
+ return ((u8 *)(info->start[sect] + ((offset * info->portwidth) << info->chip_lsb)));
}
-uchar flash_read_uchar (struct flash_info *info, uint offset);
+u8 flash_read_uchar(struct flash_info *info, unsigned int offset);
u32 jedec_read_mfr(struct flash_info *info);
#ifdef CONFIG_DRIVER_CFI_BANK_WIDTH_1
@@ -332,49 +335,25 @@ u32 jedec_read_mfr(struct flash_info *info);
static inline void flash_write_word(struct flash_info *info, cfiword_t datum, void *addr)
{
- if (bankwidth_is_1(info)) {
- debug("fw addr %p val %02x\n", addr, (u8)datum);
+ if (bankwidth_is_1(info))
flash_write8(datum, addr);
- } else if (bankwidth_is_2(info)) {
- debug("fw addr %p val %04x\n", addr, (u16)datum);
+ else if (bankwidth_is_2(info))
flash_write16(datum, addr);
- } else if (bankwidth_is_4(info)) {
- debug("fw addr %p val %08x\n", addr, (u32)datum);
+ else if (bankwidth_is_4(info))
flash_write32(datum, addr);
- } else if (bankwidth_is_8(info)) {
+ else if (bankwidth_is_8(info))
flash_write64(datum, addr);
- }
}
-extern void flash_print_info (struct flash_info *);
-extern int flash_sect_erase (ulong addr_first, ulong addr_last);
-extern int flash_sect_protect (int flag, ulong addr_first, ulong addr_last);
+extern void flash_print_info(struct flash_info *);
+extern int flash_sect_erase(unsigned long addr_first, unsigned long addr_last);
+extern int flash_sect_protect(int flag, unsigned long addr_first,
+ unsigned long addr_last);
/* common/flash.c */
-extern void flash_protect (int flag, ulong from, ulong to, struct flash_info *info);
-extern int flash_write (char *, ulong, ulong);
-extern struct flash_info *addr2info (ulong);
-//extern int write_buff (flash_info_t *info, const uchar *src, ulong addr, ulong cnt);
-
-/* board/?/flash.c */
-#if defined(CFG_FLASH_PROTECTION)
-extern int flash_real_protect(struct flash_info *info, long sector, int prot);
-extern void flash_read_user_serial(struct flash_info *info, void * buffer, int offset, int len);
-extern void flash_read_factory_serial(struct flash_info *info, void * buffer, int offset, int len);
-#endif /* CFG_FLASH_PROTECTION */
-
-/*-----------------------------------------------------------------------
- * return codes from flash_write():
- */
-#define ERR_OK 0
-#define ERR_TIMOUT 1
-#define ERR_NOT_ERASED 2
-#define ERR_PROTECTED 4
-#define ERR_INVAL 8
-#define ERR_ALIGN 16
-#define ERR_UNKNOWN_FLASH_VENDOR 32
-#define ERR_UNKNOWN_FLASH_TYPE 64
-#define ERR_PROG_ERROR 128
+extern void flash_protect(int flag, unsigned long from, unsigned long to,
+ struct flash_info *info);
+extern int flash_write(char *, unsigned long, unsigned long);
/*-----------------------------------------------------------------------
* Protection Flags for flash_protect():
@@ -729,4 +708,3 @@ extern void flash_read_factory_serial(struct flash_info *info, void * buffer, in
#define FLASH_WRITE_TIMEOUT 500 /* timeout for writes in ms */
#endif /* __CFI_FLASH_H */
-
diff --git a/drivers/mtd/nor/cfi_flash_amd.c b/drivers/mtd/nor/cfi_flash_amd.c
index 45c59b9d01..9c44561d45 100644
--- a/drivers/mtd/nor/cfi_flash_amd.c
+++ b/drivers/mtd/nor/cfi_flash_amd.c
@@ -19,7 +19,7 @@ static void cfi_reverse_geometry(struct cfi_qry *qry)
}
}
-static void flash_unlock_seq (struct flash_info *info)
+static void flash_unlock_seq(struct flash_info *info)
{
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_UNLOCK_START);
flash_write_cmd (info, 0, info->addr_unlock2, AMD_CMD_UNLOCK_ACK);
@@ -31,7 +31,7 @@ static void flash_unlock_seq (struct flash_info *info)
* Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
*
*/
-static void amd_read_jedec_ids (struct flash_info *info)
+static void amd_read_jedec_ids(struct flash_info *info)
{
info->cmd_reset = AMD_CMD_RESET;
info->manufacturer_id = 0;
@@ -62,20 +62,21 @@ static void amd_read_jedec_ids (struct flash_info *info)
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = jedec_read_mfr(info);
- info->device_id = flash_read_uchar (info,
+ info->device_id = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID);
if (info->device_id == 0x7E) {
/* AMD 3-byte (expanded) device ids */
- info->device_id2 = flash_read_uchar (info,
+ info->device_id2 = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID2);
info->device_id2 <<= 8;
- info->device_id2 |= flash_read_uchar (info,
+ info->device_id2 |= flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID3);
}
flash_write_cmd(info, 0, 0, info->cmd_reset);
}
-static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset, uchar cmd)
+static int flash_toggle(struct flash_info *info, flash_sect_t sect,
+ unsigned int offset, u8 cmd)
{
void *addr;
cfiword_t cword;
@@ -83,6 +84,7 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
addr = flash_make_addr (info, sect, offset);
flash_make_cmd (info, cmd, &cword);
+
if (bankwidth_is_1(info)) {
retval = flash_read8(addr) != flash_read8(addr);
} else if (bankwidth_is_2(info)) {
@@ -92,8 +94,9 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
} else if (bankwidth_is_8(info)) {
retval = ( (flash_read32( addr ) != flash_read32( addr )) ||
(flash_read32(addr+4) != flash_read32(addr+4)) );
- } else
+ } else {
retval = 0;
+ }
return retval;
}
@@ -102,12 +105,12 @@ static int flash_toggle (struct flash_info *info, flash_sect_t sect, uint offset
* flash_is_busy - check to see if the flash is busy
* This routine checks the status of the chip and returns true if the chip is busy
*/
-static int amd_flash_is_busy (struct flash_info *info, flash_sect_t sect)
+static int amd_flash_is_busy(struct flash_info *info, flash_sect_t sect)
{
return flash_toggle (info, sect, 0, AMD_STATUS_TOGGLE);
}
-static int amd_flash_erase_one (struct flash_info *info, long sect)
+static int amd_flash_erase_one(struct flash_info *info, long sect)
{
flash_unlock_seq(info);
flash_write_cmd (info, 0, info->addr_unlock1, AMD_CMD_ERASE_START);
@@ -124,13 +127,12 @@ static void amd_flash_prepare_write(struct flash_info *info)
}
#ifdef CONFIG_CFI_BUFFER_WRITE
-static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const uchar * cp,
- int len)
+static int amd_flash_write_cfibuffer(struct flash_info *info, unsigned long dest,
+ const u8 *cp, int len)
{
flash_sect_t sector;
int cnt;
- int retcode;
- void *src = (void*)cp;
+ void *src = (void *)cp;
void *dst = (void *)dest;
cfiword_t cword;
@@ -170,18 +172,18 @@ static int amd_flash_write_cfibuffer (struct flash_info *info, ulong dest, const
}
}
- flash_write_cmd (info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_status_check (info, sector, info->buffer_write_tout,
+ flash_write_cmd(info, sector, 0, AMD_CMD_WRITE_BUFFER_CONFIRM);
+
+ return flash_status_check(info, sector, info->buffer_write_tout,
"buffer write");
- return retcode;
}
#else
#define amd_flash_write_cfibuffer NULL
#endif /* CONFIG_CFI_BUFFER_WRITE */
-static int amd_flash_real_protect (struct flash_info *info, long sector, int prot)
+static int amd_flash_real_protect(struct flash_info *info, long sector, int prot)
{
- if (info->manufacturer_id != (uchar)ATM_MANUFACT)
+ if (info->manufacturer_id != (u8)ATM_MANUFACT)
return 0;
if (prot) {
@@ -205,7 +207,7 @@ static int amd_flash_real_protect (struct flash_info *info, long sector, int pro
* Manufacturer-specific quirks. Add workarounds for geometry
* reversal, etc. here.
*/
-static void flash_fixup_amd (struct flash_info *info, struct cfi_qry *qry)
+static void flash_fixup_amd(struct flash_info *info, struct cfi_qry *qry)
{
/* check if flash geometry needs reversal */
if (qry->num_erase_regions > 1) {
@@ -265,4 +267,3 @@ struct cfi_cmd_set cfi_cmd_set_amd = {
.flash_real_protect = amd_flash_real_protect,
.flash_fixup = amd_flash_fixup,
};
-
diff --git a/drivers/mtd/nor/cfi_flash_intel.c b/drivers/mtd/nor/cfi_flash_intel.c
index 32e581a395..6108d7cc62 100644
--- a/drivers/mtd/nor/cfi_flash_intel.c
+++ b/drivers/mtd/nor/cfi_flash_intel.c
@@ -6,8 +6,8 @@
*
* Note: assume cfi->vendor, cfi->portwidth and cfi->chipwidth are correct
*
-*/
-static void intel_read_jedec_ids (struct flash_info *info)
+ */
+static void intel_read_jedec_ids(struct flash_info *info)
{
info->cmd_reset = FLASH_CMD_RESET;
info->manufacturer_id = 0;
@@ -19,7 +19,7 @@ static void intel_read_jedec_ids (struct flash_info *info)
udelay(1000); /* some flash are slow to respond */
info->manufacturer_id = jedec_read_mfr(info);
- info->device_id = flash_read_uchar (info,
+ info->device_id = flash_read_uchar(info,
FLASH_OFFSET_DEVICE_ID);
flash_write_cmd(info, 0, 0, info->cmd_reset);
}
@@ -28,16 +28,16 @@ static void intel_read_jedec_ids (struct flash_info *info)
* flash_is_busy - check to see if the flash is busy
* This routine checks the status of the chip and returns true if the chip is busy
*/
-static int intel_flash_is_busy (struct flash_info *info, flash_sect_t sect)
+static int intel_flash_is_busy(struct flash_info *info, flash_sect_t sect)
{
return !flash_isset (info, sect, 0, FLASH_STATUS_DONE);
}
-static int intel_flash_erase_one (struct flash_info *info, long sect)
+static int intel_flash_erase_one(struct flash_info *info, long sect)
{
- flash_write_cmd (info, sect, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sect, 0, FLASH_CMD_BLOCK_ERASE);
- flash_write_cmd (info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_BLOCK_ERASE);
+ flash_write_cmd(info, sect, 0, FLASH_CMD_ERASE_CONFIRM);
return flash_status_check(info, sect, info->erase_blk_tout, "erase");
}
@@ -49,26 +49,26 @@ static void intel_flash_prepare_write(struct flash_info *info)
}
#ifdef CONFIG_CFI_BUFFER_WRITE
-static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, const uchar * cp,
- int len)
+static int intel_flash_write_cfibuffer(struct flash_info *info,
+ unsigned long dest, const u8 *cp, int len)
{
flash_sect_t sector;
int cnt;
- int retcode;
+ int ret;
void *src = (void*)cp;
void *dst = (void *)dest;
/* reduce width due to possible alignment problems */
const unsigned long ptr = (unsigned long)dest | (unsigned long)cp | info->portwidth;
const int width = ptr & -ptr;
- sector = find_sector (info, dest);
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
+ sector = find_sector(info, dest);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_TO_BUFFER);
- retcode = flash_generic_status_check (info, sector, info->buffer_write_tout,
+ ret = flash_generic_status_check(info, sector, info->buffer_write_tout,
"write to buffer");
- if (retcode != ERR_OK)
- return retcode;
+ if (ret)
+ return ret;
/* reduce the number of loops by the width of the port */
cnt = len / width;
@@ -95,69 +95,65 @@ static int intel_flash_write_cfibuffer (struct flash_info *info, ulong dest, con
}
}
- flash_write_cmd (info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM);
- retcode = flash_status_check (info, sector,
+ flash_write_cmd(info, sector, 0, FLASH_CMD_WRITE_BUFFER_CONFIRM);
+ ret = flash_status_check(info, sector,
info->buffer_write_tout,
"buffer write");
- return retcode;
+ return ret;
}
#else
#define intel_flash_write_cfibuffer NULL
#endif /* CONFIG_CFI_BUFFER_WRITE */
-static int intel_flash_status_check (struct flash_info *info, flash_sect_t sector,
- uint64_t tout, char *prompt)
+static int intel_flash_status_check(struct flash_info *info, flash_sect_t sector,
+ u64 tout, char *prompt)
{
- int retcode;
-
- retcode = flash_generic_status_check (info, sector, tout, prompt);
+ int ret;
- if ((retcode == ERR_OK)
- && !flash_isequal (info, sector, 0, FLASH_STATUS_DONE)) {
- retcode = ERR_INVAL;
- printf ("Flash %s error at address %lx\n", prompt,
+ ret = flash_generic_status_check(info, sector, tout, prompt);
+ if (!ret && !flash_isequal(info, sector, 0, FLASH_STATUS_DONE)) {
+ ret = -EINVAL;
+ printf("Flash %s error at address %lx\n", prompt,
info->start[sector]);
- if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
- puts ("Command Sequence Error.\n");
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_ECLBS | FLASH_STATUS_PSLBS)) {
+ printf("Command Sequence Error.\n");
} else if (flash_isset (info, sector, 0, FLASH_STATUS_ECLBS)) {
- puts ("Block Erase Error.\n");
- retcode = ERR_NOT_ERASED;
- } else if (flash_isset (info, sector, 0, FLASH_STATUS_PSLBS)) {
- puts ("Locking Error\n");
+ printf("Block Erase Error.\n");
+ ret = -EIO;
+ } else if (flash_isset(info, sector, 0, FLASH_STATUS_PSLBS)) {
+ printf("Locking Error\n");
}
- if (flash_isset (info, sector, 0, FLASH_STATUS_DPS)) {
- puts ("Block locked.\n");
- retcode = ERR_PROTECTED;
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_DPS)) {
+ printf("Block locked.\n");
+ ret = -EROFS;
}
- if (flash_isset (info, sector, 0, FLASH_STATUS_VPENS))
- puts ("Vpp Low Error.\n");
+
+ if (flash_isset(info, sector, 0, FLASH_STATUS_VPENS))
+ printf("Vpp Low Error.\n");
}
- flash_write_cmd (info, sector, 0, info->cmd_reset);
- return retcode;
+ flash_write_cmd(info, sector, 0, info->cmd_reset);
+
+ return ret;
}
-static int intel_flash_real_protect (struct flash_info *info, long sector, int prot)
+static int intel_flash_real_protect(struct flash_info *info, long sector, int prot)
{
- flash_write_cmd (info, sector, 0, FLASH_CMD_CLEAR_STATUS);
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_CLEAR_STATUS);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT);
+
if (prot)
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_SET);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_SET);
else
- flash_write_cmd (info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
+ flash_write_cmd(info, sector, 0, FLASH_CMD_PROTECT_CLEAR);
return 0;
}
-static void intel_flash_fixup (struct flash_info *info, struct cfi_qry *qry)
+static void intel_flash_fixup(struct flash_info *info, struct cfi_qry *qry)
{
-#ifdef CFG_FLASH_PROTECTION
- /* read legacy lock/unlock bit from intel flash */
- if (info->ext_addr) {
- info->legacy_unlock = flash_read_uchar (info,
- info->ext_addr + 5) & 0x08;
- }
-#endif
}
struct cfi_cmd_set cfi_cmd_set_intel = {
@@ -170,4 +166,3 @@ struct cfi_cmd_set cfi_cmd_set_intel = {
.flash_real_protect = intel_flash_real_protect,
.flash_fixup = intel_flash_fixup,
};
-
diff --git a/drivers/mtd/partition.c b/drivers/mtd/partition.c
index 98b90819bd..c11a3db1c5 100644
--- a/drivers/mtd/partition.c
+++ b/drivers/mtd/partition.c
@@ -31,6 +31,16 @@ static int mtd_part_write(struct mtd_info *mtd, loff_t to, size_t len,
len, retlen, buf);
}
+static int mtd_part_write_oob(struct mtd_info *mtd, loff_t to,
+ struct mtd_oob_ops *ops)
+{
+ if (to >= mtd->size)
+ return -EINVAL;
+ if (ops->datbuf && to + ops->len > mtd->size)
+ return -EINVAL;
+ return mtd->master->write_oob(mtd->master, to + mtd->master_offset, ops);
+}
+
static int mtd_part_erase(struct mtd_info *mtd, struct erase_info *instr)
{
int ret;
@@ -160,6 +170,9 @@ struct mtd_info *mtd_add_partition(struct mtd_info *mtd, off_t offset,
part->block_markbad = mtd->block_markbad ? mtd_part_block_markbad : NULL;
}
+ if (mtd->write_oob)
+ part->write_oob = mtd_part_write_oob;
+
part->block_isbad = mtd->block_isbad ? mtd_part_block_isbad : NULL;
part->size = size;
part->name = xstrdup(name);
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index b02880eb79..797022636d 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -155,8 +155,8 @@ static int uif_init(struct ubi_device *ubi, int *ref)
*ref = 0;
sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
- sprintf(ubi->dev.name, "ubi");
- ubi->dev.id = DEVICE_ID_DYNAMIC;
+ sprintf(ubi->dev.name, "%s.ubi", ubi->mtd->cdev.name);
+ ubi->dev.id = DEVICE_ID_SINGLE;
ubi->dev.parent = &ubi->mtd->class_dev;
err = register_device(&ubi->dev);
@@ -518,7 +518,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
for (i = 0; i < UBI_MAX_DEVICES; i++) {
ubi = ubi_devices[i];
if (ubi && mtd == ubi->mtd) {
- ubi_err("mtd%d is already attached to ubi%d",
+ ubi_debug("mtd%d is already attached to ubi%d",
mtd->index, i);
return -EEXIST;
}
@@ -596,9 +596,6 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
#else
ubi->fm_disabled = 1;
#endif
-
- ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
-
err = io_init(ubi, max_beb_per1024);
if (err)
goto out_free;
diff --git a/drivers/mtd/ubi/cdev.c b/drivers/mtd/ubi/cdev.c
index 90d5b2dd66..fe71a8d609 100644
--- a/drivers/mtd/ubi/cdev.c
+++ b/drivers/mtd/ubi/cdev.c
@@ -176,7 +176,7 @@ int ubi_volume_cdev_add(struct ubi_device *ubi, struct ubi_volume *vol)
priv->ubi = ubi;
cdev->ops = &ubi_volume_fops;
- cdev->name = asprintf("ubi%d.%s", ubi->ubi_num, vol->name);
+ cdev->name = asprintf("%s.%s", ubi->cdev.name, vol->name);
cdev->priv = priv;
cdev->size = vol->used_bytes;
cdev->dev = &vol->dev;
@@ -239,7 +239,7 @@ int ubi_cdev_add(struct ubi_device *ubi)
int ret;
cdev->ops = &ubi_fops;
- cdev->name = asprintf("ubi%d", ubi->ubi_num);
+ cdev->name = asprintf("%s.ubi", ubi->mtd->cdev.name);
cdev->priv = ubi;
cdev->size = 0;
diff --git a/drivers/net/altera_tse.c b/drivers/net/altera_tse.c
index 385a7150ba..a1863655fa 100644
--- a/drivers/net/altera_tse.c
+++ b/drivers/net/altera_tse.c
@@ -231,7 +231,7 @@ static int tse_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int tse_set_ethaddr(struct eth_device *edev, unsigned char *m)
+static int tse_set_ethaddr(struct eth_device *edev, const unsigned char *m)
{
struct altera_tse_priv *priv = edev->priv;
struct alt_tse_mac *mac_dev = priv->tse_regs;
diff --git a/drivers/net/ar231x.c b/drivers/net/ar231x.c
index 48e4b30fd6..7447c4484d 100644
--- a/drivers/net/ar231x.c
+++ b/drivers/net/ar231x.c
@@ -70,7 +70,7 @@ static void ar231x_reset_bit_(struct ar231x_eth_priv *priv,
(*priv->reset_bit)(val, state);
}
-static int ar231x_set_ethaddr(struct eth_device *edev, unsigned char *addr);
+static int ar231x_set_ethaddr(struct eth_device *edev, const unsigned char *addr);
static void ar231x_reset_regs(struct eth_device *edev)
{
struct ar231x_eth_priv *priv = edev->priv;
diff --git a/drivers/net/arc_emac.c b/drivers/net/arc_emac.c
index 84e2c75c5e..3dc54cd22b 100644
--- a/drivers/net/arc_emac.c
+++ b/drivers/net/arc_emac.c
@@ -332,7 +332,7 @@ static int arc_emac_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return -1;
}
-static int arc_emac_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int arc_emac_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct arc_emac_priv *priv = edev->priv;
unsigned int addr_low, addr_hi;
diff --git a/drivers/net/at91_ether.c b/drivers/net/at91_ether.c
index 5a74837f65..523e35590b 100644
--- a/drivers/net/at91_ether.c
+++ b/drivers/net/at91_ether.c
@@ -261,7 +261,7 @@ static int at91_ether_get_ethaddr(struct eth_device *eth, unsigned char *adr)
return -1;
}
-static int at91_ether_set_ethaddr(struct eth_device *eth, unsigned char *adr)
+static int at91_ether_set_ethaddr(struct eth_device *eth, const unsigned char *adr)
{
int i;
diff --git a/drivers/net/cpsw.c b/drivers/net/cpsw.c
index c0db96bb53..4d6b7b2e78 100644
--- a/drivers/net/cpsw.c
+++ b/drivers/net/cpsw.c
@@ -547,7 +547,7 @@ static int cpsw_get_hwaddr(struct eth_device *edev, unsigned char *mac)
return -1;
}
-static int cpsw_set_hwaddr(struct eth_device *edev, unsigned char *mac)
+static int cpsw_set_hwaddr(struct eth_device *edev, const unsigned char *mac)
{
struct cpsw_slave *slave = edev->priv;
struct cpsw_priv *priv = slave->cpsw;
diff --git a/drivers/net/cs8900.c b/drivers/net/cs8900.c
index dccb808f95..a4a5dcaf7f 100644
--- a/drivers/net/cs8900.c
+++ b/drivers/net/cs8900.c
@@ -341,7 +341,7 @@ static int cs8900_get_ethaddr(struct eth_device *dev, unsigned char *mac)
return 0;
}
-static int cs8900_set_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int cs8900_set_ethaddr(struct eth_device *dev, const unsigned char *mac)
{
struct cs8900_priv *priv = (struct cs8900_priv *)dev->priv;
int i;
diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c
index 056ffe28bc..9f8f0e1fa7 100644
--- a/drivers/net/davinci_emac.c
+++ b/drivers/net/davinci_emac.c
@@ -178,7 +178,7 @@ static int davinci_emac_get_ethaddr(struct eth_device *edev, unsigned char *adr)
* This function must be called before emac_open() if you want to override
* the default mac address.
*/
-static int davinci_emac_set_ethaddr(struct eth_device *edev, unsigned char *addr)
+static int davinci_emac_set_ethaddr(struct eth_device *edev, const unsigned char *addr)
{
struct davinci_emac_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/designware.c b/drivers/net/designware.c
index 213fe41359..800652760a 100644
--- a/drivers/net/designware.c
+++ b/drivers/net/designware.c
@@ -384,7 +384,7 @@ static int dwc_ether_get_ethaddr(struct eth_device *dev, u8 adr[6])
return -1;
}
-static int dwc_ether_set_ethaddr(struct eth_device *dev, u8 adr[6])
+static int dwc_ether_set_ethaddr(struct eth_device *dev, const unsigned char *adr)
{
struct dw_eth_dev *priv = dev->priv;
struct eth_mac_regs *mac_p = priv->mac_regs_p;
diff --git a/drivers/net/dm9k.c b/drivers/net/dm9k.c
index c3c2a8052a..1f1938d977 100644
--- a/drivers/net/dm9k.c
+++ b/drivers/net/dm9k.c
@@ -711,7 +711,7 @@ static int dm9k_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int dm9k_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int dm9k_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct dm9k *priv = (struct dm9k *)edev->priv;
int i, oft;
diff --git a/drivers/net/ep93xx.c b/drivers/net/ep93xx.c
index 4b73abff37..90c12fce75 100644
--- a/drivers/net/ep93xx.c
+++ b/drivers/net/ep93xx.c
@@ -466,7 +466,7 @@ static int ep93xx_eth_get_ethaddr(struct eth_device *edev,
}
static int ep93xx_eth_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct mac_regs *regs = ep93xx_get_regs(edev);
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 7c52a09eaa..6bae7d68a6 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -435,7 +435,7 @@ static int ethoc_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return 0;
}
-static int ethoc_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int ethoc_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct ethoc *dev = edev->priv;
diff --git a/drivers/net/fec_imx.c b/drivers/net/fec_imx.c
index 9a10c9f2e4..78ccb85376 100644
--- a/drivers/net/fec_imx.c
+++ b/drivers/net/fec_imx.c
@@ -249,7 +249,7 @@ static int fec_get_hwaddr(struct eth_device *dev, unsigned char *mac)
return -1;
}
-static int fec_set_hwaddr(struct eth_device *dev, unsigned char *mac)
+static int fec_set_hwaddr(struct eth_device *dev, const unsigned char *mac)
{
struct fec_priv *fec = (struct fec_priv *)dev->priv;
diff --git a/drivers/net/fec_mpc5200.c b/drivers/net/fec_mpc5200.c
index f431d79d1d..14ef872927 100644
--- a/drivers/net/fec_mpc5200.c
+++ b/drivers/net/fec_mpc5200.c
@@ -211,7 +211,7 @@ static int mpc5xxx_fec_get_ethaddr(struct eth_device *dev, unsigned char *mac)
return -1;
}
-static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, unsigned char *mac)
+static int mpc5xxx_fec_set_ethaddr(struct eth_device *dev, const unsigned char *mac)
{
mpc5xxx_fec_priv *fec = (mpc5xxx_fec_priv *)dev->priv;
uint8_t currByte; /* byte for which to compute the CRC */
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index 5e47c64e0f..ac698332cf 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -233,7 +233,7 @@ static int gfar_get_ethaddr(struct eth_device *edev, unsigned char *mac)
return -ENODEV;
}
-static int gfar_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int gfar_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct gfar_private *priv = edev->priv;
void __iomem *regs = priv->regs;
diff --git a/drivers/net/ks8851_mll.c b/drivers/net/ks8851_mll.c
index a8974cfcb9..854a666bfc 100644
--- a/drivers/net/ks8851_mll.c
+++ b/drivers/net/ks8851_mll.c
@@ -571,7 +571,7 @@ static int ks8851_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int ks8851_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int ks8851_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct ks_net *priv = (struct ks_net *)edev->priv;
diff --git a/drivers/net/macb.c b/drivers/net/macb.c
index 2ac00f3460..6d4973fa2f 100644
--- a/drivers/net/macb.c
+++ b/drivers/net/macb.c
@@ -493,7 +493,7 @@ static int macb_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int macb_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int macb_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct macb_device *macb = edev->priv;
diff --git a/drivers/net/mvneta.c b/drivers/net/mvneta.c
index 3be2ec531f..aab52c45de 100644
--- a/drivers/net/mvneta.c
+++ b/drivers/net/mvneta.c
@@ -486,7 +486,7 @@ recv_err:
return ret;
}
-static int mvneta_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int mvneta_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct mvneta_port *priv = edev->priv;
u32 mac_h = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
diff --git a/drivers/net/netx_eth.c b/drivers/net/netx_eth.c
index 96dbc7c5df..64e9886d61 100644
--- a/drivers/net/netx_eth.c
+++ b/drivers/net/netx_eth.c
@@ -210,7 +210,7 @@ static int netx_eth_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int netx_eth_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int netx_eth_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct netx_eth_priv *priv = (struct netx_eth_priv *)edev->priv;
int xcno = priv->xcno;
diff --git a/drivers/net/orion-gbe.c b/drivers/net/orion-gbe.c
index 97ffff2b26..e6bd757689 100644
--- a/drivers/net/orion-gbe.c
+++ b/drivers/net/orion-gbe.c
@@ -322,7 +322,7 @@ recv_err:
return ret;
}
-static int port_set_ethaddr(struct eth_device *edev, unsigned char *mac)
+static int port_set_ethaddr(struct eth_device *edev, const unsigned char *mac)
{
struct port_priv *port = edev->priv;
u32 mac_h = (mac[0] << 24) | (mac[1] << 16) | (mac[2] << 8) | mac[3];
diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c
index d57c706e52..a9eb865358 100644
--- a/drivers/net/rtl8139.c
+++ b/drivers/net/rtl8139.c
@@ -352,7 +352,7 @@ static int rtl8139_get_ethaddr(struct eth_device *edev, unsigned char *m)
}
static int rtl8139_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct rtl8139_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index d6a761087c..47d5e4a893 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -456,7 +456,7 @@ static int rtl8169_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int rtl8169_set_ethaddr(struct eth_device *edev, unsigned char *mac_addr)
+static int rtl8169_set_ethaddr(struct eth_device *edev, const unsigned char *mac_addr)
{
struct rtl8169_priv *priv = edev->priv;
int i;
diff --git a/drivers/net/smc91111.c b/drivers/net/smc91111.c
index c0cf42ad82..5ea1bc3259 100644
--- a/drivers/net/smc91111.c
+++ b/drivers/net/smc91111.c
@@ -1378,7 +1378,7 @@ static int smc91c111_get_ethaddr(struct eth_device *edev, unsigned char *m)
}
static int smc91c111_set_ethaddr(struct eth_device *edev,
- unsigned char *mac_addr)
+ const unsigned char *mac_addr)
{
struct smc91c111_priv *priv = (struct smc91c111_priv *)edev->priv;
unsigned address;
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c
index 9977ae3f32..60cf36ea4a 100644
--- a/drivers/net/smc911x.c
+++ b/drivers/net/smc911x.c
@@ -182,7 +182,7 @@ static int smc911x_get_ethaddr(struct eth_device *edev, unsigned char *m)
return 0;
}
-static int smc911x_set_ethaddr(struct eth_device *edev, unsigned char *m)
+static int smc911x_set_ethaddr(struct eth_device *edev, const unsigned char *m)
{
unsigned long addrh, addrl;
@@ -630,8 +630,14 @@ static int smc911x_probe(struct device_d *dev)
return 0;
}
+static const struct of_device_id smsc911x_dt_ids[] = {
+ { .compatible = "smsc,lan9115", },
+ { /* sentinel */ }
+};
+
static struct driver_d smc911x_driver = {
.name = "smc911x",
.probe = smc911x_probe,
+ .of_compatible = DRV_OF_COMPAT(smsc911x_dt_ids),
};
device_platform_driver(smc911x_driver);
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 2458fb52c7..ca53f12d92 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -65,7 +65,7 @@ static int tap_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return -1;
}
-static int tap_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int tap_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
return 0;
}
diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c
index 7cce5b929e..4c53a142f1 100644
--- a/drivers/net/usb/asix.c
+++ b/drivers/net/usb/asix.c
@@ -403,7 +403,7 @@ static int asix_get_ethaddr(struct eth_device *edev, unsigned char *adr)
return 0;
}
-static int asix_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int asix_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
/* not possible? */
return 0;
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
index 053da1822a..6360e480fe 100644
--- a/drivers/net/usb/smsc95xx.c
+++ b/drivers/net/usb/smsc95xx.c
@@ -363,7 +363,7 @@ static int smsc95xx_set_csums(struct usbnet *dev)
return 0;
}
-static int smsc95xx_set_ethaddr(struct eth_device *edev, unsigned char *adr)
+static int smsc95xx_set_ethaddr(struct eth_device *edev, const unsigned char *adr)
{
struct usbnet *udev = container_of(edev, struct usbnet, edev);
diff --git a/drivers/net/xgmac.c b/drivers/net/xgmac.c
index 3b2273fd79..7cc4d4888f 100644
--- a/drivers/net/xgmac.c
+++ b/drivers/net/xgmac.c
@@ -674,7 +674,7 @@ static int xgmac_get_ethaddr(struct eth_device *edev, unsigned char *addr)
return 0;
}
-static int xgmac_set_ethaddr(struct eth_device *dev, unsigned char *addr)
+static int xgmac_set_ethaddr(struct eth_device *dev, const unsigned char *addr)
{
struct xgmac_priv *priv = dev->priv;
u32 data;
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index ab3ccab3b6..2c075dbae3 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -118,7 +118,7 @@ static void of_device_make_bus_id(struct device_d *dev)
* Returns pointer to created platform device, or NULL if a device was not
* registered. Unavailable devices will not get registered.
*/
-static struct device_d *of_platform_device_create(struct device_node *np,
+struct device_d *of_platform_device_create(struct device_node *np,
struct device_d *parent)
{
struct device_d *dev;
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 3a0e7a5f4e..191561da03 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -129,10 +129,24 @@ static struct pci_dev *alloc_pci_dev(void)
return dev;
}
+static u32 pci_size(u32 base, u32 maxbase, u32 mask)
+{
+ u32 size = maxbase & mask;
+ if (!size)
+ return 0;
+
+ size = (size & ~(size-1)) - 1;
+
+ if (base == maxbase && ((base | size) & mask) != mask)
+ return 0;
+
+ return size + 1;
+}
+
+
static void setup_device(struct pci_dev *dev, int max_bar)
{
- int bar, size;
- u32 mask;
+ int bar;
u8 cmd;
pci_read_config_byte(dev, PCI_COMMAND, &cmd);
@@ -141,9 +155,12 @@ static void setup_device(struct pci_dev *dev, int max_bar)
for (bar = 0; bar < max_bar; bar++) {
resource_size_t last_addr;
+ u32 orig, mask, size;
+ pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &orig);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, 0xfffffffe);
pci_read_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, &mask);
+ pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, orig);
if (mask == 0 || mask == 0xffffffff) {
pr_debug("pbar%d set bad mask\n", bar);
@@ -151,7 +168,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
}
if (mask & 0x01) { /* IO */
- size = ((~(mask & 0xfffffffe)) & 0xffff) + 1;
+ size = pci_size(orig, mask, 0xfffffffe);
+ if (!size) {
+ pr_debug("pbar%d bad IO mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x io %d bytes\n", bar, mask, size);
if (last_io + size >
dev->bus->resource[PCI_BUS_RESOURCE_IO]->end) {
@@ -164,7 +185,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
last_io += size;
} else if ((mask & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
last_mem_pref) /* prefetchable MEM */ {
- size = (~(mask & 0xfffffff0)) + 1;
+ size = pci_size(orig, mask, 0xfffffff0);
+ if (!size) {
+ pr_debug("pbar%d bad P-MEM mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x P memory %d bytes\n",
bar, mask, size);
if (last_mem_pref + size >
@@ -178,7 +203,11 @@ static void setup_device(struct pci_dev *dev, int max_bar)
last_addr = last_mem_pref;
last_mem_pref += size;
} else { /* non-prefetch MEM */
- size = (~(mask & 0xfffffff0)) + 1;
+ size = pci_size(orig, mask, 0xfffffff0);
+ if (!size) {
+ pr_debug("pbar%d bad NP-MEM mask\n", bar);
+ continue;
+ }
pr_debug("pbar%d: mask=%08x NP memory %d bytes\n",
bar, mask, size);
if (last_mem + size >
@@ -391,11 +420,6 @@ unsigned int pci_scan_bus(struct pci_bus *bus)
bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
continue;
}
-
- if (class == PCI_CLASS_BRIDGE_HOST) {
- pr_debug("skip pci host bridge\n");
- continue;
- }
}
/*
diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig
index 8324d5ef19..97c3deff10 100644
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -22,4 +22,10 @@ config PWM_IMX
help
This enables PWM support for Freescale i.MX SoCs
+config PWM_MXS
+ bool "i.MXs PWM Support"
+ depends on ARCH_MXS
+ help
+ This enables PWM support for Freescale i.MX23/i.MX28 SoCs
+
endif
diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile
index dea9956c04..46865a24ee 100644
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -1,3 +1,4 @@
obj-$(CONFIG_PWM) += core.o
obj-$(CONFIG_PWM_PXA) += pxa_pwm.o
obj-$(CONFIG_PWM_IMX) += pwm-imx.o
+obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index cc33dec363..360520195a 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -181,12 +181,13 @@ struct pwm_device *pwm_request(const char *devname)
}
EXPORT_SYMBOL_GPL(pwm_request);
-static struct pwm_device *of_node_to_pwm_device(struct device_node *np)
+static struct pwm_device *of_node_to_pwm_device(struct device_node *np, int id)
{
struct pwm_device *pwm;
list_for_each_entry(pwm, &pwm_list, node) {
- if (pwm->hwdev && pwm->hwdev->device_node == np)
+ if (pwm->hwdev && pwm->hwdev->device_node == np &&
+ pwm->chip->id == id)
return pwm;
}
@@ -210,7 +211,7 @@ struct pwm_device *of_pwm_request(struct device_node *np, const char *con_id)
return ERR_PTR(ret);
}
- pwm = of_node_to_pwm_device(args.np);
+ pwm = of_node_to_pwm_device(args.np, args.args[0]);
if (IS_ERR(pwm)) {
pr_debug("%s(): PWM chip not found\n", __func__);
return pwm;
diff --git a/drivers/pwm/pwm-mxs.c b/drivers/pwm/pwm-mxs.c
new file mode 100644
index 0000000000..e66744288b
--- /dev/null
+++ b/drivers/pwm/pwm-mxs.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *
+ * 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 <common.h>
+#include <init.h>
+#include <errno.h>
+#include <io.h>
+#include <pwm.h>
+#include <stmp-device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <asm-generic/div64.h>
+
+#define SET 0x4
+#define CLR 0x8
+#define TOG 0xc
+
+#define PWM_CTRL 0x0
+#define PWM_ACTIVE0 0x10
+#define PWM_PERIOD0 0x20
+#define PERIOD_PERIOD(p) ((p) & 0xffff)
+#define PERIOD_PERIOD_MAX 0x10000
+#define PERIOD_ACTIVE_HIGH (3 << 16)
+#define PERIOD_INACTIVE_LOW (2 << 18)
+#define PERIOD_CDIV(div) (((div) & 0x7) << 20)
+#define PERIOD_CDIV_MAX 8
+
+static const unsigned int cdiv[PERIOD_CDIV_MAX] = {
+ 1, 2, 4, 8, 16, 64, 256, 1024
+};
+
+struct mxs_pwm;
+
+struct mxs_pwm_chip {
+ struct pwm_chip chip;
+ struct mxs_pwm *mxs;
+};
+
+struct mxs_pwm {
+ struct mxs_pwm_chip pwm[8];
+ struct clk *clk;
+ void __iomem *base;
+};
+
+#define to_mxs_pwm_chip(_chip) container_of(_chip, struct mxs_pwm_chip, chip)
+
+static int mxs_pwm_config(struct pwm_chip *chip, int duty_ns, int period_ns)
+{
+ struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip);
+ int div = 0;
+ unsigned int period_cycles, duty_cycles;
+ unsigned long rate;
+ unsigned long long c;
+
+ rate = clk_get_rate(mxs->mxs->clk);
+ while (1) {
+ c = rate / cdiv[div];
+ c = c * period_ns;
+ do_div(c, 1000000000);
+ if (c < PERIOD_PERIOD_MAX)
+ break;
+ div++;
+ if (div >= PERIOD_CDIV_MAX)
+ return -EINVAL;
+ }
+
+ period_cycles = c;
+ c *= duty_ns;
+ do_div(c, period_ns);
+ duty_cycles = c;
+
+ writel(duty_cycles << 16,
+ mxs->mxs->base + PWM_ACTIVE0 + mxs->chip.id * 0x20);
+ writel(PERIOD_PERIOD(period_cycles) | PERIOD_ACTIVE_HIGH |
+ PERIOD_INACTIVE_LOW | PERIOD_CDIV(div),
+ mxs->mxs->base + PWM_PERIOD0 + mxs->chip.id * 0x20);
+
+ return 0;
+}
+
+static int mxs_pwm_enable(struct pwm_chip *chip)
+{
+ struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip);
+
+ writel(1 << mxs->chip.id, mxs->mxs->base + PWM_CTRL + SET);
+
+ return 0;
+}
+
+static void mxs_pwm_disable(struct pwm_chip *chip)
+{
+ struct mxs_pwm_chip *mxs = to_mxs_pwm_chip(chip);
+
+ writel(1 << mxs->chip.id, mxs->mxs->base + PWM_CTRL + CLR);
+}
+
+static struct pwm_ops mxs_pwm_ops = {
+ .config = mxs_pwm_config,
+ .enable = mxs_pwm_enable,
+ .disable = mxs_pwm_disable,
+};
+
+static int mxs_pwm_probe(struct device_d *dev)
+{
+ struct device_node *np = dev->device_node;
+ struct mxs_pwm *mxs;
+ int ret, i;
+ uint32_t npwm;
+
+ mxs = xzalloc(sizeof(*mxs));
+
+ mxs->base = dev_request_mem_region(dev, 0);
+ if (IS_ERR(mxs->base))
+ return PTR_ERR(mxs->base);
+
+ mxs->clk = clk_get(dev, NULL);
+ if (IS_ERR(mxs->clk))
+ return PTR_ERR(mxs->clk);
+
+ clk_enable(mxs->clk);
+
+ ret = stmp_reset_block(mxs->base, 0);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "fsl,pwm-number", &npwm);
+ if (ret < 0) {
+ dev_err(dev, "failed to get pwm number: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < npwm; i++) {
+ struct mxs_pwm_chip *mxspwm = &mxs->pwm[i];
+
+ mxspwm->chip.ops = &mxs_pwm_ops;
+ mxspwm->chip.devname = asprintf("pwm%d", i);
+ mxspwm->chip.id = i;
+ mxspwm->mxs = mxs;
+
+ ret = pwmchip_add(&mxspwm->chip, dev);
+ if (ret < 0) {
+ dev_err(dev, "failed to add pwm chip %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct of_device_id mxs_pwm_dt_ids[] = {
+ { .compatible = "fsl,imx23-pwm", },
+ { /* sentinel */ }
+};
+
+static struct driver_d mxs_pwm_driver = {
+ .name = "mxs-pwm",
+ .of_compatible = mxs_pwm_dt_ids,
+ .probe = mxs_pwm_probe,
+};
+
+coredevice_platform_driver(mxs_pwm_driver);
+
+MODULE_ALIAS("platform:mxs-pwm");
+MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
+MODULE_DESCRIPTION("Freescale MXS PWM Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c
index 4d636c14ca..c186ad4d39 100644
--- a/drivers/serial/serial_ns16550.c
+++ b/drivers/serial/serial_ns16550.c
@@ -291,6 +291,7 @@ static void ns16550_probe_dt(struct device_d *dev, struct ns16550_priv *priv)
if (!IS_ENABLED(CONFIG_OFDEVICE))
return;
+ of_property_read_u32(np, "clock-frequency", &priv->plat.clock);
of_property_read_u32(np, "reg-shift", &priv->plat.shift);
}
@@ -417,7 +418,7 @@ static int ns16550_probe(struct device_d *dev)
else
ns16550_probe_dt(dev, priv);
- if (!plat || !plat->clock) {
+ if (!priv->plat.clock) {
priv->clk = clk_get(dev, NULL);
if (IS_ERR(priv->clk)) {
ret = PTR_ERR(priv->clk);
@@ -427,12 +428,6 @@ static int ns16550_probe(struct device_d *dev)
priv->plat.clock = clk_get_rate(priv->clk);
}
- if (priv->plat.clock == 0 && IS_ENABLED(CONFIG_OFDEVICE)) {
- struct device_node *np = dev->device_node;
-
- of_property_read_u32(np, "clock-frequency", &priv->plat.clock);
- }
-
if (priv->plat.clock == 0) {
dev_err(dev, "no valid clockrate\n");
ret = -EINVAL;
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 5d9158ffae..13a3e7062a 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -25,7 +25,7 @@ config USB_GADGET_DRIVER_AT91
config USB_GADGET_DRIVER_PXA27X
bool
prompt "PXA27x gadget driver"
- depends on ARCH_PXA
+ depends on ARCH_PXA27X
default y
select USB_GADGET_DUALSPEED
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ccb702980f..84a05c4f96 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -119,8 +119,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" MUSB_DRIVER_NAME);
-#define MUSB_HOST_TIMEOUT 0x5fffff
-
/*-------------------------------------------------------------------------*/
#ifndef CONFIG_BLACKFIN
@@ -1025,17 +1023,18 @@ int musb_init(struct usb_host *host)
{
struct musb *musb = to_musb(host);
void *mbase;
- int timeout = MUSB_HOST_TIMEOUT;
+ u64 start;
u8 power;
musb_start(musb);
mbase = musb->mregs;
- do {
+ start = get_time_ns();
+ while (1) {
if (musb_readb(mbase, MUSB_DEVCTL) & MUSB_DEVCTL_HM)
break;
- } while (--timeout);
- if (!timeout)
- return -ENODEV;
+ if (is_timeout(start, 4 * SECOND))
+ return -ENODEV;
+ }
power = musb_readb(mbase, MUSB_POWER);
musb_writeb(mbase, MUSB_POWER, MUSB_POWER_RESET | power);
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index f096a5456b..8e6ae99b95 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -93,4 +93,16 @@ config DRIVER_VIDEO_EDID
This enabled support for reading and parsing EDID data from an attached
monitor.
+config DRIVER_VIDEO_BACKLIGHT
+ bool "Add backlight support"
+ help
+ Enable this for backlight support.
+
+config DRIVER_VIDEO_BACKLIGHT_PWM
+ bool "PWM backlight support"
+ depends on PWM
+ depends on DRIVER_VIDEO_BACKLIGHT
+ help
+ Enable this to get support for backlight devices driven by a PWM.
+
endif
diff --git a/drivers/video/Makefile b/drivers/video/Makefile
index ae9f6e545e..76fad5c8e8 100644
--- a/drivers/video/Makefile
+++ b/drivers/video/Makefile
@@ -1,6 +1,8 @@
obj-$(CONFIG_VIDEO) += fb.o
obj-$(CONFIG_DRIVER_VIDEO_EDID) += edid.o
obj-$(CONFIG_OFDEVICE) += of_display_timing.o
+obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT) += backlight.o
+obj-$(CONFIG_DRIVER_VIDEO_BACKLIGHT_PWM) += backlight-pwm.o
obj-$(CONFIG_DRIVER_VIDEO_ATMEL) += atmel_lcdfb.o atmel_lcdfb_core.o
obj-$(CONFIG_DRIVER_VIDEO_ATMEL_HLCD) += atmel_hlcdfb.o atmel_lcdfb_core.o
diff --git a/drivers/video/backlight-pwm.c b/drivers/video/backlight-pwm.c
new file mode 100644
index 0000000000..91b148109b
--- /dev/null
+++ b/drivers/video/backlight-pwm.c
@@ -0,0 +1,199 @@
+/*
+ * pwm backlight support for barebox
+ *
+ * (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 <malloc.h>
+#include <init.h>
+#include <video/backlight.h>
+#include <pwm.h>
+#include <linux/err.h>
+#include <of.h>
+#include <gpio.h>
+#include <of_gpio.h>
+#include <asm-generic/div64.h>
+
+struct pwm_backlight {
+ struct backlight_device backlight;
+ struct pwm_device *pwm;
+ uint32_t period;
+ unsigned int *levels;
+ int enable_gpio;
+ int enable_active_high;
+ int max_value;
+ int enabled;
+};
+
+static int backlight_pwm_enable(struct pwm_backlight *pwm_backlight)
+{
+ int ret;
+
+ if (pwm_backlight->enabled)
+ return 0;
+
+ ret = pwm_enable(pwm_backlight->pwm);
+ if (ret)
+ return ret;
+
+ if (gpio_is_valid(pwm_backlight->enable_gpio)) {
+ gpio_direction_output(pwm_backlight->enable_gpio,
+ pwm_backlight->enable_active_high);
+ }
+
+ pwm_backlight->enabled = 1;
+
+ return 0;
+}
+
+static int backlight_pwm_disable(struct pwm_backlight *pwm_backlight)
+{
+ if (!pwm_backlight->enabled)
+ return 0;
+
+ if (gpio_is_valid(pwm_backlight->enable_gpio)) {
+ gpio_direction_output(pwm_backlight->enable_gpio,
+ !pwm_backlight->enable_active_high);
+ /*
+ * Only disable PWM when an enable gpio is present.
+ * The output of the PWM is undefined when the PWM
+ * is disabled.
+ */
+ pwm_disable(pwm_backlight->pwm);
+ pwm_backlight->enabled = 0;
+ }
+
+ return 0;
+}
+
+static int backlight_pwm_set(struct backlight_device *backlight,
+ int brightness)
+{
+ struct pwm_backlight *pwm_backlight = container_of(backlight,
+ struct pwm_backlight, backlight);
+ unsigned long long duty = pwm_backlight->period;
+ unsigned int max = pwm_backlight->backlight.brightness_max;
+
+ duty *= brightness;
+ do_div(duty, max);
+
+ pwm_config(pwm_backlight->pwm, duty, pwm_backlight->period);
+
+ if (brightness)
+ return backlight_pwm_enable(pwm_backlight);
+ else
+ return backlight_pwm_disable(pwm_backlight);
+}
+
+static int pwm_backlight_parse_dt(struct device_d *dev,
+ struct pwm_backlight *pwm_backlight)
+{
+ struct device_node *node = dev->device_node;
+ struct property *prop;
+ int length;
+ u32 value;
+ int ret;
+ enum of_gpio_flags flags;
+
+ if (!node)
+ return -ENODEV;
+
+ /* determine the number of brightness levels */
+ prop = of_find_property(node, "brightness-levels", &length);
+ if (!prop)
+ return -EINVAL;
+
+ pwm_backlight->backlight.brightness_max = length / sizeof(u32);
+
+ /* read brightness levels from DT property */
+ if (pwm_backlight->backlight.brightness_max > 0) {
+ size_t size = sizeof(*pwm_backlight->levels) *
+ pwm_backlight->backlight.brightness_max;
+
+ pwm_backlight->levels = xzalloc(size);
+ if (!pwm_backlight->levels)
+ return -ENOMEM;
+
+ ret = of_property_read_u32_array(node, "brightness-levels",
+ pwm_backlight->levels,
+ pwm_backlight->backlight.brightness_max);
+ if (ret < 0)
+ return ret;
+
+ ret = of_property_read_u32(node, "default-brightness-level",
+ &value);
+ if (ret < 0)
+ return ret;
+
+ pwm_backlight->backlight.brightness_default = value;
+ pwm_backlight->backlight.brightness_max--;
+ }
+
+ pwm_backlight->enable_gpio = of_get_named_gpio_flags(node, "enable-gpios", 0, &flags);
+
+ if (gpio_is_valid(pwm_backlight->enable_gpio)) {
+ if (!(flags & OF_GPIO_ACTIVE_LOW))
+ pwm_backlight->enable_active_high = 1;
+ }
+
+ return 0;
+}
+
+static int backlight_pwm_of_probe(struct device_d *dev)
+{
+ int ret;
+ struct pwm_backlight *pwm_backlight;
+ struct pwm_device *pwm;
+
+ pwm = of_pwm_request(dev->device_node, NULL);
+ if (IS_ERR(pwm))
+ return PTR_ERR(pwm);
+
+ pwm_backlight = xzalloc(sizeof(*pwm_backlight));
+ pwm_backlight->pwm = pwm;
+ pwm_backlight->period = pwm_get_period(pwm);
+
+ ret = pwm_backlight_parse_dt(dev, pwm_backlight);
+ if (ret)
+ return ret;
+
+ pwm_backlight->period = pwm_get_period(pwm_backlight->pwm);
+
+ pwm_backlight->backlight.brightness_set = backlight_pwm_set;
+ pwm_backlight->backlight.node = dev->device_node;
+
+ ret = backlight_register(&pwm_backlight->backlight);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct of_device_id backlight_pwm_of_ids[] = {
+ {
+ .compatible = "pwm-backlight",
+ }, {
+ /* sentinel */
+ }
+};
+
+static struct driver_d backlight_pwm_of_driver = {
+ .name = "pwm-backlight",
+ .probe = backlight_pwm_of_probe,
+ .of_compatible = DRV_OF_COMPAT(backlight_pwm_of_ids),
+};
+device_platform_driver(backlight_pwm_of_driver);
diff --git a/drivers/video/backlight.c b/drivers/video/backlight.c
new file mode 100644
index 0000000000..ddde6f8523
--- /dev/null
+++ b/drivers/video/backlight.c
@@ -0,0 +1,90 @@
+#include <common.h>
+#include <driver.h>
+#include <linux/list.h>
+#include <video/backlight.h>
+
+static LIST_HEAD(backlights);
+
+int backlight_set_brightness(struct backlight_device *bl, int brightness)
+{
+ int ret, step, i, num_steps;
+
+ if (brightness > bl->brightness_max)
+ brightness = bl->brightness_max;
+
+ if (brightness == bl->brightness_cur)
+ return 0;
+
+ if (brightness > bl->brightness_cur)
+ step = 1;
+ else
+ step = -1;
+
+ i = bl->brightness_cur;
+
+ num_steps = abs(brightness - bl->brightness_cur);
+
+ while (1) {
+ i += step;
+
+ ret = bl->brightness_set(bl, i);
+ if (ret)
+ return ret;
+
+ if (i == brightness)
+ break;
+
+ udelay(100000 / num_steps);
+ }
+
+
+ bl->brightness_cur = bl->brightness = brightness;
+
+ return ret;
+}
+
+int backlight_set_brightness_default(struct backlight_device *bl)
+{
+ int ret;
+
+ ret = backlight_set_brightness(bl, bl->brightness_default);
+
+ return ret;
+}
+
+static int backlight_brightness_set(struct param_d *p, void *priv)
+{
+ struct backlight_device *bl = priv;
+
+ return backlight_set_brightness(bl, bl->brightness);
+}
+
+int backlight_register(struct backlight_device *bl)
+{
+ int ret;
+
+ sprintf(bl->dev.name, "backlight");
+ bl->dev.id = DEVICE_ID_DYNAMIC;
+
+ ret = register_device(&bl->dev);
+ if (ret)
+ return ret;
+
+ dev_add_param_int(&bl->dev, "brightness", backlight_brightness_set,
+ NULL, &bl->brightness, "%d", bl);
+
+ list_add_tail(&bl->list, &backlights);
+
+ return ret;
+}
+
+struct backlight_device *of_backlight_find(struct device_node *node)
+{
+ struct backlight_device *bl;
+
+ list_for_each_entry(bl, &backlights, list)
+ if (bl->node == node)
+ return bl;
+
+ return NULL;
+}
diff --git a/drivers/video/stm.c b/drivers/video/stm.c
index 3c90c0dc3f..bf913f1ec6 100644
--- a/drivers/video/stm.c
+++ b/drivers/video/stm.c
@@ -317,7 +317,7 @@ static int stmfb_activate_var(struct fb_info *fb_info)
size = calc_line_length(mode->xres, fb_info->bits_per_pixel) *
mode->yres;
- if (pdata->fixed_screen) {
+ if (pdata && pdata->fixed_screen) {
if (pdata->fixed_screen_size < size)
return -ENOMEM;
fb_info->screen_base = pdata->fixed_screen;
@@ -497,16 +497,37 @@ static int stmfb_probe(struct device_d *hw_dev)
return PTR_ERR(fbi.clk);
clk_enable(fbi.clk);
+ fbi.info.bits_per_pixel = 16;
+
/* add runtime video info */
- fbi.info.modes.modes = pdata->mode_list;
- fbi.info.modes.num_modes = pdata->mode_cnt;
- fbi.info.mode = &fbi.info.modes.modes[0];
- fbi.info.xres = fbi.info.mode->xres;
- fbi.info.yres = fbi.info.mode->yres;
- if (pdata->bits_per_pixel)
- fbi.info.bits_per_pixel = pdata->bits_per_pixel;
- else
- fbi.info.bits_per_pixel = 16;
+ if (pdata) {
+ fbi.info.modes.modes = pdata->mode_list;
+ fbi.info.modes.num_modes = pdata->mode_cnt;
+ fbi.info.mode = &fbi.info.modes.modes[0];
+ if (pdata->bits_per_pixel)
+ fbi.info.bits_per_pixel = pdata->bits_per_pixel;
+ } else {
+ struct display_timings *modes;
+ struct device_node *display;
+
+ if (!IS_ENABLED(CONFIG_OFDEVICE) || !hw_dev->device_node)
+ return -EINVAL;
+
+ display = of_parse_phandle(hw_dev->device_node, "display", 0);
+ if (!display) {
+ dev_err(hw_dev, "no display phandle\n");
+ return -EINVAL;
+ }
+
+ modes = of_get_display_timings(display);
+ if (IS_ERR(modes)) {
+ dev_err(hw_dev, "unable to parse display timings\n");
+ return PTR_ERR(modes);
+ }
+
+ fbi.info.modes.modes = modes->modes;
+ fbi.info.modes.num_modes = modes->num_modes;
+ }
hw_dev->info = stmfb_info;
@@ -519,9 +540,20 @@ static int stmfb_probe(struct device_d *hw_dev)
return 0;
}
+static __maybe_unused struct of_device_id stmfb_compatible[] = {
+ {
+ .compatible = "fsl,imx23-lcdif",
+ }, {
+ .compatible = "fsl,imx28-lcdif",
+ }, {
+ /* sentinel */
+ }
+};
+
static struct driver_d stmfb_driver = {
.name = "stmfb",
.probe = stmfb_probe,
+ .of_compatible = DRV_OF_COMPAT(stmfb_compatible),
};
device_platform_driver(stmfb_driver);
diff --git a/dts/Bindings/clock/silabs,si5351.txt b/dts/Bindings/clock/silabs,si5351.txt
index c40711e8e8..28b28309f5 100644
--- a/dts/Bindings/clock/silabs,si5351.txt
+++ b/dts/Bindings/clock/silabs,si5351.txt
@@ -17,7 +17,8 @@ Required properties:
- #clock-cells: from common clock binding; shall be set to 1.
- clocks: from common clock binding; list of parent clock
handles, shall be xtal reference clock or xtal and clkin for
- si5351c only.
+ si5351c only. Corresponding clock input names are "xtal" and
+ "clkin" respectively.
- #address-cells: shall be set to 1.
- #size-cells: shall be set to 0.
@@ -71,6 +72,7 @@ i2c-master-node {
/* connect xtal input to 25MHz reference */
clocks = <&ref25>;
+ clock-names = "xtal";
/* connect xtal input as source of pll0 and pll1 */
silabs,pll-source = <0 0>, <1 0>;
diff --git a/dts/Bindings/input/touchscreen/tsc2005.txt b/dts/Bindings/input/touchscreen/tsc2005.txt
index 4b641c7bf1..09089a6d69 100644
--- a/dts/Bindings/input/touchscreen/tsc2005.txt
+++ b/dts/Bindings/input/touchscreen/tsc2005.txt
@@ -32,8 +32,8 @@ Example:
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
- touchscreen-max-x = <4096>;
- touchscreen-max-y = <4096>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
diff --git a/dts/Bindings/mtd/m25p80.txt b/dts/Bindings/mtd/jedec,spi-nor.txt
index f20b111b50..2bee68103b 100644
--- a/dts/Bindings/mtd/m25p80.txt
+++ b/dts/Bindings/mtd/jedec,spi-nor.txt
@@ -8,8 +8,8 @@ Required properties:
is not Linux-only, but in case of Linux, see the "m25p_ids"
table in drivers/mtd/devices/m25p80.c for the list of supported
chips.
- Must also include "nor-jedec" for any SPI NOR flash that can be
- identified by the JEDEC READ ID opcode (0x9F).
+ Must also include "jedec,spi-nor" for any SPI NOR flash that can
+ be identified by the JEDEC READ ID opcode (0x9F).
- reg : Chip-Select number
- spi-max-frequency : Maximum frequency of the SPI bus the chip can operate at
@@ -25,7 +25,7 @@ Example:
flash: m25p80@0 {
#address-cells = <1>;
#size-cells = <1>;
- compatible = "spansion,m25p80", "nor-jedec";
+ compatible = "spansion,m25p80", "jedec,spi-nor";
reg = <0>;
spi-max-frequency = <40000000>;
m25p,fast-read;
diff --git a/dts/Bindings/net/cdns-emac.txt b/dts/Bindings/net/cdns-emac.txt
index abd67c13d3..4451ee9732 100644
--- a/dts/Bindings/net/cdns-emac.txt
+++ b/dts/Bindings/net/cdns-emac.txt
@@ -3,7 +3,8 @@
Required properties:
- compatible: Should be "cdns,[<chip>-]{emac}"
Use "cdns,at91rm9200-emac" Atmel at91rm9200 SoC.
- or the generic form: "cdns,emac".
+ Use "cdns,zynq-gem" Xilinx Zynq-7xxx SoC.
+ Or the generic form: "cdns,emac".
- reg: Address and length of the register set for the device
- interrupts: Should contain macb interrupt
- phy-mode: see ethernet.txt file in the same directory.
diff --git a/dts/Bindings/usb/renesas_usbhs.txt b/dts/Bindings/usb/renesas_usbhs.txt
index dc2a18f0b3..ddbe304beb 100644
--- a/dts/Bindings/usb/renesas_usbhs.txt
+++ b/dts/Bindings/usb/renesas_usbhs.txt
@@ -15,10 +15,8 @@ Optional properties:
- phys: phandle + phy specifier pair
- phy-names: must be "usb"
- dmas: Must contain a list of references to DMA specifiers.
- - dma-names : Must contain a list of DMA names:
- - tx0 ... tx<n>
- - rx0 ... rx<n>
- - This <n> means DnFIFO in USBHS module.
+ - dma-names : named "ch%d", where %d is the channel number ranging from zero
+ to the number of channels (DnFIFOs) minus one.
Example:
usbhs: usb@e6590000 {
diff --git a/dts/src/arm/am335x-bone-common.dtsi b/dts/src/arm/am335x-bone-common.dtsi
index c3255e0c90..dbb3f4d2bf 100644
--- a/dts/src/arm/am335x-bone-common.dtsi
+++ b/dts/src/arm/am335x-bone-common.dtsi
@@ -223,6 +223,25 @@
/include/ "tps65217.dtsi"
&tps {
+ /*
+ * Configure pmic to enter OFF-state instead of SLEEP-state ("RTC-only
+ * mode") at poweroff. Most BeagleBone versions do not support RTC-only
+ * mode and risk hardware damage if this mode is entered.
+ *
+ * For details, see linux-omap mailing list May 2015 thread
+ * [PATCH] ARM: dts: am335x-bone* enable pmic-shutdown-controller
+ * In particular, messages:
+ * http://www.spinics.net/lists/linux-omap/msg118585.html
+ * http://www.spinics.net/lists/linux-omap/msg118615.html
+ *
+ * You can override this later with
+ * &tps { /delete-property/ ti,pmic-shutdown-controller; }
+ * if you want to use RTC-only mode and made sure you are not affected
+ * by the hardware problems. (Tip: double-check by performing a current
+ * measurement after shutdown: it should be less than 1 mA.)
+ */
+ ti,pmic-shutdown-controller;
+
regulators {
dcdc1_reg: regulator@0 {
regulator-name = "vdds_dpr";
diff --git a/dts/src/arm/am335x-boneblack.dts b/dts/src/arm/am335x-boneblack.dts
index 5c42d259fa..901739fcb8 100644
--- a/dts/src/arm/am335x-boneblack.dts
+++ b/dts/src/arm/am335x-boneblack.dts
@@ -80,7 +80,3 @@
status = "okay";
};
};
-
-&rtc {
- system-power-controller;
-};
diff --git a/dts/src/arm/am335x-evmsk.dts b/dts/src/arm/am335x-evmsk.dts
index 87fc7a35e8..156d05efcb 100644
--- a/dts/src/arm/am335x-evmsk.dts
+++ b/dts/src/arm/am335x-evmsk.dts
@@ -654,7 +654,7 @@
wlcore: wlcore@2 {
compatible = "ti,wl1271";
reg = <2>;
- interrupt-parent = <&gpio1>;
+ interrupt-parent = <&gpio0>;
interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; /* gpio 31 */
ref-clock-frequency = <38400000>;
};
diff --git a/dts/src/arm/am35xx-clocks.dtsi b/dts/src/arm/am35xx-clocks.dtsi
index 518b8fde88..18cc826e9d 100644
--- a/dts/src/arm/am35xx-clocks.dtsi
+++ b/dts/src/arm/am35xx-clocks.dtsi
@@ -12,7 +12,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <1>;
};
@@ -20,7 +20,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&rmii_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <9>;
};
@@ -28,7 +28,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <2>;
};
@@ -36,7 +36,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&pclk_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <10>;
};
@@ -44,7 +44,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&ipss_ick>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <0>;
};
@@ -52,7 +52,7 @@
#clock-cells = <0>;
compatible = "ti,gate-clock";
clocks = <&sys_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <8>;
};
@@ -60,7 +60,7 @@
#clock-cells = <0>;
compatible = "ti,am35xx-gate-clock";
clocks = <&sys_ck>;
- reg = <0x059c>;
+ reg = <0x032c>;
ti,bit-shift = <3>;
};
};
diff --git a/dts/src/arm/armada-375.dtsi b/dts/src/arm/armada-375.dtsi
index c675257f23..f076ff856d 100644
--- a/dts/src/arm/armada-375.dtsi
+++ b/dts/src/arm/armada-375.dtsi
@@ -69,7 +69,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
refclk: oscillator {
diff --git a/dts/src/arm/armada-38x.dtsi b/dts/src/arm/armada-38x.dtsi
index ed2dd8ba40..218a2acd36 100644
--- a/dts/src/arm/armada-38x.dtsi
+++ b/dts/src/arm/armada-38x.dtsi
@@ -585,7 +585,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
/* 25 MHz reference crystal */
diff --git a/dts/src/arm/armada-39x.dtsi b/dts/src/arm/armada-39x.dtsi
index 0e85fc15ce..ecd1318109 100644
--- a/dts/src/arm/armada-39x.dtsi
+++ b/dts/src/arm/armada-39x.dtsi
@@ -502,7 +502,7 @@
mainpll: mainpll {
compatible = "fixed-clock";
#clock-cells = <0>;
- clock-frequency = <2000000000>;
+ clock-frequency = <1000000000>;
};
};
};
diff --git a/dts/src/arm/armada-xp-linksys-mamba.dts b/dts/src/arm/armada-xp-linksys-mamba.dts
index a2cf2154dc..fdd187c55a 100644
--- a/dts/src/arm/armada-xp-linksys-mamba.dts
+++ b/dts/src/arm/armada-xp-linksys-mamba.dts
@@ -95,6 +95,11 @@
internal-regs {
+ rtc@10300 {
+ /* No crystal connected to the internal RTC */
+ status = "disabled";
+ };
+
/* J10: VCC, NC, RX, NC, TX, GND */
serial@12000 {
status = "okay";
diff --git a/dts/src/arm/dm816x.dtsi b/dts/src/arm/dm816x.dtsi
index de8427be83..289806adb3 100644
--- a/dts/src/arm/dm816x.dtsi
+++ b/dts/src/arm/dm816x.dtsi
@@ -382,7 +382,7 @@
ti,hwmods = "usb_otg_hs";
usb0: usb@47401000 {
- compatible = "ti,musb-am33xx";
+ compatible = "ti,musb-dm816";
reg = <0x47401400 0x400
0x47401000 0x200>;
reg-names = "mc", "control";
@@ -422,7 +422,7 @@
};
usb1: usb@47401800 {
- compatible = "ti,musb-am33xx";
+ compatible = "ti,musb-dm816";
reg = <0x47401c00 0x400
0x47401800 0x200>;
reg-names = "mc", "control";
diff --git a/dts/src/arm/dove-cubox.dts b/dts/src/arm/dove-cubox.dts
index aae7efc09b..e6fa251e17 100644
--- a/dts/src/arm/dove-cubox.dts
+++ b/dts/src/arm/dove-cubox.dts
@@ -87,6 +87,7 @@
/* connect xtal input to 25MHz reference */
clocks = <&ref25>;
+ clock-names = "xtal";
/* connect xtal input as source of pll0 and pll1 */
silabs,pll-source = <0 0>, <1 0>;
diff --git a/dts/src/arm/exynos4412-trats2.dts b/dts/src/arm/exynos4412-trats2.dts
index 173ffa479a..792394dd0f 100644
--- a/dts/src/arm/exynos4412-trats2.dts
+++ b/dts/src/arm/exynos4412-trats2.dts
@@ -736,7 +736,7 @@
display-timings {
timing-0 {
- clock-frequency = <0>;
+ clock-frequency = <57153600>;
hactive = <720>;
vactive = <1280>;
hfront-porch = <5>;
diff --git a/dts/src/arm/exynos5420-peach-pit.dts b/dts/src/arm/exynos5420-peach-pit.dts
index 0788d08fb4..146e71118a 100644
--- a/dts/src/arm/exynos5420-peach-pit.dts
+++ b/dts/src/arm/exynos5420-peach-pit.dts
@@ -711,6 +711,7 @@
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
diff --git a/dts/src/arm/exynos5800-peach-pi.dts b/dts/src/arm/exynos5800-peach-pi.dts
index 412f41d626..02eb8b1537 100644
--- a/dts/src/arm/exynos5800-peach-pi.dts
+++ b/dts/src/arm/exynos5800-peach-pi.dts
@@ -674,6 +674,7 @@
num-slots = <1>;
broken-cd;
cap-sdio-irq;
+ keep-power-in-suspend;
card-detect-delay = <200>;
clock-frequency = <400000000>;
samsung,dw-mshc-ciu-div = <1>;
diff --git a/dts/src/arm/imx27.dtsi b/dts/src/arm/imx27.dtsi
index 6951b66d1a..bc215e4b75 100644
--- a/dts/src/arm/imx27.dtsi
+++ b/dts/src/arm/imx27.dtsi
@@ -533,7 +533,7 @@
fec: ethernet@1002b000 {
compatible = "fsl,imx27-fec";
- reg = <0x1002b000 0x4000>;
+ reg = <0x1002b000 0x1000>;
interrupts = <50>;
clocks = <&clks IMX27_CLK_FEC_IPG_GATE>,
<&clks IMX27_CLK_FEC_AHB_GATE>;
diff --git a/dts/src/arm/omap3-devkit8000.dts b/dts/src/arm/omap3-devkit8000.dts
index 134d3f27a8..921de6605f 100644
--- a/dts/src/arm/omap3-devkit8000.dts
+++ b/dts/src/arm/omap3-devkit8000.dts
@@ -110,6 +110,8 @@
nand@0,0 {
reg = <0 0 4>; /* CS0, offset 0, IO size 4 */
nand-bus-width = <16>;
+ gpmc,device-width = <2>;
+ ti,nand-ecc-opt = "sw";
gpmc,sync-clk-ps = <0>;
gpmc,cs-on-ns = <0>;
diff --git a/dts/src/arm/omap3-n900.dts b/dts/src/arm/omap3-n900.dts
index 5c16145920..5f5e0f3d5b 100644
--- a/dts/src/arm/omap3-n900.dts
+++ b/dts/src/arm/omap3-n900.dts
@@ -832,8 +832,8 @@
touchscreen-fuzz-x = <4>;
touchscreen-fuzz-y = <7>;
touchscreen-fuzz-pressure = <2>;
- touchscreen-max-x = <4096>;
- touchscreen-max-y = <4096>;
+ touchscreen-size-x = <4096>;
+ touchscreen-size-y = <4096>;
touchscreen-max-pressure = <2048>;
ti,x-plate-ohms = <280>;
diff --git a/dts/src/arm/tegra124.dtsi b/dts/src/arm/tegra124.dtsi
index cf01c818b8..13cc7ca5e0 100644
--- a/dts/src/arm/tegra124.dtsi
+++ b/dts/src/arm/tegra124.dtsi
@@ -826,7 +826,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 59>, <&tegra_car 22>;
+ resets = <&tegra_car 22>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
@@ -838,6 +838,7 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
+ nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -862,7 +863,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 22>, <&tegra_car 22>;
+ resets = <&tegra_car 58>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
@@ -874,7 +875,6 @@
nvidia,hssquelch-level = <2>;
nvidia,hsdiscon-level = <5>;
nvidia,xcvr-hsslew = <12>;
- nvidia,has-utmi-pad-registers;
status = "disabled";
};
@@ -899,7 +899,7 @@
<&tegra_car TEGRA124_CLK_PLL_U>,
<&tegra_car TEGRA124_CLK_USBD>;
clock-names = "reg", "pll_u", "utmi-pads";
- resets = <&tegra_car 58>, <&tegra_car 22>;
+ resets = <&tegra_car 59>, <&tegra_car 22>;
reset-names = "usb", "utmi-pads";
nvidia,hssync-start-delay = <0>;
nvidia,idle-wait-delay = <17>;
diff --git a/dts/src/arm/vexpress-v2p-ca15_a7.dts b/dts/src/arm/vexpress-v2p-ca15_a7.dts
index 7a2aeacd62..107395c32d 100644
--- a/dts/src/arm/vexpress-v2p-ca15_a7.dts
+++ b/dts/src/arm/vexpress-v2p-ca15_a7.dts
@@ -191,6 +191,7 @@
compatible = "arm,cortex-a15-pmu";
interrupts = <0 68 4>,
<0 69 4>;
+ interrupt-affinity = <&cpu0>, <&cpu1>;
};
oscclk6a: oscclk6a {
diff --git a/dts/src/arm/vexpress-v2p-ca9.dts b/dts/src/arm/vexpress-v2p-ca9.dts
index 23662b5a5e..d949facba3 100644
--- a/dts/src/arm/vexpress-v2p-ca9.dts
+++ b/dts/src/arm/vexpress-v2p-ca9.dts
@@ -33,28 +33,28 @@
#address-cells = <1>;
#size-cells = <0>;
- cpu@0 {
+ A9_0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <0>;
next-level-cache = <&L2>;
};
- cpu@1 {
+ A9_1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <1>;
next-level-cache = <&L2>;
};
- cpu@2 {
+ A9_2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <2>;
next-level-cache = <&L2>;
};
- cpu@3 {
+ A9_3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a9";
reg = <3>;
@@ -170,6 +170,7 @@
compatible = "arm,pl310-cache";
reg = <0x1e00a000 0x1000>;
interrupts = <0 43 4>;
+ cache-unified;
cache-level = <2>;
arm,data-latency = <1 1 1>;
arm,tag-latency = <1 1 1>;
@@ -181,6 +182,8 @@
<0 61 4>,
<0 62 4>,
<0 63 4>;
+ interrupt-affinity = <&A9_0>, <&A9_1>, <&A9_2>, <&A9_3>;
+
};
dcc {
diff --git a/dts/src/arm/zynq-7000.dtsi b/dts/src/arm/zynq-7000.dtsi
index a5cd2eda3e..9ea54b3dba 100644
--- a/dts/src/arm/zynq-7000.dtsi
+++ b/dts/src/arm/zynq-7000.dtsi
@@ -193,7 +193,7 @@
};
gem0: ethernet@e000b000 {
- compatible = "cdns,gem";
+ compatible = "cdns,zynq-gem";
reg = <0xe000b000 0x1000>;
status = "disabled";
interrupts = <0 22 4>;
@@ -204,7 +204,7 @@
};
gem1: ethernet@e000c000 {
- compatible = "cdns,gem";
+ compatible = "cdns,zynq-gem";
reg = <0xe000c000 0x1000>;
status = "disabled";
interrupts = <0 45 4>;
diff --git a/dts/src/arm64/arm/juno-motherboard.dtsi b/dts/src/arm64/arm/juno-motherboard.dtsi
index c138b95a83..351c95bda8 100644
--- a/dts/src/arm64/arm/juno-motherboard.dtsi
+++ b/dts/src/arm64/arm/juno-motherboard.dtsi
@@ -21,6 +21,20 @@
clock-output-names = "juno_mb:clk25mhz";
};
+ v2m_refclk1mhz: refclk1mhz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <1000000>;
+ clock-output-names = "juno_mb:refclk1mhz";
+ };
+
+ v2m_refclk32khz: refclk32khz {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <32768>;
+ clock-output-names = "juno_mb:refclk32khz";
+ };
+
motherboard {
compatible = "arm,vexpress,v2p-p1", "simple-bus";
#address-cells = <2>; /* SMB chipselect number and offset */
@@ -66,6 +80,15 @@
#size-cells = <1>;
ranges = <0 3 0 0x200000>;
+ v2m_sysctl: sysctl@020000 {
+ compatible = "arm,sp810", "arm,primecell";
+ reg = <0x020000 0x1000>;
+ clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&mb_clk24mhz>;
+ clock-names = "refclk", "timclk", "apb_pclk";
+ #clock-cells = <1>;
+ clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3";
+ };
+
mmci@050000 {
compatible = "arm,pl180", "arm,primecell";
reg = <0x050000 0x1000>;
@@ -106,16 +129,16 @@
compatible = "arm,sp804", "arm,primecell";
reg = <0x110000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
v2m_timer23: timer@120000 {
compatible = "arm,sp804", "arm,primecell";
reg = <0x120000 0x10000>;
interrupts = <9>;
- clocks = <&mb_clk24mhz>, <&soc_smc50mhz>;
- clock-names = "timclken1", "apb_pclk";
+ clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&mb_clk24mhz>;
+ clock-names = "timclken1", "timclken2", "apb_pclk";
};
rtc@170000 {
diff --git a/dts/src/arm64/mediatek/mt8173-evb.dts b/dts/src/arm64/mediatek/mt8173-evb.dts
index 43d54017b7..d0ab012fa3 100644
--- a/dts/src/arm64/mediatek/mt8173-evb.dts
+++ b/dts/src/arm64/mediatek/mt8173-evb.dts
@@ -16,7 +16,8 @@
#include "mt8173.dtsi"
/ {
- model = "mediatek,mt8173-evb";
+ model = "MediaTek MT8173 evaluation board";
+ compatible = "mediatek,mt8173-evb", "mediatek,mt8173";
aliases {
serial0 = &uart0;
diff --git a/fs/cramfs/cramfs.c b/fs/cramfs/cramfs.c
index fb927149e7..97f028a3ec 100644
--- a/fs/cramfs/cramfs.c
+++ b/fs/cramfs/cramfs.c
@@ -481,4 +481,3 @@ static int cramfs_init(void)
}
device_initcall(cramfs_init);
-
diff --git a/fs/fat/fat.c b/fs/fat/fat.c
index 6d7d262f32..ece937d443 100644
--- a/fs/fat/fat.c
+++ b/fs/fat/fat.c
@@ -434,4 +434,3 @@ static int fat_init(void)
}
coredevice_initcall(fat_init);
-
diff --git a/fs/ramfs.c b/fs/ramfs.c
index fe5eb89824..716f40f5ba 100644
--- a/fs/ramfs.c
+++ b/fs/ramfs.c
@@ -644,4 +644,3 @@ static int ramfs_init(void)
}
coredevice_initcall(ramfs_init);
-
diff --git a/fs/tftp.c b/fs/tftp.c
index 72e4983a01..0de215e5e9 100644
--- a/fs/tftp.c
+++ b/fs/tftp.c
@@ -253,27 +253,24 @@ static void tftp_timer_reset(struct file_priv *priv)
priv->progress_timeout = priv->resend_timeout = get_time_ns();
}
-static void tftp_handler(void *ctx, char *packet, unsigned len)
+static void tftp_recv(struct file_priv *priv,
+ uint8_t *pkt, unsigned len, uint16_t uh_sport)
{
- struct file_priv *priv = ctx;
- uint16_t proto;
- uint16_t *s;
- char *pkt = net_eth_to_udp_payload(packet);
- struct udphdr *udp = net_eth_to_udphdr(packet);
+ uint16_t opcode;
- len = net_eth_to_udplen(packet);
- if (len < 2)
+ /* according to RFC1350 minimal tftp packet length is 4 bytes */
+ if (len < 4)
return;
- len -= 2;
+ opcode = ntohs(*(uint16_t *)pkt);
- s = (uint16_t *)pkt;
- proto = *s++;
- pkt = (unsigned char *)s;
+ /* skip tftp opcode 2-byte field */
+ len -= 2;
+ pkt += 2;
- debug("%s: proto 0x%04x\n", __func__, proto);
+ debug("%s: opcode 0x%04x\n", __func__, opcode);
- switch (ntohs(proto)) {
+ switch (opcode) {
case TFTP_RRQ:
case TFTP_WRQ:
default:
@@ -296,14 +293,14 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
priv->state = STATE_DONE;
break;
}
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
+ priv->tftp_con->udp->uh_dport = uh_sport;
priv->state = STATE_WDATA;
break;
case TFTP_OACK:
tftp_parse_oack(priv, pkt, len);
- priv->server_port = ntohs(udp->uh_sport);
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
+ priv->server_port = ntohs(uh_sport);
+ priv->tftp_con->udp->uh_dport = uh_sport;
if (priv->push) {
/* send first block */
@@ -318,16 +315,14 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
break;
case TFTP_DATA:
- if (len < 2)
- return;
len -= 2;
priv->block = ntohs(*(uint16_t *)pkt);
if (priv->state == STATE_RRQ || priv->state == STATE_OACK) {
/* first block received */
priv->state = STATE_RDATA;
- priv->tftp_con->udp->uh_dport = udp->uh_sport;
- priv->server_port = ntohs(udp->uh_sport);
+ priv->tftp_con->udp->uh_dport = uh_sport;
+ priv->server_port = ntohs(uh_sport);
priv->last_block = 0;
if (priv->block != 1) { /* Assertion */
@@ -376,6 +371,16 @@ static void tftp_handler(void *ctx, char *packet, unsigned len)
}
}
+static void tftp_handler(void *ctx, char *packet, unsigned len)
+{
+ struct file_priv *priv = ctx;
+ char *pkt = net_eth_to_udp_payload(packet);
+ struct udphdr *udp = net_eth_to_udphdr(packet);
+
+ (void)len;
+ tftp_recv(priv, pkt, net_eth_to_udplen(packet), udp->uh_sport);
+}
+
static struct file_priv *tftp_do_open(struct device_d *dev,
int accmode, const char *filename)
{
diff --git a/images/Makefile b/images/Makefile
index 587cb2651f..a5f589b303 100644
--- a/images/Makefile
+++ b/images/Makefile
@@ -75,6 +75,8 @@ quiet_cmd_pblx ?= PBLX $@
$(obj)/%.pblx: $(obj)/%.pblb $(obj)/barebox.z FORCE
$(call if_changed,pblx,$(@F))
+ $(call cmd,check_file_size,$@,$(CONFIG_BAREBOX_MAX_PBLX_SIZE))
+
$(obj)/%.s: $(obj)/% FORCE
$(call if_changed,disasm)
@@ -105,6 +107,7 @@ include $(srctree)/images/Makefile.imx
include $(srctree)/images/Makefile.imxhabv4
include $(srctree)/images/Makefile.mvebu
include $(srctree)/images/Makefile.mxs
+include $(srctree)/images/Makefile.omap3
include $(srctree)/images/Makefile.rockchip
include $(srctree)/images/Makefile.socfpga
include $(srctree)/images/Makefile.tegra
diff --git a/images/Makefile.am33xx b/images/Makefile.am33xx
index eae2a6a6e1..657aeb0e28 100644
--- a/images/Makefile.am33xx
+++ b/images/Makefile.am33xx
@@ -7,13 +7,23 @@ quiet_cmd_mlo_image = MLO $@
$(obj)/%.mlo: $(obj)/% FORCE
$(call if_changed,mlo_image)
+# %.mlospi - convert MLO image for SPI loading
+# ----------------------------------------------------------------
+quiet_cmd_mlo_spi_image = SPI-IMG $@
+ cmd_mlo_spi_image = scripts/mk-omap-image -s -a 0x402f0400 $<.mlo > $@
+
+$(obj)/%.mlospi: $(obj)/% $(obj)/%.mlo FORCE
+ $(call if_changed,mlo_spi_image)
+
pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sdram
FILE_barebox-am33xx-afi-gf.img = start_am33xx_afi_gf_sdram.pblx
am33xx-barebox-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf.img
pblx-$(CONFIG_MACH_AFI_GF) += start_am33xx_afi_gf_sram
FILE_barebox-am33xx-afi-gf-mlo.img = start_am33xx_afi_gf_sram.pblx.mlo
+FILE_barebox-am33xx-afi-gf-mlo.spi.img = start_am33xx_afi_gf_sram.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf-mlo.img
+am33xx-mlospi-$(CONFIG_MACH_AFI_GF) += barebox-am33xx-afi-gf-mlo.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sdram
FILE_barebox-am33xx-phytec-phycore.img = start_am33xx_phytec_phycore_sdram.pblx
@@ -25,19 +35,27 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_256mb
FILE_barebox-am33xx-phytec-phycore-mlo-256mb.img = start_am33xx_phytec_phycore_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-256mb.spi.img = start_am33xx_phytec_phycore_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_128mb
FILE_barebox-am33xx-phytec-phycore-mlo-128mb.img = start_am33xx_phytec_phycore_sram_128mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-128mb.spi.img = start_am33xx_phytec_phycore_sram_128mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-128mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-128mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_512mb
FILE_barebox-am33xx-phytec-phycore-mlo-512mb.img = start_am33xx_phytec_phycore_sram_512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-512mb.spi.img = start_am33xx_phytec_phycore_sram_512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycore_sram_2x512mb
FILE_barebox-am33xx-phytec-phycore-mlo-2x512mb.img = start_am33xx_phytec_phycore_sram_2x512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycore-mlo-2x512mb.spi.img = start_am33xx_phytec_phycore_sram_2x512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-2x512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycore-mlo-2x512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sdram
FILE_barebox-am33xx-phytec-phyflex.img = start_am33xx_phytec_phyflex_sdram.pblx
@@ -45,11 +63,15 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sram_256mb
FILE_barebox-am33xx-phytec-phyflex-mlo-256mb.img = start_am33xx_phytec_phyflex_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phyflex-mlo-256mb.spi.img = start_am33xx_phytec_phyflex_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phyflex_sram_512mb
FILE_barebox-am33xx-phytec-phyflex-mlo-512mb.img = start_am33xx_phytec_phyflex_sram_512mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phyflex-mlo-512mb.spi.img = start_am33xx_phytec_phyflex_sram_512mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-512mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phyflex-mlo-512mb.spi.img
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycard_sdram
FILE_barebox-am33xx-phytec-phycard.img = start_am33xx_phytec_phycard_sdram.pblx
@@ -57,7 +79,9 @@ am33xx-barebox-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard
pblx-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += start_am33xx_phytec_phycard_sram_256mb
FILE_barebox-am33xx-phytec-phycard-mlo-256mb.img = start_am33xx_phytec_phycard_sram_256mb.pblx.mlo
+FILE_barebox-am33xx-phytec-phycard-mlo-256mb.spi.img = start_am33xx_phytec_phycard_sram_256mb.pblx.mlospi
am33xx-mlo-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard-mlo-256mb.img
+am33xx-mlospi-$(CONFIG_MACH_PHYTEC_SOM_AM335X) += barebox-am33xx-phytec-phycard-mlo-256mb.spi.img
pblx-$(CONFIG_MACH_BEAGLEBONE) += start_am33xx_beaglebone_sdram
FILE_barebox-am33xx-beaglebone.img = start_am33xx_beaglebone_sdram.pblx
@@ -72,3 +96,7 @@ image-y += $(am33xx-mlo-y)
else
image-y += $(am33xx-barebox-y)
endif
+
+ifdef CONFIG_OMAP_BUILD_SPI
+image-y += $(am33xx-mlospi-y)
+endif
diff --git a/images/Makefile.omap3 b/images/Makefile.omap3
new file mode 100644
index 0000000000..694ec30836
--- /dev/null
+++ b/images/Makefile.omap3
@@ -0,0 +1,19 @@
+# %.mlo - convert into mlo image
+# ----------------------------------------------------------------
+quiet_cmd_omap3_mlo_image = MLO $@
+ cmd_omap3_mlo_image = scripts/omap_signGP -o $@ -l 0x40200000 -c $<
+
+$(obj)/%.omap3_mlo: $(obj)/% FORCE
+ $(call if_changed,omap3_mlo_image)
+
+pblx-$(CONFIG_MACH_BEAGLE) += start_omap3_beagleboard_sdram start_omap3_beagleboard_sram
+FILE_barebox-beagleboard.img = start_omap3_beagleboard_sdram.pblx
+omap3-barebox-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard.img
+FILE_barebox-beagleboard-mlo.img = start_omap3_beagleboard_sram.pblx.omap3_mlo
+omap3-mlo-$(CONFIG_MACH_BEAGLE) += barebox-beagleboard-mlo.img
+
+ifdef CONFIG_OMAP_BUILD_IFT
+image-y += $(omap3-mlo-y)
+else
+image-y += $(omap3-barebox-y)
+endif
diff --git a/include/bbu.h b/include/bbu.h
index 4a3d35e7ce..7277911718 100644
--- a/include/bbu.h
+++ b/include/bbu.h
@@ -4,6 +4,7 @@
#include <asm-generic/errno.h>
#include <linux/list.h>
#include <linux/types.h>
+#include <filetype.h>
struct bbu_data {
#define BBU_FLAG_FORCE (1 << 0)
@@ -41,6 +42,9 @@ void bbu_handlers_list(void);
int bbu_register_handler(struct bbu_handler *);
+int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype);
+
#else
static inline int bbu_register_handler(struct bbu_handler *unused)
@@ -48,6 +52,25 @@ static inline int bbu_register_handler(struct bbu_handler *unused)
return -EINVAL;
}
+static inline int bbu_register_std_file_update(const char *name, unsigned long flags,
+ char *devicefile, enum filetype imagetype)
+{
+ return -ENOSYS;
+}
+#endif
+
+#if defined(CONFIG_BAREBOX_UPDATE_IMX_NAND_FCB)
+int imx6_bbu_nand_register_handler(const char *name, unsigned long flags);
+int imx28_bbu_nand_register_handler(const char *name, unsigned long flags);
+#else
+static inline int imx6_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ return -ENOSYS;
+}
+static inline int imx28_bbu_nand_register_handler(const char *name, unsigned long flags)
+{
+ return -ENOSYS;
+}
#endif
#endif /* __INCLUDE_BBU_H */
diff --git a/include/blspec.h b/include/blspec.h
index afac5ed7ba..e22e9be11d 100644
--- a/include/blspec.h
+++ b/include/blspec.h
@@ -35,6 +35,7 @@ int blspec_boot_devicename(const char *devname, int verbose, int dryrun);
int blspec_scan_devices(struct blspec *blspec);
+int blspec_scan_device(struct blspec *blspec, struct device_d *dev);
int blspec_scan_devicename(struct blspec *blspec, const char *devname);
int blspec_scan_directory(struct blspec *blspec, const char *root);
diff --git a/include/digest.h b/include/digest.h
index 7c6711b32a..3a9d305963 100644
--- a/include/digest.h
+++ b/include/digest.h
@@ -59,6 +59,7 @@ struct digest {
/*
* digest functions
*/
+#ifdef CONFIG_DIGEST
int digest_algo_register(struct digest_algo *d);
void digest_algo_unregister(struct digest_algo *d);
void digest_algo_prints(const char *prefix);
@@ -76,6 +77,16 @@ int digest_file(struct digest *d, const char *filename,
int digest_file_by_name(const char *algo, const char *filename,
unsigned char *hash,
const unsigned char *sig);
+#else
+static inline struct digest *digest_alloc(const char *name)
+{
+ return NULL;
+}
+
+static inline void digest_free(struct digest *d)
+{
+}
+#endif
static inline int digest_init(struct digest *d)
{
diff --git a/include/filetype.h b/include/filetype.h
index cca4dad7f3..e452b7ac9d 100644
--- a/include/filetype.h
+++ b/include/filetype.h
@@ -34,6 +34,7 @@ enum filetype {
filetype_ch_image_be,
filetype_exe,
filetype_xz_compressed,
+ filetype_mxs_bootstream,
filetype_max,
};
diff --git a/include/linux/bitops.h b/include/linux/bitops.h
index be5fd38bd5..f3a740c461 100644
--- a/include/linux/bitops.h
+++ b/include/linux/bitops.h
@@ -54,7 +54,7 @@ extern unsigned long __sw_hweight64(__u64 w);
(bit) < (size); \
(bit) = find_next_zero_bit((addr), (size), (bit) + 1))
-static __inline__ int get_bitmask_order(unsigned int count)
+static inline int get_bitmask_order(unsigned int count)
{
int order;
@@ -62,7 +62,7 @@ static __inline__ int get_bitmask_order(unsigned int count)
return order; /* We could be slightly more clever with -1 here... */
}
-static __inline__ int get_count_order(unsigned int count)
+static inline int get_count_order(unsigned int count)
{
int order;
diff --git a/include/linux/mtd/concat.h b/include/linux/mtd/concat.h
new file mode 100644
index 0000000000..ccdbe93a90
--- /dev/null
+++ b/include/linux/mtd/concat.h
@@ -0,0 +1,34 @@
+/*
+ * MTD device concatenation layer definitions
+ *
+ * Copyright © 2002 Robert Kaiser <rkaiser@sysgo.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ */
+
+#ifndef MTD_CONCAT_H
+#define MTD_CONCAT_H
+
+
+struct mtd_info *mtd_concat_create(
+ struct mtd_info *subdev[], /* subdevices to concatenate */
+ int num_devs, /* number of subdevices */
+ const char *name); /* name for the new device */
+
+void mtd_concat_destroy(struct mtd_info *mtd);
+
+#endif
+
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 33f1fd512d..7e828bc98f 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -270,7 +270,7 @@ static inline uint32_t mtd_div_by_wb(uint64_t sz, struct mtd_info *mtd)
/* Kernel-side ioctl definitions */
-extern int add_mtd_device(struct mtd_info *mtd, char *devname, int device_id);
+extern int add_mtd_device(struct mtd_info *mtd, const char *devname, int device_id);
extern int del_mtd_device (struct mtd_info *mtd);
extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
diff --git a/include/net.h b/include/net.h
index 364011b20f..b93e264f54 100644
--- a/include/net.h
+++ b/include/net.h
@@ -42,7 +42,7 @@ struct eth_device {
int (*recv) (struct eth_device*);
void (*halt) (struct eth_device*);
int (*get_ethaddr) (struct eth_device*, u8 adr[6]);
- int (*set_ethaddr) (struct eth_device*, u8 adr[6]);
+ int (*set_ethaddr) (struct eth_device*, const unsigned char *adr);
struct eth_device *next;
void *priv;
@@ -60,6 +60,7 @@ struct eth_device {
IPaddr_t serverip;
IPaddr_t netmask;
IPaddr_t gateway;
+ char ethaddr_param[6];
char ethaddr[6];
};
@@ -67,6 +68,7 @@ struct eth_device {
int eth_register(struct eth_device* dev); /* Register network device */
void eth_unregister(struct eth_device* dev); /* Unregister network device */
+int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr);
int eth_send(struct eth_device *edev, void *packet, int length); /* Send a packet */
int eth_rx(void); /* Check for received packets */
diff --git a/include/of.h b/include/of.h
index c02f5f49ab..1db210b38a 100644
--- a/include/of.h
+++ b/include/of.h
@@ -224,6 +224,8 @@ extern int of_modalias_node(struct device_node *node, char *modalias, int len);
extern struct device_node *of_get_root_node(void);
extern int of_set_root_node(struct device_node *node);
+extern struct device_d *of_platform_device_create(struct device_node *np,
+ struct device_d *parent);
extern int of_platform_populate(struct device_node *root,
const struct of_device_id *matches,
struct device_d *parent);
diff --git a/include/pwm.h b/include/pwm.h
index 59d86d497d..911c760839 100644
--- a/include/pwm.h
+++ b/include/pwm.h
@@ -57,12 +57,14 @@ struct pwm_ops {
/**
* struct pwm_chip - abstract a PWM
+ * @id: The id of this pwm
* @devname: unique identifier for this pwm
* @ops: The callbacks for this PWM
* @duty_ns: The duty cycle of the PWM, in nano-seconds
* @period_ns: The period of the PWM, in nano-seconds
*/
struct pwm_chip {
+ int id;
const char *devname;
struct pwm_ops *ops;
int duty_ns;
diff --git a/include/video/backlight.h b/include/video/backlight.h
new file mode 100644
index 0000000000..56e0341ea4
--- /dev/null
+++ b/include/video/backlight.h
@@ -0,0 +1,20 @@
+#ifndef __VIDEO_BACKLIGHT_H
+#define __VIDEO_BACKLIGHT_H
+
+struct backlight_device {
+ int brightness;
+ int brightness_cur;
+ int brightness_max;
+ int brightness_default;
+ int (*brightness_set)(struct backlight_device *, int brightness);
+ struct list_head list;
+ struct device_d dev;
+ struct device_node *node;
+};
+
+int backlight_set_brightness(struct backlight_device *, int brightness);
+int backlight_set_brightness_default(struct backlight_device *);
+int backlight_register(struct backlight_device *);
+struct backlight_device *of_backlight_find(struct device_node *node);
+
+#endif /* __VIDEO_BACKLIGHT_H */
diff --git a/include/xfuncs.h b/include/xfuncs.h
index 8efc99dbc4..940a1d67ed 100644
--- a/include/xfuncs.h
+++ b/include/xfuncs.h
@@ -7,6 +7,7 @@ void *xmalloc(size_t size);
void *xrealloc(void *ptr, size_t size);
void *xzalloc(size_t size);
char *xstrdup(const char *s);
+char *xstrndup(const char *s, size_t size);
void* xmemalign(size_t alignment, size_t bytes);
void* xmemdup(const void *orig, size_t size);
diff --git a/lib/fnmatch.c b/lib/fnmatch.c
index 1a5e8d0d3d..0ab530d3b1 100644
--- a/lib/fnmatch.c
+++ b/lib/fnmatch.c
@@ -218,4 +218,3 @@ int fnmatch(const char *pattern, const char *string, int flags)
# undef FOLD
}
-
diff --git a/lib/gui/bmp.c b/lib/gui/bmp.c
index 6943a1c8e0..d457c01d84 100644
--- a/lib/gui/bmp.c
+++ b/lib/gui/bmp.c
@@ -7,6 +7,7 @@
#include <gui/graphic_utils.h>
#include <init.h>
#include <gui/image_renderer.h>
+#include <asm/unaligned.h>
struct image *bmp_open(char *inbuf, int insize)
{
@@ -19,9 +20,9 @@ struct image *bmp_open(char *inbuf, int insize)
}
img->data = inbuf;
- img->height = le32_to_cpu(bmp->header.height);
- img->width = le32_to_cpu(bmp->header.width);
- img->bits_per_pixel = le16_to_cpu(bmp->header.bit_count);
+ img->height = get_unaligned_le32(&bmp->header.height);
+ img->width = get_unaligned_le32(&bmp->header.width);
+ img->bits_per_pixel = get_unaligned_le16(&bmp->header.bit_count);
pr_debug("bmp: %d x %d x %d data@0x%p\n", img->width, img->height,
img->bits_per_pixel, img->data);
@@ -76,7 +77,7 @@ static int bmp_renderer(struct screen *sc, struct surface *s, struct image *img)
for (y = 0; y < height; y++) {
image = (char *)bmp +
- le32_to_cpu(bmp->header.data_offset);
+ get_unaligned_le32(&bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + (y + starty) * sc->info.line_length +
startx * (sc->info.bits_per_pixel >> 3);
@@ -98,7 +99,7 @@ static int bmp_renderer(struct screen *sc, struct surface *s, struct image *img)
for (y = 0; y < height; y++) {
image = (char *)bmp +
- le32_to_cpu(bmp->header.data_offset);
+ get_unaligned_le32(&bmp->header.data_offset);
image += (img->height - y - 1) * img->width * (bits_per_pixel >> 3);
adr = buf + (y + starty) * sc->info.line_length +
startx * (sc->info.bits_per_pixel >> 3);
diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c
index dd29389baa..9bef99a7b0 100644
--- a/lib/gui/image_renderer.c
+++ b/lib/gui/image_renderer.c
@@ -37,10 +37,10 @@ struct image *image_renderer_open(const char* file)
struct image *img;
int ret;
- data = read_file(file, &size);
- if (!data) {
- printf("unable to read %s\n", file);
- return ERR_PTR(-ENOMEM);
+ ret = read_file_2(file, &size, &data, FILESIZE_MAX);
+ if (ret) {
+ printf("unable to read %s: %s\n", file, strerror(-ret));
+ return ERR_PTR(ret);
}
ir = get_renderer(data, size);
diff --git a/lib/libfile.c b/lib/libfile.c
index 8acff042c8..ba03700aba 100644
--- a/lib/libfile.c
+++ b/lib/libfile.c
@@ -184,8 +184,8 @@ again:
if (read_size < s.st_size)
return -EFBIG;
- else
- return 0;
+
+ return 0;
err_out1:
close(fd);
diff --git a/lib/lzo/lzo1x_decompress_safe.c b/lib/lzo/lzo1x_decompress_safe.c
index 3c0f512634..6e8c822b3a 100644
--- a/lib/lzo/lzo1x_decompress_safe.c
+++ b/lib/lzo/lzo1x_decompress_safe.c
@@ -258,4 +258,3 @@ lookbehind_overrun:
}
EXPORT_SYMBOL(lzo1x_decompress_safe);
-
diff --git a/lib/parameter.c b/lib/parameter.c
index 865ad9f431..b23885958b 100644
--- a/lib/parameter.c
+++ b/lib/parameter.c
@@ -122,6 +122,14 @@ static const char *param_get_generic(struct device_d *dev, struct param_d *p)
return p->value ? p->value : "";
}
+static int compare(struct list_head *a, struct list_head *b)
+{
+ char *na = (char*)list_entry(a, struct param_d, list)->name;
+ char *nb = (char*)list_entry(b, struct param_d, list)->name;
+
+ return strcmp(na, nb);
+}
+
static int __dev_add_param(struct param_d *param, struct device_d *dev, const char *name,
int (*set)(struct device_d *dev, struct param_d *p, const char *val),
const char *(*get)(struct device_d *dev, struct param_d *p),
@@ -145,7 +153,7 @@ static int __dev_add_param(struct param_d *param, struct device_d *dev, const ch
param->flags = flags;
param->dev = dev;
- list_add_tail(&param->list, &dev->parameters);
+ list_add_sort(&param->list, &dev->parameters, compare);
return 0;
}
@@ -225,7 +233,7 @@ static int param_string_set(struct device_d *dev, struct param_d *p, const char
char *value_save = *ps->value;
if (!val)
- return -EINVAL;
+ val = "";
*ps->value = xstrdup(val);
@@ -575,7 +583,6 @@ struct param_d *dev_add_param_llint_ro(struct device_d *dev, const char *name,
return &piro->param;
}
-#ifdef CONFIG_NET
struct param_ip {
struct param_d param;
IPaddr_t *ip;
@@ -739,7 +746,6 @@ struct param_d *dev_add_param_mac(struct device_d *dev, const char *name,
return &pm->param;
}
-#endif
/**
* dev_remove_param - remove a parameter from a device and free its
diff --git a/lib/random.c b/lib/random.c
index 14c7da119d..210fea9946 100644
--- a/lib/random.c
+++ b/lib/random.c
@@ -25,4 +25,3 @@ void get_random_bytes(void *_buf, int len)
while (len--)
*buf++ = rand() % 256;
}
-
diff --git a/lib/strtox.c b/lib/strtox.c
index 882865b45d..cfe61240cc 100644
--- a/lib/strtox.c
+++ b/lib/strtox.c
@@ -65,4 +65,3 @@ unsigned long long simple_strtoull (const char *cp, char **endp, unsigned int ba
return result;
}
EXPORT_SYMBOL(simple_strtoull);
-
diff --git a/lib/xfuncs.c b/lib/xfuncs.c
index 0e78b670a5..f0219c43a5 100644
--- a/lib/xfuncs.c
+++ b/lib/xfuncs.c
@@ -63,6 +63,28 @@ char *xstrdup(const char *s)
}
EXPORT_SYMBOL(xstrdup);
+char *xstrndup(const char *s, size_t n)
+{
+ int m;
+ char *t;
+
+ /* We can just xmalloc(n+1) and strncpy into it, */
+ /* but think about xstrndup("abc", 10000) wastage! */
+ m = n;
+ t = (char*) s;
+ while (m) {
+ if (!*t) break;
+ m--;
+ t++;
+ }
+ n -= m;
+ t = xmalloc(n + 1);
+ t[n] = '\0';
+
+ return memcpy(t, s, n);
+}
+EXPORT_SYMBOL(xstrndup);
+
void* xmemalign(size_t alignment, size_t bytes)
{
void *p = memalign(alignment, bytes);
diff --git a/net/Makefile b/net/Makefile
index 58bf143676..8d564e7299 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -1,3 +1,4 @@
+obj-y += lib.o
obj-$(CONFIG_NET) += eth.o
obj-$(CONFIG_NET) += net.o
obj-$(CONFIG_NET_NFS) += nfs.o
diff --git a/net/dns.c b/net/dns.c
index 0a8ce8b244..0e16ea2c9d 100644
--- a/net/dns.c
+++ b/net/dns.c
@@ -116,9 +116,8 @@ static int dns_send(char *name)
return ret;
}
-static void dns_handler(void *ctx, char *packet, unsigned len)
+static void dns_recv(struct header *header, unsigned len)
{
- struct header *header;
unsigned char *p, *e, *s;
u16 type;
int found, stop, dlen;
@@ -127,7 +126,6 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
debug("%s\n", __func__);
/* We sent 1 query. We want to see more that 1 answer. */
- header = (struct header *)net_eth_to_udp_payload(packet);
if (ntohs(header->nqueries) != 1)
return;
@@ -140,7 +138,7 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
/* Skip host name */
s = &header->data[0];
- e = packet + len;
+ e = ((uint8_t *)header) + len;
for (p = s; p < e && *p != '\0'; p++)
continue;
@@ -194,6 +192,13 @@ static void dns_handler(void *ctx, char *packet, unsigned len)
}
}
+static void dns_handler(void *ctx, char *packet, unsigned len)
+{
+ (void)ctx;
+ dns_recv((struct header *)net_eth_to_udp_payload(packet),
+ net_eth_to_udplen(packet));
+}
+
IPaddr_t resolv(char *host)
{
IPaddr_t ip;
diff --git a/net/eth.c b/net/eth.c
index 0c1ff73e4c..a090961bca 100644
--- a/net/eth.c
+++ b/net/eth.c
@@ -42,15 +42,27 @@ struct eth_ethaddr {
static LIST_HEAD(ethaddr_list);
+int eth_set_ethaddr(struct eth_device *edev, const char *ethaddr)
+{
+ int ret;
+
+ ret = edev->set_ethaddr(edev, ethaddr);
+ if (ret)
+ return ret;
+
+ memcpy(edev->ethaddr, ethaddr, ETH_ALEN);
+
+ return 0;
+}
+
static void register_preset_mac_address(struct eth_device *edev, const char *ethaddr)
{
unsigned char ethaddr_str[sizeof("xx:xx:xx:xx:xx:xx")];
- ethaddr_to_string(ethaddr, ethaddr_str);
-
if (is_valid_ether_addr(ethaddr)) {
+ ethaddr_to_string(ethaddr, ethaddr_str);
dev_info(&edev->dev, "got preset MAC address: %s\n", ethaddr_str);
- dev_set_param(&edev->dev, "ethaddr", ethaddr_str);
+ eth_set_ethaddr(edev, ethaddr);
}
}
@@ -261,13 +273,11 @@ int eth_rx(void)
return 0;
}
-static int eth_set_ethaddr(struct param_d *param, void *priv)
+static int eth_param_set_ethaddr(struct param_d *param, void *priv)
{
struct eth_device *edev = priv;
- edev->set_ethaddr(edev, edev->ethaddr);
-
- return 0;
+ return eth_set_ethaddr(edev, edev->ethaddr_param);
}
#ifdef CONFIG_OFTREE
@@ -350,7 +360,8 @@ int eth_register(struct eth_device *edev)
dev_add_param_ip(dev, "serverip", NULL, NULL, &edev->serverip, edev);
dev_add_param_ip(dev, "gateway", NULL, NULL, &edev->gateway, edev);
dev_add_param_ip(dev, "netmask", NULL, NULL, &edev->netmask, edev);
- dev_add_param_mac(dev, "ethaddr", eth_set_ethaddr, NULL, edev->ethaddr, edev);
+ dev_add_param_mac(dev, "ethaddr", eth_param_set_ethaddr, NULL,
+ edev->ethaddr_param, edev);
if (edev->init)
edev->init(edev);
diff --git a/net/lib.c b/net/lib.c
new file mode 100644
index 0000000000..f1c60c9a74
--- /dev/null
+++ b/net/lib.c
@@ -0,0 +1,109 @@
+/*
+ * net.c - barebox networking support
+ *
+ * Copyright (c) 2015 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
+ *
+ * based on U-Boot (LiMon) code
+ *
+ * Copyright 1994 - 2000 Neil Russell.
+ * Copyright 2000 Roland Borde
+ * Copyright 2000 Paolo Scaffardi
+ * Copyright 2000-2002 Wolfgang Denk, wd@denx.de
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <common.h>
+#include <net.h>
+#include <linux/ctype.h>
+
+int string_to_ethaddr(const char *str, u8 enetaddr[6])
+{
+ int reg;
+ char *e;
+
+ if (!str || strlen(str) != 17) {
+ memset(enetaddr, 0, 6);
+ return -EINVAL;
+ }
+
+ if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
+ str[11] != ':' || str[14] != ':')
+ return -EINVAL;
+
+ for (reg = 0; reg < 6; ++reg) {
+ enetaddr[reg] = simple_strtoul(str, &e, 16);
+ str = e + 1;
+ }
+
+ return 0;
+}
+
+void ethaddr_to_string(const u8 enetaddr[6], char *str)
+{
+ sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
+ enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
+ enetaddr[4], enetaddr[5]);
+}
+
+void print_IPaddr(IPaddr_t x)
+{
+ puts(ip_to_string(x));
+}
+
+char *ip_to_string(IPaddr_t x)
+{
+ static char s[sizeof("xxx.xxx.xxx.xxx")];
+
+ x = ntohl(x);
+ sprintf(s, "%d.%d.%d.%d",
+ (int) ((x >> 24) & 0xff),
+ (int) ((x >> 16) & 0xff),
+ (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
+ );
+
+ return s;
+}
+
+int string_to_ip(const char *s, IPaddr_t *ip)
+{
+ IPaddr_t addr = 0;
+ char *e;
+ int i;
+
+ if (!s)
+ return -EINVAL;
+
+ for (i = 0; i < 4; i++) {
+ unsigned long val;
+
+ if (!isdigit(*s))
+ return -EINVAL;
+
+ val = simple_strtoul(s, &e, 10);
+ if (val > 255)
+ return -EINVAL;
+
+ addr = (addr << 8) | val;
+
+ if (*e != '.' && i != 3)
+ return -EINVAL;
+
+ s = e + 1;
+ }
+
+ *ip = htonl(addr);
+
+ return 0;
+}
diff --git a/net/net.c b/net/net.c
index 07350ad8fb..e5bd9bbc78 100644
--- a/net/net.c
+++ b/net/net.c
@@ -62,50 +62,6 @@ uint16_t net_checksum(unsigned char *ptr, int len)
return xsum & 0xffff;
}
-char *ip_to_string (IPaddr_t x)
-{
- static char s[sizeof("xxx.xxx.xxx.xxx")];
-
- x = ntohl (x);
- sprintf (s, "%d.%d.%d.%d",
- (int) ((x >> 24) & 0xff),
- (int) ((x >> 16) & 0xff),
- (int) ((x >> 8) & 0xff), (int) ((x >> 0) & 0xff)
- );
- return s;
-}
-
-int string_to_ip(const char *s, IPaddr_t *ip)
-{
- IPaddr_t addr = 0;
- char *e;
- int i;
-
- if (!s)
- return -EINVAL;
-
- for (i = 0; i < 4; i++) {
- unsigned long val;
-
- if (!isdigit(*s))
- return -EINVAL;
-
- val = simple_strtoul(s, &e, 10);
- if (val > 255)
- return -EINVAL;
-
- addr = (addr << 8) | val;
-
- if (*e != '.' && i != 3)
- return -EINVAL;
-
- s = e + 1;
- }
-
- *ip = htonl(addr);
- return 0;
-}
-
IPaddr_t getenv_ip(const char *name)
{
IPaddr_t ip;
@@ -131,40 +87,6 @@ int setenv_ip(const char *name, IPaddr_t ip)
return 0;
}
-void print_IPaddr (IPaddr_t x)
-{
- puts(ip_to_string(x));
-}
-
-int string_to_ethaddr(const char *str, u8 enetaddr[6])
-{
- int reg;
- char *e;
-
- if (!str || strlen(str) != 17) {
- memset(enetaddr, 0, 6);
- return -EINVAL;
- }
-
- if (str[2] != ':' || str[5] != ':' || str[8] != ':' ||
- str[11] != ':' || str[14] != ':')
- return -EINVAL;
-
- for (reg = 0; reg < 6; ++reg) {
- enetaddr[reg] = simple_strtoul (str, &e, 16);
- str = e + 1;
- }
-
- return 0;
-}
-
-void ethaddr_to_string(const u8 enetaddr[6], char *str)
-{
- sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x",
- enetaddr[0], enetaddr[1], enetaddr[2], enetaddr[3],
- enetaddr[4], enetaddr[5]);
-}
-
static unsigned char *arp_ether;
static IPaddr_t arp_wait_ip;
@@ -348,7 +270,7 @@ static struct net_connection *net_new(IPaddr_t dest, rx_handler_f *handler,
random_ether_addr(edev->ethaddr);
ethaddr_to_string(edev->ethaddr, str);
printf("warning: No MAC address set. Using random address %s\n", str);
- dev_set_param(&edev->dev, "ethaddr", str);
+ eth_set_ethaddr(edev, edev->ethaddr);
}
/* If we don't have an ip only broadcast is allowed */
@@ -667,4 +589,3 @@ static int net_init(void)
}
postcore_initcall(net_init);
-
diff --git a/net/nfs.c b/net/nfs.c
index 27533304ea..0a3021994a 100644
--- a/net/nfs.c
+++ b/net/nfs.c
@@ -731,4 +731,3 @@ BAREBOX_CMD_START(nfs)
BAREBOX_CMD_OPTS("FILE [LOCALFILE]")
BAREBOX_CMD_GROUP(CMD_GRP_NET)
BAREBOX_CMD_END
-
diff --git a/scripts/Makefile b/scripts/Makefile
index 74c22136db..a3f6222d08 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -24,6 +24,9 @@ HOSTLOADLIBES_mxsimage = `pkg-config --libs openssl`
HOSTCFLAGS_mxs-usb-loader.o = `pkg-config --cflags libusb-1.0`
HOSTLOADLIBES_mxs-usb-loader = `pkg-config --libs libusb-1.0`
hostprogs-$(CONFIG_ARCH_MXS_USBLOADER) += mxs-usb-loader
+HOSTCFLAGS_omap3-usb-loader.o = `pkg-config --cflags libusb-1.0`
+HOSTLOADLIBES_omap3-usb-loader = `pkg-config --libs libusb-1.0`
+hostprogs-$(CONFIG_OMAP3_USB_LOADER) += omap3-usb-loader
subdir-y += mod
subdir-$(CONFIG_OMAP4_USBBOOT) += omap4_usbboot
diff --git a/scripts/omap3-usb-loader.c b/scripts/omap3-usb-loader.c
new file mode 100644
index 0000000000..edf6043edf
--- /dev/null
+++ b/scripts/omap3-usb-loader.c
@@ -0,0 +1,921 @@
+/*
+ * OMAP Loader, a USB uploader application targeted at OMAP3 processors
+ * Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>
+ * Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*
+ * Reasons for the name change: this is a complete rewrite of
+ * the unversioned omap3_usbload so to lower ambiguity the name was changed.
+ * The GPLv2 license specifies rewrites as derived work.
+ */
+#define PROG_NAME "OMAP Loader"
+#define VERSION "1.0.0"
+
+#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define OMAP_IS_BIG_ENDIAN
+#endif
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#include <arpa/inet.h>
+#endif
+
+#include <unistd.h> /* for usleep and friends */
+#include <getopt.h>
+#include <errno.h>
+#include <libgen.h> /* for basename */
+
+#include <libusb-1.0/libusb.h> /* the main event */
+
+/* Device specific defines (OMAP)
+ * Primary source: http://www.ti.com/lit/pdf/sprugn4
+ * Section 26.4.5 "Peripheral Booting"
+ */
+#define OMAP_BASE_ADDRESS 0x40200000
+#define OMAP_PERIPH_BOOT 0xF0030002
+#define OMAP_VENDOR_ID 0x0451
+#define OMAP_PRODUCT_ID 0xD00E
+/* TODO: dynamically discover these endpoints */
+#define OMAP_USB_BULK_IN 0x81
+#define OMAP_USB_BULK_OUT 0x01
+#define OMAP_ASIC_ID_LEN 69
+
+#ifdef OMAP_IS_BIG_ENDIAN
+#define cpu_to_le32(v) (((v & 0xff) << 24) | ((v & 0xff00) << 8) | \
+ ((v & 0xff0000) >> 8) | ((v & 0xff000000) >> 24))
+#define le32_to_cpu(v) cpu_to_le32(v)
+#else
+#define cpu_to_le32(v) (v)
+#define le32_to_cpu(v) (v)
+#endif
+
+/*
+ * taken from x-loader/drivers/usb/usb.c
+ * All credit to Martin Mueller
+ */
+#define PACK4(a,b,c,d) (((d)<<24) | ((c)<<16) | ((b)<<8) | (a))
+#define USBLOAD_CMD_FILE PACK4('U','S','B','s') /* file size request */
+#define USBLOAD_CMD_FILE_REQ PACK4('U','S','B','f') /* file size resp */
+#define USBLOAD_CMD_JUMP PACK4('U','S','B','j') /* execute code here */
+#define USBLOAD_CMD_ECHO_SZ PACK4('U','S','B','n') /* file size confirm to */
+#define USBLOAD_CMD_REPORT_SZ PACK4('U','S','B','o') /* confirm full file */
+#define USBLOAD_CMD_MESSAGE PACK4('U','S','B','m') /* debug message */
+
+/* USB transfer characteristics */
+#define USB_MAX_WAIT 5000
+#define USB_TIMEOUT 1000
+#define USB_MAX_TIMEOUTS (USB_MAX_WAIT/USB_TIMEOUT)
+
+/* stores the data and attributes of a file to upload in to memory */
+struct file_upload {
+ size_t size;
+ void *data;
+ uint32_t addr;
+ char *path;
+ char *basename;
+};
+
+/* stores all of the arguments read in by getopt in main() */
+struct arg_state {
+ struct file_upload **files;
+ int numfiles;
+ uint32_t jumptarget;
+ uint16_t vendor, product;
+};
+
+static int g_verbose = 0;
+
+static void log_error(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[-] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static void log_info(char *fmt, ...)
+{
+ va_list va;
+
+ va_start(va, fmt);
+ fprintf(stdout, "[+] ");
+ vfprintf(stdout, fmt, va);
+ va_end(va);
+}
+
+static bool omap_usb_read(libusb_device_handle *handle, unsigned char *data,
+ int length, int *actuallength)
+{
+ int ret = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ if (!actuallength)
+ return false;
+
+ while (sizeleft > 0) {
+ int actualread = 0;
+ int readamt = sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_IN, data + iter,
+ readamt, &actualread, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* we got some data, lets cut our losses and stop here */
+ if (iter > 0)
+ break;
+
+ log_error("device timed out while transfering in %d bytes (got %d)\n",
+ length, iter);
+
+ return false;
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualRead on anything but a timeout or success */
+ sizeleft -= actualread;
+ iter += actualread;
+
+ /* stop at the first sign of data */
+ if (iter > 0)
+ break;
+ } else {
+ log_error("fatal transfer error (BULK_IN) for %d bytes (got %d): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ *actuallength = iter;
+
+ return true;
+}
+
+static bool omap_usb_write(libusb_device_handle *handle, void *data, int length)
+{
+ int ret = 0;
+ int numtimeouts = 0;
+ int iter = 0;
+ int sizeleft = length;
+
+ while (sizeleft > 0) {
+ int actualwrite = 0;
+ int writeamt = sizeleft > 512 ? 512 : sizeleft;
+
+ ret = libusb_bulk_transfer(handle, OMAP_USB_BULK_OUT, data + iter,
+ writeamt, &actualwrite, USB_TIMEOUT);
+
+ if (ret == LIBUSB_ERROR_TIMEOUT) {
+ numtimeouts++;
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+
+ /* build in some reliablity */
+ if (numtimeouts > USB_MAX_TIMEOUTS) {
+ log_error("device timed out while transfering out %d bytes (%d made it)\n",
+ length, iter);
+ return false;
+ }
+ } else if (ret == LIBUSB_SUCCESS) {
+ /* we cant trust actualWrite on anything but a timeout or success */
+ sizeleft -= actualwrite;
+ iter += actualwrite;
+ } else {
+ log_error("fatal transfer error (BULK_OUT) for %d bytes (%d made it): %s\n",
+ length, iter, libusb_error_name(ret));
+ return false;
+ }
+ }
+
+ return true;
+}
+
+static unsigned char *omap_usb_get_string(libusb_device_handle *handle, uint8_t idx)
+{
+ unsigned char *data = NULL;
+ int len = 0;
+ int ret = 0;
+
+ if (!handle)
+ return NULL;
+
+ while (true) {
+ if (!len || ret < 0) {
+ len += 256;
+ data = realloc(data, len);
+
+ if (!data)
+ return NULL;
+ }
+
+ ret = libusb_get_string_descriptor_ascii(handle, idx, data, len);
+
+ /* we can still recover... */
+ if (ret < 0) {
+ if (ret == LIBUSB_ERROR_INVALID_PARAM)
+ continue; /* try again with an increased size */
+
+ log_error("failed to lookup string index %hhu: %s\n",
+ idx, libusb_error_name(ret));
+
+ /* unrecoverable */
+ free(data);
+ return NULL;
+ } else {
+ /* we got something! */
+ break;
+ }
+ }
+
+ return data;
+}
+
+uint16_t omap_products[] = {
+ 0xd009,
+ 0xd00f,
+};
+
+static libusb_device_handle *omap_usb_open(libusb_context *ctx, uint16_t vendor, uint16_t product)
+{
+ libusb_device **devlist;
+ libusb_device_handle *handle;
+ struct libusb_device_descriptor desc;
+ ssize_t count, i;
+ int ret;
+
+ log_info("scanning for USB device matching %04hx:%04hx...\n",
+ vendor, product);
+
+ while (1) {
+ if ((count = libusb_get_device_list(ctx, &devlist)) < 0) {
+ log_error("failed to gather USB device list: %s\n",
+ libusb_error_name(count));
+ return NULL;
+ }
+
+ for (i = 0; i < count; i++) {
+ ret = libusb_get_device_descriptor(devlist[i], &desc);
+ if (ret < 0) {
+ log_error("failed to get USB device descriptor: %s\n",
+ libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ if (desc.idVendor != vendor)
+ continue;
+
+ if (product) {
+ if (desc.idProduct != product)
+ continue;
+ goto found;
+ }
+
+ for (i = 0; i < sizeof(omap_products) / sizeof(uint16_t); i++)
+ if (desc.idProduct == omap_products[i]) {
+ product = desc.idProduct;
+ goto found;
+ }
+ }
+
+ libusb_free_device_list(devlist, 1);
+
+ /* nothing found yet. have a 10ms nap */
+ usleep(10000);
+ }
+found:
+ ret = libusb_open(devlist[i], &handle);
+ if (ret < 0) {
+ log_error("failed to open USB device %04hx:%04hx: %s\n",
+ vendor, product, libusb_error_name(ret));
+ libusb_free_device_list(devlist, 1);
+ return NULL;
+ }
+
+ ret = libusb_claim_interface(handle, 0);
+ if (ret) {
+ printf("Claim failed\n");
+ return NULL;
+ }
+
+ /* grab the manufacturer and product strings for printing */
+ unsigned char *mfgstr = omap_usb_get_string(handle, desc.iManufacturer);
+ unsigned char *prodstr = omap_usb_get_string(handle, desc.iProduct);
+
+ log_info("successfully opened %04hx:%04hx (", vendor, product);
+
+ if (mfgstr) {
+ fprintf(stdout, prodstr ? "%s " : "%s", mfgstr);
+ free(mfgstr);
+ }
+
+ if (prodstr) {
+ fprintf(stdout, "%s", prodstr);
+ free(prodstr);
+ }
+
+ fprintf(stdout, ")\n");
+
+ return handle;
+}
+
+static unsigned char *read_file(char *path, size_t *readamt)
+{
+ FILE *fp = fopen(path, "rb");
+
+ if (!fp) {
+ log_error("failed to open file \'%s\': %s\n", path,
+ strerror(errno));
+ return NULL;
+ }
+
+ unsigned char *data = NULL;
+ size_t allocsize = 0;
+ size_t iter = 0;
+
+ while (1) {
+ if (iter >= iter) {
+ allocsize += 1024;
+ data = realloc(data, allocsize);
+ if (!data)
+ return NULL;
+ }
+
+ size_t readsize = allocsize - iter;
+ size_t ret = fread(data + iter, sizeof (unsigned char), readsize, fp);
+
+ iter += ret;
+
+ if (ret != readsize) {
+ if (feof(fp)) {
+ break;
+ } else if (ferror(fp)) {
+ log_error("error file reading file \'%s\': %s\n",
+ path, strerror(errno));
+ free(data);
+ return NULL;
+ }
+ }
+ }
+
+ /* trim the allocation down to size */
+ data = realloc(data, iter);
+ *readamt = iter;
+
+ return data;
+}
+
+static int transfer_first_stage(libusb_device_handle * handle, struct arg_state *args)
+{
+ unsigned char *buffer = NULL;
+ uint32_t cmd = 0;
+ uint32_t filelen = 0;
+ int bufsize = 0x200;
+ int transLen = 0;
+ int i;
+ void *data;
+ uint32_t *dbuf;
+
+ struct file_upload *file = args->files[0];
+
+ /* TODO determine buffer size based on endpoint */
+ buffer = calloc(bufsize, sizeof (unsigned char));
+ filelen = cpu_to_le32(file->size);
+
+ data = file->data;
+ dbuf = data;
+
+ if (le32toh(dbuf[5]) == 0x45534843) {
+ int chsettingssize = 512 + 2 * sizeof(uint32_t);
+
+ log_info("CHSETTINGS image detected. Skipping header\n");
+
+ data += chsettingssize;
+ filelen -= chsettingssize;
+ }
+
+ /* read the ASIC ID */
+ if (!omap_usb_read(handle, buffer, bufsize, &transLen)) {
+ log_error("failed to read ASIC ID from USB connection. "
+ "Check your USB device!\n");
+ goto fail;
+ }
+
+ if (transLen != OMAP_ASIC_ID_LEN) {
+ log_error("got some ASIC ID, but it's not the right length, %d "
+ "(expected %d)\n", transLen, OMAP_ASIC_ID_LEN);
+ goto fail;
+ }
+
+ /* optionally, print some ASIC ID info */
+ if (g_verbose) {
+ char *fields[] =
+ { "Num Subblocks", "Device ID Info", "Reserved",
+ "Ident Data", "Reserved", "CRC (4 bytes)"
+ };
+ int fieldLen[] = { 1, 7, 4, 23, 23, 11 };
+ int field = 0;
+ int nextSep = 0;
+
+ log_info("got ASIC ID - ");
+
+ for (i = 0; i < transLen; i++) {
+ if (i == nextSep) {
+ fprintf(stdout, "%s%s ",
+ (field > 0) ? ", " : "", fields[field]);
+ nextSep += fieldLen[field];
+ field++;
+
+ fprintf(stdout, "[");
+ }
+
+ fprintf(stdout, "%02x", buffer[i]);
+
+ if (i + 1 == nextSep)
+ fprintf(stdout, "]");
+ }
+
+ fprintf(stdout, "\n");
+ }
+
+ /* send the peripheral boot command */
+ cmd = cpu_to_le32(OMAP_PERIPH_BOOT);
+
+ if (!omap_usb_write(handle, (unsigned char *) &cmd, sizeof (cmd))) {
+ log_error("failed to send the peripheral boot command 0x%08x\n",
+ OMAP_PERIPH_BOOT);
+ goto fail;
+ }
+
+ /* send the length of the first file (little endian) */
+ if (!omap_usb_write
+ (handle, (unsigned char *) &filelen, sizeof (filelen))) {
+ log_error("failed to length specifier of %u to OMAP BootROM\n",
+ filelen);
+ goto fail;
+ }
+
+ /* send the file! */
+ if (!omap_usb_write(handle, data, filelen)) {
+ log_error("failed to send file \'%s\' (size %u)\n",
+ file->basename, filelen);
+ goto fail;
+ }
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int transfer_other_files(libusb_device_handle *handle, struct arg_state *args)
+{
+ uint32_t *buffer = NULL;
+ int bufsize = 128 * sizeof (*buffer);
+ int numfailures = 0; /* build in some reliablity */
+ int maxfailures = 3;
+ int transLen = 0;
+ int curfile = 1; /* skip the first file */
+ size_t len;
+
+ buffer = calloc(bufsize, sizeof(unsigned char));
+
+ /* handle the state machine for the X-Loader */
+ while (curfile < args->numfiles) {
+ uint32_t opcode = 0;
+ uint8_t *extra = NULL;
+ struct file_upload *f = args->files[curfile];
+
+ /* read the opcode from xloader ID */
+ if (!omap_usb_read
+ (handle, (unsigned char *) buffer, bufsize, &transLen)) {
+ numfailures++;
+
+ if (numfailures >= maxfailures) {
+ log_error("failed to read command from X-Loader\n");
+ goto fail;
+ }
+
+ /* sleep a bit */
+ usleep(2000 * 1000); /* 2s */
+ continue; /* try the opcode read again */
+ }
+
+ if (transLen < 8) {
+ log_error("failed to recieve enough data for the opcode\n");
+ goto fail;
+ }
+
+ /* extract the opcode and extra data pointer */
+ opcode = le32_to_cpu(buffer[0]);
+ extra = (uint8_t *)buffer;
+
+ switch (opcode) {
+ case USBLOAD_CMD_FILE_REQ:
+ /* X-loader is requesting a file to be sent */
+ /* send the opcode, size, and addr */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_FILE);
+ buffer[1] = cpu_to_le32(f->size);
+ buffer[2] = cpu_to_le32(f->addr);
+
+ if (!omap_usb_write(handle, (unsigned char *)buffer, sizeof(*buffer) * 3)) {
+ log_error("failed to send load file command to the X-loader\n");
+ goto fail;
+ }
+
+ if (g_verbose) {
+ log_info("uploading \'%s\' (size %zu) to 0x%08x\n",
+ f->basename, f->size, f->addr);
+ }
+
+ break;
+ case USBLOAD_CMD_ECHO_SZ:
+ /* X-loader confirms the size to recieve */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right file size for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ /* upload the raw file data */
+ if (!omap_usb_write(handle, f->data, f->size)) {
+ log_error
+ ("failed to send file \'%s\' to the X-loader\n",
+ f->basename);
+ goto fail;
+ }
+
+ break;
+ case USBLOAD_CMD_REPORT_SZ:
+ /* X-loader confirms the amount of data it recieved */
+ if (buffer[1] != f->size) {
+ log_error
+ ("X-loader failed to recieve the right amount of data for "
+ "file \'%s\' (got %u, expected %zu)\n",
+ f->basename, buffer[1], f->size);
+ goto fail;
+ }
+
+ curfile++; /* move on to the next file */
+ break;
+ case USBLOAD_CMD_MESSAGE:
+ /* X-loader debug message */
+ len = strlen((char *)extra);
+
+ if (len > (bufsize - sizeof (opcode) - 1))
+ log_error("X-loader debug message not NUL terminated (size %zu)\n",
+ len);
+ else
+ fprintf(stdout, "X-loader Debug: %s\n", extra);
+ break;
+ default:
+ log_error("unknown X-Loader opcode 0x%08X (%c%c%c%c)\n",
+ opcode, extra[0], extra[1], extra[2],
+ extra[3]);
+ goto fail;
+ }
+ }
+
+ /* we're done uploading files to X-loader send the jump command */
+ buffer[0] = cpu_to_le32(USBLOAD_CMD_JUMP);
+ buffer[1] = cpu_to_le32(args->jumptarget);
+
+ if (!omap_usb_write
+ (handle, (unsigned char *) buffer, sizeof (*buffer) * 2)) {
+ log_error
+ ("failed to send the final jump command to the X-loader. "
+ "Target was 0x%08x\n", args->jumptarget);
+ goto fail;
+ }
+
+ if (g_verbose)
+ log_info("jumping to address 0x%08x\n", args->jumptarget);
+
+ free(buffer);
+ return 1;
+
+ fail:
+ free(buffer);
+ return 0;
+}
+
+static int process_args(struct arg_state *args)
+{
+ int i;
+
+ /* For each file, load it in to memory
+ * TODO: defer this until transfer time (save memory and pipeline IO)
+ */
+
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ f->data = read_file(f->path, &f->size);
+
+ if (!f->data) {
+ return 1;
+ }
+ }
+
+ if (g_verbose > 0) {
+ for (i = 0; i < args->numfiles; i++) {
+ struct file_upload *f = args->files[i];
+
+ printf("File \'%s\' at 0x%08x, size %zu\n",
+ f->basename, f->addr, f->size);
+ }
+ }
+
+ libusb_context *ctx;
+ libusb_device_handle *dev;
+ int ret;
+
+ if ((ret = libusb_init(&ctx)) < 0) {
+ log_error("failed to initialize libusb context: %s\n",
+ libusb_error_name(ret));
+ return ret;
+ }
+
+ dev = omap_usb_open(ctx, args->vendor, args->product);
+
+ if (!dev) {
+ libusb_exit(ctx);
+ return 1;
+ }
+
+ /* Communicate with the TI BootROM directly
+ * - retrieve ASIC ID
+ * - start peripheral boot
+ * - upload first file
+ * - execute first file
+ */
+ if (!transfer_first_stage(dev, args)) {
+ log_error("failed to transfer the first stage file \'%s\'\n",
+ args->files[0]->basename);
+ goto fail;
+ }
+
+ /* Note: this is a race between the target's processor getting X-loader
+ * running and our processor. If we fail to communicate with the X-loader,
+ * it's possible that it hasn't been fully initialized. I'm not going to put
+ * some stupid, arbitrary sleep value here. The transfer_other_files function
+ * should be robust enough to handle some errors.
+ */
+
+ /* If we are passed one file, assume that the user just wants to
+ * upload some initial code with no X-loader chaining
+ */
+ if (args->numfiles > 1) {
+ if (!transfer_other_files(dev, args)) {
+ log_error
+ ("failed to transfer the additional files in to memory\n");
+ goto fail;
+ }
+ }
+
+ log_info("successfully transfered %d %s\n", args->numfiles,
+ (args->numfiles > 1) ? "files" : "file");
+
+ /* safely close our USB handle and context */
+ libusb_close(dev);
+ libusb_exit(ctx);
+ return 0;
+
+fail:
+ libusb_close(dev);
+ libusb_exit(ctx);
+
+ return 1;
+}
+
+/* getopt configuration */
+static int do_version = 0;
+static const char *const short_opt = "f:a:j:i:p:vh";
+static const struct option long_opt[] = {
+ {"file", 1, NULL, 'f'},
+ {"addr", 1, NULL, 'a'},
+ {"jump", 1, NULL, 'j'},
+ {"vendor", 1, NULL, 'i'},
+ {"product", 1, NULL, 'p'},
+ {"verbose", 0, NULL, 'v'},
+ {"help", 0, NULL, 'h'},
+ {"version", 0, &do_version, 1},
+ {NULL, 0, NULL, 0}
+};
+
+static void usage(char *exe)
+{
+ printf(
+"Usage: %s [options] -f first-stage [-f file -a addr]...\n"
+"Options:\n"
+" -f, --file Provide the filename of a binary file to be\n"
+" uploaded. The first file specified is uploaded to\n"
+" the fixed address 0x%08x as defined by the manual.\n"
+" Additional files must be followed by an address\n"
+" argument (-a).\n"
+" -a, --addr The address to load the prior file at.\n"
+" -j, --jump Specify the address to jump to after loading all\n"
+" of the files in to memory.\n"
+" -i, --vendor Override the default vendor ID to poll for\n"
+" (default 0x%04x).\n"
+" -p, --product Poll for specific product id. Default: All known OMAP chips\n"
+" -h, --help Display this message.\n"
+" -v, --verbose Enable verbose output.\n"
+"\n"
+"Description:\n"
+" %s's basic usage is to upload an arbitrary file in to the memory\n"
+" of a TI OMAP3 compatible processor. This program directly\n"
+" communicates with the TI BootROM in order to upload a first stage\n"
+" payload, in most cases, TI's X-Loader. Using a compatible X-Loader\n"
+" will enable the upload of any file to any part in device memory.\n"
+"\n"
+"Examples:\n"
+" Uploading a compatible X-Loader, U-Boot, Kernel, and RAMDisk, then jumping\n"
+" to the U-Boot image for further bootloading:\n"
+" %s -f x-load.bin -f u-boot.bin -a 0x80200000 -f uImage -a 0x80800000 \\\n"
+" -f uRamdisk -a 0x81000000 -j 0x80200000\n"
+" Uploading arbitrary code to be executed (doesn't have to be X-loader):\n"
+" %s -f exec_me.bin\n"
+" Trying to debug an upload issue using verbose output:\n"
+" %s -v -f exec_me.bin -f file1.bin -a 0xdeadbeef -j 0xabad1dea\n"
+"\n"
+"Authors:\n"
+" Grant Hernandez <grant.h.hernandez@gmail.com> - rewrite of omap3_usbload to\n"
+" use the newer libusb 1.0\n"
+" Martin Mueller <martinmm@pfump.org> - initial code (omap3_usbload)\n"
+" and X-Loader patch\n",
+ exe, OMAP_BASE_ADDRESS, OMAP_VENDOR_ID, PROG_NAME, exe, exe, exe
+ );
+}
+
+static void license(void)
+{
+ printf(
+"Copyright (C) 2008 Martin Mueller <martinmm@pfump.org>\n"
+"Copyright (C) 2014 Grant Hernandez <grant.h.hernandez@gmail.com>\n"
+"License GPLv2: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.\n"
+"This is free software: you are free to change and redistribute it.\n"
+"There is NO WARRANTY, to the extent permitted by law.\n"
+ );
+}
+
+int main(int argc, char *argv[])
+{
+ int opt;
+ bool gotfile = false;
+ bool gotjump = false;
+ int filecount = 0;
+ char *exe = NULL;
+
+ /* temporary local file object */
+ struct file_upload file;
+ /* total arg state */
+ struct arg_state *args = calloc(1, sizeof (*args));
+
+ if (argc < 1) {
+ log_error("invalid arguments (no argv[0])\n");
+ return 1;
+ }
+
+ exe = argv[0];
+
+ fprintf(stdout, "%s %s\n", PROG_NAME, VERSION);
+
+ /* set the default vendor and product */
+ args->vendor = OMAP_VENDOR_ID;
+ args->product = 0;
+
+ while ((opt = getopt_long(argc, argv, short_opt, long_opt, NULL)) != -1) {
+ switch (opt) {
+ case 0:
+ if (do_version) {
+ license();
+ return 0;
+ }
+ break;
+ case 'f':
+ if (gotfile) {
+ log_error("missing address argument (-a) for file \'%s\'\n",
+ file.path);
+ usage(exe);
+ return 1;
+ }
+
+ file.path = strdup(optarg);
+
+ /* necessary to be sure that we own all the memory
+ and that the path input can be modified */
+ char *tmpPath = strdup(file.path);
+ file.basename = strdup(basename(tmpPath));
+ free(tmpPath);
+
+ filecount++;
+
+ /* the first file gets uploaded to a fixed address
+ as specified by the technical reference manual */
+ if (filecount == 1) {
+ file.addr = OMAP_BASE_ADDRESS;
+
+ /* commit the file object with the processor specified base address */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof (file));
+ memcpy(args->files[filecount - 1], &file, sizeof (file));
+ } else {
+ /* commit only after an address is specified */
+ gotfile = true;
+ }
+ break;
+ case 'a':
+ if (!gotfile) {
+ log_error
+ ("missing file argument (-f) before address \'%s\'\n",
+ optarg);
+ usage(exe);
+ return 1;
+ }
+
+ /* passing 0 to strtoul enables detection of the 0x prefix with
+ base-10 fallback if missing */
+ file.addr = strtoul(optarg, NULL, 0);
+
+ /* commit the file object */
+ args->files = realloc(args->files, filecount);
+ args->numfiles = filecount;
+ args->files[filecount - 1] = malloc(sizeof(file));
+ memcpy(args->files[filecount - 1], &file, sizeof(file));
+
+ gotfile = false;
+ break;
+ case 'j':
+ args->jumptarget = strtoul(optarg, NULL, 0);
+ gotjump = true;
+ break;
+ case 'i':
+ args->vendor = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'p':
+ args->product = (uint16_t)strtoul(optarg, NULL, 0);
+ break;
+ case 'v':
+ g_verbose++;
+ break;
+ case 'h':
+ usage(exe);
+ return 0;
+ default:
+ usage(exe);
+ return 1;
+ }
+ }
+
+ if (gotfile) {
+ log_error("got file \'%s\', but no address!\n", file.path);
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles <= 0) {
+ log_error("at least one file needs to be specified\n");
+ usage(exe);
+ return 1;
+ }
+
+ if (args->numfiles == 1 && gotjump) {
+ log_info
+ ("WARNING: jump target 0x%08x specified, but will never be taken "
+ "(more than one file required)\n", args->jumptarget);
+ } else if (args->numfiles > 1 && !gotjump) {
+ log_info
+ ("WARNING: no jump target specified. Defaulting to the first "
+ "file's (\'%s\') address 0x%08x\n",
+ args->files[1]->basename, args->files[1]->addr);
+ args->jumptarget = args->files[1]->addr;
+ }
+
+ return process_args(args);
+}