diff options
326 files changed, 14148 insertions, 1457 deletions
diff --git a/.gitignore b/.gitignore index 135fdeb630..a62e08c730 100644 --- a/.gitignore +++ b/.gitignore @@ -46,6 +46,8 @@ barebox.uimage barebox.map barebox.kwb barebox.kwbuart +barebox.efi +barebox.canon-a1100.bin barebox-flash-image System.map Module.symvers @@ -66,7 +68,6 @@ include/linux/compile.h include/generated # Generated files -Doxyfile.version Documentation/commands/*.rst doctrees/ diff --git a/Documentation/boards/davinci.rst b/Documentation/boards/davinci.rst new file mode 100644 index 0000000000..a2ddc3c41f --- /dev/null +++ b/Documentation/boards/davinci.rst @@ -0,0 +1,51 @@ +TI Davinci +========== + +virt2real +--------- + +virt2real is a miniature board for creation of WiFi +or Internet controllable smart devices. + +The board has + + * TI DaVinchi DM365 running at 300 MHz; + * 128 MiB DDR2 SDRAM; + * 256 MiB NAND Flash Memory; + * 2 x UART serial interfaces; + * 1 x Ethernet interface (Micrel KS8851); + * 1 x USB interface; + * microSD card slot. + +The board uses U-Boot as bootloader. + + +Running barebox +^^^^^^^^^^^^^^^ + + 1. Connect to the boards's UART0 (115200 8N1); + Use J2.2 (GND), J2.4 (UART0_TXD), J2.6 (UART0_RXD) pins. + + 2. Turn board's power on; + + 3. Wait for ``Hit any key to stop autoboot`` prompt and press the space key. + + 4. Upload ``barebox.bin`` via Ymodem + +.. code-block:: none + virt2real ># loady +.. + + 5. Run barebox + +.. code-block:: none + virt2real ># go 0x82000000 +.. + + +Links +^^^^^ + + * http://virt2real.com/ + * http://wiki.virt2real.ru/ + * https://github.com/virt2real diff --git a/Documentation/boards/digic.rst b/Documentation/boards/digic.rst new file mode 100644 index 0000000000..e2c49b6514 --- /dev/null +++ b/Documentation/boards/digic.rst @@ -0,0 +1,16 @@ +Canon DIGIC +=========== + +Canon PowerShot A1100 IS +------------------------ + +Running barebox on QEMU +^^^^^^^^^^^^^^^^^^^^^^^ + +QEMU supports Canon A1100 camera emulation since version 2.0. + +Usage:: + + $ qemu-system-arm -M canon-a1100 \ + -nographic -monitor null -serial stdio \ + -bios barebox.canon-a1100.bin diff --git a/Documentation/boards/efi.rst b/Documentation/boards/efi.rst new file mode 100644 index 0000000000..2147cb63db --- /dev/null +++ b/Documentation/boards/efi.rst @@ -0,0 +1,298 @@ +barebox on (U)EFI +================= + +barebox can be built as an EFI application for X86 PCs. This makes +barebox a bootloader running on PC type hardware. In EFI jargon barebox +would be a EFI shell. Due to the barebox :ref:`bootloader_spec` support +it can act as a replacement for gummiboot. + +For accessing hardware the EFI drivers and abstractions are used. barebox +has several drivers which merely map to the underlying EFI layers. A plain +barebox binary provides access to the screen and keyboard. The EFI System +partition (:term:`ESP`) is available under ``/boot``, additional partitions may +be available as ``/efi*``. Networking may be available if the BIOS provides +the necessary drivers, but most likely you'll have to download/compile +network drivers yourself, see below. + +Depending on the ``CONFIG_64BIT`` option either a ia32 binary or a x86_64 +binary is built. Due to the lack of 32bit UEFI testing hardware only the +x86_64 binary currently is tested. + +Building barebox for EFI +------------------------ + +Use the following to build barebox for EFI: + +.. code-block:: sh + + export ARCH=efi + make efi_defconfig + make + +The resulting EFI image is ``barebox.efi`` (or the barebox-flash-image link). + +Running barebox on EFI systems +------------------------------ + +The simplest way to run barebox on a USB memory stick. (U)EFI only supports +FAT filesystems, so make sure you either have a FAT16 or FAT32 filesystem on +the memory stick. Put ``barebox.efi`` into the ``EFI/BOOT/`` directory and +name it ``BOOTx64.EFI`` on 64bit architectures and ``BOOTIA32.EFI`` on 32bit +architectures. Switching to USB boot in the BIOS should then be enough to +start barebox via USB. Some BIOSes allow to specify a path to a binary to +be executed, others have a "start UEFI shell" entry which executes +EFI/Shellx64.efi on the :term:`ESP`. This can be a barebox binary aswell. + +Running EFI barebox on qemu +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +barebox can be started in qemu with OVMF http://www.linux-kvm.org/page/OVMF. + +OVMF is part of several distributions and can be installed with the package +management system. qemu needs the OVMF.fd from the OVMF package file as +argument to the -pflash option. As qemu needs write access to that file it's +necessary to make a copy first. + +To start it create a USB memory stick like above and execute: + +.. code-block:: sh + + qemu-system-x86_64 -pflash OVMF.fd -nographic /dev/sdx + +A plain VFAT image will work aswell, but in this case the UEFI BIOS won't +recognize it as ESP and ``/boot`` won't be mounted. + +Loading EFI applications +------------------------ + +EFI supports loading applications aswell as drivers. barebox does not differentiate +between both. Both types can be simply executed by typing the path on the command +line. When an application/driver returns barebox iterates over the handle database +and will initialize all new devices. + +Applications +^^^^^^^^^^^^ + +barebox itself and also the Linux Kernel are EFI applications. This means both +can be directly executed. On other architectures when barebox is executed from +another barebox it means the barebox binary will be replaced. EFI behaves +differently, here different barebox instances will be nested, so exiting barebox +means passing control to the calling instance. Note that currently the :ref:`command_reset` +command will pass the control to the calling instance rather than resetting +the CPU. This may change in the future. + +Although the Linux Kernel can be directly executed one should use the :ref:`command_bootm` +command. Only the bootm command passes the Kernel commandline to the Kernel. + +Drivers +^^^^^^^ + +EFI is modular and drivers can be loaded during runtime. Many drivers are +included in the BIOS already, but some have to be loaded during runtime, +for example it's common that network drivers are not included in the BIOS. + +Drivers can be loaded under barebox simply by executing them: + +.. code-block:: sh + + barebox:/ /boot/network-drivers/0001-SnpDxe.efi + +Should the drivers instanciate new devices these are automatically registered +after the driver has been loaded. + +Simple Network Protocol (SNP) +----------------------------- + +The Simple Network Protocol provides a raw packet interface to the EFI +network drivers. Each device which supports SNP shows up as a regular +network device under barebox. To use SNP the BIOS must have the SNP +protocol and the network driver installed. For getting the SNP protocol +follow the instruction in :ref:`efi_building_edk2`. Network drivers for +the common Intel Network devices can be found here: + +https://downloadcenter.intel.com/Detail_Desc.aspx?agr=Y&DwnldID=19186 + +Once instantiated the EFI drivers take some time to bring up the link, so +it's best to only load the network drivers when needed. This can be +archieved with the following script to put under ``/env/network/eth0-discover``: + +.. code-block:: sh + + #!/bin/sh + + for i in /boot/network-drivers/*; do + $i; + done + +This script will load the drivers in ``/boot/network-drivers/`` in alphabetical +order. + +**NOTE** Loading the network drivers only works when loaded in the +correct order. First the SNP driver must be loaded and then the network device +driver. Otherwise the drivers will load without errors, but no devices will be +instantiated. For making the order sure the driver names can be prepended with +a number: + +.. code-block:: sh + + /boot/network-drivers/0001-SnpDxe.efi + /boot/network-drivers/0002-E6208X3.EFI + +It is currently not known whether this is a limitation in EFI or a bug in +barebox. + +EFI File IO Interface +--------------------- + +EFI itself has filesystem support. At least the :term:`ESP` will be mounted by the +EFI core already. The :term:`ESP` is mounted to ``/boot`` under barebox, other devices +are mounted to ``/efi<no>`` in no particular order. + +Block IO Protocol +----------------- + +EFI provides access to block devices with the Block IO Protocol. This can +be used to access raw block devices under barebox and also to access filesystems +not supported by EFI. The block devices will show up as ``/dev/disk<diskno>.<partno>`` +under barebox and can be accessed like any other device: + +.. code-block:: sh + + mount /dev/disk0.1 -text4 /mnt + +Care must be taken that a partition is only accessed either via the Block IO Protocol *or* +the File IO Interface. Doing both at the same time will most likely result in data +corruption on the partition + +EFI device pathes +----------------- + +In EFI each device can be pointed to using a device path. Device pathes have multiple +components. The toplevel component on X86 systems will be the PCI root complex, on +other systems this can be the physical memory space. Each component will now descrive +how to find the child component on the parent bus. Additional device path nodes can +describe network addresses or filenames on partitions. Device pathes have a binary +representation and a clearly defined string representation. These characteristics make +device pathes suitable for describing boot entries. barebox could use device pathes +to store the reference to kernels on boot media. Also device pathes could be used to +pass a root filesystem to the Kernel. + +Currently device pathes are only integrated into barebox in a way that each EFI device +has a device parameter ``devpath`` which contains its device path: + +.. code-block:: sh + + barebox:/ echo ${handle-00000000d0012198.devpath} + pci_root(0)/Pci(0x1d,0x0)/Usb(0x1,0x0)/Usb(0x2,0x0) + + +EFI variables +------------- + +EFI has support for variables which are exported via the EFI Variable Services. EFI variables +are identified by a 64bit GUID and a name. EFI variables can have arbitrary binary values, so +they are not compatible with barebox shell variables which can only have printable content. +Support for these variables is not yet complete in barebox. barebox contains the efivarfs which +has the same format as the Linux Kernels efivarfs. It can be mounted with: + +.. code-block:: sh + + mkdir efivarfs + mount -tefivarfs none /efivarfs + +In efivarfs each variable is represented by a file named <varname>-<guid>. Access to EFI variables +is currently readonly. Since the variables have binary content using :ref:`command_md` is often +more suitable than :ref:`command_cat`. + +EFI driver model and barebox +---------------------------- + +The EFI driver model is based around handles and protocols. A handle is an opaque +cookie that represents a hardware device or a software object. Each handle can have +multiple protocols attached to it. A protocol is a callable interface and is defined +by a C struct containing function pointers. A protocol is identified by a 64bit GUID. +Common examples for protocols are DEVICE_PATH, DEVICE_IO, BLOCK_IO, DISK_IO, +FILE_SYSTEM, SIMPLE_INPUT or SIMPLE_TEXT_OUTPUT. Every handle that implements the +DEVICE_PATH protocol is registered as device in barebox. The structure can be best +seen in the ``devinfo`` output of such a device: + +.. code-block:: sh + + barebox:/ devinfo handle-00000000cfaed198 + Driver: efi-snp + Bus: efi + Protocols: + 0: a19832b9-ac25-11d3-9a2d-0090273fc14d + 1: 330d4706-f2a0-4e4f-a369-b66fa8d54385 + 2: e5dd1403-d622-c24e-8488-c71b17f5e802 + 3: 34d59603-1428-4429-a414-e6b3b5fd7dc1 + 4: 0e1ad94a-dcf4-11db-9705-00e08161165f + 5: 1aced566-76ed-4218-bc81-767f1f977a89 + 6: e3161450-ad0f-11d9-9669-0800200c9a66 + 7: 09576e91-6d3f-11d2-8e39-00a0c969723b + 8: 51dd8b21-ad8d-48e9-bc3f-24f46722c748 + Parameters: + devpath: pci_root(0)/Pci(0x1c,0x3)/Pci(0x0,0x0)/Mac(e03f4914f157) + +The protocols section in the output shows the different protocols this +handle implements. One of this Protocols (here the first) is the Simple +Network Protocol GUID: + +.. code-block:: c + + #define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D ) + +Matching between EFI devices and drivers is done based on the Protocol GUIDs, so +whenever a driver GUID matches one of the GUIDs a device imeplements the drivers +probe function is called. + +.. _efi_building_edk2: + +Building EDK2 +------------- + +Additional drivers may be needed from the EDK2 package. For example to +use Networking in barebox not only the network device drivers are needed, +but also the Simple Network Protocol driver, SnpDxe.efi. This is often +not included in the BIOS, but can be compiled from the EDK2 package. + +Here is only a quick walkthrough for building edk2, there are more elaborated +HOWTOs in the net, for example on http://tianocore.sourceforge.net/wiki/Using_EDK_II_with_Native_GCC. + +.. code-block:: sh + + git clone git://github.com/tianocore/edk2.git + cd edk2 + make -C BaseTools + . edksetup.sh + +At least the following lines in ``Conf/target.txt`` should be edited:: + + ACTIVE_PLATFORM = MdeModulePkg/MdeModulePkg.dsc + TARGET_ARCH = X64 + TOOL_CHAIN_TAG = GCC48 + MAX_CONCURRENT_THREAD_NUMBER = 4 + +The actual build is started with invoking ``build``. After building +``Build/MdeModule/DEBUG_GCC48/X64/SnpDxe.efi`` should exist. + +**NOTE** As of this writing (July 2014) the following patch was needed to +compile EDK2. + +.. code-block:: diff + + diff --git a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + index 9783ec6..13fc06c 100644 + --- a/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + +++ b/MdeModulePkg/Universal/DebugSupportDxe/X64/AsmFuncs.S + @@ -280,7 +280,7 @@ ExtraPushDone: + + mov %ds, %rax + pushq %rax + - movw %es, %rax + + mov %es, %rax^M + pushq %rax + mov %fs, %rax + pushq %rax + diff --git a/Documentation/commands.rst b/Documentation/commands.rst index 55b04f6e56..261af2a078 100644 --- a/Documentation/commands.rst +++ b/Documentation/commands.rst @@ -1,9 +1,91 @@ Command reference ================= +Information +----------- .. toctree:: + :titlesonly: :glob: - :maxdepth: 1 - commands/* + commands/info/* + +Booting +------- +.. toctree:: + :titlesonly: + :glob: + + commands/boot/* + +Partitions and Filesystems +-------------------------- +.. toctree:: + :titlesonly: + :glob: + + commands/part/* + +Environment +----------- +.. toctree:: + :titlesonly: + :glob: + + commands/env/* + +Files +----- +.. toctree:: + :titlesonly: + :glob: + + commands/file/* + +Shell Scripting +--------------- +.. toctree:: + :titlesonly: + :glob: + + commands/script/* + +Console and Framebuffer +----------------------- +.. toctree:: + :titlesonly: + :glob: + + commands/console/* + +Memory +------ +.. toctree:: + :titlesonly: + :glob: + + commands/mem/* + +Hardware Manipulation +--------------------- +.. toctree:: + :titlesonly: + :glob: + + commands/hwmanip/* + +Miscellaneous +------------- +.. toctree:: + :titlesonly: + :glob: + + commands/misc/* + +Networking +---------- +.. toctree:: + :titlesonly: + :glob: + + commands/net/* diff --git a/Documentation/gen_commands.py b/Documentation/gen_commands.py index 4e33ccaea6..b85e2e3eab 100755 --- a/Documentation/gen_commands.py +++ b/Documentation/gen_commands.py @@ -1,8 +1,10 @@ #!/usr/bin/python +import errno import os import re import sys +import hashlib from collections import defaultdict from pprint import pprint @@ -76,7 +78,7 @@ def parse_c(name): x = CMD_GROUP.match(line) if x: last = cmd['c_group'] - last.append(x.group(1).decode("string_escape")) + last.append(x.group(1).split('_')[-1].lower()) continue x = CONT.match(line) if x: @@ -101,7 +103,7 @@ def gen_rst(name, cmd): out.append('.. _command_%s:' % name) out.append('') if 'c_desc' in cmd: - out.append("%s (%s)" % (name, ''.join(cmd['c_desc']).strip())) + out.append("%s - %s" % (name, ''.join(cmd['c_desc']).strip())) else: out.append("%s" % (name,)) out.append('='*len(out[-1])) @@ -159,6 +161,27 @@ for name in CMDS.keys(): for name, cmd in CMDS.items(): #pprint({name: cmd}) rst = gen_rst(name, cmd) - target = os.path.join(sys.argv[2], name+'.rst') + subdir = os.path.join(sys.argv[2], cmd['c_group'][0]) + try: + os.makedirs(subdir) + except OSError as e: + if e.errno == errno.EEXIST and os.path.isdir(subdir): + pass + else: + raise + target = os.path.join(subdir, name+'.rst') + + # Only write the new rst if it differs from the old one. Wroto + hash_old = hashlib.sha1() + try: + f = open(target, 'rb') + hash_old.update(f.read()) + except: + pass + hash_new = hashlib.sha1() + hash_new.update(rst) + if hash_old.hexdigest() == hash_new.hexdigest(): + continue + file(target, 'w').write(rst) diff --git a/Documentation/glossary.rst b/Documentation/glossary.rst index 8bad7dc6e8..106dce98a9 100644 --- a/Documentation/glossary.rst +++ b/Documentation/glossary.rst @@ -16,3 +16,6 @@ Glossary PBL Pre BootLoader image + + ESP + EFI System Partition diff --git a/Documentation/user/imd.rst b/Documentation/user/imd.rst new file mode 100644 index 0000000000..e0251d644e --- /dev/null +++ b/Documentation/user/imd.rst @@ -0,0 +1,54 @@ + +.. _imd: + +Image MetaData (IMD) +==================== + +barebox images can be enriched with metadata. This is useful to get information +the board an image is compiled for and which barebox version an image contains. + +There are predefined tags for: + +- The build timestamp +- The barebox release version +- The model (board) the image is compiled for +- The toplevel device tree compatible properties the image can handle + +Additionally there is a generic key/value tag to add information which does not +fit into the above categories, for example the memory size for boards which come +with different memory sizes which can't be automatically detected. + +The informations can be extracted with the ``bareboximd`` tool which lives under +``scripts/`` in the barebox sourcecode. If enabled it is compiled for the compile +host and also for the target architecture. barebox itself has the :ref:`command_imd` +command to extract the informations. Here is an example output of the tool called +without additional options:: + + # imd barebox-phytec-pbab01dl-1gib.img + build: #890 Wed Jul 30 16:15:24 CEST 2014 + release: 2014.07.0-00167-ge6632a9-dirty + parameter: memsize=1024 + of_compatible: phytec,imx6x-pbab01 phytec,imx6dl-pfla02 fsl,imx6dl + model: Phytec phyFLEX-i.MX6 Duallite Carrier-Board + +Single informations can be extracted with the ``-t <type>`` option:: + + # imd barebox-phytec-pbab01dl-1gib.img -t release + 2014.07.0-00167-ge6632a9-dirty + +Since the barebox hush does not have output redirection the barebox too has the +``-s <var>`` option to assign the output to a variable for later evaluation. + +Limitations +----------- + +The IMD tags are generated in the barebox binary before a SoC specific image is +generated. Some SoCs encrypt or otherwise manipulate the images in a way that the +IMD information is lost. The IMD mechanism does not work on these SoCs. A known +example is the Freescale i.MX28. + +IMD and barebox_update +---------------------- + +The IMD informations could well be used to check if an image is suitable for updating +barebox for a particular board. Support for such a check is planned but not yet implemented. diff --git a/Documentation/user/updating.rst b/Documentation/user/updating.rst index 2a963b6200..6a1a73348c 100644 --- a/Documentation/user/updating.rst +++ b/Documentation/user/updating.rst @@ -27,3 +27,6 @@ barebox has been started from is registered as default (marked with a ``*``):: available for your board. It is recommended to implement it, but you can also update barebox manually using :ref:`command_erase` and :ref:`command_cp` commands. The exact commands are board specific. + +**NOTE** barebox images can be enriched with metadata which can be used to check +if a given image is suitable for updating barebox, see :ref:`imd`. diff --git a/Documentation/user/user-manual.rst b/Documentation/user/user-manual.rst index 0eac0aadc7..3d68bbb9ae 100644 --- a/Documentation/user/user-manual.rst +++ b/Documentation/user/user-manual.rst @@ -19,6 +19,7 @@ Contents: hush defaultenv-2 updating + imd devicetree pbl multi-image @@ -1,5 +1,5 @@ VERSION = 2014 -PATCHLEVEL = 07 +PATCHLEVEL = 08 SUBLEVEL = 0 EXTRAVERSION = NAME = None @@ -774,10 +774,6 @@ include/config/kernel.release: include/config/auto.conf FORCE $(Q)rm -f $@ $(Q)echo $(KERNELVERSION)$(localversion) > $@ -Doxyfile.version: include/config/auto.conf FORCE - $(Q)rm -f $@ - $(Q)echo "PROJECT_NUMBER = $(KERNELRELEASE)" > $@ - # Things we need to do before we recursively start building the kernel # or the modules are listed in "prepare". # A multi level approach is used. prepareN is processed before prepareN-1. @@ -996,8 +992,9 @@ CLEAN_FILES += barebox System.map include/generated/barebox_default_env.h \ .tmp_version .tmp_barebox* barebox.bin barebox.map barebox.S \ .tmp_kallsyms* common/barebox_default_env* barebox.ldr \ scripts/bareboxenv-target barebox-flash-image \ - Doxyfile.version barebox.srec barebox.s5p barebox.ubl \ - barebox.uimage barebox.spi barebox.kwb barebox.kwbuart + barebox.srec barebox.s5p barebox.ubl barebox.zynq \ + barebox.uimage barebox.spi barebox.kwb barebox.kwbuart \ + barebox.efi barebox.canon-a1100.bin # Directories & files removed with 'make mrproper' MRPROPER_DIRS += include/config include2 usr/include @@ -179,7 +179,7 @@ net/ -> Networking stuff scripts/ -> Kconfig system -Documentation/ -> Doxygen generated documentation +Documentation/ -> Sphinx generated documentation Release Strategy diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 3af01970e3..9f34e1089b 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -62,6 +62,15 @@ config ARCH_DAVINCI select HAS_DEBUG_LL select GPIOLIB +config ARCH_DIGIC + bool "Canon DIGIC-based cameras" + select CPU_ARM946E + select HAS_DEBUG_LL + select CLOCKSOURCE_DIGIC + select GPIOLIB + help + Support for Canon's digital cameras that use the DIGIC4 chip. + config ARCH_EP93XX bool "Cirrus Logic EP93xx" select CPU_ARM920T @@ -95,6 +104,7 @@ config ARCH_MVEBU select GPIOLIB select HAS_DEBUG_LL select HAVE_PBL_MULTI_IMAGES + select HW_HAS_PCI select MVEBU_MBUS select OFTREE select OF_ADDRESS_PCI @@ -220,6 +230,7 @@ source arch/arm/mach-at91/Kconfig source arch/arm/mach-bcm2835/Kconfig source arch/arm/mach-clps711x/Kconfig source arch/arm/mach-davinci/Kconfig +source arch/arm/mach-digic/Kconfig source arch/arm/mach-ep93xx/Kconfig source arch/arm/mach-highbank/Kconfig source arch/arm/mach-imx/Kconfig diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 983f7f57cd..337aef175b 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -55,6 +55,7 @@ machine-$(CONFIG_ARCH_AT91) := at91 machine-$(CONFIG_ARCH_BCM2835) := bcm2835 machine-$(CONFIG_ARCH_CLPS711X) := clps711x machine-$(CONFIG_ARCH_DAVINCI) := davinci +machine-$(CONFIG_ARCH_DIGIC) := digic machine-$(CONFIG_ARCH_EP93XX) := ep93xx machine-$(CONFIG_ARCH_HIGHBANK) := highbank machine-$(CONFIG_ARCH_IMX) := imx @@ -184,6 +185,16 @@ ifeq ($(machine-y),zynq) KBUILD_IMAGE := barebox.zynq endif +quiet_cmd_canon_a1100_image = DD $@ + cmd_canon_a1100_image = scripts/canon-a1100-image $< $@ || \ + echo "WARNING: Couldn't create Canon A1100 image due to previous errors." +barebox.canon-a1100.bin: $(KBUILD_BINARY) FORCE + $(call if_changed,canon_a1100_image) + +ifeq ($(CONFIG_MACH_CANON_A1100),y) +KBUILD_IMAGE := barebox.canon-a1100.bin +endif + KWBIMAGE_OPTS = \ -c -i $(srctree)/$(BOARD)/kwbimage.cfg -d $(TEXT_BASE) -e $(TEXT_BASE) diff --git a/arch/arm/boards/Makefile b/arch/arm/boards/Makefile index d200512758..c60da81261 100644 --- a/arch/arm/boards/Makefile +++ b/arch/arm/boards/Makefile @@ -12,6 +12,7 @@ obj-$(CONFIG_MACH_AT91SAM9N12EK) += at91sam9n12ek/ obj-$(CONFIG_MACH_AT91SAM9X5EK) += at91sam9x5ek/ obj-$(CONFIG_MACH_BEAGLE) += beagle/ obj-$(CONFIG_MACH_BEAGLEBONE) += beaglebone/ +obj-$(CONFIG_MACH_CANON_A1100) += canon-a1100/ obj-$(CONFIG_MACH_NITROGEN6X) += boundarydevices-nitrogen6x/ obj-$(CONFIG_MACH_CCMX51) += ccxmx51/ obj-$(CONFIG_MACH_CFA10036) += crystalfontz-cfa10036/ @@ -28,6 +29,7 @@ obj-$(CONFIG_MACH_EDB9307) += edb93xx/ obj-$(CONFIG_MACH_EDB9315A) += edb93xx/ obj-$(CONFIG_MACH_EDB9315) += edb93xx/ obj-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += efika-mx-smartbook/ +obj-$(CONFIG_MACH_EMBEDSKY_E9) += embedsky-e9/ obj-$(CONFIG_MACH_EMBEST_RIOTBOARD) += embest-riotboard/ obj-$(CONFIG_MACH_EUKREA_CPUIMX25) += eukrea_cpuimx25/ obj-$(CONFIG_MACH_EUKREA_CPUIMX27) += eukrea_cpuimx27/ diff --git a/arch/arm/boards/at91sam9m10ihd/hw_version.c b/arch/arm/boards/at91sam9m10ihd/hw_version.c index 8e729013c7..96fb02d801 100644 --- a/arch/arm/boards/at91sam9m10ihd/hw_version.c +++ b/arch/arm/boards/at91sam9m10ihd/hw_version.c @@ -18,6 +18,7 @@ #include <fs.h> #include <fcntl.h> #include <libbb.h> +#include <libfile.h> #include <asm/armlinux.h> #include <of.h> diff --git a/arch/arm/boards/at91sam9x5ek/hw_version.c b/arch/arm/boards/at91sam9x5ek/hw_version.c index 2da4e5ed8c..37eb1f80c5 100644 --- a/arch/arm/boards/at91sam9x5ek/hw_version.c +++ b/arch/arm/boards/at91sam9x5ek/hw_version.c @@ -18,6 +18,7 @@ #include <fs.h> #include <fcntl.h> #include <libbb.h> +#include <libfile.h> #include <asm/armlinux.h> #include <of.h> diff --git a/arch/arm/boards/canon-a1100/Makefile b/arch/arm/boards/canon-a1100/Makefile new file mode 100644 index 0000000000..b08c4a93ca --- /dev/null +++ b/arch/arm/boards/canon-a1100/Makefile @@ -0,0 +1 @@ +lwl-y += lowlevel.o diff --git a/arch/arm/boards/canon-a1100/lowlevel.c b/arch/arm/boards/canon-a1100/lowlevel.c new file mode 100644 index 0000000000..bbae825661 --- /dev/null +++ b/arch/arm/boards/canon-a1100/lowlevel.c @@ -0,0 +1,23 @@ +#include <common.h> +#include <sizes.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> + +void __naked barebox_arm_reset_vector(void) +{ + arm_cpu_lowlevel_init(); + + /* FIXME: can we determine RAM size using CP15 register? + * + * see http://chdk.setepontos.com/index.php?topic=5980.90 + * + * http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0363e/Bgbcdeca.html + * 4.2.19. c6, MPU memory region programming registers + * + * But the 'cpuinfo' command says that the Protection + * unit is disabled. + * The Control Register value (mrc p15, 0, %0, c0, c1, 4) + * is 0x00051078. + */ + barebox_arm_entry(0x0, SZ_64M, 0); +} diff --git a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c index e28dd49fad..c94cb355e2 100644 --- a/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c +++ b/arch/arm/boards/crystalfontz-cfa10036/hwdetect.c @@ -21,6 +21,7 @@ #include <fs.h> #include <globalvar.h> #include <libbb.h> +#include <libfile.h> #include <magicvar.h> #include <asm/armlinux.h> diff --git a/arch/arm/boards/embedsky-e9/Makefile b/arch/arm/boards/embedsky-e9/Makefile new file mode 100644 index 0000000000..db2dba7769 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/Makefile @@ -0,0 +1,4 @@ +obj-y += board.o flash-header-e9.dcd.o +extra-y += flash-header-e9.dcd.S flash-header-e9.dcd +lwl-y += lowlevel.o +bbenv-y += defaultenv-e9 diff --git a/arch/arm/boards/embedsky-e9/board.c b/arch/arm/boards/embedsky-e9/board.c new file mode 100644 index 0000000000..55b4320219 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/board.c @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2014 Andrey Panov <rockford@yandex.ru> + * + * based on arch/arm/boards/freescale-mx6-sabresd/board.c + * Copyright (C) 2013 Hubert Feurstein <h.feurstein@gmail.com> + * + * based on arch/arm/boards/freescale-mx6-sabrelite/board.c + * Copyright (C) 2012 Steffen Trumtrar, Pengutronix + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <common.h> +#include <init.h> +#include <environment.h> +#include <mach/imx6-regs.h> +#include <fec.h> +#include <gpio.h> +#include <asm/armlinux.h> +#include <generated/mach-types.h> +#include <partition.h> +#include <linux/phy.h> +#include <asm/io.h> +#include <asm/mmu.h> +#include <mach/generic.h> +#include <sizes.h> +#include <net.h> +#include <mach/imx6.h> +#include <mach/devices-imx6.h> +#include <mach/iomux-mx6.h> +#include <spi/spi.h> +#include <mach/spi.h> +#include <mach/usb.h> +#include <envfs.h> + +#define PHY_ID_RTL8211E 0x001cc915 +#define PHY_ID_MASK 0xffffffff + +/* + * This should reset a PHY. Taken from E9 U-Boot/Linux source. + */ +static int rtl8211e_phy_fixup(struct phy_device *dev) +{ + phy_write(dev, 0x00, 0x3140); + mdelay(10); + phy_write(dev, 0x00, 0x3340); + mdelay(10); + + return 0; +} + +static int e9_devices_init(void) +{ + if (!of_machine_is_compatible("embedsky,e9")) + return 0; + + armlinux_set_architecture(3980); + barebox_set_hostname("e9"); + defaultenv_append_directory(defaultenv_e9); + + return 0; +} +device_initcall(e9_devices_init); + +static int e9_coredevices_init(void) +{ + if (!of_machine_is_compatible("embedsky,e9")) + return 0; + + phy_register_fixup_for_uid(PHY_ID_RTL8211E, PHY_ID_MASK, + rtl8211e_phy_fixup); + + return 0; +} +/* + * Do this before the fec initializes but after our + * gpios are available. + */ +coredevice_initcall(e9_coredevices_init); diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1 b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1 new file mode 100644 index 0000000000..0177e6c6b8 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc1 @@ -0,0 +1,6 @@ +#!/bin/sh + +mount /dev/mmc1.0 + +global.bootm.image=/mnt/mmc1.0/zImage +global.linux.bootargs.dyn.root="root=/dev/mmcblk0p2 rootwait" diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3 b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3 new file mode 100644 index 0000000000..374eb1cfe6 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/boot/mmc3 @@ -0,0 +1,6 @@ +#!/bin/sh + +mount /dev/mmc3.0 + +global.bootm.image=/mnt/mmc3.0/boot/zImage +global.linux.bootargs.dyn.root="root=/dev/mmcblk1p1 rootwait" diff --git a/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board b/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board new file mode 100644 index 0000000000..6cba769921 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/defaultenv-e9/config-board @@ -0,0 +1,7 @@ +#!/bin/sh + +# board defaults, do not change in running system. Change /env/config +# instead + +global.hostname=e9 +global.boot.default=$bootsource$bootsource_instance diff --git a/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg b/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg new file mode 100644 index 0000000000..52edefd77a --- /dev/null +++ b/arch/arm/boards/embedsky-e9/flash-header-e9.imxcfg @@ -0,0 +1,87 @@ +loadaddr 0x27800000 +soc imx6 +dcdofs 0x400 + +wm 32 0x020e0798 0x000c0000 +wm 32 0x020e0758 0x00000000 +wm 32 0x020e0588 0x00000030 +wm 32 0x020e0594 0x00000030 +wm 32 0x020e056c 0x00000030 +wm 32 0x020e0578 0x00000030 +wm 32 0x020e074c 0x00000030 +wm 32 0x020e057c 0x00000030 +wm 32 0x020e058c 0x00000000 +wm 32 0x020e059c 0x00000030 +wm 32 0x020e05a0 0x00000030 +wm 32 0x020e078c 0x00000030 +wm 32 0x020e0750 0x00020000 +wm 32 0x020e05a8 0x00000018 +wm 32 0x020e05b0 0x00000018 +wm 32 0x020e0524 0x00000018 +wm 32 0x020e051c 0x00000018 +wm 32 0x020e0518 0x00000018 +wm 32 0x020e050c 0x00000018 +wm 32 0x020e05b8 0x00000018 +wm 32 0x020e05c0 0x00000018 +wm 32 0x020e0774 0x00020000 +wm 32 0x020e0784 0x00000018 +wm 32 0x020e0788 0x00000018 +wm 32 0x020e0794 0x00000018 +wm 32 0x020e079c 0x00000018 +wm 32 0x020e07a0 0x00000018 +wm 32 0x020e07a4 0x00000018 +wm 32 0x020e07a8 0x00000018 +wm 32 0x020e0748 0x00000018 +wm 32 0x020e05ac 0x00000018 +wm 32 0x020e05b4 0x00000018 +wm 32 0x020e0528 0x00000018 +wm 32 0x020e0520 0x00000018 +wm 32 0x020e0514 0x00000018 +wm 32 0x020e0510 0x00000018 +wm 32 0x020e05bc 0x00000018 +wm 32 0x020e05c4 0x00000018 +wm 32 0x021b0800 0xa1390003 +wm 32 0x021b080c 0x001f001f +wm 32 0x021b0810 0x001f001f +wm 32 0x021b480c 0x001f001f +wm 32 0x021b4810 0x001f001f +wm 32 0x021b083c 0x4333033f +wm 32 0x021b0840 0x032c031d +wm 32 0x021b483c 0x43200332 +wm 32 0x021b4840 0x031a026a +wm 32 0x021b0848 0x4d464746 +wm 32 0x021b4848 0x47453f4d +wm 32 0x021b0850 0x3e434440 +wm 32 0x021b4850 0x47384839 +wm 32 0x021b081c 0x33333333 +wm 32 0x021b0820 0x33333333 +wm 32 0x021b0824 0x33333333 +wm 32 0x021b0828 0x33333333 +wm 32 0x021b481c 0x33333333 +wm 32 0x021b4820 0x33333333 +wm 32 0x021b4824 0x33333333 +wm 32 0x021b4828 0x33333333 +wm 32 0x021b08b8 0x00000800 +wm 32 0x021b48b8 0x00000800 +wm 32 0x021b0004 0x00020036 +wm 32 0x021b0008 0x09444040 +wm 32 0x021b000c 0x8a8f7955 +wm 32 0x021b0010 0xff328f64 +wm 32 0x021b0014 0x01ff00db +wm 32 0x021b0018 0x00001740 +wm 32 0x021b001c 0x00008000 +wm 32 0x021b002c 0x000026d2 +wm 32 0x021b0030 0x008f1023 +wm 32 0x021b0040 0x00000047 +wm 32 0x021b0000 0x841a0000 +wm 32 0x021b001c 0x04088032 +wm 32 0x021b001c 0x00008033 +wm 32 0x021b001c 0x00048031 +wm 32 0x021b001c 0x09408030 +wm 32 0x021b001c 0x04008040 +wm 32 0x021b0020 0x00005800 +wm 32 0x021b0818 0x00011117 +wm 32 0x021b4818 0x00011117 +wm 32 0x021b0004 0x00025576 +wm 32 0x021b0404 0x00011006 +wm 32 0x021b001c 0x00000000 diff --git a/arch/arm/boards/embedsky-e9/lowlevel.c b/arch/arm/boards/embedsky-e9/lowlevel.c new file mode 100644 index 0000000000..fee1011700 --- /dev/null +++ b/arch/arm/boards/embedsky-e9/lowlevel.c @@ -0,0 +1,18 @@ +#include <common.h> +#include <sizes.h> +#include <mach/generic.h> +#include <asm/barebox-arm-head.h> +#include <asm/barebox-arm.h> + +extern char __dtb_imx6q_embedsky_e9_start[]; + +ENTRY_FUNCTION(start_imx6q_embedsky_e9, r0, r1, r2) +{ + void *fdt; + + imx6_cpu_lowlevel_init(); + + fdt = __dtb_imx6q_embedsky_e9_start - get_runtime_offset(); + + barebox_arm_entry(0x10000000, SZ_2G, fdt); +} diff --git a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c index 51b9ef8db7..7d1c1d5b2a 100644 --- a/arch/arm/boards/freescale-mx53-qsb/lowlevel.c +++ b/arch/arm/boards/freescale-mx53-qsb/lowlevel.c @@ -2,6 +2,7 @@ #include <mach/esdctl.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> +#include <image-metadata.h> extern char __dtb_imx53_qsb_start[]; diff --git a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c index a0ba86a6ec..ff1f04e87f 100644 --- a/arch/arm/boards/phytec-phycore-am335x/lowlevel.c +++ b/arch/arm/boards/phytec-phycore-am335x/lowlevel.c @@ -15,7 +15,7 @@ #include <mach/wdt.h> #include <debug_ll.h> -static const struct am33xx_cmd_control MT41J256M8HX15E_2x256M8_cmd = { +static const struct am33xx_cmd_control pcm051_cmd = { .slave_ratio0 = 0x40, .dll_lock_diff0 = 0x0, .invert_clkout0 = 0x1, @@ -27,23 +27,74 @@ static const struct am33xx_cmd_control MT41J256M8HX15E_2x256M8_cmd = { .invert_clkout2 = 0x1, }; -static const struct am33xx_emif_regs MT41J256M8HX15E_2x256M8_regs = { - .emif_read_latency = 0x6, - .emif_tim1 = 0x0668A39B, - .emif_tim2 = 0x26337FDA, - .emif_tim3 = 0x501F830F, - .sdram_config = 0x61C04832, - .zq_config = 0x50074BE4, - .sdram_ref_ctrl = 0x0000093B, +struct pcm051_sdram_timings { + struct am33xx_emif_regs regs; + struct am33xx_ddr_data data; }; -static const struct am33xx_ddr_data MT41J256M8HX15E_2x256M8_data = { - .rd_slave_ratio0 = 0x3B, - .wr_dqs_slave_ratio0 = 0x85, - .fifo_we_slave_ratio0 = 0x100, - .wr_slave_ratio0 = 0xC1, - .use_rank0_delay = 0x01, - .dll_lock_diff0 = 0x0, +enum { + MT41J128M16125IT_1x256M16, + MT41J64M1615IT_1x128M16, + MT41J256M16HA15EIT_1x512M16, +}; + +struct pcm051_sdram_timings timings[] = { + /* 1x256M16 */ + [MT41J128M16125IT_1x256M16] = { + .regs = { + .emif_read_latency = 0x6, + .emif_tim1 = 0x0888A39B, + .emif_tim2 = 0x26337FDA, + .emif_tim3 = 0x501F830F, + .sdram_config = 0x61C04AB2, + .zq_config = 0x50074BE4, + .sdram_ref_ctrl = 0x0000093B, + }, + .data = { + .rd_slave_ratio0 = 0x3B, + .wr_dqs_slave_ratio0 = 0x3B, + .fifo_we_slave_ratio0 = 0x97, + .wr_slave_ratio0 = 0x76, + }, + }, + + /* 1x128M16 */ + [MT41J64M1615IT_1x128M16] = { + .regs = { + .emif_read_latency = 0x6, + .emif_tim1 = 0x0888A39B, + .emif_tim2 = 0x26247FDA, + .emif_tim3 = 0x501F821F, + .sdram_config = 0x61C04A32, + .zq_config = 0x50074BE4, + .sdram_ref_ctrl = 0x0000093B, + }, + .data = { + .rd_slave_ratio0 = 0x3A, + .wr_dqs_slave_ratio0 = 0x36, + .fifo_we_slave_ratio0 = 0xA2, + .wr_slave_ratio0 = 0x74, + }, + }, + + /* 1x512MB */ + [MT41J256M16HA15EIT_1x512M16] = { + .regs = { + .emif_read_latency = 0x6, + .emif_tim1 = 0x0888A39B, + .emif_tim2 = 0x26517FDA, + .emif_tim3 = 0x501F84EF, + .sdram_config = 0x61C04B32, + .zq_config = 0x50074BE4, + .sdram_ref_ctrl = 0x0000093B, + }, + .data = { + .rd_slave_ratio0 = 0x3B, + .wr_dqs_slave_ratio0 = 0x3B, + .fifo_we_slave_ratio0 = 0x96, + .wr_slave_ratio0 = 0x76, + }, + }, }; extern char __dtb_am335x_phytec_phycore_start[]; @@ -57,9 +108,10 @@ extern char __dtb_am335x_phytec_phycore_start[]; * * @return void */ -static noinline void pcm051_board_init(void) +static noinline void pcm051_board_init(int sdram) { void *fdt; + struct pcm051_sdram_timings *timing = &timings[sdram]; /* WDT1 is already running when the bootloader gets control * Disable it to avoid "random" resets @@ -72,9 +124,9 @@ static noinline void pcm051_board_init(void) am33xx_pll_init(MPUPLL_M_600, 25, DDRPLL_M_303); - am335x_sdram_init(0x18B, &MT41J256M8HX15E_2x256M8_cmd, - &MT41J256M8HX15E_2x256M8_regs, - &MT41J256M8HX15E_2x256M8_data); + am335x_sdram_init(0x18B, &pcm051_cmd, + &timing->regs, + &timing->data); am33xx_uart_soft_reset((void *)AM33XX_UART0_BASE); am33xx_enable_uart0_pin_mux(); @@ -83,10 +135,10 @@ static noinline void pcm051_board_init(void) fdt = __dtb_am335x_phytec_phycore_start - get_runtime_offset(); - barebox_arm_entry(0x80000000, SZ_512M, fdt); + am335x_barebox_entry(fdt); } -ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram, bootinfo, r1, r2) +static noinline void pcm051_board_entry(unsigned long bootinfo, int sdram) { am33xx_save_bootinfo((void *)bootinfo); @@ -99,7 +151,22 @@ ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram, bootinfo, r1, r2) relocate_to_current_adr(); setup_c(); - pcm051_board_init(); + pcm051_board_init(sdram); +} + +ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x256m16, bootinfo, r1, r2) +{ + pcm051_board_entry(bootinfo, MT41J128M16125IT_1x256M16); +} + +ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x128m16, bootinfo, r1, r2) +{ + pcm051_board_entry(bootinfo, MT41J64M1615IT_1x128M16); +} + +ENTRY_FUNCTION(start_am33xx_phytec_phycore_sram_1x512m16, bootinfo, r1, r2) +{ + pcm051_board_entry(bootinfo, MT41J256M16HA15EIT_1x512M16); } ENTRY_FUNCTION(start_am33xx_phytec_phycore_sdram, r0, r1, r2) @@ -108,5 +175,5 @@ ENTRY_FUNCTION(start_am33xx_phytec_phycore_sdram, r0, r1, r2) fdt = __dtb_am335x_phytec_phycore_start - get_runtime_offset(); - barebox_arm_entry(0x80000000, SZ_512M, fdt); + am335x_barebox_entry(fdt); } diff --git a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c index 55aae00954..1d08f0561a 100644 --- a/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c +++ b/arch/arm/boards/phytec-phyflex-imx6/lowlevel.c @@ -16,6 +16,7 @@ #include <common.h> #include <sizes.h> #include <io.h> +#include <image-metadata.h> #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <asm/sections.h> @@ -57,6 +58,11 @@ extern char __dtb_imx6q_phytec_pbab01_start[]; extern char __dtb_imx6dl_phytec_pbab01_start[]; extern char __dtb_imx6s_phytec_pbab01_start[]; +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_2G, IMD_TYPE_PARAMETER, "memsize=2048", 0); +BAREBOX_IMD_TAG_STRING(phyflex_mx6_memsize_4G, IMD_TYPE_PARAMETER, "memsize=4096", 0); + ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2) { void *fdt; @@ -65,6 +71,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_1gib, r0, r1, r2) arm_setup_stack(0x00920000 - 8); + IMD_USED(phyflex_mx6_memsize_1G); + if (IS_ENABLED(CONFIG_DEBUG_LL)) setup_uart(); @@ -81,6 +89,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_2gib, r0, r1, r2) arm_setup_stack(0x00920000 - 8); + IMD_USED(phyflex_mx6_memsize_2G); + if (IS_ENABLED(CONFIG_DEBUG_LL)) setup_uart(); @@ -97,6 +107,8 @@ ENTRY_FUNCTION(start_phytec_pbab01_4gib, r0, r1, r2) arm_setup_stack(0x00920000 - 8); + IMD_USED(phyflex_mx6_memsize_4G); + fdt = __dtb_imx6q_phytec_pbab01_start - get_runtime_offset(); barebox_arm_entry(0x10000000, 0xEFFFFFF8, fdt); @@ -110,6 +122,8 @@ ENTRY_FUNCTION(start_phytec_pbab01dl_1gib, r0, r1, r2) arm_setup_stack(0x00920000 - 8); + IMD_USED(phyflex_mx6_memsize_1G); + fdt = __dtb_imx6dl_phytec_pbab01_start - get_runtime_offset(); barebox_arm_entry(0x10000000, SZ_1G, fdt); @@ -123,6 +137,8 @@ ENTRY_FUNCTION(start_phytec_pbab01s_512mb, r0, r1, r2) arm_setup_stack(0x00920000 - 8); + IMD_USED(phyflex_mx6_memsize_512M); + fdt = __dtb_imx6s_phytec_pbab01_start - get_runtime_offset(); barebox_arm_entry(0x10000000, SZ_512M, fdt); diff --git a/arch/arm/boards/sama5d3_xplained/init.c b/arch/arm/boards/sama5d3_xplained/init.c index ae18863acd..ae84209cbb 100644 --- a/arch/arm/boards/sama5d3_xplained/init.c +++ b/arch/arm/boards/sama5d3_xplained/init.c @@ -57,21 +57,30 @@ static struct atmel_nand_data nand_pdata = { }; static struct sam9_smc_config sama5d3_xplained_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 1, - .ncs_write_setup = 0, - .nwe_setup = 1, + .ncs_read_setup = 1, + .nrd_setup = 2, + .ncs_write_setup = 1, + .nwe_setup = 2, - .ncs_read_pulse = 6, - .nrd_pulse = 4, + .ncs_read_pulse = 5, + .nrd_pulse = 3, .ncs_write_pulse = 5, .nwe_pulse = 3, - .read_cycle = 6, - .write_cycle = 5, + .read_cycle = 8, + .write_cycle = 8, .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 1, + .tdf_cycles = 3, + + .tclr = 3, + .tadl = 10, + .tar = 3, + .ocms = 0, + .trr = 4, + .twb = 5, + .rbnsel = 3, + .nfsel = 1 }; static void ek_add_device_nand(void) @@ -87,7 +96,7 @@ static void ek_add_device_nand(void) sama5d3_xplained_nand_smc_config.mode |= AT91_SMC_DBW_8; /* configure chip-select 3 (NAND) */ - sam9_smc_configure(0, 3, &sama5d3_xplained_nand_smc_config); + sama5_smc_configure(0, 3, &sama5d3_xplained_nand_smc_config); at91_add_device_nand(&nand_pdata); } diff --git a/arch/arm/boards/sama5d3xek/hw_version.c b/arch/arm/boards/sama5d3xek/hw_version.c index 450eb9f8a1..c809c37742 100644 --- a/arch/arm/boards/sama5d3xek/hw_version.c +++ b/arch/arm/boards/sama5d3xek/hw_version.c @@ -18,6 +18,7 @@ #include <fs.h> #include <fcntl.h> #include <libbb.h> +#include <libfile.h> #include <asm/armlinux.h> #include <of.h> diff --git a/arch/arm/boards/sama5d3xek/init.c b/arch/arm/boards/sama5d3xek/init.c index e078642242..743197fe47 100644 --- a/arch/arm/boards/sama5d3xek/init.c +++ b/arch/arm/boards/sama5d3xek/init.c @@ -72,21 +72,30 @@ static struct atmel_nand_data nand_pdata = { }; static struct sam9_smc_config cm_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 1, - .ncs_write_setup = 0, - .nwe_setup = 1, + .ncs_read_setup = 1, + .nrd_setup = 2, + .ncs_write_setup = 1, + .nwe_setup = 2, - .ncs_read_pulse = 6, - .nrd_pulse = 4, + .ncs_read_pulse = 5, + .nrd_pulse = 3, .ncs_write_pulse = 5, .nwe_pulse = 3, - .read_cycle = 6, - .write_cycle = 5, + .read_cycle = 8, + .write_cycle = 8, .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 1, + .tdf_cycles = 3, + + .tclr = 3, + .tadl = 10, + .tar = 3, + .ocms = 0, + .trr = 4, + .twb = 5, + .rbnsel = 3, + .nfsel = 1 }; static void ek_add_device_nand(void) @@ -102,7 +111,7 @@ static void ek_add_device_nand(void) cm_nand_smc_config.mode |= AT91_SMC_DBW_8; /* configure chip-select 3 (NAND) */ - sam9_smc_configure(0, 3, &cm_nand_smc_config); + sama5_smc_configure(0, 3, &cm_nand_smc_config); at91_add_device_nand(&nand_pdata); } diff --git a/arch/arm/boards/tqma53/lowlevel.c b/arch/arm/boards/tqma53/lowlevel.c index 0a67228008..cd87212555 100644 --- a/arch/arm/boards/tqma53/lowlevel.c +++ b/arch/arm/boards/tqma53/lowlevel.c @@ -5,6 +5,7 @@ #include <asm/barebox-arm-head.h> #include <asm/barebox-arm.h> #include <mach/imx5.h> +#include <image-metadata.h> extern char __dtb_imx53_mba53_start[]; @@ -34,6 +35,8 @@ static void __noreturn start_imx53_tqma53_common(void *fdt) imx53_barebox_entry(fdt); } +BAREBOX_IMD_TAG_STRING(tqma53_memsize_512M, IMD_TYPE_PARAMETER, "memsize=512", 0); + ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2) { void *fdt; @@ -42,6 +45,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2) arm_setup_stack(0xf8020000 - 8); + IMD_USED(tqma53_memsize_512M); + imx53_init_lowlevel_early(800); fdt = __dtb_imx53_mba53_start - get_runtime_offset(); @@ -49,6 +54,8 @@ ENTRY_FUNCTION(start_imx53_mba53_512mib, r0, r1, r2) start_imx53_tqma53_common(fdt); } +BAREBOX_IMD_TAG_STRING(tqma53_memsize_1G, IMD_TYPE_PARAMETER, "memsize=1024", 0); + ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2) { void *fdt; @@ -57,6 +64,8 @@ ENTRY_FUNCTION(start_imx53_mba53_1gib, r0, r1, r2) arm_setup_stack(0xf8020000 - 8); + IMD_USED(tqma53_memsize_1G); + imx53_init_lowlevel_early(800); fdt = __dtb_imx53_mba53_start - get_runtime_offset(); diff --git a/arch/arm/configs/am335x_defconfig b/arch/arm/configs/am335x_defconfig index 0c92c96e45..d3feb108a1 100644 --- a/arch/arm/configs/am335x_defconfig +++ b/arch/arm/configs/am335x_defconfig @@ -1,11 +1,11 @@ CONFIG_ARCH_OMAP=y CONFIG_BAREBOX_UPDATE_AM33XX_SPI_NOR_MLO=y +CONFIG_BAREBOX_UPDATE_AM33XX_NAND_XLOADSLOTS=y CONFIG_OMAP_MULTI_BOARDS=y CONFIG_MACH_BEAGLEBONE=y CONFIG_MACH_PCM051=y CONFIG_THUMB2_BAREBOX=y CONFIG_ARM_BOARD_APPEND_ATAG=y -CONFIG_CMD_ARM_MMUINFO=y CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y CONFIG_ARM_UNWIND=y CONFIG_MMU=y @@ -15,7 +15,6 @@ CONFIG_MALLOC_TLSF=y CONFIG_KALLSYMS=y CONFIG_RELOCATABLE=y CONFIG_PROMPT="barebox> " -CONFIG_LONGHELP=y CONFIG_HUSH_FANCY_PROMPT=y CONFIG_CMDLINE_EDITING=y CONFIG_AUTO_COMPLETE=y @@ -25,61 +24,63 @@ CONFIG_BLSPEC=y CONFIG_CONSOLE_ACTIVATE_NONE=y CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y CONFIG_DEBUG_INFO=y -CONFIG_CMD_EDIT=y -CONFIG_CMD_SLEEP=y -CONFIG_CMD_MSLEEP=y -CONFIG_CMD_SAVEENV=y -CONFIG_CMD_LOADENV=y -CONFIG_CMD_EXPORT=y -CONFIG_CMD_PRINTENV=y -CONFIG_CMD_READLINE=y -CONFIG_CMD_READF=y -CONFIG_CMD_LET=y -CONFIG_CMD_MENU=y -CONFIG_CMD_MENUTREE=y -CONFIG_CMD_TIME=y -CONFIG_CMD_LN=y -CONFIG_CMD_TFTP=y -CONFIG_CMD_FILETYPE=y -CONFIG_CMD_ECHO_E=y -CONFIG_CMD_LOADB=y -CONFIG_CMD_MEMINFO=y +CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y -CONFIG_CMD_MM=y -CONFIG_CMD_CRC=y -CONFIG_CMD_CRC_CMP=y -CONFIG_CMD_MD5SUM=y -CONFIG_CMD_FLASH=y -CONFIG_CMD_UBIFORMAT=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_ARM_MMUINFO=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_BOOTM_VERBOSE=y CONFIG_CMD_BOOTM_INITRD=y CONFIG_CMD_BOOTM_OFTREE=y -CONFIG_CMD_UIMAGE=y -CONFIG_CMD_BOOTZ=y # CONFIG_CMD_BOOTU is not set -CONFIG_CMD_RESET=y +CONFIG_CMD_BOOTZ=y CONFIG_CMD_GO=y -CONFIG_CMD_OFTREE=y -CONFIG_CMD_OF_PROPERTY=y -CONFIG_CMD_OF_NODE=y -CONFIG_CMD_BAREBOX_UPDATE=y -CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_RESET=y +CONFIG_CMD_UIMAGE=y CONFIG_CMD_PARTITION=y +CONFIG_CMD_UBIFORMAT=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y CONFIG_CMD_MAGICVAR=y CONFIG_CMD_MAGICVAR_HELP=y -CONFIG_CMD_GPIO=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_READF=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_MIITOOL=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENUTREE=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MM=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_GPIO=y CONFIG_CMD_I2C=y -CONFIG_CMD_SPI=y CONFIG_CMD_LED=y +CONFIG_CMD_SPI=y CONFIG_CMD_LED_TRIGGER=y -CONFIG_CMD_MIITOOL=y -CONFIG_CMD_DETECT=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y CONFIG_NET=y -CONFIG_CMD_DHCP=y CONFIG_NET_NFS=y -CONFIG_CMD_PING=y CONFIG_NET_NETCONSOLE=y CONFIG_NET_RESOLV=y CONFIG_OFDEVICE=y diff --git a/arch/arm/configs/am335x_mlo_defconfig b/arch/arm/configs/am335x_mlo_defconfig index b8dc4e04ec..19f78d0ae8 100644 --- a/arch/arm/configs/am335x_mlo_defconfig +++ b/arch/arm/configs/am335x_mlo_defconfig @@ -1,4 +1,5 @@ CONFIG_ARCH_OMAP=y +CONFIG_OMAP_BUILD_IFT=y CONFIG_OMAP_MULTI_BOARDS=y CONFIG_MACH_BEAGLEBONE=y CONFIG_MACH_PCM051=y diff --git a/arch/arm/configs/canon-a1100_defconfig b/arch/arm/configs/canon-a1100_defconfig new file mode 100644 index 0000000000..5c1e195a2d --- /dev/null +++ b/arch/arm/configs/canon-a1100_defconfig @@ -0,0 +1,56 @@ +CONFIG_BUILTIN_DTB=y +CONFIG_BUILTIN_DTB_NAME="canon-a1100" +CONFIG_ARCH_DIGIC=y +CONFIG_ARM_OPTIMZED_STRING_FUNCTIONS=y +CONFIG_PBL_IMAGE=y +CONFIG_IMAGE_COMPRESSION_LZ4=y +CONFIG_TEXT_BASE=0x00300000 +CONFIG_MALLOC_SIZE=0x200000 +CONFIG_PROMPT="canon-a1100 > " +CONFIG_GLOB=y +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +# CONFIG_DEFAULT_ENVIRONMENT is not set +CONFIG_DEBUG_LL=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MEMINFO=y +# CONFIG_CMD_BOOTM is not set +# CONFIG_CMD_BOOTU is not set +CONFIG_CMD_GO=y +CONFIG_CMD_LOADY=y +# CONFIG_CMD_MOUNT is not set +# CONFIG_CMD_UMOUNT is not set +CONFIG_CMD_EXPORT=y +CONFIG_CMD_GLOBAL=y +CONFIG_CMD_MD5SUM=y +# CONFIG_CMD_PWD is not set +CONFIG_CMD_SHA1SUM=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_SLEEP=y +# CONFIG_CMD_CLEAR is not set +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MEMTEST=y +CONFIG_CMD_MM=y +CONFIG_CMD_GPIO=y +CONFIG_CMD_LED=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OFTREE=y +CONFIG_OFDEVICE=y +CONFIG_DRIVER_SERIAL_DIGIC=y +# CONFIG_SPI is not set +CONFIG_MTD=y +# CONFIG_MTD_WRITE is not set +CONFIG_DRIVER_CFI=y +# CONFIG_DRIVER_CFI_BANK_WIDTH_1 is not set +CONFIG_CLOCKSOURCE_DUMMY=y +CONFIG_CLOCKSOURCE_DUMMY_RATE=2000 +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_GPIO_DIGIC=y +CONFIG_ZLIB=y diff --git a/arch/arm/configs/imx_v7_defconfig b/arch/arm/configs/imx_v7_defconfig index 66fc123223..0a4f2fe129 100644 --- a/arch/arm/configs/imx_v7_defconfig +++ b/arch/arm/configs/imx_v7_defconfig @@ -16,6 +16,7 @@ CONFIG_MACH_SABRELITE=y CONFIG_MACH_SABRESD=y CONFIG_MACH_NITROGEN6X=y CONFIG_MACH_SOLIDRUN_MICROSOM=y +CONFIG_MACH_EMBEDSKY_E9=y CONFIG_MACH_EMBEST_RIOTBOARD=y CONFIG_MACH_UDOO=y CONFIG_MACH_VARISCITE_MX6=y diff --git a/arch/arm/cpu/Kconfig b/arch/arm/cpu/Kconfig index aed4cb7c63..fb1a9998b0 100644 --- a/arch/arm/cpu/Kconfig +++ b/arch/arm/cpu/Kconfig @@ -39,6 +39,19 @@ config CPU_ARM926T Say Y if you want support for the ARM926T processor. Otherwise, say N. +# ARM946E-S +config CPU_ARM946E + bool + depends on !MMU + select CPU_32v4T + help + ARM946E-S is a member of the ARM9E-S family of high- + performance, 32-bit system-on-chip processor solutions. + The TCM and ARMv5TE 32-bit instruction set is supported. + + Say Y if you want support for the ARM946E-S processor. + Otherwise, say N. + # Feroceon config CPU_FEROCEON bool diff --git a/arch/arm/cpu/dtb.c b/arch/arm/cpu/dtb.c index abc3ccb4c0..ae4ff2a9ad 100644 --- a/arch/arm/cpu/dtb.c +++ b/arch/arm/cpu/dtb.c @@ -50,6 +50,7 @@ static int of_arm_init(void) root = of_unflatten_dtb(fdt); if (root) { of_set_root_node(root); + of_fix_tree(root); if (IS_ENABLED(CONFIG_OFDEVICE)) of_probe(); } diff --git a/arch/arm/cpu/mmu.c b/arch/arm/cpu/mmu.c index bf0141b946..e4afcc8411 100644 --- a/arch/arm/cpu/mmu.c +++ b/arch/arm/cpu/mmu.c @@ -188,6 +188,7 @@ void *map_io_sections(unsigned long phys, void *_start, size_t size) for (sec = start; sec < start + size; sec += (1 << 20)) ttb[sec >> 20] = (phys++ << 20) | PMD_SECT_DEF_UNCACHED; + dma_flush_range((unsigned long)ttb, (unsigned long)ttb + 0x4000); tlb_invalidate(); return _start; } diff --git a/arch/arm/cpu/start.c b/arch/arm/cpu/start.c index 961873d6bb..264420d084 100644 --- a/arch/arm/cpu/start.c +++ b/arch/arm/cpu/start.c @@ -103,7 +103,7 @@ static noinline __noreturn void __start(unsigned long membase, /* * Maximum malloc space is the Kconfig value if given - * or 64MB. + * or 1GB. */ if (MALLOC_SIZE > 0) { malloc_start = malloc_end - MALLOC_SIZE; @@ -111,8 +111,8 @@ static noinline __noreturn void __start(unsigned long membase, malloc_start = membase; } else { malloc_start = malloc_end - (malloc_end - membase) / 2; - if (malloc_end - malloc_start > SZ_64M) - malloc_start = malloc_end - SZ_64M; + if (malloc_end - malloc_start > SZ_1G) + malloc_start = malloc_end - SZ_1G; } mem_malloc_init((void *)malloc_start, (void *)malloc_end - 1); diff --git a/arch/arm/dts/Makefile b/arch/arm/dts/Makefile index 72ad5e6a6f..fac2b273cb 100644 --- a/arch/arm/dts/Makefile +++ b/arch/arm/dts/Makefile @@ -1,93 +1,47 @@ -dtb-$(CONFIG_ARCH_AM33XX) += \ - am335x-bone.dtb \ - am335x-boneblack.dtb \ - am335x-bone-common.dtb \ - am335x-phytec-phycore.dtb -dtb-$(CONFIG_ARCH_IMX25) += imx25-karo-tx25.dtb -dtb-$(CONFIG_ARCH_IMX27) += imx27-phytec-phycard-s-rdk-bb.dtb \ - imx27-phytec-phycore-rdk.dtb -dtb-$(CONFIG_ARCH_IMX51) += imx51-babbage.dtb \ - imx51-genesi-efika-sb.dtb -dtb-$(CONFIG_ARCH_IMX53) += imx53-mba53.dtb \ - imx53-qsb.dtb \ - imx53-qsrb.dtb \ - imx53-voipac-bsb.dtb -dtb-$(CONFIG_ARCH_IMX6) += imx6q-gk802.dtb \ - imx6dl-dfi-fs700-m60-6s.dtb \ - imx6q-dfi-fs700-m60-6q.dtb \ - imx6q-dmo-edmqmx6.dtb \ - imx6q-sabrelite.dtb \ - imx6dl-sabrelite.dtb \ - imx6q-sabresd.dtb \ - imx6dl-mba6x.dtb \ - imx6q-mba6x.dtb \ - imx6dl-phytec-pbab01.dtb \ - imx6q-phytec-pbab01.dtb \ - imx6s-phytec-pbab01.dtb \ - imx6dl-hummingboard.dtb \ - imx6q-guf-santaro.dtb \ - imx6q-nitrogen6x.dtb \ - imx6dl-nitrogen6x.dtb \ - imx6q-udoo.dtb \ - imx6q-var-custom.dtb \ - imx6s-riotboard.dtb \ - imx6q-phytec-pbaa03.dtb -dtb-$(CONFIG_ARCH_ROCKCHIP) += rk3188-radxarock.dtb -dtb-$(CONFIG_ARCH_SOCFPGA) += socfpga_cyclone5_sockit.dtb \ - socfpga_cyclone5_socrates.dtb -dtb-$(CONFIG_ARCH_TEGRA) += \ - tegra20-colibri-iris.dtb \ - tegra20-paz00.dtb \ - tegra30-beaver.dtb \ - tegra124-jetson-tk1.dtb - BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)) -obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o - -pbl-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o -pbl-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o -pbl-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o -pbl-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o -pbl-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o -pbl-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o -pbl-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o -pbl-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o -pbl-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o -pbl-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o -pbl-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o -pbl-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o -pbl-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o -pbl-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o -pbl-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o -pbl-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o -pbl-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o -pbl-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o -pbl-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o -pbl-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o -pbl-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o -pbl-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o -pbl-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o -pbl-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o -pbl-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o -pbl-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o -pbl-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o -pbl-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o -pbl-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o -pbl-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o -pbl-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o -pbl-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o -pbl-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o -pbl-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o -pbl-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o -pbl-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o -pbl-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o - -.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S -.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y)) +obj-dtb-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o -targets += dtbs -targets += $(dtb-y) +# just to build a built-in.o. Otherwise compilation fails when no devicetree is +# created. +obj-y += empty.o -extra-y += $(dtb-y) +pbl-dtb-$(CONFIG_MACH_BEAGLEBONE) += am335x-bone.dtb.o am335x-boneblack.dtb.o am335x-bone-common.dtb.o +pbl-dtb-$(CONFIG_MACH_DFI_FS700_M60) += imx6q-dfi-fs700-m60-6q.dtb.o imx6dl-dfi-fs700-m60-6s.dtb.o +pbl-dtb-$(CONFIG_MACH_EFIKA_MX_SMARTBOOK) += imx51-genesi-efika-sb.dtb.o +pbl-dtb-$(CONFIG_MACH_EMBEST_RIOTBOARD) += imx6s-riotboard.dtb.o +pbl-dtb-$(CONFIG_MACH_EMBEDSKY_E9) += imx6q-embedsky-e9.dtb.o +pbl-dtb-$(CONFIG_MACH_FREESCALE_MX51_PDK) += imx51-babbage.dtb.o +pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_LOCO) += imx53-qsb.dtb.o imx53-qsrb.dtb.o +pbl-dtb-$(CONFIG_MACH_FREESCALE_MX53_VMX53) += imx53-voipac-bsb.dtb.o +pbl-dtb-$(CONFIG_MACH_GK802) += imx6q-gk802.dtb.o +pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_GURUPLUG) += kirkwood-guruplug-server-plus-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_GLOBALSCALE_MIRABOX) += armada-370-mirabox-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_GUF_SANTARO) += imx6q-guf-santaro.dtb.o +pbl-dtb-$(CONFIG_MACH_MARVELL_ARMADA_XP_GP) += armada-xp-gp-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_NITROGEN6X) += imx6q-nitrogen6x.dtb.o imx6dl-nitrogen6x.dtb.o +pbl-dtb-$(CONFIG_MACH_NVIDIA_BEAVER) += tegra30-beaver.dtb.o +pbl-dtb-$(CONFIG_MACH_NVIDIA_JETSON) += tegra124-jetson-tk1.dtb.o +pbl-dtb-$(CONFIG_MACH_PCA100) += imx27-phytec-phycard-s-rdk-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_PCAAXL3) += imx6q-phytec-pbaa03.dtb.o +pbl-dtb-$(CONFIG_MACH_PCM038) += imx27-phytec-phycore-rdk.dtb.o +pbl-dtb-$(CONFIG_MACH_PCM051) += am335x-phytec-phycore.dtb.o +pbl-dtb-$(CONFIG_MACH_PHYTEC_PFLA02) += imx6s-phytec-pbab01.dtb.o imx6dl-phytec-pbab01.dtb.o imx6q-phytec-pbab01.dtb.o +pbl-dtb-$(CONFIG_MACH_PLATHOME_OPENBLOCKS_AX3) += armada-xp-openblocks-ax3-4-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_RADXA_ROCK) += rk3188-radxarock.dtb.o +pbl-dtb-$(CONFIG_MACH_REALQ7) += imx6q-dmo-edmqmx6.dtb.o +pbl-dtb-$(CONFIG_MACH_SABRELITE) += imx6q-sabrelite.dtb.o imx6dl-sabrelite.dtb.o +pbl-dtb-$(CONFIG_MACH_SABRESD) += imx6q-sabresd.dtb.o +pbl-dtb-$(CONFIG_MACH_SOCFPGA_EBV_SOCRATES) += socfpga_cyclone5_socrates.dtb.o +pbl-dtb-$(CONFIG_MACH_SOCFPGA_TERASIC_SOCKIT) += socfpga_cyclone5_sockit.dtb.o +pbl-dtb-$(CONFIG_MACH_SOLIDRUN_CUBOX) += dove-cubox-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_SOLIDRUN_MICROSOM) += imx6dl-hummingboard.dtb.o +pbl-dtb-$(CONFIG_MACH_TORADEX_COLIBRI_T20) += tegra20-colibri-iris.dtb.o +pbl-dtb-$(CONFIG_MACH_TOSHIBA_AC100) += tegra20-paz00.dtb.o +pbl-dtb-$(CONFIG_MACH_TQMA53) += imx53-mba53.dtb.o +pbl-dtb-$(CONFIG_MACH_TQMA6X) += imx6dl-mba6x.dtb.o imx6q-mba6x.dtb.o +pbl-dtb-$(CONFIG_MACH_TX25) += imx25-karo-tx25.dtb.o +pbl-dtb-$(CONFIG_MACH_UDOO) += imx6q-udoo.dtb.o +pbl-dtb-$(CONFIG_MACH_USI_TOPKICK) += kirkwood-topkick-bb.dtb.o +pbl-dtb-$(CONFIG_MACH_VARISCITE_MX6) += imx6q-var-custom.dtb.o clean-files := *.dtb *.dtb.S .*.dtc .*.pre .*.dts diff --git a/arch/arm/dts/am335x-bone-common.dtsi b/arch/arm/dts/am335x-bone-common.dtsi index 4cf7fdbb48..e1effac323 100644 --- a/arch/arm/dts/am335x-bone-common.dtsi +++ b/arch/arm/dts/am335x-bone-common.dtsi @@ -276,13 +276,14 @@ pinctrl-names = "default", "sleep"; pinctrl-0 = <&cpsw_default>; pinctrl-1 = <&cpsw_sleep>; - + status = "okay"; }; &davinci_mdio { pinctrl-names = "default", "sleep"; pinctrl-0 = <&davinci_mdio_default>; pinctrl-1 = <&davinci_mdio_sleep>; + status = "okay"; }; &mmc1 { diff --git a/arch/arm/dts/am335x-phytec-phycore.dts b/arch/arm/dts/am335x-phytec-phycore.dts index 6196eb3244..5678138f66 100644 --- a/arch/arm/dts/am335x-phytec-phycore.dts +++ b/arch/arm/dts/am335x-phytec-phycore.dts @@ -22,11 +22,6 @@ }; }; - memory { - device_type = "memory"; - reg = <0x80000000 0x20000000>; /* 512 MB */ - }; - gpio-leds { compatible = "gpio-leds"; pinctrl-names = "default"; @@ -214,6 +209,7 @@ &davinci_mdio { pinctrl-names = "default"; pinctrl-0 = <&davinci_mdio_default>; + status = "okay"; }; &phy_sel { @@ -236,6 +232,7 @@ pinctrl-names = "default"; pinctrl-0 = <&emac_rmii1_pins>; dual_emac = <1>; + status = "okay"; }; &gpmc { diff --git a/arch/arm/dts/armada-370-mirabox-bb.dts b/arch/arm/dts/armada-370-mirabox-bb.dts index de37a75bb9..315678151a 100644 --- a/arch/arm/dts/armada-370-mirabox-bb.dts +++ b/arch/arm/dts/armada-370-mirabox-bb.dts @@ -11,9 +11,6 @@ }; soc { - ranges = <MBUS_ID(0xf0, 0x01) 0 0xf1000000 0x100000 - MBUS_ID(0x01, 0xe0) 0 0xfff00000 0x100000>; - internal-regs { gpio_leds { green_pwr_led { diff --git a/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts b/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts index 611d72707f..e88f1dc781 100644 --- a/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts +++ b/arch/arm/dts/armada-xp-openblocks-ax3-4-bb.dts @@ -11,10 +11,6 @@ }; soc { - ranges = <MBUS_ID(0xf0, 0x01) 0 0 0xf1000000 0x100000 - MBUS_ID(0x01, 0x1d) 0 0 0xfff00000 0x100000 - MBUS_ID(0x01, 0x2f) 0 0 0xf0000000 0x8000000>; - internal-regs { gpio_leds { red_led { diff --git a/arch/arm/dts/canon-a1100.dts b/arch/arm/dts/canon-a1100.dts new file mode 100644 index 0000000000..a88eacf4d4 --- /dev/null +++ b/arch/arm/dts/canon-a1100.dts @@ -0,0 +1,35 @@ +/dts-v1/; + +/include/ "digic4.dtsi" + +/ { + model = "Canon PowerShot A1100 IS"; + compatible = "canon,a1100"; + + memory { + reg = <0x00000000 0x04000000>; + }; + + flash@f8000000 { + compatible = "cfi-flash"; + reg = <0xf8000000 0x08000000>; + }; + + leds { + compatible = "gpio-leds"; + + direct_print { + label = "direct-print (blue)"; + gpios = <&gpio 51 0>; + }; + + auto_focus { + label = "auto-focus (red)"; + gpios = <&gpio 55 0>; + }; + }; +}; + +&timer2 { + status = "okay"; +}; diff --git a/arch/arm/dts/digic4.dtsi b/arch/arm/dts/digic4.dtsi new file mode 100644 index 0000000000..21b004d4a2 --- /dev/null +++ b/arch/arm/dts/digic4.dtsi @@ -0,0 +1,42 @@ +/include/ "skeleton.dtsi" + +/ { + compatible = "canon,digic4"; + + timer0: timer@c0210000 { + compatible = "canon,digic-timer"; + reg = <0xc0210000 0x1c>; + status = "disabled"; + }; + + timer1: timer@c0210100 { + compatible = "canon,digic-timer"; + reg = <0xc0210100 0x1c>; + status = "disabled"; + }; + + timer2: timer@c0210200 { + compatible = "canon,digic-timer"; + reg = <0xc0210200 0x1c>; + status = "disabled"; + }; + + /* + * I don't know real max GPIO number but this page + * http://magiclantern.wikia.com/wiki/Register_Map#GPIO_Ports + * says about 93 pins on 5DMkIII. + * Assume that DIGIC4 has at least 96 pins. + * So resource size is 96 * 4 = 0x180. + */ + gpio: gpio { + compatible = "canon,digic-gpio"; + reg = <0xc0220000 0x180>; + #gpio-cells = <2>; + gpio-controller; + }; + + uart: uart { + compatible = "canon,digic-uart"; + reg = <0xc0800000 0x1c>; + }; +}; diff --git a/arch/arm/dts/empty.c b/arch/arm/dts/empty.c new file mode 100644 index 0000000000..d141224cf8 --- /dev/null +++ b/arch/arm/dts/empty.c @@ -0,0 +1,3 @@ +static inline void empty(void) +{ +} diff --git a/arch/arm/dts/imx6q-embedsky-e9.dts b/arch/arm/dts/imx6q-embedsky-e9.dts new file mode 100644 index 0000000000..14f6d5fe15 --- /dev/null +++ b/arch/arm/dts/imx6q-embedsky-e9.dts @@ -0,0 +1,42 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/dts-v1/; + +#include "imx6q.dtsi" +#include <arm/imx6q-embedsky-e9.dtsi> + +/ { + chosen { + linux,stdout-path = &uart4; + + environment@0 { + compatible = "barebox,environment"; + device-path = &usdhc2, "partname:barebox-environment"; + }; + + }; +}; + +&usdhc2 { + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "barebox"; + reg = <0x0 0x80000>; + }; + partition@1 { + label = "barebox-environment"; + reg = <0x80000 0x80000>; + }; +}; diff --git a/arch/arm/lib/barebox.lds.S b/arch/arm/lib/barebox.lds.S index d9588736f8..bb0354ae29 100644 --- a/arch/arm/lib/barebox.lds.S +++ b/arch/arm/lib/barebox.lds.S @@ -75,6 +75,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data*) } + .barebox_imd : { BAREBOX_IMD } + . = .; __barebox_cmd_start = .; .barebox_cmd : { BAREBOX_CMDS } diff --git a/arch/arm/lib/bootm.c b/arch/arm/lib/bootm.c index 4896d01976..baf0946a47 100644 --- a/arch/arm/lib/bootm.c +++ b/arch/arm/lib/bootm.c @@ -6,6 +6,7 @@ #include <image.h> #include <init.h> #include <fs.h> +#include <libfile.h> #include <linux/list.h> #include <xfuncs.h> #include <malloc.h> @@ -314,7 +315,7 @@ static int do_bootz_linux(struct image_data *data) image_size - sizeof(*header)); if (ret < 0) goto err_out; - if (ret < end - sizeof(*header)) { + if (ret < image_size - sizeof(*header)) { printf("premature end of image\n"); ret = -EIO; goto err_out; @@ -414,6 +415,11 @@ static int do_bootm_aimage(struct image_data *data) int to_read; struct android_header_comp *cmp; unsigned long mem_free; + unsigned long mem_start, mem_size; + + ret = sdram_start_and_size(&mem_start, &mem_size); + if (ret) + return ret; fd = open(data->os_file, O_RDONLY); if (fd < 0) { @@ -447,8 +453,17 @@ static int do_bootm_aimage(struct image_data *data) cmp = &header->kernel; data->os_res = request_sdram_region("akernel", cmp->load_addr, cmp->size); if (!data->os_res) { - ret = -ENOMEM; - goto err_out; + pr_err("Cannot request region 0x%08x - 0x%08x, using default load address\n", + cmp->load_addr, cmp->size); + + data->os_address = mem_start + PAGE_ALIGN(cmp->size * 4); + data->os_res = request_sdram_region("akernel", data->os_address, cmp->size); + if (!data->os_res) { + pr_err("Cannot request region 0x%08x - 0x%08x\n", + cmp->load_addr, cmp->size); + ret = -ENOMEM; + goto err_out; + } } ret = aimage_load_resource(fd, data->os_res, buf, header->page_size); diff --git a/arch/arm/lib/pbl.lds.S b/arch/arm/lib/pbl.lds.S index 76184a0eec..9afee2964a 100644 --- a/arch/arm/lib/pbl.lds.S +++ b/arch/arm/lib/pbl.lds.S @@ -54,6 +54,8 @@ SECTIONS . = ALIGN(4); .rodata : { *(.rodata*) } + .barebox_imd : { BAREBOX_IMD } + _etext = .; /* End of text and rodata section */ . = ALIGN(4); diff --git a/arch/arm/mach-at91/at91sam926x_lowlevel_init.c b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c index 985203ae59..e69e4a86bf 100644 --- a/arch/arm/mach-at91/at91sam926x_lowlevel_init.c +++ b/arch/arm/mach-at91/at91sam926x_lowlevel_init.c @@ -130,7 +130,7 @@ void __bare_init at91sam926x_lowlevel_init(struct at91sam926x_lowlevel_cfg *cfg) at91_sys_write(cfg->matrix_csa, cfg->ebi_csa); /* flash */ - at91_smc_write(cfg->smc_cs, AT91_SMC_MODE, cfg->smc_mode); + at91_smc_write(cfg->smc_cs, AT91_SAM9_SMC_MODE, cfg->smc_mode); at91_smc_write(cfg->smc_cs, AT91_SMC_CYCLE, cfg->smc_cycle); diff --git a/arch/arm/mach-at91/boot_test_cmd.c b/arch/arm/mach-at91/boot_test_cmd.c index 66c598b7ce..4fd1998ad0 100644 --- a/arch/arm/mach-at91/boot_test_cmd.c +++ b/arch/arm/mach-at91/boot_test_cmd.c @@ -7,6 +7,7 @@ #include <common.h> #include <command.h> #include <libbb.h> +#include <libfile.h> #include <getopt.h> #include <fs.h> #include <fcntl.h> diff --git a/arch/arm/mach-at91/clock.c b/arch/arm/mach-at91/clock.c index 59c4d1111f..9d2a846447 100644 --- a/arch/arm/mach-at91/clock.c +++ b/arch/arm/mach-at91/clock.c @@ -65,7 +65,7 @@ #define cpu_has_pllb() (!(cpu_is_at91sam9rl() \ || cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ - || cpu_is_at91sam9n12())) + || cpu_is_sama5d3())) #define cpu_has_upll() (cpu_is_at91sam9g45() \ || cpu_is_at91sam9x5() \ diff --git a/arch/arm/mach-at91/include/mach/at91sam9_smc.h b/arch/arm/mach-at91/include/mach/at91sam9_smc.h index d5cf5f762d..d19cf82eca 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9_smc.h +++ b/arch/arm/mach-at91/include/mach/at91sam9_smc.h @@ -43,12 +43,24 @@ struct sam9_smc_config { /* Mode register */ u32 mode; u8 tdf_cycles:4; + + /* Timings register */ + u8 tclr; + u8 tadl; + u8 tar; + u8 ocms; + u8 trr; + u8 twb; + u8 rbnsel; + u8 nfsel; }; extern void sam9_smc_configure(int id, int cs, struct sam9_smc_config *config); extern void sam9_smc_read(int id, int cs, struct sam9_smc_config *config); extern void sam9_smc_read_mode(int id, int cs, struct sam9_smc_config *config); extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config); + +extern void sama5_smc_configure(int id, int cs, struct sam9_smc_config *config); #endif #define AT91_SMC_SETUP 0x00 /* Setup Register for CS n */ @@ -77,7 +89,26 @@ extern void sam9_smc_write_mode(int id, int cs, struct sam9_smc_config *config); #define AT91_SMC_NRDCYCLE (0x1ff << 16) /* Total Read Cycle Length */ #define AT91_SMC_NRDCYCLE_(x) ((x) << 16) -#define AT91_SMC_MODE 0x0c /* Mode Register for CS n */ +#define AT91_SAMA5_SMC_TIMINGS 0x0c /* Timings register for CS n */ +#define AT91_SMC_TCLR (0x0f << 0) /* CLE to REN Low Delay */ +#define AT91_SMC_TCLR_(x) ((x) << 0) +#define AT91_SMC_TADL (0x0f << 4) /* ALE to Data Start */ +#define AT91_SMC_TADL_(x) ((x) << 4) +#define AT91_SMC_TAR (0x0f << 8) /* ALE to REN Low Delay */ +#define AT91_SMC_TAR_(x) ((x) << 8) +#define AT91_SMC_OCMS (0x1 << 12) /* Off Chip Memory Scrambling Enable */ +#define AT91_SMC_OCMS_(x) ((x) << 12) +#define AT91_SMC_TRR (0x0f << 16) /* Ready to REN Low Delay */ +#define AT91_SMC_TRR_(x) ((x) << 16) +#define AT91_SMC_TWB (0x0f << 24) /* WEN High to REN to Busy */ +#define AT91_SMC_TWB_(x) ((x) << 24) +#define AT91_SMC_RBNSEL (0x07 << 28) /* Ready/Busy Line Selection */ +#define AT91_SMC_RBNSEL_(x) ((x) << 28) +#define AT91_SMC_NFSEL (0x01 << 31) /* Nand Flash Selection */ +#define AT91_SMC_NFSEL_(x) ((x) << 31) + +#define AT91_SAM9_SMC_MODE 0xc +#define AT91_SAMA5_SMC_MODE 0x10 #define AT91_SMC_READMODE (1 << 0) /* Read Mode */ #define AT91_SMC_WRITEMODE (1 << 1) /* Write Mode */ #define AT91_SMC_EXNWMODE (3 << 4) /* NWAIT Mode */ diff --git a/arch/arm/mach-at91/sam9_smc.c b/arch/arm/mach-at91/sam9_smc.c index c7bfdfda63..9f028079c2 100644 --- a/arch/arm/mach-at91/sam9_smc.c +++ b/arch/arm/mach-at91/sam9_smc.c @@ -17,7 +17,9 @@ #include <mach/at91sam9_smc.h> -#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? 0x14 : 0x10) +#define AT91_SAM9_SMC_CS_STRIDE 0x10 +#define AT91_SAMA5_SMC_CS_STRIDE 0x14 +#define AT91_SMC_CS_STRIDE ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_CS_STRIDE : AT91_SAM9_SMC_CS_STRIDE) #define AT91_SMC_CS(id, n) (smc_base_addr[id] + ((n) * AT91_SMC_CS_STRIDE)) static void __iomem *smc_base_addr[2]; @@ -25,9 +27,27 @@ static void __iomem *smc_base_addr[2]; static void sam9_smc_cs_write_mode(void __iomem *base, struct sam9_smc_config *config) { + void __iomem *mode_reg; + + mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE); + __raw_writel(config->mode | AT91_SMC_TDF_(config->tdf_cycles), - base + AT91_SMC_MODE); + mode_reg); +} + +static void sam9_smc_cs_write_timings(void __iomem *base, + struct sam9_smc_config *config) +{ + __raw_writel(AT91_SMC_TCLR_(config->tclr) + | AT91_SMC_TADL_(config->tadl) + | AT91_SMC_TAR_(config->tar) + | AT91_SMC_OCMS_(config->ocms) + | AT91_SMC_TRR_(config->trr) + | AT91_SMC_TWB_(config->twb) + | AT91_SMC_RBNSEL_(config->rbnsel) + | AT91_SMC_NFSEL_(config->nfsel), + base + AT91_SAMA5_SMC_TIMINGS); } void sam9_smc_write_mode(int id, int cs, @@ -72,7 +92,12 @@ void sam9_smc_configure(int id, int cs, static void sam9_smc_cs_read_mode(void __iomem *base, struct sam9_smc_config *config) { - u32 val = __raw_readl(base + AT91_SMC_MODE); + u32 val; + void __iomem *mode_reg; + + mode_reg = base + ((at91_soc_initdata.type == AT91_SOC_SAMA5D3) ? AT91_SAMA5_SMC_MODE : AT91_SAM9_SMC_MODE); + + val = __raw_readl(mode_reg); config->mode = (val & ~AT91_SMC_NWECYCLE); config->tdf_cycles = (val & AT91_SMC_NWECYCLE) >> 16 ; @@ -120,6 +145,13 @@ void sam9_smc_read(int id, int cs, struct sam9_smc_config *config) sam9_smc_cs_read(AT91_SMC_CS(id, cs), config); } +void sama5_smc_configure(int id, int cs, struct sam9_smc_config *config) +{ + sam9_smc_configure(id, cs, config); + + sam9_smc_cs_write_timings(AT91_SMC_CS(id, cs), config); +} + static int at91sam9_smc_probe(struct device_d *dev) { int id = dev->id; diff --git a/arch/arm/mach-digic/Kconfig b/arch/arm/mach-digic/Kconfig new file mode 100644 index 0000000000..d25c3b3f51 --- /dev/null +++ b/arch/arm/mach-digic/Kconfig @@ -0,0 +1,15 @@ +if ARCH_DIGIC + +choice + prompt "camera type" + +config MACH_CANON_A1100 + bool "Canon PowerShot A1100 IS" + +endchoice + +config ARCH_TEXT_BASE + hex + default 0x00001900 if MACH_CANON_A1100 + +endif diff --git a/arch/arm/mach-digic/Makefile b/arch/arm/mach-digic/Makefile new file mode 100644 index 0000000000..820eb10ac2 --- /dev/null +++ b/arch/arm/mach-digic/Makefile @@ -0,0 +1 @@ +obj-y += core.o diff --git a/arch/arm/mach-digic/core.c b/arch/arm/mach-digic/core.c new file mode 100644 index 0000000000..b1caec0bc8 --- /dev/null +++ b/arch/arm/mach-digic/core.c @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> + +void __noreturn reset_cpu(unsigned long ignored) +{ + pr_err("%s: unimplemented\n", __func__); + hang(); +} +EXPORT_SYMBOL(reset_cpu); diff --git a/arch/arm/mach-digic/include/mach/debug_ll.h b/arch/arm/mach-digic/include/mach/debug_ll.h new file mode 100644 index 0000000000..721fd444c2 --- /dev/null +++ b/arch/arm/mach-digic/include/mach/debug_ll.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#include <io.h> +#include <mach/digic4.h> +#include <mach/uart.h> + +#define DEBUG_LL_UART DIGIC4_UART + +/* Serial interface registers */ +#define DEBUG_LL_UART_TX (DEBUG_LL_UART + DIGIC_UART_TX) +#define DEBUG_LL_UART_ST (DEBUG_LL_UART + DIGIC_UART_ST) + +static inline void PUTC_LL(char ch) +{ + while (!(readl(DEBUG_LL_UART_ST) & DIGIC_UART_ST_TX_RDY)) + ; /* noop */ + + writel(0x06, DEBUG_LL_UART_ST); + writel(ch, DEBUG_LL_UART_TX); +} + +#endif /* __MACH_DEBUG_LL_H__ */ diff --git a/arch/arm/mach-digic/include/mach/digic4.h b/arch/arm/mach-digic/include/mach/digic4.h new file mode 100644 index 0000000000..ffc7979a9c --- /dev/null +++ b/arch/arm/mach-digic/include/mach/digic4.h @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DIGIC4_H__ +#define __DIGIC4_H__ + +#define DIGIC4_UART 0xc0800000 + +#endif /* __DIGIC4_H__ */ diff --git a/arch/arm/mach-digic/include/mach/uart.h b/arch/arm/mach-digic/include/mach/uart.h new file mode 100644 index 0000000000..043f7cd0e9 --- /dev/null +++ b/arch/arm/mach-digic/include/mach/uart.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DIGIC_UART_H__ +#define __DIGIC_UART_H__ + +/* Serial interface registers offsets */ +#define DIGIC_UART_TX 0x0 +#define DIGIC_UART_RX 0x4 +#define DIGIC_UART_ST 0x14 +# define DIGIC_UART_ST_RX_RDY 1 +# define DIGIC_UART_ST_TX_RDY 2 + +#endif /* __DIGIC_UART_H__ */ diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 2d99f3eec5..53a44a06e9 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -208,6 +208,12 @@ config MACH_EFIKA_MX_SMARTBOOK help Choose this to compile barebox for the Efika MX Smartbook +config MACH_EMBEDSKY_E9 + bool "Embedsky E9 Mini-PC" + select ARCH_IMX6 + help + Choose this to compile barebox for the Embedsky E9 Mini PC + config MACH_FREESCALE_MX51_PDK bool "Freescale i.MX51 PDK" select ARCH_IMX51 diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c index bb8fec2d45..811592f7da 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -549,9 +549,9 @@ void __naked __noreturn imx53_barebox_entry(void *boarddata) unsigned long base, size; upper_or_coalesced_range(MX53_CSD0_BASE_ADDR, - imx_v3_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 0), + imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 0), MX53_CSD1_BASE_ADDR, - imx_v3_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 1), + imx_v4_sdram_size((void *)MX53_ESDCTL_BASE_ADDR, 1), &base, &size); barebox_arm_entry(base, size, boarddata); diff --git a/arch/arm/mach-imx/imx-bbu-internal.c b/arch/arm/mach-imx/imx-bbu-internal.c index 125415ec8d..56369a0f94 100644 --- a/arch/arm/mach-imx/imx-bbu-internal.c +++ b/arch/arm/mach-imx/imx-bbu-internal.c @@ -168,7 +168,7 @@ static int imx_bbu_internal_v1_update(struct bbu_handler *handler, struct bbu_da * layer. */ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler *imx_handler, - struct bbu_data *data, void *image, int image_len) + struct bbu_data *data) { struct mtd_info_user meminfo; int fd; @@ -178,6 +178,11 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * uint32_t *ptr, *num_bb, *bb; uint64_t offset; int block = 0, len, now, blocksize; + int dbbt_start_page = 4; + int firmware_start_page = 12; + void *dbbt_base; + void *image, *freep = NULL; + int pre_image_size; ret = stat(data->devicefile, &s); if (ret) @@ -193,32 +198,40 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * if (ret) goto out; + pre_image_size = firmware_start_page * meminfo.writesize; + image = freep = xzalloc(data->len + pre_image_size); + memcpy(image + pre_image_size, data->image, data->len); + blocksize = meminfo.erasesize; ptr = image + 0x4; *ptr++ = FCB_MAGIC; /* FCB */ *ptr++ = 1; /* FCB version */ + ptr = image + 0x68; /* Firmware start page */ + *ptr = firmware_start_page; + ptr = image + 0x78; /* DBBT start page */ - *ptr = 4; + *ptr = dbbt_start_page; - ptr = image + 4 * 2048 + 4; + dbbt_base = image + dbbt_start_page * meminfo.writesize; + ptr = dbbt_base + 4; *ptr++ = DBBT_MAGIC; /* DBBT */ *ptr = 1; /* DBBT version */ - ptr = (u32*)(image + 0x2010); + ptr = (u32*)(dbbt_base + 0x10); /* * This is marked as reserved in the i.MX53 reference manual, but * must be != 0. Otherwise the ROM ignores the DBBT */ *ptr = 1; - ptr = (u32*)(image + 0x4004); /* start of DBBT */ + ptr = (u32*)(dbbt_base + 4 * meminfo.writesize + 4); /* start of DBBT */ num_bb = ptr; bb = ptr + 1; offset = 0; - size_need = data->len + 0x8000; + size_need = data->len + pre_image_size; /* * Collect bad blocks and construct DBBT @@ -261,18 +274,18 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * } debug("total image size: 0x%08zx. Space needed including bad blocks: 0x%08zx\n", - data->len + 0x8000, - data->len + 0x8000 + *num_bb * blocksize); + data->len + pre_image_size, + data->len + pre_image_size + *num_bb * blocksize); - if (data->len + 0x8000 + *num_bb * blocksize > imx_handler->device_size) { + if (data->len + pre_image_size + *num_bb * blocksize > imx_handler->device_size) { printf("needed space (0x%08zx) exceeds partition space (0x%08zx)\n", - data->len + 0x8000 + *num_bb * blocksize, + data->len + pre_image_size + *num_bb * blocksize, imx_handler->device_size); ret = -ENOSPC; goto out; } - len = data->len + 0x8000; + len = data->len + pre_image_size; offset = 0; /* @@ -312,6 +325,7 @@ static int imx_bbu_internal_v2_write_nand_dbbt(struct imx_internal_bbu_handler * out: close(fd); + free(freep); return ret; } @@ -329,10 +343,7 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da { struct imx_internal_bbu_handler *imx_handler = container_of(handler, struct imx_internal_bbu_handler, handler); - void *imx_pre_image = NULL; - int imx_pre_image_size; - int ret, image_len; - void *buf; + int ret; uint32_t *barker; ret = imx_bbu_check_prereq(data); @@ -346,26 +357,10 @@ static int imx_bbu_internal_v2_update(struct bbu_handler *handler, struct bbu_da return -EINVAL; } - imx_pre_image_size = 0; - - if (imx_handler->flags & IMX_INTERNAL_FLAG_NAND) { - /* NAND needs additional space for the DBBT */ - imx_pre_image_size += 0x6000; - imx_pre_image = xzalloc(imx_pre_image_size); - - /* Create a buffer containing header and image data */ - image_len = data->len + imx_pre_image_size; - buf = xzalloc(image_len); - memcpy(buf, imx_pre_image, imx_pre_image_size); - memcpy(buf + imx_pre_image_size, data->image, data->len); - - ret = imx_bbu_internal_v2_write_nand_dbbt(imx_handler, data, buf, - image_len); - free(buf); - free(imx_pre_image); - } else { + if (imx_handler->flags & IMX_INTERNAL_FLAG_NAND) + ret = imx_bbu_internal_v2_write_nand_dbbt(imx_handler, data); + else ret = imx_bbu_write_device(imx_handler, data, data->image, data->len); - } return ret; } diff --git a/arch/arm/mach-mvebu/Kconfig b/arch/arm/mach-mvebu/Kconfig index 18f61f74f9..131f3a67ea 100644 --- a/arch/arm/mach-mvebu/Kconfig +++ b/arch/arm/mach-mvebu/Kconfig @@ -14,11 +14,13 @@ config ARCH_ARMADA_370 bool "Armada 370" select CPU_V7 select CLOCKSOURCE_MVEBU + select PINCTRL_ARMADA_370 config ARCH_ARMADA_XP bool "Armada XP" select CPU_V7 select CLOCKSOURCE_MVEBU + select PINCTRL_ARMADA_XP config ARCH_DOVE bool "Dove 88AP510" diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c index e416a38765..f2b991e5a7 100644 --- a/arch/arm/mach-mvebu/armada-370-xp.c +++ b/arch/arm/mach-mvebu/armada-370-xp.c @@ -18,6 +18,7 @@ #include <init.h> #include <io.h> #include <asm/memory.h> +#include <linux/mbus.h> #include <mach/armada-370-xp-regs.h> static inline void armada_370_xp_memory_find(unsigned long *phys_base, @@ -46,12 +47,20 @@ static inline void armada_370_xp_memory_find(unsigned long *phys_base, static int armada_370_xp_init_soc(void) { unsigned long phys_base, phys_size; + u32 reg; barebox_set_model("Marvell Armada 370/XP"); barebox_set_hostname("armada"); + /* Disable MBUS error propagation */ + reg = readl(ARMADA_370_XP_FABRIC_BASE); + reg &= ~BIT(8); + writel(reg, ARMADA_370_XP_FABRIC_BASE); + armada_370_xp_memory_find(&phys_base, &phys_size); - arm_add_mem_device("ram0", phys_base, phys_size); + + mvebu_set_memory(phys_base, phys_size); + mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE); return 0; } diff --git a/arch/arm/mach-mvebu/common.c b/arch/arm/mach-mvebu/common.c index b054bf5aff..ac4b332e01 100644 --- a/arch/arm/mach-mvebu/common.c +++ b/arch/arm/mach-mvebu/common.c @@ -79,3 +79,62 @@ static int mvebu_soc_id_init(void) return 0; } postcore_initcall(mvebu_soc_id_init); + +static u64 mvebu_mem[2]; + +void mvebu_set_memory(u64 phys_base, u64 phys_size) +{ + mvebu_mem[0] = phys_base; + mvebu_mem[1] = phys_size; +} + +/* + * Memory size is set up by BootROM and can be read from SoC's ram controller + * registers. Fixup provided DTs to reflect accessible amount of directly + * attached RAM. Removable RAM, e.g. SODIMM, should be added by a per-board + * fixup. + */ +static int mvebu_memory_of_fixup(struct device_node *root, void *context) +{ + struct device_node *np; + __be32 reg[4]; + int na, ns; + + /* bail out on zero-sized mem */ + if (!mvebu_mem[1]) + return -ENODEV; + + np = of_find_node_by_path("/memory"); + if (!np) + np = of_create_node(root, "/memory"); + if (!np) + return -EINVAL; + + na = of_n_addr_cells(np); + ns = of_n_size_cells(np); + + if (na == 2) { + reg[0] = cpu_to_be32(mvebu_mem[0] >> 32); + reg[1] = cpu_to_be32(mvebu_mem[0] & 0xffffffff); + } else { + reg[0] = cpu_to_be32(mvebu_mem[0] & 0xffffffff); + } + + if (ns == 2) { + reg[2] = cpu_to_be32(mvebu_mem[1] >> 32); + reg[3] = cpu_to_be32(mvebu_mem[1] & 0xffffffff); + } else { + reg[1] = cpu_to_be32(mvebu_mem[1] & 0xffffffff); + } + + if (of_set_property(np, "device_type", "memory", sizeof("memory"), 1) || + of_set_property(np, "reg", reg, sizeof(u32) * (na + ns), 1)) + pr_err("Unable to fixup memory node\n"); + + return 0; +} + +static int mvebu_memory_fixup_register(void) { + return of_register_fixup(mvebu_memory_of_fixup, NULL); +} +pure_initcall(mvebu_memory_fixup_register); diff --git a/arch/arm/mach-mvebu/dove.c b/arch/arm/mach-mvebu/dove.c index bcbf4b8ad7..69c6436b24 100644 --- a/arch/arm/mach-mvebu/dove.c +++ b/arch/arm/mach-mvebu/dove.c @@ -18,6 +18,7 @@ #include <init.h> #include <io.h> #include <asm/memory.h> +#include <linux/mbus.h> #include <mach/dove-regs.h> static inline void dove_remap_mc_regs(void) @@ -76,7 +77,10 @@ static int dove_init_soc(void) dove_remap_mc_regs(); dove_memory_find(&phys_base, &phys_size); - arm_add_mem_device("ram0", phys_base, phys_size); + + mvebu_set_memory(phys_base, phys_size); + mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE); + mvebu_mbus_add_range(0xf0, 0x02, DOVE_REMAP_MC_REGS); return 0; } diff --git a/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h index 5fd16e5733..ccc687c03b 100644 --- a/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h +++ b/arch/arm/mach-mvebu/include/mach/armada-370-xp-regs.h @@ -42,6 +42,8 @@ #define DDR_SIZE_CS_SHIFT 2 #define DDR_SIZE_MASK 0xff000000 +#define ARMADA_370_XP_FABRIC_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20200) + #define ARMADA_370_XP_TIMER_BASE (ARMADA_370_XP_INT_REGS_BASE + 0x20300) #endif /* __MACH_MVEBU_DOVE_REGS_H */ diff --git a/arch/arm/mach-mvebu/include/mach/common.h b/arch/arm/mach-mvebu/include/mach/common.h index 3cc1bf71c0..9f6118e4ec 100644 --- a/arch/arm/mach-mvebu/include/mach/common.h +++ b/arch/arm/mach-mvebu/include/mach/common.h @@ -20,4 +20,6 @@ #define MVEBU_REMAP_INT_REG_BASE 0xf1000000 +void mvebu_set_memory(u64 phys_base, u64 phys_size); + #endif diff --git a/arch/arm/mach-mvebu/kirkwood.c b/arch/arm/mach-mvebu/kirkwood.c index fe9ca9cbe4..c114bdb360 100644 --- a/arch/arm/mach-mvebu/kirkwood.c +++ b/arch/arm/mach-mvebu/kirkwood.c @@ -17,6 +17,7 @@ #include <init.h> #include <io.h> #include <asm/memory.h> +#include <linux/mbus.h> #include <mach/kirkwood-regs.h> static inline void kirkwood_memory_find(unsigned long *phys_base, @@ -50,7 +51,9 @@ static int kirkwood_init_soc(void) barebox_set_hostname("kirkwood"); kirkwood_memory_find(&phys_base, &phys_size); - arm_add_mem_device("ram0", phys_base, phys_size); + + mvebu_set_memory(phys_base, phys_size); + mvebu_mbus_add_range(0xf0, 0x01, MVEBU_REMAP_INT_REG_BASE); return 0; } diff --git a/arch/arm/mach-omap/Kconfig b/arch/arm/mach-omap/Kconfig index 44585724fe..732de15fec 100644 --- a/arch/arm/mach-omap/Kconfig +++ b/arch/arm/mach-omap/Kconfig @@ -72,7 +72,6 @@ config OMAP_GPMC config OMAP_BUILD_IFT prompt "build ift binary (MLO)" - depends on !OMAP_MULTI_BOARDS bool help Say Y here if you want to build an MLO binary. On TI SoCs, this @@ -81,7 +80,6 @@ config OMAP_BUILD_IFT config OMAP_BUILD_SPI prompt "build SPI binary" - depends on !OMAP_MULTI_BOARDS bool help Say Y here if you want to build an barebox.spi image as used diff --git a/arch/arm/mach-omap/Makefile b/arch/arm/mach-omap/Makefile index c9b6f4bb9f..0ebfae7437 100644 --- a/arch/arm/mach-omap/Makefile +++ b/arch/arm/mach-omap/Makefile @@ -24,6 +24,7 @@ pbl-$(CONFIG_ARCH_OMAP3) += omap3_generic.o auxcr.o obj-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o pbl-$(CONFIG_ARCH_OMAP4) += omap4_generic.o omap4_clock.o obj-pbl-$(CONFIG_ARCH_AM33XX) += am33xx_generic.o am33xx_clock.o am33xx_mux.o +obj-$(CONFIG_ARCH_AM33XX) += am33xx_scrm.o obj-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o pbl-$(CONFIG_OMAP3_CLOCK_CONFIG) += omap3_clock.o obj-$(CONFIG_OMAP_GPMC) += gpmc.o devices-gpmc-nand.o diff --git a/arch/arm/mach-omap/am33xx_generic.c b/arch/arm/mach-omap/am33xx_generic.c index 606e3918b3..71c528ca8b 100644 --- a/arch/arm/mach-omap/am33xx_generic.c +++ b/arch/arm/mach-omap/am33xx_generic.c @@ -19,6 +19,7 @@ #include <init.h> #include <io.h> #include <net.h> +#include <asm/barebox-arm.h> #include <mach/am33xx-silicon.h> #include <mach/am33xx-clock.h> #include <mach/generic.h> @@ -318,6 +319,61 @@ void am33xx_config_sdram(const struct am33xx_emif_regs *regs) writel(regs->sdram_config, AM33XX_EMIF4_0_REG(SDRAM_CONFIG)); } +/** + * am335x_sdram_size - read back SDRAM size from sdram_config register + * + * @return: The SDRAM size + */ +unsigned long am335x_sdram_size(void) +{ + int rows, cols, width, banks; + unsigned long size; + uint32_t sdram_config = readl(CM_EMIF_SDRAM_CONFIG); + + rows = ((sdram_config >> 7) & 0x7) + 9; + cols = (sdram_config & 0x7) + 8; + + switch ((sdram_config >> 14) & 0x3) { + case 0: + width = 4; + break; + case 1: + width = 2; + break; + default: + return 0; + } + + switch ((sdram_config >> 4) & 0x7) { + case 0: + banks = 1; + break; + case 1: + banks = 2; + break; + case 2: + banks = 4; + break; + case 3: + banks = 8; + break; + default: + return 0; + } + + size = (1 << rows) * (1 << cols) * banks * width; + + debug("%s: sdram_config: 0x%08x cols: %2d rows: %2d width: %2d banks: %2d size: 0x%08lx\n", + __func__, sdram_config, cols, rows, width, banks, size); + + return size; +} + +void __noreturn am335x_barebox_entry(void *boarddata) +{ + barebox_arm_entry(0x80000000, am335x_sdram_size(), boarddata); +} + void am33xx_config_io_ctrl(int ioctrl) { writel(ioctrl, AM33XX_DDR_CMD0_IOCTRL); diff --git a/arch/arm/mach-omap/am33xx_scrm.c b/arch/arm/mach-omap/am33xx_scrm.c new file mode 100644 index 0000000000..67529f8226 --- /dev/null +++ b/arch/arm/mach-omap/am33xx_scrm.c @@ -0,0 +1,51 @@ +/* + * (C) Copyright 2014 Sascha Hauer <s.hauer@pengutronix.de> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <common.h> +#include <io.h> +#include <errno.h> +#include <sizes.h> +#include <init.h> +#include <of.h> +#include <asm/barebox-arm.h> +#include <asm/memory.h> +#include <mach/am33xx-silicon.h> + +static int am33xx_scrm_probe(struct device_d *dev) +{ + arm_add_mem_device("ram0", 0x80000000, am335x_sdram_size()); + + return 0; +} + +static __maybe_unused struct of_device_id am33xx_scrm_dt_ids[] = { + { + .compatible = "ti,am3-scrm", + }, { + /* sentinel */ + } +}; + +static struct driver_d am33xx_scrm_driver = { + .name = "am33xx-scrm", + .probe = am33xx_scrm_probe, + .of_compatible = DRV_OF_COMPAT(am33xx_scrm_dt_ids), +}; + +static int am33xx_scrm_init(void) +{ + return platform_driver_register(&am33xx_scrm_driver); +} + +mem_initcall(am33xx_scrm_init); diff --git a/arch/arm/mach-omap/include/mach/am33xx-silicon.h b/arch/arm/mach-omap/include/mach/am33xx-silicon.h index 20b8e81c1c..ceca10a619 100644 --- a/arch/arm/mach-omap/include/mach/am33xx-silicon.h +++ b/arch/arm/mach-omap/include/mach/am33xx-silicon.h @@ -237,5 +237,7 @@ void am33xx_config_ddr_data(const struct am33xx_ddr_data *data, int macronr); void am335x_sdram_init(int ioctrl, const struct am33xx_cmd_control *cmd_ctrl, const struct am33xx_emif_regs *emif_regs, const struct am33xx_ddr_data *ddr_data); +unsigned long am335x_sdram_size(void); +void am335x_barebox_entry(void *boarddata); #endif diff --git a/arch/arm/mach-omap/omap_generic.c b/arch/arm/mach-omap/omap_generic.c index 060c59277f..334cf8db56 100644 --- a/arch/arm/mach-omap/omap_generic.c +++ b/arch/arm/mach-omap/omap_generic.c @@ -20,6 +20,7 @@ #include <io.h> #include <fs.h> #include <malloc.h> +#include <libfile.h> #include <linux/stat.h> #include <mach/gpmc.h> #include <mach/generic.h> diff --git a/arch/arm/mach-omap/xload.c b/arch/arm/mach-omap/xload.c index a309450109..e9d7bbb2e9 100644 --- a/arch/arm/mach-omap/xload.c +++ b/arch/arm/mach-omap/xload.c @@ -5,6 +5,7 @@ #include <init.h> #include <driver.h> #include <linux/mtd/mtd.h> +#include <libfile.h> #include <fs.h> #include <fcntl.h> #include <sizes.h> diff --git a/arch/blackfin/boards/ipe337/cmd_alternate.c b/arch/blackfin/boards/ipe337/cmd_alternate.c index 992d274847..b332cfb059 100644 --- a/arch/blackfin/boards/ipe337/cmd_alternate.c +++ b/arch/blackfin/boards/ipe337/cmd_alternate.c @@ -1,5 +1,6 @@ #include <common.h> #include <command.h> +#include <libfile.h> #include <linux/stat.h> #include <malloc.h> #include <fs.h> diff --git a/arch/efi/Kconfig b/arch/efi/Kconfig new file mode 100644 index 0000000000..26fecaa392 --- /dev/null +++ b/arch/efi/Kconfig @@ -0,0 +1,52 @@ +config ARCH_EFI + bool + default y + select HAS_DEBUG_LL + select HAS_KALLSYMS + select HAVE_DEFAULT_ENVIRONMENT_NEW + select EFI_GUID + select EFI_DEVICEPATH + select PRINTF_UUID + select GENERIC_FIND_NEXT_BIT + +config ARCH_TEXT_BASE + hex + default 0x0 + +menu "EFI specific settings" + +config 64BIT + def_bool y + help + Say yes to build a 64-bit binary - formerly known as x86_64 + Say no to build a 32-bit binary - formerly known as i386. + + 32-bit support currently does not compile and is not tested + due to the lack of hardware. + +config X86_32 + def_bool y + depends on !64BIT + +config X86_64 + def_bool y + depends on 64BIT + +config ARCH_EFI_REGISTER_COM1 + bool "Register first serial port" + help + Say yes here to register the first serial port on ioport 0x3f8. + This is useful to control barebox over a serial port if the board + has one. Enabling this option may not work on boards which do not + have a serial port. Also enable DRIVER_SERIAL_NS16550 to enable + the NS16550 driver. + +endmenu + +source common/Kconfig +source commands/Kconfig +source net/Kconfig +source drivers/Kconfig +source fs/Kconfig +source lib/Kconfig +source crypto/Kconfig diff --git a/arch/efi/Makefile b/arch/efi/Makefile new file mode 100644 index 0000000000..af280859f0 --- /dev/null +++ b/arch/efi/Makefile @@ -0,0 +1,41 @@ +CFLAGS += -fpic -fshort-wchar -mno-sse -mno-mmx + +ifeq ($(CONFIG_X86_32),y) + UTS_MACHINE := i386 + biarch := $(call cc-option,-m32) + AFLAGS += $(biarch) + CFLAGS += $(biarch) + TARGET = efi-app-ia32 +else + UTS_MACHINE := x86_64 + AFLAGS += -m64 + CFLAGS += -m64 -mno-red-zone + TARGET = efi-app-x86_64 +endif + +lds-$(CONFIG_X86_32) := arch/efi/lib/elf_ia32_efi.lds +lds-$(CONFIG_X86_64) := arch/efi/lib/elf_x86_64_efi.lds + +cmd_barebox__ ?= $(LD) $(LDFLAGS) $(LDFLAGS_barebox) -o $@ \ + -T $(lds-y) \ + -shared -Bsymbolic -nostdlib -znocombreloc \ + --start-group $(barebox-common) \ + --end-group \ + $(filter-out $(barebox-lds) $(barebox-common) FORCE ,$^) + +quiet_cmd_efi_image = EFI-IMG $@ + cmd_efi_image = objcopy -j .text -j .sdata -j .data -j .dynamic \ + -j .dynsym -j .rel -j .rela -j .reloc -j __barebox_initcalls \ + -j __barebox_cmd -j .barebox_magicvar -j .bbenv.* \ + --target=$(TARGET) $< $@ + +KBUILD_BINARY := barebox + +LDFLAGS := -m elf_$(UTS_MACHINE) --no-undefined + +barebox.efi: $(KBUILD_BINARY) FORCE + $(call if_changed,efi_image) + +KBUILD_IMAGE := barebox.efi + +common-y += arch/efi/efi/ arch/efi/lib/ diff --git a/arch/efi/configs/efi_defconfig b/arch/efi/configs/efi_defconfig new file mode 100644 index 0000000000..456f70d32b --- /dev/null +++ b/arch/efi/configs/efi_defconfig @@ -0,0 +1,78 @@ +CONFIG_MMU=y +CONFIG_MALLOC_SIZE=0x0 +CONFIG_MALLOC_TLSF=y +CONFIG_PROMPT="barebox> " +CONFIG_HUSH_FANCY_PROMPT=y +CONFIG_CMDLINE_EDITING=y +CONFIG_AUTO_COMPLETE=y +CONFIG_MENU=y +# CONFIG_TIMESTAMP is not set +CONFIG_CONSOLE_ACTIVATE_ALL=y +CONFIG_PARTITION_DISK_EFI=y +CONFIG_DEFAULT_ENVIRONMENT_GENERIC_NEW=y +CONFIG_POLLER=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_LL=y +CONFIG_LONGHELP=y +CONFIG_CMD_IOMEM=y +CONFIG_CMD_MEMINFO=y +CONFIG_CMD_BOOTM_SHOW_TYPE=y +CONFIG_CMD_BOOTM_VERBOSE=y +CONFIG_CMD_BOOTM_INITRD=y +CONFIG_CMD_BOOTM_OFTREE=y +CONFIG_CMD_GO=y +CONFIG_CMD_LOADB=y +CONFIG_CMD_RESET=y +CONFIG_CMD_UIMAGE=y +CONFIG_CMD_PARTITION=y +CONFIG_CMD_EXPORT=y +CONFIG_CMD_LOADENV=y +CONFIG_CMD_PRINTENV=y +CONFIG_CMD_MAGICVAR=y +CONFIG_CMD_MAGICVAR_HELP=y +CONFIG_CMD_SAVEENV=y +CONFIG_CMD_FILETYPE=y +CONFIG_CMD_LN=y +CONFIG_CMD_MD5SUM=y +CONFIG_CMD_UNCOMPRESS=y +CONFIG_CMD_LET=y +CONFIG_CMD_MSLEEP=y +CONFIG_CMD_READF=y +CONFIG_CMD_SLEEP=y +CONFIG_CMD_DHCP=y +CONFIG_CMD_HOST=y +CONFIG_CMD_PING=y +CONFIG_CMD_TFTP=y +CONFIG_CMD_ECHO_E=y +CONFIG_CMD_EDIT=y +CONFIG_CMD_MENU=y +CONFIG_CMD_MENUTREE=y +CONFIG_CMD_READLINE=y +CONFIG_CMD_TIMEOUT=y +CONFIG_CMD_CRC=y +CONFIG_CMD_CRC_CMP=y +CONFIG_CMD_MM=y +CONFIG_CMD_DETECT=y +CONFIG_CMD_FLASH=y +CONFIG_CMD_2048=y +CONFIG_CMD_BAREBOX_UPDATE=y +CONFIG_CMD_OF_NODE=y +CONFIG_CMD_OF_PROPERTY=y +CONFIG_CMD_OFTREE=y +CONFIG_CMD_TIME=y +CONFIG_NET=y +CONFIG_NET_NFS=y +CONFIG_NET_NETCONSOLE=y +CONFIG_DRIVER_SERIAL_EFI_STDIO=y +CONFIG_DRIVER_SERIAL_NS16550=y +CONFIG_DRIVER_NET_EFI_SNP=y +# CONFIG_SPI is not set +CONFIG_DISK=y +CONFIG_FS_EXT4=y +CONFIG_FS_TFTP=y +CONFIG_FS_NFS=y +CONFIG_FS_EFI=y +CONFIG_FS_EFIVARFS=y +CONFIG_FS_FAT=y +CONFIG_FS_FAT_WRITE=y +CONFIG_FS_FAT_LFN=y diff --git a/arch/efi/efi/Makefile b/arch/efi/efi/Makefile new file mode 100644 index 0000000000..a856e5907c --- /dev/null +++ b/arch/efi/efi/Makefile @@ -0,0 +1,2 @@ +obj-y += efi.o clocksource.o efi-block-io.o efi-device.o efi-image.o +bbenv-y += env-efi diff --git a/arch/efi/efi/clocksource.c b/arch/efi/efi/clocksource.c new file mode 100644 index 0000000000..2f33b43cce --- /dev/null +++ b/arch/efi/efi/clocksource.c @@ -0,0 +1,60 @@ +#include <common.h> +#include <efi.h> +#include <mach/efi.h> +#include <clock.h> + +#ifdef __x86_64__ +uint64_t ticks_read(void) +{ + uint64_t a, d; + + __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d)); + + return (d << 32) | a; +} +#else +uint64_t ticks_read(void) +{ + uint64_t val; + + __asm__ volatile ("rdtsc" : "=A" (val)); + + return val; +} +#endif + +static uint64_t freq; + +/* count TSC ticks during a millisecond delay */ +static uint64_t ticks_freq(void) +{ + uint64_t ticks_start, ticks_end; + + ticks_start = ticks_read(); + BS->stall(1000); + ticks_end = ticks_read(); + + return (ticks_end - ticks_start) * 1000; +} + +static uint64_t efi_clocksource_read(void) +{ + return 1000 * 1000 * ticks_read() / freq; +} + +static struct clocksource cs = { + .read = efi_clocksource_read, + .mask = CLOCKSOURCE_MASK(64), + .shift = 0, +}; + +int efi_clocksource_init(void) +{ + cs.mult = clocksource_hz2mult(1000 * 1000, cs.shift); + + freq = ticks_freq(); + + init_clock(&cs); + + return 0; +} diff --git a/arch/efi/efi/efi-block-io.c b/arch/efi/efi/efi-block-io.c new file mode 100644 index 0000000000..00115317fc --- /dev/null +++ b/arch/efi/efi/efi-block-io.c @@ -0,0 +1,174 @@ +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <fs.h> +#include <string.h> +#include <command.h> +#include <errno.h> +#include <linux/stat.h> +#include <xfuncs.h> +#include <fcntl.h> +#include <efi.h> +#include <block.h> +#include <disks.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +#define EFI_BLOCK_IO_PROTOCOL_REVISION2 0x00020001 +#define EFI_BLOCK_IO_PROTOCOL_REVISION3 ((2<<16) | (31)) + +struct efi_block_io_media{ + u32 media_id; + bool removable_media; + bool media_present; + bool logical_partition; + bool read_only; + bool write_caching; + u32 block_size; + u32 io_align; + u64 last_block; + u64 lowest_aligned_lba; /* added in Revision 2 */ + u32 logical_blocks_per_physical_block; /* added in Revision 2 */ + u32 optimal_transfer_length_granularity; /* added in Revision 3 */ +}; + +struct efi_block_io_protocol { + u64 revision; + struct efi_block_io_media *media; + efi_status_t(EFIAPI *reset)(struct efi_block_io_protocol *this, + bool ExtendedVerification); + efi_status_t(EFIAPI *read)(struct efi_block_io_protocol *this, u32 media_id, + u64 lba, unsigned long buffer_size, void *buf); + efi_status_t(EFIAPI *write)(struct efi_block_io_protocol *this, u32 media_id, + u64 lba, unsigned long buffer_size, void *buf); + efi_status_t(EFIAPI *flush)(struct efi_block_io_protocol *this); +}; + +struct efi_bio_priv { + struct efi_block_io_protocol *protocol; + struct device_d *dev; + struct block_device blk; + u32 media_id; +}; + +static int efi_bio_read(struct block_device *blk, void *buffer, int block, + int num_blocks) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->read(priv->protocol, priv->media_id, + block, num_blocks * 512, buffer); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static int efi_bio_write(struct block_device *blk, + const void *buffer, int block, int num_blocks) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->write(priv->protocol, priv->media_id, + block, num_blocks * 512, (void *)buffer); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static int efi_bio_flush(struct block_device *blk) +{ + struct efi_bio_priv *priv = container_of(blk, struct efi_bio_priv, blk); + efi_status_t efiret; + + efiret = priv->protocol->flush(priv->protocol); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static struct block_device_ops efi_bio_ops = { + .read = efi_bio_read, + .write = efi_bio_write, + .flush = efi_bio_flush, +}; + +static void efi_bio_print_info(struct efi_bio_priv *priv) +{ + struct efi_block_io_media *media = priv->protocol->media; + u64 revision = priv->protocol->revision; + + dev_dbg(priv->dev, "revision: 0x%016llx\n", revision); + dev_dbg(priv->dev, "media_id: 0x%08x\n", media->media_id); + dev_dbg(priv->dev, "removable_media: %d\n", media->removable_media); + dev_dbg(priv->dev, "media_present: %d\n", media->media_present); + dev_dbg(priv->dev, "logical_partition: %d\n", media->logical_partition); + dev_dbg(priv->dev, "read_only: %d\n", media->read_only); + dev_dbg(priv->dev, "write_caching: %d\n", media->write_caching); + dev_dbg(priv->dev, "block_size: 0x%08x\n", media->block_size); + dev_dbg(priv->dev, "io_align: 0x%08x\n", media->io_align); + dev_dbg(priv->dev, "last_block: 0x%016llx\n", media->last_block); + + if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION2) + return; + + dev_dbg(priv->dev, "u64 lowest_aligned_lba: 0x%08llx\n", + media->lowest_aligned_lba); + dev_dbg(priv->dev, "logical_blocks_per_physical_block: 0x%08x\n", + media->logical_blocks_per_physical_block); + + if (revision < EFI_BLOCK_IO_PROTOCOL_REVISION3) + return; + + dev_dbg(priv->dev, "optimal_transfer_length_granularity: 0x%08x\n", + media->optimal_transfer_length_granularity); +} + +int efi_bio_probe(struct efi_device *efidev) +{ + int ret; + struct efi_bio_priv *priv; + struct efi_block_io_media *media; + + priv = xzalloc(sizeof(*priv)); + + BS->handle_protocol(efidev->handle, &efi_block_io_protocol_guid, + (void **)&priv->protocol); + if (!priv->protocol) + return -ENODEV; + + media = priv->protocol->media; + efi_bio_print_info(priv); + priv->dev = &efidev->dev; + + priv->blk.cdev.name = asprintf("disk%d", cdev_find_free_index("disk")); + priv->blk.blockbits = ffs(media->block_size) - 1; + priv->blk.num_blocks = media->last_block; + priv->blk.ops = &efi_bio_ops; + priv->blk.dev = &efidev->dev; + + priv->media_id = media->media_id; + + ret = blockdevice_register(&priv->blk); + if (ret) + return ret; + + parse_partition_table(&priv->blk); + + return 0; +} + +static struct efi_driver efi_fs_driver = { + .driver = { + .name = "efi-block-io", + }, + .probe = efi_bio_probe, + .guid = EFI_BLOCK_IO_PROTOCOL_GUID, +}; +device_efi_driver(efi_fs_driver); diff --git a/arch/efi/efi/efi-device.c b/arch/efi/efi/efi-device.c new file mode 100644 index 0000000000..1c9553d906 --- /dev/null +++ b/arch/efi/efi/efi-device.c @@ -0,0 +1,349 @@ +/* + * efi-device.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <command.h> +#include <common.h> +#include <driver.h> +#include <malloc.h> +#include <memory.h> +#include <string.h> +#include <sizes.h> +#include <wchar.h> +#include <init.h> +#include <efi.h> +#include <mach/efi.h> +#include <mach/efi-device.h> +#include <linux/err.h> + +int efi_locate_handle(enum efi_locate_search_type search_type, + efi_guid_t *protocol, + void *search_key, + unsigned long *no_handles, + efi_handle_t **buffer) +{ + efi_status_t efiret; + unsigned long buffer_size = 0; + efi_handle_t *buf; + + efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size, + NULL); + if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) + return -efi_errno(efiret); + + buf = malloc(buffer_size); + if (!buf) + return -ENOMEM; + + efiret = BS->locate_handle(search_type, protocol, search_key, &buffer_size, + buf); + if (EFI_ERROR(efiret)) { + free(buf); + return -efi_errno(efiret); + } + + *no_handles = buffer_size / sizeof(efi_handle_t); + *buffer = buf; + + return 0; +} + +static struct efi_device *efi_find_device(efi_handle_t *handle) +{ + struct device_d *dev; + struct efi_device *efidev; + + bus_for_each_device(&efi_bus, dev) { + efidev = container_of(dev, struct efi_device, dev); + + if (efidev->handle == handle) + return efidev; + } + + return NULL; +} + +static void efi_devinfo(struct device_d *dev) +{ + struct efi_device *efidev = to_efi_device(dev); + int i; + + printf("Protocols:\n"); + + for (i = 0; i < efidev->num_guids; i++) + printf(" %d: %pUl: %s\n", i, &efidev->guids[i], + efi_guid_string(&efidev->guids[i])); +} + +static efi_handle_t *efi_find_parent(efi_handle_t *handle) +{ + unsigned long handle_count = 0; + efi_handle_t *handles = NULL, *parent; + unsigned long num_guids; + efi_guid_t **guids; + int ret, i, j, k; + efi_status_t efiret; + struct efi_open_protocol_information_entry *entry_buffer; + unsigned long entry_count; + + ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles); + if (ret) + return NULL; + + /* + * Normally one would expect a function/pointer to retrieve the parent. + * With EFI we have to: + * - get all handles + * - for each handle get the registered protocols + * - for each protocol get the users + * - the user which matches the input handle is the parent + */ + for (i = 0; i < handle_count; i++) { + efiret = BS->open_protocol(handles[i], &efi_device_path_protocol_guid, + NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + if (EFI_ERROR(efiret)) + continue; + + BS->protocols_per_handle(handles[i], &guids, &num_guids); + for (j = 0; j < num_guids; j++) { + efiret = BS->open_protocol_information(handles[i], guids[j], + &entry_buffer, &entry_count); + for (k = 0; k < entry_count; k++) { + if (entry_buffer[k].controller_handle == NULL) + continue; + if (entry_buffer[k].controller_handle == handles[i]) + continue; + if (entry_buffer[k].controller_handle == handle) { + parent = handles[i]; + goto out; + } + } + } + } + + parent = NULL; + + free(handles); +out: + return parent; +} + +static struct efi_device *efi_add_device(efi_handle_t *handle, efi_guid_t **guids, + int num_guids) +{ + struct efi_device *efidev; + int i; + efi_guid_t *guidarr; + efi_status_t efiret; + void *devpath; + + efidev = efi_find_device(handle); + if (efidev) + return ERR_PTR(-EEXIST); + + efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid, + NULL, NULL, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL); + if (EFI_ERROR(efiret)) + return ERR_PTR(-EINVAL); + + guidarr = malloc(sizeof(efi_guid_t) * num_guids); + + for (i = 0; i < num_guids; i++) + memcpy(&guidarr[i], guids[i], sizeof(efi_guid_t)); + + efiret = BS->open_protocol(handle, &efi_device_path_protocol_guid, + &devpath, NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efiret)) + return ERR_PTR(-EINVAL); + + efidev = xzalloc(sizeof(*efidev)); + + efidev->guids = guidarr; + efidev->num_guids = num_guids; + efidev->handle = handle; + efidev->dev.bus = &efi_bus; + efidev->dev.id = DEVICE_ID_SINGLE; + efidev->dev.info = efi_devinfo; + efidev->devpath = devpath; + + BS->handle_protocol(handle, &guidarr[0], &efidev->protocol); + + sprintf(efidev->dev.name, "handle-%p", handle); + + efidev->parent_handle = efi_find_parent(efidev->handle); + + return efidev; +} + + +static int efi_register_device(struct efi_device *efidev) +{ + char *dev_path_str; + struct efi_device *parent; + int ret; + + if (efi_find_device(efidev->handle)) + return -EEXIST; + + if (efidev->parent_handle) { + parent = efi_find_device(efidev->parent_handle); + if (!parent) + return -EINVAL; + + efidev->dev.parent = &parent->dev; + } + + ret = register_device(&efidev->dev); + if (ret) + return ret; + + dev_path_str = device_path_to_str(efidev->devpath); + if (dev_path_str) { + dev_add_param_fixed(&efidev->dev, "devpath", dev_path_str); + free(dev_path_str); + } + + debug("registered efi device %s\n", dev_name(&efidev->dev)); + + return 0; +} + +/** + * efi_register_devices - iterate over all EFI handles and register + * the devices found + * + * in barebox we treat all EFI handles which support the device_path + * protocol as devices. This function iterates over all handles and + * registers the corresponding devices. efi_register_devices is safe + * to call multiple times. Already registered devices will be ignored. + * + */ +void efi_register_devices(void) +{ + unsigned long handle_count = 0; + efi_handle_t *handles = NULL; + unsigned long num_guids; + efi_guid_t **guids; + int ret, i; + struct efi_device **efidevs; + int registered; + + ret = efi_locate_handle(all_handles, NULL, NULL, &handle_count, &handles); + if (ret) + return; + + efidevs = xzalloc(handle_count * sizeof(struct efi_device *)); + + for (i = 0; i < handle_count; i++) { + BS->protocols_per_handle(handles[i], &guids, &num_guids); + + efidevs[i] = efi_add_device(handles[i], guids, num_guids); + } + + /* + * We have a list of devices we want to register, but can only + * register a device when all parents are registered already. + * Do this by continiously iterating over the list until no + * further devices are registered. + */ + do { + registered = 0; + + for (i = 0; i < handle_count; i++) { + if (IS_ERR(efidevs[i])) + continue; + + ret = efi_register_device(efidevs[i]); + if (!ret) { + efidevs[i] = ERR_PTR(-EEXIST); + registered = 1; + } + } + } while (registered); + + free(efidevs); + free(handles); +} + +int efi_connect_all(void) +{ + efi_status_t efiret; + unsigned long handle_count; + efi_handle_t *handle_buffer; + int i; + + efiret = BS->locate_handle_buffer(all_handles, NULL, NULL, &handle_count, + &handle_buffer); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + for (i = 0; i < handle_count; i++) + efiret = BS->connect_controller(handle_buffer[i], NULL, NULL, true); + + if (handle_buffer) + BS->free_pool(handle_buffer); + + return 0; +} + +static int efi_bus_match(struct device_d *dev, struct driver_d *drv) +{ + struct efi_driver *efidrv = to_efi_driver(drv); + struct efi_device *efidev = to_efi_device(dev); + int i; + + for (i = 0; i < efidev->num_guids; i++) { + if (!memcmp(&efidrv->guid, &efidev->guids[i], sizeof(efi_guid_t))) + return 0; + } + + return 1; +} + +static int efi_bus_probe(struct device_d *dev) +{ + struct efi_driver *efidrv = to_efi_driver(dev->driver); + struct efi_device *efidev = to_efi_device(dev); + + return efidrv->probe(efidev); +} + +static void efi_bus_remove(struct device_d *dev) +{ + struct efi_driver *efidrv = to_efi_driver(dev->driver); + struct efi_device *efidev = to_efi_device(dev); + + return efidrv->remove(efidev); +} + +struct bus_type efi_bus = { + .name = "efi", + .match = efi_bus_match, + .probe = efi_bus_probe, + .remove = efi_bus_remove, +}; + +static int efi_init_devices(void) +{ + bus_register(&efi_bus); + + efi_register_devices(); + + return 0; +} +core_initcall(efi_init_devices); diff --git a/arch/efi/efi/efi-image.c b/arch/efi/efi/efi-image.c new file mode 100644 index 0000000000..18757d2697 --- /dev/null +++ b/arch/efi/efi/efi-image.c @@ -0,0 +1,105 @@ +/* + * efi-image.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <sizes.h> +#include <memory.h> +#include <command.h> +#include <magicvar.h> +#include <init.h> +#include <driver.h> +#include <io.h> +#include <efi.h> +#include <malloc.h> +#include <string.h> +#include <linux/err.h> +#include <boot.h> +#include <fs.h> +#include <binfmt.h> +#include <wchar.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +static int efi_execute_image(const char *file) +{ + void *exe; + size_t size; + efi_handle_t handle; + efi_status_t efiret; + const char *options; + efi_loaded_image_t *loaded_image; + + exe = read_file(file, &size); + if (!exe) + return -EINVAL; + + efiret = BS->load_image(false, efi_parent_image, efi_device_path, exe, size, + &handle); + if (EFI_ERROR(efiret)) { + pr_err("failed to LoadImage: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret);; + }; + + efiret = BS->open_protocol(handle, &efi_loaded_image_protocol_guid, + (void **)&loaded_image, + efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + options = linux_bootargs_get(); + loaded_image->load_options = strdup_char_to_wchar(options); + loaded_image->load_options_size = (strlen(options) + 1) * sizeof(wchar_t); + + efiret = BS->start_image(handle, NULL, NULL); + + efi_connect_all(); + efi_register_devices(); + + return 0; +} + +static int do_bootm_efi(struct image_data *data) +{ + return efi_execute_image(data->os_file); +} + +static struct image_handler efi_handle_tr = { + .name = "EFI Application", + .bootm = do_bootm_efi, + .filetype = filetype_exe, +}; + +static int efi_execute(struct binfmt_hook *b, char *file, int argc, char **argv) +{ + return efi_execute_image(file); +} + +static struct binfmt_hook binfmt_efi_hook = { + .type = filetype_exe, + .hook = efi_execute, +}; + +static int efi_register_image_handler(void) +{ + register_image_handler(&efi_handle_tr); + binfmt_register(&binfmt_efi_hook); + + return 0; +} +late_initcall(efi_register_image_handler); diff --git a/arch/efi/efi/efi.c b/arch/efi/efi/efi.c new file mode 100644 index 0000000000..ff97783b13 --- /dev/null +++ b/arch/efi/efi/efi.c @@ -0,0 +1,343 @@ +/* + * efi.c - barebox EFI payload support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <sizes.h> +#include <memory.h> +#include <clock.h> +#include <command.h> +#include <magicvar.h> +#include <init.h> +#include <driver.h> +#include <ns16550.h> +#include <io.h> +#include <efi.h> +#include <malloc.h> +#include <string.h> +#include <linux/err.h> +#include <boot.h> +#include <fs.h> +#include <binfmt.h> +#include <wchar.h> +#include <envfs.h> +#include <efi.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +efi_runtime_services_t *RT; +efi_boot_services_t *BS; +efi_system_table_t *efi_sys_table; +efi_handle_t efi_parent_image; +struct efi_device_path *efi_device_path; +efi_loaded_image_t *efi_loaded_image; + +void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size) +{ + efi_status_t efiret; + void *buf; + unsigned long size = 0; + s16 *name16 = strdup_char_to_wchar(name); + + efiret = RT->get_variable(name16, vendor, NULL, &size, NULL); + + if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) { + buf = ERR_PTR(-efi_errno(efiret)); + goto out; + } + + buf = malloc(size); + if (!buf) { + buf = ERR_PTR(-ENOMEM); + goto out; + } + + efiret = RT->get_variable(name16, vendor, NULL, &size, buf); + if (EFI_ERROR(efiret)) { + free(buf); + buf = ERR_PTR(-efi_errno(efiret)); + goto out; + } + + if (var_size) + *var_size = size; + +out: + free(name16); + + return buf; +} + +struct efi_boot { + u32 attributes; + u16 file_path_len; + char *description; + struct efi_device_path *path; + void *binary; +}; + +struct efi_boot *efi_get_boot(int num) +{ + struct efi_boot *boot = xzalloc(sizeof(*boot)); + void *buf, *ptr; + int size; + char *name; + + name = asprintf("Boot%04X", num); + + buf = efi_get_global_var(name, &size); + + free(name); + + if (!buf) { + free(boot); + return NULL; + } + + ptr = buf; + + boot->attributes = *(u32 *)ptr; + + ptr += sizeof(u32); + + boot->file_path_len = *(u16 *)ptr; + + ptr += sizeof(u16); + + boot->description = strdup_wchar_to_char(ptr); + + ptr += (strlen(boot->description) + 1) * 2; + + printf("description: %s\n", boot->description); + + boot->path = memdup(ptr, boot->file_path_len); + + printf("path: %s\n", device_path_to_str(boot->path)); + + return boot; +} + +static int misc_init(void) +{ + efi_get_boot(1); + efi_get_boot(2); + efi_get_boot(3); + + return 0; +} +late_initcall(misc_init); + +const char *efi_strerror(efi_status_t err) +{ + const char *str; + + switch (err) { + case EFI_SUCCESS: str = "Success"; break; + case EFI_LOAD_ERROR: str = "Load Error"; break; + case EFI_INVALID_PARAMETER: str = "Invalid Parameter"; break; + case EFI_UNSUPPORTED: str = "Unsupported"; break; + case EFI_BAD_BUFFER_SIZE: str = "Bad Buffer Size"; break; + case EFI_BUFFER_TOO_SMALL: str = "Buffer Too Small"; break; + case EFI_NOT_READY: str = "Not Ready"; break; + case EFI_DEVICE_ERROR: str = "Device Error"; break; + case EFI_WRITE_PROTECTED: str = "Write Protected"; break; + case EFI_OUT_OF_RESOURCES: str = "Out of Resources"; break; + case EFI_VOLUME_CORRUPTED: str = "Volume Corrupt"; break; + case EFI_VOLUME_FULL: str = "Volume Full"; break; + case EFI_NO_MEDIA: str = "No Media"; break; + case EFI_MEDIA_CHANGED: str = "Media changed"; break; + case EFI_NOT_FOUND: str = "Not Found"; break; + case EFI_ACCESS_DENIED: str = "Access Denied"; break; + case EFI_NO_RESPONSE: str = "No Response"; break; + case EFI_NO_MAPPING: str = "No mapping"; break; + case EFI_TIMEOUT: str = "Time out"; break; + case EFI_NOT_STARTED: str = "Not started"; break; + case EFI_ALREADY_STARTED: str = "Already started"; break; + case EFI_ABORTED: str = "Aborted"; break; + case EFI_ICMP_ERROR: str = "ICMP Error"; break; + case EFI_TFTP_ERROR: str = "TFTP Error"; break; + case EFI_PROTOCOL_ERROR: str = "Protocol Error"; break; + case EFI_INCOMPATIBLE_VERSION: str = "Incompatible Version"; break; + case EFI_SECURITY_VIOLATION: str = "Security Violation"; break; + case EFI_CRC_ERROR: str = "CRC Error"; break; + case EFI_END_OF_MEDIA: str = "End of Media"; break; + case EFI_END_OF_FILE: str = "End of File"; break; + case EFI_INVALID_LANGUAGE: str = "Invalid Language"; break; + case EFI_COMPROMISED_DATA: str = "Compromised Data"; break; + default: str = "unknown error"; + } + + return str; +} + +int efi_errno(efi_status_t err) +{ + int ret; + + switch (err) { + case EFI_SUCCESS: ret = 0; break; + case EFI_LOAD_ERROR: ret = EIO; break; + case EFI_INVALID_PARAMETER: ret = EINVAL; break; + case EFI_UNSUPPORTED: ret = ENOTSUPP; break; + case EFI_BAD_BUFFER_SIZE: ret = EINVAL; break; + case EFI_BUFFER_TOO_SMALL: ret = EINVAL; break; + case EFI_NOT_READY: ret = EAGAIN; break; + case EFI_DEVICE_ERROR: ret = EIO; break; + case EFI_WRITE_PROTECTED: ret = EROFS; break; + case EFI_OUT_OF_RESOURCES: ret = ENOMEM; break; + case EFI_VOLUME_CORRUPTED: ret = EIO; break; + case EFI_VOLUME_FULL: ret = ENOSPC; break; + case EFI_NO_MEDIA: ret = ENOMEDIUM; break; + case EFI_MEDIA_CHANGED: ret = ENOMEDIUM; break; + case EFI_NOT_FOUND: ret = ENODEV; break; + case EFI_ACCESS_DENIED: ret = EACCES; break; + case EFI_NO_RESPONSE: ret = ETIMEDOUT; break; + case EFI_NO_MAPPING: ret = EINVAL; break; + case EFI_TIMEOUT: ret = ETIMEDOUT; break; + case EFI_NOT_STARTED: ret = EINVAL; break; + case EFI_ALREADY_STARTED: ret = EINVAL; break; + case EFI_ABORTED: ret = EINTR; break; + case EFI_ICMP_ERROR: ret = EINVAL; break; + case EFI_TFTP_ERROR: ret = EINVAL; break; + case EFI_PROTOCOL_ERROR: ret = EPROTO; break; + case EFI_INCOMPATIBLE_VERSION: ret = EINVAL; break; + case EFI_SECURITY_VIOLATION: ret = EINVAL; break; + case EFI_CRC_ERROR: ret = EINVAL; break; + case EFI_END_OF_MEDIA: ret = EINVAL; break; + case EFI_END_OF_FILE: ret = EINVAL; break; + case EFI_INVALID_LANGUAGE: ret = EINVAL; break; + case EFI_COMPROMISED_DATA: ret = EINVAL; break; + default: ret = EINVAL; + } + + return ret; +} + +static struct NS16550_plat ns16550_plat = { + .clock = 115200 * 16, +}; + +static int efi_console_init(void) +{ + barebox_set_model("barebox EFI payload"); + + add_generic_device("efi-stdio", DEVICE_ID_SINGLE, NULL, 0 , 0, 0, NULL); + + if (IS_ENABLED(CONFIG_ARCH_EFI_REGISTER_COM1)) + add_ns16550_device(0, 0x3f8, 0x10, IORESOURCE_IO | IORESOURCE_MEM_8BIT, + &ns16550_plat); + + return 0; +} +console_initcall(efi_console_init); + +void reset_cpu(unsigned long addr) +{ + BS->exit(efi_parent_image, EFI_SUCCESS, 0, NULL); + + while(1); +} + +extern char image_base[]; +extern initcall_t __barebox_initcalls_start[], __barebox_early_initcalls_end[], + __barebox_initcalls_end[]; + +/* + * We have a position independent binary generated with -fpic. This function + * fixes the linker generated tables. + */ +static void fixup_tables(void) +{ + initcall_t *initcall; + unsigned long offset = (unsigned long)image_base; + struct command *cmdtp; + struct magicvar *m; + + for (initcall = __barebox_initcalls_start; + initcall < __barebox_initcalls_end; initcall++) + *initcall += offset; + + for (cmdtp = &__barebox_cmd_start; + cmdtp != &__barebox_cmd_end; + cmdtp++) { + cmdtp->name += offset; + cmdtp->cmd += offset; + if (cmdtp->complete) + cmdtp->complete += offset; + if (cmdtp->desc) + cmdtp->desc += offset; + if (cmdtp->help) + cmdtp->help += offset; + if (cmdtp->opts) + cmdtp->opts += offset; + if (cmdtp->aliases) + cmdtp->aliases = (void *)cmdtp->aliases + offset; + } + + for (m = &__barebox_magicvar_start; + m != &__barebox_magicvar_end; + m++) { + m->name += offset; + m->description += offset; + } +} + +static int efi_init(void) +{ + defaultenv_append_directory(env_efi); + + return 0; +} +device_initcall(efi_init); + +/** + * efi-main - Entry point for EFI images + */ +efi_status_t efi_main(efi_handle_t image, efi_system_table_t *sys_table) +{ + void *mem; + efi_status_t efiret; + +#ifdef DEBUG + sys_table->con_out->output_string(sys_table->con_out, L"barebox\n"); +#endif + + BS = sys_table->boottime; + + efi_parent_image = image; + efi_sys_table = sys_table; + RT = sys_table->runtime; + + efiret = BS->open_protocol(efi_parent_image, &efi_loaded_image_protocol_guid, + (void **)&efi_loaded_image, + efi_parent_image, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (!EFI_ERROR(efiret)) + BS->handle_protocol(efi_loaded_image->device_handle, + &efi_device_path_protocol_guid, (void **)&efi_device_path); + + fixup_tables(); + + BS->allocate_pool(efi_loaded_image->image_data_type, SZ_16M, &mem); + mem_malloc_init(mem, mem + SZ_16M); + + efi_clocksource_init(); + + start_barebox(); + + return EFI_SUCCESS; +} diff --git a/arch/efi/efi/env-efi/network/eth0-discover b/arch/efi/efi/env-efi/network/eth0-discover new file mode 100644 index 0000000000..62c31a553c --- /dev/null +++ b/arch/efi/efi/env-efi/network/eth0-discover @@ -0,0 +1,5 @@ +#!/bin/sh + +for i in /boot/network-drivers/*; do + $i; +done diff --git a/arch/efi/include/asm/barebox.h b/arch/efi/include/asm/barebox.h new file mode 100644 index 0000000000..2997587d82 --- /dev/null +++ b/arch/efi/include/asm/barebox.h @@ -0,0 +1 @@ +/* dummy */ diff --git a/arch/efi/include/asm/bitops.h b/arch/efi/include/asm/bitops.h new file mode 100644 index 0000000000..447023da63 --- /dev/null +++ b/arch/efi/include/asm/bitops.h @@ -0,0 +1,22 @@ +#ifndef _SANDBOX_BITOPS_H +#define _SANDBOX_BITOPS_H + +/* nothing but the defaults.. */ +#include <asm-generic/bitops/__ffs.h> +#include <asm-generic/bitops/__fls.h> +#include <asm-generic/bitops/ffs.h> +#include <asm-generic/bitops/fls.h> +#include <asm-generic/bitops/ffz.h> +#include <asm-generic/bitops/find.h> +#include <asm-generic/bitops/fls64.h> +#include <asm-generic/bitops/hweight.h> +#include <asm-generic/bitops/ops.h> + +#define set_bit(x, y) __set_bit(x, y) +#define clear_bit(x, y) __clear_bit(x, y) +#define change_bit(x, y) __change_bit(x, y) +#define test_and_set_bit(x, y) __test_and_set_bit(x, y) +#define test_and_clear_bit(x, y) __test_and_clear_bit(x, y) +#define test_and_change_bit(x, y) __test_and_change_bit(x, y) + +#endif diff --git a/arch/efi/include/asm/byteorder.h b/arch/efi/include/asm/byteorder.h new file mode 100644 index 0000000000..37316f2371 --- /dev/null +++ b/arch/efi/include/asm/byteorder.h @@ -0,0 +1,8 @@ +#ifndef _I386_BYTEORDER_H +#define _I386_BYTEORDER_H + +#include <asm/types.h> + +#include <linux/byteorder/little_endian.h> + +#endif /* _I386_BYTEORDER_H */ diff --git a/arch/efi/include/asm/common.h b/arch/efi/include/asm/common.h new file mode 100644 index 0000000000..b0e6b7fb18 --- /dev/null +++ b/arch/efi/include/asm/common.h @@ -0,0 +1,4 @@ +#ifndef ASM_COMMON_H +#define ASM_COMMON_H + +#endif /* ASM_COMMON_H */ diff --git a/arch/efi/include/asm/dma.h b/arch/efi/include/asm/dma.h new file mode 100644 index 0000000000..459536779e --- /dev/null +++ b/arch/efi/include/asm/dma.h @@ -0,0 +1,13 @@ +/* + * Copyright (C) 2012 by Marc Kleine-Budde <mkl@pengutronix.de> + * + * This file is released under the GPLv2 + * + */ + +#ifndef __ASM_DMA_H +#define __ASM_DMA_H + +/* empty*/ + +#endif /* __ASM_DMA_H */ diff --git a/arch/efi/include/asm/elf.h b/arch/efi/include/asm/elf.h new file mode 100644 index 0000000000..ddde035188 --- /dev/null +++ b/arch/efi/include/asm/elf.h @@ -0,0 +1,60 @@ +#ifndef __ASM_SANDBOX_ELF_H__ +#define __ASM_SANDBOX_ELF_H__ + +#ifdef __i386__ + +typedef struct user_fxsr_struct elf_fpxregset_t; + +#define R_386_NONE 0 +#define R_386_32 1 +#define R_386_PC32 2 +#define R_386_GOT32 3 +#define R_386_PLT32 4 +#define R_386_COPY 5 +#define R_386_GLOB_DAT 6 +#define R_386_JMP_SLOT 7 +#define R_386_RELATIVE 8 +#define R_386_GOTOFF 9 +#define R_386_GOTPC 10 +#define R_386_NUM 11 + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_386 + +#else + +/* x86-64 relocation types */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed pc relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ + +#define R_X86_64_NUM 16 + +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 + +#endif + +#endif /* __ASM_SANDBOX_ELF_H__ */ diff --git a/arch/efi/include/asm/io.h b/arch/efi/include/asm/io.h new file mode 100644 index 0000000000..ac8a9c1b35 --- /dev/null +++ b/arch/efi/include/asm/io.h @@ -0,0 +1,55 @@ +#ifndef __ASM_SANDBOX_IO_H +#define __ASM_SANDBOX_IO_H + +#define build_mmio_read(name, size, type, reg, barrier) \ + static inline type name(const volatile void *addr) \ + { type ret; asm volatile("mov" size " %1,%0":reg (ret) \ + :"m" (*(volatile type*)addr) barrier); return ret; } + +build_mmio_read(readb, "b", unsigned char, "=q", :"memory") +build_mmio_read(readw, "w", unsigned short, "=r", :"memory") +build_mmio_read(readl, "l", unsigned int, "=r", :"memory") + +#define build_mmio_write(name, size, type, reg, barrier) \ + static inline void name(type val, volatile void *addr) \ + { asm volatile("mov" size " %0,%1": :reg (val), \ + "m" (*(volatile type*)addr) barrier); } + +build_mmio_write(writeb, "b", unsigned char, "q", :"memory") +build_mmio_write(writew, "w", unsigned short, "r", :"memory") +build_mmio_write(writel, "l", unsigned int, "r", :"memory") + +#define BUILDIO(bwl, bw, type) \ +static inline void out##bwl(unsigned type value, int port) \ +{ \ + asm volatile("out" #bwl " %" #bw "0, %w1" \ + : : "a"(value), "Nd"(port)); \ +} \ + \ +static inline unsigned type in##bwl(int port) \ +{ \ + unsigned type value; \ + asm volatile("in" #bwl " %w1, %" #bw "0" \ + : "=a"(value) : "Nd"(port)); \ + return value; \ +} \ + \ +static inline void outs##bwl(int port, const void *addr, unsigned long count) \ +{ \ + asm volatile("rep; outs" #bwl \ + : "+S"(addr), "+c"(count) : "d"(port)); \ +} \ + \ +static inline void ins##bwl(int port, void *addr, unsigned long count) \ +{ \ + asm volatile("rep; ins" #bwl \ + : "+D"(addr), "+c"(count) : "d"(port)); \ +} + +BUILDIO(b, b, char) +BUILDIO(w, w, short) +BUILDIO(l, , int) + +#define IO_SPACE_LIMIT 0xffff + +#endif /* __ASM_SANDBOX_IO_H */ diff --git a/arch/efi/include/asm/posix_types.h b/arch/efi/include/asm/posix_types.h new file mode 100644 index 0000000000..6985b8eb4a --- /dev/null +++ b/arch/efi/include/asm/posix_types.h @@ -0,0 +1,93 @@ +#ifndef __ARCH_I386_POSIX_TYPES_H +#define __ARCH_I386_POSIX_TYPES_H + +/* + * This file is generally used by user-level software, so you need to + * be a little careful about namespace pollution etc. Also, we cannot + * assume GCC is being used. + */ + +typedef unsigned long __kernel_ino_t; +typedef unsigned short __kernel_mode_t; +typedef unsigned short __kernel_nlink_t; +typedef long __kernel_off_t; +typedef int __kernel_pid_t; +typedef unsigned short __kernel_ipc_pid_t; +typedef unsigned short __kernel_uid_t; +typedef unsigned short __kernel_gid_t; +/* + * Most 32 bit architectures use "unsigned int" size_t, + * and all 64 bit architectures use "unsigned long" size_t. + * + * TODO: It's not clean to use __x86_64__ here. It's better + * to check on __BITS_PER_LONG here. But this is wrong set in + * arch/sandbox/include/asm/types.h. + */ +#ifdef __x86_64__ +typedef unsigned long __kernel_size_t; +typedef long __kernel_ssize_t; +typedef long __kernel_ptrdiff_t; +#else +typedef unsigned int __kernel_size_t; +typedef int __kernel_ssize_t; +typedef int __kernel_ptrdiff_t; +#endif +typedef long __kernel_time_t; +typedef long __kernel_suseconds_t; +typedef long __kernel_clock_t; +typedef int __kernel_daddr_t; +typedef char * __kernel_caddr_t; +typedef unsigned short __kernel_uid16_t; +typedef unsigned short __kernel_gid16_t; +typedef unsigned int __kernel_uid32_t; +typedef unsigned int __kernel_gid32_t; + +typedef unsigned short __kernel_old_uid_t; +typedef unsigned short __kernel_old_gid_t; + +#ifdef __GNUC__ +typedef long long __kernel_loff_t; +#endif + +typedef struct { +#if defined(__KERNEL__) || defined(__USE_ALL) + int val[2]; +#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */ + int __val[2]; +#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */ +} __kernel_fsid_t; + +#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) + +#undef __FD_SET +#define __FD_SET(fd,fdsetp) \ + __asm__ __volatile__("btsl %1,%0": \ + "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef __FD_CLR +#define __FD_CLR(fd,fdsetp) \ + __asm__ __volatile__("btrl %1,%0": \ + "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd))) + +#undef __FD_ISSET +#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \ + unsigned char __result; \ + __asm__ __volatile__("btl %1,%2 ; setb %0" \ + :"=q" (__result) :"r" ((int) (fd)), \ + "m" (*(__kernel_fd_set *) (fdsetp))); \ + __result; })) + +#undef __FD_ZERO +#define __FD_ZERO(fdsetp) \ +do { \ + int __d0, __d1; \ + __asm__ __volatile__("cld ; rep ; stosl" \ + :"=m" (*(__kernel_fd_set *) (fdsetp)), \ + "=&c" (__d0), "=&D" (__d1) \ + :"a" (0), "1" (__FDSET_LONGS), \ + "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \ +} while (0) + +#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */ + +#endif diff --git a/arch/efi/include/asm/sections.h b/arch/efi/include/asm/sections.h new file mode 100644 index 0000000000..2b8c516038 --- /dev/null +++ b/arch/efi/include/asm/sections.h @@ -0,0 +1 @@ +#include <asm-generic/sections.h> diff --git a/arch/efi/include/asm/string.h b/arch/efi/include/asm/string.h new file mode 100644 index 0000000000..2997587d82 --- /dev/null +++ b/arch/efi/include/asm/string.h @@ -0,0 +1 @@ +/* dummy */ diff --git a/arch/efi/include/asm/swab.h b/arch/efi/include/asm/swab.h new file mode 100644 index 0000000000..60a90120b6 --- /dev/null +++ b/arch/efi/include/asm/swab.h @@ -0,0 +1,6 @@ +#ifndef _ASM_SWAB_H +#define _ASM_SWAB_H + +/* nothing. use generic functions */ + +#endif /* _ASM_SWAB_H */ diff --git a/arch/efi/include/asm/types.h b/arch/efi/include/asm/types.h new file mode 100644 index 0000000000..3204448dce --- /dev/null +++ b/arch/efi/include/asm/types.h @@ -0,0 +1,73 @@ +#ifndef __ASM_I386_TYPES_H +#define __ASM_I386_TYPES_H + +#ifndef __ASSEMBLY__ + +#ifdef __x86_64__ +/* + * This is used in dlmalloc. On X86_64 we need it to be + * 64 bit + */ +#define INTERNAL_SIZE_T unsigned long + +/* + * This is a Kconfig variable in the Kernel, but we want to detect + * this during compile time, so we set it here. + */ +#define CONFIG_PHYS_ADDR_T_64BIT + +#endif + +typedef unsigned short umode_t; + +/* + * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the + * header files exported to user space + */ + +typedef __signed__ char __s8; +typedef unsigned char __u8; + +typedef __signed__ short __s16; +typedef unsigned short __u16; + +typedef __signed__ int __s32; +typedef unsigned int __u32; + +#if defined(__GNUC__) && !defined(__STRICT_ANSI__) +typedef __signed__ long long __s64; +typedef unsigned long long __u64; +#endif + +/* + * These aren't exported outside the kernel to avoid name space clashes + */ +#ifdef __KERNEL__ + +typedef signed char s8; +typedef unsigned char u8; + +typedef signed short s16; +typedef unsigned short u16; + +typedef signed int s32; +typedef unsigned int u32; + +typedef signed long long s64; +typedef unsigned long long u64; + +#ifdef __x86_64__ +#define BITS_PER_LONG 64 +#else +#define BITS_PER_LONG 32 +#endif + +/* Dma addresses are 32-bits wide. */ + +typedef u32 dma_addr_t; + +#endif /* __KERNEL__ */ + +#endif + +#endif diff --git a/arch/efi/include/asm/unaligned.h b/arch/efi/include/asm/unaligned.h new file mode 100644 index 0000000000..d02da6e60d --- /dev/null +++ b/arch/efi/include/asm/unaligned.h @@ -0,0 +1,19 @@ +#ifndef _ASM_SANDBOX_UNALIGNED_H +#define _ASM_SANDBOX_UNALIGNED_H + +/* + * The architecture sandbox is compiled on can do unaligned accesses itself. + */ + +#include <linux/unaligned/access_ok.h> +#include <linux/unaligned/generic.h> + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define get_unaligned __get_unaligned_le +#define put_unaligned __put_unaligned_le +#else +#define get_unaligned __get_unaligned_be +#define put_unaligned __put_unaligned_be +#endif + +#endif /* _ASM_SANDBOX_UNALIGNED_H */ diff --git a/arch/efi/include/mach/debug_ll.h b/arch/efi/include/mach/debug_ll.h new file mode 100644 index 0000000000..0fb2cb8c2a --- /dev/null +++ b/arch/efi/include/mach/debug_ll.h @@ -0,0 +1,20 @@ +#ifndef __MACH_DEBUG_LL_H__ +#define __MACH_DEBUG_LL_H__ + +#define EFI_DEBUG 0 +#define EFI_DEBUG_CLEAR_MEMORY 0 + +#include <efi.h> +#include <mach/efi.h> + +static inline void PUTC_LL(char c) +{ + uint16_t str[2] = {}; + struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out; + + str[0] = c; + + con_out->output_string(con_out, str); +} + +#endif diff --git a/arch/efi/include/mach/efi-device.h b/arch/efi/include/mach/efi-device.h new file mode 100644 index 0000000000..fe074a44bb --- /dev/null +++ b/arch/efi/include/mach/efi-device.h @@ -0,0 +1,45 @@ +#ifndef __MACH_EFI_DEVICE_H +#define __MACH_EFI_DEVICE_H + +struct efi_device { + struct device_d dev; + efi_guid_t *guids; + int num_guids; + efi_handle_t handle; + efi_handle_t parent_handle; + void *protocol; + struct efi_device_path *devpath; +}; + +struct efi_driver { + struct driver_d driver; + int (*probe)(struct efi_device *efidev); + void (*remove)(struct efi_device *efidev); + efi_guid_t guid; +}; + +extern struct bus_type efi_bus; + +static inline struct efi_device *to_efi_device(struct device_d *dev) +{ + return container_of(dev, struct efi_device, dev); +} + +static inline struct efi_driver *to_efi_driver(struct driver_d *drv) +{ + return container_of(drv, struct efi_driver, driver); +} + +#define device_efi_driver(drv) \ + register_driver_macro(device, efi, drv) + +static inline int efi_driver_register(struct efi_driver *efidrv) +{ + efidrv->driver.bus = &efi_bus; + return register_driver(&efidrv->driver); +} + +int efi_connect_all(void); +void efi_register_devices(void); + +#endif /* __MACH_EFI_DEVICE_H */ diff --git a/arch/efi/include/mach/efi.h b/arch/efi/include/mach/efi.h new file mode 100644 index 0000000000..1e9782a136 --- /dev/null +++ b/arch/efi/include/mach/efi.h @@ -0,0 +1,24 @@ +#ifndef __MACH_EFI_H +#define __MACH_EFI_H + +#include <efi.h> + +const char *efi_strerror(efi_status_t err); + +extern efi_system_table_t *efi_sys_table; +extern efi_handle_t efi_parent_image; +extern struct efi_device_path *efi_device_path; +extern efi_loaded_image_t *efi_loaded_image; + +int efi_errno(efi_status_t err); + +int efi_clocksource_init(void); + +void *efi_get_variable(char *name, efi_guid_t *vendor, int *var_size); + +static inline void *efi_get_global_var(char *name, int *var_size) +{ + return efi_get_variable(name, &efi_global_variable_guid, var_size); +} + +#endif /* __MACH_EFI_H */ diff --git a/arch/efi/lib/.gitignore b/arch/efi/lib/.gitignore new file mode 100644 index 0000000000..847e317701 --- /dev/null +++ b/arch/efi/lib/.gitignore @@ -0,0 +1,2 @@ +elf_x86_64_efi.lds +elf_ia32_efi.lds diff --git a/arch/efi/lib/Makefile b/arch/efi/lib/Makefile new file mode 100644 index 0000000000..c8a97bae07 --- /dev/null +++ b/arch/efi/lib/Makefile @@ -0,0 +1,4 @@ +obj-$(CONFIG_X86_64) += reloc_x86_64.o crt0-efi-x86_64.o +obj-$(CONFIG_X86_32) += reloc_ia32.o crt0-efi-ia32.o +extra-$(CONFIG_X86_32) += elf_ia32_efi.lds +extra-$(CONFIG_X86_64) += elf_x86_64_efi.lds diff --git a/arch/efi/lib/crt0-efi-ia32.S b/arch/efi/lib/crt0-efi-ia32.S new file mode 100644 index 0000000000..6f0f2e872e --- /dev/null +++ b/arch/efi/lib/crt0-efi-ia32.S @@ -0,0 +1,76 @@ +/* crt0-efi-ia32.S - x86 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + + .text + .align 4 + + .globl _start +_start: + pushl %ebp + movl %esp,%ebp + + pushl 12(%ebp) # copy "image" argument + pushl 8(%ebp) # copy "systab" argument + + call 0f +0: popl %eax + movl %eax,%ebx + + addl $image_base-0b,%eax # %eax = ldbase + addl $_DYNAMIC-0b,%ebx # %ebx = _DYNAMIC + + pushl %ebx # pass _DYNAMIC as second argument + pushl %eax # pass ldbase as first argument + call _relocate + popl %ebx + popl %ebx + testl %eax,%eax + jne .exit + + call efi_main # call app with "image" and "systab" argument + +.exit: leave + ret + + /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */ + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc + .long dummy /* Page RVA */ + .long 10 /* Block Size (2*4+2) */ + .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */ diff --git a/arch/efi/lib/crt0-efi-x86_64.S b/arch/efi/lib/crt0-efi-x86_64.S new file mode 100644 index 0000000000..aa03106e9c --- /dev/null +++ b/arch/efi/lib/crt0-efi-x86_64.S @@ -0,0 +1,75 @@ +/* crt0-efi-x86_64.S - x86_64 EFI startup code. + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu <fenghua.yu@intel.com>. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + .text + .align 4 + + .globl _start +_start: + subq $8, %rsp + pushq %rcx + pushq %rdx + +0: + lea image_base(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + + popq %rcx + popq %rdx + pushq %rcx + pushq %rdx + call _relocate + + popq %rdi + popq %rsi + + call efi_main + addq $8, %rsp + +.exit: + ret + + /* hand-craft a dummy .reloc section so EFI knows it's a relocatable executable: */ + + .data +dummy: .long 0 + +#define IMAGE_REL_ABSOLUTE 0 + .section .reloc, "a" +label1: + .long dummy-label1 /* Page RVA */ + .long 10 /* Block Size (2*4+2) */ + .word (IMAGE_REL_ABSOLUTE<<12) + 0 /* reloc for dummy */ diff --git a/arch/efi/lib/elf_ia32_efi.lds.S b/arch/efi/lib/elf_ia32_efi.lds.S new file mode 100644 index 0000000000..a5f6287500 --- /dev/null +++ b/arch/efi/lib/elf_ia32_efi.lds.S @@ -0,0 +1,102 @@ +#include <asm-generic/barebox.lds.h> + +OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386") +OUTPUT_ARCH(i386) +ENTRY(_start) +SECTIONS +{ + . = 0; + image_base = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .text : + { + _stext = .; + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + _etext = .; + + . = ALIGN(4096); + .sdata : { + *(.got.plt) + *(.got) + *(.srodata) + *(.sdata) + *(.sbss) + *(.scommon) + } + + . = ALIGN(4096); + _sdata = .; + + .data : { + *(.rodata*) + *(.data) + *(.data1) + *(.data.*) + *(.sdata) + *(.got.plt) + *(.got) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + } + + . = ALIGN(64); + + __barebox_initcalls_start = .; + __barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + + . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + + . = ALIGN(64); + __barebox_cmd_start = .; + __barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + .rel : { + *(.rel.data) + *(.rel.data.*) + *(.rel.got) + *(.rel.stab) + *(.data.rel.ro.local) + *(.data.rel.local) + *(.data.rel.ro) + *(.data.rel*) + } + + . = ALIGN(4096); + .reloc : /* This is the PECOFF .reloc section! */ + { + *(.reloc) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + /DISCARD/ : + { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/efi/lib/elf_x86_64_efi.lds.S b/arch/efi/lib/elf_x86_64_efi.lds.S new file mode 100644 index 0000000000..d48432d21b --- /dev/null +++ b/arch/efi/lib/elf_x86_64_efi.lds.S @@ -0,0 +1,93 @@ +#include <asm-generic/barebox.lds.h> + +/* Same as elf_x86_64_fbsd_efi.lds, except for OUTPUT_FORMAT below - KEEP IN SYNC */ + +OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") +OUTPUT_ARCH(i386:x86-64) +ENTRY(_start) +SECTIONS +{ + . = 0; + image_base = .; + .hash : { *(.hash) } /* this MUST come first! */ + . = ALIGN(4096); + .eh_frame : { + *(.eh_frame) + } + + . = ALIGN(4096); + + .text : { + _stext = .; + _text = .; + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + } + + _etext = .; + + . = ALIGN(4096); + + .reloc : { + *(.reloc) + } + + . = ALIGN(4096); + _sdata = .; + + .data : { + *(.rodata*) + *(.got.plt) + *(.got) + *(.data*) + *(.sdata) + /* the EFI loader doesn't seem to like a .bss section, so we stick + * it all into .data: */ + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(COMMON) + *(.rel.local) + } + + . = ALIGN(64); + + __barebox_initcalls_start = .; + __barebox_initcalls : { INITCALLS } + __barebox_initcalls_end = .; + + . = ALIGN(64); + __barebox_magicvar_start = .; + .barebox_magicvar : { BAREBOX_MAGICVARS } + __barebox_magicvar_end = .; + + . = ALIGN(64); + __barebox_cmd_start = .; + __barebox_cmd : { BAREBOX_CMDS } + __barebox_cmd_end = .; + + . = ALIGN(4096); + .dynamic : { *(.dynamic) } + . = ALIGN(4096); + + .rela : { + *(.rela.data*) + *(.rela.got) + *(.rela.stab) + } + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .ignored.reloc : { + *(.rela.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + + .comment 0 : { *(.comment) } +} diff --git a/arch/efi/lib/reloc_ia32.c b/arch/efi/lib/reloc_ia32.c new file mode 100644 index 0000000000..46929631ec --- /dev/null +++ b/arch/efi/lib/reloc_ia32.c @@ -0,0 +1,97 @@ +/* reloc_ia32.c - position independent x86 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include <common.h> +#include <efi.h> + +#include <elf.h> + +efi_status_t _relocate(long ldbase, Elf32_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab) +{ + long relsz = 0, relent = 0; + Elf32_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_REL: + rel = (Elf32_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELSZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELENT: + relent = dyn[i].d_un.d_val; + break; + + case DT_RELA: + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF32_R_TYPE (rel->r_info)) { + case R_386_NONE: + break; + + case R_386_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf32_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/arch/efi/lib/reloc_x86_64.c b/arch/efi/lib/reloc_x86_64.c new file mode 100644 index 0000000000..1db72f5dbc --- /dev/null +++ b/arch/efi/lib/reloc_x86_64.c @@ -0,0 +1,96 @@ +/* reloc_x86_64.c - position independent x86_64 ELF shared object relocator + Copyright (C) 1999 Hewlett-Packard Co. + Contributed by David Mosberger <davidm@hpl.hp.com>. + Copyright (C) 2005 Intel Co. + Contributed by Fenghua Yu <fenghua.yu@intel.com>. + + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials + provided with the distribution. + * Neither the name of Hewlett-Packard Co. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS + BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. +*/ + +#include <common.h> +#include <efi.h> + +#include <elf.h> + +efi_status_t _relocate (long ldbase, Elf64_Dyn *dyn, efi_handle_t image, efi_system_table_t *systab) +{ + long relsz = 0, relent = 0; + Elf64_Rel *rel = 0; + unsigned long *addr; + int i; + + for (i = 0; dyn[i].d_tag != DT_NULL; ++i) { + switch (dyn[i].d_tag) { + case DT_RELA: + rel = (Elf64_Rel*) + ((unsigned long)dyn[i].d_un.d_ptr + + ldbase); + break; + + case DT_RELASZ: + relsz = dyn[i].d_un.d_val; + break; + + case DT_RELAENT: + relent = dyn[i].d_un.d_val; + break; + + default: + break; + } + } + + if (!rel && relent == 0) + return EFI_SUCCESS; + + if (!rel || relent == 0) + return EFI_LOAD_ERROR; + + while (relsz > 0) { + /* apply the relocs */ + switch (ELF64_R_TYPE (rel->r_info)) { + case R_X86_64_NONE: + break; + + case R_X86_64_RELATIVE: + addr = (unsigned long *) + (ldbase + rel->r_offset); + *addr += ldbase; + break; + + default: + break; + } + rel = (Elf64_Rel*) ((char *) rel + relent); + relsz -= relent; + } + return EFI_SUCCESS; +} diff --git a/arch/mips/configs/qemu-malta_defconfig b/arch/mips/configs/qemu-malta_defconfig index 6ee302df02..5a1ca36822 100644 --- a/arch/mips/configs/qemu-malta_defconfig +++ b/arch/mips/configs/qemu-malta_defconfig @@ -14,6 +14,7 @@ CONFIG_POLLER=y CONFIG_DEBUG_INFO=y CONFIG_LONGHELP=y CONFIG_CMD_IOMEM=y +CONFIG_CMD_IMD=y CONFIG_CMD_MEMINFO=y CONFIG_CMD_BOOTM_SHOW_TYPE=y CONFIG_CMD_GO=y diff --git a/arch/mips/configs/ritmix-rzx50_defconfig b/arch/mips/configs/ritmix-rzx50_defconfig index e6f10fb938..232faa2659 100644 --- a/arch/mips/configs/ritmix-rzx50_defconfig +++ b/arch/mips/configs/ritmix-rzx50_defconfig @@ -29,12 +29,18 @@ CONFIG_CMD_GETOPT=y CONFIG_CMD_SLEEP=y CONFIG_CMD_EDIT=y CONFIG_CMD_GPIO=y +CONFIG_CMD_LED=y CONFIG_CMD_POWEROFF=y +CONFIG_CMD_LED_TRIGGER=y CONFIG_CMD_OF_NODE=y CONFIG_CMD_OF_PROPERTY=y CONFIG_CMD_OFTREE=y CONFIG_OFDEVICE=y # CONFIG_SPI is not set +CONFIG_LED=y +CONFIG_LED_GPIO=y +CONFIG_LED_GPIO_OF=y +CONFIG_LED_TRIGGERS=y CONFIG_GPIO_JZ4740=y CONFIG_SHA1=y CONFIG_SHA224=y diff --git a/arch/mips/dts/Makefile b/arch/mips/dts/Makefile index 7ccb2f811c..6d6c9a3ce0 100644 --- a/arch/mips/dts/Makefile +++ b/arch/mips/dts/Makefile @@ -2,14 +2,4 @@ BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_NAME)) obj-$(CONFIG_BUILTIN_DTB) += $(BUILTIN_DTB).dtb.o -dtb-y += ${BUILTIN_DTB}.dtb - -.SECONDARY: $(obj)/$(BUILTIN_DTB).dtb.S -.SECONDARY: $(patsubst %,$(obj)/%.S,$(dtb-y)) - -targets += dtbs -targets += $(dtb-y) - -extra-y += $(dtb-y) - clean-files := *.dtb *.dtb.S diff --git a/arch/mips/dts/rzx50.dts b/arch/mips/dts/rzx50.dts index 360c1bf5de..7ec3352666 100644 --- a/arch/mips/dts/rzx50.dts +++ b/arch/mips/dts/rzx50.dts @@ -9,6 +9,16 @@ memory { reg = <0x00000000 0x4000000>; }; + + gpio-leds { + compatible = "gpio-leds"; + + lcd-backlight-enable { + label = "lcd backlight"; + gpios = <&gpio4 22 0>; + linux,default-trigger = "default-on"; + }; + }; }; &serial1 { diff --git a/arch/mips/lib/barebox.lds.S b/arch/mips/lib/barebox.lds.S index 4ee4252b6d..c690e71976 100644 --- a/arch/mips/lib/barebox.lds.S +++ b/arch/mips/lib/barebox.lds.S @@ -49,6 +49,8 @@ SECTIONS . = ALIGN(4); .data : { *(.data*) } + .barebox_imd : { BAREBOX_IMD } + . = ALIGN(4); .got : { *(.got*) } diff --git a/arch/mips/lib/bootm.c b/arch/mips/lib/bootm.c index 3d6a4ce648..0e03aa9bcb 100644 --- a/arch/mips/lib/bootm.c +++ b/arch/mips/lib/bootm.c @@ -1,5 +1,6 @@ #include <boot.h> #include <common.h> +#include <libfile.h> #include <init.h> #include <fs.h> #include <errno.h> diff --git a/arch/mips/pbl/zbarebox.lds.S b/arch/mips/pbl/zbarebox.lds.S index 3a26942b4c..a883fdb2db 100644 --- a/arch/mips/pbl/zbarebox.lds.S +++ b/arch/mips/pbl/zbarebox.lds.S @@ -44,6 +44,8 @@ SECTIONS . = ALIGN(4); .rodata : { *(.rodata*) } + .barebox_imd : { BAREBOX_IMD } + _etext = .; /* End of text and rodata section */ . = ALIGN(4); diff --git a/commands/Kconfig b/commands/Kconfig index 61816f5115..71cd1ee99e 100644 --- a/commands/Kconfig +++ b/commands/Kconfig @@ -148,6 +148,15 @@ config CMD_IOMEM Show information about iomem/ioport usage. Pendant to 'cat /proc/iomem' and 'cat /proc/ioports' under Linux. +config CMD_IMD + tristate + prompt "imd" + select IMD + help + barebox images can have metadata in them which contains information + like the barebox version and the build time. Say yes here to get the + imd command which can extract that information from images. + config CMD_MEMINFO tristate prompt "meminfo" @@ -1859,7 +1868,7 @@ endmenu -menu "Miscelleanous" +menu "Miscellaneous" config CMD_2048 tristate @@ -1976,7 +1985,7 @@ config CMD_TIME Note: This command depends on COMMAND being interruptible, otherwise the timer may overrun resulting in incorrect results -# end Miscelleanous commands +# end Miscellaneous commands endmenu diff --git a/commands/Makefile b/commands/Makefile index d42aca5c0c..44741360e2 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -100,3 +100,4 @@ obj-$(CONFIG_CMD_MENUTREE) += menutree.o obj-$(CONFIG_CMD_2048) += 2048.o obj-$(CONFIG_CMD_REGULATOR) += regulator.o obj-$(CONFIG_CMD_LSPCI) += lspci.o +obj-$(CONFIG_CMD_IMD) += imd.o diff --git a/commands/barebox-update.c b/commands/barebox-update.c index a24dc3ef4d..92e0efab6a 100644 --- a/commands/barebox-update.c +++ b/commands/barebox-update.c @@ -17,6 +17,7 @@ */ #include <common.h> #include <command.h> +#include <libfile.h> #include <getopt.h> #include <malloc.h> #include <errno.h> diff --git a/commands/cp.c b/commands/cp.c index 1a5675405e..af7a3d4dc0 100644 --- a/commands/cp.c +++ b/commands/cp.c @@ -26,6 +26,7 @@ #include <malloc.h> #include <libgen.h> #include <getopt.h> +#include <libfile.h> /** * @param[in] argc Argument count from command line diff --git a/commands/crc.c b/commands/crc.c index 7c2936c23c..9b6a3e2a4b 100644 --- a/commands/crc.c +++ b/commands/crc.c @@ -22,6 +22,7 @@ #include <fs.h> #include <getopt.h> #include <malloc.h> +#include <libfile.h> #include <environment.h> static int crc_from_file(const char* file, ulong *crc) diff --git a/commands/dfu.c b/commands/dfu.c index 354625260d..7f78f3bbc2 100644 --- a/commands/dfu.c +++ b/commands/dfu.c @@ -172,12 +172,15 @@ out: BAREBOX_CMD_HELP_START(dfu) BAREBOX_CMD_HELP_TEXT("Turn's the USB host into DFU mode (Device Firmware Mode) and accepts") -BAREBOX_CMD_HELP_TEXT("a new firmware. The destination is described by DESC in the this format:") -BAREBOX_CMD_HELP_TEXT(" DEVICE(NAME)[src]...") -BAREBOX_CMD_HELP_TEXT("Specify the '(') and ')' literal, the [] however denote this optional modes:") -BAREBOX_CMD_HELP_TEXT("- 's' safe mode (download the complete image before flashing)") -BAREBOX_CMD_HELP_TEXT("- 'r' readback of the firmware is allowed") -BAREBOX_CMD_HELP_TEXT("- 'c' the file will be created (for use with regular files)") +BAREBOX_CMD_HELP_TEXT("a new firmware. The destination is described by DESC in the format") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("\tDEVICE(NAME)[src]...") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Here '(' and ')' are literal characters. The '[' and ']' however denote") +BAREBOX_CMD_HELP_TEXT("one of the following optional modes:") +BAREBOX_CMD_HELP_TEXT("'s': safe mode (download the complete image before flashing); ") +BAREBOX_CMD_HELP_TEXT("'r': readback of the firmware is allowed; ") +BAREBOX_CMD_HELP_TEXT("'c': the file will be created (for use with regular files).") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-m STR", "Manufacturer string (barebox)") diff --git a/commands/edit.c b/commands/edit.c index 5a2da7d034..b28e2b92a1 100644 --- a/commands/edit.c +++ b/commands/edit.c @@ -21,6 +21,7 @@ #include <fs.h> #include <linux/ctype.h> #include <fcntl.h> +#include <libfile.h> #include <readkey.h> #include <errno.h> #include <xfuncs.h> @@ -379,7 +380,16 @@ static int do_edit(int argc, char *argv[]) return COMMAND_ERROR_USAGE; screenwidth = 80; - screenheight = 25; + + /* + * The EFI simple text output protocol wraps to the next line and scrolls + * down when we write to the right bottom screen position. Reduce the number + * of rows by one to work around this. + */ + if (IS_ENABLED(CONFIG_ARCH_EFI)) + screenheight = 24; + else + screenheight = 25; /* check if we are called as "sedit" instead of "edit" */ if (*argv[0] == 's') { diff --git a/commands/exec.c b/commands/exec.c index 635f65eeb2..7c8934f137 100644 --- a/commands/exec.c +++ b/commands/exec.c @@ -23,6 +23,7 @@ #include <fcntl.h> #include <linux/stat.h> #include <errno.h> +#include <libfile.h> #include <malloc.h> #include <xfuncs.h> diff --git a/commands/help.c b/commands/help.c index 9c33807fad..898533594f 100644 --- a/commands/help.c +++ b/commands/help.c @@ -128,7 +128,7 @@ static int do_help(int argc, char *argv[]) BAREBOX_CMD_HELP_START(help) -BAREBOX_CMD_HELP_TEXT("Without arguments, lists all all commands. With an argument, print help") +BAREBOX_CMD_HELP_TEXT("Without arguments, lists all commands. With an argument, print help") BAREBOX_CMD_HELP_TEXT("about the specified command. If the argument is 'all', then output help") BAREBOX_CMD_HELP_TEXT("for all commands.") BAREBOX_CMD_HELP_TEXT("") diff --git a/commands/i2c.c b/commands/i2c.c index 2811f6abeb..d6c5412762 100644 --- a/commands/i2c.c +++ b/commands/i2c.c @@ -75,7 +75,7 @@ static int do_i2c_write(int argc, char *argv[]) int addr = -1, reg = -1, count = -1, verbose = 0, ret, opt, i, bus = 0, wide = 0; u8 *buf; - while ((opt = getopt(argc, argv, "a:b:r:v:w")) > 0) { + while ((opt = getopt(argc, argv, "a:b:r:vw")) > 0) { switch (opt) { case 'a': addr = simple_strtol(optarg, NULL, 0); @@ -90,7 +90,7 @@ static int do_i2c_write(int argc, char *argv[]) verbose = 1; break; case 'w': - wide = 1; + wide = I2C_ADDR_16_BIT; break; } } @@ -113,9 +113,13 @@ static int do_i2c_write(int argc, char *argv[]) for (i = 0; i < count; i++) *(buf + i) = (char) simple_strtol(argv[optind+i], NULL, 16); - ret = i2c_write_reg(&client, reg | (wide ? I2C_ADDR_16_BIT : 0), buf, count); - if (ret != count) + ret = i2c_write_reg(&client, reg | wide, buf, count); + if (ret != count) { + if (verbose) + printf("write aborted, count(%i) != writestatus(%i)\n", + count, ret); goto out; + } ret = 0; if (verbose) { @@ -155,7 +159,7 @@ static int do_i2c_read(int argc, char *argv[]) u8 *buf; int count = -1, addr = -1, reg = -1, verbose = 0, ret, opt, bus = 0, wide = 0; - while ((opt = getopt(argc, argv, "a:b:c:r:v:w")) > 0) { + while ((opt = getopt(argc, argv, "a:b:c:r:vw")) > 0) { switch (opt) { case 'a': addr = simple_strtol(optarg, NULL, 0); @@ -173,7 +177,7 @@ static int do_i2c_read(int argc, char *argv[]) verbose = 1; break; case 'w': - wide = 1; + wide = I2C_ADDR_16_BIT; break; } } @@ -191,7 +195,7 @@ static int do_i2c_read(int argc, char *argv[]) client.addr = addr; buf = xmalloc(count); - ret = i2c_read_reg(&client, reg | (wide ? I2C_ADDR_16_BIT : 0), buf, count); + ret = i2c_read_reg(&client, reg | wide, buf, count); if (ret == count) { int i; if (verbose) diff --git a/commands/imd.c b/commands/imd.c new file mode 100644 index 0000000000..f1a22cef96 --- /dev/null +++ b/commands/imd.c @@ -0,0 +1,60 @@ +/* + * (C) Copyright 2014 Sascha Hauer, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <command.h> +#include <complete.h> +#include <environment.h> +#include <image-metadata.h> + +int imd_command_setenv(const char *variable_name, const char *value) +{ + return setenv(variable_name, value); +} + +static int do_imd(int argc, char *argv[]) +{ + int ret; + + ret = imd_command(argc, argv); + + if (ret == -ENOSYS) + return COMMAND_ERROR_USAGE; + + return ret; +} + +BAREBOX_CMD_HELP_START(imd) +BAREBOX_CMD_HELP_TEXT("extract metadata from barebox binary") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Options:") +BAREBOX_CMD_HELP_OPT ("-t <type>", "only show information of <type>") +BAREBOX_CMD_HELP_OPT ("-n <no>", "for tags with multiple strings only show string <no>") +BAREBOX_CMD_HELP_OPT ("-s VARNAME", "set variable VARNAME instead of showing information") +BAREBOX_CMD_HELP_TEXT("") +BAREBOX_CMD_HELP_TEXT("Without options all information available is printed. Valid types are:") +BAREBOX_CMD_HELP_TEXT("release, build, model, of_compatible") +BAREBOX_CMD_HELP_END + +BAREBOX_CMD_START(imd) + .cmd = do_imd, + BAREBOX_CMD_DESC("extract metadata from barebox binary") + BAREBOX_CMD_OPTS("[nst] FILE") + BAREBOX_CMD_GROUP(CMD_GRP_INFO) + BAREBOX_CMD_HELP(cmd_imd_help) +BAREBOX_CMD_END diff --git a/commands/insmod.c b/commands/insmod.c index 176437ee70..735dde0222 100644 --- a/commands/insmod.c +++ b/commands/insmod.c @@ -3,6 +3,7 @@ #include <module.h> #include <errno.h> #include <fs.h> +#include <libfile.h> #include <malloc.h> static int do_insmod(int argc, char *argv[]) diff --git a/commands/linux16.c b/commands/linux16.c index 594efc7dc2..bb678bdb83 100644 --- a/commands/linux16.c +++ b/commands/linux16.c @@ -24,6 +24,7 @@ #include <environment.h> #include <fs.h> #include <errno.h> +#include <libfile.h> #include <getopt.h> #include <malloc.h> #include <boot.h> diff --git a/commands/lspci.c b/commands/lspci.c index c00b57f894..fdf02691b5 100644 --- a/commands/lspci.c +++ b/commands/lspci.c @@ -46,7 +46,7 @@ static int do_lspci(int argc, char *argv[]) BAREBOX_CMD_START(lspci) .cmd = do_lspci, - BAREBOX_CMD_DESC("Show PCI info") + BAREBOX_CMD_DESC("show PCI info") BAREBOX_CMD_GROUP(CMD_GRP_INFO) BAREBOX_CMD_COMPLETE(empty_complete) BAREBOX_CMD_END diff --git a/commands/of_dump.c b/commands/of_dump.c index cafde07b7c..315dbbae8c 100644 --- a/commands/of_dump.c +++ b/commands/of_dump.c @@ -18,6 +18,7 @@ */ #include <common.h> +#include <libfile.h> #include <fdt.h> #include <of.h> #include <command.h> diff --git a/commands/oftree.c b/commands/oftree.c index 983a0a59ea..8a47c0be58 100644 --- a/commands/oftree.c +++ b/commands/oftree.c @@ -26,6 +26,7 @@ #include <common.h> #include <environment.h> #include <fdt.h> +#include <libfile.h> #include <of.h> #include <command.h> #include <fs.h> @@ -42,7 +43,7 @@ static int do_oftree(int argc, char *argv[]) { struct fdt_header *fdt = NULL; - int size; + size_t size; int opt; int probe = 0; char *load = NULL; diff --git a/commands/readf.c b/commands/readf.c index c8cc574f35..8dd5a2b55a 100644 --- a/commands/readf.c +++ b/commands/readf.c @@ -1,6 +1,7 @@ #include <common.h> #include <command.h> #include <fs.h> +#include <libfile.h> #include <malloc.h> #include <linux/stat.h> #include <linux/ctype.h> diff --git a/commands/saveenv.c b/commands/saveenv.c index 54b6fa1b7b..9da733e722 100644 --- a/commands/saveenv.c +++ b/commands/saveenv.c @@ -18,26 +18,39 @@ #include <common.h> #include <command.h> #include <errno.h> +#include <getopt.h> #include <fs.h> #include <fcntl.h> #include <envfs.h> static int do_saveenv(int argc, char *argv[]) { - int ret; + int ret, opt; + unsigned envfs_flags = 0; char *filename, *dirname; printf("saving environment\n"); - if (argc < 3) + while ((opt = getopt(argc, argv, "z")) > 0) { + switch (opt) { + case 'z': + envfs_flags |= ENVFS_FLAGS_FORCE_BUILT_IN; + break; + } + } + + /* destination and source are given? */ + if (argc == optind + 2) + dirname = argv[optind + 1]; + else dirname = "/env"; + + /* destination only given? */ + if (argc == optind + 1) + filename = argv[optind]; else - dirname = argv[2]; - if (argc < 2) filename = default_environment_path_get(); - else - filename = argv[1]; - ret = envfs_save(filename, dirname); + ret = envfs_save(filename, dirname, envfs_flags); return ret; } @@ -47,15 +60,15 @@ BAREBOX_CMD_HELP_TEXT("Save the files in DIRECTORY to the persistent storage dev BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("ENVFS is usually a block in flash but can be any other file. If") BAREBOX_CMD_HELP_TEXT("omitted, DIRECTORY defaults to /env and ENVFS defaults to") -BAREBOX_CMD_HELP_TEXT("/dev/env0. Note that envfs can only handle files, directories are being") -BAREBOX_CMD_HELP_TEXT("skipped silently.") +BAREBOX_CMD_HELP_TEXT("/dev/env0.") +BAREBOX_CMD_HELP_OPT ("-z", "force the built-in default environment at startup") BAREBOX_CMD_HELP_END BAREBOX_CMD_START(saveenv) .cmd = do_saveenv, BAREBOX_CMD_DESC("save environment to persistent storage") - BAREBOX_CMD_OPTS("[ENVFS] [DIRECTORY]") + BAREBOX_CMD_OPTS("[-z] [ENVFS [DIRECTORY]]") BAREBOX_CMD_GROUP(CMD_GRP_ENV) BAREBOX_CMD_HELP(cmd_saveenv_help) BAREBOX_CMD_END diff --git a/commands/tftp.c b/commands/tftp.c index c066631ad4..8a3b541382 100644 --- a/commands/tftp.c +++ b/commands/tftp.c @@ -24,6 +24,7 @@ #include <fs.h> #include <net.h> #include <libbb.h> +#include <libfile.h> #define TFTP_MOUNT_PATH "/.tftp_tmp_path" @@ -92,7 +93,8 @@ err_free: } BAREBOX_CMD_HELP_START(tftp) -BAREBOX_CMD_HELP_TEXT("Load (or save) a file via TFTP.") +BAREBOX_CMD_HELP_TEXT("Load (or save) a file via TFTP. SOURCE is a path on server,") +BAREBOX_CMD_HELP_TEXT("server address is taken from the environment (ethX.serverip).") BAREBOX_CMD_HELP_TEXT("") BAREBOX_CMD_HELP_TEXT("Options:") BAREBOX_CMD_HELP_OPT ("-p", "push to TFTP server") diff --git a/commands/trigger.c b/commands/trigger.c index 17c8411501..b605448a91 100644 --- a/commands/trigger.c +++ b/commands/trigger.c @@ -68,8 +68,9 @@ static int do_trigger(int argc, char *argv[]) break; case LED_COMMAND_DISABLE_TRIGGER: - led_set_trigger(trigger, NULL); - return 0; + ret = led_set_trigger(trigger, NULL); + break; + case LED_COMMAND_SET_TRIGGER: if (argc - optind != 1) return COMMAND_ERROR_USAGE; diff --git a/commands/ubiformat.c b/commands/ubiformat.c index 443d645a5a..df0b801da9 100644 --- a/commands/ubiformat.c +++ b/commands/ubiformat.c @@ -40,6 +40,7 @@ #include <malloc.h> #include <ioctl.h> #include <libbb.h> +#include <libfile.h> #include <linux/mtd/mtd.h> #include <linux/kernel.h> #include <linux/stat.h> diff --git a/commands/uimage.c b/commands/uimage.c index 33523d7e5c..7c2dca41ec 100644 --- a/commands/uimage.c +++ b/commands/uimage.c @@ -7,6 +7,7 @@ #include <malloc.h> #include <errno.h> #include <getopt.h> +#include <libfile.h> static int uimage_fd; diff --git a/common/Kconfig b/common/Kconfig index 6aa0aac991..d3d9b884cf 100644 --- a/common/Kconfig +++ b/common/Kconfig @@ -80,6 +80,14 @@ config MENUTREE select GLOB select GLOB_SORT +config EFI_GUID + bool + help + With this option a table of EFI guids is compiled in. + +config EFI_DEVICEPATH + bool + menu "General Settings" config LOCALVERSION @@ -473,6 +481,13 @@ config BLSPEC on a device and it allows the Operating System to install / update kernels. +config IMD + bool "barebox metadata support" + +config IMD_TARGET + bool "build bareboximd target tool" + depends on IMD + config KERNEL_INSTALL_TARGET bool depends on !SANDBOX diff --git a/common/Makefile b/common/Makefile index 204241c919..ddd7db2578 100644 --- a/common/Makefile +++ b/common/Makefile @@ -43,7 +43,11 @@ obj-$(CONFIG_RESET_SOURCE) += reset_source.o obj-$(CONFIG_SHELL_HUSH) += hush.o obj-$(CONFIG_SHELL_SIMPLE) += parser.o obj-$(CONFIG_UIMAGE) += image.o uimage.o -obj-$(CONFIG_MENUTREE) += menutree.o +obj-$(CONFIG_MENUTREE) += menutree.o +obj-$(CONFIG_EFI_GUID) += efi-guid.o +obj-$(CONFIG_EFI_DEVICEPATH) += efi-devicepath.o +lwl-$(CONFIG_IMD) += imd-barebox.o +obj-$(CONFIG_IMD) += imd.o quiet_cmd_pwd_h = PWDH $@ ifdef CONFIG_PASSWORD diff --git a/common/block.c b/common/block.c index e522ee425a..0edc8619ef 100644 --- a/common/block.c +++ b/common/block.c @@ -55,6 +55,9 @@ static int writebuffer_flush(struct block_device *blk) } } + if (blk->ops->flush) + return blk->ops->flush(blk); + return 0; } diff --git a/common/blspec.c b/common/blspec.c index 9314eeab04..a4adc48da9 100644 --- a/common/blspec.c +++ b/common/blspec.c @@ -21,6 +21,7 @@ #include <malloc.h> #include <block.h> #include <fcntl.h> +#include <libfile.h> #include <libbb.h> #include <init.h> #include <boot.h> diff --git a/common/bootm.c b/common/bootm.c index 71390cb845..447c9b624c 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -16,6 +16,7 @@ #include <fs.h> #include <malloc.h> #include <memory.h> +#include <libfile.h> #include <globalvar.h> #include <init.h> diff --git a/common/console.c b/common/console.c index aa9e3ce0f5..e5f4267cbd 100644 --- a/common/console.c +++ b/common/console.c @@ -162,6 +162,22 @@ static void console_set_stdoutpath(struct console_device *cdev) free(str); } +static int __console_puts(struct console_device *cdev, const char *s) +{ + int n = 0; + + while (*s) { + if (*s == '\n') { + cdev->putc(cdev, '\r'); + n++; + } + cdev->putc(cdev, *s); + n++; + s++; + } + return n; +} + int console_register(struct console_device *newcdev) { struct device_d *dev = &newcdev->class_dev; @@ -170,8 +186,14 @@ int console_register(struct console_device *newcdev) if (initialized == CONSOLE_UNINITIALIZED) console_init_early(); - dev->id = DEVICE_ID_DYNAMIC; - strcpy(dev->name, "cs"); + if (newcdev->devname) { + dev->id = DEVICE_ID_SINGLE; + strcpy(dev->name, newcdev->devname); + } else { + dev->id = DEVICE_ID_DYNAMIC; + strcpy(dev->name, "cs"); + } + if (newcdev->dev) dev->parent = newcdev->dev; platform_device_register(dev); @@ -182,6 +204,9 @@ int console_register(struct console_device *newcdev) NULL, &newcdev->baudrate, "%u", newcdev); } + if (newcdev->putc && !newcdev->puts) + newcdev->puts = __console_puts; + dev_add_param(dev, "active", console_std_set, NULL, 0); if (IS_ENABLED(CONFIG_CONSOLE_ACTIVATE_FIRST)) { @@ -342,9 +367,19 @@ EXPORT_SYMBOL(console_putc); int console_puts(unsigned int ch, const char *str) { + struct console_device *cdev; const char *s = str; int n = 0; + if (initialized == CONSOLE_INIT_FULL) { + for_each_console(cdev) { + if (cdev->f_active & ch) { + n = cdev->puts(cdev, str); + } + } + return n; + } + while (*s) { if (*s == '\n') { console_putc(ch, '\r'); diff --git a/common/efi-devicepath.c b/common/efi-devicepath.c new file mode 100644 index 0000000000..2b1d916768 --- /dev/null +++ b/common/efi-devicepath.c @@ -0,0 +1,1370 @@ +#include <common.h> +#include <efi.h> +#include <malloc.h> +#include <string.h> +#include <wchar.h> + +struct string { + char *str; + int len; +}; + +char *cprintf(struct string *str, const char *fmt, ...) + __attribute__ ((format(__printf__, 2, 3))); + +char *cprintf(struct string *str, const char *fmt, ...) +{ + va_list args; + int len; + + va_start(args, fmt); + if (str->str) + len = vsprintf(str->str + str->len, fmt, args); + else + len = vsnprintf(NULL, 0, fmt, args); + va_end(args); + + str->len += len; + + return NULL; +} + +#define MIN_ALIGNMENT_SIZE 8 /* FIXME: X86_64 specific */ +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +#define EFI_DP_TYPE_MASK 0x7f +#define EFI_DP_TYPE_UNPACKED 0x80 + +#define END_DEVICE_PATH_TYPE 0x7f + +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 +#define END_DEVICE_PATH_LENGTH (sizeof(struct efi_device_path)) + +#define DP_IS_END_TYPE(a) +#define DP_IS_END_SUBTYPE(a) ( ((a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE ) + +#define device_path_type(a) ( ((a)->type) & EFI_DP_TYPE_MASK ) +#define next_device_path_node(a) ( (struct efi_device_path *) ( ((u8 *) (a)) + (a)->length)) +#define is_device_path_end_type(a) ( device_path_type(a) == END_DEVICE_PATH_TYPE ) +#define is_device_path_end_sub_type(a) ( (a)->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE ) +#define is_device_path_end(a) ( is_device_path_end_type(a) && is_device_path_end_sub_type(a) ) +#define is_device_path_unpacked(a) ( (a)->type & EFI_DP_TYPE_UNPACKED ) + +#define set_device_path_end_node(a) { \ + (a)->type = END_DEVICE_PATH_TYPE; \ + (a)->sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ + (a)->length = sizeof(struct efi_device_path); \ + } + +/* + * Hardware Device Path (UEFI 2.4 specification, version 2.4 § 9.3.2.) + */ + +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +struct pci_device_path { + struct efi_device_path header; + u8 Function; + u8 Device; +}; + +#define HW_PCCARD_DP 0x02 +struct pccard_device_path { + struct efi_device_path header; + u8 function_number; +}; + +#define HW_MEMMAP_DP 0x03 +struct memmap_device_path { + struct efi_device_path header; + u32 memory_type; + efi_physical_addr_t starting_address; + efi_physical_addr_t ending_address; +}; + +#define HW_VENDOR_DP 0x04 +struct vendor_device_path { + struct efi_device_path header; + efi_guid_t Guid; +}; + +struct unknown_device_vendor_device_path { + struct vendor_device_path device_path; + u8 legacy_drive_letter; +}; + +#define HW_CONTROLLER_DP 0x05 +struct controller_device_path { + struct efi_device_path header; + u32 Controller; +}; + +/* + * ACPI Device Path (UEFI 2.4 specification, version 2.4 § 9.3.3 and 9.3.4.) + */ +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +struct acpi_hid_device_path { + struct efi_device_path header; + u32 HID; + u32 UID; +}; + +#define EXPANDED_ACPI_DP 0x02 +struct expanded_acpi_hid_device_path { + struct efi_device_path header; + u32 HID; + u32 UID; + u32 CID; + u8 hid_str[1]; +}; + +#define ACPI_ADR_DP 3 +struct acpi_adr_device_path { + struct efi_device_path header; + u32 ADR; +}; + +/* + * EISA ID Macro + * EISA ID Definition 32-bits + * bits[15:0] - three character compressed ASCII EISA ID. + * bits[31:16] - binary number + * Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' + */ +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((u32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + +/* + * Messaging Device Path (UEFI 2.4 specification, version 2.4 § 9.3.5.) + */ +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +struct atapi_device_path { + struct efi_device_path header; + u8 primary_secondary; + u8 slave_master; + u16 Lun; +}; + +#define MSG_SCSI_DP 0x02 +struct scsi_device_path { + struct efi_device_path header; + u16 Pun; + u16 Lun; +}; + +#define MSG_FIBRECHANNEL_DP 0x03 +struct fibrechannel_device_path { + struct efi_device_path header; + u32 Reserved; + u64 WWN; + u64 Lun; +}; + +/** + * Fibre Channel Ex sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_FIBRECHANNELEX_DP 21 +struct fibrechannelex_device_path { + struct efi_device_path header; + u32 Reserved; + u8 WWN[8]; /* World Wide Name */ + u8 Lun[8]; /* Logical unit, T-10 SCSI Architecture Model 4 specification */ +}; + +#define MSG_1394_DP 0x04 +struct f1394_device_path { + struct efi_device_path header; + u32 Reserved; + u64 Guid; +}; + +#define MSG_USB_DP 0x05 +struct usb_device_path { + struct efi_device_path header; + u8 Port; + u8 Endpoint; +}; + +/** + * SATA Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.6. + */ +#define MSG_SATA_DP 18 +struct sata_device_path { + struct efi_device_path header; + u16 HBAPort_number; + u16 port_multiplier_port_number; + u16 Lun; /* Logical Unit Number */ +}; + +/** + * USB WWID Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.7. + */ +#define MSG_USB_WWID_DP 16 +struct usb_wwid_device_path { + struct efi_device_path header; + u16 interface_number; + u16 vendor_id; + u16 product_id; + s16 serial_number[1]; /* UTF-16 characters of the USB serial number */ +}; + +/** + * Device Logical Unit sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_DEVICE_LOGICAL_UNIT_DP 17 +struct device_logical_unit_device_path { + struct efi_device_path header; + u8 Lun; /* Logical Unit Number */ +}; + +#define MSG_USB_CLASS_DP 0x0_f +struct usb_class_device_path { + struct efi_device_path header; + u16 vendor_id; + u16 product_id; + u8 device_class; + u8 device_subclass; + u8 device_protocol; +}; + +#define MSG_I2_o_DP 0x06 +struct i2_o_device_path { + struct efi_device_path header; + u32 Tid; +}; + +#define MSG_MAC_ADDR_DP 0x0b +struct mac_addr_device_path { + struct efi_device_path header; + efi_mac_address mac_address; + u8 if_type; +}; + +#define MSG_IPv4_DP 0x0c +struct ipv4_device_path { + struct efi_device_path header; + efi_ipv4_address local_ip_address; + efi_ipv4_address remote_ip_address; + u16 local_port; + u16 remote_port; + u16 Protocol; + bool static_ip_address; + /* new from UEFI version 2, code must check length field in header */ + efi_ipv4_address gateway_ip_address; + efi_ipv4_address subnet_mask; +}; + +#define MSG_IPv6_DP 0x0d +struct ipv6_device_path { + struct efi_device_path header; + efi_ipv6_address local_ip_address; + efi_ipv6_address remote_ip_address; + u16 local_port; + u16 remote_port; + u16 Protocol; + bool IPAddress_origin; + /* new from UEFI version 2, code must check length field in header */ + u8 prefix_length; + efi_ipv6_address gateway_ip_address; +}; + +/** + * Device Logical Unit sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.5.8. + */ +#define MSG_VLAN_DP 20 +struct vlan_device_path { + struct efi_device_path header; + u16 vlan_id; +}; + +#define MSG_INFINIBAND_DP 0x09 +struct infiniband_device_path { + struct efi_device_path header; + u32 resource_flags; + efi_guid_t port_gid; + u64 service_id; + u64 target_port_id; + u64 device_id; +}; + +#define MSG_UART_DP 0x0e +struct uart_device_path { + struct efi_device_path header; + u32 Reserved; + u64 baud_rate; + u8 data_bits; + u8 Parity; + u8 stop_bits; +}; + +#define MSG_VENDOR_DP 0x0a +/* Use VENDOR_DEVICE_PATH struct */ + +#define DEVICE_PATH_MESSAGING_PC_ANSI \ + { 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define DEVICE_PATH_MESSAGING_VT_100 \ + { 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } + +#define DEVICE_PATH_MESSAGING_VT_100_PLUS \ + { 0x7baec70b , 0x57e0 , 0x4c76 , { 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } } + +#define DEVICE_PATH_MESSAGING_VT_UTF8 \ + { 0xad15a0d6 , 0x8bec , 0x4acf , { 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } } + +#define EFI_PC_ANSI_GUID \ + { 0xe0c14753 , 0xf9be , 0x11d2 , 0x9a , 0x0c , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d } + +#define EFI_VT_100_GUID \ + { 0xdfa66065 , 0xb419 , 0x11d3 , 0x9a , 0x2d , 0x00 , 0x90 , 0x27 , 0x3f , 0xc1 , 0x4d } + +#define EFI_VT_100_PLUS_GUID \ + { 0x7baec70b , 0x57e0 , 0x4c76 , 0x8e , 0x87 , 0x2f , 0x9e , 0x28 , 0x08 , 0x83 , 0x43 } + +#define EFI_VT_UTF8_GUID \ + { 0xad15a0d6 , 0x8bec , 0x4acf , 0xa0 , 0x73 , 0xd0 , 0x1d , 0xe7 , 0x7e , 0x2d , 0x88 } + +/* + * Media Device Path (UEFI 2.4 specification, version 2.4 § 9.3.6.) + */ +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +struct harddrive_device_path { + struct efi_device_path header; + u32 partition_number; + u64 partition_start; + u64 partition_size; + u8 signature[16]; + u8 mbr_type; + u8 signature_type; +}; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +struct cdrom_device_path { + struct efi_device_path header; + u32 boot_entry; + u64 partition_start; + u64 partition_size; +}; + +#define MEDIA_VENDOR_DP 0x03 +/* Use VENDOR_DEVICE_PATH struct */ + +#define MEDIA_FILEPATH_DP 0x04 +struct filepath_device_path { + struct efi_device_path header; + s16 path_name[1]; +}; + +#define SIZE_OF_FILEPATH_DEVICE_PATH offsetof(FILEPATH_DEVICE_PATH,path_name) + +#define MEDIA_PROTOCOL_DP 0x05 +struct media_protocol_device_path { + struct efi_device_path header; + efi_guid_t Protocol; +}; + +/** + * PIWG Firmware File sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.6.6. + */ +#define MEDIA_PIWG_FW_FILE_DP 6 +struct media_fw_vol_filepath_device_path { + struct efi_device_path header; + efi_guid_t fv_file_name; +}; + +/** + * PIWG Firmware Volume Device Path sub_type. + * UEFI 2.0 specification version 2.4 § 9.3.6.7. + */ +#define MEDIA_PIWG_FW_VOL_DP 7 +struct media_fw_vol_device_path { + struct efi_device_path header; + efi_guid_t fv_name; +}; + +/** + * Media relative offset range device path. + * UEFI 2.0 specification version 2.4 § 9.3.6.8. + */ +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 8 +struct media_relative_offset_range_device_path { + struct efi_device_path header; + u32 Reserved; + u64 starting_offset; + u64 ending_offset; +}; + +/* + * BIOS Boot Specification Device Path (UEFI 2.4 specification, version 2.4 § 9.3.7.) + */ +#define BBS_DEVICE_PATH 0x05 + +#define BBS_BBS_DP 0x01 +struct bbs_bbs_device_path { + struct efi_device_path header; + u16 device_type; + u16 status_flag; + s8 String[1]; +}; + +/* device_type definitions - from BBS specification */ +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_DEV 0x80 +#define BBS_TYPE_UNKNOWN 0x_fF + +struct efi_device_path end_device_path = { + .type = END_DEVICE_PATH_TYPE, + .sub_type = END_ENTIRE_DEVICE_PATH_SUBTYPE, + .length = END_DEVICE_PATH_LENGTH, +}; + +struct efi_device_path end_instance_device_path = { + .type = END_DEVICE_PATH_TYPE, + .sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE, + .length = END_DEVICE_PATH_LENGTH, +}; + +unsigned long +device_path_size(struct efi_device_path *dev_path) +{ + struct efi_device_path *Start; + + Start = dev_path; + while (!is_device_path_end(dev_path)) + dev_path = next_device_path_node(dev_path); + + return ((unsigned long) dev_path - (unsigned long) Start) + + sizeof (struct efi_device_path); +} + +struct efi_device_path * +duplicate_device_path(struct efi_device_path *dev_path) +{ + struct efi_device_path *new_dev_path; + unsigned long Size; + + Size = device_path_size(dev_path); + + new_dev_path = malloc(Size); + if (new_dev_path) + memcpy(new_dev_path, dev_path, Size); + + return new_dev_path; +} + +struct efi_device_path * +device_path_from_handle(efi_handle_t Handle) +{ + efi_status_t Status; + struct efi_device_path *device_path; + + Status = BS->handle_protocol(Handle, &efi_device_path_protocol_guid, + (void *) &device_path); + if (EFI_ERROR(Status)) + device_path = NULL; + + return device_path; +} + +struct efi_device_path * +device_path_instance(struct efi_device_path **device_path, unsigned long *Size) +{ + struct efi_device_path *Start, *Next, *dev_path; + unsigned long Count; + + dev_path = *device_path; + Start = dev_path; + + if (!dev_path) + return NULL; + + for (Count = 0;; Count++) { + Next = next_device_path_node(dev_path); + + if (is_device_path_end_type(dev_path)) + break; + + dev_path = Next; + } + + if (dev_path->sub_type == END_ENTIRE_DEVICE_PATH_SUBTYPE) + Next = NULL; + + *device_path = Next; + + *Size = ((u8 *) dev_path) - ((u8 *) Start); + + return Start; +} + +unsigned long +device_path_instance_count(struct efi_device_path *device_path) +{ + unsigned long Count, Size; + + Count = 0; + while (device_path_instance(&device_path, &Size)) { + Count += 1; + } + + return Count; +} + +struct efi_device_path * +append_device_path(struct efi_device_path *Src1, struct efi_device_path *Src2) +/* + * Src1 may have multiple "instances" and each instance is appended + * Src2 is appended to each instance is Src1. (E.g., it's possible + * to append a new instance to the complete device path by passing + * it in Src2) + */ +{ + unsigned long src1_size, src1_inst, src2_size, Size; + struct efi_device_path *Dst, *Inst; + u8 *dst_pos; + + if (!Src1) + return duplicate_device_path(Src2); + + if (!Src2) { + return duplicate_device_path(Src1); + } + + src1_size = device_path_size(Src1); + src1_inst = device_path_instance_count(Src1); + src2_size = device_path_size(Src2); + Size = src1_size * src1_inst + src2_size; + + Dst = malloc(Size); + if (Dst) { + dst_pos = (u8 *) Dst; + + /* Copy all device path instances */ + + while ((Inst = device_path_instance(&Src1, &Size))) { + + memcpy(dst_pos, Inst, Size); + dst_pos += Size; + + memcpy(dst_pos, Src2, src2_size); + dst_pos += src2_size; + + memcpy(dst_pos, &end_instance_device_path, + sizeof (struct efi_device_path)); + dst_pos += sizeof (struct efi_device_path); + } + + /* Change last end marker */ + dst_pos -= sizeof (struct efi_device_path); + memcpy(dst_pos, &end_device_path, + sizeof (struct efi_device_path)); + } + + return Dst; +} + +struct efi_device_path * +append_device_path_node(struct efi_device_path *Src1, + struct efi_device_path *Src2) +/* + * Src1 may have multiple "instances" and each instance is appended + * Src2 is a signal device path node (without a terminator) that is + * appended to each instance is Src1. + */ +{ + struct efi_device_path *Temp, *Eop; + unsigned long length; + + /* Build a Src2 that has a terminator on it */ + + length = Src2->length; + Temp = malloc(length + sizeof (struct efi_device_path)); + if (!Temp) + return NULL; + + memcpy(Temp, Src2, length); + Eop = next_device_path_node(Temp); + set_device_path_end_node(Eop); + + /* Append device paths */ + + Src1 = append_device_path(Src1, Temp); + free(Temp); + return Src1; +} + +struct efi_device_path * +unpack_device_path(struct efi_device_path *dev_path) +{ + struct efi_device_path *Src, *Dest, *new_path; + unsigned long Size; + + /* Walk device path and round sizes to valid boundries */ + + Src = dev_path; + Size = 0; + for (;;) { + Size += Src->length; + Size += ALIGN_SIZE(Size); + + if (is_device_path_end(Src)) { + break; + } + + Src = next_device_path_node(Src); + } + + new_path = xzalloc(Size); + + Src = dev_path; + Dest = new_path; + for (;;) { + Size = Src->length; + memcpy(Dest, Src, Size); + Size += ALIGN_SIZE(Size); + Dest->length = Size; + Dest->type |= EFI_DP_TYPE_UNPACKED; + Dest = + (struct efi_device_path *) (((u8 *) Dest) + Size); + + if (is_device_path_end(Src)) + break; + + Src = next_device_path_node(Src); + } + + return new_path; +} + +struct efi_device_path * +append_device_path_instance(struct efi_device_path *Src, + struct efi_device_path *Instance) +{ + u8 *Ptr; + struct efi_device_path *dev_path; + unsigned long src_size; + unsigned long instance_size; + + if (Src == NULL) + return duplicate_device_path(Instance); + + src_size = device_path_size(Src); + instance_size = device_path_size(Instance); + Ptr = malloc(src_size + instance_size); + dev_path = (struct efi_device_path *) Ptr; + + memcpy(Ptr, Src, src_size); + + while (!is_device_path_end(dev_path)) + dev_path = next_device_path_node(dev_path); + + /* + * Convert the End to an End Instance, since we are + * appending another instacne after this one its a good + * idea. + */ + dev_path->sub_type = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + dev_path = next_device_path_node(dev_path); + memcpy(dev_path, Instance, instance_size); + + return (struct efi_device_path *) Ptr; +} + +efi_status_t +lib_device_path_to_interface(efi_guid_t * Protocol, + struct efi_device_path *file_path, + void **Interface) +{ + efi_status_t Status; + efi_handle_t Device; + + Status = BS->locate_device_path(Protocol, &file_path, &Device); + + if (!EFI_ERROR(Status)) { + + /* If we didn't get a direct match return not found */ + Status = EFI_NOT_FOUND; + + if (is_device_path_end(file_path)) { + + /* It was a direct match, lookup the protocol interface */ + + Status = + BS->handle_protocol(Device, Protocol, Interface); + } + } + + if (EFI_ERROR(Status)) + *Interface = NULL; + + return Status; +} + +static void +dev_path_pci(struct string *str, void *dev_path) +{ + struct pci_device_path *Pci; + + Pci = dev_path; + cprintf(str, "Pci(0x%x,0x%x)", Pci->Device, Pci->Function); +} + +static void +dev_path_pccard(struct string *str, void *dev_path) +{ + struct pccard_device_path *Pccard; + + Pccard = dev_path; + cprintf(str, "Pccard(0x%x)", Pccard->function_number); +} + +static void +dev_path_mem_map(struct string *str, void *dev_path) +{ + struct memmap_device_path *mem_map; + + mem_map = dev_path; + cprintf(str, "mem_map(%d,0x%llx,0x%llx)", + mem_map->memory_type, + mem_map->starting_address, mem_map->ending_address); +} + +static void +dev_path_controller(struct string *str, void *dev_path) +{ + struct controller_device_path *Controller; + + Controller = dev_path; + cprintf(str, "Ctrl(%d)", Controller->Controller); +} + +static void +dev_path_vendor(struct string *str, void *dev_path) +{ + struct vendor_device_path *Vendor; + char *type; + struct unknown_device_vendor_device_path *unknown_dev_path; + + Vendor = dev_path; + switch (device_path_type(&Vendor->header)) { + case HARDWARE_DEVICE_PATH: + type = "Hw"; + break; + case MESSAGING_DEVICE_PATH: + type = "Msg"; + break; + case MEDIA_DEVICE_PATH: + type = "Media"; + break; + default: + type = "?"; + break; + } + + cprintf(str, "Ven%s(%pU", type, &Vendor->Guid); + if (efi_compare_guid(&Vendor->Guid, &efi_unknown_device_guid) == 0) { + /* GUID used by EFI to enumerate an EDD 1.1 device */ + unknown_dev_path = + (struct unknown_device_vendor_device_path *) Vendor; + cprintf(str, ":%02x)", unknown_dev_path->legacy_drive_letter); + } else { + cprintf(str, ")"); + } +} + +/* + type: 2 (ACPI Device Path) sub_type: 1 (ACPI Device Path) + */ +static void +dev_path_acpi(struct string *str, void *dev_path) +{ + struct acpi_hid_device_path *Acpi; + + Acpi = dev_path; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + switch (EISA_ID_TO_NUM(Acpi->HID)) { + case 0x301: + cprintf(str, "Keyboard(%d)", Acpi->UID); + break; + + case 0x401: + cprintf(str, "parallel_port(%d)", Acpi->UID); + break; + case 0x501: + cprintf(str, "Serial(%d)", Acpi->UID); + break; + case 0x604: + cprintf(str, "Floppy(%d)", Acpi->UID); + break; + case 0xa03: + cprintf(str, "pci_root(%d)", Acpi->UID); + break; + case 0xa08: + cprintf(str, "pcie_root(%d)", Acpi->UID); + break; + default: + cprintf(str, "Acpi(PNP%04x", + EISA_ID_TO_NUM(Acpi->HID)); + if (Acpi->UID) + cprintf(str, ",%d", Acpi->UID); + cprintf(str, ")"); + break; + } + } else { + cprintf(str, "Acpi(0x%X", Acpi->HID); + if (Acpi->UID) + cprintf(str, ",%d", Acpi->UID); + cprintf(str, ")"); + } +} + +static void +dev_path_atapi(struct string *str, void *dev_path) +{ + struct atapi_device_path *Atapi; + + Atapi = dev_path; + cprintf(str, "Ata(%s,%s)", + Atapi->primary_secondary ? "Secondary" : "Primary", + Atapi->slave_master ? "Slave" : "Master"); +} + +static void +dev_path_scsi(struct string *str, void *dev_path) +{ + struct scsi_device_path *Scsi; + + Scsi = dev_path; + cprintf(str, "Scsi(%d,%d)", Scsi->Pun, Scsi->Lun); +} + +static void +dev_path_fibre(struct string *str, void *dev_path) +{ + struct fibrechannel_device_path *Fibre; + + Fibre = dev_path; + cprintf(str, "Fibre%s(0x%016llx,0x%016llx)", + device_path_type(&Fibre->header) == + MSG_FIBRECHANNEL_DP ? "" : "Ex", Fibre->WWN, Fibre->Lun); +} + +static void +dev_path1394(struct string *str, void *dev_path) +{ + struct f1394_device_path *F1394; + + F1394 = dev_path; + cprintf(str, "1394(%pU)", &F1394->Guid); +} + +static void +dev_path_usb(struct string *str, void *dev_path) +{ + struct usb_device_path *Usb; + + Usb = dev_path; + cprintf(str, "Usb(0x%x,0x%x)", Usb->Port, Usb->Endpoint); +} + +static void +dev_path_i2_o(struct string *str, void *dev_path) +{ + struct i2_o_device_path *i2_o; + + i2_o = dev_path; + cprintf(str, "i2_o(0x%X)", i2_o->Tid); +} + +static void +dev_path_mac_addr(struct string *str, void *dev_path) +{ + struct mac_addr_device_path *MAC; + unsigned long hw_address_size; + unsigned long Index; + + MAC = dev_path; + + /* hw_address_size = sizeof(EFI_MAC_ADDRESS); */ + hw_address_size = MAC->header.length; + hw_address_size -= sizeof (MAC->header); + hw_address_size -= sizeof (MAC->if_type); + if (MAC->if_type == 0x01 || MAC->if_type == 0x00) + hw_address_size = 6; + + cprintf(str, "Mac("); + + for (Index = 0; Index < hw_address_size; Index++) + cprintf(str, "%02x", MAC->mac_address.Addr[Index]); + + if (MAC->if_type != 0) + cprintf(str, ",%d", MAC->if_type); + + cprintf(str, ")"); +} + +static void +cat_print_iPv4(struct string *str, efi_ipv4_address * address) +{ + cprintf(str, "%d.%d.%d.%d", address->Addr[0], address->Addr[1], + address->Addr[2], address->Addr[3]); +} + +static bool +is_not_null_iPv4(efi_ipv4_address * address) +{ + u8 val; + + val = address->Addr[0] | address->Addr[1]; + val |= address->Addr[2] | address->Addr[3]; + + return val != 0; +} + +static void +cat_print_network_protocol(struct string *str, u16 Proto) +{ + if (Proto == 6) + cprintf(str, "TCP"); + else if (Proto == 17) + cprintf(str, "UDP"); + else + cprintf(str, "%d", Proto); +} + +static void +dev_path_iPv4(struct string *str, void *dev_path) +{ + struct ipv4_device_path *ip; + bool show; + + ip = dev_path; + cprintf(str, "IPv4("); + cat_print_iPv4(str, &ip->remote_ip_address); + cprintf(str, ","); + cat_print_network_protocol(str, ip->Protocol); + cprintf(str, ",%s", ip->static_ip_address ? "Static" : "DHCP"); + show = is_not_null_iPv4(&ip->local_ip_address); + if (!show + && ip->header.length == + sizeof (struct ipv4_device_path)) { + /* only version 2 includes gateway and netmask */ + show |= is_not_null_iPv4(&ip->gateway_ip_address); + show |= is_not_null_iPv4(&ip->subnet_mask); + } + if (show) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->local_ip_address); + if (ip->header.length == + sizeof (struct ipv4_device_path)) { + /* only version 2 includes gateway and netmask */ + show = is_not_null_iPv4(&ip->gateway_ip_address); + show |= is_not_null_iPv4(&ip->subnet_mask); + if (show) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->gateway_ip_address); + if (is_not_null_iPv4(&ip->subnet_mask)) { + cprintf(str, ","); + cat_print_iPv4(str, &ip->subnet_mask); + } + } + } + } + cprintf(str, ")"); +} + +#define cat_print_iPv6_ADD( x , y ) ( ( (u16) ( x ) ) << 8 | ( y ) ) +static void +cat_print_ipv6(struct string *str, efi_ipv6_address * address) +{ + cprintf(str, "%x:%x:%x:%x:%x:%x:%x:%x", + cat_print_iPv6_ADD(address->Addr[0], address->Addr[1]), + cat_print_iPv6_ADD(address->Addr[2], address->Addr[3]), + cat_print_iPv6_ADD(address->Addr[4], address->Addr[5]), + cat_print_iPv6_ADD(address->Addr[6], address->Addr[7]), + cat_print_iPv6_ADD(address->Addr[8], address->Addr[9]), + cat_print_iPv6_ADD(address->Addr[10], address->Addr[11]), + cat_print_iPv6_ADD(address->Addr[12], address->Addr[13]), + cat_print_iPv6_ADD(address->Addr[14], address->Addr[15])); +} + +static void +dev_path_iPv6(struct string *str, void *dev_path) +{ + struct ipv6_device_path *ip; + + ip = dev_path; + cprintf(str, "IPv6("); + cat_print_ipv6(str, &ip->remote_ip_address); + cprintf(str, ","); + cat_print_network_protocol(str, ip->Protocol); + cprintf(str, ",%s,", ip->IPAddress_origin ? + (ip->IPAddress_origin == 1 ? "stateless_auto_configure" : + "stateful_auto_configure") : "Static"); + cat_print_ipv6(str, &ip->local_ip_address); + if (ip->header.length == + sizeof (struct ipv6_device_path)) { + cprintf(str, ","); + cat_print_ipv6(str, &ip->gateway_ip_address); + cprintf(str, ","); + cprintf(str, "%d", ip->prefix_length); + } + cprintf(str, ")"); +} + +static void +dev_path_infini_band(struct string *str, void *dev_path) +{ + struct infiniband_device_path *infini_band; + + infini_band = dev_path; + cprintf(str, "Infiniband(0x%x,%pU,0x%llx,0x%llx,0x%llx)", + infini_band->resource_flags, &infini_band->port_gid, + infini_band->service_id, infini_band->target_port_id, + infini_band->device_id); +} + +static void +dev_path_uart(struct string *str, void *dev_path) +{ + struct uart_device_path *Uart; + s8 Parity; + + Uart = dev_path; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + case 1: + Parity = 'N'; + break; + case 2: + Parity = 'E'; + break; + case 3: + Parity = 'O'; + break; + case 4: + Parity = 'M'; + break; + case 5: + Parity = 'S'; + break; + default: + Parity = 'x'; + break; + } + + if (Uart->baud_rate == 0) + cprintf(str, "Uart(DEFAULT %c", Parity); + else + cprintf(str, "Uart(%lld %c", Uart->baud_rate, Parity); + + if (Uart->data_bits == 0) + cprintf(str, "D"); + else + cprintf(str, "%d", Uart->data_bits); + + switch (Uart->stop_bits) { + case 0: + cprintf(str, "D)"); + break; + case 1: + cprintf(str, "1)"); + break; + case 2: + cprintf(str, "1.5)"); + break; + case 3: + cprintf(str, "2)"); + break; + default: + cprintf(str, "x)"); + break; + } +} + +static void +dev_path_sata(struct string *str, void *dev_path) +{ + struct sata_device_path *sata; + + sata = dev_path; + cprintf(str, "Sata(0x%x,0x%x,0x%x)", sata->HBAPort_number, + sata->port_multiplier_port_number, sata->Lun); +} + +static void +dev_path_hard_drive(struct string *str, void *dev_path) +{ + struct harddrive_device_path *hd; + + hd = dev_path; + switch (hd->signature_type) { + case SIGNATURE_TYPE_MBR: + cprintf(str, "HD(Part%d,Sig%08x)", + hd->partition_number, *((u32 *) (&(hd->signature[0]))) + ); + break; + case SIGNATURE_TYPE_GUID: + cprintf(str, "HD(Part%d,Sig%pU)", + hd->partition_number, + (efi_guid_t *) & (hd->signature[0]) + ); + break; + default: + cprintf(str, "HD(Part%d,mbr_type=%02x,sig_type=%02x)", + hd->partition_number, hd->mbr_type, hd->signature_type); + break; + } +} + +static void +dev_path_cdrom(struct string *str, void *dev_path) +{ + struct cdrom_device_path *cd; + + cd = dev_path; + cprintf(str, "CDROM(0x%x)", cd->boot_entry); +} + +static void +dev_path_file_path(struct string *str, void *dev_path) +{ + struct filepath_device_path *Fp; + char *dst; + + Fp = dev_path; + + dst = strdup_wchar_to_char(Fp->path_name); + + cprintf(str, "%s", dst); + + free(dst); +} + +static void +dev_path_media_protocol(struct string *str, void *dev_path) +{ + struct media_protocol_device_path *media_prot; + + media_prot = dev_path; + cprintf(str, "%pU", &media_prot->Protocol); +} + +static void +dev_path_bss_bss(struct string *str, void *dev_path) +{ + struct bbs_bbs_device_path *Bss; + char *type; + + Bss = dev_path; + switch (Bss->device_type) { + case BBS_TYPE_FLOPPY: + type = "Floppy"; + break; + case BBS_TYPE_HARDDRIVE: + type = "Harddrive"; + break; + case BBS_TYPE_CDROM: + type = "CDROM"; + break; + case BBS_TYPE_PCMCIA: + type = "PCMCIA"; + break; + case BBS_TYPE_USB: + type = "Usb"; + break; + case BBS_TYPE_EMBEDDED_NETWORK: + type = "Net"; + break; + default: + type = "?"; + break; + } + + cprintf(str, "Bss-%s(%s)", type, Bss->String); +} + +static void +dev_path_end_instance(struct string *str, void *dev_path) +{ + cprintf(str, ","); +} + +/** + * Print unknown device node. + * UEFI 2.4 § 9.6.1.6 table 89. + */ + +static void +dev_path_node_unknown(struct string *str, void *dev_path) +{ + struct efi_device_path *Path; + u8 *value; + int length, index; + Path = dev_path; + value = dev_path; + value += 4; + switch (Path->type) { + case HARDWARE_DEVICE_PATH:{ + /* Unknown Hardware Device Path */ + cprintf(str, "hardware_path(%d", Path->sub_type); + break; + } + case ACPI_DEVICE_PATH:{/* Unknown ACPI Device Path */ + cprintf(str, "acpi_path(%d", Path->sub_type); + break; + } + case MESSAGING_DEVICE_PATH:{ + /* Unknown Messaging Device Path */ + cprintf(str, "Msg(%d", Path->sub_type); + break; + } + case MEDIA_DEVICE_PATH:{ + /* Unknown Media Device Path */ + cprintf(str, "media_path(%d", Path->sub_type); + break; + } + case BBS_DEVICE_PATH:{ /* Unknown BIOS Boot Specification Device Path */ + cprintf(str, "bbs_path(%d", Path->sub_type); + break; + } + default:{ /* Unknown Device Path */ + cprintf(str, "Path(%d,%d", Path->type, Path->sub_type); + break; + } + } + length = Path->length; + for (index = 0; index < length; index++) { + if (index == 0) + cprintf(str, ",0x"); + cprintf(str, "%02x", *value); + value++; + } + cprintf(str, ")"); +} + +/* + * Table to convert "type" and "sub_type" to a "convert to text" function/ + * Entries hold "type" and "sub_type" for know values. + * Special "sub_type" 0 is used as default for known type with unknown subtype. + */ +struct { + u8 type; + u8 sub_type; + void (*Function) (struct string *, void *); +} dev_path_table[] = { + { + HARDWARE_DEVICE_PATH, HW_PCI_DP, dev_path_pci}, { + HARDWARE_DEVICE_PATH, HW_PCCARD_DP, dev_path_pccard}, { + HARDWARE_DEVICE_PATH, HW_MEMMAP_DP, dev_path_mem_map}, { + HARDWARE_DEVICE_PATH, HW_VENDOR_DP, dev_path_vendor}, { + HARDWARE_DEVICE_PATH, HW_CONTROLLER_DP, dev_path_controller}, { + ACPI_DEVICE_PATH, ACPI_DP, dev_path_acpi}, { + MESSAGING_DEVICE_PATH, MSG_ATAPI_DP, dev_path_atapi}, { + MESSAGING_DEVICE_PATH, MSG_SCSI_DP, dev_path_scsi}, { + MESSAGING_DEVICE_PATH, MSG_FIBRECHANNEL_DP, dev_path_fibre}, { + MESSAGING_DEVICE_PATH, MSG_1394_DP, dev_path1394}, { + MESSAGING_DEVICE_PATH, MSG_USB_DP, dev_path_usb}, { + MESSAGING_DEVICE_PATH, MSG_I2_o_DP, dev_path_i2_o}, { + MESSAGING_DEVICE_PATH, MSG_MAC_ADDR_DP, dev_path_mac_addr}, { + MESSAGING_DEVICE_PATH, MSG_IPv4_DP, dev_path_iPv4}, { + MESSAGING_DEVICE_PATH, MSG_IPv6_DP, dev_path_iPv6}, { + MESSAGING_DEVICE_PATH, MSG_INFINIBAND_DP, dev_path_infini_band}, { + MESSAGING_DEVICE_PATH, MSG_UART_DP, dev_path_uart}, { + MESSAGING_DEVICE_PATH, MSG_SATA_DP, dev_path_sata}, { + MESSAGING_DEVICE_PATH, MSG_VENDOR_DP, dev_path_vendor}, { + MEDIA_DEVICE_PATH, MEDIA_HARDDRIVE_DP, dev_path_hard_drive}, { + MEDIA_DEVICE_PATH, MEDIA_CDROM_DP, dev_path_cdrom}, { + MEDIA_DEVICE_PATH, MEDIA_VENDOR_DP, dev_path_vendor}, { + MEDIA_DEVICE_PATH, MEDIA_FILEPATH_DP, dev_path_file_path}, { + MEDIA_DEVICE_PATH, MEDIA_PROTOCOL_DP, dev_path_media_protocol}, { + BBS_DEVICE_PATH, BBS_BBS_DP, dev_path_bss_bss}, { + END_DEVICE_PATH_TYPE, END_INSTANCE_DEVICE_PATH_SUBTYPE, + dev_path_end_instance}, { + 0, 0, NULL} +}; + +static int __device_path_to_str(struct string *str, struct efi_device_path *dev_path) +{ + struct efi_device_path *dev_path_node; + void (*dump_node) (struct string *, void *); + int i; + + dev_path = unpack_device_path(dev_path); + + dev_path_node = dev_path; + while (!is_device_path_end(dev_path_node)) { + dump_node = NULL; + for (i = 0; dev_path_table[i].Function; i += 1) { + + if (device_path_type(dev_path_node) == + dev_path_table[i].type + && dev_path_node->sub_type == + dev_path_table[i].sub_type) { + dump_node = dev_path_table[i].Function; + break; + } + } + + if (!dump_node) + dump_node = dev_path_node_unknown; + + if (str->len && dump_node != dev_path_end_instance) + cprintf(str, "/"); + + dump_node(str, dev_path_node); + + dev_path_node = next_device_path_node(dev_path_node); + } + + return 0; +} + +char *device_path_to_str(struct efi_device_path *dev_path) +{ + struct string str = {}; + + __device_path_to_str(&str, dev_path); + + str.str = malloc(str.len + 1); + if (!str.str) + return NULL; + + str.len = 0; + + __device_path_to_str(&str, dev_path); + + return str.str; +} diff --git a/common/efi-guid.c b/common/efi-guid.c new file mode 100644 index 0000000000..f6b0404105 --- /dev/null +++ b/common/efi-guid.c @@ -0,0 +1,84 @@ +#include <common.h> +#include <efi.h> + +efi_guid_t efi_file_info_id = EFI_FILE_INFO_GUID; +efi_guid_t efi_simple_file_system_protocol_guid = EFI_SIMPLE_FILE_SYSTEM_GUID; +efi_guid_t efi_device_path_protocol_guid = EFI_DEVICE_PATH_PROTOCOL_GUID; +efi_guid_t efi_loaded_image_protocol_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; +efi_guid_t efi_unknown_device_guid = EFI_UNKNOWN_DEVICE_GUID; +efi_guid_t efi_null_guid = EFI_NULL_GUID; +efi_guid_t efi_global_variable_guid = EFI_GLOBAL_VARIABLE_GUID; +efi_guid_t efi_block_io_protocol_guid = EFI_BLOCK_IO_PROTOCOL_GUID; + +#define EFI_GUID_STRING(guid, short, long) do { \ + if (!efi_guidcmp(guid, *g)) \ + return long; \ + } while(0) + +const char *efi_guid_string(efi_guid_t *g) +{ + EFI_GUID_STRING(EFI_NULL_GUID, "NULL", "NULL GUID"); + EFI_GUID_STRING(EFI_MPS_TABLE_GUID, "MPS Table", "MPS Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_ACPI_TABLE_GUID, "ACPI Table", "ACPI 1.0 Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_ACPI_20_TABLE_GUID, "ACPI 2.0 Table", "ACPI 2.0 Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_SMBIOS_TABLE_GUID, "SMBIOS Table", "SMBIOS Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_SAL_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_HCDP_TABLE_GUID, "HDCP Table", "HDCP Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol"); + EFI_GUID_STRING(EFI_GLOBAL_VARIABLE_GUID, "Efi", "Efi Variable GUID"); + EFI_GUID_STRING(EFI_UV_SYSTEM_TABLE_GUID, "SAL System Table", "SAL System Table GUID in EFI System Table"); + EFI_GUID_STRING(EFI_LINUX_EFI_CRASH_GUID, "Linux EFI Crash", "Linux EFI Crash GUID"); + EFI_GUID_STRING(EFI_LOADED_IMAGE_PROTOCOL_GUID, "LoadedImage Protocol", "EFI 1.0 Loaded Image Protocol"); + EFI_GUID_STRING(EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID, "EFI Graphics Output Protocol", "UEFI Graphics Output Protocol"); + EFI_GUID_STRING(EFI_UGA_PROTOCOL_GUID, "UGA Draw Protocol", "EFI 1.1 UGA Draw Protocol"); + EFI_GUID_STRING(EFI_UGA_IO_PROTOCOL_GUID, "UGA Protocol", "EFI 1.1 UGA Protocol"); + EFI_GUID_STRING(EFI_PCI_IO_PROTOCOL_GUID, "PCI IO Protocol", "EFI 1.1 PCI IO Protocol"); + EFI_GUID_STRING(EFI_FILE_INFO_GUID, "File Info", "EFI File Infom"); + EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_GUID, "Filesystem", "EFI 1.0 Simple FileSystem"); + EFI_GUID_STRING(EFI_DEVICE_TREE_GUID, "Device Tree", "EFI Device Tree GUID"); + EFI_GUID_STRING(EFI_DEVICE_PATH_PROTOCOL_GUID, "Device Path Protocol", "EFI 1.0 Device Path protocol"); + EFI_GUID_STRING(EFI_SIMPLE_NETWORK_PROTOCOL_GUID, "Simple Network Protocol", "EFI 1.0 Simple Network Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, "Filesystem Protocol", "EFI 1.0 Simple FileSystem Protocol"); + EFI_GUID_STRING(EFI_UNKNOWN_DEVICE_GUID, "Efi Unknown Device", "Efi Unknown Device GUID"); + EFI_GUID_STRING(EFI_BLOCK_IO_PROTOCOL_GUID, "BlockIo Protocol", "EFI 1.0 Block IO protocol"); + + EFI_GUID_STRING(EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID, "FirmwareVolume2Protocol", "Efi FirmwareVolume2Protocol"); + EFI_GUID_STRING(EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID, "FirmwareVolumeBlock Protocol", "Firmware Volume Block protocol"); + EFI_GUID_STRING(EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID, "PciRootBridgeIo Protocol", "EFI 1.1 Pci Root Bridge IO Protocol"); + EFI_GUID_STRING(EFI_ISA_ACPI_PROTOCOL_GUID, "ISA Acpi Protocol", "ISA Acpi Protocol"); + EFI_GUID_STRING(EFI_ISA_IO_PROTOCOL_GUID, "ISA IO Protocol", "ISA IO Protocol"); + EFI_GUID_STRING(EFI_STANDARD_ERROR_DEVICE_GUID, "Standard Error Device Guid", "EFI Standard Error Device Guid"); + EFI_GUID_STRING(EFI_CONSOLE_OUT_DEVICE_GUID, "Console Out Device Guid", "EFI Console Out Device Guid"); + EFI_GUID_STRING(EFI_CONSOLE_IN_DEVICE_GUID, "Console In Device Guid", "EFI Conosle In Device Guid"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID, "Simple Text Out Protocol", "EFI 1.0 Simple Text Out Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID, "Simple Text Input Ex Protocol", "UEFI 2.1 Simple Text Input Ex Protocol"); + EFI_GUID_STRING(EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID, "Simple Text In Protocol", "EFI 1.0 Simple Text In Protocol"); + EFI_GUID_STRING(EFI_DISK_IO_PROTOCOL_GUID, "DiskIo Protocol", "EFI 1.0 Disk IO Protocol"); + EFI_GUID_STRING(EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID, "IDE Controller Init Protocol", "Platform IDE Init Protocol"); + EFI_GUID_STRING(EFI_DISK_INFO_PROTOCOL_GUID, "Disk Info Protocol", "Disk Info Protocol"); + EFI_GUID_STRING(EFI_SERIAL_IO_PROTOCOL_GUID, "SerialIo Protocol", "EFI 1.0 Serial IO Protocol"); + EFI_GUID_STRING(EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID, "Bus Specific Driver Override Protocol", "EFI 1.1 Bus Specific Driver Override Protocol"); + EFI_GUID_STRING(EFI_LOAD_FILE2_PROTOCOL_GUID, "LoadFile2 Protocol", "EFI Load File 2 Protocol"); + EFI_GUID_STRING(EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID, "MTFTP4 Service Binding Protocol", "MTFTP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_DHCP4_PROTOCOL_GUID, "DHCP4 Protocol", "DHCP4 Protocol"); + EFI_GUID_STRING(EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID, "UDP4 Service Binding Protocol", "UDP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID, "TCP4 Service Binding Protocol", "TCP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID, "IP4 Service Binding Protocol", "IP4 Service Binding Protocol"); + EFI_GUID_STRING(EFI_IP4_CONFIG_PROTOCOL_GUID, "Ip4Config Protocol", "Ip4Config Protocol"); + EFI_GUID_STRING(EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID, "ARP Service Binding Protocol", "ARP Service Binding Protocol"); + EFI_GUID_STRING(EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID, "Managed Network Service Binding Protocol", "Managed Network Service Binding Protocol"); + EFI_GUID_STRING(EFI_VLAN_CONFIG_PROTOCOL_GUID, "VlanConfig Protocol", "VlanConfig Protocol"); + EFI_GUID_STRING(EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID, "HII Config Access Protocol", "HII Config Access 2.1 protocol"); + EFI_GUID_STRING(LOAD_FILE_PROTOCOL_GUID, "LoadFile Protocol", "EFI 1.0 Load File Protocol"); + EFI_GUID_STRING(EFI_COMPONENT_NAME2_PROTOCOL_GUID, "Component Name2 Protocol", "UEFI 2.0 Component Name2 Protocol"); + EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31, "Network Interface Identifier Protocol_31", "EFI1.1 Network Interface Identifier Protocol"); + EFI_GUID_STRING(EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID, "Network Interface Identifier Protocol", "EFI Network Interface Identifier Protocol"); + + /* File */ + EFI_GUID_STRING(EFI_IDEBUSDXE_INF_GUID, "IdeBusDxe.inf", "EFI IdeBusDxe.inf File GUID"); + EFI_GUID_STRING(EFI_TERMINALDXE_INF_GUID, "TerminalDxe.inf", "EFI TerminalDxe.inf File GUID"); + EFI_GUID_STRING(EFI_ISCSIDXE_INF_GUID, "IScsiDxe.inf", "EFI IScsiDxe.inf File GUID"); + EFI_GUID_STRING(EFI_VLANCONFIGDXE_INF_GUID, "VlanConfigDxe.inf", "EFI VlanConfigDxe.inf File GUID"); + + return "unknown"; +} diff --git a/common/environment.c b/common/environment.c index 2d1edf8381..e55c7b7417 100644 --- a/common/environment.c +++ b/common/environment.c @@ -167,12 +167,13 @@ out: * Make the current environment persistent * @param[in] filename where to store * @param[in] dirname what to store (all files in this dir) + * @param[in] flags superblock flags (refer ENVFS_FLAGS_* macros) * @return 0 on success, anything else in case of failure * * Note: This function will also be used on the host! See note in the header * of this file. */ -int envfs_save(const char *filename, const char *dirname) +int envfs_save(const char *filename, const char *dirname, unsigned flags) { struct envfs_super *super; int envfd, size, ret; @@ -182,11 +183,15 @@ int envfs_save(const char *filename, const char *dirname) data.writep = NULL; data.base = dirname; - /* first pass: calculate size */ - recursive_action(dirname, ACTION_RECURSE, file_size_action, - NULL, &data, 0); + if (flags & ENVFS_FLAGS_FORCE_BUILT_IN) { + size = 0; /* force no content */ + } else { + /* first pass: calculate size */ + recursive_action(dirname, ACTION_RECURSE, file_size_action, + NULL, &data, 0); - size = (unsigned long)data.writep; + size = (unsigned long)data.writep; + } buf = xzalloc(size + sizeof(struct envfs_super)); data.writep = buf + sizeof(struct envfs_super); @@ -196,10 +201,13 @@ int envfs_save(const char *filename, const char *dirname) super->major = ENVFS_MAJOR; super->minor = ENVFS_MINOR; super->size = ENVFS_32(size); + super->flags = ENVFS_32(flags); - /* second pass: copy files to buffer */ - recursive_action(dirname, ACTION_RECURSE, file_save_action, - NULL, &data, 0); + if (!(flags & ENVFS_FLAGS_FORCE_BUILT_IN)) { + /* second pass: copy files to buffer */ + recursive_action(dirname, ACTION_RECURSE, file_save_action, + NULL, &data, 0); + } super->crc = ENVFS_32(crc32(0, buf + sizeof(struct envfs_super), size)); super->sb_crc = ENVFS_32(crc32(0, buf, sizeof(struct envfs_super) - 4)); @@ -447,6 +455,15 @@ int envfs_load(const char *filename, const char *dir, unsigned flags) if (ret) goto out; + if (super.flags & ENVFS_FLAGS_FORCE_BUILT_IN) { + printf("found force-builtin environment, using defaultenv\n"); + ret = defaultenv_load(dir, 0); + if (ret) + printf("failed to load default environment: %s\n", + strerror(-ret)); + goto out; + } + buf = xmalloc(size); rbuf = buf; diff --git a/common/filetype.c b/common/filetype.c index 508a2b56bf..c8f3582cd1 100644 --- a/common/filetype.c +++ b/common/filetype.c @@ -51,8 +51,13 @@ static const struct filetype_str filetype_str[] = { [filetype_png] = { "PNG image", "png" }, [filetype_ext] = { "EXT filesystem", "ext" }, [filetype_gpt] = { "GUID Partition Table", "gpt" }, + [filetype_ubifs] = { "UBIFS image", "ubifs" }, [filetype_bpk] = { "Binary PacKage", "bpk" }, [filetype_barebox_env] = { "barebox environment file", "bbenv" }, + [filetype_ch_image] = { "TI OMAP CH boot image", "ch-image" }, + [filetype_ch_image_be] = { + "TI OMAP CH boot image (big endian)", "ch-image-be" }, + [filetype_exe] = { "MS-DOS executable", "exe" }, }; const char *file_type_to_string(enum filetype f) @@ -177,6 +182,8 @@ enum filetype file_detect_partition_table(const void *_buf, size_t bufsize) return filetype_unknown; } +#define CH_TOC_section_name 0x14 + enum filetype file_detect_type(const void *_buf, size_t bufsize) { const u32 *buf = _buf; @@ -231,6 +238,9 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) if (bufsize < 64) return filetype_unknown; + if (buf8[0] == 'M' && buf8[1] == 'Z') + return filetype_exe; + if (is_barebox_arm_head(_buf)) return filetype_arm_barebox; if (buf[9] == 0x016f2818 || buf[9] == 0x18286f01) @@ -246,6 +256,13 @@ enum filetype file_detect_type(const void *_buf, size_t bufsize) if (bufsize >= 1536 && buf16[512 + 28] == le16_to_cpu(0xef53)) return filetype_ext; + if (strncmp(buf8 + CH_TOC_section_name, "CHSETTINGS", 10) == 0) + return filetype_ch_image; + + if (buf[5] == 0x43485345 && buf[6] == 0x5454494E && + buf[7] == 0x47530000) + return filetype_ch_image_be; + return filetype_unknown; } diff --git a/common/hush.c b/common/hush.c index f6aaa03514..b23b3f6633 100644 --- a/common/hush.c +++ b/common/hush.c @@ -118,6 +118,7 @@ #include <libbb.h> #include <glob.h> #include <getopt.h> +#include <libfile.h> #include <libbb.h> #include <magicvar.h> #include <linux/list.h> diff --git a/common/imd-barebox.c b/common/imd-barebox.c new file mode 100644 index 0000000000..e9cd37d83e --- /dev/null +++ b/common/imd-barebox.c @@ -0,0 +1,25 @@ +#include <common.h> +#include <image-metadata.h> +#include <generated/compile.h> +#include <generated/utsrelease.h> + +/* + * Mark a imd entry as used so that the linker cannot + * throw it away. + */ +void imd_used(const void *used) +{ +} + +struct imd_header imd_start_header +__BAREBOX_IMD_SECTION(.barebox_imd_start) = { + .type = cpu_to_le32(IMD_TYPE_START), +}; + +struct imd_header imd_end_header +__BAREBOX_IMD_SECTION(.barebox_imd_end) = { + .type = cpu_to_le32(IMD_TYPE_END), +}; + +BAREBOX_IMD_TAG_STRING(imd_build_tag, IMD_TYPE_BUILD, UTS_VERSION, 1); +BAREBOX_IMD_TAG_STRING(imd_release_tag, IMD_TYPE_RELEASE, UTS_RELEASE, 1); diff --git a/common/imd.c b/common/imd.c new file mode 100644 index 0000000000..2c837d6f25 --- /dev/null +++ b/common/imd.c @@ -0,0 +1,322 @@ +/* + * (C) Copyright 2014 Sascha Hauer, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#ifdef __BAREBOX__ +#include <common.h> +#include <image-metadata.h> +#include <libfile.h> +#include <getopt.h> +#include <malloc.h> +#include <fs.h> +#endif + +/* + * imd_next - return a pointer to the next metadata field. + * @imd The current metadata field + */ +struct imd_header *imd_next(struct imd_header *imd) +{ + int length; + + length = imd_read_length(imd); + length = ALIGN(length, 4); + length += 8; + + return (void *)imd + length; +} + +struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type) +{ + imd_for_each(imd, imd) + if (imd_read_type(imd) == type) + return imd; + + return NULL; +} + +static int imd_next_validate(void *buf, int bufsize, int start_ofs) +{ + int length, size; + struct imd_header *imd = buf + start_ofs; + + size = bufsize - start_ofs; + + if (size < 8) { + debug("trunkated tag at offset %dd\n", start_ofs); + return -EINVAL; + } + + length = imd_read_length(imd); + length = ALIGN(length, 4); + length += 8; + + if (size < length) { + debug("tag at offset %d with size %d exceeds bufsize %d\n", + start_ofs, size, bufsize); + return -EINVAL; + } + + debug("tag at offset %d has length %d\n", start_ofs, length); + + return length; +} + +static int imd_validate_tags(void *buf, int bufsize, int start_ofs) +{ + int ret; + struct imd_header *imd = buf + start_ofs; + + while (1) { + uint32_t type; + + ret = imd_next_validate(buf, bufsize, start_ofs); + if (ret < 0) { + debug("Invalid tag at offset %d\n", start_ofs); + return -EINVAL; + } + + imd = (void *)imd + ret; + start_ofs += ret; + + type = imd_read_type(imd); + + if (!imd_type_valid(type)) { + debug("Invalid: tag: 0x%08x\n", type); + return -EINVAL; + } + + if (type == IMD_TYPE_END) + return 0; + } +} + +/* + * imd_search_validate - find valid metadata in a buffer + * @buf the buffer + * @size buffer size + * @start The returned pointer to the metadata + * + * This iterates over a buffer and searches for metadata. The metadata + * is checked for consistency (length fields not exceeding buffer and + * presence of end header) and returned in @start. The returned pointer + * is only valid when 0 is returned. The returned data may be unaligned. + */ +static int imd_search_validate(void *buf, int size, struct imd_header **start) +{ + int start_ofs = 0; + int i, ret; + + for (i = start_ofs; i < size - 32; i++) { + uint32_t type; + + type = imd_read_le32(buf + i); + + if (type != IMD_TYPE_START) + continue; + + debug("Start tag found at offset %d\n", i); + + ret = imd_validate_tags(buf, size, i); + if (!ret) { + *start = buf + i; + return 0; + } + } + + return -EINVAL; +} + +struct imd_type_names { + uint32_t type; + const char *name; +}; + +static struct imd_type_names imd_types[] = { + { + .type = IMD_TYPE_RELEASE, + .name = "release", + }, { + .type = IMD_TYPE_BUILD, + .name = "build", + }, { + .type = IMD_TYPE_MODEL, + .name = "model", + }, { + .type = IMD_TYPE_PARAMETER, + .name = "parameter", + }, { + .type = IMD_TYPE_OF_COMPATIBLE, + .name = "of_compatible", + }, +}; + +static const char *imd_type_to_name(uint32_t type) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imd_types); i++) + if (imd_types[i].type == type) + return imd_types[i].name; + + return "unknown"; +} + +static uint32_t imd_name_to_type(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(imd_types); i++) + if (!strcmp(imd_types[i].name, name)) + return imd_types[i].type; + + return IMD_TYPE_INVALID; +} + +static char *imd_string_data(struct imd_entry_string *imd_string, int index) +{ + int i, total = 0, l = 0; + int len = imd_read_length(&imd_string->header); + char *p = imd_string->data; + + for (i = 0; total < len; total += l, p += l) { + l = strlen(p) + 1; + if (i++ == index) + return p; + } + + return NULL; +} + +static char *imd_concat_strings(struct imd_entry_string *imd_string) +{ + int i, len = imd_read_length(&imd_string->header); + char *str; + + str = malloc(len); + if (!str) + return NULL; + + memcpy(str, imd_string->data, len); + + for (i = 0; i < len - 1; i++) + if (str[i] == 0) + str[i] = ' '; + + return str; +} + +int imd_command_verbose; + +int imd_command(int argc, char *argv[]) +{ + int ret, opt, strno = -1; + void *buf; + size_t size; + uint32_t type = IMD_TYPE_INVALID; + struct imd_header *imd_start, *imd; + const char *filename; + const char *variable_name = NULL; + char *str; + + imd_command_verbose = 0; + + while ((opt = getopt(argc, argv, "vt:s:n:")) > 0) { + switch(opt) { + case 't': + type = imd_name_to_type(optarg); + if (type == IMD_TYPE_INVALID) { + fprintf(stderr, "no such type: %s\n", optarg); + return -ENOSYS; + } + break; + case 's': + variable_name = optarg; + break; + case 'v': + imd_command_verbose = 1; + break; + case 'n': + strno = simple_strtoul(optarg, NULL, 0); + break; + default: + return -ENOSYS; + } + } + + if (optind == argc) { + fprintf(stderr, "No image given\n"); + return -ENOSYS; + } + + filename = argv[optind]; + + ret = read_file_2(filename, &size, &buf, 0x100000); + if (ret && ret != -EFBIG) + return -errno; + + ret = imd_search_validate(buf, size, &imd_start); + if (ret) + return ret; + + if (type == IMD_TYPE_INVALID) { + imd_for_each(imd_start, imd) { + uint32_t type = imd_read_type(imd); + + if (imd_is_string(type)) { + struct imd_entry_string *imd_string = + (struct imd_entry_string *)imd; + + str = imd_concat_strings(imd_string); + + printf("%s: %s\n", imd_type_to_name(type), str); + } else { + debug("Unknown tag 0x%08x\n", type); + } + } + } else { + imd = imd_find_type(imd_start, type); + if (!imd) { + debug("No tag of type 0x%08x found\n", type); + return -ENODATA; + } + + if (imd_is_string(type)) { + struct imd_entry_string *imd_string = + (struct imd_entry_string *)imd; + + if (strno >= 0) + str = imd_string_data(imd_string, strno); + else + str = imd_concat_strings(imd_string); + + if (!str) + return -ENODATA; + + if (variable_name) + imd_command_setenv(variable_name, str); + else + printf("%s\n", str); + + if (strno < 0) + free(str); + } else { + printf("tag 0x%08x present\n", type); + } + } + + return 0; +} diff --git a/common/memory.c b/common/memory.c index 7dbd7f4399..4a8fe283f2 100644 --- a/common/memory.c +++ b/common/memory.c @@ -58,7 +58,7 @@ void mem_malloc_init(void *start, void *end) #endif } -#ifndef __SANDBOX__ +#if !defined __SANDBOX__ && !defined CONFIG_ARCH_EFI static int mem_malloc_resource(void) { /* diff --git a/common/menutree.c b/common/menutree.c index 814512d7b7..97e628de88 100644 --- a/common/menutree.c +++ b/common/menutree.c @@ -15,6 +15,7 @@ #include <glob.h> #include <menu.h> #include <fs.h> +#include <libfile.h> #include <linux/stat.h> diff --git a/common/partitions/efi.c b/common/partitions/efi.c index ee1326e622..dcb95414f6 100644 --- a/common/partitions/efi.c +++ b/common/partitions/efi.c @@ -232,7 +232,7 @@ static int is_gpt_valid(struct block_device *blk, u64 lba, static inline int is_pte_valid(const gpt_entry *pte, const u64 lastlba) { - if ((!efi_guidcmp(pte->partition_type_guid, NULL_GUID)) || + if ((!efi_guidcmp(pte->partition_type_guid, EFI_NULL_GUID)) || le64_to_cpu(pte->starting_lba) > lastlba || le64_to_cpu(pte->ending_lba) > lastlba) return 0; diff --git a/common/partitions/efi.h b/common/partitions/efi.h index 703ecca2f2..a9b10c1266 100644 --- a/common/partitions/efi.h +++ b/common/partitions/efi.h @@ -21,7 +21,7 @@ #ifndef FS_PART_EFI_H_INCLUDED #define FS_PART_EFI_H_INCLUDED -#include <linux/efi.h> +#include <efi.h> #define MSDOS_MBR_SIGNATURE 0xaa55 #define EFI_PMBR_OSTYPE_EFI 0xEF diff --git a/common/uimage.c b/common/uimage.c index 4ef09682c1..a7011a7623 100644 --- a/common/uimage.c +++ b/common/uimage.c @@ -22,6 +22,7 @@ #include <malloc.h> #include <errno.h> #include <libbb.h> +#include <libfile.h> #include <uncompress.h> #include <fcntl.h> #include <fs.h> diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index 11e3777a60..b7f78367d4 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -53,6 +53,7 @@ #include <common.h> #include <init.h> #include <io.h> +#include <malloc.h> #include <of.h> #include <of_address.h> #include <linux/mbus.h> @@ -187,7 +188,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, phys_addr_t base, size_t size, u8 target, u8 attr) { - u64 end = (u64)base + size; + u64 end = (u64)base + size - 1; int win; for (win = 0; win < mbus->soc->num_wins; win++) { @@ -203,7 +204,7 @@ static int mvebu_mbus_window_conflicts(struct mvebu_mbus_state *mbus, if (!enabled) continue; - wend = wbase + wsize; + wend = wbase + wsize - 1; /* * Check if the current window overlaps with the @@ -546,7 +547,7 @@ void mvebu_mbus_get_pcie_io_aperture(struct resource *res) * - bits 16 to 23: window attribute ID * - bits 0 to 15: unused */ -#define CUSTOM(id) (((id) & 0xF0000000) >> 24) +#define CUSTOM(id) (((id) & 0xF0000000) >> 28) #define TARGET(id) (((id) & 0x0F000000) >> 24) #define ATTR(id) (((id) & 0x00FF0000) >> 16) @@ -661,7 +662,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np, reg, ARRAY_SIZE(reg)); if (!ret) { mem->start = reg[0]; - mem->end = mem->start + reg[1]; + mem->end = mem->start + reg[1] - 1; mem->flags = IORESOURCE_MEM; } @@ -669,7 +670,7 @@ static void mvebu_mbus_get_pcie_resources(struct device_node *np, reg, ARRAY_SIZE(reg)); if (!ret) { io->start = reg[0]; - io->end = io->start + reg[1]; + io->end = io->start + reg[1] - 1; io->flags = IORESOURCE_IO; } } @@ -741,3 +742,89 @@ static int mvebu_mbus_init(void) return platform_driver_register(&mvebu_mbus_driver); } postcore_initcall(mvebu_mbus_init); + +struct mbus_range { + u32 mbusid; + u32 remap; + struct list_head list; +}; + +#define MBUS_ID(t,a) (((t) << 24) | ((attr) << 16)) +static LIST_HEAD(mbus_ranges); + +void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap) +{ + struct mbus_range *r = xzalloc(sizeof(*r)); + + r->mbusid = MBUS_ID(target, attr); + r->remap = remap; + list_add_tail(&r->list, &mbus_ranges); +} + +/* + * Barebox always remaps internal registers to 0xf1000000 on every SoC. + * As we (and Linux) need a working DT and there is no way to tell the current + * remap address, fixup any provided DT to ensure custom MBUS_IDs are correct. + */ +static int mvebu_mbus_of_fixup(struct device_node *root, void *context) +{ + struct device_node *np; + + for_each_matching_node(np, mvebu_mbus_dt_ids) { + struct property *p; + int n, pa, na, ns, lenp, size; + u32 *ranges; + + p = of_find_property(np, "ranges", &lenp); + if (!p) + return -EINVAL; + + pa = of_n_addr_cells(np); + if (of_property_read_u32(np, "#address-cells", &na) || + of_property_read_u32(np, "#size-cells", &ns)) + return -EINVAL; + + size = pa + na + ns; + ranges = xzalloc(lenp); + of_property_read_u32_array(np, "ranges", ranges, lenp/4); + + /* + * Iterate through each ranges tuple and fixup the custom + * window ranges low base address. Because Armada XP supports + * LPAE, it has 2 cells for the parent address: + * <windowid child_base high_base low_base size> + * + * whereas for Armada 370, there's just one: + * <windowid child_base base size> + * + * For instance, the following tuple: + * <MBUS_ID(0xf0, 0x01) child_base {0} base 0x100000> + * + * would be fixed-up like: + * <MBUS_ID(0xf0, 0x01) child_base {0} remap 0x100000> + */ + for (n = 0; n < lenp/4; n += size) { + struct mbus_range *r; + u32 mbusid = ranges[n]; + + if (!CUSTOM(mbusid)) + continue; + + list_for_each_entry(r, &mbus_ranges, list) { + if (r->mbusid == mbusid) + ranges[n + na + pa - 1] = r->remap; + } + } + + if (of_property_write_u32_array(np, "ranges", ranges, lenp/4)) + pr_err("Unable to fixup mbus ranges\n"); + free(ranges); + } + + return 0; +} + +static int mvebu_mbus_fixup_register(void) { + return of_register_fixup(mvebu_mbus_of_fixup, NULL); +} +pure_initcall(mvebu_mbus_fixup_register); diff --git a/drivers/bus/omap-gpmc.c b/drivers/bus/omap-gpmc.c index ad21af2903..d7b02cf6ec 100644 --- a/drivers/bus/omap-gpmc.c +++ b/drivers/bus/omap-gpmc.c @@ -382,9 +382,6 @@ static struct dt_eccmode modes[] = { .mode = OMAP_ECC_BCH4_CODE_HW, }, { .name = "bch8", - .mode = OMAP_ECC_BCH8_CODE_HW, - }, { - .name = "bch8-romcode", .mode = OMAP_ECC_BCH8_CODE_HW_ROMCODE, }, }; diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index c1480ceaaf..fc5a389b95 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -14,6 +14,10 @@ config CLOCKSOURCE_CLPS711X bool depends on ARCH_CLPS711X +config CLOCKSOURCE_DIGIC + bool + depends on ARCH_DIGIC + config CLOCKSOURCE_DUMMY bool "Enable dummy software-only clocksource" help diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 97c0288aaa..b80df6b2c9 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_AMBA_SP804) += amba-sp804.o obj-$(CONFIG_ARM_SMP_TWD) += arm_smp_twd.o obj-$(CONFIG_CLOCKSOURCE_BCM2835) += bcm2835.o obj-$(CONFIG_CLOCKSOURCE_CLPS711X) += clps711x.o +obj-$(CONFIG_CLOCKSOURCE_DIGIC) += digic.o obj-$(CONFIG_CLOCKSOURCE_DUMMY) += dummy.o obj-$(CONFIG_CLOCKSOURCE_MVEBU) += mvebu.o obj-$(CONFIG_CLOCKSOURCE_NOMADIK) += nomadik.o diff --git a/drivers/clocksource/digic.c b/drivers/clocksource/digic.c new file mode 100644 index 0000000000..b80ef6f6fa --- /dev/null +++ b/drivers/clocksource/digic.c @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <io.h> +#include <init.h> +#include <clock.h> + +#define DIGIC_TIMER_CLOCK 1000000 + +#define DIGIC_TIMER_CONTROL 0x00 +#define DIGIC_TIMER_VALUE 0x0c + +static void __iomem *timer_base; + +static uint64_t digic_cs_read(void) +{ + return (uint64_t)(0xffff - readl(timer_base + DIGIC_TIMER_VALUE)); +} + +static struct clocksource digic_cs = { + .read = digic_cs_read, + .mask = CLOCKSOURCE_MASK(16), +}; + +static int digic_timer_probe(struct device_d *dev) +{ + /* use only one timer */ + if (timer_base) + return -EBUSY; + + timer_base = dev_request_mem_region(dev, 0); + if (!timer_base) { + dev_err(dev, "could not get memory region\n"); + return -ENODEV; + } + + clocks_calc_mult_shift(&digic_cs.mult, &digic_cs.shift, + DIGIC_TIMER_CLOCK, NSEC_PER_SEC, 1); + + /* disable timer */ + writel(0x80000000, timer_base + DIGIC_TIMER_CONTROL); + + /* magic values... divider? */ + writel(0x00000002, timer_base + 0x04); + writel(0x00000003, timer_base + 0x14); + + /* max counter value */ + writel(0x0000ffff, timer_base + 0x08); + + init_clock(&digic_cs); + + /* enable timer */ + writel(0x00000001, timer_base + DIGIC_TIMER_CONTROL); + /* start timer */ + writel(0x00000001, timer_base + 0x10); + + return 0; +} + +static __maybe_unused struct of_device_id digic_timer_dt_ids[] = { + { + .compatible = "canon,digic-timer", + }, { + /* sentinel */ + } +}; + +static struct driver_d digic_timer_driver = { + .probe = digic_timer_probe, + .name = "digic-timer", + .of_compatible = DRV_OF_COMPAT(digic_timer_dt_ids), +}; + +static int digic_timer_init(void) +{ + return platform_driver_register(&digic_timer_driver); +} +coredevice_initcall(digic_timer_init); diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index f98a9c00ef..0ca7df450a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -9,6 +9,10 @@ menu "GPIO" config GPIO_GENERIC bool +config GPIO_DIGIC + bool "GPIO support for Canon DIGIC" + depends on ARCH_DIGIC + config GPIO_BCM2835 bool "GPIO support for BCM2835" depends on ARCH_BCM2835 @@ -64,6 +68,26 @@ config GPIO_ORION found on Marvell Orion and MVEBU SoCs (Armada 370/XP, Dove, Kirkwood, MV78x00, Orion5x). +config GPIO_PCA953X + bool "PCA95[357]x, PCA9698, TCA64xx, and MAX7310 I/O ports" + depends on I2C + help + Say yes here to provide access to several register-oriented + SMBus I/O expanders, made mostly by NXP or TI. Compatible + models include: + + 4 bits: pca9536, pca9537 + + 8 bits: max7310, max7315, pca6107, pca9534, pca9538, pca9554, + pca9556, pca9557, pca9574, tca6408, xra1202 + + 16 bits: max7312, max7313, pca9535, pca9539, pca9555, pca9575, + tca6416 + + 24 bits: tca6424 + + 40 bits: pca9505, pca9698 + config GPIO_PL061 bool "PrimeCell PL061 GPIO support" depends on ARM_AMBA diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 22d2ac0706..510d146ff5 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -3,12 +3,14 @@ obj-$(CONFIG_GPIOLIB) += gpiolib.o obj-$(CONFIG_GPIO_BCM2835) += gpio-bcm2835.o obj-$(CONFIG_GPIO_DAVINCI) += gpio-davinci.o obj-$(CONFIG_GPIO_CLPS711X) += gpio-clps711x.o +obj-$(CONFIG_GPIO_DIGIC) += gpio-digic.o obj-$(CONFIG_GPIO_GENERIC) += gpio-generic.o obj-$(CONFIG_GPIO_IMX) += gpio-imx.o obj-$(CONFIG_GPIO_JZ4740) += gpio-jz4740.o obj-$(CONFIG_GPIO_MALTA_FPGA_I2C) += gpio-malta-fpga-i2c.o obj-$(CONFIG_GPIO_ORION) += gpio-orion.o obj-$(CONFIG_GPIO_OMAP) += gpio-omap.o +obj-$(CONFIG_GPIO_PCA953X) += gpio-pca953x.o obj-$(CONFIG_GPIO_PL061) += gpio-pl061.o obj-$(CONFIG_GPIO_STMPE) += gpio-stmpe.o obj-$(CONFIG_GPIO_TEGRA) += gpio-tegra.o diff --git a/drivers/gpio/gpio-digic.c b/drivers/gpio/gpio-digic.c new file mode 100644 index 0000000000..468aaa79ab --- /dev/null +++ b/drivers/gpio/gpio-digic.c @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2013 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <malloc.h> +#include <errno.h> +#include <io.h> +#include <gpio.h> +#include <init.h> + +/* + * See http://magiclantern.wikia.com/wiki/Register_Map#GPIO_Ports + */ + +#define DIGIC_GPIO_IN_LVL 1 +#define DIGIC_GPIO_OUT_LVL 2 +#define DIGIC_GPIO_DIR 4 +#define DIGIC_GPIO_TRISTATE 8 + +struct digic_gpio_chip { + void __iomem *base; + struct gpio_chip gc; +}; + +#define to_digic_gpio_chip(c) container_of(c, struct digic_gpio_chip, gc) + +static inline uint32_t digic_gpio_readl(struct digic_gpio_chip *chip, + uint32_t offset) +{ + return readl(chip->base + 4 * offset); +} + +static inline void digic_gpio_writel(struct digic_gpio_chip *chip, + uint32_t value, uint32_t offset) +{ + writel(value, chip->base + 4 * offset); +} + +static int digic_gpio_get_value(struct gpio_chip *gc, unsigned offset) +{ + struct digic_gpio_chip *chip = to_digic_gpio_chip(gc); + + if (offset >= gc->ngpio) + return -EINVAL; + + return digic_gpio_readl(chip, offset) & DIGIC_GPIO_IN_LVL; +} + +static void digic_gpio_set_value(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct digic_gpio_chip *chip = to_digic_gpio_chip(gc); + uint32_t t; + + if (offset >= gc->ngpio) + return; + + t = digic_gpio_readl(chip, offset); + /* Port direction (1 = OUT, 0 = IN) */ + if (value) + t |= DIGIC_GPIO_OUT_LVL; + else + t &= ~(DIGIC_GPIO_OUT_LVL); + digic_gpio_writel(chip, t, offset); +} + +static int digic_gpio_direction_input(struct gpio_chip *gc, unsigned offset) +{ + struct digic_gpio_chip *chip = to_digic_gpio_chip(gc); + uint32_t t; + + if (offset >= gc->ngpio) + return -EINVAL; + + t = digic_gpio_readl(chip, offset); + /* Port direction (1 = OUT, 0 = IN) */ + t &= ~(DIGIC_GPIO_DIR); + digic_gpio_writel(chip, t, offset); + + return 0; +} + +static int digic_gpio_direction_output(struct gpio_chip *gc, unsigned offset, + int value) +{ + struct digic_gpio_chip *chip = to_digic_gpio_chip(gc); + uint32_t t; + + if (offset >= gc->ngpio) + return -EINVAL; + + t = digic_gpio_readl(chip, offset); + /* Port direction (1 = OUT, 0 = IN) */ + t |= DIGIC_GPIO_DIR; + digic_gpio_writel(chip, t, offset); + + digic_gpio_set_value(gc, offset, value); + + return 0; +} + +static struct gpio_ops digic_gpio_ops = { + .direction_input = digic_gpio_direction_input, + .direction_output = digic_gpio_direction_output, + .get = digic_gpio_get_value, + .set = digic_gpio_set_value, +}; + +static int digic_gpio_probe(struct device_d *dev) +{ + struct digic_gpio_chip *chip; + struct resource *res; + resource_size_t rsize; + int ret = -EINVAL; + + chip = xzalloc(sizeof(*chip)); + + res = dev_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + goto err; + + rsize = resource_size(res); + chip->gc.ngpio = rsize / sizeof(int32_t); + + chip->base = dev_request_mem_region(dev, 0); + chip->gc.ops = &digic_gpio_ops; + chip->gc.base = 0; + + chip->gc.dev = dev; + + ret = gpiochip_add(&chip->gc); + if (ret) { + dev_err(dev, "couldn't add gpiochip, ret = %d\n", ret); + goto err; + } + + dev_info(dev, "probed gpiochip%d with base %d\n", + dev->id, chip->gc.base); + + return 0; + +err: + kfree(chip); + + return ret; +} + +static __maybe_unused struct of_device_id digic_gpio_dt_ids[] = { + { + .compatible = "canon,digic-gpio", + }, { + /* sentinel */ + } +}; + +static struct driver_d digic_gpio_driver = { + .name = "digic-gpio", + .probe = digic_gpio_probe, + .of_compatible = DRV_OF_COMPAT(digic_gpio_dt_ids), +}; + +static int digic_gpio_init(void) +{ + return platform_driver_register(&digic_gpio_driver); +} +coredevice_initcall(digic_gpio_init); diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c new file mode 100644 index 0000000000..aabbb09eb8 --- /dev/null +++ b/drivers/gpio/gpio-pca953x.c @@ -0,0 +1,481 @@ +/* + * PCA953x 4/8/16/24/40 bit I/O ports + * + * This code was ported from linux-3.15 kernel by Antony Pavlov. + * + * Copyright (C) 2005 Ben Gardner <bgardner@wabtec.com> + * Copyright (C) 2007 Marvell International Ltd. + * + * Derived from drivers/i2c/chips/pca9539.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + */ + +#include <common.h> +#include <init.h> +#include <malloc.h> +#include <driver.h> +#include <xfuncs.h> +#include <errno.h> +#include <i2c/i2c.h> + +#include <gpio.h> +#include <platform_data/pca953x.h> + +#define PCA953X_INPUT 0 +#define PCA953X_OUTPUT 1 +#define PCA953X_INVERT 2 +#define PCA953X_DIRECTION 3 + +#define REG_ADDR_AI 0x80 + +#define PCA957X_IN 0 +#define PCA957X_INVRT 1 +#define PCA957X_BKEN 2 +#define PCA957X_PUPD 3 +#define PCA957X_CFG 4 +#define PCA957X_OUT 5 +#define PCA957X_MSK 6 +#define PCA957X_INTS 7 + +#define PCA_GPIO_MASK 0x00FF +#define PCA_INT 0x0100 +#define PCA953X_TYPE 0x1000 +#define PCA957X_TYPE 0x2000 + +static struct platform_device_id pca953x_id[] = { + { "pca9505", 40 | PCA953X_TYPE | PCA_INT, }, + { "pca9534", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca9535", 16 | PCA953X_TYPE | PCA_INT, }, + { "pca9536", 4 | PCA953X_TYPE, }, + { "pca9537", 4 | PCA953X_TYPE | PCA_INT, }, + { "pca9538", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca9539", 16 | PCA953X_TYPE | PCA_INT, }, + { "pca9554", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca9555", 16 | PCA953X_TYPE | PCA_INT, }, + { "pca9556", 8 | PCA953X_TYPE, }, + { "pca9557", 8 | PCA953X_TYPE, }, + { "pca9574", 8 | PCA957X_TYPE | PCA_INT, }, + { "pca9575", 16 | PCA957X_TYPE | PCA_INT, }, + { "pca9698", 40 | PCA953X_TYPE, }, + + { "max7310", 8 | PCA953X_TYPE, }, + { "max7312", 16 | PCA953X_TYPE | PCA_INT, }, + { "max7313", 16 | PCA953X_TYPE | PCA_INT, }, + { "max7315", 8 | PCA953X_TYPE | PCA_INT, }, + { "pca6107", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6408", 8 | PCA953X_TYPE | PCA_INT, }, + { "tca6416", 16 | PCA953X_TYPE | PCA_INT, }, + { "tca6424", 24 | PCA953X_TYPE | PCA_INT, }, + { "xra1202", 8 | PCA953X_TYPE }, + { } +}; + +#define MAX_BANK 5 +#define BANK_SZ 8 + +#define NBANK(chip) (chip->gpio_chip.ngpio / BANK_SZ) + +struct pca953x_chip { + unsigned gpio_start; + u8 reg_output[MAX_BANK]; + u8 reg_direction[MAX_BANK]; + struct i2c_client *client; + struct gpio_chip gpio_chip; + const char *const *names; + int chip_type; +}; + +static inline struct pca953x_chip *to_pca(struct gpio_chip *gc) +{ + return container_of(gc, struct pca953x_chip, gpio_chip); +} + +static int pca953x_read_single(struct pca953x_chip *chip, int reg, u32 *val, + int off) +{ + int ret; + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int offset = off / BANK_SZ; + + ret = i2c_smbus_read_byte_data(chip->client, + (reg << bank_shift) + offset); + *val = ret; + + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return ret; + } + + return 0; +} + +static int pca953x_write_single(struct pca953x_chip *chip, int reg, u32 val, + int off) +{ + int ret = 0; + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + int offset = off / BANK_SZ; + + ret = i2c_smbus_write_byte_data(chip->client, + (reg << bank_shift) + offset, val); + + if (ret < 0) { + dev_err(&chip->client->dev, "failed writing register\n"); + return ret; + } + + return 0; +} + +static int pca953x_write_regs(struct pca953x_chip *chip, int reg, u8 *val) +{ + int ret = 0; + + if (chip->gpio_chip.ngpio <= 8) + ret = i2c_smbus_write_byte_data(chip->client, reg, *val); + else if (chip->gpio_chip.ngpio >= 24) { + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + ret = i2c_smbus_write_i2c_block_data(chip->client, + (reg << bank_shift) | REG_ADDR_AI, + NBANK(chip), val); + } else { + switch (chip->chip_type) { + case PCA953X_TYPE: + ret = i2c_smbus_write_word_data(chip->client, + reg << 1, (u16) *val); + break; + case PCA957X_TYPE: + ret = i2c_smbus_write_byte_data(chip->client, reg << 1, + val[0]); + if (ret < 0) + break; + ret = i2c_smbus_write_byte_data(chip->client, + (reg << 1) + 1, + val[1]); + break; + } + } + + if (ret < 0) { + dev_err(&chip->client->dev, "failed writing register\n"); + return ret; + } + + return 0; +} + +static int pca953x_read_regs(struct pca953x_chip *chip, int reg, u8 *val) +{ + int ret; + + if (chip->gpio_chip.ngpio <= 8) { + ret = i2c_smbus_read_byte_data(chip->client, reg); + *val = ret; + } else if (chip->gpio_chip.ngpio >= 24) { + int bank_shift = fls((chip->gpio_chip.ngpio - 1) / BANK_SZ); + + ret = i2c_smbus_read_i2c_block_data(chip->client, + (reg << bank_shift) | REG_ADDR_AI, + NBANK(chip), val); + } else { + ret = i2c_smbus_read_word_data(chip->client, reg << 1); + val[0] = (u16)ret & 0xFF; + val[1] = (u16)ret >> 8; + } + if (ret < 0) { + dev_err(&chip->client->dev, "failed reading register\n"); + return ret; + } + + return 0; +} + +static int pca953x_gpio_direction_input(struct gpio_chip *gc, unsigned off) +{ + struct pca953x_chip *chip = to_pca(gc); + u8 reg_val; + int ret, offset = 0; + + reg_val = chip->reg_direction[off / BANK_SZ] | (1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_DIRECTION; + break; + case PCA957X_TYPE: + offset = PCA957X_CFG; + break; + } + ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + + chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; +exit: + return ret; +} + +static int pca953x_gpio_direction_output(struct gpio_chip *gc, + unsigned off, int val) +{ + struct pca953x_chip *chip = to_pca(gc); + u8 reg_val; + int ret, offset = 0; + + /* set output level */ + if (val) + reg_val = chip->reg_output[off / BANK_SZ] + | (1u << (off % BANK_SZ)); + else + reg_val = chip->reg_output[off / BANK_SZ] + & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_OUTPUT; + break; + case PCA957X_TYPE: + offset = PCA957X_OUT; + break; + } + ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + + chip->reg_output[off / BANK_SZ] = reg_val; + + /* then direction */ + reg_val = chip->reg_direction[off / BANK_SZ] & ~(1u << (off % BANK_SZ)); + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_DIRECTION; + break; + case PCA957X_TYPE: + offset = PCA957X_CFG; + break; + } + ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + + chip->reg_direction[off / BANK_SZ] = reg_val; + ret = 0; +exit: + return ret; +} + +static int pca953x_gpio_get_direction(struct gpio_chip *gc, unsigned off) +{ + struct pca953x_chip *chip = to_pca(gc); + u8 reg_val; + + reg_val = chip->reg_direction[off / BANK_SZ] & (1u << (off % BANK_SZ)); + + if (reg_val) + return GPIOF_DIR_IN; + + return GPIOF_DIR_OUT; +} + +static int pca953x_gpio_get_value(struct gpio_chip *gc, unsigned off) +{ + struct pca953x_chip *chip = to_pca(gc); + u32 reg_val; + int ret, offset = 0; + + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_INPUT; + break; + case PCA957X_TYPE: + offset = PCA957X_IN; + break; + } + ret = pca953x_read_single(chip, offset, ®_val, off); + if (ret < 0) { + /* NOTE: diagnostic already emitted; that's all we should + * do unless gpio_*_value_cansleep() calls become different + * from their nonsleeping siblings (and report faults). + */ + return 0; + } + + return (reg_val & (1u << (off % BANK_SZ))) ? 1 : 0; +} + +static void pca953x_gpio_set_value(struct gpio_chip *gc, unsigned off, int val) +{ + struct pca953x_chip *chip = to_pca(gc); + u8 reg_val; + int ret, offset = 0; + + if (val) + reg_val = chip->reg_output[off / BANK_SZ] + | (1u << (off % BANK_SZ)); + else + reg_val = chip->reg_output[off / BANK_SZ] + & ~(1u << (off % BANK_SZ)); + + switch (chip->chip_type) { + case PCA953X_TYPE: + offset = PCA953X_OUTPUT; + break; + case PCA957X_TYPE: + offset = PCA957X_OUT; + break; + } + ret = pca953x_write_single(chip, offset, reg_val, off); + if (ret) + goto exit; + + chip->reg_output[off / BANK_SZ] = reg_val; +exit: + return; +} + +static struct gpio_ops pca953x_gpio_ops = { + .direction_input = pca953x_gpio_direction_input, + .direction_output = pca953x_gpio_direction_output, + .get_direction = pca953x_gpio_get_direction, + .get = pca953x_gpio_get_value, + .set = pca953x_gpio_set_value, +}; + +static void pca953x_setup_gpio(struct pca953x_chip *chip, int gpios) +{ + struct gpio_chip *gc; + + gc = &chip->gpio_chip; + + gc->ops = &pca953x_gpio_ops; + + gc->base = chip->gpio_start; + gc->ngpio = gpios; + gc->dev = &chip->client->dev; +} + +static int device_pca953x_init(struct pca953x_chip *chip, u32 invert) +{ + int ret; + u8 val[MAX_BANK]; + + ret = pca953x_read_regs(chip, PCA953X_OUTPUT, chip->reg_output); + if (ret) + goto out; + + ret = pca953x_read_regs(chip, PCA953X_DIRECTION, + chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ + if (invert) + memset(val, 0xFF, NBANK(chip)); + else + memset(val, 0, NBANK(chip)); + + ret = pca953x_write_regs(chip, PCA953X_INVERT, val); +out: + return ret; +} + +static int device_pca957x_init(struct pca953x_chip *chip, u32 invert) +{ + int ret; + u8 val[MAX_BANK]; + + ret = pca953x_read_regs(chip, PCA957X_OUT, chip->reg_output); + if (ret) + goto out; + ret = pca953x_read_regs(chip, PCA957X_CFG, chip->reg_direction); + if (ret) + goto out; + + /* set platform specific polarity inversion */ + if (invert) + memset(val, 0xFF, NBANK(chip)); + else + memset(val, 0, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_INVRT, val); + + /* To enable register 6, 7 to controll pull up and pull down */ + memset(val, 0x02, NBANK(chip)); + pca953x_write_regs(chip, PCA957X_BKEN, val); + + return 0; +out: + return ret; +} + +static int pca953x_probe(struct device_d *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + unsigned long driver_data; + struct pca953x_platform_data *pdata; + struct pca953x_chip *chip; + int ret; + u32 invert = 0; + + chip = xzalloc(sizeof(struct pca953x_chip)); + + driver_data = 0; + pdata = dev->platform_data; + if (pdata) { + chip->gpio_start = pdata->gpio_base; + invert = pdata->invert; + chip->names = pdata->names; + } else { + int err; + + err = dev_get_drvdata(dev, &driver_data); + if (err) + return err; + + chip->gpio_start = -1; + } + + chip->client = client; + + chip->chip_type = driver_data & (PCA953X_TYPE | PCA957X_TYPE); + + /* initialize cached registers from their original values. + * we can't share this chip with another i2c master. + */ + pca953x_setup_gpio(chip, driver_data & PCA_GPIO_MASK); + + if (chip->chip_type == PCA953X_TYPE) + ret = device_pca953x_init(chip, invert); + else + ret = device_pca957x_init(chip, invert); + if (ret) + return ret; + + ret = gpiochip_add(&chip->gpio_chip); + if (ret) + return ret; + + if (pdata && pdata->setup) { + ret = pdata->setup(client, chip->gpio_chip.base, + chip->gpio_chip.ngpio, pdata->context); + if (ret < 0) + dev_warn(&client->dev, "setup failed, %d\n", ret); + } + + return 0; +} + +static struct driver_d pca953x_driver = { + .name = "pca953x", + .probe = pca953x_probe, + .id_table = pca953x_id, +}; + +static int __init pca953x_init(void) +{ + return i2c_driver_register(&pca953x_driver); +} +device_initcall(pca953x_init); diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 5ce0324714..648d844252 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -1 +1 @@ -obj-$(CONFIG_I2C) += i2c.o busses/ algos/ +obj-$(CONFIG_I2C) += i2c.o i2c-smbus.o busses/ algos/ diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 370abb0c2e..39622863fb 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -12,10 +12,22 @@ config I2C_GPIO This is a very simple bitbanging I2C driver utilizing the arch-neutral GPIO API to control the SCL and SDA lines. +config I2C_AT91 + bool "AT91 I2C Master driver" + depends on ARCH_AT91 + config I2C_IMX bool "MPC85xx/i.MX I2C Master driver" depends on (ARCH_IMX && !ARCH_IMX1) || ARCH_MPC85XX +config I2C_MV64XXX + bool "Marvell mv64xxx I2C Controller" + depends on HAVE_CLK && OFDEVICE + help + If you say yes to this option, support will be included for the + built-in I2C interface on the Marvell 64xxx line of host bridges. + This driver is also used for Allwinner SoCs I2C controllers. + config I2C_OMAP bool "OMAP I2C Master driver" depends on ARCH_OMAP diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 9823d1bd36..1dbfbdf93b 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -1,5 +1,7 @@ +obj-$(CONFIG_I2C_AT91) += i2c-at91.o obj-$(CONFIG_I2C_GPIO) += i2c-gpio.o -obj-$(CONFIG_I2C_IMX) += i2c-imx.o -obj-$(CONFIG_I2C_OMAP) += i2c-omap.o +obj-$(CONFIG_I2C_IMX) += i2c-imx.o +obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o +obj-$(CONFIG_I2C_OMAP) += i2c-omap.o obj-$(CONFIG_I2C_TEGRA) += i2c-tegra.o obj-$(CONFIG_I2C_VERSATILE) += i2c-versatile.o diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c new file mode 100644 index 0000000000..399f6a94be --- /dev/null +++ b/drivers/i2c/busses/i2c-at91.c @@ -0,0 +1,437 @@ +/* + * i2c Support for Atmel's AT91 Two-Wire Interface (TWI) + * + * Copyright (C) 2011 Weinmann Medical GmbH + * Author: Nikolaus Voss <n.voss@weinmann.de> + * + * Evolved from original work by: + * Copyright (C) 2004 Rick Bronson + * Converted to 2.6 by Andrew Victor <andrew@sanpeople.com> + * + * Borrowed heavily from original work by: + * Copyright (C) 2000 Philip Edelbrock <phil@stimpy.netroedge.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <common.h> +#include <clock.h> +#include <i2c/i2c.h> +#include <malloc.h> +#include <of.h> +#include <io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <driver.h> +#include <init.h> + +#define DEFAULT_TWI_CLK_HZ 100000 /* max 400 Kbits/s */ +#define AT91_I2C_TIMEOUT (100 * MSECOND) /* transfer timeout */ +#define AT91_I2C_DMA_THRESHOLD 8 /* enable DMA if transfer size is bigger than this threshold */ + +/* AT91 TWI register definitions */ +#define AT91_TWI_CR 0x0000 /* Control Register */ +#define AT91_TWI_START 0x0001 /* Send a Start Condition */ +#define AT91_TWI_STOP 0x0002 /* Send a Stop Condition */ +#define AT91_TWI_MSEN 0x0004 /* Master Transfer Enable */ +#define AT91_TWI_SVDIS 0x0020 /* Slave Transfer Disable */ +#define AT91_TWI_QUICK 0x0040 /* SMBus quick command */ +#define AT91_TWI_SWRST 0x0080 /* Software Reset */ + +#define AT91_TWI_MMR 0x0004 /* Master Mode Register */ +#define AT91_TWI_IADRSZ_1 0x0100 /* Internal Device Address Size */ +#define AT91_TWI_MREAD 0x1000 /* Master Read Direction */ + +#define AT91_TWI_IADR 0x000c /* Internal Address Register */ + +#define AT91_TWI_CWGR 0x0010 /* Clock Waveform Generator Reg */ + +#define AT91_TWI_SR 0x0020 /* Status Register */ +#define AT91_TWI_TXCOMP 0x0001 /* Transmission Complete */ +#define AT91_TWI_RXRDY 0x0002 /* Receive Holding Register Ready */ +#define AT91_TWI_TXRDY 0x0004 /* Transmit Holding Register Ready */ + +#define AT91_TWI_OVRE 0x0040 /* Overrun Error */ +#define AT91_TWI_UNRE 0x0080 /* Underrun Error */ +#define AT91_TWI_NACK 0x0100 /* Not Acknowledged */ + +#define AT91_TWI_IER 0x0024 /* Interrupt Enable Register */ +#define AT91_TWI_IDR 0x0028 /* Interrupt Disable Register */ +#define AT91_TWI_IMR 0x002c /* Interrupt Mask Register */ +#define AT91_TWI_RHR 0x0030 /* Receive Holding Register */ +#define AT91_TWI_THR 0x0034 /* Transmit Holding Register */ + +struct at91_twi_pdata { + unsigned clk_max_div; + unsigned clk_offset; + bool has_unre_flag; +}; + +struct at91_twi_dev { + struct device *dev; + void __iomem *base; + struct clk *clk; + u8 *buf; + size_t buf_len; + struct i2c_msg *msg; + unsigned imr; + unsigned transfer_status; + struct i2c_adapter adapter; + unsigned twi_cwgr_reg; + struct at91_twi_pdata *pdata; +}; + +#define to_at91_twi_dev(a) container_of(a, struct at91_twi_dev, adapter) + +static unsigned at91_twi_read(struct at91_twi_dev *dev, unsigned reg) +{ + return __raw_readl(dev->base + reg); +} + +static void at91_twi_write(struct at91_twi_dev *dev, unsigned reg, unsigned val) +{ + __raw_writel(val, dev->base + reg); +} + +static void at91_disable_twi_interrupts(struct at91_twi_dev *dev) +{ + at91_twi_write(dev, AT91_TWI_IDR, + AT91_TWI_TXCOMP | AT91_TWI_RXRDY | AT91_TWI_TXRDY); +} + +static void at91_init_twi_bus(struct at91_twi_dev *dev) +{ + at91_disable_twi_interrupts(dev); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SWRST); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_MSEN); + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_SVDIS); + at91_twi_write(dev, AT91_TWI_CWGR, dev->twi_cwgr_reg); +} + +/* + * Calculate symmetric clock as stated in datasheet: + * twi_clk = F_MAIN / (2 * (cdiv * (1 << ckdiv) + offset)) + */ +static void at91_calc_twi_clock(struct at91_twi_dev *dev, int twi_clk) +{ + int ckdiv, cdiv, div; + struct at91_twi_pdata *pdata = dev->pdata; + int offset = pdata->clk_offset; + int max_ckdiv = pdata->clk_max_div; + + div = max(0, (int)DIV_ROUND_UP(clk_get_rate(dev->clk), + 2 * twi_clk) - offset); + ckdiv = fls(div >> 8); + cdiv = div >> ckdiv; + + if (ckdiv > max_ckdiv) { + dev_warn(&dev->adapter.dev, "%d exceeds ckdiv max value which is %d.\n", + ckdiv, max_ckdiv); + ckdiv = max_ckdiv; + cdiv = 255; + } + + dev->twi_cwgr_reg = (ckdiv << 16) | (cdiv << 8) | cdiv; + dev_dbg(&dev->adapter.dev, "cdiv %d ckdiv %d\n", cdiv, ckdiv); +} + +static void at91_twi_write_next_byte(struct at91_twi_dev *dev) +{ + if (dev->buf_len <= 0) + return; + + at91_twi_write(dev, AT91_TWI_THR, *dev->buf); + + /* send stop when last byte has been written */ + if (--dev->buf_len == 0) + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + + dev_dbg(&dev->adapter.dev, "wrote 0x%x, to go %d\n", *dev->buf, dev->buf_len); + + ++dev->buf; +} + +static void at91_twi_read_next_byte(struct at91_twi_dev *dev) +{ + if (dev->buf_len <= 0) + return; + + *dev->buf = at91_twi_read(dev, AT91_TWI_RHR) & 0xff; + --dev->buf_len; + + /* send stop if second but last byte has been read */ + if (dev->buf_len == 1) + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_STOP); + + dev_dbg(&dev->adapter.dev, "read 0x%x, to go %d\n", *dev->buf, dev->buf_len); + + ++dev->buf; +} + +static int at91_twi_wait_completion(struct at91_twi_dev *dev) +{ + uint64_t start = get_time_ns(); + unsigned int status = at91_twi_read(dev, AT91_TWI_SR); + unsigned int irqstatus = at91_twi_read(dev, AT91_TWI_IMR); + + if (irqstatus & AT91_TWI_RXRDY) + at91_twi_read_next_byte(dev); + else if (irqstatus & AT91_TWI_TXRDY) + at91_twi_write_next_byte(dev); + else + dev_warn(&dev->adapter.dev, "neither rx and tx are ready\n"); + + dev->transfer_status |= status; + + while(!(at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_TXCOMP)) { + if(is_timeout(start, AT91_I2C_TIMEOUT)) { + dev_warn(&dev->adapter.dev, "timeout waiting for bus ready\n"); + return -ETIMEDOUT; + } + } + + at91_disable_twi_interrupts(dev); + + return 0; +} + +static int at91_do_twi_transfer(struct at91_twi_dev *dev) +{ + int ret; + bool has_unre_flag = dev->pdata->has_unre_flag; + + dev_dbg(&dev->adapter.dev, "transfer: %s %d bytes.\n", + (dev->msg->flags & I2C_M_RD) ? "read" : "write", dev->buf_len); + + dev->transfer_status = 0; + + if (!dev->buf_len) { + at91_twi_write(dev, AT91_TWI_CR, AT91_TWI_QUICK); + at91_twi_write(dev, AT91_TWI_IER, AT91_TWI_TXCOMP); + } else if (dev->msg->flags & I2C_M_RD) { + unsigned start_flags = AT91_TWI_START; + + if (at91_twi_read(dev, AT91_TWI_SR) & AT91_TWI_RXRDY) { + dev_err(&dev->adapter.dev, "RXRDY still set!"); + at91_twi_read(dev, AT91_TWI_RHR); + } + + /* if only one byte is to be read, immediately stop transfer */ + if (dev->buf_len <= 1) + start_flags |= AT91_TWI_STOP; + + at91_twi_write(dev, AT91_TWI_CR, start_flags); + + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP | AT91_TWI_RXRDY); + } else { + at91_twi_write_next_byte(dev); + at91_twi_write(dev, AT91_TWI_IER, + AT91_TWI_TXCOMP | AT91_TWI_TXRDY); + } + + ret = at91_twi_wait_completion(dev); + if (ret < 0) { + dev_err(&dev->adapter.dev, "controller timed out\n"); + at91_init_twi_bus(dev); + ret = -ETIMEDOUT; + goto error; + } + if (dev->transfer_status & AT91_TWI_NACK) { + dev_dbg(&dev->adapter.dev, "received nack\n"); + ret = -EREMOTEIO; + goto error; + } + if (dev->transfer_status & AT91_TWI_OVRE) { + dev_err(&dev->adapter.dev, "overrun while reading\n"); + ret = -EIO; + goto error; + } + if (has_unre_flag && dev->transfer_status & AT91_TWI_UNRE) { + dev_err(&dev->adapter.dev, "underrun while writing\n"); + ret = -EIO; + goto error; + } + dev_dbg(&dev->adapter.dev, "transfer complete\n"); + + return 0; + +error: + return ret; +} + +static int at91_twi_xfer(struct i2c_adapter *adap, struct i2c_msg *msg, int num) +{ + struct at91_twi_dev *dev = to_at91_twi_dev(adap); + int ret; + unsigned int_addr_flag = 0; + struct i2c_msg *m_start = msg; + + dev_dbg(&adap->dev, "at91_xfer: processing %d messages:\n", num); + + /* + * The hardware can handle at most two messages concatenated by a + * repeated start via it's internal address feature. + */ + if (num > 2) { + dev_err(&dev->adapter.dev, + "cannot handle more than two concatenated messages.\n"); + return 0; + } else if (num == 2) { + int internal_address = 0; + int i; + + if (msg->flags & I2C_M_RD) { + dev_err(&dev->adapter.dev, "first transfer must be write.\n"); + return -EINVAL; + } + if (msg->len > 3) { + dev_err(&dev->adapter.dev, "first message size must be <= 3.\n"); + return -EINVAL; + } + + /* 1st msg is put into the internal address, start with 2nd */ + m_start = &msg[1]; + for (i = 0; i < msg->len; ++i) { + const unsigned addr = msg->buf[msg->len - 1 - i]; + + internal_address |= addr << (8 * i); + int_addr_flag += AT91_TWI_IADRSZ_1; + } + at91_twi_write(dev, AT91_TWI_IADR, internal_address); + } + + at91_twi_write(dev, AT91_TWI_MMR, (m_start->addr << 16) | int_addr_flag + | ((m_start->flags & I2C_M_RD) ? AT91_TWI_MREAD : 0)); + + dev->buf_len = m_start->len; + dev->buf = m_start->buf; + dev->msg = m_start; + + ret = at91_do_twi_transfer(dev); + + return (ret < 0) ? ret : num; +} + +static struct at91_twi_pdata at91rm9200_config = { + .clk_max_div = 5, + .clk_offset = 3, + .has_unre_flag = true, +}; + +static struct at91_twi_pdata at91sam9261_config = { + .clk_max_div = 5, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9260_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9g20_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct at91_twi_pdata at91sam9g10_config = { + .clk_max_div = 7, + .clk_offset = 4, + .has_unre_flag = false, +}; + +static struct platform_device_id at91_twi_devtypes[] = { + { + .name = "i2c-at91rm9200", + .driver_data = (unsigned long) &at91rm9200_config, + }, { + .name = "i2c-at91sam9261", + .driver_data = (unsigned long) &at91sam9261_config, + }, { + .name = "i2c-at91sam9260", + .driver_data = (unsigned long) &at91sam9260_config, + }, { + .name = "i2c-at91sam9g20", + .driver_data = (unsigned long) &at91sam9g20_config, + }, { + .name = "i2c-at91sam9g10", + .driver_data = (unsigned long) &at91sam9g10_config, + }, { + /* sentinel */ + } +}; + +static int at91_twi_probe(struct device_d *dev) +{ + struct at91_twi_dev *i2c_at91; + struct at91_twi_pdata *i2c_data; + int rc; + u32 bus_clk_rate; + + i2c_at91 = xzalloc(sizeof(struct at91_twi_dev)); + + rc = dev_get_drvdata(dev, (unsigned long *)&i2c_data); + if (rc) + goto out_free; + + i2c_at91->pdata = i2c_data; + + i2c_at91->base = dev_request_mem_region(dev, 0); + if (!i2c_at91->base) { + dev_err(dev, "could not get memory region\n"); + rc = -ENODEV; + goto out_free; + } + + i2c_at91->clk = clk_get(dev, "twi_clk"); + if (IS_ERR(i2c_at91->clk)) { + dev_err(dev, "no clock defined\n"); + rc = -ENODEV; + goto out_free; + } + + clk_enable(i2c_at91->clk); + + bus_clk_rate = DEFAULT_TWI_CLK_HZ; + + at91_calc_twi_clock(i2c_at91, bus_clk_rate); + at91_init_twi_bus(i2c_at91); + + i2c_at91->adapter.master_xfer = at91_twi_xfer; + i2c_at91->adapter.dev.parent = dev; + i2c_at91->adapter.nr = dev->id; + i2c_at91->adapter.dev.device_node = dev->device_node; + + rc = i2c_add_numbered_adapter(&i2c_at91->adapter); + if (rc) { + dev_err(dev, "Failed to add I2C adapter\n"); + goto out_adap_fail; + } + + dev_info(dev, "AT91 i2c bus driver.\n"); + return 0; + +out_adap_fail: + clk_disable(i2c_at91->clk); + clk_put(i2c_at91->clk); +out_free: + kfree(i2c_at91); + return rc; +} + +static struct driver_d at91_twi_driver = { + .name = "at91-twi", + .probe = at91_twi_probe, + .id_table = at91_twi_devtypes, +}; +device_platform_driver(at91_twi_driver); + +MODULE_AUTHOR("Nikolaus Voss <n.voss@weinmann.de>"); +MODULE_DESCRIPTION("I2C (TWI) driver for Atmel AT91"); +MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c new file mode 100644 index 0000000000..6d8c85b9d7 --- /dev/null +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -0,0 +1,647 @@ +/* + * Driver for the i2c controller on the Marvell line of host bridges + * (e.g, gt642[46]0, mv643[46]0, mv644[46]0, and Orion SoC family). + * + * This code was ported from linux-3.15 kernel by Antony Pavlov. + * + * Author: Mark A. Greer <mgreer@mvista.com> + * + * 2005 (c) MontaVista, Software, Inc. This file is licensed under + * the terms of the GNU General Public License version 2. This program + * is licensed "as is" without any warranty of any kind, whether express + * or implied. + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <of.h> +#include <malloc.h> +#include <types.h> +#include <xfuncs.h> +#include <clock.h> +#include <linux/clk.h> +#include <linux/err.h> + +#include <io.h> +#include <i2c/i2c.h> + +#define ADDR_ADDR(val) ((val & 0x7f) << 1) +#define BAUD_DIV_N(val) (val & 0x7) +#define BAUD_DIV_M(val) ((val & 0xf) << 3) + +#define REG_CONTROL_ACK 0x00000004 +#define REG_CONTROL_IFLG 0x00000008 +#define REG_CONTROL_STOP 0x00000010 +#define REG_CONTROL_START 0x00000020 +#define REG_CONTROL_TWSIEN 0x00000040 +#define REG_CONTROL_INTEN 0x00000080 + +/* Ctlr status values */ +#define STATUS_MAST_START 0x08 +#define STATUS_MAST_REPEAT_START 0x10 +#define STATUS_MAST_WR_ADDR_ACK 0x18 +#define STATUS_MAST_WR_ADDR_NO_ACK 0x20 +#define STATUS_MAST_WR_ACK 0x28 +#define STATUS_MAST_WR_NO_ACK 0x30 +#define STATUS_MAST_RD_ADDR_ACK 0x40 +#define STATUS_MAST_RD_ADDR_NO_ACK 0x48 +#define STATUS_MAST_RD_DATA_ACK 0x50 +#define STATUS_MAST_RD_DATA_NO_ACK 0x58 +#define STATUS_MAST_WR_ADDR_2_ACK 0xd0 +#define STATUS_MAST_RD_ADDR_2_ACK 0xe0 + +/* Driver states */ +enum mv64xxx_state { + STATE_INVALID, + STATE_IDLE, + STATE_WAITING_FOR_START_COND, + STATE_WAITING_FOR_RESTART, + STATE_WAITING_FOR_ADDR_1_ACK, + STATE_WAITING_FOR_ADDR_2_ACK, + STATE_WAITING_FOR_SLAVE_ACK, + STATE_WAITING_FOR_SLAVE_DATA, +}; + +/* Driver actions */ +enum mv64xxx_action { + ACTION_INVALID, + ACTION_CONTINUE, + ACTION_SEND_RESTART, + ACTION_OFFLOAD_RESTART, + ACTION_SEND_ADDR_1, + ACTION_SEND_ADDR_2, + ACTION_SEND_DATA, + ACTION_RCV_DATA, + ACTION_RCV_DATA_STOP, + ACTION_SEND_STOP, + ACTION_OFFLOAD_SEND_STOP, +}; + +struct mv64xxx_i2c_regs { + u8 addr; + u8 ext_addr; + u8 data; + u8 control; + u8 status; + u8 clock; + u8 soft_reset; +}; + +struct mv64xxx_i2c_data { + struct i2c_msg *msgs; + int num_msgs; + enum mv64xxx_state state; + enum mv64xxx_action action; + u8 cntl_bits; + void __iomem *reg_base; + struct mv64xxx_i2c_regs reg_offsets; + u8 addr1; + u8 addr2; + u8 bytes_left; + u8 byte_posn; + u8 send_stop; + bool block; + int rc; + u32 freq_m; + u32 freq_n; + struct clk *clk; + struct i2c_msg *msg; + struct i2c_adapter adapter; +/* 5us delay in order to avoid repeated start timing violation */ + bool errata_delay; + void (*write_reg)(struct mv64xxx_i2c_data *drv_data, u32 v, unsigned reg); + u32 (*read_reg)(struct mv64xxx_i2c_data *drv_data, unsigned reg); +}; + +static struct mv64xxx_i2c_regs mv64xxx_i2c_regs_mv64xxx = { + .addr = 0x00, + .ext_addr = 0x10, + .data = 0x04, + .control = 0x08, + .status = 0x0c, + .clock = 0x0c, + .soft_reset = 0x1c, +}; + +static void mv64xxx_writeb(struct mv64xxx_i2c_data *drv_data, + u32 v, unsigned reg) +{ + writeb(v, drv_data->reg_base + reg); +} + +static void mv64xxx_writel(struct mv64xxx_i2c_data *drv_data, + u32 v, unsigned reg) +{ + writel(v, drv_data->reg_base + reg); +} + +static inline void mv64xxx_write(struct mv64xxx_i2c_data *drv_data, + u32 v, unsigned reg) +{ + drv_data->write_reg(drv_data, v, reg); +} + +static u32 mv64xxx_readb(struct mv64xxx_i2c_data *drv_data, unsigned reg) +{ + return readb(drv_data->reg_base + reg); +} + +static u32 mv64xxx_readl(struct mv64xxx_i2c_data *drv_data, unsigned reg) +{ + return readl(drv_data->reg_base + reg); +} + +static inline u32 mv64xxx_read(struct mv64xxx_i2c_data *drv_data, unsigned reg) +{ + return drv_data->read_reg(drv_data, reg); +} + +static void +mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data, + struct i2c_msg *msg) +{ + u32 dir = 0; + + drv_data->cntl_bits = REG_CONTROL_ACK | + REG_CONTROL_INTEN | REG_CONTROL_TWSIEN; + + if (msg->flags & I2C_M_RD) + dir = 1; + + if (msg->flags & I2C_M_TEN) { + drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir; + drv_data->addr2 = (u32)msg->addr & 0xff; + } else { + drv_data->addr1 = ADDR_ADDR((u32)msg->addr) | dir; + drv_data->addr2 = 0; + } +} + +/* + ***************************************************************************** + * + * Finite State Machine & Interrupt Routines + * + ***************************************************************************** + */ + +/* Reset hardware and initialize FSM */ +static void +mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) +{ + mv64xxx_write(drv_data, 0, drv_data->reg_offsets.soft_reset); + mv64xxx_write(drv_data, BAUD_DIV_M(drv_data->freq_m) + | BAUD_DIV_N(drv_data->freq_n), + drv_data->reg_offsets.clock); + mv64xxx_write(drv_data, 0, drv_data->reg_offsets.addr); + mv64xxx_write(drv_data, 0, drv_data->reg_offsets.ext_addr); + mv64xxx_write(drv_data, REG_CONTROL_TWSIEN + | REG_CONTROL_STOP, + drv_data->reg_offsets.control); + drv_data->state = STATE_IDLE; +} + +static void +mv64xxx_i2c_fsm(struct mv64xxx_i2c_data *drv_data, u32 status) +{ + /* + * If state is idle, then this is likely the remnants of an old + * operation that driver has given up on or the user has killed. + * If so, issue the stop condition and go to idle. + */ + if (drv_data->state == STATE_IDLE) { + drv_data->action = ACTION_SEND_STOP; + return; + } + + /* The status from the ctlr [mostly] tells us what to do next */ + switch (status) { + /* Start condition interrupt */ + case STATUS_MAST_START: /* 0x08 */ + case STATUS_MAST_REPEAT_START: /* 0x10 */ + drv_data->action = ACTION_SEND_ADDR_1; + drv_data->state = STATE_WAITING_FOR_ADDR_1_ACK; + break; + + /* Performing a write */ + case STATUS_MAST_WR_ADDR_ACK: /* 0x18 */ + if (drv_data->msg->flags & I2C_M_TEN) { + drv_data->action = ACTION_SEND_ADDR_2; + drv_data->state = + STATE_WAITING_FOR_ADDR_2_ACK; + break; + } + /* FALLTHRU */ + case STATUS_MAST_WR_ADDR_2_ACK: /* 0xd0 */ + case STATUS_MAST_WR_ACK: /* 0x28 */ + if (drv_data->bytes_left == 0) { + if (drv_data->send_stop) { + drv_data->action = ACTION_SEND_STOP; + drv_data->state = STATE_IDLE; + } else { + drv_data->action = + ACTION_SEND_RESTART; + drv_data->state = + STATE_WAITING_FOR_RESTART; + } + } else { + drv_data->action = ACTION_SEND_DATA; + drv_data->state = + STATE_WAITING_FOR_SLAVE_ACK; + drv_data->bytes_left--; + } + break; + + /* Performing a read */ + case STATUS_MAST_RD_ADDR_ACK: /* 40 */ + if (drv_data->msg->flags & I2C_M_TEN) { + drv_data->action = ACTION_SEND_ADDR_2; + drv_data->state = + STATE_WAITING_FOR_ADDR_2_ACK; + break; + } + /* FALLTHRU */ + case STATUS_MAST_RD_ADDR_2_ACK: /* 0xe0 */ + if (drv_data->bytes_left == 0) { + drv_data->action = ACTION_SEND_STOP; + drv_data->state = STATE_IDLE; + break; + } + /* FALLTHRU */ + case STATUS_MAST_RD_DATA_ACK: /* 0x50 */ + if (status != STATUS_MAST_RD_DATA_ACK) + drv_data->action = ACTION_CONTINUE; + else { + drv_data->action = ACTION_RCV_DATA; + drv_data->bytes_left--; + } + drv_data->state = STATE_WAITING_FOR_SLAVE_DATA; + + if (drv_data->bytes_left == 1) + drv_data->cntl_bits &= ~REG_CONTROL_ACK; + break; + + case STATUS_MAST_RD_DATA_NO_ACK: /* 0x58 */ + drv_data->action = ACTION_RCV_DATA_STOP; + drv_data->state = STATE_IDLE; + break; + + case STATUS_MAST_WR_ADDR_NO_ACK: /* 0x20 */ + case STATUS_MAST_WR_NO_ACK: /* 30 */ + case STATUS_MAST_RD_ADDR_NO_ACK: /* 48 */ + /* Doesn't seem to be a device at other end */ + drv_data->action = ACTION_SEND_STOP; + drv_data->state = STATE_IDLE; + drv_data->rc = -ENXIO; + break; + + default: + dev_err(&drv_data->adapter.dev, + "mv64xxx_i2c_fsm: Ctlr Error -- state: 0x%x, " + "status: 0x%x, addr: 0x%x, flags: 0x%x\n", + drv_data->state, status, drv_data->msg->addr, + drv_data->msg->flags); + drv_data->action = ACTION_SEND_STOP; + mv64xxx_i2c_hw_init(drv_data); + drv_data->rc = -EIO; + } +} + +static void mv64xxx_i2c_send_start(struct mv64xxx_i2c_data *drv_data) +{ + drv_data->msg = drv_data->msgs; + drv_data->byte_posn = 0; + drv_data->bytes_left = drv_data->msg->len; + drv_data->rc = 0; + + mv64xxx_i2c_prepare_for_io(drv_data, drv_data->msgs); + mv64xxx_write(drv_data, drv_data->cntl_bits | REG_CONTROL_START, + drv_data->reg_offsets.control); +} + +static void +mv64xxx_i2c_do_action(struct mv64xxx_i2c_data *drv_data) +{ + switch (drv_data->action) { + case ACTION_SEND_RESTART: + /* We should only get here if we have further messages */ + BUG_ON(drv_data->num_msgs == 0); + + drv_data->msgs++; + drv_data->num_msgs--; + mv64xxx_i2c_send_start(drv_data); + + if (drv_data->errata_delay) + udelay(5); + + /* + * We're never at the start of the message here, and by this + * time it's already too late to do any protocol mangling. + * Thankfully, do not advertise support for that feature. + */ + drv_data->send_stop = drv_data->num_msgs == 1; + break; + + case ACTION_CONTINUE: + mv64xxx_write(drv_data, drv_data->cntl_bits, + drv_data->reg_offsets.control); + break; + + case ACTION_SEND_ADDR_1: + mv64xxx_write(drv_data, drv_data->addr1, + drv_data->reg_offsets.data); + mv64xxx_write(drv_data, drv_data->cntl_bits, + drv_data->reg_offsets.control); + break; + + case ACTION_SEND_ADDR_2: + mv64xxx_write(drv_data, drv_data->addr2, + drv_data->reg_offsets.data); + mv64xxx_write(drv_data, drv_data->cntl_bits, + drv_data->reg_offsets.control); + break; + + case ACTION_SEND_DATA: + mv64xxx_write(drv_data, drv_data->msg->buf[drv_data->byte_posn++], + drv_data->reg_offsets.data); + mv64xxx_write(drv_data, drv_data->cntl_bits, + drv_data->reg_offsets.control); + break; + + case ACTION_RCV_DATA: + drv_data->msg->buf[drv_data->byte_posn++] = + mv64xxx_read(drv_data, drv_data->reg_offsets.data); + mv64xxx_write(drv_data, drv_data->cntl_bits, + drv_data->reg_offsets.control); + break; + + case ACTION_RCV_DATA_STOP: + drv_data->msg->buf[drv_data->byte_posn++] = + mv64xxx_read(drv_data, drv_data->reg_offsets.data); + drv_data->cntl_bits &= ~REG_CONTROL_INTEN; + mv64xxx_write(drv_data, drv_data->cntl_bits | REG_CONTROL_STOP, + drv_data->reg_offsets.control); + drv_data->block = false; + if (drv_data->errata_delay) + udelay(5); + + break; + + case ACTION_INVALID: + default: + dev_err(&drv_data->adapter.dev, + "mv64xxx_i2c_do_action: Invalid action: %d\n", + drv_data->action); + drv_data->rc = -EIO; + + /* FALLTHRU */ + case ACTION_SEND_STOP: + drv_data->cntl_bits &= ~REG_CONTROL_INTEN; + mv64xxx_write(drv_data, drv_data->cntl_bits + | REG_CONTROL_STOP, + drv_data->reg_offsets.control); + drv_data->block = false; + break; + } +} + +static void mv64xxx_i2c_intr(struct mv64xxx_i2c_data *drv_data) +{ + u32 status; + uint64_t start; + + start = get_time_ns(); + + while (mv64xxx_read(drv_data, drv_data->reg_offsets.control) & + REG_CONTROL_IFLG) { + status = mv64xxx_read(drv_data, drv_data->reg_offsets.status); + mv64xxx_i2c_fsm(drv_data, status); + mv64xxx_i2c_do_action(drv_data); + + if (is_timeout_non_interruptible(start, 3 * SECOND)) { + drv_data->rc = -EIO; + break; + } + } +} + +/* + ***************************************************************************** + * + * I2C Msg Execution Routines + * + ***************************************************************************** + */ +static void +mv64xxx_i2c_wait_for_completion(struct mv64xxx_i2c_data *drv_data) +{ + do { + mv64xxx_i2c_intr(drv_data); + if (drv_data->rc) { + drv_data->state = STATE_IDLE; + dev_err(&drv_data->adapter.dev, "I2C bus error\n"); + mv64xxx_i2c_hw_init(drv_data); + drv_data->block = false; + } + } while (drv_data->block); +} + +/* + ***************************************************************************** + * + * I2C Core Support Routines (Interface to higher level I2C code) + * + ***************************************************************************** + */ +static int +mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) +{ + struct mv64xxx_i2c_data *drv_data = container_of(adap, struct mv64xxx_i2c_data, adapter); + int ret = num; + + BUG_ON(drv_data->msgs != NULL); + + drv_data->msgs = msgs; + drv_data->num_msgs = num; + drv_data->state = STATE_WAITING_FOR_START_COND; + drv_data->send_stop = (num == 1); + drv_data->block = true; + mv64xxx_i2c_send_start(drv_data); + mv64xxx_i2c_wait_for_completion(drv_data); + + if (drv_data->rc < 0) + ret = drv_data->rc; + + drv_data->num_msgs = 0; + drv_data->msgs = NULL; + + return ret; +} + +/* + ***************************************************************************** + * + * Driver Interface & Early Init Routines + * + ***************************************************************************** + */ +static struct of_device_id mv64xxx_i2c_of_match_table[] = { + { .compatible = "marvell,mv64xxx-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx}, + { .compatible = "marvell,mv78230-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx}, + { .compatible = "marvell,mv78230-a0-i2c", .data = (unsigned long)&mv64xxx_i2c_regs_mv64xxx}, + {} +}; + +static inline int +mv64xxx_calc_freq(const int tclk, const int n, const int m) +{ + return tclk / (10 * (m + 1) * (2 << n)); +} + +static bool +mv64xxx_find_baud_factors(const u32 req_freq, const u32 tclk, u32 *best_n, + u32 *best_m) +{ + int freq, delta, best_delta = INT_MAX; + int m, n; + + for (n = 0; n <= 7; n++) + for (m = 0; m <= 15; m++) { + freq = mv64xxx_calc_freq(tclk, n, m); + delta = req_freq - freq; + if (delta >= 0 && delta < best_delta) { + *best_m = m; + *best_n = n; + best_delta = delta; + } + if (best_delta == 0) + return true; + } + if (best_delta == INT_MAX) + return false; + return true; +} + +static int +mv64xxx_of_config(struct mv64xxx_i2c_data *drv_data, + struct device_d *pd) +{ + struct device_node *np = pd->device_node; + u32 bus_freq, tclk; + int rc = 0; + u32 prop; + struct mv64xxx_i2c_regs *mv64xxx_regs; + int freq; + + if (IS_ERR(drv_data->clk)) { + rc = -ENODEV; + goto out; + } + tclk = clk_get_rate(drv_data->clk); + + rc = of_property_read_u32(np, "clock-frequency", &bus_freq); + if (rc) + bus_freq = 100000; /* 100kHz by default */ + + if (!mv64xxx_find_baud_factors(bus_freq, tclk, + &drv_data->freq_n, &drv_data->freq_m)) { + rc = -EINVAL; + goto out; + } + + freq = mv64xxx_calc_freq(tclk, drv_data->freq_n, drv_data->freq_m); + dev_dbg(pd, "tclk=%d freq_n=%d freq_m=%d freq=%d\n", + tclk, drv_data->freq_n, drv_data->freq_m, freq); + + if (of_property_read_u32(np, "reg-io-width", &prop)) { + /* Use 32-bit registers by default */ + prop = 4; + } + + switch (prop) { + case 1: + drv_data->write_reg = mv64xxx_writeb; + drv_data->read_reg = mv64xxx_readb; + break; + case 4: + drv_data->write_reg = mv64xxx_writel; + drv_data->read_reg = mv64xxx_readl; + break; + default: + dev_err(pd, "unsupported reg-io-width (%d)\n", prop); + rc = -EINVAL; + goto out; + } + + dev_get_drvdata(pd, (unsigned long *)&mv64xxx_regs); + memcpy(&drv_data->reg_offsets, mv64xxx_regs, + sizeof(drv_data->reg_offsets)); + + /* + * For controllers embedded in new SoCs activate the errata fix. + */ + if (of_device_is_compatible(np, "marvell,mv78230-i2c")) { + drv_data->errata_delay = true; + } + + if (of_device_is_compatible(np, "marvell,mv78230-a0-i2c")) { + drv_data->errata_delay = true; + } + +out: + return rc; +} + +static int +mv64xxx_i2c_probe(struct device_d *pd) +{ + struct mv64xxx_i2c_data *drv_data; + int rc; + + if (!pd->device_node) + return -ENODEV; + + drv_data = xzalloc(sizeof(*drv_data)); + + drv_data->reg_base = dev_request_mem_region(pd, 0); + if (IS_ERR(drv_data->reg_base)) + return PTR_ERR(drv_data->reg_base); + + drv_data->clk = clk_get(pd, NULL); + if (IS_ERR(drv_data->clk)) + return PTR_ERR(drv_data->clk); + + clk_enable(drv_data->clk); + + rc = mv64xxx_of_config(drv_data, pd); + if (rc) + goto exit_clk; + + drv_data->adapter.master_xfer = mv64xxx_i2c_xfer; + drv_data->adapter.dev.parent = pd; + drv_data->adapter.nr = pd->id; + drv_data->adapter.dev.device_node = pd->device_node; + + mv64xxx_i2c_hw_init(drv_data); + + rc = i2c_add_numbered_adapter(&drv_data->adapter); + if (rc) { + dev_err(pd, "Failed to add I2C adapter\n"); + goto exit_clk; + } + + return 0; + +exit_clk: + clk_disable(drv_data->clk); + + return rc; +} + +static struct driver_d mv64xxx_i2c_driver = { + .probe = mv64xxx_i2c_probe, + .name = "mv64xxx_i2c", + .of_compatible = DRV_OF_COMPAT(mv64xxx_i2c_of_match_table), +}; +device_platform_driver(mv64xxx_i2c_driver); diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c new file mode 100644 index 0000000000..e8aeaa7234 --- /dev/null +++ b/drivers/i2c/i2c-smbus.c @@ -0,0 +1,371 @@ +#include <common.h> +#include <errno.h> +#include <i2c/i2c.h> + +/* The SMBus parts */ + +#define POLY (0x1070U << 3) +static u8 crc8(u16 data) +{ + int i; + + for (i = 0; i < 8; i++) { + if (data & 0x8000) + data = data ^ POLY; + data = data << 1; + } + return (u8)(data >> 8); +} + +/* Incremental CRC8 over count bytes in the array pointed to by p */ +static u8 i2c_smbus_pec(u8 crc, u8 *p, size_t count) +{ + int i; + + for (i = 0; i < count; i++) + crc = crc8((crc ^ p[i]) << 8); + return crc; +} + +/* Assume a 7-bit address, which is reasonable for SMBus */ +static u8 i2c_smbus_msg_pec(u8 pec, struct i2c_msg *msg) +{ + /* The address will be sent first */ + u8 addr = (msg->addr << 1) | !!(msg->flags & I2C_M_RD); + pec = i2c_smbus_pec(pec, &addr, 1); + + /* The data buffer follows */ + return i2c_smbus_pec(pec, msg->buf, msg->len); +} + +/* Used for write only transactions */ +static inline void i2c_smbus_add_pec(struct i2c_msg *msg) +{ + msg->buf[msg->len] = i2c_smbus_msg_pec(0, msg); + msg->len++; +} + +/* Return <0 on CRC error + If there was a write before this read (most cases) we need to take the + partial CRC from the write part into account. + Note that this function does modify the message (we need to decrease the + message length to hide the CRC byte from the caller). */ +static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) +{ + u8 rpec = msg->buf[--msg->len]; + cpec = i2c_smbus_msg_pec(cpec, msg); + + if (rpec != cpec) { + pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", + rpec, cpec); + return -EBADMSG; + } + return 0; +} + +/** + * i2c_smbus_read_byte - SMBus "receive byte" protocol + * @client: Handle to slave device + * + * This executes the SMBus "receive byte" protocol, returning negative errno + * else the byte received from the device. + */ +s32 i2c_smbus_read_byte(const struct i2c_client *client) +{ + union i2c_smbus_data data; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data); + return (status < 0) ? status : data.byte; +} +EXPORT_SYMBOL(i2c_smbus_read_byte); + +/** + * i2c_smbus_write_byte - SMBus "send byte" protocol + * @client: Handle to slave device + * @value: Byte to be sent + * + * This executes the SMBus "send byte" protocol, returning negative errno + * else zero on success. + */ +s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value) +{ + return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); +} +EXPORT_SYMBOL(i2c_smbus_write_byte); + +/** + * i2c_smbus_read_byte_data - SMBus "read byte" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * + * This executes the SMBus "read byte" protocol, returning negative errno + * else a data byte received from the device. + */ +s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command) +{ + union i2c_smbus_data data; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; +} +EXPORT_SYMBOL(i2c_smbus_read_byte_data); + +/** + * i2c_smbus_write_byte_data - SMBus "write byte" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: Byte being written + * + * This executes the SMBus "write byte" protocol, returning negative errno + * else zero on success. + */ +s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, + u8 value) +{ + union i2c_smbus_data data; + data.byte = value; + return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_BYTE_DATA, &data); +} +EXPORT_SYMBOL(i2c_smbus_write_byte_data); + +/** + * i2c_smbus_read_word_data - SMBus "read word" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * + * This executes the SMBus "read word" protocol, returning negative errno + * else a 16-bit unsigned "word" received from the device. + */ +s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command) +{ + union i2c_smbus_data data; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + return (status < 0) ? status : data.word; +} +EXPORT_SYMBOL(i2c_smbus_read_word_data); + +/** + * i2c_smbus_write_word_data - SMBus "write word" protocol + * @client: Handle to slave device + * @command: Byte interpreted by slave + * @value: 16-bit "word" being written + * + * This executes the SMBus "write word" protocol, returning negative errno + * else zero on success. + */ +s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, + u16 value) +{ + union i2c_smbus_data data; + data.word = value; + return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_WORD_DATA, &data); +} +EXPORT_SYMBOL(i2c_smbus_write_word_data); + +/* Returns the number of read bytes */ +s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, u8 command, + u8 length, u8 *values) +{ + union i2c_smbus_data data; + int status; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + status = i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (status < 0) + return status; + + memcpy(values, &data.block[1], data.block[0]); + return data.block[0]; +} +EXPORT_SYMBOL(i2c_smbus_read_i2c_block_data); + +s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, u8 command, + u8 length, const u8 *values) +{ + union i2c_smbus_data data; + + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + data.block[0] = length; + memcpy(data.block + 1, values, length); + return i2c_smbus_xfer(client->adapter, client->addr, 0 /* client->flags */, + I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); +} +EXPORT_SYMBOL(i2c_smbus_write_i2c_block_data); + +/* Simulate a SMBus command using the i2c protocol + No checking of parameters is done! */ +static s32 i2c_smbus_xfer_emulated(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, + char read_write, u8 command, int size, + union i2c_smbus_data *data) +{ + /* So we need to generate a series of msgs. In the case of writing, we + need to use only one message; when reading, we need two. We initialize + most things with sane defaults, to keep the code below somewhat + simpler. */ + unsigned char msgbuf0[I2C_SMBUS_BLOCK_MAX+3]; + unsigned char msgbuf1[I2C_SMBUS_BLOCK_MAX+2]; + int num = read_write == I2C_SMBUS_READ ? 2 : 1; + int i; + u8 partial_pec = 0; + int status; + struct i2c_msg msg[2] = { + { + .addr = addr, + .flags = flags, + .len = 1, + .buf = msgbuf0, + }, { + .addr = addr, + .flags = flags | I2C_M_RD, + .len = 0, + .buf = msgbuf1, + }, + }; + + msgbuf0[0] = command; + switch (size) { + case I2C_SMBUS_QUICK: + msg[0].len = 0; + /* Special case: The read/write field is used as data */ + msg[0].flags = flags | (read_write == I2C_SMBUS_READ ? + I2C_M_RD : 0); + num = 1; + break; + case I2C_SMBUS_BYTE: + if (read_write == I2C_SMBUS_READ) { + /* Special case: only a read! */ + msg[0].flags = I2C_M_RD | flags; + num = 1; + } + break; + case I2C_SMBUS_BYTE_DATA: + if (read_write == I2C_SMBUS_READ) + msg[1].len = 1; + else { + msg[0].len = 2; + msgbuf0[1] = data->byte; + } + break; + case I2C_SMBUS_WORD_DATA: + if (read_write == I2C_SMBUS_READ) + msg[1].len = 2; + else { + msg[0].len = 3; + msgbuf0[1] = data->word & 0xff; + msgbuf0[2] = data->word >> 8; + } + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + if (read_write == I2C_SMBUS_READ) { + msg[1].len = data->block[0]; + } else { + msg[0].len = data->block[0] + 1; + if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; + } + for (i = 1; i <= data->block[0]; i++) + msgbuf0[i] = data->block[i]; + } + break; + default: + dev_err(&adapter->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; + } + + i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK + && size != I2C_SMBUS_I2C_BLOCK_DATA); + if (i) { + /* Compute PEC if first message is a write */ + if (!(msg[0].flags & I2C_M_RD)) { + if (num == 1) /* Write only */ + i2c_smbus_add_pec(&msg[0]); + else /* Write followed by read */ + partial_pec = i2c_smbus_msg_pec(0, &msg[0]); + } + /* Ask for PEC if last message is a read */ + if (msg[num-1].flags & I2C_M_RD) + msg[num-1].len++; + } + + status = i2c_transfer(adapter, msg, num); + if (status < 0) + return status; + + /* Check PEC if last message is a read */ + if (i && (msg[num-1].flags & I2C_M_RD)) { + status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); + if (status < 0) + return status; + } + + if (read_write == I2C_SMBUS_READ) + switch (size) { + case I2C_SMBUS_BYTE: + data->byte = msgbuf0[0]; + break; + case I2C_SMBUS_BYTE_DATA: + data->byte = msgbuf1[0]; + break; + case I2C_SMBUS_WORD_DATA: + data->word = msgbuf1[0] | (msgbuf1[1] << 8); + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + for (i = 0; i < data->block[0]; i++) + data->block[i+1] = msgbuf1[i]; + break; + } + return 0; +} + +/** + * i2c_smbus_xfer - execute SMBus protocol operations + * @adapter: Handle to I2C bus + * @addr: Address of SMBus slave on that bus + * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC) + * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE + * @command: Byte interpreted by slave, for protocols which use such bytes + * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL + * @data: Data to be read or written + * + * This executes an SMBus protocol operation, and returns a negative + * errno code else zero on success. + */ +s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags, + char read_write, u8 command, int protocol, + union i2c_smbus_data *data) +{ + s32 res; + + flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_CLIENT_SCCB; + + res = i2c_smbus_xfer_emulated(adapter, addr, flags, read_write, + command, protocol, data); + + return res; +} +EXPORT_SYMBOL(i2c_smbus_xfer); diff --git a/drivers/led/led-triggers.c b/drivers/led/led-triggers.c index 5eaf732764..c5484d59a5 100644 --- a/drivers/led/led-triggers.c +++ b/drivers/led/led-triggers.c @@ -124,7 +124,7 @@ int led_set_trigger(enum led_trigger trigger, struct led *led) triggers[trigger].led = led; - if (trigger == LED_TRIGGER_DEFAULT_ON) + if (led && trigger == LED_TRIGGER_DEFAULT_ON) led_set(triggers[trigger].led, triggers[trigger].led->max_value); return 0; @@ -145,7 +145,7 @@ int led_get_trigger(enum led_trigger trigger) return led_get_number(triggers[trigger].led); } -int trigger_init(void) +static int trigger_init(void) { return poller_register(&trigger_poller); } diff --git a/drivers/mtd/nand/nand_omap_gpmc.c b/drivers/mtd/nand/nand_omap_gpmc.c index 59712b8119..b1d266f4d6 100644 --- a/drivers/mtd/nand/nand_omap_gpmc.c +++ b/drivers/mtd/nand/nand_omap_gpmc.c @@ -804,8 +804,8 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, offset - omap_oobinfo.eccbytes; break; case OMAP_ECC_BCH4_CODE_HW: - oinfo->nand.ecc.bytes = 4 * 7; - oinfo->nand.ecc.size = 4 * 512; + oinfo->nand.ecc.bytes = 7; + oinfo->nand.ecc.size = 512; oinfo->nand.ecc.strength = BCH4_MAX_ERROR; omap_oobinfo.oobfree->offset = offset; omap_oobinfo.oobfree->length = minfo->oobsize - @@ -815,8 +815,8 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, omap_oobinfo.eccpos[i] = i + offset; break; case OMAP_ECC_BCH8_CODE_HW: - oinfo->nand.ecc.bytes = 4 * 13; - oinfo->nand.ecc.size = 4 * 512; + oinfo->nand.ecc.bytes = 13; + oinfo->nand.ecc.size = 512; oinfo->nand.ecc.strength = BCH8_MAX_ERROR; omap_oobinfo.oobfree->offset = offset; omap_oobinfo.oobfree->length = minfo->oobsize - @@ -826,19 +826,13 @@ static int omap_gpmc_eccmode(struct gpmc_nand_info *oinfo, omap_oobinfo.eccpos[i] = i + offset; break; case OMAP_ECC_BCH8_CODE_HW_ROMCODE: - oinfo->nand.ecc.bytes = 4 * 13; - oinfo->nand.ecc.size = 4 * 512; + oinfo->nand.ecc.bytes = 13 + 1; + oinfo->nand.ecc.size = 512; oinfo->nand.ecc.strength = BCH8_MAX_ERROR; nand->ecc.read_page = omap_gpmc_read_page_bch_rom_mode; omap_oobinfo.oobfree->length = 0; j = 0; - for (i = 2; i < 15; i++) - omap_oobinfo.eccpos[j++] = i; - for (i = 16; i < 29; i++) - omap_oobinfo.eccpos[j++] = i; - for (i = 30; i < 43; i++) - omap_oobinfo.eccpos[j++] = i; - for (i = 44; i < 57; i++) + for (i = 2; i < 58; i++) omap_oobinfo.eccpos[j++] = i; break; case OMAP_ECC_SOFT: diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ffce40a506..c99fcc8316 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -174,6 +174,10 @@ config DRIVER_NET_TAP bool "tap Ethernet driver" depends on LINUX +config DRIVER_NET_EFI_SNP + bool "EFI SNP ethernet driver" + depends on ARCH_EFI + config DRIVER_NET_TSE depends on NIOS2 bool "Altera TSE ethernet driver" diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 33bb5c8fa0..1b85778f9f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -26,3 +26,4 @@ obj-$(CONFIG_DRIVER_NET_SMC911X) += smc911x.o obj-$(CONFIG_DRIVER_NET_SMC91111) += smc91111.o obj-$(CONFIG_DRIVER_NET_TAP) += tap.o obj-$(CONFIG_DRIVER_NET_TSE) += altera_tse.o +obj-$(CONFIG_DRIVER_NET_EFI_SNP) += efi-snp.o diff --git a/drivers/net/efi-snp.c b/drivers/net/efi-snp.c new file mode 100644 index 0000000000..5b96fbf462 --- /dev/null +++ b/drivers/net/efi-snp.c @@ -0,0 +1,296 @@ +/* + * efi-snp.c - Simple Network Protocol driver for EFI + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <driver.h> +#include <malloc.h> +#include <net.h> +#include <init.h> +#include <efi.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +struct efi_network_statistics { + uint64_t RxTotalFrames; + uint64_t RxGoodFrames; + uint64_t RxUndersizeFrames; + uint64_t RxOversizeFrames; + uint64_t RxDroppedFrames; + uint64_t RxUnicastFrames; + uint64_t RxBroadcastFrames; + uint64_t RxMulticastFrames; + uint64_t RxCrcErrorFrames; + uint64_t RxTotalBytes; + uint64_t TxTotalFrames; + uint64_t TxGoodFrames; + uint64_t TxUndersizeFrames; + uint64_t TxOversizeFrames; + uint64_t TxDroppedFrames; + uint64_t TxUnicastFrames; + uint64_t TxBroadcastFrames; + uint64_t TxMulticastFrames; + uint64_t TxCrcErrorFrames; + uint64_t TxTotalBytes; + uint64_t Collisions; + uint64_t UnsupportedProtocol; +}; + +enum efi_simple_network_state { + EfiSimpleNetworkStopped, + EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, + EfiSimpleNetworkMaxState +}; + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 + +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + +#define MAX_MCAST_FILTER_CNT 16 +struct efi_simple_network_mode { + uint32_t State; + uint32_t HwAddressSize; + uint32_t MediaHeaderSize; + uint32_t MaxPacketSize; + uint32_t NvRamSize; + uint32_t NvRamAccessSize; + uint32_t ReceiveFilterMask; + uint32_t ReceiveFilterSetting; + uint32_t MaxMCastFilterCount; + uint32_t MCastFilterCount; + efi_mac_address MCastFilter[MAX_MCAST_FILTER_CNT]; + efi_mac_address CurrentAddress; + efi_mac_address BroadcastAddress; + efi_mac_address PermanentAddress; + uint8_t IfType; + bool MacAddressChangeable; + bool MultipleTxSupported; + bool MediaPresentSupported; + bool MediaPresent; +}; + +#define EFI_SIMPLE_NETWORK_INTERFACE_REVISION 0x00010000 + +struct efi_simple_network { + uint64_t Revision; + efi_status_t (EFIAPI *start) (struct efi_simple_network *This); + efi_status_t (EFIAPI *stop) (struct efi_simple_network *This); + efi_status_t (EFIAPI *initialize) (struct efi_simple_network *This, + unsigned long ExtraRxBufferSize, unsigned long ExtraTxBufferSize); + efi_status_t (EFIAPI *reset) (struct efi_simple_network *This, bool ExtendedVerification); + efi_status_t (EFIAPI *shutdown) (struct efi_simple_network *This); + efi_status_t (EFIAPI *receive_filters) (struct efi_simple_network *This, + uint32_t Enable, uint32_t Disable, bool ResetMCastFilter, + unsigned long MCastFilterCnt, efi_mac_address *MCastFilter); + efi_status_t (EFIAPI *station_address) (struct efi_simple_network *This, + bool Reset, efi_mac_address *New); + efi_status_t (EFIAPI *statistics) (struct efi_simple_network *This, + bool Reset, unsigned long *StatisticsSize, + struct efi_network_statistics *StatisticsTable); + efi_status_t (EFIAPI *mcast_ip_to_mac) (struct efi_simple_network *This, + bool IPv6, efi_ip_address *IP, efi_mac_address *MAC); + efi_status_t (EFIAPI *nvdata) (struct efi_simple_network *This, + bool ReadWrite, unsigned long Offset, unsigned long BufferSize, + void *Buffer); + efi_status_t (EFIAPI *get_status) (struct efi_simple_network *This, + uint32_t *InterruptStatus, void **TxBuf); + efi_status_t (EFIAPI *transmit) (struct efi_simple_network *This, + unsigned long HeaderSize, unsigned long BufferSize, void *Buffer, + efi_mac_address *SrcAddr, efi_mac_address *DestAddr, + uint16_t *Protocol); + efi_status_t (EFIAPI *receive) (struct efi_simple_network *This, + unsigned long *HeaderSize, unsigned long *BufferSize, void *Buffer, + efi_mac_address *SrcAddr, efi_mac_address *DestAddr, uint16_t *Protocol); + void *WaitForPacket; + struct efi_simple_network_mode *Mode; +}; + +struct efi_snp_priv { + struct device_d *dev; + struct eth_device edev; + struct efi_simple_network *snp; +}; + +static inline struct efi_snp_priv *to_priv(struct eth_device *edev) +{ + return container_of(edev, struct efi_snp_priv, edev); +} + +static int efi_snp_eth_send(struct eth_device *edev, void *packet, int length) +{ + struct efi_snp_priv *priv = to_priv(edev); + efi_status_t efiret; + void *txbuf; + uint64_t start; + + efiret = priv->snp->transmit(priv->snp, 0, length, packet, NULL, NULL, NULL); + if (EFI_ERROR(efiret)) { + dev_err(priv->dev, "failed to send: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret); + } + + start = get_time_ns(); + + while (!is_timeout(start, SECOND)) { + uint32_t irq; + priv->snp->get_status(priv->snp, &irq, &txbuf); + if (txbuf) + return 0; + } + + dev_err(priv->dev, "tx time out\n"); + + return -ETIMEDOUT; +} + +static int efi_snp_eth_rx(struct eth_device *edev) +{ + struct efi_snp_priv *priv = to_priv(edev); + long bufsize = PKTSIZE; + efi_status_t efiret; + + efiret = priv->snp->receive(priv->snp, NULL, &bufsize, NetRxPackets[0], NULL, NULL, NULL); + if (efiret == EFI_NOT_READY) + return 0; + + if (EFI_ERROR(efiret)) { + dev_err(priv->dev, "failed to receive: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret); + } + + net_receive(edev, NetRxPackets[0], bufsize); + + return 0; +} + +static int efi_snp_eth_open(struct eth_device *edev) +{ + struct efi_snp_priv *priv = to_priv(edev); + uint32_t mask; + efi_status_t efiret; + + priv->snp->shutdown(priv->snp); + priv->snp->stop(priv->snp); + priv->snp->start(priv->snp); + efiret = priv->snp->initialize(priv->snp, 0, 0); + if (EFI_ERROR(efiret)) { + dev_err(priv->dev, "Initialize failed with: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret); + } + + efiret = priv->snp->station_address(priv->snp, false, + (efi_mac_address *)priv->snp->Mode->PermanentAddress.Addr ); + if (EFI_ERROR(efiret)) { + dev_err(priv->dev, "failed to set MAC address: %s\n", + efi_strerror(efiret)); + return -efi_errno(efiret); + } + + mask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST | + EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST | + EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; + efiret = priv->snp->receive_filters(priv->snp, mask, 0, 0, 0, 0); + if (EFI_ERROR(efiret)) { + dev_err(priv->dev, "failed to set receive filters: %s\n", + efi_strerror(efiret)); + return -efi_errno(efiret); + } + + return 0; +} + +static void efi_snp_eth_halt(struct eth_device *edev) +{ + struct efi_snp_priv *priv = to_priv(edev); + + priv->snp->stop(priv->snp); +} + +static int efi_snp_get_ethaddr(struct eth_device *edev, unsigned char *adr) +{ + struct efi_snp_priv *priv = to_priv(edev); + + memcpy(adr, priv->snp->Mode->PermanentAddress.Addr, 6); + + return 0; +} + +static int efi_snp_set_ethaddr(struct eth_device *edev, unsigned char *adr) +{ + return 0; +} + +int efi_snp_probe(struct efi_device *efidev) +{ + struct eth_device *edev; + struct efi_snp_priv *priv; + int ret; + + dev_dbg(&efidev->dev, "efi_snp_probe\n"); + + priv = xzalloc(sizeof(struct efi_snp_priv)); + priv->snp = efidev->protocol; + priv->dev = &efidev->dev; + + dev_dbg(&efidev->dev, "perm: %02x:%02x:%02x:%02x:%02x:%02x\n", + priv->snp->Mode->PermanentAddress.Addr[0], + priv->snp->Mode->PermanentAddress.Addr[1], + priv->snp->Mode->PermanentAddress.Addr[2], + priv->snp->Mode->PermanentAddress.Addr[3], + priv->snp->Mode->PermanentAddress.Addr[4], + priv->snp->Mode->PermanentAddress.Addr[5]); + dev_dbg(&efidev->dev, "curr: %02x:%02x:%02x:%02x:%02x:%02x\n", + priv->snp->Mode->CurrentAddress.Addr[0], + priv->snp->Mode->CurrentAddress.Addr[1], + priv->snp->Mode->CurrentAddress.Addr[2], + priv->snp->Mode->CurrentAddress.Addr[3], + priv->snp->Mode->CurrentAddress.Addr[4], + priv->snp->Mode->CurrentAddress.Addr[5]); + + edev = &priv->edev; + edev->priv = priv; + edev->parent = &efidev->dev; + + edev->open = efi_snp_eth_open; + edev->send = efi_snp_eth_send; + edev->recv = efi_snp_eth_rx; + edev->halt = efi_snp_eth_halt; + edev->get_ethaddr = efi_snp_get_ethaddr; + edev->set_ethaddr = efi_snp_set_ethaddr; + + ret = eth_register(edev); + + return ret; +} + +static struct efi_driver efi_snp_driver = { + .driver = { + .name = "efi-snp", + }, + .probe = efi_snp_probe, + .guid = EFI_SIMPLE_NETWORK_PROTOCOL_GUID, +}; +device_efi_driver(efi_snp_driver); diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 45f77a759f..81955063d7 100644 --- a/drivers/of/Kconfig +++ b/drivers/of/Kconfig @@ -4,7 +4,7 @@ config OFTREE config OFTREE_MEM_GENERIC depends on OFTREE - depends on PPC || ARM + depends on PPC || ARM || ARCH_EFI def_bool y config DTC @@ -27,6 +27,12 @@ config OF_GPIO depends on OFDEVICE def_bool y +config OF_PCI + bool + depends on PCI + help + OpenFirmware PCI bus accessors + config OF_BAREBOX_DRIVERS depends on OFDEVICE depends on ENV_HANDLING diff --git a/drivers/of/Makefile b/drivers/of/Makefile index c883e516c8..0dc2f8d63e 100644 --- a/drivers/of/Makefile +++ b/drivers/of/Makefile @@ -1,6 +1,7 @@ obj-y += address.o base.o fdt.o platform.o obj-$(CONFIG_OFTREE_MEM_GENERIC) += mem_generic.o obj-$(CONFIG_OF_GPIO) += of_gpio.o +obj-$(CONFIG_OF_PCI) += of_pci.o obj-y += partition.o obj-y += of_net.o obj-$(CONFIG_MTD) += of_mtd.o diff --git a/drivers/of/of_pci.c b/drivers/of/of_pci.c new file mode 100644 index 0000000000..2d0fbd2e5f --- /dev/null +++ b/drivers/of/of_pci.c @@ -0,0 +1,27 @@ +#include <common.h> +#include <errno.h> +#include <of.h> +#include <of_pci.h> + +/** + * of_pci_get_devfn() - Get device and function numbers for a device node + * @np: device node + * + * Parses a standard 5-cell PCI resource and returns an 8-bit value that can + * be passed to the PCI_SLOT() and PCI_FUNC() macros to extract the device + * and function numbers respectively. On error a negative error code is + * returned. + */ +int of_pci_get_devfn(struct device_node *np) +{ + unsigned int size; + const __be32 *reg; + + reg = of_get_property(np, "reg", &size); + + if (!reg || size < 5 * sizeof(__be32)) + return -EINVAL; + + return (be32_to_cpup(reg) >> 8) & 0xff; +} +EXPORT_SYMBOL_GPL(of_pci_get_devfn); diff --git a/drivers/of/partition.c b/drivers/of/partition.c index e2ddec564e..3dce84404f 100644 --- a/drivers/of/partition.c +++ b/drivers/of/partition.c @@ -21,6 +21,7 @@ #include <of.h> #include <malloc.h> #include <linux/mtd/mtd.h> +#include <linux/err.h> #include <nand.h> struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) @@ -60,6 +61,9 @@ struct cdev *of_parse_partition(struct cdev *cdev, struct device_node *node) filename = asprintf("%s.%s", cdev->name, partname); new = devfs_add_partition(cdev->name, offset, size, flags, filename); + if (IS_ERR(new)) + new = NULL; + if (new && new->dev) new->dev->device_node = node; diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 72e75cc079..c417cfdcd9 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -183,7 +183,8 @@ static struct device_d *of_platform_device_create(struct device_node *np, dev->num_resources = num_reg; of_device_make_bus_id(dev); - debug("%s: register device %s, io=0x%08x\n", __func__, dev_name(dev), + debug("%s: register device %s, io=" PRINTF_CONVERSION_RESOURCE "\n", + __func__, dev_name(dev), (num_reg) ? dev->resource[0].start : (-1)); ret = platform_device_register(dev); diff --git a/drivers/pci/Kconfig b/drivers/pci/Kconfig index 9e4659270d..d17a151082 100644 --- a/drivers/pci/Kconfig +++ b/drivers/pci/Kconfig @@ -24,6 +24,12 @@ config PCI_DEBUG When in doubt, say N. +config PCI_MVEBU + bool "Marvell EBU PCIe driver" + depends on ARCH_MVEBU + select OF_PCI + select PCI + endmenu endif diff --git a/drivers/pci/Makefile b/drivers/pci/Makefile index edac1a53de..442353173c 100644 --- a/drivers/pci/Makefile +++ b/drivers/pci/Makefile @@ -6,3 +6,5 @@ obj-y += pci.o bus.o pci_iomap.o ccflags-$(CONFIG_PCI_DEBUG) := -DDEBUG CPPFLAGS += $(ccflags-y) + +obj-$(CONFIG_PCI_MVEBU) += pci-mvebu.o pci-mvebu-phy.o diff --git a/drivers/pci/pci-mvebu-phy.c b/drivers/pci/pci-mvebu-phy.c new file mode 100644 index 0000000000..55a1d39f62 --- /dev/null +++ b/drivers/pci/pci-mvebu-phy.c @@ -0,0 +1,208 @@ +/* + * SoC specific PCIe PHY setup for Marvell MVEBU SoCs + * + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> + * + * based on Marvell BSP code (C) Marvell International Ltd. + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <common.h> +#include <of.h> +#include <of_address.h> + +#include "pci-mvebu.h" + +static u32 mvebu_pcie_phy_indirect(void __iomem *phybase, u8 lane, + u8 off, u16 val, bool is_read) +{ + u32 reg = (lane << 24) | (off << 16) | val; + + if (is_read) + reg |= BIT(31); + writel(reg, phybase); + + return (is_read) ? readl(phybase) & 0xffff : 0; +} + +static inline u32 mvebu_pcie_phy_read(void __iomem *phybase, u8 lane, + u8 off) +{ + return mvebu_pcie_phy_indirect(phybase, lane, off, 0, true); +} + +static inline void mvebu_pcie_phy_write(void __iomem *phybase, u8 lane, + u8 off, u16 val) +{ + mvebu_pcie_phy_indirect(phybase, lane, off, val, false); +} + +/* PCIe registers */ +#define ARMADA_370_XP_PCIE_LINK_CAPS 0x6c +#define MAX_LINK_WIDTH_MASK MAX_LINK_WIDTH(0x3f) +#define MAX_LINK_WIDTH(x) ((x) << 4) +#define MAX_LINK_SPEED_MASK 0xf +#define MAX_LINK_SPEED_5G0 0x2 +#define MAX_LINK_SPEED_2G5 0x1 +#define ARMADA_370_XP_PHY_OFFSET 0x1b00 +/* System Control registers */ +#define ARMADA_370_XP_SOC_CTRL 0x04 +#define PCIE1_QUADX1_EN BIT(8) /* Armada XP */ +#define PCIE0_QUADX1_EN BIT(7) /* Armada XP */ +#define PCIE0_EN BIT(0) +#define ARMADA_370_XP_SERDES03_SEL 0x70 +#define ARMADA_370_XP_SERDES47_SEL 0x74 +#define SERDES(x, v) ((v) << ((x) * 0x4)) +#define SERDES_MASK(x) SERDES((x), 0xf) + +int armada_370_phy_setup(struct mvebu_pcie *pcie) +{ + struct device_node *np = of_find_compatible_node(NULL, NULL, + "marvell,armada-370-xp-system-controller"); + void __iomem *sysctrl = of_iomap(np, 0); + void __iomem *phybase = pcie->base + ARMADA_370_XP_PHY_OFFSET; + u32 reg; + + if (!sysctrl) + return -ENODEV; + + /* Enable PEX */ + reg = readl(sysctrl + ARMADA_370_XP_SOC_CTRL); + reg |= PCIE0_EN << pcie->port; + writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL); + + /* Set SERDES selector */ + reg = readl(sysctrl + ARMADA_370_XP_SERDES03_SEL); + reg &= ~SERDES_MASK(pcie->port); + reg |= SERDES(pcie->port, 0x1); + writel(reg, sysctrl + ARMADA_370_XP_SERDES03_SEL); + + /* BTS #232 - PCIe clock (undocumented) */ + writel(0x00000077, sysctrl + 0x2f0); + + /* Set x1 Link Capability */ + reg = readl(pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS); + reg &= ~(MAX_LINK_WIDTH_MASK | MAX_LINK_SPEED_MASK); + reg |= MAX_LINK_WIDTH(0x1) | MAX_LINK_SPEED_5G0; + writel(reg, pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS); + + /* PEX pipe configuration */ + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xd0, 0x0100); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xd1, 0x3014); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc5, 0x011f); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x80, 0x1000); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x81, 0x0011); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x0f, 0x2a21); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x45, 0x00df); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x4f, 0x6219); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000); + + reg = mvebu_pcie_phy_read(phybase, pcie->lane, 0x48) & ~0x4; + mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, reg & 0xffff); + + mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024); + + mdelay(15); + + return 0; +} + +/* + * MV78230: 2 PCIe units Gen2.0, one unit 1x4 or 4x1, one unit 1x1 + * MV78260: 3 PCIe units Gen2.0, two units 1x4 or 4x1, one unit 1x1/1x4 + * MV78460: 4 PCIe units Gen2.0, two units 1x4 or 4x1, two units 1x1/1x4 + */ +#define ARMADA_XP_COMM_PHY_REFCLK_ALIGN 0xf8 +#define REFCLK_ALIGN(x) (0xf << ((x) * 0x4)) +int armada_xp_phy_setup(struct mvebu_pcie *pcie) +{ + struct device_node *np = of_find_compatible_node(NULL, NULL, + "marvell,armada-370-xp-system-controller"); + void __iomem *sysctrl = of_iomap(np, 0); + void __iomem *phybase = pcie->base + ARMADA_370_XP_PHY_OFFSET; + u32 serdes_off = (pcie->port < 2) ? ARMADA_370_XP_SERDES03_SEL : + ARMADA_370_XP_SERDES47_SEL; + bool single_x4 = (pcie->lane_mask == 0xf); + u32 reg, mask; + + if (!sysctrl) + return -ENODEV; + + /* Prepare PEX */ + reg = readl(sysctrl + ARMADA_370_XP_SOC_CTRL); + reg &= ~(PCIE0_EN << pcie->port); + writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL); + + if (pcie->port < 2) { + mask = PCIE0_QUADX1_EN << pcie->port; + if (single_x4) + reg &= ~mask; + else + reg |= mask; + } + reg |= PCIE0_EN << pcie->port; + writel(reg, sysctrl + ARMADA_370_XP_SOC_CTRL); + + /* Set SERDES selector */ + reg = readl(sysctrl + serdes_off); + for (mask = pcie->lane_mask; mask;) { + u32 l = ffs(mask)-1; + u32 off = 4 * (pcie->port % 2); + reg &= ~SERDES_MASK(off + l); + reg |= SERDES(off + l, 0x1); + mask &= ~BIT(l); + } + reg &= ~SERDES_MASK(pcie->port % 2); + reg |= SERDES(pcie->port % 2, 0x1); + writel(reg, sysctrl + serdes_off); + + /* Reference Clock Alignment for 1x4 */ + reg = readl(sysctrl + ARMADA_XP_COMM_PHY_REFCLK_ALIGN); + if (single_x4) + reg |= REFCLK_ALIGN(pcie->port); + else + reg &= ~REFCLK_ALIGN(pcie->port); + writel(reg, sysctrl + ARMADA_XP_COMM_PHY_REFCLK_ALIGN); + + /* Set x1/x4 Link Capability */ + reg = readl(pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS); + reg &= ~(MAX_LINK_WIDTH_MASK | MAX_LINK_SPEED_MASK); + if (single_x4) + reg |= MAX_LINK_WIDTH(0x4); + else + reg |= MAX_LINK_WIDTH(0x1); + reg |= MAX_LINK_SPEED_5G0; + writel(reg, pcie->base + ARMADA_370_XP_PCIE_LINK_CAPS); + + /* PEX pipe configuration */ + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0025); + if (single_x4) { + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc2, 0x0200); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x0001); + } else { + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc2, 0x0000); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc3, 0x000f); + } + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc8, 0x0005); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x01, 0xfc60); + mvebu_pcie_phy_write(phybase, pcie->lane, 0x46, 0x0000); + + mvebu_pcie_phy_write(phybase, pcie->lane, 0x02, 0x0040); + mvebu_pcie_phy_write(phybase, pcie->lane, 0xc1, 0x0024); + if (single_x4) + mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, 0x1080); + else + mvebu_pcie_phy_write(phybase, pcie->lane, 0x48, 0x9080); + + mdelay(15); + + return 0; +} diff --git a/drivers/pci/pci-mvebu.c b/drivers/pci/pci-mvebu.c new file mode 100644 index 0000000000..45befbba20 --- /dev/null +++ b/drivers/pci/pci-mvebu.c @@ -0,0 +1,446 @@ +/* + * PCIe driver for Marvell MVEBU SoCs + * + * Based on Linux drivers/pci/host/pci-mvebu.c + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#include <common.h> +#include <gpio.h> +#include <init.h> +#include <io.h> +#include <linux/clk.h> +#include <linux/err.h> +#include <linux/mbus.h> +#include <linux/pci_regs.h> +#include <malloc.h> +#include <of_address.h> +#include <of_gpio.h> +#include <of_pci.h> +#include <sizes.h> + +#include "pci-mvebu.h" + +/* PCIe unit register offsets */ +#define PCIE_DEV_ID_OFF 0x0000 +#define PCIE_CMD_OFF 0x0004 +#define PCIE_DEV_REV_OFF 0x0008 +#define PCIE_BAR_LO_OFF(n) (0x0010 + ((n) << 3)) +#define PCIE_BAR_HI_OFF(n) (0x0014 + ((n) << 3)) +#define PCIE_HEADER_LOG_4_OFF 0x0128 +#define PCIE_BAR_CTRL_OFF(n) (0x1804 + (((n) - 1) * 4)) +#define PCIE_WIN04_CTRL_OFF(n) (0x1820 + ((n) << 4)) +#define PCIE_WIN04_BASE_OFF(n) (0x1824 + ((n) << 4)) +#define PCIE_WIN04_REMAP_OFF(n) (0x182c + ((n) << 4)) +#define PCIE_WIN5_CTRL_OFF 0x1880 +#define PCIE_WIN5_BASE_OFF 0x1884 +#define PCIE_WIN5_REMAP_OFF 0x188c +#define PCIE_CONF_ADDR_OFF 0x18f8 +#define PCIE_CONF_ADDR_EN BIT(31) +#define PCIE_CONF_REG(r) ((((r) & 0xf00) << 16) | ((r) & 0xfc)) +#define PCIE_CONF_BUS(b) (((b) & 0xff) << 16) +#define PCIE_CONF_DEV(d) (((d) & 0x1f) << 11) +#define PCIE_CONF_FUNC(f) (((f) & 0x7) << 8) +#define PCIE_CONF_ADDR(bus, devfn, where) \ + (PCIE_CONF_BUS(bus) | PCIE_CONF_DEV(PCI_SLOT(devfn)) | \ + PCIE_CONF_FUNC(PCI_FUNC(devfn)) | PCIE_CONF_REG(where) | \ + PCIE_CONF_ADDR_EN) +#define PCIE_CONF_DATA_OFF 0x18fc +#define PCIE_MASK_OFF 0x1910 +#define PCIE_MASK_ENABLE_INTS (0xf << 24) +#define PCIE_CTRL_OFF 0x1a00 +#define PCIE_CTRL_X1_MODE BIT(0) +#define PCIE_STAT_OFF 0x1a04 +#define PCIE_STAT_BUS (0xff << 8) +#define PCIE_STAT_DEV (0x1f << 16) +#define PCIE_STAT_LINK_DOWN BIT(0) +#define PCIE_DEBUG_CTRL 0x1a60 +#define PCIE_DEBUG_SOFT_RESET BIT(20) + +#define to_pcie(_hc) container_of(_hc, struct mvebu_pcie, pci) + +/* + * MVEBU PCIe controller needs MEMORY and I/O BARs to be mapped + * into SoCs address space. Each controller will map 32M of MEM + * and 64K of I/O space when registered. + */ +static void __iomem *mvebu_pcie_membase = IOMEM(0xe0000000); +static void __iomem *mvebu_pcie_iobase = IOMEM(0xffe00000); + +static inline bool mvebu_pcie_link_up(struct mvebu_pcie *pcie) +{ + return !(readl(pcie->base + PCIE_STAT_OFF) & PCIE_STAT_LINK_DOWN); +} + +static void mvebu_pcie_set_local_bus_nr(struct pci_controller *host, int busno) +{ + struct mvebu_pcie *pcie = to_pcie(host); + u32 stat; + + stat = readl(pcie->base + PCIE_STAT_OFF); + stat &= ~PCIE_STAT_BUS; + stat |= busno << 8; + writel(stat, pcie->base + PCIE_STAT_OFF); +} + +static void mvebu_pcie_set_local_dev_nr(struct mvebu_pcie *pcie, int devno) +{ + u32 stat; + + stat = readl(pcie->base + PCIE_STAT_OFF); + stat &= ~PCIE_STAT_DEV; + stat |= devno << 16; + writel(stat, pcie->base + PCIE_STAT_OFF); +} + +static int mvebu_pcie_indirect_rd_conf(struct pci_bus *bus, + unsigned int devfn, int where, int size, u32 *val) +{ + struct mvebu_pcie *pcie = to_pcie(bus->host); + + /* Skip all requests not directed to device behind bridge */ + if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie)) { + *val = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + writel(PCIE_CONF_ADDR(bus->number, devfn, where), + pcie->base + PCIE_CONF_ADDR_OFF); + + *val = readl(pcie->base + PCIE_CONF_DATA_OFF); + + if (size == 1) + *val = (*val >> (8 * (where & 3))) & 0xff; + else if (size == 2) + *val = (*val >> (8 * (where & 3))) & 0xffff; + + return PCIBIOS_SUCCESSFUL; +} + +static int mvebu_pcie_indirect_wr_conf(struct pci_bus *bus, + unsigned int devfn, int where, int size, u32 val) +{ + struct mvebu_pcie *pcie = to_pcie(bus->host); + u32 _val, shift = 8 * (where & 3); + + /* Skip all requests not directed to device behind bridge */ + if (devfn != pcie->devfn || !mvebu_pcie_link_up(pcie)) + return PCIBIOS_DEVICE_NOT_FOUND; + + writel(PCIE_CONF_ADDR(bus->number, devfn, where), + pcie->base + PCIE_CONF_ADDR_OFF); + _val = readl(pcie->base + PCIE_CONF_DATA_OFF); + + if (size == 4) + _val = val; + else if (size == 2) + _val = (_val & ~(0xffff << shift)) | ((val & 0xffff) << shift); + else if (size == 1) + _val = (_val & ~(0xff << shift)) | ((val & 0xff) << shift); + else + return PCIBIOS_BAD_REGISTER_NUMBER; + + writel(_val, pcie->base + PCIE_CONF_DATA_OFF); + + return PCIBIOS_SUCCESSFUL; +} + +static int mvebu_pcie_res_start(struct pci_bus *bus, resource_size_t res_addr) +{ + struct mvebu_pcie *pcie = to_pcie(bus->host); + + return (int)pcie->membase + (res_addr & (resource_size(&pcie->mem)-1)); +} + +static struct pci_ops mvebu_pcie_indirect_ops = { + .read = mvebu_pcie_indirect_rd_conf, + .write = mvebu_pcie_indirect_wr_conf, + .res_start = mvebu_pcie_res_start, +}; + +/* + * Setup PCIE BARs and Address Decode Wins: + * BAR[0,2] -> disabled, BAR[1] -> covers all DRAM banks + * WIN[0-3] -> DRAM bank[0-3] + */ +static void mvebu_pcie_setup_wins(struct mvebu_pcie *pcie) +{ + const struct mbus_dram_target_info *dram = mvebu_mbus_dram_info(); + u32 size; + int i; + + /* First, disable and clear BARs and windows. */ + for (i = 1; i < 3; i++) { + writel(0, pcie->base + PCIE_BAR_CTRL_OFF(i)); + writel(0, pcie->base + PCIE_BAR_LO_OFF(i)); + writel(0, pcie->base + PCIE_BAR_HI_OFF(i)); + } + + for (i = 0; i < 5; i++) { + writel(0, pcie->base + PCIE_WIN04_CTRL_OFF(i)); + writel(0, pcie->base + PCIE_WIN04_BASE_OFF(i)); + writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); + } + + writel(0, pcie->base + PCIE_WIN5_CTRL_OFF); + writel(0, pcie->base + PCIE_WIN5_BASE_OFF); + writel(0, pcie->base + PCIE_WIN5_REMAP_OFF); + + /* Setup windows for DDR banks. Count total DDR size on the fly. */ + size = 0; + for (i = 0; i < dram->num_cs; i++) { + const struct mbus_dram_window *cs = dram->cs + i; + + writel(cs->base & 0xffff0000, + pcie->base + PCIE_WIN04_BASE_OFF(i)); + writel(0, pcie->base + PCIE_WIN04_REMAP_OFF(i)); + writel(((cs->size - 1) & 0xffff0000) | + (cs->mbus_attr << 8) | + (dram->mbus_dram_target_id << 4) | 1, + pcie->base + PCIE_WIN04_CTRL_OFF(i)); + + size += cs->size; + } + + /* Round up 'size' to the nearest power of two. */ + if ((size & (size - 1)) != 0) + size = 1 << fls(size); + + /* Setup BAR[1] to all DRAM banks. */ + writel(dram->cs[0].base, pcie->base + PCIE_BAR_LO_OFF(1)); + writel(0, pcie->base + PCIE_BAR_HI_OFF(1)); + writel(((size - 1) & 0xffff0000) | 1, + pcie->base + PCIE_BAR_CTRL_OFF(1)); +} + +#define DT_FLAGS_TO_TYPE(flags) (((flags) >> 24) & 0x03) +#define DT_TYPE_IO 0x1 +#define DT_TYPE_MEM32 0x2 +#define DT_CPUADDR_TO_TARGET(cpuaddr) (((cpuaddr) >> 56) & 0xFF) +#define DT_CPUADDR_TO_ATTR(cpuaddr) (((cpuaddr) >> 48) & 0xFF) + +static int mvebu_get_target_attr(struct device_node *np, int devfn, + unsigned long type, unsigned int *target, unsigned int *attr) +{ + const int na = 3, ns = 2; + const __be32 *range; + int rlen, nranges, rangesz, pna, i; + + *target = -1; + *attr = -1; + + range = of_get_property(np, "ranges", &rlen); + if (!range) + return -EINVAL; + + pna = of_n_addr_cells(np); + rangesz = pna + na + ns; + nranges = rlen / sizeof(__be32) / rangesz; + + for (i = 0; i < nranges; i++) { + u32 flags = of_read_number(range, 1); + u32 slot = of_read_number(range + 1, 1); + u64 cpuaddr = of_read_number(range + na, pna); + unsigned long rtype; + + if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_IO) + rtype = IORESOURCE_IO; + else if (DT_FLAGS_TO_TYPE(flags) == DT_TYPE_MEM32) + rtype = IORESOURCE_MEM; + + if (slot == PCI_SLOT(devfn) && type == rtype) { + *target = DT_CPUADDR_TO_TARGET(cpuaddr); + *attr = DT_CPUADDR_TO_ATTR(cpuaddr); + return 0; + } + + range += rangesz; + } + + return -ENOENT; +} + +static struct mvebu_pcie *mvebu_pcie_port_probe(struct device_d *dev, + struct device_node *np) +{ + struct mvebu_pcie *pcie; + struct clk *clk; + enum of_gpio_flags flags; + struct property *prop; + const __be32 *p; + int reset_gpio; + u32 u, port, lane, lane_mask, devfn; + int mem_target, mem_attr; + int io_target, io_attr; + int ret; + + if (of_property_read_u32(np, "marvell,pcie-port", &port)) { + dev_err(dev, "missing pcie-port property\n"); + return ERR_PTR(-EINVAL); + } + + lane_mask = 0; + of_property_for_each_u32(np, "marvell,pcie-lane", prop, p, u) + lane_mask |= BIT(u); + lane = ffs(lane_mask)-1; + + devfn = of_pci_get_devfn(np); + if (devfn < 0) { + dev_err(dev, "unable to parse devfn\n"); + return ERR_PTR(-EINVAL); + } + + if (mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_MEM, + &mem_target, &mem_attr)) { + dev_err(dev, "unable to get target/attr for mem window\n"); + return ERR_PTR(-EINVAL); + } + + /* I/O windows are optional */ + mvebu_get_target_attr(dev->device_node, devfn, IORESOURCE_IO, + &io_target, &io_attr); + + reset_gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags); + if (gpio_is_valid(reset_gpio)) { + int reset_active_low = flags & OF_GPIO_ACTIVE_LOW; + char *reset_name = asprintf("pcie%d.%d-reset", port, lane); + u32 reset_udelay = 20000; + + of_property_read_u32(np, "reset-delay-us", &reset_udelay); + + ret = gpio_request_one(reset_gpio, GPIOF_DIR_OUT, reset_name); + if (ret) + return ERR_PTR(ret); + + /* Ensure a full reset cycle*/ + gpio_set_value(reset_gpio, 1 ^ reset_active_low); + udelay(reset_udelay); + gpio_set_value(reset_gpio, 0 ^ reset_active_low); + udelay(reset_udelay); + } + + pcie = xzalloc(sizeof(*pcie)); + pcie->port = port; + pcie->lane = lane; + pcie->lane_mask = lane_mask; + pcie->name = asprintf("pcie%d.%d", port, lane); + pcie->devfn = devfn; + + pcie->base = of_iomap(np, 0); + if (!pcie->base) { + dev_err(dev, "PCIe%d.%d unable to map registers\n", port, lane); + free(pcie); + return ERR_PTR(-ENOMEM); + } + + pcie->membase = mvebu_pcie_membase; + pcie->mem.start = (u32)mvebu_pcie_membase; + pcie->mem.end = pcie->mem.start + SZ_32M - 1; + if (mvebu_mbus_add_window_remap_by_id(mem_target, mem_attr, + (resource_size_t)pcie->membase, resource_size(&pcie->mem), + (u32)pcie->mem.start)) { + dev_err(dev, "PCIe%d.%d unable to add mbus window for mem at %08x+%08x", + port, lane, (u32)pcie->mem.start, resource_size(&pcie->mem)); + + free(pcie); + return ERR_PTR(-EBUSY); + } + mvebu_pcie_membase += SZ_32M; + + if (io_target >= 0 && io_attr >= 0) { + pcie->iobase = mvebu_pcie_iobase; + pcie->io.start = (u32)mvebu_pcie_iobase; + pcie->io.end = pcie->io.start + SZ_64K - 1; + + mvebu_mbus_add_window_remap_by_id(io_target, io_attr, + (resource_size_t)pcie->iobase, resource_size(&pcie->io), + (u32)pcie->io.start); + mvebu_pcie_iobase += SZ_64K; + } + + clk = of_clk_get(np, 0); + if (!IS_ERR(clk)) + clk_enable(clk); + + pcie->pci.set_busno = mvebu_pcie_set_local_bus_nr; + pcie->pci.pci_ops = &mvebu_pcie_indirect_ops; + pcie->pci.mem_resource = &pcie->mem; + pcie->pci.io_resource = &pcie->io; + + return pcie; +} + +static struct mvebu_pcie_ops __maybe_unused armada_370_ops = { + .phy_setup = armada_370_phy_setup, +}; + +static struct mvebu_pcie_ops __maybe_unused armada_xp_ops = { + .phy_setup = armada_xp_phy_setup, +}; + +static struct of_device_id mvebu_pcie_dt_ids[] = { +#if defined(CONFIG_ARCH_ARMADA_XP) + { .compatible = "marvell,armada-xp-pcie", .data = (u32)&armada_xp_ops, }, +#endif +#if defined(CONFIG_ARCH_ARMADA_370) + { .compatible = "marvell,armada-370-pcie", .data = (u32)&armada_370_ops, }, +#endif +#if defined(CONFIG_ARCH_DOVE) + { .compatible = "marvell,dove-pcie", }, +#endif +#if defined(CONFIG_ARCH_KIRKWOOD) + { .compatible = "marvell,kirkwood-pcie", }, +#endif + { }, +}; + +static int mvebu_pcie_probe(struct device_d *dev) +{ + struct device_node *np = dev->device_node; + const struct of_device_id *match = of_match_node(mvebu_pcie_dt_ids, np); + struct mvebu_pcie_ops *ops = (struct mvebu_pcie_ops *)match->data; + struct device_node *pnp; + + for_each_child_of_node(np, pnp) { + struct mvebu_pcie *pcie; + u32 reg; + + if (!of_device_is_available(pnp)) + continue; + + pcie = mvebu_pcie_port_probe(dev, pnp); + if (IS_ERR(pcie)) + continue; + + if (ops && ops->phy_setup) + ops->phy_setup(pcie); + + mvebu_pcie_set_local_dev_nr(pcie, 0); + mvebu_pcie_setup_wins(pcie); + + /* Master + slave enable. */ + reg = readl(pcie->base + PCIE_CMD_OFF); + reg |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY; + reg |= PCI_COMMAND_MASTER; + writel(reg, pcie->base + PCIE_CMD_OFF); + + /* Disable interrupts */ + reg = readl(pcie->base + PCIE_MASK_OFF); + reg &= ~PCIE_MASK_ENABLE_INTS; + writel(reg, pcie->base + PCIE_MASK_OFF); + + register_pci_controller(&pcie->pci); + } + + return 0; +} + +static struct driver_d mvebu_pcie_driver = { + .name = "mvebu-pcie", + .probe = mvebu_pcie_probe, + .of_compatible = mvebu_pcie_dt_ids, +}; +device_platform_driver(mvebu_pcie_driver); diff --git a/drivers/pci/pci-mvebu.h b/drivers/pci/pci-mvebu.h new file mode 100644 index 0000000000..8ced9fefca --- /dev/null +++ b/drivers/pci/pci-mvebu.h @@ -0,0 +1,37 @@ +/* + * PCIe include for Marvell MVEBU SoCs + * + * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> + * + * This file is licensed under the terms of the GNU General Public + * License version 2. This program is licensed "as is" without any + * warranty of any kind, whether express or implied. + */ + +#ifndef __MVEBU_PCI_H +#define __MVEBU_PCI_H + +#include <linux/pci.h> + +struct mvebu_pcie { + struct pci_controller pci; + char *name; + void __iomem *base; + void __iomem *membase; + struct resource mem; + void __iomem *iobase; + struct resource io; + u32 port; + u32 lane; + u32 lane_mask; + int devfn; +}; + +struct mvebu_pcie_ops { + int (*phy_setup)(struct mvebu_pcie *pcie); +}; + +int armada_370_phy_setup(struct mvebu_pcie *pcie); +int armada_xp_phy_setup(struct mvebu_pcie *pcie); + +#endif diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index 3d88b0ff5f..a1b7680254 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -11,6 +11,7 @@ static struct pci_controller *hose_head, **hose_tail = &hose_head; LIST_HEAD(pci_root_buses); EXPORT_SYMBOL(pci_root_buses); +static u8 bus_index; static struct pci_bus *pci_alloc_bus(void) { @@ -36,10 +37,14 @@ void register_pci_controller(struct pci_controller *hose) bus = pci_alloc_bus(); hose->bus = bus; + bus->host = hose; bus->ops = hose->pci_ops; bus->resource[0] = hose->mem_resource; bus->resource[1] = hose->io_resource; + bus->number = bus_index++; + if (hose->set_busno) + hose->set_busno(hose, bus->number); pci_scan_bus(bus); list_add_tail(&bus->node, &pci_root_buses); @@ -186,14 +191,15 @@ unsigned int pci_scan_bus(struct pci_bus *bus) DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device); - list_add_tail(&dev->bus_list, &bus->devices); - pci_register_device(dev); - if (class == PCI_CLASS_BRIDGE_HOST) { DBG("PCI: skip pci host bridge\n"); continue; } + pci_read_config_byte(dev, PCI_COMMAND, &cmd); + pci_write_config_byte(dev, PCI_COMMAND, + cmd & ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY)); + for (bar = 0; bar < 6; bar++) { resource_size_t last_addr; @@ -211,20 +217,34 @@ unsigned int pci_scan_bus(struct pci_bus *bus) size = -(mask & 0xfffffffe); DBG(" PCI: pbar%d: mask=%08x io %d bytes\n", bar, mask, size); pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_io); + dev->resource[bar].flags = IORESOURCE_IO; last_addr = last_io; last_io += size; - } else { /* MEM */ size = -(mask & 0xfffffff0); DBG(" PCI: pbar%d: mask=%08x memory %d bytes\n", bar, mask, size); pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + bar * 4, last_mem); + dev->resource[bar].flags = IORESOURCE_MEM; last_addr = last_mem; last_mem += size; + + if ((mask & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == + PCI_BASE_ADDRESS_MEM_TYPE_64) { + dev->resource[bar].flags |= IORESOURCE_MEM_64; + pci_write_config_dword(dev, + PCI_BASE_ADDRESS_1 + bar * 4, 0); + } } dev->resource[bar].start = last_addr; dev->resource[bar].end = last_addr + size - 1; + if (dev->resource[bar].flags & IORESOURCE_MEM_64) + bar++; } + + pci_write_config_byte(dev, PCI_COMMAND, cmd); + list_add_tail(&dev->bus_list, &bus->devices); + pci_register_device(dev); } /* diff --git a/drivers/pinctrl/mvebu/Kconfig b/drivers/pinctrl/mvebu/Kconfig index f5cf60804c..be154ed437 100644 --- a/drivers/pinctrl/mvebu/Kconfig +++ b/drivers/pinctrl/mvebu/Kconfig @@ -1,3 +1,11 @@ +config PINCTRL_ARMADA_370 + bool + select PINCTRL + +config PINCTRL_ARMADA_XP + bool + select PINCTRL + config PINCTRL_DOVE bool select PINCTRL diff --git a/drivers/pinctrl/mvebu/Makefile b/drivers/pinctrl/mvebu/Makefile index 05f320d5a3..6255a5f56d 100644 --- a/drivers/pinctrl/mvebu/Makefile +++ b/drivers/pinctrl/mvebu/Makefile @@ -1,3 +1,5 @@ obj-y += common.o +obj-$(CONFIG_ARCH_ARMADA_370) += armada-370.o +obj-$(CONFIG_ARCH_ARMADA_XP) += armada-xp.o obj-$(CONFIG_ARCH_DOVE) += dove.o obj-$(CONFIG_ARCH_KIRKWOOD) += kirkwood.o diff --git a/drivers/pinctrl/mvebu/armada-370.c b/drivers/pinctrl/mvebu/armada-370.c new file mode 100644 index 0000000000..4778358fad --- /dev/null +++ b/drivers/pinctrl/mvebu/armada-370.c @@ -0,0 +1,416 @@ +/* + * Marvell Armada 370 pinctrl driver based on mvebu pinctrl core + * + * Copyright (C) 2012 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include <common.h> +#include <init.h> +#include <linux/clk.h> +#include <malloc.h> +#include <of.h> +#include <of_address.h> +#include <sizes.h> + +#include "common.h" + +static void __iomem *mpp_base; + +static int armada_370_mpp_ctrl_get(unsigned pid, unsigned long *config) +{ + return default_mpp_ctrl_get(mpp_base, pid, config); +} + +static int armada_370_mpp_ctrl_set(unsigned pid, unsigned long config) +{ + return default_mpp_ctrl_set(mpp_base, pid, config); +} + +static struct mvebu_mpp_mode mv88f6710_mpp_modes[] = { + MPP_MODE(0, "mpp0", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "uart0", "rxd")), + MPP_MODE(1, "mpp1", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "uart0", "txd")), + MPP_MODE(2, "mpp2", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "i2c0", "sck"), + MPP_FUNCTION(0x2, "uart0", "txd")), + MPP_MODE(3, "mpp3", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "i2c0", "sda"), + MPP_FUNCTION(0x2, "uart0", "rxd")), + MPP_MODE(4, "mpp4", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "cpu_pd", "vdd")), + MPP_MODE(5, "mpp5", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txclko"), + MPP_FUNCTION(0x2, "uart1", "txd"), + MPP_FUNCTION(0x4, "spi1", "clk"), + MPP_FUNCTION(0x5, "audio", "mclk")), + MPP_MODE(6, "mpp6", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "txd0"), + MPP_FUNCTION(0x2, "sata0", "prsnt"), + MPP_FUNCTION(0x4, "tdm", "rst"), + MPP_FUNCTION(0x5, "audio", "sdo")), + MPP_MODE(7, "mpp7", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd1"), + MPP_FUNCTION(0x4, "tdm", "tdx"), + MPP_FUNCTION(0x5, "audio", "lrclk")), + MPP_MODE(8, "mpp8", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "txd2"), + MPP_FUNCTION(0x2, "uart0", "rts"), + MPP_FUNCTION(0x4, "tdm", "drx"), + MPP_FUNCTION(0x5, "audio", "bclk")), + MPP_MODE(9, "mpp9", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd3"), + MPP_FUNCTION(0x2, "uart1", "txd"), + MPP_FUNCTION(0x3, "sd0", "clk"), + MPP_FUNCTION(0x5, "audio", "spdifo")), + MPP_MODE(10, "mpp10", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "txctl"), + MPP_FUNCTION(0x2, "uart0", "cts"), + MPP_FUNCTION(0x4, "tdm", "fsync"), + MPP_FUNCTION(0x5, "audio", "sdi")), + MPP_MODE(11, "mpp11", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd0"), + MPP_FUNCTION(0x2, "uart1", "rxd"), + MPP_FUNCTION(0x3, "sd0", "cmd"), + MPP_FUNCTION(0x4, "spi0", "cs1"), + MPP_FUNCTION(0x5, "sata1", "prsnt"), + MPP_FUNCTION(0x6, "spi1", "cs1")), + MPP_MODE(12, "mpp12", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd1"), + MPP_FUNCTION(0x2, "i2c1", "sda"), + MPP_FUNCTION(0x3, "sd0", "d0"), + MPP_FUNCTION(0x4, "spi1", "cs0"), + MPP_FUNCTION(0x5, "audio", "spdifi")), + MPP_MODE(13, "mpp13", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd2"), + MPP_FUNCTION(0x2, "i2c1", "sck"), + MPP_FUNCTION(0x3, "sd0", "d1"), + MPP_FUNCTION(0x4, "tdm", "pclk"), + MPP_FUNCTION(0x5, "audio", "rmclk")), + MPP_MODE(14, "mpp14", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd3"), + MPP_FUNCTION(0x2, "pcie", "clkreq0"), + MPP_FUNCTION(0x3, "sd0", "d2"), + MPP_FUNCTION(0x4, "spi1", "mosi"), + MPP_FUNCTION(0x5, "spi0", "cs2")), + MPP_MODE(15, "mpp15", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxctl"), + MPP_FUNCTION(0x2, "pcie", "clkreq1"), + MPP_FUNCTION(0x3, "sd0", "d3"), + MPP_FUNCTION(0x4, "spi1", "miso"), + MPP_FUNCTION(0x5, "spi0", "cs3")), + MPP_MODE(16, "mpp16", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxclk"), + MPP_FUNCTION(0x2, "uart1", "rxd"), + MPP_FUNCTION(0x4, "tdm", "int"), + MPP_FUNCTION(0x5, "audio", "extclk")), + MPP_MODE(17, "mpp17", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge", "mdc")), + MPP_MODE(18, "mpp18", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge", "mdio")), + MPP_MODE(19, "mpp19", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "txclk"), + MPP_FUNCTION(0x2, "ge1", "txclkout"), + MPP_FUNCTION(0x4, "tdm", "pclk")), + MPP_MODE(20, "mpp20", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd4"), + MPP_FUNCTION(0x2, "ge1", "txd0")), + MPP_MODE(21, "mpp21", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd5"), + MPP_FUNCTION(0x2, "ge1", "txd1"), + MPP_FUNCTION(0x4, "uart1", "txd")), + MPP_MODE(22, "mpp22", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd6"), + MPP_FUNCTION(0x2, "ge1", "txd2"), + MPP_FUNCTION(0x4, "uart0", "rts")), + MPP_MODE(23, "mpp23", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "ge0", "txd7"), + MPP_FUNCTION(0x2, "ge1", "txd3"), + MPP_FUNCTION(0x4, "spi1", "mosi")), + MPP_MODE(24, "mpp24", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "col"), + MPP_FUNCTION(0x2, "ge1", "txctl"), + MPP_FUNCTION(0x4, "spi1", "cs0")), + MPP_MODE(25, "mpp25", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxerr"), + MPP_FUNCTION(0x2, "ge1", "rxd0"), + MPP_FUNCTION(0x4, "uart1", "rxd")), + MPP_MODE(26, "mpp26", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "crs"), + MPP_FUNCTION(0x2, "ge1", "rxd1"), + MPP_FUNCTION(0x4, "spi1", "miso")), + MPP_MODE(27, "mpp27", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd4"), + MPP_FUNCTION(0x2, "ge1", "rxd2"), + MPP_FUNCTION(0x4, "uart0", "cts")), + MPP_MODE(28, "mpp28", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd5"), + MPP_FUNCTION(0x2, "ge1", "rxd3")), + MPP_MODE(29, "mpp29", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd6"), + MPP_FUNCTION(0x2, "ge1", "rxctl"), + MPP_FUNCTION(0x4, "i2c1", "sda")), + MPP_MODE(30, "mpp30", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "ge0", "rxd7"), + MPP_FUNCTION(0x2, "ge1", "rxclk"), + MPP_FUNCTION(0x4, "i2c1", "sck")), + MPP_MODE(31, "mpp31", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x3, "tclk", NULL), + MPP_FUNCTION(0x4, "ge0", "txerr")), + MPP_MODE(32, "mpp32", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "cs0")), + MPP_MODE(33, "mpp33", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "bootcs"), + MPP_FUNCTION(0x2, "spi0", "cs0")), + MPP_MODE(34, "mpp34", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "wen0"), + MPP_FUNCTION(0x2, "spi0", "mosi")), + MPP_MODE(35, "mpp35", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "oen"), + MPP_FUNCTION(0x2, "spi0", "sck")), + MPP_MODE(36, "mpp36", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "a1"), + MPP_FUNCTION(0x2, "spi0", "miso")), + MPP_MODE(37, "mpp37", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "a0"), + MPP_FUNCTION(0x2, "sata0", "prsnt")), + MPP_MODE(38, "mpp38", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ready"), + MPP_FUNCTION(0x2, "uart1", "cts"), + MPP_FUNCTION(0x3, "uart0", "cts")), + MPP_MODE(39, "mpp39", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad0"), + MPP_FUNCTION(0x2, "audio", "spdifo")), + MPP_MODE(40, "mpp40", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad1"), + MPP_FUNCTION(0x2, "uart1", "rts"), + MPP_FUNCTION(0x3, "uart0", "rts")), + MPP_MODE(41, "mpp41", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad2"), + MPP_FUNCTION(0x2, "uart1", "rxd")), + MPP_MODE(42, "mpp42", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad3"), + MPP_FUNCTION(0x2, "uart1", "txd")), + MPP_MODE(43, "mpp43", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad4"), + MPP_FUNCTION(0x2, "audio", "bclk")), + MPP_MODE(44, "mpp44", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad5"), + MPP_FUNCTION(0x2, "audio", "mclk")), + MPP_MODE(45, "mpp45", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad6"), + MPP_FUNCTION(0x2, "audio", "lrclk")), + MPP_MODE(46, "mpp46", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad7"), + MPP_FUNCTION(0x2, "audio", "sdo")), + MPP_MODE(47, "mpp47", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad8"), + MPP_FUNCTION(0x3, "sd0", "clk"), + MPP_FUNCTION(0x5, "audio", "spdifo")), + MPP_MODE(48, "mpp48", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad9"), + MPP_FUNCTION(0x2, "uart0", "rts"), + MPP_FUNCTION(0x3, "sd0", "cmd"), + MPP_FUNCTION(0x4, "sata1", "prsnt"), + MPP_FUNCTION(0x5, "spi0", "cs1")), + MPP_MODE(49, "mpp49", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad10"), + MPP_FUNCTION(0x2, "pcie", "clkreq1"), + MPP_FUNCTION(0x3, "sd0", "d0"), + MPP_FUNCTION(0x4, "spi1", "cs0"), + MPP_FUNCTION(0x5, "audio", "spdifi")), + MPP_MODE(50, "mpp50", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad11"), + MPP_FUNCTION(0x2, "uart0", "cts"), + MPP_FUNCTION(0x3, "sd0", "d1"), + MPP_FUNCTION(0x4, "spi1", "miso"), + MPP_FUNCTION(0x5, "audio", "rmclk")), + MPP_MODE(51, "mpp51", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad12"), + MPP_FUNCTION(0x2, "i2c1", "sda"), + MPP_FUNCTION(0x3, "sd0", "d2"), + MPP_FUNCTION(0x4, "spi1", "mosi")), + MPP_MODE(52, "mpp52", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad13"), + MPP_FUNCTION(0x2, "i2c1", "sck"), + MPP_FUNCTION(0x3, "sd0", "d3"), + MPP_FUNCTION(0x4, "spi1", "sck")), + MPP_MODE(53, "mpp53", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ad14"), + MPP_FUNCTION(0x2, "sd0", "clk"), + MPP_FUNCTION(0x3, "tdm", "pclk"), + MPP_FUNCTION(0x4, "spi0", "cs2"), + MPP_FUNCTION(0x5, "pcie", "clkreq1")), + MPP_MODE(54, "mpp54", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ad15"), + MPP_FUNCTION(0x3, "tdm", "dtx")), + MPP_MODE(55, "mpp55", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "cs1"), + MPP_FUNCTION(0x2, "uart1", "txd"), + MPP_FUNCTION(0x3, "tdm", "rst"), + MPP_FUNCTION(0x4, "sata1", "prsnt"), + MPP_FUNCTION(0x5, "sata0", "prsnt")), + MPP_MODE(56, "mpp56", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "cs2"), + MPP_FUNCTION(0x2, "uart1", "cts"), + MPP_FUNCTION(0x3, "uart0", "cts"), + MPP_FUNCTION(0x4, "spi0", "cs3"), + MPP_FUNCTION(0x5, "pcie", "clkreq0"), + MPP_FUNCTION(0x6, "spi1", "cs1")), + MPP_MODE(57, "mpp57", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "cs3"), + MPP_FUNCTION(0x2, "uart1", "rxd"), + MPP_FUNCTION(0x3, "tdm", "fsync"), + MPP_FUNCTION(0x4, "sata0", "prsnt"), + MPP_FUNCTION(0x5, "audio", "sdo")), + MPP_MODE(58, "mpp58", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "cs0"), + MPP_FUNCTION(0x2, "uart1", "rts"), + MPP_FUNCTION(0x3, "tdm", "int"), + MPP_FUNCTION(0x5, "audio", "extclk"), + MPP_FUNCTION(0x6, "uart0", "rts")), + MPP_MODE(59, "mpp59", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "ale0"), + MPP_FUNCTION(0x2, "uart1", "rts"), + MPP_FUNCTION(0x3, "uart0", "rts"), + MPP_FUNCTION(0x5, "audio", "bclk")), + MPP_MODE(60, "mpp60", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "ale1"), + MPP_FUNCTION(0x2, "uart1", "rxd"), + MPP_FUNCTION(0x3, "sata0", "prsnt"), + MPP_FUNCTION(0x4, "pcie", "rst-out"), + MPP_FUNCTION(0x5, "audio", "sdi")), + MPP_MODE(61, "mpp61", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "dev", "wen1"), + MPP_FUNCTION(0x2, "uart1", "txd"), + MPP_FUNCTION(0x5, "audio", "rclk")), + MPP_MODE(62, "mpp62", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "dev", "a2"), + MPP_FUNCTION(0x2, "uart1", "cts"), + MPP_FUNCTION(0x3, "tdm", "drx"), + MPP_FUNCTION(0x4, "pcie", "clkreq0"), + MPP_FUNCTION(0x5, "audio", "mclk"), + MPP_FUNCTION(0x6, "uart0", "cts")), + MPP_MODE(63, "mpp63", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpo", NULL), + MPP_FUNCTION(0x1, "spi0", "sck"), + MPP_FUNCTION(0x2, "tclk", NULL)), + MPP_MODE(64, "mpp64", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "miso"), + MPP_FUNCTION(0x2, "spi0-1", "cs1")), + MPP_MODE(65, "mpp65", armada_370_mpp_ctrl, + MPP_FUNCTION(0x0, "gpio", NULL), + MPP_FUNCTION(0x1, "spi0", "mosi"), + MPP_FUNCTION(0x2, "spi0-1", "cs2")), +}; + +static struct mvebu_pinctrl_soc_info mv88f6710_pinctrl_info = { + .modes = mv88f6710_mpp_modes, + .nmodes = ARRAY_SIZE(mv88f6710_mpp_modes), + .variant = 0, +}; + +static struct of_device_id armada_370_pinctrl_of_match[] = { + { + .compatible = "marvell,mv88f6710-pinctrl", + .data = (u32)&mv88f6710_pinctrl_info, + }, + { }, +}; + +static int armada_370_pinctrl_probe(struct device_d *dev) +{ + const struct of_device_id *match = + of_match_node(armada_370_pinctrl_of_match, dev->device_node); + struct mvebu_pinctrl_soc_info *soc = + (struct mvebu_pinctrl_soc_info *)match->data; + + mpp_base = dev_request_mem_region(dev, 0); + if (!mpp_base) + return -EBUSY; + + return mvebu_pinctrl_probe(dev, soc); +} + +static struct driver_d armada_370_pinctrl_driver = { + .name = "pinctrl-armada-370", + .probe = armada_370_pinctrl_probe, + .of_compatible = armada_370_pinctrl_of_match, +}; + +static int armada_370_pinctrl_init(void) +{ + return platform_driver_register(&armada_370_pinctrl_driver); +} +postcore_initcall(armada_370_pinctrl_init); diff --git a/drivers/pinctrl/mvebu/armada-xp.c b/drivers/pinctrl/mvebu/armada-xp.c new file mode 100644 index 0000000000..9f79d373e4 --- /dev/null +++ b/drivers/pinctrl/mvebu/armada-xp.c @@ -0,0 +1,403 @@ +/* + * Marvell Armada XP pinctrl driver based on mvebu pinctrl core + * + * Copyright (C) 2012 Marvell + * + * Thomas Petazzoni <thomas.petazzoni@free-electrons.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This file supports the three variants of Armada XP SoCs that are + * available: mv78230, mv78260 and mv78460. From a pin muxing + * perspective, the mv78230 has 49 MPP pins. The mv78260 and mv78460 + * both have 67 MPP pins (more GPIOs and address lines for the memory + * bus mainly). The only difference between the mv78260 and the + * mv78460 in terms of pin muxing is the addition of two functions on + * pins 43 and 56 to access the VDD of the CPU2 and 3 (mv78260 has two + * cores, mv78460 has four cores). + */ + +#include <common.h> +#include <init.h> +#include <linux/clk.h> +#include <malloc.h> +#include <of.h> +#include <of_address.h> +#include <sizes.h> + +#include "common.h" + +static void __iomem *mpp_base; + +static int armada_xp_mpp_ctrl_get(unsigned pid, unsigned long *config) +{ + return default_mpp_ctrl_get(mpp_base, pid, config); +} + +static int armada_xp_mpp_ctrl_set(unsigned pid, unsigned long config) +{ + return default_mpp_ctrl_set(mpp_base, pid, config); +} + +enum armada_xp_variant { + V_MV78230 = BIT(0), + V_MV78260 = BIT(1), + V_MV78460 = BIT(2), + V_MV78230_PLUS = (V_MV78230 | V_MV78260 | V_MV78460), + V_MV78260_PLUS = (V_MV78260 | V_MV78460), +}; + +static struct mvebu_mpp_mode armada_xp_mpp_modes[] = { + MPP_MODE(0, "mpp0", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txclko", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d0", V_MV78230_PLUS)), + MPP_MODE(1, "mpp1", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d1", V_MV78230_PLUS)), + MPP_MODE(2, "mpp2", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d2", V_MV78230_PLUS)), + MPP_MODE(3, "mpp3", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d3", V_MV78230_PLUS)), + MPP_MODE(4, "mpp4", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d4", V_MV78230_PLUS)), + MPP_MODE(5, "mpp5", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txctl", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d5", V_MV78230_PLUS)), + MPP_MODE(6, "mpp6", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d6", V_MV78230_PLUS)), + MPP_MODE(7, "mpp7", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d7", V_MV78230_PLUS)), + MPP_MODE(8, "mpp8", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d8", V_MV78230_PLUS)), + MPP_MODE(9, "mpp9", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d9", V_MV78230_PLUS)), + MPP_MODE(10, "mpp10", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxctl", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d10", V_MV78230_PLUS)), + MPP_MODE(11, "mpp11", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d11", V_MV78230_PLUS)), + MPP_MODE(12, "mpp12", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd4", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "clkout", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d12", V_MV78230_PLUS)), + MPP_MODE(13, "mpp13", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd5", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "txd0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d13", V_MV78230_PLUS)), + MPP_MODE(14, "mpp14", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd6", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "txd1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d14", V_MV78230_PLUS)), + MPP_MODE(15, "mpp15", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txd7", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "txd2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d15", V_MV78230_PLUS)), + MPP_MODE(16, "mpp16", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "txclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "txd3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d16", V_MV78230_PLUS)), + MPP_MODE(17, "mpp17", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "col", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "txctl", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d17", V_MV78230_PLUS)), + MPP_MODE(18, "mpp18", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxerr", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxd0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "ptp", "trig", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d18", V_MV78230_PLUS)), + MPP_MODE(19, "mpp19", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "crs", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxd1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "ptp", "evreq", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d19", V_MV78230_PLUS)), + MPP_MODE(20, "mpp20", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd4", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxd2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "ptp", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d20", V_MV78230_PLUS)), + MPP_MODE(21, "mpp21", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd5", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxd3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "mem", "bat", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d21", V_MV78230_PLUS)), + MPP_MODE(22, "mpp22", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd6", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxctl", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "sata0", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d22", V_MV78230_PLUS)), + MPP_MODE(23, "mpp23", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ge0", "rxd7", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "ge1", "rxclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "d23", V_MV78230_PLUS)), + MPP_MODE(24, "mpp24", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata1", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "nf", "bootcs-re", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "rst", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "hsync", V_MV78230_PLUS)), + MPP_MODE(25, "mpp25", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sata0", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "nf", "bootcs-we", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "pclk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vsync", V_MV78230_PLUS)), + MPP_MODE(26, "mpp26", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "fsync", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), + MPP_MODE(27, "mpp27", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "trig", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "dtx", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "e", V_MV78230_PLUS)), + MPP_MODE(28, "mpp28", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "evreq", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "drx", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "pwm", V_MV78230_PLUS)), + MPP_MODE(29, "mpp29", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "ptp", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "ref-clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), + MPP_MODE(30, "mpp30", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "clk", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int1", V_MV78230_PLUS)), + MPP_MODE(31, "mpp31", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "cmd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), + MPP_MODE(32, "mpp32", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d0", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu1-pd", V_MV78230_PLUS)), + MPP_MODE(33, "mpp33", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int4", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS)), + MPP_MODE(34, "mpp34", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "sata0", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int5", V_MV78230_PLUS)), + MPP_MODE(35, "mpp35", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "sd0", "d3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "sata1", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int6", V_MV78230_PLUS)), + MPP_MODE(36, "mpp36", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "mosi", V_MV78230_PLUS)), + MPP_MODE(37, "mpp37", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "miso", V_MV78230_PLUS)), + MPP_MODE(38, "mpp38", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "sck", V_MV78230_PLUS)), + MPP_MODE(39, "mpp39", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "cs0", V_MV78230_PLUS)), + MPP_MODE(40, "mpp40", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "cs1", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart2", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "vdd", "cpu1-pd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vga-hsync", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq0", V_MV78230_PLUS)), + MPP_MODE(41, "mpp41", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "spi", "cs2", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart2", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "sata1", "prsnt", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "lcd", "vga-vsync", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq1", V_MV78230_PLUS)), + MPP_MODE(42, "mpp42", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "rxd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "tdm", "int7", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "tdm-1", "timer", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu0-pd", V_MV78230_PLUS)), + MPP_MODE(43, "mpp43", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "txd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart0", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs3", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "pcie", "rstout", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "vdd", "cpu2-3-pd", V_MV78460)), + MPP_MODE(44, "mpp44", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart3", "rxd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs4", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "mem", "bat", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq2", V_MV78230_PLUS)), + MPP_MODE(45, "mpp45", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart2", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart3", "txd", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs5", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "sata1", "prsnt", V_MV78230_PLUS)), + MPP_MODE(46, "mpp46", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart3", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart1", "rts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs6", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "sata0", "prsnt", V_MV78230_PLUS)), + MPP_MODE(47, "mpp47", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "uart3", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "uart1", "cts", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x3, "spi", "cs7", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x4, "ref", "clkout", V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x5, "pcie", "clkreq3", V_MV78230_PLUS)), + MPP_MODE(48, "mpp48", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x1, "tclk", NULL, V_MV78230_PLUS), + MPP_VAR_FUNCTION(0x2, "dev", "burst/last", V_MV78230_PLUS)), + MPP_MODE(49, "mpp49", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "we3", V_MV78260_PLUS)), + MPP_MODE(50, "mpp50", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "we2", V_MV78260_PLUS)), + MPP_MODE(51, "mpp51", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad16", V_MV78260_PLUS)), + MPP_MODE(52, "mpp52", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad17", V_MV78260_PLUS)), + MPP_MODE(53, "mpp53", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad18", V_MV78260_PLUS)), + MPP_MODE(54, "mpp54", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad19", V_MV78260_PLUS)), + MPP_MODE(55, "mpp55", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad20", V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x2, "vdd", "cpu0-pd", V_MV78260_PLUS)), + MPP_MODE(56, "mpp56", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad21", V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x2, "vdd", "cpu1-pd", V_MV78260_PLUS)), + MPP_MODE(57, "mpp57", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad22", V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x2, "vdd", "cpu2-3-pd", V_MV78460)), + MPP_MODE(58, "mpp58", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad23", V_MV78260_PLUS)), + MPP_MODE(59, "mpp59", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad24", V_MV78260_PLUS)), + MPP_MODE(60, "mpp60", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad25", V_MV78260_PLUS)), + MPP_MODE(61, "mpp61", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad26", V_MV78260_PLUS)), + MPP_MODE(62, "mpp62", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad27", V_MV78260_PLUS)), + MPP_MODE(63, "mpp63", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad28", V_MV78260_PLUS)), + MPP_MODE(64, "mpp64", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad29", V_MV78260_PLUS)), + MPP_MODE(65, "mpp65", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad30", V_MV78260_PLUS)), + MPP_MODE(66, "mpp66", armada_xp_mpp_ctrl, + MPP_VAR_FUNCTION(0x0, "gpio", NULL, V_MV78260_PLUS), + MPP_VAR_FUNCTION(0x1, "dev", "ad31", V_MV78260_PLUS)), +}; + +static struct mvebu_pinctrl_soc_info armada_xp_pinctrl_info = { + .modes = armada_xp_mpp_modes, + .nmodes = ARRAY_SIZE(armada_xp_mpp_modes), +}; + +static struct of_device_id armada_xp_pinctrl_of_match[] = { + { .compatible = "marvell,mv78230-pinctrl", .data = (u32)V_MV78230, }, + { .compatible = "marvell,mv78260-pinctrl", .data = (u32)V_MV78260, }, + { .compatible = "marvell,mv78460-pinctrl", .data = (u32)V_MV78460, }, + { }, +}; + +static int armada_xp_pinctrl_probe(struct device_d *dev) +{ + const struct of_device_id *match = + of_match_node(armada_xp_pinctrl_of_match, dev->device_node); + struct mvebu_pinctrl_soc_info *soc = &armada_xp_pinctrl_info; + + mpp_base = dev_request_mem_region(dev, 0); + if (!mpp_base) + return -EBUSY; + + soc->variant = (enum armada_xp_variant)match->data; + + /* + * We don't necessarily want the full list of the armada_xp_mpp_modes, + * but only the first 'n' ones that are available on this SoC + */ + if (soc->variant == V_MV78230) + soc->nmodes = 49; + + return mvebu_pinctrl_probe(dev, soc); +} + +static struct driver_d armada_xp_pinctrl_driver = { + .name = "pinctrl-armada-xp", + .probe = armada_xp_pinctrl_probe, + .of_compatible = armada_xp_pinctrl_of_match, +}; + +static int armada_xp_pinctrl_init(void) +{ + return platform_driver_register(&armada_xp_pinctrl_driver); +} +postcore_initcall(armada_xp_pinctrl_init); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index f51c6e6b02..146bf1ec3c 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -45,6 +45,10 @@ config DRIVER_SERIAL_LINUX_CONSOLE default y bool "linux console driver" +config DRIVER_SERIAL_EFI_STDIO + depends on ARCH_EFI + bool "EFI stdio driver" + config DRIVER_SERIAL_MPC5XXX depends on MPC5200 default y @@ -129,4 +133,8 @@ config DRIVER_SERIAL_CADENCE help Say Y here if you have a Cadence serial IP core. +config DRIVER_SERIAL_DIGIC + bool "Canon DIGIC serial driver" + depends on ARCH_DIGIC + endmenu diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index e1865f725a..189e777777 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -18,3 +18,5 @@ obj-$(CONFIG_DRIVER_SERIAL_PXA) += serial_pxa.o obj-$(CONFIG_DRIVER_SERIAL_OMAP4_USBBOOT) += serial_omap4_usbboot.o obj-$(CONFIG_DRIVER_SERIAL_AUART) += serial_auart.o obj-$(CONFIG_DRIVER_SERIAL_CADENCE) += serial_cadence.o +obj-$(CONFIG_DRIVER_SERIAL_EFI_STDIO) += efi-stdio.o +obj-$(CONFIG_DRIVER_SERIAL_DIGIC) += serial_digic.o diff --git a/drivers/serial/efi-stdio.c b/drivers/serial/efi-stdio.c new file mode 100644 index 0000000000..bf14c5e24a --- /dev/null +++ b/drivers/serial/efi-stdio.c @@ -0,0 +1,367 @@ +/* + * efi_console.c - EFI console support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <console.h> +#include <xfuncs.h> +#include <efi.h> +#include <readkey.h> +#include <linux/ctype.h> +#include <mach/efi.h> + +#define EFI_SHIFT_STATE_VALID 0x80000000 +#define EFI_RIGHT_CONTROL_PRESSED 0x00000004 +#define EFI_LEFT_CONTROL_PRESSED 0x00000008 +#define EFI_RIGHT_ALT_PRESSED 0x00000010 +#define EFI_LEFT_ALT_PRESSED 0x00000020 + +#define EFI_CONTROL_PRESSED (EFI_RIGHT_CONTROL_PRESSED | EFI_LEFT_CONTROL_PRESSED) +#define EFI_ALT_PRESSED (EFI_RIGHT_ALT_PRESSED | EFI_LEFT_ALT_PRESSED) +#define KEYPRESS(keys, scan, uni) ((((uint64_t)keys) << 32) | ((scan) << 16) | (uni)) +#define KEYCHAR(k) ((k) & 0xffff) +#define CHAR_CTRL(c) ((c) - 'a' + 1) + +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN (EFI_BLUE | EFI_GREEN) +#define EFI_RED 0x04 +#define EFI_MAGENTA (EFI_BLUE | EFI_RED) +#define EFI_BROWN (EFI_GREEN | EFI_RED) +#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY (EFI_BRIGHT) +#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) +#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) +#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) +#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) +#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) +#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) +#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) + +#define EFI_TEXT_ATTR(f,b) ((f) | ((b) << 4)) + +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) + +struct efi_console_priv { + struct efi_simple_text_output_protocol *out; + struct efi_simple_input_interface *in; + struct console_device cdev; + int lastkey; + u16 efi_console_buffer[CONFIG_CBSIZE]; + + unsigned long columns, rows; + + int current_color; + s16 *blank_line; +}; + +static inline struct efi_console_priv *to_efi(struct console_device *cdev) +{ + return container_of(cdev, struct efi_console_priv, cdev); +} + +struct efi_ctrlkey { + u8 scan_code; + u8 bb_key; +}; + +static struct efi_ctrlkey ctrlkeys[] = { + { 0x01, BB_KEY_UP }, + { 0x02, BB_KEY_DOWN }, + { 0x03, BB_KEY_RIGHT }, + { 0x04, BB_KEY_LEFT }, + { 0x05, BB_KEY_HOME }, + { 0x06, BB_KEY_END }, + { 0x07, BB_KEY_INSERT }, + { 0x08, BB_KEY_DEL }, + { 0x09, BB_KEY_PAGEUP }, + { 0x0a, BB_KEY_PAGEDOWN }, +}; + +static int efi_read_key(struct efi_console_priv *priv, bool wait) +{ + unsigned long index; + efi_status_t efiret; + struct efi_input_key k; + int i; + + /* wait until key is pressed */ + if (wait) + BS->wait_for_event(1, priv->in->wait_for_key, &index); + + efiret = priv->in->read_key_stroke(efi_sys_table->con_in, &k); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */ + for (i = 0; i < ARRAY_SIZE(ctrlkeys); i++) { + if (ctrlkeys[i].scan_code == k.scan_code) + return ctrlkeys[i].bb_key; + + } + + return k.unicode_char & 0xff; +} + +static void efi_console_putc(struct console_device *cdev, char c) +{ + uint16_t str[2] = {}; + struct efi_simple_text_output_protocol *con_out = efi_sys_table->con_out; + + str[0] = c; + + con_out->output_string(con_out, str); +} + +static void clear_to_eol(struct efi_console_priv *priv) +{ + int pos = priv->out->mode->cursor_column; + + priv->out->output_string(priv->out, priv->blank_line + pos); +} + +static int efi_process_square_bracket(struct efi_console_priv *priv, const char *inp) +{ + int x, y; + char *endp; + + inp++; + + switch (*inp) { + case 'A': + /* Cursor up */ + case 'B': + /* Cursor down */ + case 'C': + /* Cursor right */ + case 'D': + /* Cursor left */ + case 'H': + /* home */ + case 'F': + /* end */ + return 3; + case 'K': + clear_to_eol(priv); + return 3; + } + + if (*inp == '2' && *(inp + 1) == 'J') { + priv->out->clear_screen(priv->out); + return 4; + } + + if (*inp == '0' && *(inp + 1) == 'm') { + priv->out->set_attribute(priv->out, + EFI_TEXT_ATTR(EFI_WHITE, EFI_BLACK)); + return 4; + } + + if (*inp == '7' && *(inp + 1) == 'm') { + priv->out->set_attribute(priv->out, + EFI_TEXT_ATTR(EFI_BLACK, priv->current_color)); + return 4; + } + + if (*inp == '1' && + *(inp + 1) == ';' && + *(inp + 2) == '3' && + *(inp + 3) && + *(inp + 4) == 'm') { + int color; + switch (*(inp + 3)) { + case '1': color = EFI_RED; break; + case '4': color = EFI_BLUE; break; + case '2': color = EFI_GREEN; break; + case '6': color = EFI_CYAN; break; + case '3': color = EFI_YELLOW; break; + case '5': color = EFI_MAGENTA; break; + case '7': color = EFI_WHITE; break; + default: color = EFI_WHITE; break; + } + + priv->current_color = color; + + priv->out->set_attribute(priv->out, + EFI_TEXT_ATTR(color, EFI_BLACK)); + return 7; + } + + y = simple_strtoul(inp, &endp, 10); + if (*endp == ';') { + x = simple_strtoul(endp + 1, &endp, 10); + if (*endp == 'H') { + priv->out->set_cursor_position(priv->out, x - 1, y - 1); + return endp - inp + 3; + } + } + + return 8; +} + +static int efi_process_key(struct efi_console_priv *priv, const char *inp) +{ + char c; + + c = *inp; + + if (c != 27) + return 0; + + inp++; + + if (*inp == '[') + return efi_process_square_bracket(priv, inp); + + return 1; +} + +static int efi_console_puts(struct console_device *cdev, const char *s) +{ + struct efi_console_priv *priv = to_efi(cdev); + int n = 0; + + while (*s) { + if (*s == 27) { + priv->efi_console_buffer[n] = 0; + priv->out->output_string(priv->out, + priv->efi_console_buffer); + n = 0; + s += efi_process_key(priv, s); + continue; + } + + if (*s == '\n') + priv->efi_console_buffer[n++] = '\r'; + priv->efi_console_buffer[n] = *s; + s++; + n++; + } + + priv->efi_console_buffer[n] = 0; + + priv->out->output_string(priv->out, priv->efi_console_buffer); + + return n; +} + +static int efi_console_tstc(struct console_device *cdev) +{ + struct efi_console_priv *priv = to_efi(cdev); + int key; + + if (priv->lastkey > 0) + return 1; + + key = efi_read_key(priv, 0); + if (key < 0) + return 0; + + priv->lastkey = key; + + return 1; +} + +static int efi_console_getc(struct console_device *cdev) +{ + struct efi_console_priv *priv = to_efi(cdev); + int key; + + if (priv->lastkey > 0) { + key = priv->lastkey; + priv->lastkey = -1; + return key; + } + + return efi_read_key(priv, 1); +} + +static void efi_set_mode(struct efi_console_priv *priv) +{ +#if 0 + int i; + unsigned long rows, columns, best = 0, mode = 0; + efi_status_t efiret; + + for (i = 0; i < priv->out->mode->max_mode; i++) { + priv->out->query_mode(priv->out, i, &columns, &rows); + printf("%d: %ld %ld\n", i, columns, rows); + if (rows * columns > best) { + best = rows * columns; + mode = i; + } + } + + /* + * Setting the mode doesn't work as expected. set_mode succeeds, but + * the graphics resolution is not changed. + */ + priv->out->set_mode(priv->out, mode); +#endif + priv->out->query_mode(priv->out, priv->out->mode->mode, &priv->columns, &priv->rows); +} + +static int efi_console_probe(struct device_d *dev) +{ + struct console_device *cdev; + struct efi_console_priv *priv; + int i; + + priv = xzalloc(sizeof(*priv)); + + priv->out = efi_sys_table->con_out; + priv->in = efi_sys_table->con_in; + + priv->current_color = EFI_WHITE; + + efi_set_mode(priv); + + priv->out->enable_cursor(priv->out, 1); + + priv->blank_line = xzalloc((priv->columns + 1) * sizeof(s16)); + for (i = 0; i < priv->columns; i++) + priv->blank_line[i] = ' '; + + cdev = &priv->cdev; + cdev->dev = dev; + cdev->tstc = efi_console_tstc; + cdev->getc = efi_console_getc; + cdev->putc = efi_console_putc; + cdev->puts = efi_console_puts; + + priv->lastkey = -1; + + return console_register(cdev); +} + +static struct driver_d efi_console_driver = { + .name = "efi-stdio", + .probe = efi_console_probe, +}; +console_platform_driver(efi_console_driver); diff --git a/drivers/serial/serial_digic.c b/drivers/serial/serial_digic.c new file mode 100644 index 0000000000..235ea0ff47 --- /dev/null +++ b/drivers/serial/serial_digic.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2013, 2014 Antony Pavlov <antonynpavlov@gmail.com> + * + * This file is part of barebox. + * See file CREDITS for list of people who contributed to this project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <init.h> +#include <malloc.h> +#include <io.h> + +#include <mach/uart.h> + +/* + * This driver is based on the "Serial terminal" docs here: + * http://magiclantern.wikia.com/wiki/Register_Map#Misc_Registers + * + * See also disassembler output for Canon A1100IS firmware + * (version a1100_100c): + * * a outc-like function can be found at address 0xffff18f0; + * * a getc-like function can be found at address 0xffff192c. + */ + +static inline uint32_t digic_serial_readl(struct console_device *cdev, + uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + return readl(base + offset); +} + +static inline void digic_serial_writel(struct console_device *cdev, + uint32_t value, uint32_t offset) +{ + void __iomem *base = cdev->dev->priv; + + writel(value, base + offset); +} + +static int digic_serial_setbaudrate(struct console_device *cdev, int baudrate) +{ + /* I don't know how to setup baudrate :( */ + + return 0; +} + +static void digic_serial_putc(struct console_device *cdev, char c) +{ + uint32_t status; + + do { + status = digic_serial_readl(cdev, DIGIC_UART_ST); + } while (!(status & DIGIC_UART_ST_TX_RDY)); + + digic_serial_writel(cdev, 0x06, DIGIC_UART_ST); + digic_serial_writel(cdev, c, DIGIC_UART_TX); +} + +static int digic_serial_getc(struct console_device *cdev) +{ + uint32_t status; + + do { + status = digic_serial_readl(cdev, DIGIC_UART_ST); + } while (!(status & DIGIC_UART_ST_RX_RDY)); + + digic_serial_writel(cdev, 0x01, DIGIC_UART_ST); + + return digic_serial_readl(cdev, DIGIC_UART_RX); +} + +static int digic_serial_tstc(struct console_device *cdev) +{ + uint32_t status = digic_serial_readl(cdev, DIGIC_UART_ST); + + return ((status & DIGIC_UART_ST_RX_RDY) != 0); + + /* + * Canon folks use additional check, something like this: + * + * if (digic_serial_readl(cdev, DIGIC_UART_ST) & 0x38) { + * digic_serial_writel(cdev, 0x38, DIGIC_UART_ST); + * return 0; + * } + * + * But I know nothing about these magic bits in the status register... + * + */ +} + +static int digic_serial_probe(struct device_d *dev) +{ + struct console_device *cdev; + + cdev = xzalloc(sizeof(struct console_device)); + dev->priv = dev_request_mem_region(dev, 0); + cdev->dev = dev; + cdev->tstc = &digic_serial_tstc; + cdev->putc = &digic_serial_putc; + cdev->getc = &digic_serial_getc; + cdev->setbrg = &digic_serial_setbaudrate; + + console_register(cdev); + + return 0; +} + +static __maybe_unused struct of_device_id digic_serial_dt_ids[] = { + { + .compatible = "canon,digic-uart", + }, { + /* sentinel */ + } +}; + +static struct driver_d digic_serial_driver = { + .name = "digic-uart", + .probe = digic_serial_probe, + .of_compatible = DRV_OF_COMPAT(digic_serial_dt_ids), +}; +console_platform_driver(digic_serial_driver); diff --git a/drivers/serial/serial_imx.c b/drivers/serial/serial_imx.c index cb106271d5..474bfafff0 100644 --- a/drivers/serial/serial_imx.c +++ b/drivers/serial/serial_imx.c @@ -313,6 +313,7 @@ static int imx_serial_probe(struct device_d *dev) uint32_t val; struct imx_serial_devtype_data *devtype; int ret; + const char *devname; ret = dev_get_drvdata(dev, (unsigned long *)&devtype); if (ret) @@ -337,6 +338,9 @@ static int imx_serial_probe(struct device_d *dev) cdev->flush = imx_serial_flush; cdev->setbrg = imx_serial_setbaudrate; cdev->linux_console_name = "ttymxc"; + devname = of_alias_get(dev->device_node); + if (devname) + cdev->devname = xstrdup(devname); imx_serial_init_port(cdev); diff --git a/drivers/serial/serial_ns16550.c b/drivers/serial/serial_ns16550.c index 709f704cb4..09e6a6aba8 100644 --- a/drivers/serial/serial_ns16550.c +++ b/drivers/serial/serial_ns16550.c @@ -46,10 +46,17 @@ struct ns16550_priv { struct console_device cdev; struct NS16550_plat plat; - int access_width; - int mmio; struct clk *clk; uint32_t fcrval; + void __iomem *mmiobase; + unsigned iobase; + void (*write_reg)(struct ns16550_priv *, uint8_t val, unsigned offset); + uint8_t (*read_reg)(struct ns16550_priv *, unsigned offset); +}; + +struct ns16550_drvdata { + void (*init_port)(struct console_device *cdev); + const char *linux_console_name; }; static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev) @@ -57,93 +64,64 @@ static inline struct ns16550_priv *to_ns16550_priv(struct console_device *cdev) return container_of(cdev, struct ns16550_priv, cdev); } -struct ns16550_drvdata { - void (*init_port)(struct console_device *cdev); - const char *linux_console_name; -}; +static uint8_t ns16550_read_reg_mmio_8(struct ns16550_priv *priv, unsigned offset) +{ + return readb(priv->mmiobase + offset); +} -/** - * @brief read system i/o (byte) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint8_t ns16550_sys_readb(void __iomem *addr, int mmio) +static void ns16550_write_reg_mmio_8(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - return readb(addr); - else - return (uint8_t) inb((int) addr); + writeb(val, priv->mmiobase + offset); } -/** - * @brief read system i/o (word) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint16_t ns16550_sys_readw(void __iomem *addr, int mmio) +static uint8_t ns16550_read_reg_mmio_16(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - return readw(addr); - else - return (uint16_t) inw((int) addr); + return readw(priv->mmiobase + offset); } -/** - * @brief read system i/o (dword) - * @param[in] addr address to read - * @param[in] mmio memory i/o space or i/o port space - */ -static inline uint32_t ns16550_sys_readl(void __iomem *addr, int mmio) +static void ns16550_write_reg_mmio_16(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - return readl(addr); - else - return (uint32_t) inl((int) addr); + writew(val, priv->mmiobase + offset); } -/** - * @brief write system i/o (byte) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writeb(uint8_t val, void __iomem *addr, - int mmio) +static uint8_t ns16550_read_reg_mmio_32(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - writeb(val, addr); - else - outb(val, (int) addr); + return readl(priv->mmiobase + offset); } -/** - * @brief read system i/o (word) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writew(uint16_t val, void __iomem *addr, - int mmio) +static void ns16550_write_reg_mmio_32(struct ns16550_priv *priv, uint8_t val, unsigned offset) { - if (mmio) - writew(val, addr); - else - outw(val, (int) addr); + writel(val, priv->mmiobase + offset); } -/** - * @brief read system i/o (dword) - * @param[in] val data to write - * @param[in] addr address to write to - * @param[in] mmio memory i/o space or i/o port space - */ -static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr, - int mmio) +static uint8_t ns16550_read_reg_ioport_8(struct ns16550_priv *priv, unsigned offset) { - if (mmio) - writel(val, addr); - else - outl(val, (int) addr); + return inb(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_8(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outb(val, priv->iobase + offset); +} + +static uint8_t ns16550_read_reg_ioport_16(struct ns16550_priv *priv, unsigned offset) +{ + return inw(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_16(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outw(val, priv->iobase + offset); +} + +static uint8_t ns16550_read_reg_ioport_32(struct ns16550_priv *priv, unsigned offset) +{ + return inl(priv->iobase + offset); +} + +static void ns16550_write_reg_ioport_32(struct ns16550_priv *priv, uint8_t val, unsigned offset) +{ + outl(val, priv->iobase + offset); } /** @@ -157,21 +135,9 @@ static inline void ns16550_sys_writel(uint32_t val, void __iomem *addr, static uint32_t ns16550_read(struct console_device *cdev, uint32_t off) { struct ns16550_priv *priv = to_ns16550_priv(cdev); - struct device_d *dev = cdev->dev; struct NS16550_plat *plat = &priv->plat; - int width = priv->access_width; - - off <<= plat->shift; - switch (width) { - case IORESOURCE_MEM_8BIT: - return ns16550_sys_readb(dev->priv + off, priv->mmio); - case IORESOURCE_MEM_16BIT: - return ns16550_sys_readw(dev->priv + off, priv->mmio); - case IORESOURCE_MEM_32BIT: - return ns16550_sys_readl(dev->priv + off, priv->mmio); - } - return -1; + return priv->read_reg(priv, off << plat->shift); } /** @@ -185,23 +151,9 @@ static void ns16550_write(struct console_device *cdev, uint32_t val, uint32_t off) { struct ns16550_priv *priv = to_ns16550_priv(cdev); - struct device_d *dev = cdev->dev; struct NS16550_plat *plat = &priv->plat; - int width = priv->access_width; - - off <<= plat->shift; - switch (width) { - case IORESOURCE_MEM_8BIT: - ns16550_sys_writeb(val & 0xff, dev->priv + off, priv->mmio); - break; - case IORESOURCE_MEM_16BIT: - ns16550_sys_writew(val & 0xffff, dev->priv + off, priv->mmio); - break; - case IORESOURCE_MEM_32BIT: - ns16550_sys_writel(val, dev->priv + off, priv->mmio); - break; - } + priv->write_reg(priv, val, off << plat->shift); } /** @@ -359,6 +311,70 @@ static __maybe_unused struct ns16550_drvdata jz_drvdata = { .init_port = ns16550_jz_init_port, }; +static int ns16550_init_iomem(struct device_d *dev, struct ns16550_priv *priv) +{ + struct resource *res; + int width; + + res = dev_get_resource(dev, IORESOURCE_MEM, 0); + if (!res) + return -ENODEV; + + priv->mmiobase = dev_request_mem_region(dev, 0); + + width = res->flags & IORESOURCE_MEM_TYPE_MASK; + switch (width) { + case IORESOURCE_MEM_8BIT: + priv->read_reg = ns16550_read_reg_mmio_8; + priv->write_reg = ns16550_write_reg_mmio_8; + break; + case IORESOURCE_MEM_16BIT: + priv->read_reg = ns16550_read_reg_mmio_16; + priv->write_reg = ns16550_write_reg_mmio_16; + break; + case IORESOURCE_MEM_32BIT: + priv->read_reg = ns16550_read_reg_mmio_32; + priv->write_reg = ns16550_write_reg_mmio_32; + break; + } + + return 0; +} + +static int ns16550_init_ioport(struct device_d *dev, struct ns16550_priv *priv) +{ + struct resource *res; + int width; + + res = dev_get_resource(dev, IORESOURCE_IO, 0); + if (!res) + return -ENODEV; + + res = request_ioport_region(dev_name(dev), res->start, res->end); + if (!res) + return -ENODEV; + + priv->iobase = res->start; + + width = res->flags & IORESOURCE_MEM_TYPE_MASK; + switch (width) { + case IORESOURCE_MEM_8BIT: + priv->read_reg = ns16550_read_reg_ioport_8; + priv->write_reg = ns16550_write_reg_ioport_8; + break; + case IORESOURCE_MEM_16BIT: + priv->read_reg = ns16550_read_reg_ioport_16; + priv->write_reg = ns16550_write_reg_ioport_16; + break; + case IORESOURCE_MEM_32BIT: + priv->read_reg = ns16550_read_reg_ioport_32; + priv->write_reg = ns16550_write_reg_ioport_32; + break; + } + + return 0; +} + /** * @brief Probe entry point -called on the first match for device * @@ -374,7 +390,6 @@ static int ns16550_probe(struct device_d *dev) struct console_device *cdev; struct NS16550_plat *plat = (struct NS16550_plat *)dev->platform_data; struct ns16550_drvdata *devtype; - struct resource *res; int ret; ret = dev_get_drvdata(dev, (unsigned long *)&devtype); @@ -383,20 +398,12 @@ static int ns16550_probe(struct device_d *dev) priv = xzalloc(sizeof(*priv)); - res = dev_get_resource(dev, IORESOURCE_MEM, 0); - priv->mmio = (res != NULL); - if (res) { - res = request_iomem_region(dev_name(dev), res->start, res->end); - } else { - res = dev_get_resource(dev, IORESOURCE_IO, 0); - if (res) - res = request_ioport_region(dev_name(dev), res->start, - res->end); - } - if (!res) - goto err; - dev->priv = (void __force __iomem *) res->start; + ret = ns16550_init_iomem(dev, priv); + if (ret) + ret = ns16550_init_ioport(dev, priv); + if (ret) + return ret; if (plat) priv->plat = *plat; @@ -424,8 +431,6 @@ static int ns16550_probe(struct device_d *dev) goto err; } - priv->access_width = dev->resource[0].flags & IORESOURCE_MEM_TYPE_MASK; - cdev = &priv->cdev; cdev->dev = dev; cdev->tstc = ns16550_tstc; diff --git a/drivers/usb/gadget/dfu.c b/drivers/usb/gadget/dfu.c index d0f2155e49..bc5ee9c7dd 100644 --- a/drivers/usb/gadget/dfu.c +++ b/drivers/usb/gadget/dfu.c @@ -43,6 +43,7 @@ #include <linux/list.h> #include <usb/gadget.h> #include <linux/stat.h> +#include <libfile.h> #include <usb/ch9.h> #include <usb/dfu.h> #include <config.h> diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 574e0975b9..2f9353edca 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -475,7 +475,12 @@ int gserial_connect(struct gserial *gser, u8 port_num) cdev->getc = serial_getc; cdev->flush = serial_flush; cdev->setbrg = serial_setbaudrate; - console_register(cdev); + cdev->devname = "usbserial"; + + status = console_register(cdev); + if (status) + goto fail_out; + mycdev = cdev; return status; diff --git a/dts/Bindings/arm/armada-38x.txt b/dts/Bindings/arm/armada-38x.txt index 11f2330a65..ad9f8ed4d9 100644 --- a/dts/Bindings/arm/armada-38x.txt +++ b/dts/Bindings/arm/armada-38x.txt @@ -6,5 +6,15 @@ following property: Required root node property: - - compatible: must contain either "marvell,armada380" or - "marvell,armada385" depending on the variant of the SoC being used. + - compatible: must contain "marvell,armada380" + +In addition, boards using the Marvell Armada 385 SoC shall have the +following property before the previous one: + +Required root node property: + +compatible: must contain "marvell,armada385" + +Example: + +compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada380"; diff --git a/dts/Bindings/arm/exynos/power_domain.txt b/dts/Bindings/arm/exynos/power_domain.txt index 5216b41901..8b4f7b7fe8 100644 --- a/dts/Bindings/arm/exynos/power_domain.txt +++ b/dts/Bindings/arm/exynos/power_domain.txt @@ -9,6 +9,18 @@ Required Properties: - reg: physical base address of the controller and length of memory mapped region. +Optional Properties: +- clocks: List of clock handles. The parent clocks of the input clocks to the + devices in this power domain are set to oscclk before power gating + and restored back after powering on a domain. This is required for + all domains which are powered on and off and not required for unused + domains. +- clock-names: The following clocks can be specified: + - oscclk: Oscillator clock. + - pclkN, clkN: Pairs of parent of input clock and input clock to the + devices in this power domain. Maximum of 4 pairs (N = 0 to 3) + are supported currently. + Node of a device using power domains must have a samsung,power-domain property defined with a phandle to respective power domain. @@ -19,6 +31,14 @@ Example: reg = <0x10023C00 0x10>; }; + mfc_pd: power-domain@10044060 { + compatible = "samsung,exynos4210-pd"; + reg = <0x10044060 0x20>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>, + <&clock CLK_MOUT_USER_ACLK333>; + clock-names = "oscclk", "pclk0", "clk0"; + }; + Example of the node using power domain: node { diff --git a/dts/Bindings/arm/l2cc.txt b/dts/Bindings/arm/l2cc.txt index b513cb8196..af527ee111 100644 --- a/dts/Bindings/arm/l2cc.txt +++ b/dts/Bindings/arm/l2cc.txt @@ -40,6 +40,9 @@ Optional properties: - arm,filter-ranges : <start length> Starting address and length of window to filter. Addresses in the filter window are directed to the M1 port. Other addresses will go to the M0 port. +- arm,io-coherent : indicates that the system is operating in an hardware + I/O coherent mode. Valid only when the arm,pl310-cache compatible + string is used. - interrupts : 1 combined interrupt. - cache-id-part: cache id part number to be used if it is not present on hardware diff --git a/dts/Bindings/arm/samsung/exynos-adc.txt b/dts/Bindings/arm/samsung/exynos-adc.txt index 5d49f2b37f..832fe8cc24 100644 --- a/dts/Bindings/arm/samsung/exynos-adc.txt +++ b/dts/Bindings/arm/samsung/exynos-adc.txt @@ -48,7 +48,7 @@ adc@12D10000 { /* NTC thermistor is a hwmon device */ ncp15wb473@0 { - compatible = "ntc,ncp15wb473"; + compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; pulldown-ohm = <0>; diff --git a/dts/Bindings/cpufreq/cpufreq-cpu0.txt b/dts/Bindings/cpufreq/cpufreq-cpu0.txt index f055515d2b..366690cb86 100644 --- a/dts/Bindings/cpufreq/cpufreq-cpu0.txt +++ b/dts/Bindings/cpufreq/cpufreq-cpu0.txt @@ -8,10 +8,12 @@ Both required and optional properties listed below must be defined under node /cpus/cpu@0. Required properties: -- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt - for details +- None Optional properties: +- operating-points: Refer to Documentation/devicetree/bindings/power/opp.txt for + details. OPPs *must* be supplied either via DT, i.e. this property, or + populated at runtime. - clock-latency: Specify the possible maximum transition latency for clock, in unit of nanoseconds. - voltage-tolerance: Specify the CPU voltage tolerance in percentage. diff --git a/dts/Bindings/hwmon/ntc_thermistor.txt b/dts/Bindings/hwmon/ntc_thermistor.txt index c6f66674f1..b117b2e9e1 100644 --- a/dts/Bindings/hwmon/ntc_thermistor.txt +++ b/dts/Bindings/hwmon/ntc_thermistor.txt @@ -3,11 +3,19 @@ NTC Thermistor hwmon sensors Requires node properties: - "compatible" value : one of - "ntc,ncp15wb473" - "ntc,ncp18wb473" - "ntc,ncp21wb473" - "ntc,ncp03wb473" - "ntc,ncp15wl333" + "murata,ncp15wb473" + "murata,ncp18wb473" + "murata,ncp21wb473" + "murata,ncp03wb473" + "murata,ncp15wl333" + +/* Usage of vendor name "ntc" is deprecated */ +<DEPRECATED> "ntc,ncp15wb473" +<DEPRECATED> "ntc,ncp18wb473" +<DEPRECATED> "ntc,ncp21wb473" +<DEPRECATED> "ntc,ncp03wb473" +<DEPRECATED> "ntc,ncp15wl333" + - "pullup-uv" Pull up voltage in micro volts - "pullup-ohm" Pull up resistor value in ohms - "pulldown-ohm" Pull down resistor value in ohms @@ -21,7 +29,7 @@ Read more about iio bindings at Example: ncp15wb473@0 { - compatible = "ntc,ncp15wb473"; + compatible = "murata,ncp15wb473"; pullup-uv = <1800000>; pullup-ohm = <47000>; pulldown-ohm = <0>; diff --git a/dts/Bindings/serial/renesas,sci-serial.txt b/dts/Bindings/serial/renesas,sci-serial.txt index 64fd7dec1b..b3556609a0 100644 --- a/dts/Bindings/serial/renesas,sci-serial.txt +++ b/dts/Bindings/serial/renesas,sci-serial.txt @@ -4,6 +4,13 @@ Required properties: - compatible: Must contain one of the following: + - "renesas,scifa-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFA compatible UART. + - "renesas,scifb-sh73a0" for SH73A0 (SH-Mobile AG5) SCIFB compatible UART. + - "renesas,scifa-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFA compatible UART. + - "renesas,scifb-r8a73a4" for R8A73A4 (R-Mobile APE6) SCIFB compatible UART. + - "renesas,scifa-r8a7740" for R8A7740 (R-Mobile A1) SCIFA compatible UART. + - "renesas,scifb-r8a7740" for R8A7740 (R-Mobile A1) SCIFB compatible UART. + - "renesas,scif-r8a7778" for R8A7778 (R-Car M1) SCIF compatible UART. - "renesas,scif-r8a7779" for R8A7779 (R-Car H1) SCIF compatible UART. - "renesas,scif-r8a7790" for R8A7790 (R-Car H2) SCIF compatible UART. - "renesas,scifa-r8a7790" for R8A7790 (R-Car H2) SCIFA compatible UART. diff --git a/dts/Bindings/spi/qcom,spi-qup.txt b/dts/Bindings/spi/qcom,spi-qup.txt index b82a268f1b..bee6ff204b 100644 --- a/dts/Bindings/spi/qcom,spi-qup.txt +++ b/dts/Bindings/spi/qcom,spi-qup.txt @@ -23,6 +23,12 @@ Optional properties: - spi-max-frequency: Specifies maximum SPI clock frequency, Units - Hz. Definition as per Documentation/devicetree/bindings/spi/spi-bus.txt +- num-cs: total number of chipselects +- cs-gpios: should specify GPIOs used for chipselects. + The gpios will be referred to as reg = <index> in the SPI child + nodes. If unspecified, a single SPI device without a chip + select can be used. + SPI slave nodes must be children of the SPI master node and can contain properties described in Documentation/devicetree/bindings/spi/spi-bus.txt diff --git a/dts/Bindings/vendor-prefixes.txt b/dts/Bindings/vendor-prefixes.txt index 4d7f3758d1..46a311e728 100644 --- a/dts/Bindings/vendor-prefixes.txt +++ b/dts/Bindings/vendor-prefixes.txt @@ -83,6 +83,7 @@ mosaixtech Mosaix Technologies, Inc. moxa Moxa mpl MPL AG mundoreader Mundo Reader S.L. +murata Murata Manufacturing Co., Ltd. mxicy Macronix International Co., Ltd. national National Semiconductor neonode Neonode Inc. diff --git a/dts/include/dt-bindings/clock/exynos5420.h b/dts/include/dt-bindings/clock/exynos5420.h index 97dcb89d37..21d51ae1d2 100644 --- a/dts/include/dt-bindings/clock/exynos5420.h +++ b/dts/include/dt-bindings/clock/exynos5420.h @@ -63,7 +63,6 @@ #define CLK_SCLK_MPHY_IXTAL24 161 /* gate clocks */ -#define CLK_ACLK66_PERIC 256 #define CLK_UART0 257 #define CLK_UART1 258 #define CLK_UART2 259 @@ -203,6 +202,8 @@ #define CLK_MOUT_G3D 641 #define CLK_MOUT_VPLL 642 #define CLK_MOUT_MAUDIO0 643 +#define CLK_MOUT_USER_ACLK333 644 +#define CLK_MOUT_SW_ACLK333 645 /* divider clocks */ #define CLK_DOUT_PIXEL 768 diff --git a/dts/include/dt-bindings/clock/imx6sl-clock.h b/dts/include/dt-bindings/clock/imx6sl-clock.h index 7cf5c99693..b91dd462ba 100644 --- a/dts/include/dt-bindings/clock/imx6sl-clock.h +++ b/dts/include/dt-bindings/clock/imx6sl-clock.h @@ -145,6 +145,7 @@ #define IMX6SL_CLK_USDHC4 132 #define IMX6SL_CLK_PLL4_AUDIO_DIV 133 #define IMX6SL_CLK_SPBA 134 -#define IMX6SL_CLK_END 135 +#define IMX6SL_CLK_ENET 135 +#define IMX6SL_CLK_END 136 #endif /* __DT_BINDINGS_CLOCK_IMX6SL_H */ diff --git a/dts/include/dt-bindings/clock/stih415-clks.h b/dts/include/dt-bindings/clock/stih415-clks.h index 0d2c7397e0..d80caa68ae 100644 --- a/dts/include/dt-bindings/clock/stih415-clks.h +++ b/dts/include/dt-bindings/clock/stih415-clks.h @@ -10,6 +10,7 @@ #define CLK_ETH1_PHY 4 /* CLOCKGEN A1 */ +#define CLK_ICN_IF_2 0 #define CLK_GMAC0_PHY 3 #endif diff --git a/dts/include/dt-bindings/clock/stih416-clks.h b/dts/include/dt-bindings/clock/stih416-clks.h index 552c779eb6..f9bdbd1356 100644 --- a/dts/include/dt-bindings/clock/stih416-clks.h +++ b/dts/include/dt-bindings/clock/stih416-clks.h @@ -10,6 +10,7 @@ #define CLK_ETH1_PHY 4 /* CLOCKGEN A1 */ +#define CLK_ICN_IF_2 0 #define CLK_GMAC0_PHY 3 #endif diff --git a/dts/include/dt-bindings/pinctrl/dra.h b/dts/include/dt-bindings/pinctrl/dra.h index 002a2855c0..3d33794e4f 100644 --- a/dts/include/dt-bindings/pinctrl/dra.h +++ b/dts/include/dt-bindings/pinctrl/dra.h @@ -30,7 +30,8 @@ #define MUX_MODE14 0xe #define MUX_MODE15 0xf -#define PULL_ENA (1 << 16) +#define PULL_ENA (0 << 16) +#define PULL_DIS (1 << 16) #define PULL_UP (1 << 17) #define INPUT_EN (1 << 18) #define SLEWCONTROL (1 << 19) @@ -38,10 +39,10 @@ #define WAKEUP_EVENT (1 << 25) /* Active pin states */ -#define PIN_OUTPUT 0 +#define PIN_OUTPUT (0 | PULL_DIS) #define PIN_OUTPUT_PULLUP (PIN_OUTPUT | PULL_ENA | PULL_UP) #define PIN_OUTPUT_PULLDOWN (PIN_OUTPUT | PULL_ENA) -#define PIN_INPUT INPUT_EN +#define PIN_INPUT (INPUT_EN | PULL_DIS) #define PIN_INPUT_SLEW (INPUT_EN | SLEWCONTROL) #define PIN_INPUT_PULLUP (PULL_ENA | INPUT_EN | PULL_UP) #define PIN_INPUT_PULLDOWN (PULL_ENA | INPUT_EN) diff --git a/dts/src/arm/am335x-evm.dts b/dts/src/arm/am335x-evm.dts index ecb267767c..e2156a583d 100644 --- a/dts/src/arm/am335x-evm.dts +++ b/dts/src/arm/am335x-evm.dts @@ -529,8 +529,8 @@ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ 0 0 1 2 >; - tx-num-evt = <1>; - rx-num-evt = <1>; + tx-num-evt = <32>; + rx-num-evt = <32>; }; &tps { diff --git a/dts/src/arm/am335x-evmsk.dts b/dts/src/arm/am335x-evmsk.dts index ab9a34ce52..80a3b215e7 100644 --- a/dts/src/arm/am335x-evmsk.dts +++ b/dts/src/arm/am335x-evmsk.dts @@ -560,8 +560,8 @@ serial-dir = < /* 0: INACTIVE, 1: TX, 2: RX */ 0 0 1 2 >; - tx-num-evt = <1>; - rx-num-evt = <1>; + tx-num-evt = <32>; + rx-num-evt = <32>; }; &tscadc { diff --git a/dts/src/arm/am335x-igep0033.dtsi b/dts/src/arm/am335x-igep0033.dtsi index 8a0a72dc7d..a1a0cc5eb3 100644 --- a/dts/src/arm/am335x-igep0033.dtsi +++ b/dts/src/arm/am335x-igep0033.dtsi @@ -105,10 +105,16 @@ &cpsw_emac0 { phy_id = <&davinci_mdio>, <0>; + phy-mode = "rmii"; }; &cpsw_emac1 { phy_id = <&davinci_mdio>, <1>; + phy-mode = "rmii"; +}; + +&phy_sel { + rmii-clock-ext; }; &elm { diff --git a/dts/src/arm/am43x-epos-evm.dts b/dts/src/arm/am43x-epos-evm.dts index 19f1f7e875..90098f98a5 100644 --- a/dts/src/arm/am43x-epos-evm.dts +++ b/dts/src/arm/am43x-epos-evm.dts @@ -319,6 +319,10 @@ phy-mode = "rmii"; }; +&phy_sel { + rmii-clock-ext; +}; + &i2c0 { status = "okay"; pinctrl-names = "default"; diff --git a/dts/src/arm/armada-380.dtsi b/dts/src/arm/armada-380.dtsi index e69bc6759c..4173a8ab34 100644 --- a/dts/src/arm/armada-380.dtsi +++ b/dts/src/arm/armada-380.dtsi @@ -16,7 +16,7 @@ / { model = "Marvell Armada 380 family SoC"; - compatible = "marvell,armada380", "marvell,armada38x"; + compatible = "marvell,armada380"; cpus { #address-cells = <1>; diff --git a/dts/src/arm/armada-385-db.dts b/dts/src/arm/armada-385-db.dts index 5bae473182..1af886f1e4 100644 --- a/dts/src/arm/armada-385-db.dts +++ b/dts/src/arm/armada-385-db.dts @@ -16,7 +16,7 @@ / { model = "Marvell Armada 385 Development Board"; - compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada38x"; + compatible = "marvell,a385-db", "marvell,armada385", "marvell,armada380"; chosen { bootargs = "console=ttyS0,115200 earlyprintk"; diff --git a/dts/src/arm/armada-385-rd.dts b/dts/src/arm/armada-385-rd.dts index 40893255a3..aaca2861dc 100644 --- a/dts/src/arm/armada-385-rd.dts +++ b/dts/src/arm/armada-385-rd.dts @@ -17,7 +17,7 @@ / { model = "Marvell Armada 385 Reference Design"; - compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada38x"; + compatible = "marvell,a385-rd", "marvell,armada385", "marvell,armada380"; chosen { bootargs = "console=ttyS0,115200 earlyprintk"; diff --git a/dts/src/arm/armada-385.dtsi b/dts/src/arm/armada-385.dtsi index f011009bf4..6283d7912f 100644 --- a/dts/src/arm/armada-385.dtsi +++ b/dts/src/arm/armada-385.dtsi @@ -16,7 +16,7 @@ / { model = "Marvell Armada 385 family SoC"; - compatible = "marvell,armada385", "marvell,armada38x"; + compatible = "marvell,armada385", "marvell,armada380"; cpus { #address-cells = <1>; diff --git a/dts/src/arm/armada-38x.dtsi b/dts/src/arm/armada-38x.dtsi index 3de364e81b..689fa1a467 100644 --- a/dts/src/arm/armada-38x.dtsi +++ b/dts/src/arm/armada-38x.dtsi @@ -20,7 +20,7 @@ / { model = "Marvell Armada 38x family SoC"; - compatible = "marvell,armada38x"; + compatible = "marvell,armada380"; aliases { gpio0 = &gpio0; diff --git a/dts/src/arm/at91sam9261.dtsi b/dts/src/arm/at91sam9261.dtsi index b309c1c6e8..04927db1d6 100644 --- a/dts/src/arm/at91sam9261.dtsi +++ b/dts/src/arm/at91sam9261.dtsi @@ -568,24 +568,17 @@ #size-cells = <0>; #interrupt-cells = <1>; - slow_rc_osc: slow_rc_osc { - compatible = "fixed-clock"; + main_osc: main_osc { + compatible = "atmel,at91rm9200-clk-main-osc"; #clock-cells = <0>; - clock-frequency = <32768>; - clock-accuracy = <50000000>; - }; - - clk32k: slck { - compatible = "atmel,at91sam9260-clk-slow"; - #clock-cells = <0>; - clocks = <&slow_rc_osc &slow_xtal>; + interrupts-extended = <&pmc AT91_PMC_MOSCS>; + clocks = <&main_xtal>; }; main: mainck { compatible = "atmel,at91rm9200-clk-main"; #clock-cells = <0>; - interrupts-extended = <&pmc AT91_PMC_MOSCS>; - clocks = <&main_xtal>; + clocks = <&main_osc>; }; plla: pllack { @@ -615,7 +608,7 @@ compatible = "atmel,at91rm9200-clk-master"; #clock-cells = <0>; interrupts-extended = <&pmc AT91_PMC_MCKRDY>; - clocks = <&clk32k>, <&main>, <&plla>, <&pllb>; + clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>; atmel,clk-output-range = <0 94000000>; atmel,clk-divisors = <1 2 4 0>; }; @@ -632,7 +625,7 @@ #address-cells = <1>; #size-cells = <0>; interrupt-parent = <&pmc>; - clocks = <&clk32k>, <&main>, <&plla>, <&pllb>; + clocks = <&slow_xtal>, <&main>, <&plla>, <&pllb>; prog0: prog0 { #clock-cells = <0>; diff --git a/dts/src/arm/at91sam9261ek.dts b/dts/src/arm/at91sam9261ek.dts index c6683ea8b7..aa35a7aec9 100644 --- a/dts/src/arm/at91sam9261ek.dts +++ b/dts/src/arm/at91sam9261ek.dts @@ -20,6 +20,10 @@ reg = <0x20000000 0x4000000>; }; + slow_xtal { + clock-frequency = <32768>; + }; + main_xtal { clock-frequency = <18432000>; }; diff --git a/dts/src/arm/at91sam9n12.dtsi b/dts/src/arm/at91sam9n12.dtsi index d1b82e6635..b84bac5bad 100644 --- a/dts/src/arm/at91sam9n12.dtsi +++ b/dts/src/arm/at91sam9n12.dtsi @@ -132,8 +132,8 @@ <595000000 650000000 3 0>, <545000000 600000000 0 1>, <495000000 555000000 1 1>, - <445000000 500000000 1 2>, - <400000000 450000000 1 3>; + <445000000 500000000 2 1>, + <400000000 450000000 3 1>; }; plladiv: plladivck { @@ -925,7 +925,7 @@ compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00500000 0x00100000>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>; - clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>, + clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck"; status = "disabled"; diff --git a/dts/src/arm/at91sam9x5.dtsi b/dts/src/arm/at91sam9x5.dtsi index 1a57298636..2c0d6ea3ab 100644 --- a/dts/src/arm/at91sam9x5.dtsi +++ b/dts/src/arm/at91sam9x5.dtsi @@ -140,8 +140,8 @@ 595000000 650000000 3 0 545000000 600000000 0 1 495000000 555000000 1 1 - 445000000 500000000 1 2 - 400000000 450000000 1 3>; + 445000000 500000000 2 1 + 400000000 450000000 3 1>; }; plladiv: plladivck { @@ -1045,6 +1045,8 @@ reg = <0x00500000 0x80000 0xf803c000 0x400>; interrupts = <23 IRQ_TYPE_LEVEL_HIGH 0>; + clocks = <&usb>, <&udphs_clk>; + clock-names = "hclk", "pclk"; status = "disabled"; ep0 { @@ -1122,6 +1124,7 @@ compatible = "atmel,at91sam9rl-pwm"; reg = <0xf8034000 0x300>; interrupts = <18 IRQ_TYPE_LEVEL_HIGH 4>; + clocks = <&pwm_clk>; #pwm-cells = <3>; status = "disabled"; }; @@ -1153,8 +1156,7 @@ compatible = "atmel,at91rm9200-ohci", "usb-ohci"; reg = <0x00600000 0x100000>; interrupts = <22 IRQ_TYPE_LEVEL_HIGH 2>; - clocks = <&usb>, <&uhphs_clk>, <&udphs_clk>, - <&uhpck>; + clocks = <&usb>, <&uhphs_clk>, <&uhphs_clk>, <&uhpck>; clock-names = "usb_clk", "ohci_clk", "hclk", "uhpck"; status = "disabled"; }; diff --git a/dts/src/arm/dra7-evm.dts b/dts/src/arm/dra7-evm.dts index 4adc28039c..83089540e3 100644 --- a/dts/src/arm/dra7-evm.dts +++ b/dts/src/arm/dra7-evm.dts @@ -240,6 +240,7 @@ regulator-name = "ldo3"; regulator-min-microvolt = <1800000>; regulator-max-microvolt = <1800000>; + regulator-always-on; regulator-boot-on; }; diff --git a/dts/src/arm/dra7.dtsi b/dts/src/arm/dra7.dtsi index c29945e07c..80127638b3 100644 --- a/dts/src/arm/dra7.dtsi +++ b/dts/src/arm/dra7.dtsi @@ -773,7 +773,6 @@ clocks = <&qspi_gfclk_div>; clock-names = "fck"; num-cs = <4>; - interrupts = <0 343 0x4>; status = "disabled"; }; @@ -984,6 +983,17 @@ #size-cells = <1>; status = "disabled"; }; + + atl: atl@4843c000 { + compatible = "ti,dra7-atl"; + reg = <0x4843c000 0x3ff>; + ti,hwmods = "atl"; + ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>, + <&atl_clkin2_ck>, <&atl_clkin3_ck>; + clocks = <&atl_gfclk_mux>; + clock-names = "fck"; + status = "disabled"; + }; }; }; diff --git a/dts/src/arm/dra7xx-clocks.dtsi b/dts/src/arm/dra7xx-clocks.dtsi index b03cfe49d2..dc7a292fe9 100644 --- a/dts/src/arm/dra7xx-clocks.dtsi +++ b/dts/src/arm/dra7xx-clocks.dtsi @@ -10,26 +10,26 @@ &cm_core_aon_clocks { atl_clkin0_ck: atl_clkin0_ck { #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; + compatible = "ti,dra7-atl-clock"; + clocks = <&atl_gfclk_mux>; }; atl_clkin1_ck: atl_clkin1_ck { #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; + compatible = "ti,dra7-atl-clock"; + clocks = <&atl_gfclk_mux>; }; atl_clkin2_ck: atl_clkin2_ck { #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; + compatible = "ti,dra7-atl-clock"; + clocks = <&atl_gfclk_mux>; }; atl_clkin3_ck: atl_clkin3_ck { #clock-cells = <0>; - compatible = "fixed-clock"; - clock-frequency = <0>; + compatible = "ti,dra7-atl-clock"; + clocks = <&atl_gfclk_mux>; }; hdmi_clkin_ck: hdmi_clkin_ck { @@ -673,10 +673,12 @@ l3_iclk_div: l3_iclk_div { #clock-cells = <0>; - compatible = "fixed-factor-clock"; + compatible = "ti,divider-clock"; + ti,max-div = <2>; + ti,bit-shift = <4>; + reg = <0x0100>; clocks = <&dpll_core_h12x2_ck>; - clock-mult = <1>; - clock-div = <1>; + ti,index-power-of-two; }; l4_root_clk_div: l4_root_clk_div { @@ -684,7 +686,7 @@ compatible = "fixed-factor-clock"; clocks = <&l3_iclk_div>; clock-mult = <1>; - clock-div = <1>; + clock-div = <2>; }; video1_clk2_div: video1_clk2_div { diff --git a/dts/src/arm/exynos4.dtsi b/dts/src/arm/exynos4.dtsi index b8ece4be41..17b22e9cc2 100644 --- a/dts/src/arm/exynos4.dtsi +++ b/dts/src/arm/exynos4.dtsi @@ -113,7 +113,7 @@ compatible = "arm,cortex-a9-gic"; #interrupt-cells = <3>; interrupt-controller; - reg = <0x10490000 0x1000>, <0x10480000 0x100>; + reg = <0x10490000 0x10000>, <0x10480000 0x10000>; }; combiner: interrupt-controller@10440000 { @@ -554,7 +554,7 @@ interrupts = <0 37 0>, <0 38 0>, <0 39 0>, <0 40 0>, <0 41 0>; clocks = <&clock CLK_PWM>; clock-names = "timers"; - #pwm-cells = <2>; + #pwm-cells = <3>; status = "disabled"; }; diff --git a/dts/src/arm/exynos5420.dtsi b/dts/src/arm/exynos5420.dtsi index e38532271e..15957227ff 100644 --- a/dts/src/arm/exynos5420.dtsi +++ b/dts/src/arm/exynos5420.dtsi @@ -167,7 +167,7 @@ compatible = "samsung,exynos5420-audss-clock"; reg = <0x03810000 0x0C>; #clock-cells = <1>; - clocks = <&clock CLK_FIN_PLL>, <&clock CLK_FOUT_EPLL>, + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MAU_EPLL>, <&clock CLK_SCLK_MAUDIO0>, <&clock CLK_SCLK_MAUPCM0>; clock-names = "pll_ref", "pll_in", "sclk_audio", "sclk_pcm_in"; }; @@ -260,6 +260,9 @@ mfc_pd: power-domain@10044060 { compatible = "samsung,exynos4210-pd"; reg = <0x10044060 0x20>; + clocks = <&clock CLK_FIN_PLL>, <&clock CLK_MOUT_SW_ACLK333>, + <&clock CLK_MOUT_USER_ACLK333>; + clock-names = "oscclk", "pclk0", "clk0"; }; disp_pd: power-domain@100440C0 { diff --git a/dts/src/arm/hi3620.dtsi b/dts/src/arm/hi3620.dtsi index ab1116d086..83a5b8685b 100644 --- a/dts/src/arm/hi3620.dtsi +++ b/dts/src/arm/hi3620.dtsi @@ -73,7 +73,7 @@ L2: l2-cache { compatible = "arm,pl310-cache"; - reg = <0xfc10000 0x100000>; + reg = <0x100000 0x100000>; interrupts = <0 15 4>; cache-unified; cache-level = <2>; diff --git a/dts/src/arm/imx51-babbage.dts b/dts/src/arm/imx51-babbage.dts index 6bc3243a80..181d77fa2f 100644 --- a/dts/src/arm/imx51-babbage.dts +++ b/dts/src/arm/imx51-babbage.dts @@ -315,15 +315,15 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1>; - fsl,cd-controller; - fsl,wp-controller; + cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; + wp-gpios = <&gpio1 1 GPIO_ACTIVE_HIGH>; status = "okay"; }; &esdhc2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc2>; - cd-gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>; + cd-gpios = <&gpio1 6 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio1 5 GPIO_ACTIVE_HIGH>; status = "okay"; }; @@ -468,8 +468,8 @@ MX51_PAD_SD1_DATA1__SD1_DATA1 0x20d5 MX51_PAD_SD1_DATA2__SD1_DATA2 0x20d5 MX51_PAD_SD1_DATA3__SD1_DATA3 0x20d5 - MX51_PAD_GPIO1_0__SD1_CD 0x20d5 - MX51_PAD_GPIO1_1__SD1_WP 0x20d5 + MX51_PAD_GPIO1_0__GPIO1_0 0x100 + MX51_PAD_GPIO1_1__GPIO1_1 0x100 >; }; diff --git a/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts b/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts index 75e66c9c61..31cfb7f2b0 100644 --- a/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts +++ b/dts/src/arm/imx51-eukrea-mbimxsd51-baseboard.dts @@ -107,7 +107,7 @@ &esdhc1 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_esdhc1 &pinctrl_esdhc1_cd>; - fsl,cd-controller; + cd-gpios = <&gpio1 0 GPIO_ACTIVE_LOW>; status = "okay"; }; @@ -206,7 +206,7 @@ pinctrl_esdhc1_cd: esdhc1_cd { fsl,pins = < - MX51_PAD_GPIO1_0__SD1_CD 0x20d5 + MX51_PAD_GPIO1_0__GPIO1_0 0xd5 >; }; diff --git a/dts/src/arm/imx53-m53evk.dts b/dts/src/arm/imx53-m53evk.dts index d5d146a8b1..c4956b0ffb 100644 --- a/dts/src/arm/imx53-m53evk.dts +++ b/dts/src/arm/imx53-m53evk.dts @@ -21,27 +21,25 @@ <0xb0000000 0x20000000>; }; - soc { - display1: display@di1 { - compatible = "fsl,imx-parallel-display"; - interface-pix-fmt = "bgr666"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_ipu_disp1>; - - display-timings { - 800x480p60 { - native-mode; - clock-frequency = <31500000>; - hactive = <800>; - vactive = <480>; - hfront-porch = <40>; - hback-porch = <88>; - hsync-len = <128>; - vback-porch = <33>; - vfront-porch = <9>; - vsync-len = <3>; - vsync-active = <1>; - }; + display1: display@di1 { + compatible = "fsl,imx-parallel-display"; + interface-pix-fmt = "bgr666"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_ipu_disp1>; + + display-timings { + 800x480p60 { + native-mode; + clock-frequency = <31500000>; + hactive = <800>; + vactive = <480>; + hfront-porch = <40>; + hback-porch = <88>; + hsync-len = <128>; + vback-porch = <33>; + vfront-porch = <9>; + vsync-len = <3>; + vsync-active = <1>; }; }; diff --git a/dts/src/arm/imx6dl-hummingboard.dts b/dts/src/arm/imx6dl-hummingboard.dts index 5373a5f278..c8e51dd41b 100644 --- a/dts/src/arm/imx6dl-hummingboard.dts +++ b/dts/src/arm/imx6dl-hummingboard.dts @@ -143,6 +143,14 @@ fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x1b0b0>; }; + pinctrl_hummingboard_usbotg_id: hummingboard-usbotg-id { + /* + * Similar to pinctrl_usbotg_2, but we want it + * pulled down for a fixed host connection. + */ + fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>; + }; + pinctrl_hummingboard_usbotg_vbus: hummingboard-usbotg-vbus { fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x1b0b0>; }; @@ -178,6 +186,8 @@ }; &usbotg { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hummingboard_usbotg_id>; vbus-supply = <®_usbotg_vbus>; status = "okay"; }; diff --git a/dts/src/arm/imx6q-embedsky-e9.dtsi b/dts/src/arm/imx6q-embedsky-e9.dtsi new file mode 100644 index 0000000000..a29de9f3c4 --- /dev/null +++ b/dts/src/arm/imx6q-embedsky-e9.dtsi @@ -0,0 +1,395 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * Copyright 2011 Linaro Ltd. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include <dt-bindings/gpio/gpio.h> +#include <dt-bindings/input/input.h> + +/ { + model = "Embedsky E9"; + compatible = "embedsky,e9", "fsl,imx6q"; + + regulators { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <0>; + + reg_2p5v: regulator@0 { + compatible = "regulator-fixed"; + reg = <0>; + regulator-name = "2P5V"; + regulator-min-microvolt = <2500000>; + regulator-max-microvolt = <2500000>; + regulator-always-on; + }; + + reg_3p3v: regulator@1 { + compatible = "regulator-fixed"; + reg = <1>; + regulator-name = "3P3V"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + reg_usb_otg_vbus: regulator@2 { + compatible = "regulator-fixed"; + reg = <2>; + regulator-name = "usb_otg_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio3 22 0>; + enable-active-high; + }; + + reg_usb_h1_vbus: regulator@3 { + compatible = "regulator-fixed"; + reg = <3>; + regulator-name = "usb_h1_vbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio1 29 0>; + enable-active-high; + }; + + }; + + gpio-keys { + compatible = "gpio-keys"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_gpio_keys>; + + power { + label = "Power Button"; + gpios = <&gpio6 31 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + linux,code = <KEY_POWER>; + }; + + volume-up { + label = "Volume Up"; + gpios = <&gpio4 8 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + linux,code = <KEY_VOLUMEUP>; + }; + + volume-down { + label = "Volume Down"; + gpios = <&gpio4 9 GPIO_ACTIVE_LOW>; + gpio-key,wakeup; + linux,code = <KEY_VOLUMEDOWN>; + }; + }; + +}; + +&audmux { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_audmux>; + status = "okay"; +}; + +&fec { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_enet>; + phy-mode = "rgmii"; + phy-supply=<®_3p3v>; + status = "okay"; +}; + +&i2c1 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c1>; + status = "okay"; + +}; + +&i2c2 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c2>; + status = "okay"; +}; + +&i2c3 { + clock-frequency = <100000>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2c3>; + status = "okay"; +}; + +&iomuxc { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_hog>; + + imx6qdl-embedsky-e9 { + pinctrl_hog: hoggrp { + fsl,pins = < + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000 + MX6QDL_PAD_NANDF_D0__GPIO2_IO00 0x80000000 + MX6QDL_PAD_NANDF_D1__GPIO2_IO01 0x80000000 + MX6QDL_PAD_NANDF_D2__GPIO2_IO02 0x80000000 + MX6QDL_PAD_NANDF_D3__GPIO2_IO03 0x80000000 + MX6QDL_PAD_GPIO_0__CCM_CLKO1 0x130b0 + MX6QDL_PAD_NANDF_CLE__GPIO6_IO07 0x80000000 + MX6QDL_PAD_ENET_TXD1__GPIO1_IO29 0x80000000 + MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x80000000 + >; + }; + + pinctrl_audmux: audmuxgrp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT7__AUD3_RXD 0x130b0 + MX6QDL_PAD_CSI0_DAT4__AUD3_TXC 0x130b0 + MX6QDL_PAD_CSI0_DAT5__AUD3_TXD 0x110b0 + MX6QDL_PAD_CSI0_DAT6__AUD3_TXFS 0x130b0 + >; + }; + + pinctrl_ecspi1: ecspi1grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL1__ECSPI1_MISO 0x100b1 + MX6QDL_PAD_KEY_ROW0__ECSPI1_MOSI 0x100b1 + MX6QDL_PAD_KEY_COL0__ECSPI1_SCLK 0x100b1 + >; + }; + + pinctrl_enet: enetgrp { + fsl,pins = < + MX6QDL_PAD_ENET_MDIO__ENET_MDIO 0x1b0b0 + MX6QDL_PAD_ENET_MDC__ENET_MDC 0x1b0b0 + MX6QDL_PAD_RGMII_TXC__RGMII_TXC 0x1b0b0 + MX6QDL_PAD_RGMII_TD0__RGMII_TD0 0x1b0b0 + MX6QDL_PAD_RGMII_TD1__RGMII_TD1 0x1b0b0 + MX6QDL_PAD_RGMII_TD2__RGMII_TD2 0x1b0b0 + MX6QDL_PAD_RGMII_TD3__RGMII_TD3 0x1b0b0 + MX6QDL_PAD_RGMII_TX_CTL__RGMII_TX_CTL 0x1b0b0 + MX6QDL_PAD_ENET_REF_CLK__ENET_TX_CLK 0x1b0b0 + MX6QDL_PAD_RGMII_RXC__RGMII_RXC 0x1b0b0 + MX6QDL_PAD_RGMII_RD0__RGMII_RD0 0x1b0b0 + MX6QDL_PAD_RGMII_RD1__RGMII_RD1 0x1b0b0 + MX6QDL_PAD_RGMII_RD2__RGMII_RD2 0x1b0b0 + MX6QDL_PAD_RGMII_RD3__RGMII_RD3 0x1b0b0 + MX6QDL_PAD_RGMII_RX_CTL__RGMII_RX_CTL 0x1b0b0 + MX6QDL_PAD_ENET_CRS_DV__GPIO1_IO25 0x4001b0a8 + MX6QDL_PAD_GPIO_16__ENET_REF_CLK 0x4001b0a8 + MX6QDL_PAD_ENET_RXD1__GPIO1_IO26 0x4001b0a8 + >; + }; + + pinctrl_gpio_keys: gpio_keysgrp { + fsl,pins = < + MX6QDL_PAD_EIM_BCLK__GPIO6_IO31 0x80000000 + MX6QDL_PAD_KEY_COL1__KEY_COL1 0x80000000 + MX6QDL_PAD_KEY_ROW1__KEY_ROW1 0x80000000 + >; + }; + + pinctrl_i2c1: i2c1grp { + fsl,pins = < + MX6QDL_PAD_CSI0_DAT8__I2C1_SDA 0x4001b8b1 + MX6QDL_PAD_CSI0_DAT9__I2C1_SCL 0x4001b8b1 + >; + }; + + pinctrl_i2c2: i2c2grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL3__I2C2_SCL 0x4001b8b1 + MX6QDL_PAD_KEY_ROW3__I2C2_SDA 0x4001b8b1 + >; + }; + + pinctrl_i2c3: i2c3grp { + fsl,pins = < + MX6QDL_PAD_GPIO_3__I2C3_SCL 0x4001b8b1 + MX6QDL_PAD_GPIO_6__I2C3_SDA 0x4001b8b1 + >; + }; + + pinctrl_uart1: uart1grp { + fsl,pins = < + MX6QDL_PAD_SD3_DAT7__UART1_TX_DATA 0x1b0b1 + MX6QDL_PAD_SD3_DAT6__UART1_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart2: uart2grp { + fsl,pins = < + MX6QDL_PAD_EIM_D26__UART2_RX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D27__UART2_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D28__UART2_DTE_CTS_B 0x1b0b1 + MX6QDL_PAD_EIM_D29__UART2_DTE_RTS_B 0x1b0b1 + >; + }; + + pinctrl_uart3: uart3grp { + fsl,pins = < + MX6QDL_PAD_EIM_D24__UART3_TX_DATA 0x1b0b1 + MX6QDL_PAD_EIM_D25__UART3_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_uart4: uart4grp { + fsl,pins = < + MX6QDL_PAD_KEY_COL0__UART4_TX_DATA 0x1b0b1 + MX6QDL_PAD_KEY_ROW0__UART4_RX_DATA 0x1b0b1 + >; + }; + + pinctrl_usbotg: usbotggrp { + fsl,pins = < + MX6QDL_PAD_ENET_RX_ER__USB_OTG_ID 0x17059 + >; + }; + + pinctrl_usdhc1: usdhc1grp { + fsl,pins = < + MX6QDL_PAD_SD1_CMD__SD1_CMD 0x17059 + MX6QDL_PAD_SD1_CLK__SD1_CLK 0x10059 + MX6QDL_PAD_SD1_DAT0__SD1_DATA0 0x17059 + MX6QDL_PAD_SD1_DAT1__SD1_DATA1 0x17059 + MX6QDL_PAD_SD1_DAT2__SD1_DATA2 0x17059 + MX6QDL_PAD_SD1_DAT3__SD1_DATA3 0x17059 + >; + }; + + pinctrl_usdhc2: usdhc2grp { + fsl,pins = < + MX6QDL_PAD_SD2_CMD__SD2_CMD 0x17059 + MX6QDL_PAD_SD2_CLK__SD2_CLK 0x10059 + MX6QDL_PAD_SD2_DAT0__SD2_DATA0 0x17059 + MX6QDL_PAD_SD2_DAT1__SD2_DATA1 0x17059 + MX6QDL_PAD_SD2_DAT2__SD2_DATA2 0x17059 + MX6QDL_PAD_SD2_DAT3__SD2_DATA3 0x17059 + MX6QDL_PAD_GPIO_4__GPIO1_IO04 0x1f071 + >; + }; + + pinctrl_usdhc3: usdhc3grp { + fsl,pins = < + MX6QDL_PAD_SD3_CMD__SD3_CMD 0x17059 + MX6QDL_PAD_SD3_CLK__SD3_CLK 0x10059 + MX6QDL_PAD_SD3_DAT0__SD3_DATA0 0x17059 + MX6QDL_PAD_SD3_DAT1__SD3_DATA1 0x17059 + MX6QDL_PAD_SD3_DAT2__SD3_DATA2 0x17059 + MX6QDL_PAD_SD3_DAT3__SD3_DATA3 0x17059 + >; + }; + + pinctrl_usdhc4: usdhc4grp { + fsl,pins = < + MX6QDL_PAD_SD4_CMD__SD4_CMD 0x17059 + MX6QDL_PAD_SD4_CLK__SD4_CLK 0x10059 + MX6QDL_PAD_SD4_DAT0__SD4_DATA0 0x17059 + MX6QDL_PAD_SD4_DAT1__SD4_DATA1 0x17059 + MX6QDL_PAD_SD4_DAT2__SD4_DATA2 0x17059 + MX6QDL_PAD_SD4_DAT3__SD4_DATA3 0x17059 + MX6QDL_PAD_SD4_DAT4__SD4_DATA4 0x17059 + MX6QDL_PAD_SD4_DAT5__SD4_DATA5 0x17059 + MX6QDL_PAD_SD4_DAT6__SD4_DATA6 0x17059 + MX6QDL_PAD_SD4_DAT7__SD4_DATA7 0x17059 + >; + }; + }; +}; + +&ldb { + status = "okay"; +}; + +&uart1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart1>; + status = "okay"; +}; + +&uart2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart2>; + status = "okay"; +}; + +&uart3 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_uart4>; + status = "okay"; +}; + +&usbh1 { + vbus-supply = <®_usb_h1_vbus>; + status = "okay"; +}; + +&usbotg { + vbus-supply = <®_usb_otg_vbus>; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usbotg>; + disable-over-current; + status = "okay"; +}; + +&usdhc1 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc1>; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&usdhc2 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc2>; + cd-gpios = <&gpio1 4 0>; + vmmc-supply = <®_3p3v>; + status = "okay"; +}; + +&usdhc4 { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_usdhc4>; + vmmc-supply = <®_3p3v>; + non-removable; + status = "okay"; +}; + +&ldb { + status = "okay"; +}; + +&hdmi { + status = "okay"; +}; + +&pcie { + status = "okay"; +}; + +&can1 { + status = "okay"; +}; + +&sata { + status = "okay"; +}; + +&usdhc3 { + status = "disabled"; +}; + +&ecspi1 { + status = "disabled"; +}; diff --git a/dts/src/arm/imx6q-gw51xx.dts b/dts/src/arm/imx6q-gw51xx.dts index af4929aee0..0e1406e58e 100644 --- a/dts/src/arm/imx6q-gw51xx.dts +++ b/dts/src/arm/imx6q-gw51xx.dts @@ -11,7 +11,7 @@ /dts-v1/; #include "imx6q.dtsi" -#include "imx6qdl-gw54xx.dtsi" +#include "imx6qdl-gw51xx.dtsi" / { model = "Gateworks Ventana i.MX6 Quad GW51XX"; diff --git a/dts/src/arm/imx6qdl-cubox-i.dtsi b/dts/src/arm/imx6qdl-cubox-i.dtsi index 25da82a031..e8e781656b 100644 --- a/dts/src/arm/imx6qdl-cubox-i.dtsi +++ b/dts/src/arm/imx6qdl-cubox-i.dtsi @@ -12,6 +12,19 @@ pinctrl-0 = <&pinctrl_cubox_i_ir>; }; + pwmleds { + compatible = "pwm-leds"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_pwm1>; + + front { + active-low; + label = "imx6:red:front"; + max-brightness = <248>; + pwms = <&pwm1 0 50000>; + }; + }; + regulators { compatible = "simple-bus"; @@ -109,6 +122,10 @@ >; }; + pinctrl_cubox_i_pwm1: cubox-i-pwm1-front-led { + fsl,pins = <MX6QDL_PAD_DISP0_DAT8__PWM1_OUT 0x1b0b0>; + }; + pinctrl_cubox_i_spdif: cubox-i-spdif { fsl,pins = <MX6QDL_PAD_GPIO_17__SPDIF_OUT 0x13091>; }; @@ -117,6 +134,14 @@ fsl,pins = <MX6QDL_PAD_GPIO_0__GPIO1_IO00 0x4001b0b0>; }; + pinctrl_cubox_i_usbotg_id: cubox-i-usbotg-id { + /* + * The Cubox-i pulls this low, but as it's pointless + * leaving it as a pull-up, even if it is just 10uA. + */ + fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>; + }; + pinctrl_cubox_i_usbotg_vbus: cubox-i-usbotg-vbus { fsl,pins = <MX6QDL_PAD_EIM_D22__GPIO3_IO22 0x4001b0b0>; }; @@ -153,6 +178,8 @@ }; &usbotg { + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_cubox_i_usbotg_id>; vbus-supply = <®_usbotg_vbus>; status = "okay"; }; diff --git a/dts/src/arm/imx6qdl-gw51xx.dtsi b/dts/src/arm/imx6qdl-gw51xx.dtsi index 31665adcbf..0db15af41c 100644 --- a/dts/src/arm/imx6qdl-gw51xx.dtsi +++ b/dts/src/arm/imx6qdl-gw51xx.dtsi @@ -161,7 +161,7 @@ status = "okay"; pmic: ltc3676@3c { - compatible = "ltc,ltc3676"; + compatible = "lltc,ltc3676"; reg = <0x3c>; regulators { diff --git a/dts/src/arm/imx6qdl-gw52xx.dtsi b/dts/src/arm/imx6qdl-gw52xx.dtsi index 367af3ec94..744c8a2d81 100644 --- a/dts/src/arm/imx6qdl-gw52xx.dtsi +++ b/dts/src/arm/imx6qdl-gw52xx.dtsi @@ -220,7 +220,7 @@ }; pmic: ltc3676@3c { - compatible = "ltc,ltc3676"; + compatible = "lltc,ltc3676"; reg = <0x3c>; regulators { @@ -288,7 +288,7 @@ codec: sgtl5000@0a { compatible = "fsl,sgtl5000"; reg = <0x0a>; - clocks = <&clks 169>; + clocks = <&clks 201>; VDDA-supply = <®_1p8v>; VDDIO-supply = <®_3p3v>; }; diff --git a/dts/src/arm/imx6qdl-gw53xx.dtsi b/dts/src/arm/imx6qdl-gw53xx.dtsi index c91b5a6c76..adf150c1be 100644 --- a/dts/src/arm/imx6qdl-gw53xx.dtsi +++ b/dts/src/arm/imx6qdl-gw53xx.dtsi @@ -234,7 +234,7 @@ }; pmic: ltc3676@3c { - compatible = "ltc,ltc3676"; + compatible = "lltc,ltc3676"; reg = <0x3c>; regulators { diff --git a/dts/src/arm/imx6qdl-microsom.dtsi b/dts/src/arm/imx6qdl-microsom.dtsi index d729d0b15f..79eac6849d 100644 --- a/dts/src/arm/imx6qdl-microsom.dtsi +++ b/dts/src/arm/imx6qdl-microsom.dtsi @@ -10,14 +10,6 @@ MX6QDL_PAD_CSI0_DAT11__UART1_RX_DATA 0x1b0b1 >; }; - - pinctrl_microsom_usbotg: microsom-usbotg { - /* - * Similar to pinctrl_usbotg_2, but we want it - * pulled down for a fixed host connection. - */ - fsl,pins = <MX6QDL_PAD_GPIO_1__USB_OTG_ID 0x13059>; - }; }; }; @@ -26,8 +18,3 @@ pinctrl-0 = <&pinctrl_microsom_uart1>; status = "okay"; }; - -&usbotg { - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_microsom_usbotg>; -}; diff --git a/dts/src/arm/imx6sl.dtsi b/dts/src/arm/imx6sl.dtsi index 2d4e5285f3..57d4abe03a 100644 --- a/dts/src/arm/imx6sl.dtsi +++ b/dts/src/arm/imx6sl.dtsi @@ -686,7 +686,7 @@ compatible = "fsl,imx6sl-fec", "fsl,imx25-fec"; reg = <0x02188000 0x4000>; interrupts = <0 114 IRQ_TYPE_LEVEL_HIGH>; - clocks = <&clks IMX6SL_CLK_ENET_REF>, + clocks = <&clks IMX6SL_CLK_ENET>, <&clks IMX6SL_CLK_ENET_REF>; clock-names = "ipg", "ahb"; status = "disabled"; diff --git a/dts/src/arm/kirkwood-guruplug-server-plus.dts b/dts/src/arm/kirkwood-guruplug-server-plus.dts index c5a1fc75c7..b2d9834bf4 100644 --- a/dts/src/arm/kirkwood-guruplug-server-plus.dts +++ b/dts/src/arm/kirkwood-guruplug-server-plus.dts @@ -105,7 +105,6 @@ compatible = "ethernet-phy-id0141.0cb0", "ethernet-phy-ieee802.3-c22"; reg = <0>; - phy-connection-type = "rgmii-id"; }; ethphy1: ethernet-phy@1 { @@ -113,7 +112,6 @@ compatible = "ethernet-phy-id0141.0cb0", "ethernet-phy-ieee802.3-c22"; reg = <1>; - phy-connection-type = "rgmii-id"; }; }; @@ -121,6 +119,7 @@ status = "okay"; ethernet0-port@0 { phy-handle = <ðphy0>; + phy-connection-type = "rgmii-id"; }; }; @@ -128,5 +127,6 @@ status = "okay"; ethernet1-port@0 { phy-handle = <ðphy1>; + phy-connection-type = "rgmii-id"; }; }; diff --git a/dts/src/arm/omap3-beagle-xm.dts b/dts/src/arm/omap3-beagle-xm.dts index cf0be66229..1becefce82 100644 --- a/dts/src/arm/omap3-beagle-xm.dts +++ b/dts/src/arm/omap3-beagle-xm.dts @@ -251,6 +251,11 @@ codec { }; }; + + twl_power: power { + compatible = "ti,twl4030-power-beagleboard-xm", "ti,twl4030-power-idle-osc-off"; + ti,use_poweroff; + }; }; }; @@ -301,6 +306,7 @@ }; &uart3 { + interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>; pinctrl-names = "default"; pinctrl-0 = <&uart3_pins>; }; diff --git a/dts/src/arm/omap3-evm-common.dtsi b/dts/src/arm/omap3-evm-common.dtsi index 8ae8f007c8..c8747c7f1c 100644 --- a/dts/src/arm/omap3-evm-common.dtsi +++ b/dts/src/arm/omap3-evm-common.dtsi @@ -50,6 +50,13 @@ gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>; }; +&twl { + twl_power: power { + compatible = "ti,twl4030-power-omap3-evm", "ti,twl4030-power-idle"; + ti,use_poweroff; + }; +}; + &i2c2 { clock-frequency = <400000>; }; diff --git a/dts/src/arm/omap3-n900.dts b/dts/src/arm/omap3-n900.dts index ae8ae3f4f9..b15f1a77d6 100644 --- a/dts/src/arm/omap3-n900.dts +++ b/dts/src/arm/omap3-n900.dts @@ -351,6 +351,11 @@ compatible = "ti,twl4030-audio"; ti,enable-vibra = <1>; }; + + twl_power: power { + compatible = "ti,twl4030-power-n900"; + ti,use_poweroff; + }; }; &twl_keypad { diff --git a/dts/src/arm/omap5.dtsi b/dts/src/arm/omap5.dtsi index 3bfda16c8b..a4ed549888 100644 --- a/dts/src/arm/omap5.dtsi +++ b/dts/src/arm/omap5.dtsi @@ -45,7 +45,6 @@ operating-points = < /* kHz uV */ - 500000 880000 1000000 1060000 1500000 1250000 >; diff --git a/dts/src/arm/r8a7791.dtsi b/dts/src/arm/r8a7791.dtsi index 8d7ffaeff6..79f68acfd5 100644 --- a/dts/src/arm/r8a7791.dtsi +++ b/dts/src/arm/r8a7791.dtsi @@ -540,9 +540,9 @@ #clock-cells = <0>; clock-output-names = "sd1"; }; - sd2_clk: sd3_clk@e615007c { + sd2_clk: sd3_clk@e615026c { compatible = "renesas,r8a7791-div6-clock", "renesas,cpg-div6-clock"; - reg = <0 0xe615007c 0 4>; + reg = <0 0xe615026c 0 4>; clocks = <&pll1_div2_clk>; #clock-cells = <0>; clock-output-names = "sd2"; diff --git a/dts/src/arm/ste-nomadik-s8815.dts b/dts/src/arm/ste-nomadik-s8815.dts index f557feb997..90d8b6c7a2 100644 --- a/dts/src/arm/ste-nomadik-s8815.dts +++ b/dts/src/arm/ste-nomadik-s8815.dts @@ -4,7 +4,7 @@ */ /dts-v1/; -/include/ "ste-nomadik-stn8815.dtsi" +#include "ste-nomadik-stn8815.dtsi" / { model = "Calao Systems USB-S8815"; diff --git a/dts/src/arm/ste-nomadik-stn8815.dtsi b/dts/src/arm/ste-nomadik-stn8815.dtsi index d316c955bd..dbcf521b01 100644 --- a/dts/src/arm/ste-nomadik-stn8815.dtsi +++ b/dts/src/arm/ste-nomadik-stn8815.dtsi @@ -1,7 +1,9 @@ /* * Device Tree for the ST-Ericsson Nomadik 8815 STn8815 SoC */ -/include/ "skeleton.dtsi" + +#include <dt-bindings/gpio/gpio.h> +#include "skeleton.dtsi" / { #address-cells = <1>; @@ -842,8 +844,7 @@ bus-width = <4>; cap-mmc-highspeed; cap-sd-highspeed; - cd-gpios = <&gpio3 15 0x1>; - cd-inverted; + cd-gpios = <&gpio3 15 GPIO_ACTIVE_LOW>; pinctrl-names = "default"; pinctrl-0 = <&mmcsd_default_mux>, <&mmcsd_default_mode>; vmmc-supply = <&vmmc_regulator>; diff --git a/dts/src/arm/stih415.dtsi b/dts/src/arm/stih415.dtsi index d6f254f302..a0f6f75fe3 100644 --- a/dts/src/arm/stih415.dtsi +++ b/dts/src/arm/stih415.dtsi @@ -169,8 +169,8 @@ pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mii0>; - clock-names = "stmmaceth"; - clocks = <&clk_s_a1_ls CLK_GMAC0_PHY>; + clock-names = "stmmaceth", "sti-ethclk"; + clocks = <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>; }; ethernet1: dwmac@fef08000 { @@ -192,8 +192,8 @@ reset-names = "stmmaceth"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mii1>; - clock-names = "stmmaceth"; - clocks = <&clk_s_a0_ls CLK_ETH1_PHY>; + clock-names = "stmmaceth", "sti-ethclk"; + clocks = <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>; }; rc: rc@fe518000 { diff --git a/dts/src/arm/stih416-b2020-revE.dts b/dts/src/arm/stih416-b2020e.dts index ba0fa2caaf..ba0fa2caaf 100644 --- a/dts/src/arm/stih416-b2020-revE.dts +++ b/dts/src/arm/stih416-b2020e.dts diff --git a/dts/src/arm/stih416.dtsi b/dts/src/arm/stih416.dtsi index 06473c5d9e..84758d76d0 100644 --- a/dts/src/arm/stih416.dtsi +++ b/dts/src/arm/stih416.dtsi @@ -175,8 +175,8 @@ reset-names = "stmmaceth"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mii0>; - clock-names = "stmmaceth"; - clocks = <&clk_s_a1_ls CLK_GMAC0_PHY>; + clock-names = "stmmaceth", "sti-ethclk"; + clocks = <&clk_s_a1_ls CLK_ICN_IF_2>, <&clk_s_a1_ls CLK_GMAC0_PHY>; }; ethernet1: dwmac@fef08000 { @@ -197,8 +197,8 @@ reset-names = "stmmaceth"; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_mii1>; - clock-names = "stmmaceth"; - clocks = <&clk_s_a0_ls CLK_ETH1_PHY>; + clock-names = "stmmaceth", "sti-ethclk"; + clocks = <&clk_s_a0_ls CLK_ICN_REG>, <&clk_s_a0_ls CLK_ETH1_PHY>; }; rc: rc@fe518000 { diff --git a/fs/Kconfig b/fs/Kconfig index 3724b34f9a..64fc1176a6 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -41,6 +41,21 @@ config FS_NFS bool prompt "nfs support" +config FS_EFI + depends on ARCH_EFI + bool + prompt "EFI filesystem support" + help + This filesystem driver provides access to the filesystems provided + by the EFI Firmware via the EFI Simple File System Protocol. + +config FS_EFIVARFS + depends on ARCH_EFI + bool + prompt "EFI variable filesystem support (efivarfs)" + help + This filesystem driver provides access to EFI variables. + source fs/fat/Kconfig source fs/ubifs/Kconfig diff --git a/fs/Makefile b/fs/Makefile index d3465edfa5..f5aae91a60 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -11,3 +11,5 @@ obj-$(CONFIG_FS_OMAP4_USBBOOT) += omap4_usbbootfs.o obj-$(CONFIG_FS_NFS) += nfs.o parseopt.o obj-$(CONFIG_FS_BPKFS) += bpkfs.o obj-$(CONFIG_FS_UIMAGEFS) += uimagefs.o +obj-$(CONFIG_FS_EFI) += efi.o +obj-$(CONFIG_FS_EFIVARFS) += efivarfs.o diff --git a/fs/efi.c b/fs/efi.c new file mode 100644 index 0000000000..f096f91f58 --- /dev/null +++ b/fs/efi.c @@ -0,0 +1,563 @@ +/* + * efi.c - EFI filesystem mirror driver + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <fs.h> +#include <string.h> +#include <command.h> +#include <errno.h> +#include <linux/stat.h> +#include <xfuncs.h> +#include <fcntl.h> +#include <wchar.h> +#include <efi.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +/* Open modes */ +#define EFI_FILE_MODE_READ 0x0000000000000001 +#define EFI_FILE_MODE_WRITE 0x0000000000000002 +#define EFI_FILE_MODE_CREATE 0x8000000000000000 + +/* File attributes */ +#define EFI_FILE_READ_ONLY 0x0000000000000001 +#define EFI_FILE_HIDDEN 0x0000000000000002 +#define EFI_FILE_SYSTEM 0x0000000000000004 +#define EFI_FILE_RESERVIED 0x0000000000000008 +#define EFI_FILE_DIRECTORY 0x0000000000000010 +#define EFI_FILE_ARCHIVE 0x0000000000000020 +#define EFI_FILE_VALID_ATTR 0x0000000000000037 + +#define EFI_FILE_HANDLE_REVISION 0x00010000 +struct efi_file_handle { + uint64_t Revision; + efi_status_t(EFIAPI *open)(struct efi_file_handle *File, + struct efi_file_handle **NewHandle, s16 *FileName, + uint64_t OpenMode, uint64_t Attributes); + efi_status_t(EFIAPI *close)(struct efi_file_handle *File); + efi_status_t(EFIAPI *delete)(struct efi_file_handle *File); + efi_status_t(EFIAPI *read)(struct efi_file_handle *File, unsigned long *BufferSize, + void *Buffer); + efi_status_t(EFIAPI *write)(struct efi_file_handle *File, + unsigned long *BufferSize, void *Buffer); + efi_status_t(EFIAPI *get_position)(struct efi_file_handle *File, + uint64_t *Position); + efi_status_t(EFIAPI *set_position)(struct efi_file_handle *File, + uint64_t Position); + efi_status_t(EFIAPI *get_info)(struct efi_file_handle *File, + efi_guid_t *InformationType, unsigned long *BufferSize, + void *Buffer); + efi_status_t(EFIAPI *set_info)(struct efi_file_handle *File, + efi_guid_t *InformationType, unsigned long BufferSize, + void *Buffer); + efi_status_t(EFIAPI *flush)(struct efi_file_handle *File); +}; + +#define EFI_FILE_IO_INTERFACE_REVISION 0x00010000 + +struct efi_file_io_interface { + uint64_t Revision; + efi_status_t(EFIAPI *open_volume)( + struct efi_file_io_interface *This, + struct efi_file_handle **Root); +}; + +struct efi_file_info { + uint64_t Size; + uint64_t FileSize; + uint64_t PhysicalSize; + efi_time_t CreateTime; + efi_time_t LastAccessTime; + efi_time_t ModificationTime; + uint64_t Attribute; + s16 FileName[1]; +}; + +typedef unsigned short wchar_t; + +struct efifs_priv { + struct efi_file_handle *root_dir; + struct efi_file_io_interface *protocol; +}; + +struct efifs_file { + struct efi_file_handle *entry; +}; + +struct efifs_dir { + DIR dir; + struct efi_file_handle *entries; +}; + +static wchar_t *path_to_efi(const char *path) +{ + wchar_t *dst; + wchar_t *ret; + + if (!*path) + return strdup_char_to_wchar("\\"); + + dst = strdup_char_to_wchar(path); + if (!dst) + return NULL; + + ret = dst; + + while (*dst) { + if (*dst == '/') + *dst = '\\'; + dst++; + } + + return ret; +} + +static int efifs_create(struct device_d *dev, const char *pathname, mode_t mode) +{ + struct efifs_priv *priv = dev->priv; + wchar_t *efi_path = path_to_efi(pathname); + struct efi_file_handle *entry; + efi_status_t efiret; + + efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + 0ULL); + + free(efi_path); + + if (EFI_ERROR(efiret)) { + printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret)); + return -efi_errno(efiret); + } + + entry->close(entry); + + return 0; +} + +static int efifs_unlink(struct device_d *dev, const char *pathname) +{ + struct efifs_priv *priv = dev->priv; + wchar_t *efi_path = path_to_efi(pathname); + struct efi_file_handle *entry; + efi_status_t efiret; + + efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE, 0ULL); + + free(efi_path); + + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + efiret = entry->delete(entry); + if (EFI_ERROR(efiret)) + return -efi_errno(efiret); + + return 0; +} + +static int efifs_mkdir(struct device_d *dev, const char *pathname) +{ + struct efifs_priv *priv = dev->priv; + wchar_t *efi_path = path_to_efi(pathname); + struct efi_file_handle *entry; + efi_status_t efiret; + + efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, + EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, + EFI_FILE_DIRECTORY); + + free(efi_path); + + if (EFI_ERROR(efiret)) { + printf("%s %s: %s\n", __func__, pathname, efi_strerror(efiret)); + return -efi_errno(efiret); + } + + entry->close(entry); + + return 0; +} + +static int efifs_rmdir(struct device_d *dev, const char *pathname) +{ + return efifs_unlink(dev, pathname); +} + +static int efifs_open(struct device_d *dev, FILE *f, const char *filename) +{ + struct efifs_priv *priv = dev->priv; + efi_status_t efiret; + struct efifs_file *ufile; + wchar_t *efi_path = path_to_efi(filename); + struct efi_file_info *info; + unsigned long bufsize = 1024; + uint64_t efimode = EFI_FILE_MODE_READ; + int ret; + + ufile = xzalloc(sizeof(*ufile)); + + if (f->flags & O_ACCMODE) + efimode |= EFI_FILE_MODE_WRITE; + + efiret = priv->root_dir->open(priv->root_dir, &ufile->entry, efi_path, + efimode, 0ULL); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to Open %s: %s\n", __func__, + filename, efi_strerror(efiret)); + free(ufile); + return -efi_errno(efiret); + } + + free(efi_path); + + info = xzalloc(1024); + efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to GetInfo %s: %s\n", __func__, + filename, efi_strerror(efiret)); + ret = -efi_errno(efiret); + goto out; + } + + f->size = info->FileSize; + + free(info); + f->inode = ufile; + + return 0; +out: + free(info); + free(ufile); + return ret; +} + +static int efifs_close(struct device_d *dev, FILE *f) +{ + struct efifs_file *ufile = f->inode; + + ufile->entry->close(ufile->entry); + + free(ufile); + + return 0; +} + +static int efifs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) +{ + struct efifs_file *ufile = f->inode; + efi_status_t efiret; + unsigned long bufsize = insize; + + efiret = ufile->entry->read(ufile->entry, &bufsize, buf); + if (EFI_ERROR(efiret)) { + return -efi_errno(efiret); + } + + return bufsize; +} + +static int efifs_write(struct device_d *_dev, FILE *f, const void *buf, size_t insize) +{ + struct efifs_file *ufile = f->inode; + efi_status_t efiret; + unsigned long bufsize = insize; + + efiret = ufile->entry->write(ufile->entry, &bufsize, (void *)buf); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to write: %s\n", __func__, efi_strerror(efiret)); + return -efi_errno(efiret); + } + + return bufsize; +} + +static loff_t efifs_lseek(struct device_d *dev, FILE *f, loff_t pos) +{ + struct efifs_file *ufile = f->inode; + efi_status_t efiret; + + f->pos = pos; + + efiret = ufile->entry->set_position(ufile->entry, pos); + if (EFI_ERROR(efiret)) { + return -efi_errno(efiret); + } + + return f->pos; +} + +static int efifs_truncate(struct device_d *dev, FILE *f, unsigned long size) +{ + struct efifs_file *ufile = f->inode; + efi_status_t efiret; + struct efi_file_info *info; + unsigned long bufsize = 1024; + int ret; + + info = xzalloc(1024); + + efiret = ufile->entry->get_info(ufile->entry, &efi_file_info_id, &bufsize, info); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to GetInfo: %s\n", __func__, efi_strerror(efiret)); + ret = -efi_errno(efiret); + goto out; + } + + if (size > info->FileSize) + return 0; + + info->FileSize = size; + + efiret = ufile->entry->set_info(ufile->entry, &efi_file_info_id, bufsize, info); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to SetInfo: %s\n", __func__, efi_strerror(efiret)); + ret = -efi_errno(efiret); + goto out; + } + + return 0; +out: + return ret; +} + +static DIR *efifs_opendir(struct device_d *dev, const char *pathname) +{ + struct efifs_priv *priv = dev->priv; + efi_status_t efiret; + struct efifs_dir *udir; + wchar_t *efi_path = path_to_efi(pathname); + + udir = xzalloc(sizeof(*udir)); + + efiret = priv->root_dir->open(priv->root_dir, &udir->entries, efi_path, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(efiret)) { + free(udir); + return NULL; + } + + free(efi_path); + + return &udir->dir; +} + +static struct dirent *efifs_readdir(struct device_d *dev, DIR *dir) +{ + struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir); + efi_status_t efiret; + unsigned long bufsize = 256; + s16 buf[256]; + struct efi_file_info *f; + + efiret = udir->entries->read(udir->entries, &bufsize, buf); + if (EFI_ERROR(efiret) || bufsize == 0) + return NULL; + + f = (struct efi_file_info *)buf; + + strcpy_wchar_to_char(dir->d.d_name, f->FileName); + + return &dir->d; +} + +static int efifs_closedir(struct device_d *dev, DIR *dir) +{ + struct efifs_dir *udir = container_of(dir, struct efifs_dir, dir); + + udir->entries->close(udir->entries); + + free(dir); + + return 0; +} + +static int efifs_stat(struct device_d *dev, const char *filename, struct stat *s) +{ + struct efifs_priv *priv = dev->priv; + wchar_t *efi_path; + efi_status_t efiret; + struct efi_file_handle *entry; + struct efi_file_info *info; + unsigned long bufsize = 1024; + int ret; + + info = xzalloc(1024); + + efi_path = path_to_efi(filename); + + efiret = priv->root_dir->open(priv->root_dir, &entry, efi_path, EFI_FILE_MODE_READ, 0ULL); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to Open %s: %s\n", __func__, filename, + efi_strerror(efiret)); + ret = -efi_errno(efiret); + goto out_free; + } + + efiret = entry->get_info(entry, &efi_file_info_id, &bufsize, info); + if (EFI_ERROR(efiret)) { + pr_err("%s: unable to GetInfo %s: %s\n", __func__, filename, + efi_strerror(efiret)); + ret = -efi_errno(efiret); + goto out; + } + + s->st_size = info->FileSize; + s->st_mode = 00555; + + if (!info->Attribute & EFI_FILE_READ_ONLY) + s->st_mode |= 00222; + + if (info->Attribute & EFI_FILE_DIRECTORY) + s->st_mode |= S_IFDIR; + else + s->st_mode |= S_IFREG; + + ret = 0; +out: + entry->close(entry); +out_free: + free(efi_path); + free(info); + + return ret; +} + +static int efifs_symlink(struct device_d *dev, const char *pathname, + const char *newpath) +{ + return -EROFS; +} + +static int efifs_readlink(struct device_d *dev, const char *pathname, + char *buf, size_t bufsiz) +{ + return -ENOENT; +} + +static int efifs_probe(struct device_d *dev) +{ + struct fs_device_d *fsdev = dev_to_fs_device(dev); + struct efifs_priv *priv; + efi_status_t efiret; + struct efi_file_handle *file; + struct device_d *efi = get_device_by_name(fsdev->backingstore); + struct efi_device *udev = container_of(efi, struct efi_device, dev); + + priv = xzalloc(sizeof(struct efifs_priv)); + priv->protocol = udev->protocol; + dev->priv = priv; + dev->parent = &udev->dev; + + efiret = priv->protocol->open_volume(priv->protocol, &file); + if (EFI_ERROR(efiret)) { + dev_err(dev, "failed to open volume: %s\n", efi_strerror(efiret)); + return -efi_errno(efiret); + } + + priv->root_dir = file; + + return 0; +} + +static void efifs_remove(struct device_d *dev) +{ + free(dev->priv); +} + +static struct fs_driver_d efifs_driver = { + .create = efifs_create, + .unlink = efifs_unlink, + .open = efifs_open, + .close = efifs_close, + .truncate = efifs_truncate, + .read = efifs_read, + .write = efifs_write, + .lseek = efifs_lseek, + .mkdir = efifs_mkdir, + .rmdir = efifs_rmdir, + .opendir = efifs_opendir, + .readdir = efifs_readdir, + .closedir = efifs_closedir, + .stat = efifs_stat, + .symlink = efifs_symlink, + .readlink = efifs_readlink, + .drv = { + .probe = efifs_probe, + .remove = efifs_remove, + .name = "efifs", + } +}; + +static int efifs_init(void) +{ + return register_fs_driver(&efifs_driver); +} + +coredevice_initcall(efifs_init); + +static int index; + +int efi_fs_probe(struct efi_device *efidev) +{ + char *path, *device; + int ret; + struct efi_file_io_interface *volume; + + if (efi_loaded_image) + BS->handle_protocol(efi_loaded_image->device_handle, + &efi_simple_file_system_protocol_guid, (void*)&volume); + + if (efidev->protocol == volume) + path = xstrdup("/boot"); + else + path = asprintf("/efi%d", index); + device = asprintf("%s", dev_name(&efidev->dev)); + + ret = make_directory(path); + if (ret) + goto out; + + ret = mount(device, "efifs", path, NULL); + if (ret) + goto out; + + index++; + + dev_info(&efidev->dev, "mounted on %s\n", path); + + ret = 0; +out: + free(path); + free(device); + + return ret; +} + +static struct efi_driver efi_fs_driver = { + .driver = { + .name = "efi-fs", + }, + .probe = efi_fs_probe, + .guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID, +}; +device_efi_driver(efi_fs_driver); diff --git a/fs/efivarfs.c b/fs/efivarfs.c new file mode 100644 index 0000000000..58c637ef19 --- /dev/null +++ b/fs/efivarfs.c @@ -0,0 +1,340 @@ +/* + * ramfs.c - a malloc based filesystem + * + * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <common.h> +#include <driver.h> +#include <init.h> +#include <malloc.h> +#include <fs.h> +#include <string.h> +#include <errno.h> +#include <linux/stat.h> +#include <xfuncs.h> +#include <fcntl.h> +#include <efi.h> +#include <wchar.h> +#include <linux/err.h> +#include <linux/ctype.h> +#include <mach/efi.h> +#include <mach/efi-device.h> + +struct efivarfs_priv { + struct efi_file_handle *root_dir; + struct efi_file_io_interface *protocol; +}; + +static int char_to_nibble(char c) +{ + int ret = tolower(c); + + return ret <= '9' ? ret - '0' : ret - 'a' + 10; +} + +static int read_byte_str(const char *str, u8 *out) +{ + if (!isxdigit(*str) || !isxdigit(*(str + 1))) + return -EINVAL; + + *out = (char_to_nibble(*str) << 4) | char_to_nibble(*(str + 1)); + + return 0; +} + +int efi_guid_parse(const char *str, efi_guid_t *guid) +{ + int i, ret; + u8 idx[] = { 3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15 }; + + for (i = 0; i < 16; i++) { + ret = read_byte_str(str, &guid->b[idx[i]]); + if (ret) + return ret; + str += 2; + + switch (i) { + case 3: + case 5: + case 7: + case 9: + if (*str != '-') + return -EINVAL; + str++; + break; + } + } + + return 0; +} + +static int efivarfs_parse_filename(const char *filename, efi_guid_t *vendor, s16 **name) +{ + int len, ret; + const char *guidstr; + s16 *varname; + int i; + + if (*filename == '/') + filename++; + + len = strlen(filename); + + if (len < sizeof("-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) + return -EINVAL; + + guidstr = filename + len - sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"); + if (*guidstr != '-') + return -EINVAL; + + guidstr++; + + ret = efi_guid_parse(guidstr, vendor); + + varname = xzalloc((guidstr - filename) * sizeof(s16)); + + for (i = 0; i < guidstr - filename - 1; i++) + varname[i] = filename[i]; + + *name = varname; + + return 0; +} + +struct efivars_file { + void *buf; + unsigned long size; + efi_guid_t vendor; + s16 *name; +}; + +static int efivarfs_open(struct device_d *dev, FILE *f, const char *filename) +{ + struct efivars_file *efile; + efi_status_t efiret; + int ret; + uint32_t attributes; + + efile = xzalloc(sizeof(*efile)); + + ret = efivarfs_parse_filename(filename, &efile->vendor, &efile->name); + if (ret) + return -ENOENT; + + efiret = RT->get_variable(efile->name, &efile->vendor, &attributes, &efile->size, NULL); + if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) { + ret = -efi_errno(efiret); + goto out; + } + + efile->buf = malloc(efile->size + sizeof(uint32_t)); + if (!efile->buf) { + ret = -ENOMEM; + goto out; + } + + efiret = RT->get_variable(efile->name, &efile->vendor, NULL, &efile->size, + efile->buf + sizeof(uint32_t)); + if (EFI_ERROR(efiret)) { + ret = -efi_errno(efiret); + goto out; + } + + *(uint32_t *)efile->buf = attributes; + + f->size = efile->size + sizeof(uint32_t); + f->inode = efile; + + return 0; + +out: + free(efile->buf); + free(efile); + + return ret; +} + +static int efivarfs_close(struct device_d *dev, FILE *f) +{ + struct efivars_file *efile = f->inode; + + free(efile->buf); + free(efile); + + return 0; +} + +static int efivarfs_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) +{ + struct efivars_file *efile = f->inode; + + memcpy(buf, efile->buf + f->pos, insize); + + return insize; +} + +static loff_t efivarfs_lseek(struct device_d *dev, FILE *f, loff_t pos) +{ + f->pos = pos; + + return f->pos; +} + +struct efivarfs_dir_entry { + char *name; + struct efivarfs_dir_entry *next; +}; + +struct efivarfs_dir { + struct efivarfs_dir_entry *first; + struct efivarfs_dir_entry *current; + DIR dir; +}; + +static DIR *efivarfs_opendir(struct device_d *dev, const char *pathname) +{ + efi_status_t efiret; + efi_guid_t vendor; + s16 name[1024]; + struct efivarfs_dir *edir; + unsigned long size; + unsigned char *name8; + + name[0] = 0; + + edir = xzalloc(sizeof(*edir)); + + while (1) { + struct efivarfs_dir_entry *entry; + + size = sizeof(name); + efiret = RT->get_next_variable(&size, name, &vendor); + if (EFI_ERROR(efiret)) + break; + + entry = xzalloc(sizeof(*entry)); + name8 = strdup_wchar_to_char(name); + + entry->name = asprintf("%s-%pUl", name8, &vendor); + + free(name8); + + if (!edir->first) + edir->first = entry; + + if (edir->current) + edir->current->next = entry; + + edir->current = entry; + } + + edir->current = edir->first; + + return &edir->dir; +} + +static struct dirent *efivarfs_readdir(struct device_d *dev, DIR *dir) +{ + struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir); + + if (!edir->current) + return NULL; + + strcpy(dir->d.d_name, edir->current->name); + + edir->current = edir->current->next; + + return &dir->d; +} + +static int efivarfs_closedir(struct device_d *dev, DIR *dir) +{ + struct efivarfs_dir *edir = container_of(dir, struct efivarfs_dir, dir); + struct efivarfs_dir_entry *entry; + + entry = edir->first; + + while (entry) { + struct efivarfs_dir_entry *tmp; + free(entry->name); + tmp = entry->next; + free(entry); + entry = tmp; + } + + free(edir); + + return 0; +} + +static int efivarfs_stat(struct device_d *dev, const char *filename, struct stat *s) +{ + efi_guid_t vendor; + s16 *name; + efi_status_t efiret; + unsigned long size = 0; + int ret; + + ret = efivarfs_parse_filename(filename, &vendor, &name); + if (ret) + return -ENOENT; + + efiret = RT->get_variable(name, &vendor, NULL, &size, NULL); + + free(name); + + if (EFI_ERROR(efiret) && efiret != EFI_BUFFER_TOO_SMALL) + return -efi_errno(efiret); + + s->st_mode = 00666 | S_IFREG; + s->st_size = size; + + return 0; +} + +static int efivarfs_probe(struct device_d *dev) +{ + return 0; +} + +static void efivarfs_remove(struct device_d *dev) +{ + free(dev->priv); +} + +static struct fs_driver_d efivarfs_driver = { + .open = efivarfs_open, + .close = efivarfs_close, + .read = efivarfs_read, + .lseek = efivarfs_lseek, + .opendir = efivarfs_opendir, + .readdir = efivarfs_readdir, + .closedir = efivarfs_closedir, + .stat = efivarfs_stat, + .drv = { + .probe = efivarfs_probe, + .remove = efivarfs_remove, + .name = "efivarfs", + } +}; + +static int efivarfs_init(void) +{ + return register_fs_driver(&efivarfs_driver); +} + +coredevice_initcall(efivarfs_init); diff --git a/fs/ext4/ext4_common.c b/fs/ext4/ext4_common.c index ceb965f492..ab0e6b5fbc 100644 --- a/fs/ext4/ext4_common.c +++ b/fs/ext4/ext4_common.c @@ -45,12 +45,13 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data struct ext4_extent_idx *index; unsigned long long block; struct ext_filesystem *fs = data->fs; + int blksz = EXT2_BLOCK_SIZE(data); int i, ret; while (1) { index = (struct ext4_extent_idx *)(ext_block + 1); - if (le32_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) + if (le16_to_cpu(ext_block->eh_magic) != EXT4_EXT_MAGIC) return 0; if (ext_block->eh_depth == 0) @@ -58,17 +59,17 @@ static struct ext4_extent_header *ext4fs_get_extent_block(struct ext2_data *data i = -1; do { i++; - if (i >= le32_to_cpu(ext_block->eh_entries)) + if (i >= le16_to_cpu(ext_block->eh_entries)) break; - } while (fileblock > le32_to_cpu(index[i].ei_block)); + } while (fileblock >= le32_to_cpu(index[i].ei_block)); if (--i < 0) return 0; - block = le32_to_cpu(index[i].ei_leaf_hi); + block = le16_to_cpu(index[i].ei_leaf_hi); block = (block << 32) + le32_to_cpu(index[i].ei_leaf_lo); - ret = ext4fs_devread(fs, block << log2_blksz, 0, fs->blksz, buf); + ret = ext4fs_devread(fs, block << log2_blksz, 0, blksz, buf); if (ret) return NULL; else @@ -186,18 +187,18 @@ long int read_allocated_block(struct ext2fs_node *node, int fileblock) do { i++; - if (i >= le32_to_cpu(ext_block->eh_entries)) + if (i >= le16_to_cpu(ext_block->eh_entries)) break; } while (fileblock >= le32_to_cpu(extent[i].ee_block)); if (--i >= 0) { fileblock -= le32_to_cpu(extent[i].ee_block); - if (fileblock >= le32_to_cpu(extent[i].ee_len)) { + if (fileblock >= le16_to_cpu(extent[i].ee_len)) { free(buf); return 0; } - start = le32_to_cpu(extent[i].ee_start_hi); + start = le16_to_cpu(extent[i].ee_start_hi); start = (start << 32) + le32_to_cpu(extent[i].ee_start_lo); free(buf); diff --git a/fs/fat/fat.c b/fs/fat/fat.c index e65ef585a2..f8094d0608 100644 --- a/fs/fat/fat.c +++ b/fs/fat/fat.c @@ -167,7 +167,7 @@ static int fat_write(struct device_d *_dev, FILE *f, const void *buf, size_t ins ret = f_write(f_file, buf, insize, &outsize); - debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file); + debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file); if (ret) return ret; @@ -260,7 +260,7 @@ static int fat_read(struct device_d *_dev, FILE *f, void *buf, size_t insize) ret = f_read(f_file, buf, insize, &outsize); - debug("%s: %d %d %d %p\n", __func__, ret, insize, outsize, f_file); + debug("%s: %d %zd %d %p\n", __func__, ret, insize, outsize, f_file); if (ret) return ret; @@ -34,78 +34,6 @@ #include <libgen.h> #include <block.h> -void *read_file(const char *filename, size_t *size) -{ - int fd; - struct stat s; - void *buf = NULL; - const char *tmpfile = "/.read_file_tmp"; - int ret; - -again: - if (stat(filename, &s)) - return NULL; - - if (s.st_size == FILESIZE_MAX) { - ret = copy_file(filename, tmpfile, 0); - if (ret) - return NULL; - filename = tmpfile; - goto again; - } - - buf = xzalloc(s.st_size + 1); - - fd = open(filename, O_RDONLY); - if (fd < 0) - goto err_out; - - ret = read_full(fd, buf, s.st_size); - if (ret < 0) - goto err_out1; - - close(fd); - - if (size) - *size = s.st_size; - - if (filename == tmpfile) - unlink(tmpfile); - - return buf; - -err_out1: - close(fd); -err_out: - free(buf); - - if (filename == tmpfile) - unlink(tmpfile); - - return NULL; -} - -EXPORT_SYMBOL(read_file); - -int write_file(const char *filename, void *buf, size_t size) -{ - int fd, ret; - - fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT); - if (fd < 0) - return fd; - - ret = write_full(fd, buf, size); - - close(fd); - - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL(write_file); - char *mkmodestr(unsigned long mode, char *str) { static const char *l = "xwr"; diff --git a/fs/uimagefs.c b/fs/uimagefs.c index 6547b7cb77..63931c2d7d 100644 --- a/fs/uimagefs.c +++ b/fs/uimagefs.c @@ -17,6 +17,7 @@ #include <uimagefs.h> #include <libbb.h> #include <rtc.h> +#include <libfile.h> static bool uimagefs_is_data_file(struct uimagefs_handle_data *d) { diff --git a/images/.gitignore b/images/.gitignore index ec9e3c0bc6..d27e71a0c8 100644 --- a/images/.gitignore +++ b/images/.gitignore @@ -14,6 +14,8 @@ *.t30img.cfg *.t124img *.t124img.cfg +*.mlo +*.mlospi pbl.lds barebox.x barebox.z diff --git a/images/Makefile b/images/Makefile index 740c197754..738fcb6bd3 100644 --- a/images/Makefile +++ b/images/Makefile @@ -118,5 +118,5 @@ images: $(addprefix $(obj)/, $(image-y)) FORCE clean-files := *.pbl *.pblb *.pblx *.map start_*.imximg *.img barebox.z start_*.kwbimg \ start_*.kwbuartimg *.socfpgaimg *.mlo *.t20img *.t20img.cfg *.t30img \ - *.t30img.cfg *.t124img *.t124img.cfg + *.t30img.cfg *.t124img *.t124img.cfg *.mlospi *.mlo clean-files += pbl.lds diff --git a/images/Makefile.am33xx b/images/Makefile.am33xx index dacc2d123c..fa1f848816 100644 --- a/images/Makefile.am33xx +++ b/images/Makefile.am33xx @@ -11,9 +11,17 @@ pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sdram FILE_barebox-am33xx-phytec-phycore.img = start_am33xx_phytec_phycore_sdram.pblx am33xx-barebox-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore.img -pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram -FILE_barebox-am33xx-phytec-phycore-mlo.img = start_am33xx_phytec_phycore_sram.pblx.mlo -am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo.img +pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x256m16 +FILE_barebox-am33xx-phytec-phycore-mlo-1x256m16.img = start_am33xx_phytec_phycore_sram_1x256m16.pblx.mlo +am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x256m16.img + +pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x128m16 +FILE_barebox-am33xx-phytec-phycore-mlo-1x128m16.img = start_am33xx_phytec_phycore_sram_1x128m16.pblx.mlo +am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x128m16.img + +pblx-$(CONFIG_MACH_PCM051) += start_am33xx_phytec_phycore_sram_1x512m16 +FILE_barebox-am33xx-phytec-phycore-mlo-1x512m16.img = start_am33xx_phytec_phycore_sram_1x512m16.pblx.mlo +am33xx-mlo-$(CONFIG_MACH_PCM051) += barebox-am33xx-phytec-phycore-mlo-1x512m16.img pblx-$(CONFIG_MACH_BEAGLEBONE) += start_am33xx_beaglebone_sdram FILE_barebox-am33xx-beaglebone.img = start_am33xx_beaglebone_sdram.pblx diff --git a/images/Makefile.imx b/images/Makefile.imx index 1d0edd2fda..5ff72957c6 100644 --- a/images/Makefile.imx +++ b/images/Makefile.imx @@ -92,7 +92,6 @@ image-$(CONFIG_MACH_TQMA6X) += barebox-tq-tqma6q-mba6x.img pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib CFG_start_phytec_pbab01_4gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02-4gib.imxcfg -imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01_4gib.pblx.imximg FILE_barebox-phytec-pbab01-4gib.img = start_phytec_pbab01_4gib.pblx.imximg image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-4gib.img @@ -108,13 +107,11 @@ image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01-1gib.img pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib CFG_start_phytec_pbab01dl_1gib.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02dl-1gib.imxcfg -imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01dl_1gib.pblx.imximg FILE_barebox-phytec-pbab01dl-1gib.img = start_phytec_pbab01dl_1gib.pblx.imximg image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01dl-1gib.img pblx-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb CFG_start_phytec_pbab01s_512mb.pblx.imximg = $(board)/phytec-phyflex-imx6/flash-header-phytec-pfla02s-512mb.imxcfg -imximage-$(CONFIG_MACH_PHYTEC_PFLA02) += start_phytec_pbab01s_512mb.pblx.imximg FILE_barebox-phytec-pbab01s-512mb.img = start_phytec_pbab01s_512mb.pblx.imximg image-$(CONFIG_MACH_PHYTEC_PFLA02) += barebox-phytec-pbab01s-512mb.img @@ -125,13 +122,11 @@ image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6s.img pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_micron CFG_start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-micron.imxcfg -imximage-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg FILE_barebox-dfi-fs700-m60-6q-micron.img = start_imx6q_dfi_fs700_m60_6q_micron.pblx.imximg image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-micron.img pblx-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_nanya CFG_start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg = $(board)/dfi-fs700-m60/flash-header-fs700-m60-6q-nanya.imxcfg -imximage-$(CONFIG_MACH_DFI_FS700_M60) += start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg FILE_barebox-dfi-fs700-m60-6q-nanya.img = start_imx6q_dfi_fs700_m60_6q_nanya.pblx.imximg image-$(CONFIG_MACH_DFI_FS700_M60) += barebox-dfi-fs700-m60-6q-nanya.img @@ -175,6 +170,11 @@ CFG_start_variscite_custom.pblx.imximg = $(board)/variscite-mx6/flash-header-var FILE_barebox-variscite-custom.img = start_variscite_custom.pblx.imximg image-$(CONFIG_MACH_VARISCITE_MX6) += barebox-variscite-custom.img +pblx-$(CONFIG_MACH_EMBEDSKY_E9) += start_imx6q_embedsky_e9 +CFG_start_imx6q_embedsky_e9.pblx.imximg = $(board)/embedsky-e9/flash-header-e9.imxcfg +FILE_barebox-freescale-imx6q-embedsky-e9.img = start_imx6q_embedsky_e9.pblx.imximg +image-$(CONFIG_MACH_EMBEDSKY_E9) += barebox-freescale-imx6q-embedsky-e9.img + pblx-$(CONFIG_MACH_EMBEST_RIOTBOARD) += start_imx6s_riotboard CFG_start_imx6s_riotboard.pblx.imximg = $(board)/embest-riotboard/flash-header-embest-riotboard.imxcfg FILE_barebox-embest-imx6s-riotboard.img = start_imx6s_riotboard.pblx.imximg diff --git a/include/asm-generic/barebox.lds.h b/include/asm-generic/barebox.lds.h index 5dabda3fbb..66abff30fa 100644 --- a/include/asm-generic/barebox.lds.h +++ b/include/asm-generic/barebox.lds.h @@ -53,6 +53,12 @@ KEEP(*(.dtb.rodata.*)); \ __dtb_end = .; +#define BAREBOX_IMD \ + KEEP(*(.barebox_imd_start)) \ + KEEP(*(.barebox_imd_1*)) \ + *(.barebox_imd_0*) \ + KEEP(*(.barebox_imd_end)) + #if defined(CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE) && \ CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE < CONFIG_BAREBOX_MAX_BARE_INIT_SIZE #define MAX_BARE_INIT_SIZE CONFIG_ARCH_BAREBOX_MAX_BARE_INIT_SIZE diff --git a/include/block.h b/include/block.h index 872a4c1bba..91377679b0 100644 --- a/include/block.h +++ b/include/block.h @@ -9,6 +9,7 @@ struct block_device; struct block_device_ops { int (*read)(struct block_device *, void *buf, int block, int num_blocks); int (*write)(struct block_device *, const void *buf, int block, int num_blocks); + int (*flush)(struct block_device *); }; struct chunk; diff --git a/include/console.h b/include/console.h index 6da0199aba..97a406d9c9 100644 --- a/include/console.h +++ b/include/console.h @@ -39,11 +39,14 @@ struct console_device { int (*tstc)(struct console_device *cdev); void (*putc)(struct console_device *cdev, char c); + int (*puts)(struct console_device *cdev, const char *s); int (*getc)(struct console_device *cdev); int (*setbrg)(struct console_device *cdev, int baudrate); void (*flush)(struct console_device *cdev); int (*set_mode)(struct console_device *cdev, enum console_mode mode); + char *devname; + struct list_head list; unsigned char f_active; diff --git a/include/efi.h b/include/efi.h new file mode 100644 index 0000000000..4ad9f69237 --- /dev/null +++ b/include/efi.h @@ -0,0 +1,621 @@ +#ifndef _LINUX_EFI_H +#define _LINUX_EFI_H + +/* + * Extensible Firmware Interface + * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 + * + * Copyright (C) 1999 VA Linux Systems + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> + * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. + * David Mosberger-Tang <davidm@hpl.hp.com> + * Stephane Eranian <eranian@hpl.hp.com> + */ +#include <linux/string.h> +#include <linux/types.h> + +#ifdef CONFIG_ARCH_EFI +#define EFIAPI __attribute__((ms_abi)) +#else +#define EFIAPI +#endif + +struct efi_device_path; + +#define EFI_SUCCESS 0 +#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) +#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) +#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) +#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_READY ( 6 | (1UL << (BITS_PER_LONG-1))) +#define EFI_DEVICE_ERROR ( 7 | (1UL << (BITS_PER_LONG-1))) +#define EFI_WRITE_PROTECTED ( 8 | (1UL << (BITS_PER_LONG-1))) +#define EFI_OUT_OF_RESOURCES ( 9 | (1UL << (BITS_PER_LONG-1))) +#define EFI_VOLUME_CORRUPTED ( 10 | (1UL << (BITS_PER_LONG-1))) +#define EFI_VOLUME_FULL ( 11 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NO_MEDIA ( 12 | (1UL << (BITS_PER_LONG-1))) +#define EFI_MEDIA_CHANGED ( 13 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_FOUND ( 14 | (1UL << (BITS_PER_LONG-1))) +#define EFI_ACCESS_DENIED ( 15 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NO_RESPONSE ( 16 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NO_MAPPING ( 17 | (1UL << (BITS_PER_LONG-1))) +#define EFI_TIMEOUT ( 18 | (1UL << (BITS_PER_LONG-1))) +#define EFI_NOT_STARTED ( 19 | (1UL << (BITS_PER_LONG-1))) +#define EFI_ALREADY_STARTED ( 20 | (1UL << (BITS_PER_LONG-1))) +#define EFI_ABORTED ( 21 | (1UL << (BITS_PER_LONG-1))) +#define EFI_ICMP_ERROR ( 22 | (1UL << (BITS_PER_LONG-1))) +#define EFI_TFTP_ERROR ( 23 | (1UL << (BITS_PER_LONG-1))) +#define EFI_PROTOCOL_ERROR ( 24 | (1UL << (BITS_PER_LONG-1))) +#define EFI_INCOMPATIBLE_VERSION ( 25 | (1UL << (BITS_PER_LONG-1))) +#define EFI_SECURITY_VIOLATION ( 26 | (1UL << (BITS_PER_LONG-1))) +#define EFI_CRC_ERROR ( 27 | (1UL << (BITS_PER_LONG-1))) +#define EFI_END_OF_MEDIA ( 28 | (1UL << (BITS_PER_LONG-1))) +#define EFI_END_OF_FILE ( 31 | (1UL << (BITS_PER_LONG-1))) +#define EFI_INVALID_LANGUAGE ( 32 | (1UL << (BITS_PER_LONG-1))) +#define EFI_COMPROMISED_DATA ( 33 | (1UL << (BITS_PER_LONG-1))) + +#define EFI_ERROR(a) (((signed long) a) < 0) + +typedef unsigned long efi_status_t; +typedef u8 efi_bool_t; +typedef u16 efi_char16_t; /* UNICODE character */ +typedef u64 efi_physical_addr_t; +typedef void *efi_handle_t; + + +typedef struct { + u8 b[16]; +} efi_guid_t; + +#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ +((efi_guid_t) \ +{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ + (b) & 0xff, ((b) >> 8) & 0xff, \ + (c) & 0xff, ((c) >> 8) & 0xff, \ + (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) + +/* + * Generic EFI table header + */ +typedef struct { + u64 signature; + u32 revision; + u32 headersize; + u32 crc32; + u32 reserved; +} efi_table_hdr_t; + +/* + * Memory map descriptor: + */ + +/* Memory types: */ +#define EFI_RESERVED_TYPE 0 +#define EFI_LOADER_CODE 1 +#define EFI_LOADER_DATA 2 +#define EFI_BOOT_SERVICES_CODE 3 +#define EFI_BOOT_SERVICES_DATA 4 +#define EFI_RUNTIME_SERVICES_CODE 5 +#define EFI_RUNTIME_SERVICES_DATA 6 +#define EFI_CONVENTIONAL_MEMORY 7 +#define EFI_UNUSABLE_MEMORY 8 +#define EFI_ACPI_RECLAIM_MEMORY 9 +#define EFI_ACPI_MEMORY_NVS 10 +#define EFI_MEMORY_MAPPED_IO 11 +#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 +#define EFI_PAL_CODE 13 +#define EFI_MAX_MEMORY_TYPE 14 + +/* Attribute values: */ +#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ +#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ +#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ +#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ +#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ +#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ +#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ +#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 + +#define EFI_PAGE_SHIFT 12 +#define EFI_PAGE_SIZE (1UL << EFI_PAGE_SHIFT) + +/* + * Allocation types for calls to boottime->allocate_pages. + */ +#define EFI_ALLOCATE_ANY_PAGES 0 +#define EFI_ALLOCATE_MAX_ADDRESS 1 +#define EFI_ALLOCATE_ADDRESS 2 +#define EFI_MAX_ALLOCATE_TYPE 3 + +typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); + +/* + * Types and defines for Time Services + */ +#define EFI_TIME_ADJUST_DAYLIGHT 0x1 +#define EFI_TIME_IN_DAYLIGHT 0x2 +#define EFI_UNSPECIFIED_TIMEZONE 0x07ff + +typedef struct { + u16 year; + u8 month; + u8 day; + u8 hour; + u8 minute; + u8 second; + u8 pad1; + u32 nanosecond; + s16 timezone; + u8 daylight; + u8 pad2; +} efi_time_t; + +typedef struct { + u32 resolution; + u32 accuracy; + u8 sets_to_zero; +} efi_time_cap_t; + +enum efi_locate_search_type { + all_handles, + by_register_notify, + by_protocol +}; + +struct efi_open_protocol_information_entry { + efi_handle_t agent_handle; + efi_handle_t controller_handle; + u32 attributes; + u32 open_count; +}; + +/* + * EFI Boot Services table + */ +typedef struct { + efi_table_hdr_t hdr; + void *raise_tpl; + void *restore_tpl; + efi_status_t (EFIAPI *allocate_pages)(int, int, unsigned long, + efi_physical_addr_t *); + efi_status_t (EFIAPI *free_pages)(efi_physical_addr_t, unsigned long); + efi_status_t (EFIAPI *get_memory_map)(unsigned long *, void *, unsigned long *, + unsigned long *, u32 *); + efi_status_t (EFIAPI *allocate_pool)(int, unsigned long, void **); + efi_status_t (EFIAPI *free_pool)(void *); + void *create_event; + void *set_timer; + efi_status_t(EFIAPI *wait_for_event)(unsigned long number_of_events, void *event, + unsigned long *index); + void *signal_event; + void *close_event; + void *check_event; + void *install_protocol_interface; + void *reinstall_protocol_interface; + void *uninstall_protocol_interface; + efi_status_t (EFIAPI *handle_protocol)(efi_handle_t, efi_guid_t *, void **); + void *__reserved; + void *register_protocol_notify; + efi_status_t (EFIAPI *locate_handle) (enum efi_locate_search_type search_type, + efi_guid_t *protocol, void *search_key, + unsigned long *buffer_size, efi_handle_t *buffer); + efi_status_t (EFIAPI *locate_device_path)(efi_guid_t *protocol, + struct efi_device_path **device_path, efi_handle_t *device); + void *install_configuration_table; + efi_status_t (EFIAPI *load_image)(bool boot_policiy, efi_handle_t parent_image, + struct efi_device_path *file_path, void *source_buffer, + unsigned long source_size, efi_handle_t *image); + efi_status_t (EFIAPI *start_image)(efi_handle_t handle, + unsigned long *exitdata_size, s16 **exitdata); + efi_status_t(EFIAPI *exit)(efi_handle_t handle, efi_status_t exit_status, + unsigned long exitdata_size, s16 *exitdata); + void *unload_image; + efi_status_t (EFIAPI *exit_boot_services)(efi_handle_t, unsigned long); + void *get_next_monotonic_count; + efi_status_t (EFIAPI *stall)(unsigned long usecs); + void *set_watchdog_timer; + efi_status_t(EFIAPI *connect_controller)(efi_handle_t controller_handle, + efi_handle_t *driver_image_handle, + struct efi_device_path *remaining_device_path, + bool Recursive); + void *disconnect_controller; +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + efi_status_t (EFIAPI *open_protocol)(efi_handle_t handle, efi_guid_t *protocol, + void ** interface, efi_handle_t agent_handle, + efi_handle_t controller_handle, u32 attributes); + void *close_protocol; + efi_status_t(EFIAPI *open_protocol_information)(efi_handle_t handle, efi_guid_t *Protocol, + struct efi_open_protocol_information_entry **entry_buffer, + unsigned long *entry_count); + efi_status_t (EFIAPI *protocols_per_handle)(efi_handle_t handle, + efi_guid_t ***protocol_buffer, + unsigned long *protocols_buffer_count); + efi_status_t (EFIAPI *locate_handle_buffer) ( + enum efi_locate_search_type search_type, + efi_guid_t *protocol, void *search_key, + unsigned long *no_handles, efi_handle_t **buffer); + void *locate_protocol; + void *install_multiple_protocol_interfaces; + void *uninstall_multiple_protocol_interfaces; + void *calculate_crc32; + void *copy_mem; + void *set_mem; + void *create_event_ex; +} efi_boot_services_t; + +extern efi_boot_services_t *BS; + +/* + * Types and defines for EFI ResetSystem + */ +#define EFI_RESET_COLD 0 +#define EFI_RESET_WARM 1 +#define EFI_RESET_SHUTDOWN 2 + +/* + * EFI Runtime Services table + */ +#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) +#define EFI_RUNTIME_SERVICES_REVISION 0x00010000 + +typedef struct { + efi_table_hdr_t hdr; + void *get_time; + void *set_time; + void *get_wakeup_time; + void *set_wakeup_time; + void *set_virtual_address_map; + void *convert_pointer; + efi_status_t (EFIAPI *get_variable)(s16 *variable_name, efi_guid_t *vendor, + u32 *Attributes, unsigned long *data_size, void *data); + efi_status_t (EFIAPI *get_next_variable)(unsigned long *variable_name_size, + s16 *variable_name, efi_guid_t *vendor); + void *set_variable; + void *get_next_high_mono_count; + void *reset_system; + void *update_capsule; + void *query_capsule_caps; + void *query_variable_info; +} efi_runtime_services_t; + +extern efi_runtime_services_t *RT; + +/* + * EFI Configuration Table and GUID definitions + */ +#define EFI_NULL_GUID \ + EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) + +#define EFI_MPS_TABLE_GUID \ + EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define EFI_ACPI_TABLE_GUID \ + EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define EFI_ACPI_20_TABLE_GUID \ + EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 ) + +#define EFI_SMBIOS_TABLE_GUID \ + EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define EFI_SAL_SYSTEM_TABLE_GUID \ + EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) + +#define EFI_HCDP_TABLE_GUID \ + EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 ) + +#define EFI_UGA_IO_PROTOCOL_GUID \ + EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) + +#define EFI_GLOBAL_VARIABLE_GUID \ + EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c ) + +#define EFI_UV_SYSTEM_TABLE_GUID \ + EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 ) + +#define EFI_LINUX_EFI_CRASH_GUID \ + EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) + +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) + +#define EFI_UGA_PROTOCOL_GUID \ + EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) + +#define EFI_PCI_IO_PROTOCOL_GUID \ + EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) + +#define EFI_FILE_INFO_GUID \ + EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_SIMPLE_FILE_SYSTEM_GUID \ + EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_DEVICE_TREE_GUID \ + EFI_GUID( 0xb1b621d5, 0xf19c, 0x41a5, 0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0 ) + +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + EFI_GUID( 0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) + +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + EFI_GUID( 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D ) + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + EFI_GUID(0x0964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_UNKNOWN_DEVICE_GUID \ + EFI_GUID(0xcf31fac5, 0xc24e, 0x11d2, 0x85, 0xf3, 0x0, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b) + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + EFI_GUID(0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +/* additional GUID from EDK2 */ +#define EFI_FIRMWARE_VOLUME2_PROTOCOL_GUID \ + EFI_GUID(0x220e73b6, 0x6bdb, 0x4413, 0x84, 0x5, 0xb9, 0x74, 0xb1, 0x8, 0x61, 0x9a) + +#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \ + EFI_GUID(0x8f644fa9, 0xe850, 0x4db1, 0x9c, 0xe2, 0xb, 0x44, 0x69, 0x8e, 0x8d, 0xa4) + +#define EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_GUID \ + EFI_GUID(0x2f707ebb, 0x4a1a, 0x11d4, 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_ISA_ACPI_PROTOCOL_GUID \ + EFI_GUID(0x64a892dc, 0x5561, 0x4536, 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55) + +#define EFI_ISA_IO_PROTOCOL_GUID \ + EFI_GUID(0x7ee2bd44, 0x3da0, 0x11d4, 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_STANDARD_ERROR_DEVICE_GUID \ + EFI_GUID(0xd3b36f2d, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_CONSOLE_OUT_DEVICE_GUID \ + EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_CONSOLE_IN_DEVICE_GUID \ + EFI_GUID(0xd3b36f2b, 0xd551, 0x11d4, 0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d) + +#define EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID \ + EFI_GUID(0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \ + EFI_GUID(0xdd9e7534, 0x7762, 0x4698, 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa) + +#define EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID \ + EFI_GUID(0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_DISK_IO_PROTOCOL_GUID \ + EFI_GUID(0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \ + EFI_GUID(0xa1e37052, 0x80d9, 0x4e65, 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9) + +#define EFI_DISK_INFO_PROTOCOL_GUID \ + EFI_GUID(0xd432a67f, 0x14dc, 0x484b, 0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27) + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + EFI_GUID(0xbb25cf6f, 0xf1d4, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0xfd) + +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + EFI_GUID(0x3bc1b285, 0x8a15, 0x4a82, 0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65) + +#define EFI_LOAD_FILE2_PROTOCOL_GUID \ + EFI_GUID(0x4006c0c1, 0xfcb3, 0x403e, 0x99, 0x6d, 0x4a, 0x6c, 0x87, 0x24, 0xe0, 0x6d) + +#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x2fe800be, 0x8f01, 0x4aa6, 0x94, 0x6b, 0xd7, 0x13, 0x88, 0xe1, 0x83, 0x3f) + +#define EFI_DHCP4_PROTOCOL_GUID \ + EFI_GUID(0x9d9a39d8, 0xbd42, 0x4a73, 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80) + +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x83f01464, 0x99bd, 0x45e5, 0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6) + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0x00720665, 0x67EB, 0x4a99, 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9) + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0xc51711e7, 0xb4bf, 0x404a, 0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4) + +#define EFI_IP4_CONFIG_PROTOCOL_GUID \ + EFI_GUID(0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e) + +#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID\ + EFI_GUID(0xf44c00ee, 0x1f2c, 0x4a00, 0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3) + +#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \ + EFI_GUID(0xf36ff770, 0xa7e1, 0x42cf, 0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c) + +#define EFI_VLAN_CONFIG_PROTOCOL_GUID \ + EFI_GUID(0x9e23d768, 0xd2f3, 0x4366, 0x9f, 0xc3, 0x3a, 0x7a, 0xba, 0x86, 0x43, 0x74) + +#define EFI_HII_CONFIG_ACCESS_PROTOCOL_GUID \ + EFI_GUID(0x330d4706, 0xf2a0, 0x4e4f, 0xa3, 0x69, 0xb6, 0x6f, 0xa8, 0xd5, 0x43, 0x85) + +#define LOAD_FILE_PROTOCOL_GUID \ + EFI_GUID(0x56ec3091, 0x954c, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b) + +#define EFI_COMPONENT_NAME2_PROTOCOL_GUID \ + EFI_GUID(0x6a7a5cff, 0xe8d9, 0x4f70, 0xba, 0xda, 0x75, 0xab, 0x30, 0x25, 0xce, 0x14) + +#define EFI_IDEBUSDXE_INF_GUID \ + EFI_GUID(0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2) + +#define EFI_TERMINALDXE_INF_GUID \ + EFI_GUID(0x9e863906, 0xa40f, 0x4875, 0x97, 0x7f, 0x5b, 0x93, 0xff, 0x23, 0x7f, 0xc6) + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID_31 \ + EFI_GUID(0x1aced566, 0x76ed, 0x4218, 0xbc, 0x81, 0x76, 0x7f, 0x1f, 0x97, 0x7a, 0x89) + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + EFI_GUID(0xe18541cd, 0xf755, 0x4f73, 0x92, 0x8d, 0x64, 0x3c, 0x8a, 0x79, 0xb2, 0x29) + +#define EFI_ISCSIDXE_INF_GUID \ + EFI_GUID(0x4579b72d, 0x7ec4, 0x4dd4, 0x84, 0x86, 0x08, 0x3c, 0x86, 0xb1, 0x82, 0xa7) + +#define EFI_VLANCONFIGDXE_INF_GUID \ + EFI_GUID(0xe4f61863, 0xfe2c, 0x4b56, 0xa8, 0xf4, 0x08, 0x51, 0x9b, 0xc4, 0x39, 0xdf) + +extern efi_guid_t efi_file_info_id; +extern efi_guid_t efi_simple_file_system_protocol_guid; +extern efi_guid_t efi_device_path_protocol_guid; +extern efi_guid_t efi_loaded_image_protocol_guid; +extern efi_guid_t efi_unknown_device_guid; +extern efi_guid_t efi_null_guid; +extern efi_guid_t efi_global_variable_guid; +extern efi_guid_t efi_block_io_protocol_guid; + +#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) + +#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) +#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) +#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) + +typedef struct { + efi_table_hdr_t hdr; + unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ + u32 fw_revision; + unsigned long con_in_handle; + struct efi_simple_input_interface *con_in; + unsigned long con_out_handle; + struct efi_simple_text_output_protocol *con_out; + unsigned long stderr_handle; + unsigned long std_err; + efi_runtime_services_t *runtime; + efi_boot_services_t *boottime; + unsigned long nr_tables; + unsigned long tables; +} efi_system_table_t; + +typedef struct { + u32 revision; + void *parent_handle; + efi_system_table_t *system_table; + void *device_handle; + void *file_path; + void *reserved; + u32 load_options_size; + void *load_options; + void *image_base; + __aligned_u64 image_size; + unsigned int image_code_type; + unsigned int image_data_type; + unsigned long unload; +} efi_loaded_image_t; + +static inline int +efi_guidcmp (efi_guid_t left, efi_guid_t right) +{ + return memcmp(&left, &right, sizeof (efi_guid_t)); +} + +/* + * Variable Attributes + */ +#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008 +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010 +#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020 +#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040 + +#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \ + EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS | \ + EFI_VARIABLE_HARDWARE_ERROR_RECORD | \ + EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ + EFI_VARIABLE_APPEND_WRITE) +/* + * Length of a GUID string (strlen("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee")) + * not including trailing NUL + */ +#define EFI_VARIABLE_GUID_LEN 36 + +struct efi_device_path { + u8 type; + u8 sub_type; + u16 length; +} __attribute ((packed)); + +struct simple_text_output_mode { + s32 max_mode; + s32 mode; + s32 attribute; + s32 cursor_column; + s32 cursor_row; + bool cursor_visible; +}; + +struct efi_simple_text_output_protocol { + void *reset; + efi_status_t (EFIAPI *output_string)(void *, void *); + void *test_string; + + efi_status_t(EFIAPI *query_mode)(struct efi_simple_text_output_protocol *this, + unsigned long mode_number, unsigned long *columns, unsigned long *rows); + efi_status_t(EFIAPI *set_mode)(struct efi_simple_text_output_protocol *this, + unsigned long mode_number); + efi_status_t(EFIAPI *set_attribute)(struct efi_simple_text_output_protocol *this, + unsigned long attribute); + efi_status_t(EFIAPI *clear_screen) (struct efi_simple_text_output_protocol *this); + efi_status_t(EFIAPI *set_cursor_position) (struct efi_simple_text_output_protocol *this, + unsigned long column, unsigned long row); + efi_status_t(EFIAPI *enable_cursor)(void *, bool enable); + struct simple_text_output_mode *mode; +}; + +struct efi_input_key { + u16 scan_code; + s16 unicode_char; +}; + +struct efi_simple_input_interface { + efi_status_t(EFIAPI *reset)(struct efi_simple_input_interface *this, + bool ExtendedVerification); + efi_status_t(EFIAPI *read_key_stroke)(struct efi_simple_input_interface *this, + struct efi_input_key *key); + void *wait_for_key; +}; + +typedef struct { + uint8_t Addr[32]; +} efi_mac_address; + +typedef struct { + uint8_t Addr[4]; +} efi_ipv4_address; + +typedef struct { + uint8_t Addr[16]; +} efi_ipv6_address; + +typedef union { + uint32_t Addr[4]; + efi_ipv4_address v4; + efi_ipv6_address v6; +} efi_ip_address; + +static inline int efi_compare_guid(efi_guid_t *a, efi_guid_t *b) +{ + return memcmp(a, b, sizeof(efi_guid_t)); +} + +char *device_path_to_str(struct efi_device_path *dev_path); + +const char *efi_guid_string(efi_guid_t *g); + +#endif /* _LINUX_EFI_H */ diff --git a/include/envfs.h b/include/envfs.h index 9b86398984..fdcb8a8d97 100644 --- a/include/envfs.h +++ b/include/envfs.h @@ -43,6 +43,7 @@ struct envfs_super { uint8_t minor; /* minor */ uint16_t future; /* reserved for future use */ uint32_t flags; /* feature flags */ +#define ENVFS_FLAGS_FORCE_BUILT_IN (1 << 0) uint32_t sb_crc; /* crc for the superblock */ }; @@ -92,7 +93,7 @@ struct envfs_super { #define ENV_FLAG_NO_OVERWRITE (1 << 0) int envfs_load(const char *filename, const char *dirname, unsigned flags); -int envfs_save(const char *filename, const char *dirname); +int envfs_save(const char *filename, const char *dirname, unsigned flags); int envfs_load_from_buf(void *buf, int len, const char *dir, unsigned flags); /* defaults to /dev/env0 */ diff --git a/include/filetype.h b/include/filetype.h index c20a4f9395..eedf4b4afe 100644 --- a/include/filetype.h +++ b/include/filetype.h @@ -30,6 +30,9 @@ enum filetype { filetype_ubifs, filetype_bpk, filetype_barebox_env, + filetype_ch_image, + filetype_ch_image_be, + filetype_exe, filetype_max, }; diff --git a/include/fs.h b/include/fs.h index 073641c747..b2541a4ee5 100644 --- a/include/fs.h +++ b/include/fs.h @@ -164,20 +164,6 @@ int ls(const char *path, ulong flags); char *mkmodestr(unsigned long mode, char *str); /* - * Read a file into memory. Memory is allocated with malloc and must - * be freed with free() afterwards. This function allocates one - * byte more than actually needed and sets this to zero, so that - * it can be used for text files. - * If size is nonzero it s set to the file size. - */ -void *read_file(const char *filename, size_t *size); - -/* - * Write a buffer to a file. This file is newly created. - */ -int write_file(const char *filename, void *buf, size_t size); - -/* * This function turns 'path' into an absolute path and removes all occurrences * of "..", "." and double slashes. The returned string must be freed wit free(). */ diff --git a/include/i2c/i2c.h b/include/i2c/i2c.h index a107f5edb7..4696f43e31 100644 --- a/include/i2c/i2c.h +++ b/include/i2c/i2c.h @@ -85,6 +85,63 @@ struct i2c_client { #define to_i2c_client(a) container_of(a, struct i2c_client, dev) +/*flags for the client struct: */ +#define I2C_CLIENT_PEC 0x04 /* Use Packet Error Checking */ +#define I2C_CLIENT_SCCB 0x9000 /* Use Omnivision SCCB protocol */ + /* Must match I2C_M_STOP|IGNORE_NAK */ + +/* + * Data for SMBus Messages + */ +#define I2C_SMBUS_BLOCK_MAX 32 /* As specified in SMBus standard */ +union i2c_smbus_data { + __u8 byte; + __u16 word; + __u8 block[I2C_SMBUS_BLOCK_MAX + 2]; /* block[0] is used for length */ + /* and one more for user-space compatibility */ +}; + +/* i2c_smbus_xfer read or write markers */ +#define I2C_SMBUS_READ 1 +#define I2C_SMBUS_WRITE 0 + +/* SMBus transaction types (size parameter in the above functions) + Note: these no longer correspond to the (arbitrary) PIIX4 internal codes! */ +#define I2C_SMBUS_QUICK 0 +#define I2C_SMBUS_BYTE 1 +#define I2C_SMBUS_BYTE_DATA 2 +#define I2C_SMBUS_WORD_DATA 3 +#define I2C_SMBUS_I2C_BLOCK_DATA 8 + +/* This is the very generalized SMBus access routine. You probably do not + want to use this, though; one of the functions below may be much easier, + and probably just as fast. + Note that we use i2c_adapter here, because you do not need a specific + smbus adapter to call this function. */ +extern s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, + unsigned short flags, char read_write, u8 command, + int size, union i2c_smbus_data *data); + +/* Now follow the 'nice' access routines. These also document the calling + conventions of i2c_smbus_xfer. */ + +extern s32 i2c_smbus_read_byte(const struct i2c_client *client); +extern s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value); +extern s32 i2c_smbus_read_byte_data(const struct i2c_client *client, + u8 command); +extern s32 i2c_smbus_write_byte_data(const struct i2c_client *client, + u8 command, u8 value); +extern s32 i2c_smbus_read_word_data(const struct i2c_client *client, + u8 command); +extern s32 i2c_smbus_write_word_data(const struct i2c_client *client, + u8 command, u16 value); + +/* Returns the number of read bytes */ +extern s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, u8 *values); +extern s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client, + u8 command, u8 length, + const u8 *values); /** * struct i2c_board_info - template for device creation diff --git a/include/image-metadata.h b/include/image-metadata.h new file mode 100644 index 0000000000..34dae5ce34 --- /dev/null +++ b/include/image-metadata.h @@ -0,0 +1,117 @@ +#ifndef __INCLUDE_IMAGE_METADTA_H +#define __INCLUDE_IMAGE_METADTA_H + +/* + * barebox Image MetaData (IMD) + * + * IMD is a mechanism to store metadata in barebox images. With IMD + * it's possible to extract the release, the build timestamp and the + * board type from a barebox image. + * + * Since there is no fixed place in the image suitable for all SoC image + * types the metadata can be stored anywhere in the image and is found + * by iterating over the image. The metadata starts with a start header + * and ends with an end header. All tags in between carry the payload. + * + * Make sure source files containing IMD data are compiled with lwl-y so + * that the tags end up in the PBL if one exists and in the regular image + * without PBL. + * + * The following types exist: + */ +#define IMD_TYPE_START 0x640c0001 +#define IMD_TYPE_RELEASE 0x640c8002 /* The barebox release aka UTS_RELEASE */ +#define IMD_TYPE_BUILD 0x640c8003 /* build number and timestamp (UTS_VERSION) */ +#define IMD_TYPE_MODEL 0x640c8004 /* The board name this image is for */ +#define IMD_TYPE_OF_COMPATIBLE 0x640c8005 /* the device tree compatible string */ +#define IMD_TYPE_PARAMETER 0x640c8006 /* A generic parameter. Use key=value as data */ +#define IMD_TYPE_END 0x640c7fff +#define IMD_TYPE_INVALID 0xffffffff + +/* + * The IMD header. All data is stored in little endian format in the image. + * The next header starts at the next 4 byte boundary after the data. + */ +struct imd_header { + uint32_t type; /* One of IMD_TYPE_* above */ + uint32_t datalength; /* Length of the data (exluding the header) */ +}; + +/* + * A IMD string. Set bit 15 of the IMD_TYPE to indicate the data is printable + * as string. + */ +struct imd_entry_string { + struct imd_header header; + char data[]; +}; + +static inline int imd_is_string(uint32_t type) +{ + return (type & 0x8000) ? 1 : 0; +} + +static inline int imd_type_valid(uint32_t type) +{ + return (type & 0xffff0000) == 0x640c0000; +} + +struct imd_header *imd_next(struct imd_header *imd); + +#define imd_for_each(start, imd) \ + for (imd = imd_next(start); imd_read_type(imd) != IMD_TYPE_END; imd = imd_next(imd)) + +static inline uint32_t imd_read_le32(void *_ptr) +{ + uint8_t *ptr = _ptr; + + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static inline uint32_t imd_read_type(struct imd_header *imd) +{ + return imd_read_le32(&imd->type); +} + +static inline uint32_t imd_read_length(struct imd_header *imd) +{ + return imd_read_le32(&imd->datalength); +} + +struct imd_header *imd_find_type(struct imd_header *imd, uint32_t type); + +extern int imd_command_verbose; +int imd_command_setenv(const char *variable_name, const char *value); +int imd_command(int argc, char *argv[]); + +#ifdef __BAREBOX__ + +#include <linux/stringify.h> + +#define __BAREBOX_IMD_SECTION(_section) \ + __attribute__ ((unused,section (__stringify(_section)))) \ + __attribute__((aligned(4))) + +#define BAREBOX_IMD_TAG_STRING(_name, _type, _string, _keep_if_unused) \ + const struct imd_entry_string __barebox_imd_##_name \ + __BAREBOX_IMD_SECTION(.barebox_imd_ ## _keep_if_unused ## _ ## _name) = { \ + .header.type = cpu_to_le32(_type), \ + .header.datalength = cpu_to_le32(sizeof(_string)), \ + .data = _string, \ + } + + +#ifdef CONFIG_IMD +void imd_used(const void *); +#else +static inline void imd_used(const void *unused) +{ +} +#endif + +#define IMD_USED(_name) \ + imd_used(&__barebox_imd_##_name) + +#endif /* __BAREBOX__ */ + +#endif /* __INCLUDE_IMAGE_METADTA_H */ diff --git a/include/libbb.h b/include/libbb.h index 2fe710c368..a362bd32d8 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -26,15 +26,8 @@ int recursive_action(const char *fileName, unsigned flags, char * safe_strncpy(char *dst, const char *src, size_t size); -int copy_file(const char *src, const char *dst, int verbose); - int process_escape_sequence(const char *source, char *dest, int destlen); char *simple_itoa(unsigned int i); -int write_full(int fd, void *buf, size_t size); -int read_full(int fd, void *buf, size_t size); - -char *read_file_line(const char *fmt, ...); - #endif /* __LIBBB_H */ diff --git a/include/libfile.h b/include/libfile.h new file mode 100644 index 0000000000..4a25a9153c --- /dev/null +++ b/include/libfile.h @@ -0,0 +1,18 @@ +#ifndef __LIBFILE_H +#define __LIBFILE_H + +int write_full(int fd, void *buf, size_t size); +int read_full(int fd, void *buf, size_t size); + +char *read_file_line(const char *fmt, ...); + +void *read_file(const char *filename, size_t *size); + +int read_file_2(const char *filename, size_t *size, void **outbuf, + loff_t max_size); + +int write_file(const char *filename, void *buf, size_t size); + +int copy_file(const char *src, const char *dst, int verbose); + +#endif /* __LIBFILE_H */ diff --git a/include/linux/efi.h b/include/linux/efi.h deleted file mode 100644 index 570eff75de..0000000000 --- a/include/linux/efi.h +++ /dev/null @@ -1,547 +0,0 @@ -#ifndef _LINUX_EFI_H -#define _LINUX_EFI_H - -/* - * Extensible Firmware Interface - * Based on 'Extensible Firmware Interface Specification' version 0.9, April 30, 1999 - * - * Copyright (C) 1999 VA Linux Systems - * Copyright (C) 1999 Walt Drummond <drummond@valinux.com> - * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co. - * David Mosberger-Tang <davidm@hpl.hp.com> - * Stephane Eranian <eranian@hpl.hp.com> - */ -#include <linux/string.h> -#include <linux/types.h> - -#define EFI_SUCCESS 0 -#define EFI_LOAD_ERROR ( 1 | (1UL << (BITS_PER_LONG-1))) -#define EFI_INVALID_PARAMETER ( 2 | (1UL << (BITS_PER_LONG-1))) -#define EFI_UNSUPPORTED ( 3 | (1UL << (BITS_PER_LONG-1))) -#define EFI_BAD_BUFFER_SIZE ( 4 | (1UL << (BITS_PER_LONG-1))) -#define EFI_BUFFER_TOO_SMALL ( 5 | (1UL << (BITS_PER_LONG-1))) -#define EFI_NOT_FOUND (14 | (1UL << (BITS_PER_LONG-1))) - -typedef unsigned long efi_status_t; -typedef u8 efi_bool_t; -typedef u16 efi_char16_t; /* UNICODE character */ - - -typedef struct { - u8 b[16]; -} efi_guid_t; - -#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \ -((efi_guid_t) \ -{{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \ - (b) & 0xff, ((b) >> 8) & 0xff, \ - (c) & 0xff, ((c) >> 8) & 0xff, \ - (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }}) - -/* - * Generic EFI table header - */ -typedef struct { - u64 signature; - u32 revision; - u32 headersize; - u32 crc32; - u32 reserved; -} efi_table_hdr_t; - -/* - * Memory map descriptor: - */ - -/* Memory types: */ -#define EFI_RESERVED_TYPE 0 -#define EFI_LOADER_CODE 1 -#define EFI_LOADER_DATA 2 -#define EFI_BOOT_SERVICES_CODE 3 -#define EFI_BOOT_SERVICES_DATA 4 -#define EFI_RUNTIME_SERVICES_CODE 5 -#define EFI_RUNTIME_SERVICES_DATA 6 -#define EFI_CONVENTIONAL_MEMORY 7 -#define EFI_UNUSABLE_MEMORY 8 -#define EFI_ACPI_RECLAIM_MEMORY 9 -#define EFI_ACPI_MEMORY_NVS 10 -#define EFI_MEMORY_MAPPED_IO 11 -#define EFI_MEMORY_MAPPED_IO_PORT_SPACE 12 -#define EFI_PAL_CODE 13 -#define EFI_MAX_MEMORY_TYPE 14 - -/* Attribute values: */ -#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */ -#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */ -#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */ -#define EFI_MEMORY_WB ((u64)0x0000000000000008ULL) /* write-back */ -#define EFI_MEMORY_WP ((u64)0x0000000000001000ULL) /* write-protect */ -#define EFI_MEMORY_RP ((u64)0x0000000000002000ULL) /* read-protect */ -#define EFI_MEMORY_XP ((u64)0x0000000000004000ULL) /* execute-protect */ -#define EFI_MEMORY_RUNTIME ((u64)0x8000000000000000ULL) /* range requires runtime mapping */ -#define EFI_MEMORY_DESCRIPTOR_VERSION 1 - -#define EFI_PAGE_SHIFT 12 - -typedef struct { - u32 type; - u32 pad; - u64 phys_addr; - u64 virt_addr; - u64 num_pages; - u64 attribute; -} efi_memory_desc_t; - -typedef struct { - efi_guid_t guid; - u32 headersize; - u32 flags; - u32 imagesize; -} efi_capsule_header_t; - -/* - * Allocation types for calls to boottime->allocate_pages. - */ -#define EFI_ALLOCATE_ANY_PAGES 0 -#define EFI_ALLOCATE_MAX_ADDRESS 1 -#define EFI_ALLOCATE_ADDRESS 2 -#define EFI_MAX_ALLOCATE_TYPE 3 - -typedef int (*efi_freemem_callback_t) (u64 start, u64 end, void *arg); - -/* - * Types and defines for Time Services - */ -#define EFI_TIME_ADJUST_DAYLIGHT 0x1 -#define EFI_TIME_IN_DAYLIGHT 0x2 -#define EFI_UNSPECIFIED_TIMEZONE 0x07ff - -typedef struct { - u16 year; - u8 month; - u8 day; - u8 hour; - u8 minute; - u8 second; - u8 pad1; - u32 nanosecond; - s16 timezone; - u8 daylight; - u8 pad2; -} efi_time_t; - -typedef struct { - u32 resolution; - u32 accuracy; - u8 sets_to_zero; -} efi_time_cap_t; - -/* - * EFI Boot Services table - */ -typedef struct { - efi_table_hdr_t hdr; - void *raise_tpl; - void *restore_tpl; - void *allocate_pages; - void *free_pages; - void *get_memory_map; - void *allocate_pool; - void *free_pool; - void *create_event; - void *set_timer; - void *wait_for_event; - void *signal_event; - void *close_event; - void *check_event; - void *install_protocol_interface; - void *reinstall_protocol_interface; - void *uninstall_protocol_interface; - void *handle_protocol; - void *__reserved; - void *register_protocol_notify; - void *locate_handle; - void *locate_device_path; - void *install_configuration_table; - void *load_image; - void *start_image; - void *exit; - void *unload_image; - void *exit_boot_services; - void *get_next_monotonic_count; - void *stall; - void *set_watchdog_timer; - void *connect_controller; - void *disconnect_controller; - void *open_protocol; - void *close_protocol; - void *open_protocol_information; - void *protocols_per_handle; - void *locate_handle_buffer; - void *locate_protocol; - void *install_multiple_protocol_interfaces; - void *uninstall_multiple_protocol_interfaces; - void *calculate_crc32; - void *copy_mem; - void *set_mem; - void *create_event_ex; -} efi_boot_services_t; - -/* - * Types and defines for EFI ResetSystem - */ -#define EFI_RESET_COLD 0 -#define EFI_RESET_WARM 1 -#define EFI_RESET_SHUTDOWN 2 - -/* - * EFI Runtime Services table - */ -#define EFI_RUNTIME_SERVICES_SIGNATURE ((u64)0x5652453544e5552ULL) -#define EFI_RUNTIME_SERVICES_REVISION 0x00010000 - -typedef struct { - efi_table_hdr_t hdr; - unsigned long get_time; - unsigned long set_time; - unsigned long get_wakeup_time; - unsigned long set_wakeup_time; - unsigned long set_virtual_address_map; - unsigned long convert_pointer; - unsigned long get_variable; - unsigned long get_next_variable; - unsigned long set_variable; - unsigned long get_next_high_mono_count; - unsigned long reset_system; - unsigned long update_capsule; - unsigned long query_capsule_caps; - unsigned long query_variable_info; -} efi_runtime_services_t; - -typedef efi_status_t efi_get_time_t (efi_time_t *tm, efi_time_cap_t *tc); -typedef efi_status_t efi_set_time_t (efi_time_t *tm); -typedef efi_status_t efi_get_wakeup_time_t (efi_bool_t *enabled, efi_bool_t *pending, - efi_time_t *tm); -typedef efi_status_t efi_set_wakeup_time_t (efi_bool_t enabled, efi_time_t *tm); -typedef efi_status_t efi_get_variable_t (efi_char16_t *name, efi_guid_t *vendor, u32 *attr, - unsigned long *data_size, void *data); -typedef efi_status_t efi_get_next_variable_t (unsigned long *name_size, efi_char16_t *name, - efi_guid_t *vendor); -typedef efi_status_t efi_set_variable_t (efi_char16_t *name, efi_guid_t *vendor, - u32 attr, unsigned long data_size, - void *data); -typedef efi_status_t efi_get_next_high_mono_count_t (u32 *count); -typedef void efi_reset_system_t (int reset_type, efi_status_t status, - unsigned long data_size, efi_char16_t *data); -typedef efi_status_t efi_set_virtual_address_map_t (unsigned long memory_map_size, - unsigned long descriptor_size, - u32 descriptor_version, - efi_memory_desc_t *virtual_map); -typedef efi_status_t efi_query_variable_info_t(u32 attr, - u64 *storage_space, - u64 *remaining_space, - u64 *max_variable_size); -typedef efi_status_t efi_update_capsule_t(efi_capsule_header_t **capsules, - unsigned long count, - unsigned long sg_list); -typedef efi_status_t efi_query_capsule_caps_t(efi_capsule_header_t **capsules, - unsigned long count, - u64 *max_size, - int *reset_type); - -/* - * EFI Configuration Table and GUID definitions - */ -#define NULL_GUID \ - EFI_GUID( 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ) - -#define MPS_TABLE_GUID \ - EFI_GUID( 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) - -#define ACPI_TABLE_GUID \ - EFI_GUID( 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) - -#define ACPI_20_TABLE_GUID \ - EFI_GUID( 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 ) - -#define SMBIOS_TABLE_GUID \ - EFI_GUID( 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) - -#define SAL_SYSTEM_TABLE_GUID \ - EFI_GUID( 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d ) - -#define HCDP_TABLE_GUID \ - EFI_GUID( 0xf951938d, 0x620b, 0x42ef, 0x82, 0x79, 0xa8, 0x4b, 0x79, 0x61, 0x78, 0x98 ) - -#define UGA_IO_PROTOCOL_GUID \ - EFI_GUID( 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 ) - -#define EFI_GLOBAL_VARIABLE_GUID \ - EFI_GUID( 0x8be4df61, 0x93ca, 0x11d2, 0xaa, 0x0d, 0x00, 0xe0, 0x98, 0x03, 0x2b, 0x8c ) - -#define UV_SYSTEM_TABLE_GUID \ - EFI_GUID( 0x3b13a7d4, 0x633e, 0x11dd, 0x93, 0xec, 0xda, 0x25, 0x56, 0xd8, 0x95, 0x93 ) - -#define LINUX_EFI_CRASH_GUID \ - EFI_GUID( 0xcfc8fc79, 0xbe2e, 0x4ddc, 0x97, 0xf0, 0x9f, 0x98, 0xbf, 0xe2, 0x98, 0xa0 ) - -#define LOADED_IMAGE_PROTOCOL_GUID \ - EFI_GUID( 0x5b1b31a1, 0x9562, 0x11d2, 0x8e, 0x3f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ - EFI_GUID( 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a ) - -#define EFI_UGA_PROTOCOL_GUID \ - EFI_GUID( 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 ) - -#define EFI_PCI_IO_PROTOCOL_GUID \ - EFI_GUID( 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a ) - -#define EFI_FILE_INFO_ID \ - EFI_GUID( 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -#define EFI_FILE_SYSTEM_GUID \ - EFI_GUID( 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b ) - -typedef struct { - efi_guid_t guid; - u64 table; -} efi_config_table_64_t; - -typedef struct { - efi_guid_t guid; - u32 table; -} efi_config_table_32_t; - -typedef struct { - efi_guid_t guid; - unsigned long table; -} efi_config_table_t; - -#define EFI_SYSTEM_TABLE_SIGNATURE ((u64)0x5453595320494249ULL) - -#define EFI_2_30_SYSTEM_TABLE_REVISION ((2 << 16) | (30)) -#define EFI_2_20_SYSTEM_TABLE_REVISION ((2 << 16) | (20)) -#define EFI_2_10_SYSTEM_TABLE_REVISION ((2 << 16) | (10)) -#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | (00)) -#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | (10)) -#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | (02)) - -typedef struct { - efi_table_hdr_t hdr; - u64 fw_vendor; /* physical addr of CHAR16 vendor string */ - u32 fw_revision; - u32 __pad1; - u64 con_in_handle; - u64 con_in; - u64 con_out_handle; - u64 con_out; - u64 stderr_handle; - u64 _stderr; - u64 runtime; - u64 boottime; - u32 nr_tables; - u32 __pad2; - u64 tables; -} efi_system_table_64_t; - -typedef struct { - efi_table_hdr_t hdr; - u32 fw_vendor; /* physical addr of CHAR16 vendor string */ - u32 fw_revision; - u32 con_in_handle; - u32 con_in; - u32 con_out_handle; - u32 con_out; - u32 stderr_handle; - u32 _stderr; - u32 runtime; - u32 boottime; - u32 nr_tables; - u32 tables; -} efi_system_table_32_t; - -typedef struct { - efi_table_hdr_t hdr; - unsigned long fw_vendor; /* physical addr of CHAR16 vendor string */ - u32 fw_revision; - unsigned long con_in_handle; - unsigned long con_in; - unsigned long con_out_handle; - unsigned long con_out; - unsigned long stderr_handle; - unsigned long _stderr; - efi_runtime_services_t *runtime; - efi_boot_services_t *boottime; - unsigned long nr_tables; - unsigned long tables; -} efi_system_table_t; - -struct efi_memory_map { - void *phys_map; - void *map; - void *map_end; - int nr_map; - unsigned long desc_version; - unsigned long desc_size; -}; - -typedef struct { - u32 revision; - void *parent_handle; - efi_system_table_t *system_table; - void *device_handle; - void *file_path; - void *reserved; - u32 load_options_size; - void *load_options; - void *image_base; - __aligned_u64 image_size; - unsigned int image_code_type; - unsigned int image_data_type; - unsigned long unload; -} efi_loaded_image_t; - -typedef struct { - u64 revision; - void *open_volume; -} efi_file_io_interface_t; - -typedef struct { - u64 size; - u64 file_size; - u64 phys_size; - efi_time_t create_time; - efi_time_t last_access_time; - efi_time_t modification_time; - __aligned_u64 attribute; - efi_char16_t filename[1]; -} efi_file_info_t; - -typedef struct { - u64 revision; - void *open; - void *close; - void *delete; - void *read; - void *write; - void *get_position; - void *set_position; - void *get_info; - void *set_info; - void *flush; -} efi_file_handle_t; - -#define EFI_FILE_MODE_READ 0x0000000000000001 -#define EFI_FILE_MODE_WRITE 0x0000000000000002 -#define EFI_FILE_MODE_CREATE 0x8000000000000000 - -#define EFI_INVALID_TABLE_ADDR (~0UL) - -/* - * All runtime access to EFI goes through this structure: - */ -extern struct efi { - efi_system_table_t *systab; /* EFI system table */ - unsigned int runtime_version; /* Runtime services version */ - unsigned long mps; /* MPS table */ - unsigned long acpi; /* ACPI table (IA64 ext 0.71) */ - unsigned long acpi20; /* ACPI table (ACPI 2.0) */ - unsigned long smbios; /* SM BIOS table */ - unsigned long sal_systab; /* SAL system table */ - unsigned long boot_info; /* boot info table */ - unsigned long hcdp; /* HCDP table */ - unsigned long uga; /* UGA table */ - unsigned long uv_systab; /* UV system table */ - efi_get_time_t *get_time; - efi_set_time_t *set_time; - efi_get_wakeup_time_t *get_wakeup_time; - efi_set_wakeup_time_t *set_wakeup_time; - efi_get_variable_t *get_variable; - efi_get_next_variable_t *get_next_variable; - efi_set_variable_t *set_variable; - efi_query_variable_info_t *query_variable_info; - efi_update_capsule_t *update_capsule; - efi_query_capsule_caps_t *query_capsule_caps; - efi_get_next_high_mono_count_t *get_next_high_mono_count; - efi_reset_system_t *reset_system; - efi_set_virtual_address_map_t *set_virtual_address_map; -} efi; - -static inline int -efi_guidcmp (efi_guid_t left, efi_guid_t right) -{ - return memcmp(&left, &right, sizeof (efi_guid_t)); -} - -static inline char * -efi_guid_unparse(efi_guid_t *guid, char *out) -{ - sprintf(out, "%pUl", guid->b); - return out; -} - -/* - * Variable Attributes - */ -#define EFI_VARIABLE_NON_VOLATILE 0x0000000000000001 -#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x0000000000000002 -#define EFI_VARIABLE_RUNTIME_ACCESS 0x0000000000000004 -#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x0000000000000008 -#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x0000000000000010 -#define EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS 0x0000000000000020 -#define EFI_VARIABLE_APPEND_WRITE 0x0000000000000040 - -#define EFI_VARIABLE_MASK (EFI_VARIABLE_NON_VOLATILE | \ - EFI_VARIABLE_BOOTSERVICE_ACCESS | \ - EFI_VARIABLE_RUNTIME_ACCESS | \ - EFI_VARIABLE_HARDWARE_ERROR_RECORD | \ - EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS | \ - EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS | \ - EFI_VARIABLE_APPEND_WRITE) -/* - * The type of search to perform when calling boottime->locate_handle - */ -#define EFI_LOCATE_ALL_HANDLES 0 -#define EFI_LOCATE_BY_REGISTER_NOTIFY 1 -#define EFI_LOCATE_BY_PROTOCOL 2 - -/* - * EFI Device Path information - */ -#define EFI_DEV_HW 0x01 -#define EFI_DEV_PCI 1 -#define EFI_DEV_PCCARD 2 -#define EFI_DEV_MEM_MAPPED 3 -#define EFI_DEV_VENDOR 4 -#define EFI_DEV_CONTROLLER 5 -#define EFI_DEV_ACPI 0x02 -#define EFI_DEV_BASIC_ACPI 1 -#define EFI_DEV_EXPANDED_ACPI 2 -#define EFI_DEV_MSG 0x03 -#define EFI_DEV_MSG_ATAPI 1 -#define EFI_DEV_MSG_SCSI 2 -#define EFI_DEV_MSG_FC 3 -#define EFI_DEV_MSG_1394 4 -#define EFI_DEV_MSG_USB 5 -#define EFI_DEV_MSG_USB_CLASS 15 -#define EFI_DEV_MSG_I20 6 -#define EFI_DEV_MSG_MAC 11 -#define EFI_DEV_MSG_IPV4 12 -#define EFI_DEV_MSG_IPV6 13 -#define EFI_DEV_MSG_INFINIBAND 9 -#define EFI_DEV_MSG_UART 14 -#define EFI_DEV_MSG_VENDOR 10 -#define EFI_DEV_MEDIA 0x04 -#define EFI_DEV_MEDIA_HARD_DRIVE 1 -#define EFI_DEV_MEDIA_CDROM 2 -#define EFI_DEV_MEDIA_VENDOR 3 -#define EFI_DEV_MEDIA_FILE 4 -#define EFI_DEV_MEDIA_PROTOCOL 5 -#define EFI_DEV_BIOS_BOOT 0x05 -#define EFI_DEV_END_PATH 0x7F -#define EFI_DEV_END_PATH2 0xFF -#define EFI_DEV_END_INSTANCE 0x01 -#define EFI_DEV_END_ENTIRE 0xFF - -#endif /* _LINUX_EFI_H */ diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b90d8f7e04..d512adcea1 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -130,5 +130,26 @@ } \ ) -#endif /* _LINUX_KERNEL_H */ +extern const char hex_asc[]; +#define hex_asc_lo(x) hex_asc[((x) & 0x0f)] +#define hex_asc_hi(x) hex_asc[((x) & 0xf0) >> 4] + +static inline char *hex_byte_pack(char *buf, u8 byte) +{ + *buf++ = hex_asc_hi(byte); + *buf++ = hex_asc_lo(byte); + return buf; +} + +extern const char hex_asc_upper[]; +#define hex_asc_upper_lo(x) hex_asc_upper[((x) & 0x0f)] +#define hex_asc_upper_hi(x) hex_asc_upper[((x) & 0xf0) >> 4] +static inline char *hex_byte_pack_upper(char *buf, u8 byte) +{ + *buf++ = hex_asc_upper_hi(byte); + *buf++ = hex_asc_upper_lo(byte); + return buf; +} + +#endif /* _LINUX_KERNEL_H */ diff --git a/include/linux/mbus.h b/include/linux/mbus.h index 578ff33146..ac14982875 100644 --- a/include/linux/mbus.h +++ b/include/linux/mbus.h @@ -58,4 +58,6 @@ int mvebu_mbus_add_window_by_id(unsigned int target, unsigned int attribute, phys_addr_t base, size_t size); int mvebu_mbus_del_window(phys_addr_t base, size_t size); +void mvebu_mbus_add_range(u8 target, u8 attr, u32 remap); + #endif /* __LINUX_MBUS_H */ diff --git a/include/linux/pci.h b/include/linux/pci.h index 6caed01c99..0ec1320b2f 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -91,9 +91,6 @@ struct pci_dev { struct list_head bus_list; /* node in per-bus list */ struct pci_bus *bus; /* bus this device is on */ struct pci_bus *subordinate; /* bus this device bridges to */ - - void *sysdata; /* hook for sys-specific extension */ - struct proc_dir_entry *procent; /* device entry in /proc/bus/pci */ struct pci_slot *slot; /* Physical slot this device is in */ struct device_d dev; @@ -118,6 +115,7 @@ struct pci_dev { #define to_pci_dev(dev) container_of(dev, struct pci_dev, dev) struct pci_bus { + struct pci_controller *host; /* associated host controller */ struct list_head node; /* node in list of buses */ struct list_head children; /* list of child buses */ struct list_head devices; /* list of devices on this bus */ @@ -126,8 +124,6 @@ struct pci_bus { struct list_head resources; /* address space routed to this bus */ struct pci_ops *ops; /* configuration access functions */ - void *sysdata; /* hook for sys-specific extension */ - struct proc_dir_entry *procdir; /* directory entry in /proc/bus/pci */ unsigned char number; /* bus number */ unsigned char primary; /* number of primary bridge */ @@ -167,10 +163,8 @@ struct pci_controller { unsigned int index; - /* Optional access methods for reading/writing the bus number - of the PCI controller */ - int (*get_busno)(void); - void (*set_busno)(int busno); + /* Optional access method for writing the bus number */ + void (*set_busno)(struct pci_controller *host, int busno); }; struct pci_driver { diff --git a/include/of_pci.h b/include/of_pci.h new file mode 100644 index 0000000000..c95cb0135a --- /dev/null +++ b/include/of_pci.h @@ -0,0 +1,17 @@ +#ifndef __OF_PCI_H +#define __OF_PCI_H + +#include <linux/pci.h> + +#ifdef CONFIG_OF_PCI +int of_pci_get_devfn(struct device_node *np); + +#else +static inline int of_pci_get_devfn(struct device_node *np) +{ + return -EINVAL; +} + +#endif + +#endif diff --git a/include/param.h b/include/param.h index 24827c5e78..8f200df847 100644 --- a/include/param.h +++ b/include/param.h @@ -7,7 +7,7 @@ #define PARAM_FLAG_RO (1 << 0) struct device_d; -typedef unsigned long IPaddr_t; +typedef uint32_t IPaddr_t; struct param_d { const char* (*get)(struct device_d *, struct param_d *param); diff --git a/include/platform_data/pca953x.h b/include/platform_data/pca953x.h new file mode 100644 index 0000000000..cfd253ebce --- /dev/null +++ b/include/platform_data/pca953x.h @@ -0,0 +1,27 @@ +#ifndef _LINUX_PCA953X_H +#define _LINUX_PCA953X_H + +#include <linux/types.h> +#include <i2c/i2c.h> + +/* platform data for the PCA9539 16-bit I/O expander driver */ + +struct pca953x_platform_data { + /* number of the first GPIO */ + unsigned gpio_base; + + /* initial polarity inversion setting */ + u32 invert; + + void *context; /* param to setup/teardown */ + + int (*setup)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); + int (*teardown)(struct i2c_client *client, + unsigned gpio, unsigned ngpio, + void *context); + const char *const *names; +}; + +#endif /* _LINUX_PCA953X_H */ diff --git a/include/wchar.h b/include/wchar.h new file mode 100644 index 0000000000..80dcd81bf4 --- /dev/null +++ b/include/wchar.h @@ -0,0 +1,18 @@ +#ifndef __WCHAR_H +#define __WCHAR_H + +#include <linux/types.h> + +typedef u16 wchar_t; + +char *strcpy_wchar_to_char(char *dst, const wchar_t *src); + +wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src); + +wchar_t *strdup_char_to_wchar(const char *src); + +char *strdup_wchar_to_char(const wchar_t *src); + +size_t wcslen(const wchar_t *s); + +#endif /* __WCHAR_H */ diff --git a/lib/Kconfig b/lib/Kconfig index d9ad4aa949..09a1674820 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -54,4 +54,7 @@ source lib/gui/Kconfig source lib/bootstrap/Kconfig +config PRINTF_UUID + bool + endmenu diff --git a/lib/Makefile b/lib/Makefile index 78f724a095..77207dc773 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -25,7 +25,6 @@ obj-$(CONFIG_GLOB) += fnmatch.o obj-$(CONFIG_GENERIC_FIND_NEXT_BIT) += find_next_bit.o obj-y += glob.o obj-y += notifier.o -obj-y += copy_file.o obj-y += random.o obj-y += lzo/ obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/ @@ -44,4 +43,6 @@ obj-y += gui/ obj-$(CONFIG_XYMODEM) += xymodem.o obj-y += unlink-recursive.o obj-$(CONFIG_STMP_DEVICE) += stmp-device.o +obj-y += wchar.o +obj-y += libfile.o obj-y += bitmap.o diff --git a/lib/bootstrap/disk.c b/lib/bootstrap/disk.c index 527e430897..1e9fbd834b 100644 --- a/lib/bootstrap/disk.c +++ b/lib/bootstrap/disk.c @@ -11,6 +11,7 @@ #include <sizes.h> #include <errno.h> #include <malloc.h> +#include <libfile.h> #include <bootstrap.h> void* bootstrap_read_disk(char *dev, char *fstype) diff --git a/lib/copy_file.c b/lib/copy_file.c deleted file mode 100644 index fdd0cacb40..0000000000 --- a/lib/copy_file.c +++ /dev/null @@ -1,86 +0,0 @@ -#include <common.h> -#include <fs.h> -#include <fcntl.h> -#include <errno.h> -#include <malloc.h> -#include <libbb.h> -#include <progress.h> - -/** - * @param[in] src FIXME - * @param[out] dst FIXME - * @param[in] verbose FIXME - */ -int copy_file(const char *src, const char *dst, int verbose) -{ - char *rw_buf = NULL; - int srcfd = 0, dstfd = 0; - int r, w; - int ret = 1; - void *buf; - int total = 0; - struct stat statbuf; - - rw_buf = xmalloc(RW_BUF_SIZE); - - srcfd = open(src, O_RDONLY); - if (srcfd < 0) { - printf("could not open %s: %s\n", src, errno_str()); - goto out; - } - - dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC); - if (dstfd < 0) { - printf("could not open %s: %s\n", dst, errno_str()); - goto out; - } - - if (verbose) { - if (stat(src, &statbuf) < 0) - statbuf.st_size = 0; - - init_progression_bar(statbuf.st_size); - } - - while(1) { - r = read(srcfd, rw_buf, RW_BUF_SIZE); - if (r < 0) { - perror("read"); - goto out; - } - if (!r) - break; - - buf = rw_buf; - while (r) { - w = write(dstfd, buf, r); - if (w < 0) { - perror("write"); - goto out; - } - buf += w; - r -= w; - total += w; - } - - if (verbose) { - if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX) - show_progress(total); - else - show_progress(total / 16384); - } - } - - ret = 0; -out: - if (verbose) - putchar('\n'); - - free(rw_buf); - if (srcfd > 0) - close(srcfd); - if (dstfd > 0) - close(dstfd); - - return ret; -} diff --git a/lib/gui/image_renderer.c b/lib/gui/image_renderer.c index 8047961e9e..dd29389baa 100644 --- a/lib/gui/image_renderer.c +++ b/lib/gui/image_renderer.c @@ -10,6 +10,7 @@ #include <errno.h> #include <fs.h> #include <malloc.h> +#include <libfile.h> static LIST_HEAD(image_renderers); diff --git a/lib/libbb.c b/lib/libbb.c index dd42e662b4..239611c27b 100644 --- a/lib/libbb.c +++ b/lib/libbb.c @@ -126,96 +126,3 @@ char *simple_itoa(unsigned int i) return p + 1; } EXPORT_SYMBOL(simple_itoa); - -/* - * write_full - write to filedescriptor - * - * Like write, but guarantees to write the full buffer out, else - * it returns with an error. - */ -int write_full(int fd, void *buf, size_t size) -{ - size_t insize = size; - int now; - - while (size) { - now = write(fd, buf, size); - if (now <= 0) - return now; - size -= now; - buf += now; - } - - return insize; -} -EXPORT_SYMBOL(write_full); - -/* - * read_full - read from filedescriptor - * - * Like read, but this function only returns less bytes than - * requested when the end of file is reached. - */ -int read_full(int fd, void *buf, size_t size) -{ - size_t insize = size; - int now; - int total = 0; - - while (size) { - now = read(fd, buf, size); - if (now == 0) - return total; - if (now < 0) - return now; - total += now; - size -= now; - buf += now; - } - - return insize; -} -EXPORT_SYMBOL(read_full); - -/* - * read_file_line - read a line from a file - * - * Used to compose a filename from a printf format and to read a line from this - * file. All leading and trailing whitespaces (including line endings) are - * removed. The returned buffer must be freed with free(). This function is - * supposed for reading variable like content into a buffer, so files > 1024 - * bytes are ignored. - */ -char *read_file_line(const char *fmt, ...) -{ - va_list args; - char *filename; - char *buf, *line = NULL; - size_t size; - int ret; - struct stat s; - - va_start(args, fmt); - filename = vasprintf(fmt, args); - va_end(args); - - ret = stat(filename, &s); - if (ret) - goto out; - - if (s.st_size > 1024) - goto out; - - buf = read_file(filename, &size); - if (!buf) - goto out; - - line = strim(buf); - - line = xstrdup(line); - free(buf); -out: - free(filename); - return line; -} -EXPORT_SYMBOL_GPL(read_file_line); diff --git a/lib/libfile.c b/lib/libfile.c new file mode 100644 index 0000000000..c6fb6d7157 --- /dev/null +++ b/lib/libfile.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ +#include <common.h> +#include <fs.h> +#include <fcntl.h> +#include <malloc.h> +#include <libfile.h> +#include <progress.h> +#include <linux/stat.h> + +/* + * write_full - write to filedescriptor + * + * Like write, but guarantees to write the full buffer out, else + * it returns with an error. + */ +int write_full(int fd, void *buf, size_t size) +{ + size_t insize = size; + int now; + + while (size) { + now = write(fd, buf, size); + if (now <= 0) + return now; + size -= now; + buf += now; + } + + return insize; +} +EXPORT_SYMBOL(write_full); + +/* + * read_full - read from filedescriptor + * + * Like read, but this function only returns less bytes than + * requested when the end of file is reached. + */ +int read_full(int fd, void *buf, size_t size) +{ + size_t insize = size; + int now; + int total = 0; + + while (size) { + now = read(fd, buf, size); + if (now == 0) + return total; + if (now < 0) + return now; + total += now; + size -= now; + buf += now; + } + + return insize; +} +EXPORT_SYMBOL(read_full); + +/* + * read_file_line - read a line from a file + * + * Used to compose a filename from a printf format and to read a line from this + * file. All leading and trailing whitespaces (including line endings) are + * removed. The returned buffer must be freed with free(). This function is + * supposed for reading variable like content into a buffer, so files > 1024 + * bytes are ignored. + */ +char *read_file_line(const char *fmt, ...) +{ + va_list args; + char *filename; + char *buf, *line = NULL; + size_t size; + int ret; + struct stat s; + + va_start(args, fmt); + filename = vasprintf(fmt, args); + va_end(args); + + ret = stat(filename, &s); + if (ret) + goto out; + + if (s.st_size > 1024) + goto out; + + buf = read_file(filename, &size); + if (!buf) + goto out; + + line = strim(buf); + + line = xstrdup(line); + free(buf); +out: + free(filename); + return line; +} +EXPORT_SYMBOL_GPL(read_file_line); + +/** + * read_file_2 - read a file to an allocated buffer + * @filename: The filename to read + * @size: After successful return contains the size of the file + * @outbuf: contains a pointer to the file data after successful return + * @max_size: The maximum size to read. Use FILESIZE_MAX for reading files + * of any size. + * + * This function reads a file to an allocated buffer. At maximum @max_size + * bytes are read. The actual read size is returned in @size. -EFBIG is + * returned if the file is bigger than @max_size, but the buffer is read + * anyway up to @max_size in this case. Free the buffer with free() after + * usage. + * + * Return: 0 for success, or negative error code. -EFBIG is returned + * when the file has been bigger than max_size. + */ +int read_file_2(const char *filename, size_t *size, void **outbuf, + loff_t max_size) +{ + int fd; + struct stat s; + void *buf = NULL; + const char *tmpfile = "/.read_file_tmp"; + int ret; + loff_t read_size; + +again: + ret = stat(filename, &s); + if (ret) + return ret; + + if (max_size == FILESIZE_MAX) + read_size = s.st_size; + else + read_size = max_size; + + if (read_size == FILESIZE_MAX) { + ret = copy_file(filename, tmpfile, 0); + if (ret) + return ret; + filename = tmpfile; + goto again; + } + + buf = xzalloc(read_size + 1); + + fd = open(filename, O_RDONLY); + if (fd < 0) + goto err_out; + + ret = read_full(fd, buf, read_size); + if (ret < 0) + goto err_out1; + + close(fd); + + if (size) + *size = ret; + + if (filename == tmpfile) + unlink(tmpfile); + + *outbuf = buf; + + if (read_size < s.st_size) + return -EFBIG; + else + return 0; + +err_out1: + close(fd); +err_out: + free(buf); + + if (filename == tmpfile) + unlink(tmpfile); + + return ret; +} +EXPORT_SYMBOL(read_file_2); + +/** + * read_file - read a file to an allocated buffer + * @filename: The filename to read + * @size: After successful return contains the size of the file + * + * This function reads a file to an allocated buffer. + * Some TFTP servers do not transfer the size of a file. In this case + * a the file is first read to a temporary file. + * + * Return: The buffer conataining the file or NULL on failure + */ +void *read_file(const char *filename, size_t *size) +{ + int ret; + void *buf; + + ret = read_file_2(filename, size, &buf, FILESIZE_MAX); + if (!ret) + return buf; + + return NULL; +} +EXPORT_SYMBOL(read_file); + +/** + * write_file - write a buffer to a file + * @filename: The filename to write + * @size: The size of the buffer + * + * Return: 0 for success or negative error value + */ +int write_file(const char *filename, void *buf, size_t size) +{ + int fd, ret; + + fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT); + if (fd < 0) + return fd; + + ret = write_full(fd, buf, size); + + close(fd); + + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL(write_file); + +/** + * copy_file - Copy a file + * @src: The source filename + * @dst: The destination filename + * @verbose: if true, show a progression bar + * + * Return: 0 for success or negative error code + */ +int copy_file(const char *src, const char *dst, int verbose) +{ + char *rw_buf = NULL; + int srcfd = 0, dstfd = 0; + int r, w; + int ret = 1; + void *buf; + int total = 0; + struct stat statbuf; + + rw_buf = xmalloc(RW_BUF_SIZE); + + srcfd = open(src, O_RDONLY); + if (srcfd < 0) { + printf("could not open %s: %s\n", src, errno_str()); + goto out; + } + + dstfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC); + if (dstfd < 0) { + printf("could not open %s: %s\n", dst, errno_str()); + goto out; + } + + if (verbose) { + if (stat(src, &statbuf) < 0) + statbuf.st_size = 0; + + init_progression_bar(statbuf.st_size); + } + + while (1) { + r = read(srcfd, rw_buf, RW_BUF_SIZE); + if (r < 0) { + perror("read"); + goto out; + } + if (!r) + break; + + buf = rw_buf; + while (r) { + w = write(dstfd, buf, r); + if (w < 0) { + perror("write"); + goto out; + } + buf += w; + r -= w; + total += w; + } + + if (verbose) { + if (statbuf.st_size && statbuf.st_size != FILESIZE_MAX) + show_progress(total); + else + show_progress(total / 16384); + } + } + + ret = 0; +out: + if (verbose) + putchar('\n'); + + free(rw_buf); + if (srcfd > 0) + close(srcfd); + if (dstfd > 0) + close(dstfd); + + return ret; +} +EXPORT_SYMBOL(copy_file); diff --git a/lib/misc.c b/lib/misc.c index 0f3eb9aabb..87626c1e8b 100644 --- a/lib/misc.c +++ b/lib/misc.c @@ -21,6 +21,7 @@ #include <malloc.h> #include <errno.h> #include <fs.h> +#include <string.h> #include <linux/ctype.h> /* @@ -113,3 +114,5 @@ int parse_area_spec(const char *str, loff_t *start, loff_t *size) return -1; } EXPORT_SYMBOL(parse_area_spec); + +const char hex_asc[] = "0123456789abcdef"; diff --git a/lib/readkey.c b/lib/readkey.c index 7b38110113..2073a732f4 100644 --- a/lib/readkey.c +++ b/lib/readkey.c @@ -25,7 +25,7 @@ struct esc_cmds { const char *seq; - char val; + unsigned char val; }; static const struct esc_cmds esccmds[] = { diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 066338b4e8..512c88247f 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -253,6 +253,53 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int #endif } +static noinline_for_stack +char *uuid_string(char *buf, char *end, const u8 *addr, int field_width, + int precision, int flags, const char *fmt) +{ + char uuid[sizeof("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")]; + char *p = uuid; + int i; + static const u8 be[16] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; + static const u8 le[16] = {3,2,1,0,5,4,7,6,8,9,10,11,12,13,14,15}; + const u8 *index = be; + bool uc = false; + + switch (*(++fmt)) { + case 'L': + uc = true; /* fall-through */ + case 'l': + index = le; + break; + case 'B': + uc = true; + break; + } + + for (i = 0; i < 16; i++) { + p = hex_byte_pack(p, addr[index[i]]); + switch (i) { + case 3: + case 5: + case 7: + case 9: + *p++ = '-'; + break; + } + } + + *p = 0; + + if (uc) { + p = uuid; + do { + *p = toupper(*p); + } while (*(++p)); + } + + return string(buf, end, uuid, field_width, precision, flags); +} + /* * Show a '%p' thing. A kernel extension is that the '%p' is followed * by an extra set of alphanumeric characters that are extended format @@ -261,6 +308,17 @@ static char *symbol_string(char *buf, char *end, void *ptr, int field_width, int * Right now we handle: * * - 'S' For symbolic direct pointers + * - 'U' For a 16 byte UUID/GUID, it prints the UUID/GUID in the form + * "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" + * Options for %pU are: + * b big endian lower case hex (default) + * B big endian UPPER case hex + * l little endian lower case hex + * L little endian UPPER case hex + * big endian output byte order is: + * [0][1][2][3]-[4][5]-[6][7]-[8][9]-[10][11][12][13][14][15] + * little endian output byte order is: + * [3][2][1][0]-[5][4]-[7][6]-[8][9]-[10][11][12][13][14][15] * * Note: The difference between 'S' and 'F' is that on ia64 and ppc64 * function pointers are really function descriptors, which contain a @@ -271,6 +329,10 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field switch (*fmt) { case 'S': return symbol_string(buf, end, ptr, field_width, precision, flags); + case 'U': + if (IS_ENABLED(CONFIG_PRINTF_UUID)) + return uuid_string(buf, end, ptr, field_width, precision, flags, fmt); + break; } flags |= SMALL; if (field_width == -1) { diff --git a/lib/wchar.c b/lib/wchar.c new file mode 100644 index 0000000000..6368a01994 --- /dev/null +++ b/lib/wchar.c @@ -0,0 +1,80 @@ +/* + * wchar.c - wide character support + * + * Copyright (c) 2014 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <wchar.h> +#include <malloc.h> +#include <string.h> + +size_t wcslen(const wchar_t *s) +{ + size_t len = 0; + + while (*s++) + len++; + + return len; +} + +char *strcpy_wchar_to_char(char *dst, const wchar_t *src) +{ + char *ret = dst; + + while (*src) + *dst++ = *src++ & 0xff; + + *dst = 0; + + return ret; +} + +wchar_t *strcpy_char_to_wchar(wchar_t *dst, const char *src) +{ + wchar_t *ret = dst; + + while (*src) + *dst++ = *src++; + + *dst = 0; + + return ret; +} + +wchar_t *strdup_char_to_wchar(const char *src) +{ + wchar_t *dst = malloc((strlen(src) + 1) * sizeof(wchar_t)); + + if (!dst) + return NULL; + + strcpy_char_to_wchar(dst, src); + + return dst; +} + +char *strdup_wchar_to_char(const wchar_t *src) +{ + char *dst = malloc((wcslen(src) + 1)); + + if (!dst) + return NULL; + + strcpy_wchar_to_char(dst, src); + + return dst; +} diff --git a/net/netconsole.c b/net/netconsole.c index 021820b13a..c817107296 100644 --- a/net/netconsole.c +++ b/net/netconsole.c @@ -141,6 +141,7 @@ static int netconsole_init(void) cdev->tstc = nc_tstc; cdev->putc = nc_putc; cdev->getc = nc_getc; + cdev->devname = "netconsole"; g_priv = priv; diff --git a/scripts/Makefile b/scripts/Makefile index 9c77680a17..2050ec497d 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -10,6 +10,7 @@ hostprogs-y += fix_size hostprogs-y += bareboxenv hostprogs-y += bareboxcrc32 hostprogs-y += kernel-install +hostprogs-$(CONFIG_IMD) += bareboximd hostprogs-$(CONFIG_KALLSYMS) += kallsyms hostprogs-$(CONFIG_ARCH_MVEBU) += kwbimage kwboot hostprogs-$(CONFIG_ARCH_NETX) += gen_netx_image @@ -29,6 +30,7 @@ subdir-$(CONFIG_ARCH_TEGRA) += tegra targetprogs-$(CONFIG_BAREBOXENV_TARGET) += bareboxenv-target targetprogs-$(CONFIG_KERNEL_INSTALL_TARGET) += kernel-install-target targetprogs-$(CONFIG_BAREBOXCRC32_TARGET) += bareboxcrc32-target +targetprogs-$(CONFIG_IMD_TARGET) += bareboximd-target # Let clean descend into subdirs subdir- += basic kconfig setupmbr diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 08518704fe..7d97d573ab 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -14,6 +14,13 @@ obj-m := $(filter-out $(obj-y),$(obj-m)) lib-y := $(filter-out $(obj-y), $(sort $(lib-y) $(lib-m))) +pbl-y += $(pbl-dtb-y) +obj-y += $(obj-dtb-y) +extra-y += $(patsubst %.dtb.o,%.dtb.S,$(obj-dtb-y)) +extra-y += $(patsubst %.dtb.o,%.dtb,$(obj-dtb-y)) +extra-y += $(patsubst %.dtb.o,%.dtb.S,$(pbl-dtb-y)) +extra-y += $(patsubst %.dtb.o,%.dtb,$(pbl-dtb-y)) + # Handle objects in subdirs # --------------------------------------------------------------------------- # o if we encounter foo/ in $(obj-y), replace it by foo/built-in.o @@ -203,21 +210,9 @@ cmd_gzip = (cat $(filter-out FORCE,$^) | gzip -n -f -9 > $@) || \ # Generate an assembly file to wrap the output of the device tree compiler quiet_cmd_dt_S_dtb = DTB $@ -cmd_dt_S_dtb= \ -( \ - echo '\#include <asm-generic/barebox.lds.h>'; \ - echo '.section .dtb.rodata.$(subst -,_,$(*F)),"a"'; \ - echo '.balign STRUCT_ALIGNMENT'; \ - echo '.global __dtb_$(subst -,_,$(*F))_start'; \ - echo '__dtb_$(subst -,_,$(*F))_start:'; \ - echo '.incbin "$<" '; \ - echo '__dtb_$(subst -,_,$(*F))_end:'; \ - echo '.global __dtb_$(subst -,_,$(*F))_end'; \ - echo '.balign STRUCT_ALIGNMENT'; \ -) > $@ - -$(obj)/%.dtb.S: $(obj)/%.dtb - $(call cmd,dt_S_dtb) +cmd_dt_S_dtb = $(srctree)/scripts/gen-dtb-s $(subst -,_,$(*F)) $< $(CONFIG_IMD) > $@ +$(obj)/%.dtb.S: $(obj)/%.dtb $(srctree)/scripts/gen-dtb-s FORCE + $(call if_changed,dt_S_dtb) quiet_cmd_dtc = DTC $@ cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ diff --git a/scripts/bareboxenv.c b/scripts/bareboxenv.c index da420db578..249e65b251 100644 --- a/scripts/bareboxenv.c +++ b/scripts/bareboxenv.c @@ -109,6 +109,7 @@ static void usage(char *prgname) "\n" "options:\n" " -s save (directory -> environment sector)\n" + " -z force the built-in default environment at startup\n" " -l load (environment sector -> directory)\n" " -p <size> pad output file to given size\n" " -v verbose\n", @@ -120,9 +121,10 @@ int main(int argc, char *argv[]) int opt; int save = 0, load = 0, pad = 0, err = 0, fd; char *filename = NULL, *dirname = NULL; + unsigned envfs_flags = 0; int verbose = 0; - while((opt = getopt(argc, argv, "slp:v")) != -1) { + while((opt = getopt(argc, argv, "slp:vz")) != -1) { switch (opt) { case 's': save = 1; @@ -133,6 +135,10 @@ int main(int argc, char *argv[]) case 'p': pad = strtoul(optarg, NULL, 0); break; + case 'z': + envfs_flags |= ENVFS_FLAGS_FORCE_BUILT_IN; + save = 1; + break; case 'v': verbose = 1; break; @@ -181,7 +187,7 @@ int main(int argc, char *argv[]) if (verbose) printf("saving contents of %s to file %s\n", dirname, filename); - err = envfs_save(filename, dirname); + err = envfs_save(filename, dirname, envfs_flags); if (verbose && err) printf("saving env failed: %d\n", err); diff --git a/scripts/bareboximd.c b/scripts/bareboximd.c new file mode 100644 index 0000000000..a3622af821 --- /dev/null +++ b/scripts/bareboximd.c @@ -0,0 +1,161 @@ +/* + * (C) Copyright 2014 Sascha Hauer, Pengutronix + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#define __ALIGN_MASK(x, mask) (((x) + (mask)) & ~(mask)) +#define ALIGN(x, a) __ALIGN_MASK(x, (typeof(x))(a) - 1) +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +#include <stdio.h> +#include <sys/types.h> +#include <stdint.h> +#include <asm-generic/errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/mman.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> + +#include "../include/image-metadata.h" + +static void debug(const char *fmt, ...) +{ + va_list ap; + + if (!imd_command_verbose) + return; + + va_start(ap, fmt); + vfprintf(stderr, fmt, ap); + va_end(ap); +} + +int imd_command_setenv(const char *variable_name, const char *value) +{ + fprintf(stderr, "-s option ignored\n"); + + return -EINVAL; +} + +static int read_file_2(const char *filename, size_t *size, void **outbuf, loff_t max_size) +{ + off_t fsize; + ssize_t rsize; + int ret, fd; + void *buf; + + *size = 0; + *outbuf = NULL; + + fd = open(filename, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "Cannot open %s: %s\n", filename, strerror(errno)); + return -errno; + } + + fsize = lseek(fd, 0, SEEK_END); + if (fsize == -1) { + fprintf(stderr, "Cannot get size %s: %s\n", filename, strerror(errno)); + ret = -errno; + goto close; + } + + if (fsize < max_size) + max_size = fsize; + + if (lseek(fd, 0, SEEK_SET) == -1) { + fprintf(stderr, "Cannot seek to start %s: %s\n", filename, strerror(errno)); + ret = -errno; + goto close; + } + + buf = malloc(max_size); + if (!buf) { + fprintf(stderr, "Cannot allocate memory\n"); + ret = -ENOMEM; + goto close; + } + + *outbuf = buf; + while (*size < max_size) { + rsize = read(fd, buf, max_size-*size); + if (rsize == 0) { + ret = -EIO; + goto free; + } else if (rsize < 0) { + if (errno == EAGAIN) + continue; + else { + ret = -errno; + goto free; + } + } /* ret > 0 */ + buf += rsize; + *size += rsize; + } + + ret = 0; + goto close; +free: + *outbuf = NULL; + free(buf); +close: + close(fd); + return ret; +} + +static unsigned long simple_strtoul(const char *cp, char **endp, unsigned int base) +{ + return strtoul(cp, endp, base); +} + +#include "../common/imd.c" + +static void usage(const char *prgname) +{ + printf( +"Extract metadata from a barebox image\n" +"\n" +"Usage: %s [OPTIONS] FILE\n" +"Options:\n" +"-t <type> only show information of <type>\n" +"-n <no> for tags with multiple strings only show string <no>\n" +"\n" +"Without options all information available is printed. Valid types are:\n" +"release, build, model, of_compatible\n", + prgname); +} + +int main(int argc, char *argv[]) +{ + int ret; + + ret = imd_command(argc, argv); + if (ret == -ENOSYS) { + usage(argv[0]); + exit(1); + } + + if (ret) + fprintf(stderr, "%s\n", strerror(-ret)); + + return ret ? 1 : 0; +} diff --git a/scripts/canon-a1100-image b/scripts/canon-a1100-image new file mode 100755 index 0000000000..6c08d7493a --- /dev/null +++ b/scripts/canon-a1100-image @@ -0,0 +1,10 @@ +#!/bin/bash -e + +IFILE=$1 +OFILE=$2 + +dd if=/dev/zero bs=4M count=1 of=$OFILE 2>/dev/null +dd if=$IFILE of=$OFILE conv=notrunc 2>/dev/null + +# 0xffff0000: fe 3f f0 ea b 0xffc00000 +echo -n -e "\xfe\x3f\xf0\xea" | dd of=$OFILE bs=64K seek=63 conv=notrunc 2>/dev/null diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e80926fa0b..153af8dd82 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -329,7 +329,7 @@ sub top_of_kernel_tree { my @tree_check = ( "arch", "commands", "common", "COPYING", "CREDITS", "defaultenv", - "Documentation", "Doxyfile", "drivers", "fs", "include", "lib", + "Documentation", "drivers", "fs", "include", "lib", "MAKEALL", "Makefile", "net", "README", "scripts", "TODO" ); diff --git a/scripts/dtc/.gitignore b/scripts/dtc/.gitignore index cdabdc95a6..80f6b50fdf 100644 --- a/scripts/dtc/.gitignore +++ b/scripts/dtc/.gitignore @@ -2,3 +2,4 @@ dtc dtc-lexer.lex.c dtc-parser.tab.c dtc-parser.tab.h +fdtget diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index 2a48022c41..05973b12aa 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -1,15 +1,20 @@ # scripts/dtc makefile -hostprogs-y := dtc +hostprogs-y := dtc fdtget always := $(hostprogs-y) dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ srcpos.o checks.o util.o dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o +libfdt-objs = fdt.o fdt_ro.o fdt_strerror.o fdt_wip.o +libfdt-objs += fdt_empty_tree.o fdt_rw.o fdt_sw.o + +fdtget-objs += fdtget.o $(libfdt-objs) util.o + # Source files need to get at the userspace version of libfdt_env.h to compile -HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt +HOSTCFLAGS_DTC := -I$(src) HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC) HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC) @@ -21,6 +26,15 @@ HOSTCFLAGS_srcpos.o := $(HOSTCFLAGS_DTC) HOSTCFLAGS_treesource.o := $(HOSTCFLAGS_DTC) HOSTCFLAGS_util.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_ro.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_strerror.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_wip.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_empty_tree.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_rw.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdt_sw.o := $(HOSTCFLAGS_DTC) +HOSTCFLAGS_fdtget.o := $(HOSTCFLAGS_DTC) + HOSTCFLAGS_dtc-lexer.lex.o := $(HOSTCFLAGS_DTC) HOSTCFLAGS_dtc-parser.tab.o := $(HOSTCFLAGS_DTC) diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/fdt.c index e56833ae9b..e56833ae9b 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/fdt.c diff --git a/scripts/dtc/libfdt/fdt.h b/scripts/dtc/fdt.h index 48ccfd9100..48ccfd9100 100644 --- a/scripts/dtc/libfdt/fdt.h +++ b/scripts/dtc/fdt.h diff --git a/scripts/dtc/libfdt/fdt_empty_tree.c b/scripts/dtc/fdt_empty_tree.c index f72d13b1d1..f72d13b1d1 100644 --- a/scripts/dtc/libfdt/fdt_empty_tree.c +++ b/scripts/dtc/fdt_empty_tree.c diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/fdt_ro.c index 02b6d68753..02b6d68753 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/fdt_ro.c diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/fdt_rw.c index 24437dfc32..24437dfc32 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/fdt_rw.c diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/fdt_strerror.c index e6c3ceee8c..e6c3ceee8c 100644 --- a/scripts/dtc/libfdt/fdt_strerror.c +++ b/scripts/dtc/fdt_strerror.c diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/fdt_sw.c index 55ebebf1eb..55ebebf1eb 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/fdt_sw.c diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/fdt_wip.c index 6025fa1fe8..6025fa1fe8 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/fdt_wip.c diff --git a/scripts/dtc/libfdt/libfdt.h b/scripts/dtc/libfdt.h index 73f49759a5..73f49759a5 100644 --- a/scripts/dtc/libfdt/libfdt.h +++ b/scripts/dtc/libfdt.h diff --git a/scripts/dtc/libfdt/libfdt_env.h b/scripts/dtc/libfdt_env.h index 213d7fb81c..213d7fb81c 100644 --- a/scripts/dtc/libfdt/libfdt_env.h +++ b/scripts/dtc/libfdt_env.h diff --git a/scripts/dtc/libfdt/libfdt_internal.h b/scripts/dtc/libfdt_internal.h index 381133ba81..381133ba81 100644 --- a/scripts/dtc/libfdt/libfdt_internal.h +++ b/scripts/dtc/libfdt_internal.h diff --git a/scripts/gen-dtb-s b/scripts/gen-dtb-s new file mode 100755 index 0000000000..434612f362 --- /dev/null +++ b/scripts/gen-dtb-s @@ -0,0 +1,56 @@ +#!/bin/bash + +name=$1 +dtb=$2 +imd=$3 + +echo "#include <asm-generic/barebox.lds.h>" + +le32() { + printf ".byte 0x%02x, 0x%02x, 0x%02x, 0x%02x\n" \ + $(($1 & 0xff)) \ + $((($1 >> 8) & 0xff)) \ + $((($1 >> 16) & 0xff)) \ + $((($1 >> 24) & 0xff)) +} + +FDTGET=scripts/dtc/fdtget + +if [ "$imd" = "y" ]; then + echo ".section .barebox_imd_0.${name},\"a\"" + echo ".global __imd_${name}_start" + echo "__imd_${name}_start:" + + compat=$($FDTGET -d notfound -t bi "$dtb" / compatible | sed "s^ ^,^g") + if [ "$compat" != "notfound" ]; then + + compatlen=$($FDTGET -t s "$dtb" / compatible | wc -c) + le32 0x640c8005 + le32 $compatlen + echo ".byte " $compat + echo ".balign 4" + fi + + model=$($FDTGET -d notfound -t bi "$dtb" / model | sed "s^ ^,^g") + + if [ "$model" != "notfound" ]; then + modellen=$($FDTGET -t s "$dtb" / model | wc -c) + le32 0x640c8004 + le32 $compatlen + echo ".byte " $model + echo ".balign 4" + fi +fi + +echo ".section .dtb.rodata.${name},\"a\"" +echo ".balign STRUCT_ALIGNMENT" +echo ".global __dtb_${name}_start" +echo "__dtb_${name}_start:" +echo ".incbin \"$dtb\"" +echo "__dtb_${name}_end:" +echo ".global __dtb_${name}_end" +echo ".balign STRUCT_ALIGNMENT" + +if [ "$imd" = "y" ]; then + echo ".word __imd_${name}_start" +fi |